예제 #1
0
/**********************************************************************//**
 * @brief  Global API call to record audio on the mike. 
 * 
 * - Initializes the record using setupRecord()
 * - Erases the memory reserved for audio recording
 * - Records until the memory is full using record()
 * - Shuts down the record using shutdownRecord()
 * 
 * @param  mode The mode of audio record 
 * 
 * - AUDIO_TEST_MODE ...for production test
 * - AUDIO_DEMO_MODE ...called for user sample code
 * 
 * @return none
 *************************************************************************/
void audioRecord(unsigned char mode)
{
  unsigned char i;
    
  setupRecord(); 

  halLcdPrintLine("   Erasing  ", 6, INVERT_TEXT | OVERWRITE_TEXT);  
  halLcdPrintLineCol("----", 8, 12,  OVERWRITE_TEXT);
  
  // Not used in User Experience sample code 
  if (mode == AUDIO_TEST_MODE)
  {
    flashErase(MemstartTest, Memend);
    __data16_write_addr((unsigned short)&DMA0DA, MemstartTest);      
    DMA0SZ = (long) (Memend - MemstartTest);
    
    record();
    
    if (DMA0SZ != ( long) (Memend - MemstartTest))
      lastAudioByte = Memend - DMA0SZ;
    else
      lastAudioByte = Memend;
  }
  // Always used in User Experience sample code 
  else
  {
    flashEraseBank(AUDIO_MEM_START[0]);
    flashEraseBank(AUDIO_MEM_START[1]);
    flashEraseBank(AUDIO_MEM_START[2]);
    flashErase(AUDIO_MEM_START[3], AUDIO_MEM_START[4]);    
    
    for (i=0;i<3;i++)
    {  
      __data16_write_addr((unsigned short)&DMA0DA, AUDIO_MEM_START[i]);               
      DMA0SZ = AUDIO_MEM_START[i+1] - AUDIO_MEM_START[i] - 1;
      
      record();
      
      if (DMA0SZ != AUDIO_MEM_START[i+1] - AUDIO_MEM_START[i] - 1)
      {
        lastAudioByte = AUDIO_MEM_START[i+1] - DMA0SZ;
        break;
      }
      else lastAudioByte = AUDIO_MEM_START[i+1]-1;      
    }
  }
  
  shutdownRecord();
}
static void ram_to_rom(struct ParseState *Parser, struct Value *ReturnValue,
		struct Value **Param, int NumArgs)
{
	(void) ReturnValue;
	(void) NumArgs;
	(void) Param;

