Полная версия этой страницы:
samsung NAND
самуснговская NAND K9F2G08U0M, 2048 + 64 байт страница. стираю блок, сначала записываю страницу данных (2048 байт), дожидаюсь завершения, читаю статус (команда 0х70), все в порядке.
col1 = 0x00
col2 = 0x00
row1 = (unsigned char) page;
row1 = (unsigned char) page>>8;
row1 = (unsigned char) page>>16;
затем пишу spare area (64 байта) той же страницы.
col1 = 0x00
col2 = 0x80
row1 = (unsigned char) page;
row1 = (unsigned char) page>>8;
row1 = (unsigned char) page>>16;
дожидаюсь завершения, читаю статус - все в порядке.
но иногда при последующем чтении видно, что или данные или спаре область не записались. то-ли не стер я её.... то-ли х.з. уже и в режим рандом ввода/вывода загонял. все равно некоторые страницы не пишутся. и их много. линукс как ни странно все пишет/читает хорошо =)
А блок точно не битый?
Если "маркировку" стерли, в принципе, можно SAM-BA-ой восстановить.
чипа подключена к at91sam9260, линух форматирует эту флэшку с двумя бэдами. моей программой я их тоже вижу. есть еще куча блоков, которые линух пишет, а моя программа нет.
Понятно, кстати, сори, SAM-BA только сканирует а не помечает битые блоки ...
Ну а если проверять весь блок на "чистоту" после стриния ...
А не пробовали писать сразу все 2112 байт, такой режим ведь тоже возможен. Записать 2048 данных а затем добить еще spare область.
И просто посмотреть что получится. По идее это самый комфортный для NAND способ, чем меньше к ней обращаешься, тем данные надежней.
можно по идее и сразу все писать. там драйвер верхнего уровня хочет кусками писать. прийдется его изнахратить. не уверен, что это приведет к положительным результатам.
Самсунговская память вполне выдерживает запись по частям. Проверьте временнУю диаграмму. Особенно то место, где проверяется готовность. Там нужно обязательно выдержать небольшую паузу между командой и проверкой готовности, она может не успеть выставиться, а Вы сочтете, что она уже снялась. Я когда-то на такое наезжал - эффект очень похож на описанный Вами. Все довольны, только работает со сбоями.
Alex11 была мысль про тайминги. возможно при стирании блока выставляет готовность после того как я уже проверил ее. в понедельник доберусь до работы - проверю.
Код
#define WRITE_NAND_COMMAND(d) do{ *(volatile unsigned char *)((unsigned long)base_addressCLE) = (unsigned char)(d); } while(0)
#define WRITE_NAND_ADDRESS(d) do{ *(volatile unsigned char *)((unsigned long)base_addressALE) = (unsigned char)(d); } while(0)
#define WRITE_NAND(d) do{ *(volatile unsigned char *)((unsigned long)base_address) = (unsigned char)d; } while(0)
#define READ_NAND() ((unsigned char)(*(volatile unsigned char *)(unsigned long)base_address))
int nand_wait_busy(struct chipio *cio, uint32_t usec) {
uint32_t a=0;
for(a=0;a<5;a++)nanospin_ns(1000);
for(usec = MAX_ERASE_USEC; usec; --usec) {
if( (((AT91PS_PIO)base_PIO_C)->PIO_PDSR & AT91C_PIO_PC13) != 0){
return(0);
}
nanospin_ns(1000);
}
// We will exit from the log and never reach here.
return(-1);
}
//================================================================================
===================
int nand_erase_blk(struct chipio * cio, unsigned blk){
unsigned char status;
#ifdef debug
fprintf(stderr, "nand_erase_page: block %X\n", blk);
#endif
//set NAND CE
((AT91PS_PIO)base_PIO_C)->PIO_CODR = AT91C_PC14_NCS3_NANDCS;
WRITE_NAND_COMMAND(NANDCMD_ERASE);
/* Push sector address in three cycles */
WRITE_NAND_ADDRESS((blk >> 0) & 0xFF);
WRITE_NAND_ADDRESS((blk >> 8) & 0xFF);
WRITE_NAND_ADDRESS((blk >> 16) & 0xFF);
WRITE_NAND_COMMAND(NANDCMD_ERASECONFIRM);
if(nand_wait_busy(cio, MAX_ERASE_USEC) != 0) {
fprintf(stderr, "nand_erase_blk: nand_wait_busy - error...\n");
return(-1);
}
if(nand_wait_busy(cio, MAX_ERASE_USEC) != 0) {
fprintf(stderr, "nand_erase_blk: nand_wait_busy - error...\n");
return(-1);
}
WRITE_NAND_COMMAND(NANDCMD_STATUSREAD);
if(nand_wait_busy(cio, MAX_READ_USEC) != 0) {
fprintf(stderr, "nand_erase_blk: nand_wait_busy - error...\n");
return(-1);
}else{
status = READ_NAND();
if(status & NAND_PROGRAM_ERASE_ERROR){
fprintf(stderr, "nand_erase_blk: ERROR ERASING BLOCK\n");
return(-1);
}
}
//clear NAND CE
// ((AT91PS_PIO)base_PIO_C)->PIO_SODR = AT91C_PC14_NCS3_NANDCS;
return 0;
}
облома при стирании не происходит. тем не менее при чтении страницы из стертого блока обнаруживается, что страница не чистая. куда рыть уже не знаю. времянки вроде выдержаны.
Совсем дурацкий вопрос - Вы помните, что нога Busy - открытый сток?
И еще один совет. Попробуйте в качестве эксперимента вместо анализа Busy сделать тупую задержку на 0.5 сек. Если все заработает - ищите, где у Вас сигнал не доходит до анализа бита.
RW9UAO
Feb 10 2009, 01:03
нога подтянута. =) линукс-то пашет там замечательно. и у-бут. просто задержку пробовал. такая же песня. анализ ноги R/B происходит, он сделан с таймаутом. так я вижу, что чтение требует 1-2 цикла до готовности, запись 8-9 циклов, и стирание блока 840-850 циклов. уже весь моск сломал. сегодня попробую еще один вариант - руками выставлять CLE и ALE.
Может "плюшки" как раз при чтении (если пин R/B аппаратно устанавливается а а сектора якобы не чистые) ...
RW9UAO
Feb 10 2009, 13:18
да не, читается нормально. сегодня перетряхнул настройки всяких SMC_SETUP3 на предмет таймингов. с неправильными таймингами вообще не работает. попутно нашел косяк в атмеловской аппноте на предмет настройки этих регистров. уже начинаю подозревать, что это мне контроллер ЕСС мешает. хотя как он может мешать стирать блок? перетряхнул исходники u-boot - без толку, я точно так-же все делаю. видимо что-то все же не так.
И все-таки, гляньте осциллом, если после команды стирания блока R/B устанавливается, а в блоке присутствуют "грязные" страницы , это явно глюк чтения, потому как сами вы блок не стираете (это ведь сам чип делает) а вот чтение под вашей опекой ...
Ну и в добавок, если "грязь" в страницах будет плавать (от чтения к чтению) - еще один довод в сторону глюка чтения.
Alex11
Feb 10 2009, 21:54
Проверьте еще одно. Нет ли в диаграмме лишних RD и WR, или иголок на них - тоже дает потрясающий эффект. Эти чипы иголки вместо полновесных сигналов ловят на ура.
RW9UAO
Feb 11 2009, 09:57
в процедуре
int nand_erase_blk(struct chipio * cio, unsigned blk)
надо было
row = blk << 6
и только потом совать его в NAND.
WRITE_NAND_COMMAND(NANDCMD_ERASE);
WRITE_NAND_ADDRESS((row >> 0) & 0xFF);
WRITE_NAND_ADDRESS((row >> 8) & 0xFF);
WRITE_NAND_ADDRESS((row >> 16) & 0xFF);
WRITE_NAND_COMMAND(NANDCMD_ERASECONFIRM);
курим внимательно даташит. пень, короче, не доглядел. щас все пишется и стирается.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.