From e564034a6062e0629c0139c4a4854c4698fcd008 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 19 May 2014 08:20:46 +0200 Subject: [PATCH] nand: Write multiple copies of UBL and U-Boot The NAND might have more bit flips than can be recovered. The way to deal with it is to write multiple copies on multiple pages. The probability of all pages failing depends on the specific NAND flash used and was not calculated so far. The RBL is capable of trying to load several copies and we should be more safe now. This requires a new partioning inside the U-Boot or other bootloader. --- nand.c | 4 ++-- nand.h | 11 ++++++++--- nandboot.c | 12 ++++++++---- uartboot.c | 37 ++++++++++++++++++++++++------------- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/nand.c b/nand.c index 926f9be..4d7947e 100644 --- a/nand.c +++ b/nand.c @@ -935,10 +935,10 @@ nand_write_prog(struct nand_image_descriptor_t *im_desc, const uint8_t *src, uart_send_lf(); /* Check whether writing UBL or APP (based on destination block) */ - if (im_desc->block_num == START_UBL_BLOCK_NUM) + if (im_desc->block_num <= END_UBL_BLOCK_NUM) max_block_num = END_UBL_BLOCK_NUM; else - max_block_num = nand_info.num_blocks - 1; + max_block_num = im_desc->block_num + MAX_BLOCK_PER_UBOOT - 1; NAND_WRITE_RETRY: if (im_desc->block_num > max_block_num) { diff --git a/nand.h b/nand.h index 8fa1c37..b264f9e 100644 --- a/nand.h +++ b/nand.h @@ -27,10 +27,15 @@ #include "common.h" #include "davinci.h" -/* Define which blocks are valid for writing UBL and APP data */ +/* Define which blocks are valid for writing UBL data */ #define START_UBL_BLOCK_NUM 1 -#define END_UBL_BLOCK_NUM (START_APP_BLOCK_NUM - 1) -#define START_APP_BLOCK_NUM ((nand_get_bytes_per_block() == 16384) ? 32 : 4) +#define END_UBL_BLOCK_NUM ((nand_get_bytes_per_block() == 16384) ? 32 : 5) + +/* Define which blocks are valid for writing U-BOOT data */ +/* NUTAQ: Adjust it according to your requirements */ +#define START_UBOOT_BLOCK_NUM (END_UBL_BLOCK_NUM + 1) +#define MAX_BLOCK_PER_UBOOT 6 +#define END_UBOOT_BLOCK_NUM 31 #define MAX_PAGE_SIZE (2048+64) /* Data bytes + spare area */ diff --git a/nandboot.c b/nandboot.c index d78db42..75fb6e2 100644 --- a/nandboot.c +++ b/nandboot.c @@ -46,12 +46,14 @@ nand_copy(uint32_t *jump_entry_point) struct nand_image_descriptor_t im_desc; int last_header_block; - start_block = START_APP_BLOCK_NUM; - last_header_block = start_block + 10; + start_block = START_UBOOT_BLOCK_NUM; + last_header_block = END_UBOOT_BLOCK_NUM; NAND_startAgain: - /* Read header about application starting at START_APP_BLOCK_NUM, Page 0 - * and try 10 blocks. */ + failedOnceAlready = false; + + /* Read header about application starting at START_UBOOT_BLOCK_NUM, Page 0 + * and try 50 blocks. */ for (count = start_block; count <= last_header_block; count++) { if (nand_read_page(count, 0, nand_header) != E_PASS) continue; @@ -79,6 +81,8 @@ NAND_startAgain: uart_send_hexnum(im_desc.size_in_pages, 8); uart_send_str(", Load = "); uart_send_hexnum(im_desc.load_address, 8); + uart_send_str(", Block = "); + uart_send_hexnum(im_desc.block_num, 8); uart_send_lf(); rxBuf = (uint8_t *) im_desc.load_address; diff --git a/uartboot.c b/uartboot.c index 836b4e6..d64085c 100644 --- a/uartboot.c +++ b/uartboot.c @@ -86,6 +86,8 @@ void uart_boot(uint32_t *jump_entry_point) { #if defined(FLASH_TYPE_NAND) + int prog_ok = 0; + int block_num; struct nand_image_descriptor_t im_desc; #elif defined(FLASH_TYPE_NOR) struct nor_boot_t norBoot; @@ -128,13 +130,16 @@ uart_boot(uint32_t *jump_entry_point) NOR_WriteBytes(nor_get_flashbase(), uart_ack_header.size, (uint32_t) uart_ack_header.recv_buffer); #elif defined(FLASH_TYPE_NAND) - im_desc.magic = uart_ack_header.magic; - im_desc.entry_point = uart_ack_header.entry_point; - im_desc.block_num = START_UBL_BLOCK_NUM; - im_desc.load_address = 0; /* Load address not used by RBL */ + for (block_num = START_UBL_BLOCK_NUM; block_num <= END_UBL_BLOCK_NUM; block_num++) { + im_desc.magic = uart_ack_header.magic; + im_desc.block_num = block_num; + im_desc.entry_point = uart_ack_header.entry_point; + im_desc.load_address = 0; /* Load address not used by RBL */ - if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, - uart_ack_header.size) != E_PASS) + if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, uart_ack_header.size) == E_PASS) + prog_ok = 1; + } + if (!prog_ok) goto uartboot_error; #endif @@ -186,14 +191,20 @@ uart_boot(uint32_t *jump_entry_point) uart_ack_header.entry_point) != E_PASS) goto uartboot_error; #elif defined(FLASH_TYPE_NAND) - im_desc.magic = uart_ack_header.magic; - im_desc.entry_point = uart_ack_header.entry_point; - im_desc.block_num = START_APP_BLOCK_NUM; - /* Assuming load address is identical to entry point. */ - im_desc.load_address = uart_ack_header.entry_point; + /* Write multiple copy of U-Boot (depending on the defines in NAND.h) */ + prog_ok = 0; + for (block_num = START_UBOOT_BLOCK_NUM; (block_num+MAX_BLOCK_PER_UBOOT-1) <= END_UBOOT_BLOCK_NUM; block_num += MAX_BLOCK_PER_UBOOT) { + im_desc.magic = uart_ack_header.magic; + im_desc.block_num = block_num; + im_desc.entry_point = uart_ack_header.entry_point; - if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, - uart_ack_header.size) != E_PASS) + /* Assuming load address is identical to entry point. */ + im_desc.load_address = uart_ack_header.entry_point; + + if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, uart_ack_header.size) == E_PASS) + prog_ok = 1; + } + if (!prog_ok) goto uartboot_error; #endif