5151 NP_ERR_LEN_NOT_ALIGN = -111 ,
5252 NP_ERR_LEN_EXCEEDED = -112 ,
5353 NP_ERR_LEN_INVALID = -113 ,
54+ NP_ERR_BBT_OVERFLOW = -114 ,
5455};
5556
5657typedef struct __attribute__((__packed__ ))
@@ -170,6 +171,7 @@ typedef struct
170171 uint32_t addr ;
171172 uint32_t len ;
172173 int addr_is_set ;
174+ int bb_is_read ;
173175 np_page_t page ;
174176 uint32_t bytes_written ;
175177 uint32_t bytes_ack ;
@@ -251,6 +253,73 @@ static int np_cmd_nand_read_id(np_prog_t *prog)
251253 return ret ;
252254}
253255
256+ static int np_read_bad_block_info_from_page (np_prog_t * prog , uint32_t block ,
257+ uint32_t page , chip_info_t * chip_info , bool * is_bad )
258+ {
259+ uint8_t bad_block_data ;
260+ uint32_t status , addr = block * chip_info -> block_size ;
261+
262+ status = nand_read_data (& bad_block_data , page , chip_info -> page_size ,
263+ sizeof (bad_block_data ));
264+ switch (status )
265+ {
266+ case NAND_READY :
267+ break ;
268+ case NAND_ERROR :
269+ ERROR_PRINT ("NAND read bad block info error at 0x%lx\r\n" , addr );
270+ return NP_ERR_NAND_RD ;
271+ case NAND_TIMEOUT_ERROR :
272+ ERROR_PRINT ("NAND read timeout at 0x%lx\r\n" , addr );
273+ return NP_ERR_NAND_RD ;
274+ default :
275+ ERROR_PRINT ("Unknown NAND status\r\n" );
276+ return NP_ERR_NAND_RD ;
277+ }
278+
279+ * is_bad = bad_block_data != NP_NAND_GOOD_BLOCK_MARK ;
280+
281+ return 0 ;
282+ }
283+
284+ static int _np_cmd_read_bad_blocks (np_prog_t * prog )
285+ {
286+ int ret ;
287+ bool is_bad ;
288+ uint32_t block , block_num , page_num , page ;
289+
290+ block_num = prog -> chip_info -> size / prog -> chip_info -> block_size ;
291+ page_num = prog -> chip_info -> block_size / prog -> chip_info -> page_size ;
292+
293+ /* Bad block - not 0xFF value in the first or second page in the block at
294+ * zero offset in the page spare area
295+ */
296+ for (block = 0 ; block < block_num ; block ++ )
297+ {
298+ page = block * page_num ;
299+ if ((ret = np_read_bad_block_info_from_page (prog , block , page ,
300+ prog -> chip_info , & is_bad )))
301+ {
302+ return ret ;
303+ }
304+
305+ if (!is_bad && (ret = np_read_bad_block_info_from_page (prog , block ,
306+ page + 1 , prog -> chip_info , & is_bad )))
307+ {
308+ return ret ;
309+ }
310+
311+ if (is_bad && nand_bad_block_table_add (block *
312+ prog -> chip_info -> block_size ))
313+ {
314+ return NP_ERR_BBT_OVERFLOW ;
315+ }
316+ }
317+
318+ prog -> bb_is_read = 1 ;
319+
320+ return 0 ;
321+ }
322+
254323static int np_nand_erase (np_prog_t * prog , uint32_t page )
255324{
256325 uint32_t status ;
@@ -280,6 +349,7 @@ static int np_nand_erase(np_prog_t *prog, uint32_t page)
280349
281350static int _np_cmd_nand_erase (np_prog_t * prog )
282351{
352+ int ret ;
283353 uint32_t addr , page , pages_in_block , len ;
284354 np_erase_cmd_t * erase_cmd = (np_erase_cmd_t * )prog -> rx_buf ;
285355 bool is_bad = false, skip_bb = erase_cmd -> flags .skip_bb ;
@@ -289,6 +359,9 @@ static int _np_cmd_nand_erase(np_prog_t *prog)
289359
290360 DEBUG_PRINT ("Erase at 0x%lx %lx bytes command\r\n" , addr , len );
291361
362+ if (skip_bb && !prog -> bb_is_read && (ret = _np_cmd_read_bad_blocks (prog )))
363+ return ret ;
364+
292365 if (addr & (prog -> chip_info -> block_size - 1 ))
293366 {
294367 ERROR_PRINT ("Address 0x%lx is not aligned to block size 0x%lx\r\n" ,
@@ -372,6 +445,7 @@ static int np_send_write_ack(uint32_t bytes_ack)
372445
373446static int np_cmd_nand_write_start (np_prog_t * prog )
374447{
448+ int ret ;
375449 uint32_t addr , len ;
376450
377451 np_write_start_cmd_t * write_start_cmd =
@@ -408,6 +482,13 @@ static int np_cmd_nand_write_start(np_prog_t *prog)
408482 return NP_ERR_ADDR_NOT_ALIGN ;
409483 }
410484
485+ prog -> skip_bb = write_start_cmd -> flags .skip_bb ;
486+ if (prog -> skip_bb && !prog -> bb_is_read &&
487+ (ret = _np_cmd_read_bad_blocks (prog )))
488+ {
489+ return ret ;
490+ }
491+
411492 prog -> addr = addr ;
412493 prog -> len = len ;
413494 prog -> addr_is_set = 1 ;
@@ -417,7 +498,6 @@ static int np_cmd_nand_write_start(np_prog_t *prog)
417498
418499 prog -> bytes_written = 0 ;
419500 prog -> bytes_ack = 0 ;
420- prog -> skip_bb = write_start_cmd -> flags .skip_bb ;
421501
422502 return np_send_ok_status ();
423503}
@@ -627,6 +707,7 @@ static int np_nand_read(uint32_t addr, np_page_t *page,
627707
628708static int _np_cmd_nand_read (np_prog_t * prog )
629709{
710+ int ret ;
630711 uint32_t addr , len , send_len ;
631712 static np_page_t page ;
632713 uint32_t resp_header_size = offsetof(np_resp_t , data );
@@ -666,6 +747,9 @@ static int _np_cmd_nand_read(np_prog_t *prog)
666747 return NP_ERR_LEN_NOT_ALIGN ;
667748 }
668749
750+ if (skip_bb && !prog -> bb_is_read && (ret = _np_cmd_read_bad_blocks (prog )))
751+ return ret ;
752+
669753 page .page = addr / prog -> chip_info -> page_size ;
670754 page .offset = 0 ;
671755
@@ -752,6 +836,7 @@ static int np_cmd_nand_select(np_prog_t *prog)
752836 {
753837 nand_init ();
754838 nand_bad_block_table_init ();
839+ prog -> bb_is_read = 0 ;
755840 prog -> chip_info = chip_info_selected_get ();
756841 }
757842 else
@@ -765,73 +850,21 @@ static int np_cmd_nand_select(np_prog_t *prog)
765850 return np_send_ok_status ();
766851}
767852
768- static int np_read_bad_block_info_from_page (np_prog_t * prog , uint32_t block ,
769- uint32_t page , chip_info_t * chip_info , bool * is_bad )
853+ static int np_send_bad_blocks (np_prog_t * prog )
770854{
771- uint8_t bad_block_data ;
772- uint32_t status , addr = block * chip_info -> block_size ;
773-
774- status = nand_read_data (& bad_block_data , page , chip_info -> page_size ,
775- sizeof (bad_block_data ));
776- switch (status )
777- {
778- case NAND_READY :
779- break ;
780- case NAND_ERROR :
781- ERROR_PRINT ("NAND read bad block info error at 0x%lx\r\n" , addr );
782- return NP_ERR_NAND_RD ;
783- case NAND_TIMEOUT_ERROR :
784- ERROR_PRINT ("NAND read timeout at 0x%lx\r\n" , addr );
785- return NP_ERR_NAND_RD ;
786- default :
787- ERROR_PRINT ("Unknown NAND status\r\n" );
788- return NP_ERR_NAND_RD ;
789- }
855+ uint32_t addr ;
856+ void * bb_iter ;
790857
791- if (bad_block_data != NP_NAND_GOOD_BLOCK_MARK )
858+ for (bb_iter = nand_bad_block_table_iter_alloc (& addr ); bb_iter ;
859+ bb_iter = nand_bad_block_table_iter_next (bb_iter , & addr ))
792860 {
793- * is_bad = true;
794861 if (np_send_bad_block_info (addr , prog -> chip_info -> block_size ))
795862 return -1 ;
796- if (nand_bad_block_table_add (addr ))
797- return -1 ;
798863 }
799- else
800- * is_bad = false;
801864
802865 return 0 ;
803866}
804867
805- static int _np_cmd_read_bad_blocks (np_prog_t * prog )
806- {
807- bool is_bad ;
808- uint32_t block , block_num , page_num , page ;
809-
810- block_num = prog -> chip_info -> size / prog -> chip_info -> block_size ;
811- page_num = prog -> chip_info -> block_size / prog -> chip_info -> page_size ;
812-
813- /* Bad block - not 0xFF value in the first or second page in the block at
814- * zero offset in the page spare area
815- */
816- for (block = 0 ; block < block_num ; block ++ )
817- {
818- page = block * page_num ;
819- if (np_read_bad_block_info_from_page (prog , block , page , prog -> chip_info ,
820- & is_bad ))
821- {
822- return -1 ;
823- }
824-
825- if (!is_bad && np_read_bad_block_info_from_page (prog , block , page + 1 ,
826- prog -> chip_info , & is_bad ))
827- {
828- return -1 ;
829- }
830- }
831-
832- return np_send_ok_status ();
833- }
834-
835868int np_cmd_read_bad_blocks (np_prog_t * prog )
836869{
837870 int ret ;
@@ -840,7 +873,10 @@ int np_cmd_read_bad_blocks(np_prog_t *prog)
840873 ret = _np_cmd_read_bad_blocks (prog );
841874 led_rd_set (false);
842875
843- return ret ;
876+ if (ret || (ret = np_send_bad_blocks (prog )))
877+ return ret ;
878+
879+ return np_send_ok_status ();
844880}
845881
846882static np_cmd_handler_t cmd_handler [] =
0 commit comments