Mcuzone 野芯科技
标题: SAM4E-EK开发板代码解读07——NAND_FLASH [打印本页]
作者: Mcuzone_TKN 时间: 2020-5-13 15:54
标题: SAM4E-EK开发板代码解读07——NAND_FLASH
本帖最后由 Mcuzone_TKN 于 2020-5-15 09:15 编辑
关键词:Microchip Atmel SAM4E SAM4E-EK SAM4E16E 芯片 NAND_FLASH
概述:简要运行NAND闪存组件单元测试
NAND Flash的容量较大。整片Flash分为若干个块(Block),每个Block分为若干个页(Page)。在每个页中,除了数据区域,也包含若干“多余”的区域,用来进行ECC等操作。在进行擦除操作是,基本单位是“块”;而编程的基本单位是“页”。另外,NAND Flash的物理特性决定了其在编程时,每个bit只能从1变成0,不能从0变成1,所以写之前,必须先对块进行擦除(擦除时把所有位置为1)。
读写时序:因为没有地址线,所以读写较为复杂。读写时,需要先发送相应操作命令,然后发送地址,才能进行数据传输。
打开产品光盘SAM4E16E-EK/SAM4E16E-EK中文资料/softpack软件包/Atmel Studio 7,打开08_NAND_FLASH_UNIT_TEST例子。
int main(void)
{
const usart_serial_options_t usart_serial_options = {
.baudrate = CONF_TEST_BAUDRATE,
.charlength = CONF_TEST_CHARLENGTH,
.paritytype = CONF_TEST_PARITY,
.stopbits = CONF_TEST_STOPBITS
};
sysclk_init();
#if SAM
sysclk_enable_peripheral_clock(CONSOLE_UART_ID);
#else
sysclk_enable_hsb_module(SYSCLK_EBI);
sysclk_enable_pbb_module(SYSCLK_SMC_REGS);
sysclk_enable_pbb_module(SYSCLK_HMATRIX);
#endif
board_init();
stdio_serial_init(CONF_TEST_USART, &usart_serial_options);
//定义所有测试用例
DEFINE_TEST_CASE(nand_flash_test_read_id, NULL, run_test_initialization, NULL,
"NAND Flash initialization and id test");
DEFINE_TEST_CASE(nand_flash_test_raw_read_write, NULL,
run_test_raw_read_write, NULL,
"NAND Flash raw data read/write test");
DEFINE_TEST_CASE(nand_flash_test_software_ecc, NULL,
run_test_software_ecc, NULL,
"NAND Flash data read/write with software ECC test");
//将测试用例地址放在数组中。
DEFINE_TEST_ARRAY(nand_flash_test_array) = {
&nand_flash_test_read_id,
&nand_flash_test_raw_read_write,
&nand_flash_test_software_ecc,};
//定义测试套件
DEFINE_TEST_SUITE(nand_flash_suite, nand_flash_test_array,
"NAND Flash component test suite");
//在测试套件中运行所有测试
test_suite_run(&nand_flash_suite);
while (1) {
}
}
作者: Mcuzone_TKN 时间: 2020-5-13 16:00
//简要测试NAND FLASH初始化 这个测试调用初始化函数并检查flash id。param测试当前测试用例
static void run_test_initialization(const struct test_case *test)
{
//Test1:检查initialize函数
error_code = nand_flash_raw_initialize(&nf_raw, 0, cmd_address,
addr_address, data_address);
test_assert_true(test, error_code == 0,
"NAND Flash initialization failed!");
//获取设备参数
num_block = nand_flash_model_get_device_size_in_blocks(&nf_raw.model);
page_size = nand_flash_model_get_page_data_size(&nf_raw.model);
nf_ecc.raw = nf_raw;
//检查flash ID
flash_id = nand_flash_raw_read_id(&nf_raw);
#if (SAM3XA || SAM3S)
test_assert_true(test, flash_id == 0x9580DA2C,
"NAND Flash ID error!");
#endif
#if SAM3U
test_assert_true(test, flash_id == 0xD580CA2C,
"NAND Flash ID error!");
#endif
#if UC3A3
test_assert_true(test, flash_id == 0x1580DA2C,
"NAND Flash ID error!");
#endif
}
作者: Mcuzone_TKN 时间: 2020-5-13 16:07
本帖最后由 Mcuzone_TKN 于 2020-5-13 16:09 编辑
//简单测试原始的读写函数,这个测试调用原话的读写并检查数据值。param测试当前测试用例
static void run_test_raw_read_write(const struct test_case *test)
{
uint32_t i;
//擦除块,并使用第一个良好的块读写测试
for (block = (num_block - 1); block > 0; block--) {
error_code = nand_flash_raw_erase_block(&nf_raw, block);
if (!error_code) {
break;
}
}
//检查擦除结果
test_assert_true(test, block != 0,
"All block erase failed!");
//重置读缓冲区。
memset(read_buffer, 0, sizeof(read_buffer));
//从已擦除的NAND闪存块中读取第一页
nand_flash_raw_read_page(&nf_raw, block, 0, read_buffer, 0);
//检查删除结果的数据内容
for (i = 0; i < page_size; i++) {
if (read_buffer != 0xFF) {
error_code = 1;
break;
}
}
test_assert_true(test, error_code == 0,
"The content of the block erase result error!");
//在SRAM中准备一个页面大小的缓冲区
for (i = 0; i < page_size; i++) {
write_buffer = i & 0xFF;
}
//重置缓冲区
memset(read_buffer, 0, sizeof(read_buffer));
//给NAND FLASH写页
error_code = nand_flash_raw_write_page(&nf_raw, block, 0, write_buffer,
0);
//从NAND Flash里面读页/
nand_flash_raw_read_page(&nf_raw, block, 0, read_buffer, 0);
//测试读缓冲区是否与SRAM缓冲区相同
error_code = memcmp(read_buffer, write_buffer, sizeof(write_buffer));
//检查擦除结果
test_assert_true(test, error_code == 0,
"The raw read/write functions test failed!");
}
作者: Mcuzone_TKN 时间: 2020-5-13 16:17
//简要测试软件ECC的读写功能
本测试调用软件ECC的读写功能,并检查数据值。
static void run_test_software_ecc(const struct test_case *test)
{
uint32_t i;
//擦除块,并使用第一个良好的块读写测试
for (block = (num_block - 1); block > 0; block--) {
error_code = nand_flash_raw_erase_block(&nf_raw, block);
if (!error_code) {
break;
}
}
//检查擦除结果
test_assert_true(test, block != 0,
"All block erase failed!");
//重置读缓冲区
memset(read_buffer, 0, sizeof(read_buffer));
//从已擦除的NANDFLASH中读取第一页
nand_flash_raw_read_page(&nf_raw, block, 0, read_buffer, 0);
//检查删除结果的数据内容
for (i = 0; i < page_size; i++) {
if (read_buffer[i] != 0xFF) {
error_code = 1;
break;
}
}
test_assert_true(test, error_code == 0,
"The content of the block erase result error!");
//在SRAM中准备一个页面大小的缓冲区
for (i = 0; i < page_size; i++) {
write_buffer[i] = i & 0xFF;
}
//重置读缓冲区
memset(read_buffer, 0, sizeof(read_buffer));
//往NANDFLASH里面写页
error_code = nand_flash_ecc_write_page(&nf_ecc, block, 0, write_buffer,
spare_buffer);
//从NANDFLASH里面读页
nand_flash_ecc_read_page(&nf_ecc, block, 0, read_buffer, spare_buffer);
//测试读缓冲区是否与SRAM缓冲区相同
error_code = memcmp(read_buffer, write_buffer, sizeof(write_buffer));
//检查擦除结果
test_assert_true(test, error_code == 0,
"The software ECC read/write functions test failed!");
//清除所有块以清除NANDFLASH
for (i = 0; i < num_block; i++) {
nand_flash_raw_erase_block(&nf_raw, i);
}
}
欢迎光临 Mcuzone 野芯科技 (http://testbbs.mcuzone.com/) |
Powered by Discuz! X3.1 |