int32_t flash_program2(const uint32_t &addr, const uint32_t &len, const uint8_t *data) { uint32_t i, laddr = addr; // add offset if (laddr>=FLASH_BEGIN && laddr<=FLASH_END) laddr += FLASH_OFFSET; // check range if (laddr<FLASH_BEGIN_B || laddr>FLASH_END_B || laddr+len>FLASH_END_B) return -1; // erase all sectors spanned by this segment for (i=FLASH_SECTOR_MASK(laddr); i<laddr+len; i+=FLASH_SECTOR_SIZE) { if (erase(i)<0) return -3; } if (flash_program(laddr, data, len)<0) return -2; // verify for (i=0; i<len; i++) { if (*(uint8_t *)(laddr+i) != data[i]) return -4; } return 0; }
int store_iap(const void *pbuf,unsigned short len) { unsigned int addr; if(icount.size+len>CODE_SIZE){ //PrintLog(LOGTYPE_SHORT,"iap flash overflow\n"); return -1; } if(icount.records>=UPDATE_RECORDS){ //PrintLog(LOGTYPE_SHORT,"iap records overflow\n"); return -1; } //代码写到Flash------------------------------------------------------------- addr = UPDATE_CODE_ADDR+icount.size; flash_program(addr,pbuf,len); //写记录数据---------------------------------------------------------------- irecord.offset = icount.size; irecord.bytes = len; irecord.codecrc = calculate_crc(pbuf,len); addr = UPDATE_RECORD_ADDR; addr = UPDATE_RECORD_ADDR+UPDATE_RECORD_SIZE*icount.records; f_program(addr,&irecord,sizeof(irecord)); icount.size+=len; icount.records++; //PrintLog(LOGTYPE_SHORT,"save code frame:%d,size:%d",icount.records,icount.size); return 0; }
int hal_flash_program(void *addr, void *data, int len, void **err) { int swabbed = 0; cyg_uint32 *p; int i, retval; if (is_swabbed_redboot(addr, data) #if (CYG_BYTEORDER == CYG_LSBFIRST) && defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_MSBFIRST) #ifdef CYGOPT_REDBOOT_FIS || addr == fis_addr #endif #ifdef CYGSEM_REDBOOT_FLASH_CONFIG || addr == cfg_base #endif #endif ) { swabbed = 1; for (i = 0, p = data; i < len; i += 4, ++p) *p = CYG_SWAP32(*p); } retval = flash_program(addr, data, len, err); if (swabbed) { for (i = 0, p = data; i < len; i += 4, ++p) *p = CYG_SWAP32(*p); } return retval; }
static Cyg_ErrNo flashiodev_bwrite( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len, cyg_uint32 pos ) { struct cyg_devtab_entry *tab = (struct cyg_devtab_entry *)handle; struct flashiodev_priv_t *dev = (struct flashiodev_priv_t *)tab->priv; Cyg_ErrNo err = ENOERR; void *erraddr; char *startpos = dev->start + pos; #ifdef CYGPKG_INFRA_DEBUG // don't bother checking this all the time char *endpos = startpos + *len - 1; char *flashend = MIN( (char *)flash_info.end - 1, dev->end - 1); if ( startpos < dev->start ) return -EINVAL; if ( endpos > flashend ) return -EINVAL; #endif err = flash_program( startpos, (void *)buf, *len, &erraddr ); if ( err ) err = -EIO; // just something sane return err; } // flashiodev_bwrite()
/* program data_addr[0-data_size] to dev, starting addr's offset is flash_offset*/ int flash_write(struct flash_device *dev, u32 flash_offset, char *data_addr, size_t data_size) { int ret; u8 *tmp_buf; // for store flash content which will be use later size_t pre_size; ulong real_start_addr; ulong start_addr = dev->vaddr + flash_offset; real_start_addr = head_erase_align(dev, start_addr); pre_size = start_addr - real_start_addr; tmp_buf = malloc(pre_size + data_size); if(tmp_buf == NULL) { printf("out of memory!\n"); return -ENOMEM; } /*save the pre data, clear the following data in tht sector*/ memcpy((void *)tmp_buf, (void *)real_start_addr, pre_size); memcpy((void *)tmp_buf + pre_size, (void *)data_addr, data_size); ret = flash_erase(dev, real_start_addr, (start_addr + data_size -1)); if(ret <= 0){ printf("erase failed, exit!"); return 0; } flash_program(dev, real_start_addr, (start_addr + data_size -1), tmp_buf); return 0; }
int32_t prm_setChirp(const char *id, const uint32_t &valLen, const uint8_t *val) { ParamRecord *rec; uint8_t *buf; uint32_t offset; void *sector; int32_t res = 0; rec = prm_find(id); if (rec==NULL) { // Good god this is an ugly hack. But, creating parameters should only be handled from within the firmware, so that the correct // description can be inserted. There may be other parameters like this, such that when these parameters are lost, we want to resave, // in which case, we should formalize this hack somehow. if (strncmp(id, "Signature label", 15)==0) { char desc[100]; sprintf(desc, "@c Signature_Labels Sets the label for objects that match signature%s.", id+15); prm_add(id, 0, desc, val[0], val+1, END); return 0; } return -1; } buf = (uint8_t *)malloc(FLASH_SECTOR_SIZE); if (buf==NULL) return -2; sector = (void *)FLASH_SECTOR_MASK((uint32_t)rec); memcpy(buf, sector, FLASH_SECTOR_SIZE); rec = prm_find(id, buf); if (rec==NULL) { res = -1; goto end; } offset = prm_getDataOffset(rec); if (memcmp((uint8_t *)rec+offset, val, valLen)==0) goto end; memcpy((uint8_t *)rec+offset, val, valLen); rec->len = valLen; rec->crc = prm_crc(rec); flash_erase((uint32_t)sector, FLASH_SECTOR_SIZE); flash_program((uint32_t)sector, buf, FLASH_SECTOR_SIZE); end: free(buf); return res; }
int write_eeprom(ADDR start_addr, const void *data_arg, int data_size) { void *err_addr; if (flash_program((void *)start_addr, data_arg, data_size, &err_addr) != 0) { cmd_stat = E_EEPROM_FAIL; return ERR; } return OK; }
int prm_add(const char *id, uint32_t flags, const char *desc, ...) { char buf[PRM_MAX_LEN]; int len; uint32_t freeLoc, offset=PRM_HEADER_LEN; va_list args; ParamRecord *rec = (ParamRecord *)buf; // if it already exists, if (prm_find(id)) return -2; memset((void *)rec, 0, PRM_MAX_LEN); strcpy((char *)rec+offset, id); offset += strlen(id) + 1; if (desc!=NULL) { strcpy((char *)rec+offset, desc); offset += strlen(desc) + 1; } else { *(char *)(rec+offset) = '\0'; offset++; } // data section should be aligned to 4 bytes ALIGN(offset, 4); va_start(args, desc); len = Chirp::vserialize(NULL, (uint8_t *)rec+offset, PRM_MAX_LEN-offset, &args); va_end(args); if (len<0) return -3; rec->flags = flags; rec->len = len; rec->crc = prm_crc(rec); if ((freeLoc=prm_nextFree())==NULL) return -4; return flash_program(freeLoc, (uint8_t *)rec, len+prm_getDataOffset(rec)); }
/** Program a set of addresses of the STM32F4 flash memory. * Note : sector containing addresses must be erased before addresses can be * programmed. * * \param address Starting address of set to program * \param data Data to program addresses with * \param length Length of set of addresses to program - counts up from * starting address * \return Error code */ u8 stm_flash_program(u32 address, u8 data[], u8 length) { /* Check that arguments are valid. */ if (address > STM_FLASH_MAX_ADDR) return FLASH_INVALID_ADDR; if (address < STM_FLASH_MIN_ADDR) return FLASH_INVALID_ADDR; if (address+length-1 > STM_FLASH_MAX_ADDR) return FLASH_INVALID_RANGE; /* Program specified addresses with data */ flash_unlock(); flash_program(address, data, length); flash_lock(); return FLASH_OK; }
//! Запись файла. modbus_rtu_error_t boot_modbus_rtu_on_write_file_record(uint16_t file, uint16_t record, uint16_t count, const uint16_t* values) { switch(file){ default: return MODBUS_RTU_ERROR_INVALID_ADDRESS; case BOOT_MODBUS_FILE_PAGE:{ if((record + count) > (flash_page_size_bytes() / 2)) return MODBUS_RTU_ERROR_INVALID_ADDRESS; if(!flash_unlock()) return MODBUS_RTU_ERROR_NONRECOVERABLE; uint32_t address = flash_page_address(boot_modbus.page_number) + (uint32_t)record * sizeof(uint16_t); uint16_t i; for(i = 0; i < count; i ++, address += 2){ if(!flash_program(address, values[i])){ flash_lock(); return MODBUS_RTU_ERROR_NONRECOVERABLE; } } flash_lock(); }break; } return MODBUS_RTU_ERROR_NONE; }
// Program the current page into flash. void flash_load_finish(void) { cyg_uint32 retcode = FLASH_ERR_OK; void * err_addr; if (init_done && flash_page_init) { flash_page_init = false; retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); if (retcode != FLASH_ERR_OK){ diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); } else { retcode = flash_program(current_flash_page, flash_buffer, flash_block_size, &err_addr); if (retcode != FLASH_ERR_OK){ diag_printf("Error writing at %p: %s\n", err_addr, flash_errmsg(retcode)); } } } flash_init(diag_printf); }
// Write a byte into flash. We maintain a copy in RAM of the FLASH // page we are currently "writing" into. This copy is loaded with the // current contents of the FLASH page when the first byte is "written" // to the page. The "writes" are then made into the RAM copy. We only // write to FLASH when there is a "write" outside of the current page, // or the flash_load_finish function is called. void flash_load_write(cyg_uint8 *flash_addr, cyg_uint8 value) { cyg_uint32 retcode = FLASH_ERR_OK; void * err_addr; cyg_uint32 addr = (cyg_uint32)flash_addr; cyg_uint32 offset; if (!flash_page_init) { /* First Byte for the current flash block. Read the current contents */ current_flash_page = flash_block_begin(addr); flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); flash_page_init = true; } if (flash_block_begin(addr) != current_flash_page) { /* We have moved into the next flash page. Write the current page so we can move on */ retcode = flash_erase(current_flash_page, flash_block_size, &err_addr); if (retcode != FLASH_ERR_OK){ /* Flash ERROR */ diag_printf("Error erase at %p: %s\n", err_addr, flash_errmsg(retcode)); return; } retcode = flash_program(current_flash_page, flash_buffer, flash_block_size, &err_addr); if (retcode != FLASH_ERR_OK){ diag_printf("Error writing at %p: %s\n", err_addr, flash_errmsg(retcode)); return; } current_flash_page = flash_block_begin(addr); flash_read(flash_buffer, current_flash_page, flash_block_size, &err_addr); } offset = flash_addr - current_flash_page; CYG_ASSERT(offset < flash_block_size, "offset not inside flash block"); flash_buffer[offset] = value; }
void main(void) { /* Port F Bit 1 active when error occurs */ PTFDD |= 0x01; PTFD |= 0x01; EnableInterrupts; flash_init(); copyinRAM(); /* Copy flash routine to RAM */ if (flash_erase( 0xF800)) /* Erase flash sector */ PTFD &= ~0x01; if (flash_program( 0xF800, data)) /* Program single byte*/ PTFD &= ~0x01; for( ; ; ) { __RESET_WATCHDOG(); } /* Loop always */ }
int32_t prm_setChirp(const char *id, const uint32_t &valLen, const uint8_t *val) { ParamRecord *rec; uint8_t *buf; uint32_t offset; void *sector; buf = (uint8_t *)malloc(FLASH_SECTOR_SIZE); if (buf==NULL) return -2; rec = prm_find(id); if (rec==NULL) return -1; sector = (void *)FLASH_SECTOR_MASK((uint32_t)rec); memcpy(buf, sector, FLASH_SECTOR_SIZE); rec = prm_find(id, buf); if (rec==NULL) return -1; offset = prm_getDataOffset(rec); memcpy((uint8_t *)rec+offset, val, valLen); rec->len = valLen; rec->crc = prm_crc(rec); flash_erase((uint32_t)sector, FLASH_SECTOR_SIZE); flash_program((uint32_t)sector, buf, FLASH_SECTOR_SIZE); free(buf); return 0; }
void doFlash(){ uint32_t addr=0x0; uint32_t sw=0x1; uint8_t data[256]; uint8_t x=0; flashInit(); lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr(addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); lcdDisplay(); while(1){ TOGGLE(LED1); switch(getInput()){ case BTN_UP: /* addr-=sw; lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); lcdDisplay(); */ flash_write_enable(); lcdPrint("WE done."); lcdDisplay(); break; case BTN_DOWN: addr+=sw; lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); lcdDisplay(); break; case BTN_LEFT: /*sw<<=1; lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); lcdDisplay(); */ lcdPrint(IntToStr(flash_status1(),2,F_HEX)); lcdPrint(" "); lcdPrint(IntToStr(flash_status2(),2,F_HEX)); lcdNl();lcdDisplay(); break; case BTN_RIGHT: /*sw>>=1; lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr((uint32_t)addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); lcdDisplay(); */ data[0]=0xfe; data[1]=0xf8; flash_program(addr,0x2,data); lcdPrint("done."); lcdNl(); lcdDisplay(); break; case BTN_ENTER: lcdClear(0xff); lcdPrint("xxd @ "); lcdPrint(IntToStr(addr,8,F_HEX));lcdNl(); lcdPrint(" "); lcdPrint(IntToStr(sw,8,F_HEX));lcdNl(); flash_read(addr,0x100,data); int ctr; for (ctr=0x00;ctr<0x024;ctr++){ if (ctr%4==0){ lcdNl(); lcdPrint(IntToStr(ctr,2,F_HEX)); lcdPrint(":"); }; lcdPrint(" "); lcdPrint(IntToStr(data[ctr],2,F_HEX)); }; lcdNl(); lcdDisplay(); break; }; }; };
void cyg_user_start(void) { int ret; char data[1024]; void *flash_start, *flash_end; int block_size, blocks; char *prog_start; unsigned char * ptr; CYG_TEST_INIT(); ret=flash_init(NULL,0,(_printf *)diag_printf); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_init"); flash_dev_query(data); CYG_TEST_PASS_FAIL(!strncmp(data,"Linux Synthetic Flash",sizeof(data)), "flash_query"); ret = flash_get_limits(NULL,&flash_start,&flash_end); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_get_limits"); ret = flash_get_block_info(&block_size, &blocks); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_get_block_info"); /* Erase the whole flash. Not recommended on real hardware since this will probably erase the bootloader etc!!! */ ret=flash_erase(flash_start,block_size * blocks,NULL); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_erase1"); /* check that its actually been erased, and test the mmap area */ for (ptr=flash_start,ret=0; ptr < (unsigned char *)flash_end; ptr++) { if (*ptr != 0xff) { ret++; } } CYG_TEST_PASS_FAIL((ret == 0),"flash empty check"); ret = flash_program(flash_start,©right,sizeof(copyright),NULL); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_program1"); /* Check the contents made it into the flash */ CYG_TEST_PASS_FAIL(!strncmp(flash_start,copyright,sizeof(copyright)), "flash program contents"); /* .. and check nothing else changed */ for (ptr=(unsigned char *)flash_start+sizeof(copyright),ret=0; ptr < (unsigned char *)flash_end; ptr++) { if (*ptr != 0xff) { ret++; } } CYG_TEST_PASS_FAIL((ret == 0),"flash program overrun check"); /* Program over a block boundary */ prog_start = (unsigned char *)flash_start + block_size - sizeof(copyright)/2; ret = flash_program(prog_start,©right,sizeof(copyright),NULL); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_program2"); /* Check the first version is still OK */ CYG_TEST_PASS_FAIL(!strncmp(flash_start,copyright,sizeof(copyright)), "Original contents"); CYG_TEST_PASS_FAIL(!strncmp(prog_start,copyright,sizeof(copyright)), "New program contents"); /* Check the bit in between is still erased */ for (ptr=(unsigned char *)flash_start+sizeof(copyright),ret=0; ptr < (unsigned char *)prog_start; ptr++) { if (*ptr != 0xff) { ret++; } } CYG_TEST_PASS_FAIL((ret == 0),"flash erase check1"); /* Erase the second block and make sure the first is not erased */ ret=flash_erase((void *)((unsigned)flash_start+block_size), block_size,NULL); CYG_TEST_PASS_FAIL((ret == FLASH_ERR_OK),"flash_erase2"); /* Check the erase worked */ for (ptr=(unsigned char *)flash_start+block_size,ret=0; ptr < (unsigned char *)flash_start+block_size*2; ptr++) { if (*ptr != 0xff) { ret++; } } CYG_TEST_PASS_FAIL((ret == 0), "flash erase check2"); /* Lastly check the first half of the copyright message is still there */ CYG_TEST_PASS_FAIL(!strncmp(prog_start,copyright,sizeof(copyright)/2), "Block 1 OK"); #if 0 /* This test it fatal! Its not run by default! Check the flash is read only, by trying to write to it. We expect to get an exception */ *(char *)flash_start = 'a'; #endif CYG_TEST_PASS_FINISH("flash1"); }
static void cmd_handler(uint8_t dlci, struct msgb *msg) { if (msg->data_len < 1) { return; } uint8_t command = msgb_pull_u8(msg); int res = 0; flash_lock_t lock; void *data; uint8_t chip; uint8_t nbytes; uint16_t crc, mycrc; uint32_t address; struct msgb *reply = sercomm_alloc_msgb(256); // XXX if (!reply) { printf("Failed to allocate reply buffer!\n"); goto out; } switch (command) { case LOADER_PING: loader_send_simple(reply, dlci, LOADER_PING); break; case LOADER_RESET: loader_send_simple(reply, dlci, LOADER_RESET); device_reset(); break; case LOADER_POWEROFF: loader_send_simple(reply, dlci, LOADER_POWEROFF); device_poweroff(); break; case LOADER_ENTER_ROM_LOADER: loader_send_simple(reply, dlci, LOADER_ENTER_ROM_LOADER); device_enter_loader(1); break; case LOADER_ENTER_FLASH_LOADER: loader_send_simple(reply, dlci, LOADER_ENTER_FLASH_LOADER); device_enter_loader(0); break; case LOADER_MEM_READ: nbytes = msgb_pull_u8(msg); address = msgb_pull_u32(msg); crc = osmo_crc16(0, (void *)address, nbytes); msgb_put_u8(reply, LOADER_MEM_READ); msgb_put_u8(reply, nbytes); msgb_put_u16(reply, crc); msgb_put_u32(reply, address); memcpy(msgb_put(reply, nbytes), (void *)address, nbytes); sercomm_sendmsg(dlci, reply); break; case LOADER_MEM_WRITE: nbytes = msgb_pull_u8(msg); crc = msgb_pull_u16(msg); address = msgb_pull_u32(msg); data = msgb_pull(msg, nbytes) - nbytes; mycrc = osmo_crc16(0, data, nbytes); if (mycrc == crc) { memcpy((void *)address, data, nbytes); } msgb_put_u8(reply, LOADER_MEM_WRITE); msgb_put_u8(reply, nbytes); msgb_put_u16(reply, mycrc); msgb_put_u32(reply, address); sercomm_sendmsg(dlci, reply); break; case LOADER_JUMP: address = msgb_pull_u32(msg); msgb_put_u8(reply, LOADER_JUMP); msgb_put_u32(reply, address); sercomm_sendmsg(dlci, reply); device_jump((void *)address); break; case LOADER_FLASH_INFO: msgb_put_u8(reply, LOADER_FLASH_INFO); msgb_put_u8(reply, 1); // nchips // chip 1 msgb_put_u32(reply, (uint32_t)the_flash.f_base); msgb_put_u32(reply, the_flash.f_size); msgb_put_u8(reply, the_flash.f_nregions); unsigned i; for (i = 0; i < the_flash.f_nregions; i++) { msgb_put_u32(reply, the_flash.f_regions[i].fr_bnum); msgb_put_u32(reply, the_flash.f_regions[i].fr_bsize); } sercomm_sendmsg(dlci, reply); break; case LOADER_FLASH_ERASE: case LOADER_FLASH_UNLOCK: case LOADER_FLASH_LOCK: case LOADER_FLASH_LOCKDOWN: chip = msgb_pull_u8(msg); address = msgb_pull_u32(msg); if (command == LOADER_FLASH_ERASE) { res = flash_block_erase(&the_flash, address); } if (command == LOADER_FLASH_UNLOCK) { res = flash_block_unlock(&the_flash, address); } if (command == LOADER_FLASH_LOCK) { res = flash_block_lock(&the_flash, address); } if (command == LOADER_FLASH_LOCKDOWN) { res = flash_block_lockdown(&the_flash, address); } msgb_put_u8(reply, command); msgb_put_u8(reply, chip); msgb_put_u32(reply, address); msgb_put_u32(reply, (res != 0)); sercomm_sendmsg(dlci, reply); break; case LOADER_FLASH_GETLOCK: chip = msgb_pull_u8(msg); address = msgb_pull_u32(msg); lock = flash_block_getlock(&the_flash, address); msgb_put_u8(reply, command); msgb_put_u8(reply, chip); msgb_put_u32(reply, address); switch (lock) { case FLASH_UNLOCKED: msgb_put_u32(reply, LOADER_FLASH_UNLOCKED); break; case FLASH_LOCKED: msgb_put_u32(reply, LOADER_FLASH_LOCKED); break; case FLASH_LOCKED_DOWN: msgb_put_u32(reply, LOADER_FLASH_LOCKED_DOWN); break; default: msgb_put_u32(reply, 0xFFFFFFFF); break; } sercomm_sendmsg(dlci, reply); break; case LOADER_FLASH_PROGRAM: nbytes = msgb_pull_u8(msg); crc = msgb_pull_u16(msg); msgb_pull_u8(msg); // XXX align chip = msgb_pull_u8(msg); address = msgb_pull_u32(msg); data = msgb_pull(msg, nbytes) - nbytes; mycrc = osmo_crc16(0, data, nbytes); if (mycrc == crc) { res = flash_program(&the_flash, address, data, nbytes); } msgb_put_u8(reply, LOADER_FLASH_PROGRAM); msgb_put_u8(reply, nbytes); msgb_put_u16(reply, mycrc); msgb_put_u8(reply, 0); // XXX align msgb_put_u8(reply, chip); msgb_put_u32(reply, address); msgb_put_u32(reply, (uint32_t) res); // XXX sercomm_sendmsg(dlci, reply); break; default: printf("unknown command %d\n", command); msgb_free(reply); break; } out: msgb_free(msg); }
externC void cyg_start( void ) { int stat; void *err_addr; CYG_ADDRWORD flash_start, flash_end; void **flash_start_addr = (void *)&flash_start; void **flash_end_addr = (void *)&flash_end; void *flash_test_start, *flash_addr; cyg_int32 flash_block_size, flash_num_blocks; CYG_ADDRWORD test_buf1, test_buf2; cyg_uint32 *lp1, *lp2; int i, len; cyg_bool passed, ok; CYG_TEST_INIT(); #if 0 int j; diag_printf("Testing udelay: "); for (i = 0; i < 30; i++) { for (j = 0; j < 1000; j++) { CYGACC_CALL_IF_DELAY_US(1000); // Should be 1 second } diag_printf("."); } diag_printf("\n"); #endif passed = true; if ((stat = flash_init(diag_printf)) != 0) { diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); CYG_TEST_FAIL_FINISH("FLASH driver init failed"); } flash_get_limits((void *)0, flash_start_addr, flash_end_addr); // Keep 'end' address as last valid location, to avoid wrap around problems flash_end = flash_end - 1; flash_get_block_info(&flash_block_size, &flash_num_blocks); diag_printf("FLASH: 0x%x - 0x%x, %d blocks of 0x%x bytes each.\n", flash_start, flash_end + 1, flash_num_blocks, flash_block_size); // Verify that the testing limits are within the bounds of the // physical device. Also verify that the size matches with // the erase block size on the device if ((CYGNUM_IO_FLASH_TEST_OFFSET > (flash_end - flash_start)) || ((CYGNUM_IO_FLASH_TEST_OFFSET + CYGNUM_IO_FLASH_TEST_LENGTH) > (flash_end - flash_start))) { CYG_TEST_FAIL_FINISH("FLASH test region outside physical limits"); } if ((CYGNUM_IO_FLASH_TEST_LENGTH % flash_block_size) != 0) { CYG_TEST_FAIL_FINISH("FLASH test region must be integral multiple of erase block size"); } // Allocate two buffers large enough for the test test_buf1 = (CYG_ADDRWORD)CYGMEM_SECTION_heap1; test_buf2 = test_buf1 + CYGNUM_IO_FLASH_TEST_LENGTH; if (CYGMEM_SECTION_heap1_SIZE < (CYGNUM_IO_FLASH_TEST_LENGTH * 2)) { CYG_TEST_FAIL_FINISH("FLASH not enough heap space - reduce size of test region"); } diag_printf("... Using test buffers at %p and %p\n", (void *)test_buf1, (void *)test_buf2); flash_test_start = (void *)(flash_start + CYGNUM_IO_FLASH_TEST_OFFSET); #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Unlock test diag_printf("... Unlock test\n"); ok = true; if ((stat = flash_unlock(flash_test_start, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat)); ok = false; } #endif // Erase test diag_printf("... Erase test\n"); ok = true; if ((stat = flash_erase(flash_test_start, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: erase failed: %s\n", flash_errmsg(stat)); ok = false; } if (ok && (stat = flash_read(flash_test_start, (void *)test_buf1, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read/verify after erase failed: %s\n", flash_errmsg(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < CYGNUM_IO_FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp1++ != 0xFFFFFFFF) { diag_printf("FLASH: non-erased data found at offset %x\n", (CYG_ADDRWORD)(lp1-1) - test_buf1); diag_dump_buf((void *)(lp1-1), 32); ok = false; break; } } // Try reading in little pieces len = CYGNUM_IO_FLASH_TEST_LENGTH; flash_addr = flash_test_start; while (len > 0) { if ((stat = flash_read(flash_addr, (void *)test_buf1, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat)); ok = false; break; } flash_addr = (cyg_uint8 *)flash_addr + 0x200; len -= 0x200; lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < 0x200; i += sizeof(cyg_uint32)) { if (*lp1++ != 0xFFFFFFFF) { diag_printf("FLASH: non-erased data found at offset %p\n", (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp1-1) - test_buf1)); diag_dump_buf((void *)(lp1-1), 32); ok = false; len = 0; break; } } } if (!ok) { CYG_TEST_INFO("FLASH erase failed"); passed = false; } // Simple write/verify test diag_printf("... Write/verify test\n"); lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < CYGNUM_IO_FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { *lp1 = (cyg_uint32)lp1; lp1++; } ok = true; if (ok && (stat = flash_program(flash_test_start, (void *)test_buf1, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: write failed: %s\n", flash_errmsg(stat)); ok = false; } if (ok && (stat = flash_read(flash_test_start, (void *)test_buf2, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read/verify after write failed: %s\n", flash_errmsg(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; for (i = 0; i < CYGNUM_IO_FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp2++ != *lp1++) { diag_printf("FLASH: incorrect data found at offset %x\n", (CYG_ADDRWORD)(lp2-1) - test_buf2); diag_dump_buf((void *)(lp2-1), 32); ok = false; break; } } // Try reading in little pieces len = CYGNUM_IO_FLASH_TEST_LENGTH; flash_addr = flash_test_start; lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; while (len > 0) { if ((stat = flash_read(flash_addr, lp2, 0x200, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", flash_errmsg(stat)); ok = false; break; } flash_addr = (cyg_uint8 *)flash_addr + 0x200; len -= 0x200; for (i = 0; i < 0x200; i += sizeof(cyg_uint32)) { if (*lp2++ != *lp1++) { diag_printf("FLASH: incorrect data found at offset %p\n", (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp2-1) - test_buf2)); diag_dump_buf((void *)(lp2-1), 32); ok = false; len = 0; break; } } } if (!ok) { CYG_TEST_INFO("FLASH write/verify failed"); } #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Lock test diag_printf("... Lock test\n"); ok = true; if ((stat = flash_lock(flash_test_start, CYGNUM_IO_FLASH_TEST_LENGTH, &err_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: unlock failed: %s\n", flash_errmsg(stat)); ok = false; } #endif if (passed) { CYG_TEST_PASS_FINISH("FLASH test1"); } else { CYG_TEST_FAIL_FINISH("FLASH test1"); } }