	//delete flash page
	PlatformPrintf(Parser->pc, "erasing flash\n");
	if (!flashErase(sector))
	{
		//write data to flash
		PlatformPrintf(Parser->pc, "writing to flash\n");
		if (!flashWrite((uint32_t *) flash_base, script_buffer,
				strlen(script_buffer) + 1))
		{
			PlatformPrintf(Parser->pc, "done!\n");
		}
		else
		{
			PlatformPrintf(Parser->pc, "!! writing error !!\n");
		}
	}
	else
	{
		PlatformPrintf(Parser->pc, "!! flash erasing error !!\n");
	}

}
예제 #3
0
void test_flashErase_given_StartSector_15_and_20() {
  HAL_FLASH_Unlock_ExpectAndReturn(HAL_OK);
  HAL_FLASHEx_Erase_IgnoreAndReturn(HAL_OK);
  HAL_FLASH_Lock_ExpectAndReturn(HAL_OK);
  
  flashErase(ADDR_FLASH_SECTOR_15, 20);
}
예제 #4
0
void eeprom_flush(void *arg) {
  (void)arg;

  flashErase(((uint32_t)&flash_area) / 1024, 1);
  flashWrite((uint8_t *)flash_backing, (const uint8_t *)&flash_area,
             sizeof(flash_backing));
  flash_state = STATE_CLEAN;
}
예제 #5
0
파일: flash_main.c 프로젝트: jharvey/rusefi
void writeToFlash(void) {
    flashState.version = FLASH_DATA_VERSION;
    scheduleMsg(&logger, "FLASH_DATA_VERSION=%d", flashState.version);
    crc result = flashStateCrc(&flashState);
    flashState.value = result;
    scheduleMsg(&logger, "Reseting flash=%d", FLASH_USAGE);
    flashErase(FLASH_ADDR, FLASH_USAGE);
    scheduleMsg(&logger, "Flashing with CRC=%d", result);
    time_t now = chTimeNow();
    result = flashWrite(FLASH_ADDR, (const char *) &flashState, FLASH_USAGE);
    scheduleMsg(&logger, "Flash programmed in (ms): %d", chTimeNow() - now);
    scheduleMsg(&logger, "Flashed: %d", result);
}
예제 #6
0
파일: main.c 프로젝트: KuanYuChen/mansos
// -------------------------------------
// Main function
// -------------------------------------
void appMain(void)
{
    uint16_t i;

    // timers (used to get an extra interrupt context)
    alarmInit(&timer, onTimer, NULL);
    alarmSchedule(&timer, 1000);

    // radio
    radioSetReceiveHandle(radioRecvCb);
    radioOn();

    for (i = 0; i < BUFFER_SIZE; i++) {
        buffer[i] = i;
    }

    randomInit();

    // SELECT_FLASH;
    // extFlashBulkErase();
    // UNSELECT_FLASH;

    for (i = 0; ; i++) {
        uint32_t address = i * 64ul;

        SELECT_FLASH;

        if (IS_ALIGNED(address, EXT_FLASH_SECTOR_SIZE)) {
            PRINTF("erase address %lu\n", address);
            flashErase(address);
        }

        PRINTF("write address %lu\n", address);
        flashWrite(address);

        if (address > 0) {
            PRINTF("verify...\n");
            flashRead(address - 64);
        }

        UNSELECT_FLASH;

        msleep(randomInRange(400, 1000));

        PRINTF("send smth to radio...\n");
        radioSend("hello world", sizeof("hello world"));

        greenLedToggle();
    }
}
예제 #7
0
void writeToFlash(void) {
#if EFI_INTERNAL_FLASH
	persistentState.size = PERSISTENT_SIZE;
	persistentState.version = FLASH_DATA_VERSION;
	scheduleMsg(&logger, "flash compatible with %d", persistentState.version);
	crc_t result = flashStateCrc(&persistentState);
	persistentState.value = result;
	scheduleMsg(&logger, "Reseting flash: size=%d", PERSISTENT_SIZE);
	flashErase(FLASH_ADDR, PERSISTENT_SIZE);
	scheduleMsg(&logger, "Flashing with CRC=%d", result);
	efitimems_t nowMs = currentTimeMillis();
	result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE);
	scheduleMsg(&logger, "Flash programmed in (ms): %d", currentTimeMillis() - nowMs);
	scheduleMsg(&logger, "Flashing result: %d", result);
#endif /* EFI_INTERNAL_FLASH */
}
예제 #8
0
void writeToFlashNow(void) {
	scheduleMsg(logger, " !!!!!!!!!!!!!!!!!!!! BE SURE NOT WRITE WITH IGNITION ON !!!!!!!!!!!!!!!!!!!!");
	persistentState.size = PERSISTENT_SIZE;
	persistentState.version = FLASH_DATA_VERSION;
	scheduleMsg(logger, "flash compatible with %d", persistentState.version);
	crc_t crcResult = flashStateCrc(&persistentState);
	persistentState.value = crcResult;
	scheduleMsg(logger, "Reseting flash: size=%d", PERSISTENT_SIZE);
	flashErase(FLASH_ADDR, PERSISTENT_SIZE);
	scheduleMsg(logger, "Flashing with CRC=%d", crcResult);
	efitimems_t nowMs = currentTimeMillis();
	int result = flashWrite(FLASH_ADDR, (const char *) &persistentState, PERSISTENT_SIZE);
	scheduleMsg(logger, "Flash programmed in %dms", currentTimeMillis() - nowMs);
	bool isSuccess = result == FLASH_RETURN_SUCCESS;
	if (isSuccess) {
		scheduleMsg(logger, FLASH_SUCCESS_MSG);
	} else {
		scheduleMsg(logger, "Flashing failed");
	}
	maxLockTime = 0;
}
예제 #9
0
파일: config.c 프로젝트: ryanSie/Advantech
/**
 * reads the EEPROM common configuration area, if this area is invalid then
 * a default configuration is used and also stored in EEPROM for next start,
 * it also reads the backplane fru eeprom
 *
 * \return E_OK if configuration is valid, otherwise Errorcode
 */
