cyg_bool jffs2_flash_read(struct jffs2_sb_info * c, cyg_uint32 read_buffer_offset, const size_t size, size_t * return_size, unsigned char *write_buffer) { Cyg_ErrNo err; cyg_uint32 len = size; struct super_block *sb = OFNI_BS_2SFFJ(c); //D2(printf("FLASH READ\n")); //D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset)); //D2(printf("write address = %x\n", write_buffer)); //D2(printf("size = %x\n", size)); err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset); *return_size = (size_t) len; return ((err == ENOERR) ? ENOERR : -EIO); }
externC void cyg_start( void ) { Cyg_ErrNo stat; cyg_io_handle_t flash_handle; cyg_io_flash_getconfig_erase_t e; cyg_io_flash_getconfig_devsize_t d; cyg_io_flash_getconfig_blocksize_t b; cyg_io_flash_getconfig_lock_t l; cyg_io_flash_getconfig_unlock_t u; CYG_ADDRWORD flash_start, flash_end; CYG_ADDRWORD flash_test_start, flash_addr; cyg_uint32 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(); passed = true; if ((stat = cyg_io_lookup(FLASH_TEST_DEVICE, &flash_handle)) == -ENOENT) { stat = cyg_io_lookup(FLASH_TEST_DEVICE2, &flash_handle); } if (stat != 0) { diag_printf("FLASH: driver init failed: %s\n", strerror(-stat)); CYG_TEST_FAIL_FINISH("FLASH driver init failed"); } len = sizeof(d); stat = cyg_io_get_config( flash_handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &d, &len ); flash_start = 0; // Keep 'end' address as last valid location, to avoid wrap around problems flash_end = d.dev_size - 1; len = sizeof(b); b.offset = 0; stat = cyg_io_get_config( flash_handle, CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &b, &len ); flash_block_size = b.block_size; flash_num_blocks = d.dev_size/flash_block_size; diag_printf("FLASH: %p - %p, %d blocks of 0x%x bytes each.\n", (void*)flash_start, (void*)(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 ((FLASH_TEST_OFFSET > (flash_end - flash_start)) || ((FLASH_TEST_OFFSET + FLASH_TEST_LENGTH) > (flash_end - flash_start))) { CYG_TEST_FAIL_FINISH("FLASH test region outside physical limits"); } if ((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 + FLASH_TEST_LENGTH; if (CYGMEM_SECTION_heap1_SIZE < (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 = flash_start + FLASH_TEST_OFFSET; #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Unlock test diag_printf("... Unlock test\n"); ok = true; u.offset = flash_test_start; u.len = FLASH_TEST_LENGTH; len = sizeof(u); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_UNLOCK, &u, &len ) ) != 0 || u.flasherr != 0) { diag_printf("FLASH: unlock failed: %s %s\n", strerror(stat), cyg_flash_errmsg(u.flasherr)); ok = false; } #endif // Erase test diag_printf("... Erase test\n"); ok = true; e.offset = flash_test_start; e.len = FLASH_TEST_LENGTH; len = sizeof(e); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len ) ) != 0 || e.flasherr != 0) { diag_printf("FLASH: erase failed: %s %s\n", cyg_epcs_errmsg(stat), cyg_epcs_errmsg(e.flasherr)); ok = false; } len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bread(flash_handle, (void *)test_buf1, &len, flash_test_start)) != 0) { diag_printf("FLASH: read/verify after erase failed: %s\n", cyg_epcs_errmsg(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp1++ != 0xFFFFFFFF) { diag_printf("FLASH: non-erased data found at offset %p\n", (void*)((CYG_ADDRWORD)(lp1-1) - test_buf1)); diag_dump_buf((void *)(lp1-1), 32); ok = false; break; } } // Try reading in little pieces len = FLASH_TEST_LENGTH; flash_addr = flash_test_start; while (len > 0) { cyg_uint32 l = 0x200; if ((stat = cyg_io_bread(flash_handle, (void *)test_buf1, &l, flash_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", strerror(stat)); ok = false; break; } flash_addr = flash_addr + l; len -= l; 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 < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { *lp1 = (cyg_uint32)lp1; lp1++; } ok = true; len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bwrite(flash_handle, (void *)test_buf1, &len, flash_test_start)) != 0) { diag_printf("FLASH: write failed: %s\n", strerror(stat)); ok = false; } len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bread(flash_handle, (void *)test_buf2, &len, flash_test_start)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read/verify after write failed: %s\n", strerror(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; for (i = 0; i < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp2++ != *lp1++) { diag_printf("FLASH: incorrect data found at offset %p\n", (void *)((CYG_ADDRWORD)(lp2-1) - test_buf2)); diag_dump_buf((void *)(lp2-1), 32); ok = false; break; } } // Try reading in little pieces len = FLASH_TEST_LENGTH; flash_addr = flash_test_start; lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; while (len > 0) { cyg_uint32 l = 0x200; if ((stat = cyg_io_bread(flash_handle, (void *)lp2, &l, flash_addr)) != 0) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", strerror(stat)); ok = false; break; } flash_addr = flash_addr + l; len -= l; for (i = 0; i < l; 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; } } } #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Lock test diag_printf("... Lock test\n"); ok = true; l.offset = flash_test_start; l.len = FLASH_TEST_LENGTH; len = sizeof(l); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_LOCK, &l, &len ) ) != 0 || l.flasherr != 0 ) { diag_printf("FLASH: unlock failed: %s %s\n", strerror(stat), cyg_flash_errmsg(l.flasherr)); ok = false; } #endif if (!ok) { CYG_TEST_INFO("FLASH write/verify failed"); } if (passed) { CYG_TEST_PASS_FINISH("FLASH test1"); } else { CYG_TEST_FAIL_FINISH("FLASH test1"); } }