int global_config(void)
{
    unsigned int eeprom_valid = 0x00000000;
#if defined(CFG_LAN) || defined(CFG_PEF_ENABLE)
    unsigned short i;
#endif

#ifdef CFG_ONCHIP_FLASH_GLOBAL_CONF
    unsigned char buf[] = { 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00 };	/* 0xDEADBEEF */
#endif

#ifdef CFG_LAN
    unsigned short len;
#endif

    /* read valid flag */
#ifndef CFG_ONCHIP_FLASH_GLOBAL_CONF
    fs_read(FILE_INTEGRITY_AREA1, 0, sizeof(unsigned int), &eeprom_valid);
#else
    eeprom_valid = *(unsigned int *)OCFLH_GBLCFG_ADDR_BASE;
#endif

    /* the EEPROM configuration is empty or invalid */
    if (eeprom_valid != EEPROM_VALID_FLAG)
    {
        /* init global config with default values */
        global_conf.allow_sdr_access = YES;
        global_conf.allow_coldreset = YES;
        global_conf.global_enables = CFG_GLOBAL_ENABLES;
#ifdef CFG_MCMC
        global_conf.operation_mode = CFG_OPERATION_MODE;
#endif

#ifdef CFG_LAN
        /* load LAN configuration */
        load_global_lan_config();

        /* save the lan configuration to eeprom */
        save_global_lan_config();

        /* load user configuration */
        load_global_user_config();

        /* save the user configuration to eeprom */
        save_global_user_config();

        /* restore MC NC-SI MAC address from FRU */
        custom_set_ncsi_mac();
#endif /* CFG_LAN */

        /* load default oem configuration */
        custom_load_oem_config_defaults();

        /* save default configuration settings to eeprom */
        save_oem_config();

#ifdef CFG_UART_MUX
        /* UART MUX setting needs to be updated */
        custom_set_uart_mux();
#endif

        /* set event receiver address and lun, default  */
        event_receiver_addr = 0x20;
        event_receiver_lun = 0x00;

        /* init the SDR Repository */
        sdr_repo_info.add_timestamp = 0xFFFFFFFF;
        sdr_repo_info.erase_timestamp = 0xFFFFFFFF;

#ifdef CFG_PEF_ENABLE
        /* init PEF configuration */
        pef_config.set_in_progress = 0x00;
        pef_config.control = DISABLE_PEF;
        pef_config.action_control = PEF_DEFAULT_ACTION;
        pef_config.startup_delay = PEF_DEFAULT_STARTUP_DELAY;
        pef_config.alert_startup_delay = PEF_DEFAULT_ALERT_STARTUP_DELAY;
        pef_config.number_event_filters = 0;
        pef_config.number_alert_policy = 0;

        memset(&pef_config.system_guid.node[0], 0x00, 16);

        pef_config.number_alert_strings = 0;
        pef_config.number_group_control = 0;

        /* init PEF event filters */
        for (i = 0; i < MAX_EVENT_FILTERS; i++)
        {
            event_filter_table[i].config = DISABLE_FILTER;
        }
#endif /* CFG_PEF_ENABLE */

#ifdef CFG_ONCHIP_FLASH_GLOBAL_CONF
        flashErase(OCFLH_GBLCFG_SECT_START, OCFLH_GBLCFG_SECT_END);
        flashWrite((void *)OCFLH_GBLCFG_ADDR_BASE, (void *)buf, sizeof(buf));

        eeprom_valid = *(unsigned int *)OCFLH_GBLCFG_ADDR_BASE;
#endif
    }
    else	/* valid EEPROM configuration exists */
    {
        /* init global config with default values */
        global_conf.allow_sdr_access = YES;
        global_conf.allow_coldreset = YES;
        global_conf.global_enables = CFG_GLOBAL_ENABLES;
#ifdef CFG_MCMC
        global_conf.operation_mode = CFG_OPERATION_MODE;
#endif

#if defined (CFG_ATCA) || defined (CFG_MCMC)
        /* set event receiver address and lun, default  */
        event_receiver_addr = 0x20;
        event_receiver_lun = 0x00;
#endif /* CFG_ATCA || CFG_MCMC */

#ifdef CFG_LAN
        /* read lan interface specific parameter */
        spi_eeprom_safe_area_read(LAN_CONFIGURATION_OFFSET, sizeof(global_lan_conf_t), &lan_conf);

        /* check CRC for lan configuration */
        len = ((unsigned char *)(&(lan_conf.crc)) - (unsigned char *)(&lan_conf));
        if (!_check_crc(&lan_conf, len, lan_conf.crc))
        {
            uart_printf("Error Lan Config CRC\n");
        }

#ifdef CFG_HW_DEPENDENT_LAN_ADDRESS
        custom_set_hw_dependent_ip_mac_addr();
#endif

        /* set volatile privilege level to the non-volatile value */
        lan_conf.priv_level_curr = lan_conf.priv_level;

        /* read user specific parameter */
        spi_eeprom_safe_area_read(USER_CONFIGURATION_OFFSET, sizeof(global_user_conf_t), &global_user);

        /* check CRC for user configuration */
        len = ((unsigned char *)(&(global_user.crc)) - (unsigned char *)(&global_user));
        if (!_check_crc(&global_user, len, global_user.crc))
        {
            uart_printf("Error User Config CRC\n");
        }

        /* decrypt the passwords with the XTEA algorithm */
        for (i = 0; i < configPRIV_MAX_USERS; i++)
        {
            if (xtea_decrypt_block((unsigned char *)(global_user.user[i].password), IPMI_PRIV_PW_MAX_LEN, pw_crypto_key) != 0)
            {
                uart_printf("Error User Config Decryption\n");
            }
        }
#endif /* CFG_LAN */

        /* read oem configuration from eeprom */
        load_oem_config();

        /* load oem configuration defaults, if version number is different */
        if (oem_config.version != OEM_CONFIG_VERSION)
        {
            uart_printf("Configuration setting EEPROM layout (version 0x%02X) "
                        "updated to version 0x%02X\n", oem_config.version, OEM_CONFIG_VERSION);

            /* load default oem configuration */
            custom_load_oem_config_defaults();

            /* save default configuration settings to eeprom */
            save_oem_config();

#ifdef CFG_UART_MUX
            /* UART MUX setting needs to be updated */
            custom_set_uart_mux();
#endif
        }
    }

    return E_OK;
}
예제 #10
0
uint8_t configFlashWrite(void) {
    configRec_t *recs;
    uint8_t ret = 0;
    int i;

    recs = (void *)aqCalloc(CONFIG_NUM_PARAMS, sizeof(configRec_t));

    if (recs) {
        configToken_t *tr = (configToken_t *)recs;
        configToken_t *tf = 0;

        // read all tokens
        do {
            tf = configTokenIterate(tf);

            // copy to RAM
            if (tf) {
                // only one instance per key
                do {
                    if (tr->key == 0 || tr->key == tf->key) {
                        memcpy(tr, tf, sizeof(configToken_t));
                        break;
                    }
                    tr++;
                } while (1);
            }
        } while (tf);

        ret = flashErase(flashStartAddr(), CONFIG_NUM_PARAMS*sizeof(configRec_t)/sizeof(uint32_t));

        // invalidate the flash data cache
        FLASH_DataCacheCmd(DISABLE);
        FLASH_DataCacheReset();
        FLASH_DataCacheCmd(ENABLE);

        if (ret) {
            tr = (configToken_t *)recs;

            // copy tokens back to flash
            while (tr->key)
                configTokenStore(tr++);

            // create param list in RAM
            for (i = 0; i < CONFIG_NUM_PARAMS; i++) {
                memcpy(recs[i].name, configParameterStrings[i], 16);
                recs[i].val = p[i];
            }

            ret = flashAddress(flashStartAddr(), (uint32_t *)recs, CONFIG_NUM_PARAMS*sizeof(configRec_t)/sizeof(uint32_t));
        }

        aqFree(recs, CONFIG_NUM_PARAMS, sizeof(configRec_t));

	AQ_NOTICE("config: Parameters saved to flash memory.\n");
    }
    else {
        AQ_NOTICE("config: Error writing params to flash, cannot allocate memory.\n");
    }

    return ret;
}
예제 #11
0
/**
Handle incomming frames from the serial port.
*/
void rxhandler(void) {
    switch (serRxBuf.header.type) {
        case ACK:
        case NACK:
            break;

        case T_CONNECT:                         //connect JTAG to the target
            InitTarget();
            if (GetDevice() == STATUS_OK) {
                txACK();
                //printf("Device type: %04x\n", DEVICE);
            } else{
                txNACKstr("no target");
            }
            break;
        case T_RELEASE:                         //release JTAG from target
            ClrTCLK();
            IR_Shift(IR_CNTRL_SIG_16BIT);
            DR_Shift16(0x3001);         //lch
            IR_Shift(IR_CNTRL_SIG_RELEASE);
            SetTCLK();
            ReleaseTarget();
            txACK();
            break;
        case T_RESET:                           //reset the target and release JTAG
            ReleaseDevice(V_RESET);
            ReleaseTarget();
            txACK();
            break;
        case T_PUC:                             //reset the target through JTAG, keep connection
            ExecutePUC();
            txACK();
            break;

        case T_MEMREAD:                         //ream memory from target
            {                                   //use a new block for local vars
                word size = serRxBuf.data.memread.size;
                word address = serRxBuf.data.memread.address;
                word offset;
    
                txACK();
                HaltCPU();
                if (size > sizeof(serTxBuf.data.memdata.data)) {
                   size = sizeof(serTxBuf.data.memdata.data);
                }
                if (address <= 0xff) {          //peripherals in bytemode
                    for (offset = 0; offset < size; offset++) {
                        serTxBuf.data.memdata.data[offset] = ReadMem(F_BYTE, address+offset);
                    }
                } else {                        //peripherals in wordmode as well as RAM and Flash
                    address = address & 0xfffe; //startaddress has to be even!
                    for (offset = 0; offset < size/2; offset++) {
                        ((word *)serTxBuf.data.memdata.data)[offset] = ReadMem(F_WORD, address+offset*2);
                    }
                    if (size & 1) {
                        //odd size, read last byte separate
                        //odd sizes on word-mode peripherals yield  wrong results
                        //in the last word!!
                        serTxBuf.data.memdata.data[size-1] = ReadMem(F_BYTE, address+size-1);
                    }
                }
                serTxBuf.data.memdata.address = address;
                serTxBuf.header.type = T_MEMDATA;
                serTxBuf.header.size = 2+size;
                sendMessage(&serTxBuf);
            }
            break;
        case T_MEMWRITE:                        //write target memory (Peripherals, RAM, Flash)
            {
                word offset;
                word size = serRxBuf.header.size - 2;
                HaltCPU();
                if ((serRxBuf.data.memwrite.address >= 0x100) &&
                    (serRxBuf.data.memwrite.address <= 0x1ff)) { //peripherals in wordmode
                    for (offset = 0; offset < size; offset+=2) {
                        WriteMem(F_WORD,
                                 serRxBuf.data.memwrite.address+offset,
                                 ((word*)serRxBuf.data.memwrite.data)[offset/2]
                        );
                    }
                } else if (serRxBuf.data.memwrite.address < 0x1000) {  //ram + peripherals, bytemode
                    for (offset = 0; offset < size; offset++) {
                        WriteMem(F_BYTE,
                                 serRxBuf.data.memwrite.address+offset,
                                 serRxBuf.data.memwrite.data[offset]
                        );
                    }
                } else {                        //flash memory, wordmode
                    WriteFLASH(serRxBuf.data.memwrite.address,
                               size/2,
                               (word *)serRxBuf.data.memwrite.data
                    );
                }
                txACK();
            }
            break;
        case T_EXEC:                            //execute target program located at given address
            ReleaseDevice(serRxBuf.data.exec.address);
            txACK();
            break;
        case T_MEMERASE:                        //erase target flash (Segment, Main or All)
            HaltCPU();
            EraseFLASH(
                serRxBuf.data.memerase.mode,
                serRxBuf.data.memerase.address
            );
            txACK();
            break;
        case T_MCLK:                            //provide MCLKs, allows sort of single stepping
            ClrTCLK();
            IR_Shift(IR_CNTRL_SIG_16BIT);
            DR_Shift16(0x3401);         //lch
            while (serRxBuf.data.step.numsteps--) {
                SetTCLK();
                ClrTCLK();
            }
            SetTCLK();
            txACK();
            break;

        case MEMREAD:                           //host memory read
            {
                word size = serRxBuf.data.memread.size;
                byte *address = (byte*)serRxBuf.data.memread.address;
                word offset;
                txACK();
                if (size > sizeof(serTxBuf.data.memdata.data)) {
                   size = sizeof(serTxBuf.data.memdata.data);
                }
                if (address <= (byte *)0xff) {      //bytemode
                    for (offset = 0; offset < size; offset++) {
                        serTxBuf.data.memdata.data[offset] = address[offset];
                    }
                } else {                            //wordmode
                    address = (byte *)((word)address & 0xfffe);    //startaddress has to be even!
                    size &= 0xfffe;                     //size has to be even
                    for (offset = 0; offset < size/2; offset++) {
                        ((word *)serTxBuf.data.memdata.data)[offset] = ((word *)address)[offset];
                    }
                }
                serTxBuf.data.memdata.address = (word)address;
                serTxBuf.header.type = MEMDATA;
                serTxBuf.header.size = 2+size;
                sendMessage(&serTxBuf);
            }
            break;
        case MEMWRITE:                          //host memory write, used to download user programs
            {
                void *adr = (byte *)serRxBuf.data.memwrite.address;
                word offset;
                word size = serRxBuf.header.size - 2;
                if ((adr >= (void *)0x100) && (adr <= (void *)0x1ff)) { //peripherals, wordmode
                    for (offset = 0; offset < size/2; offset++) {
                        ((word *)adr)[offset] = ((word *)serRxBuf.data.memwrite.data)[offset];
                    }
                    txACK();
                    return;
                }
                if (adr < (void *)0x1000) {     //ram + peripherals, bytemode
                    for (offset = 0; offset < size; offset++) {
                        ((byte *)adr)[offset] = serRxBuf.data.memwrite.data[offset];
                    }
                } else {                        //flash
                    flashWriteBlock(
                        serRxBuf.data.memwrite.data,
                        (void *)serRxBuf.data.memwrite.address,
                        size);
                }
                txACK();
            }
            break;
        case MEMERASE:                          //erase one segemnt on host
            flashErase((void *)serRxBuf.data.memerase.address);
            txACK();
            break;
        //~ case MEMEXEC:                       //exec code on host
                //~ serRxBuf.memexec.function(
                    //~ serRxBuf.memexec.arg1,
                    //~ serRxBuf.memexec.arg2
                //~ );
            //~ txACK();
            //~ break;
        case STARTBSL:                          //start BSL for firmware upgrade
            txACK();
            while((UTCTL0 & TXEPT) == 0) {}     //wait until last byte is sent
            FCTL3 = 0;                          //generate a flash key violation -> POR reset, see main()
            break;
        default:
            txNACKstr("unknown command");       //serialComm error: unknown command
    }
}
예제 #12
0
파일: flash.c 프로젝트: 0s4l/u-boot-xlnx
STATUS flashDiag (flash_dev_t * dev)
{
	unsigned int *buf = 0;
	int i, len, sector;
	int rv = ERROR;

	if (flashCheck (dev) == ERROR)
		return ERROR;

	printf ("flashDiag: Testing device %d, "
		"base: 0x%x, %d sectors @ %d kB = %d kB\n",
		DEV_NO (dev), dev->base,
		dev->sectors,
		1 << (dev->lgSectorSize - 10),
		dev->sectors << (dev->lgSectorSize - 10));

	len = 1 << dev->lgSectorSize;

	printf ("flashDiag: Erasing\n");

	if (flashErase (dev) == ERROR) {
		printf ("flashDiag: Erase failed\n");
		goto done;
	}
	printf ("%d bytes requested ...\n", len);
	buf = malloc (len);
	printf ("allocated %d bytes ...\n", len);
	if (buf == 0) {
		printf ("flashDiag: Out of memory\n");
		goto done;
	}

	/*
	 * Write unique counting pattern to each sector
	 */

	for (sector = 0; sector < dev->sectors; sector++) {
		printf ("flashDiag: Write sector %d\n", sector);

		for (i = 0; i < len / 4; i++)
			buf[i] = sector << 24 | i;

		if (flashWrite (dev,
				sector << dev->lgSectorSize,
				(char *) buf, len) == ERROR) {
			printf ("flashDiag: Write failed (dev: %d, sector: %d)\n",
				DEV_NO (dev), sector);
			goto done;
		}
	}

	/*
	 * Verify
	 */

	for (sector = 0; sector < dev->sectors; sector++) {
		printf ("flashDiag: Verify sector %d\n", sector);

		if (flashRead (dev,
				   sector << dev->lgSectorSize,
				   (char *) buf, len) == ERROR) {
			printf ("flashDiag: Read failed (dev: %d, sector: %d)\n",
				DEV_NO (dev), sector);
			goto done;
		}

		for (i = 0; i < len / 4; i++) {
			if (buf[i] != (sector << 24 | i)) {
				printf ("flashDiag: Verify error "
					"(dev: %d, sector: %d, offset: 0x%x)\n",
					DEV_NO (dev), sector, i);
				printf ("flashDiag: Expected 0x%08x, got 0x%08x\n",
					sector << 24 | i, buf[i]);

				goto done;
			}
		}
	}

	printf ("flashDiag: Erasing\n");

	if (flashErase (dev) == ERROR) {
		printf ("flashDiag: Final erase failed\n");
		goto done;
	}

	rv = OK;

  done:
	if (buf)
		free (buf);

	if (rv == OK)
		printf ("flashDiag: Device %d passed\n", DEV_NO (dev));
	else
		printf ("flashDiag: Device %d failed\n", DEV_NO (dev));

	return rv;
}