Skip to content

Commit b03376d

Browse files
committed
Skip bad blocks on erase
1 parent 98e522c commit b03376d

File tree

4 files changed

+88
-5
lines changed

4 files changed

+88
-5
lines changed

firmware/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ USB_SRCS=hw_config.c stm32_it.c usb_prop.c usb_desc.c usb_istr.c usb_pwr.c \
5252

5353

5454
SRCS=main.c system_stm32f10x.c syscalls.c fsmc_nand.c chip_db.c led.c uart.c \
55-
jtag.c cdc.c nand_programmer.c $(USB_SRCS)
55+
jtag.c cdc.c nand_programmer.c nand_bad_block.c $(USB_SRCS)
5656

5757
OBJS=$(addprefix $(OBJ_DIR),$(SRCS:.c=.o)) \
5858
$(addprefix $(OBJ_DIR),$(STARTUP:.s=.o))

firmware/nand_bad_block.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* Copyright (C) 2017 Bogdan Bogush <[email protected]>
2+
* This program is free software; you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License version 3.
4+
*/
5+
6+
#include "nand_bad_block.h"
7+
#include <string.h>
8+
9+
#define NAND_BAD_BLOCK_TABLE_SIZE 20
10+
11+
static uint32_t nand_bad_block_table_count;
12+
static uint32_t nand_bad_block_table[NAND_BAD_BLOCK_TABLE_SIZE];
13+
14+
void nand_bad_block_table_init()
15+
{
16+
memset(nand_bad_block_table, 0, NAND_BAD_BLOCK_TABLE_SIZE);
17+
nand_bad_block_table_count = 0;
18+
}
19+
20+
int nand_bad_block_table_add(uint32_t addr)
21+
{
22+
if (nand_bad_block_table_count == NAND_BAD_BLOCK_TABLE_SIZE)
23+
return -1;
24+
25+
nand_bad_block_table[nand_bad_block_table_count++] = addr;
26+
return 0;
27+
}
28+
29+
bool nand_bad_block_table_lookup(uint32_t addr)
30+
{
31+
uint32_t i;
32+
33+
for (i = 0; i < nand_bad_block_table_count; i++)
34+
{
35+
if (nand_bad_block_table[i] == addr)
36+
return true;
37+
}
38+
39+
return false;
40+
}

firmware/nand_bad_block.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* Copyright (C) 2017 Bogdan Bogush <[email protected]>
2+
* This program is free software; you can redistribute it and/or modify
3+
* it under the terms of the GNU General Public License version 3.
4+
*/
5+
6+
#ifndef _NAND_BAD_BLOCK_H_
7+
#define _NAND_BAD_BLOCK_H_
8+
9+
#include <stdint.h>
10+
#include <stdbool.h>
11+
12+
void nand_bad_block_table_init();
13+
int nand_bad_block_table_add(uint32_t addr);
14+
bool nand_bad_block_table_lookup(uint32_t addr);
15+
16+
#endif

firmware/nand_programmer.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
#include "nand_programmer.h"
7+
#include "nand_bad_block.h"
78
#include "fsmc_nand.h"
89
#include "chip_db.h"
910
#include "led.h"
@@ -49,6 +50,7 @@ enum
4950
NP_ERR_BUF_OVERFLOW = -110,
5051
NP_ERR_LEN_NOT_ALIGN = -111,
5152
NP_ERR_LEN_EXCEEDED = -112,
53+
NP_ERR_LEN_INVALID = -113,
5254
};
5355

5456
typedef struct __attribute__((__packed__))
@@ -268,6 +270,7 @@ static int np_nand_erase(np_prog_t *prog, uint32_t page)
268270

269271
static int _np_cmd_nand_erase(np_prog_t *prog)
270272
{
273+
int is_bad;
271274
uint32_t addr, page, pages_in_block, len;
272275
np_erase_cmd_t *erase_cmd = (np_erase_cmd_t *)prog->rx_buf;
273276

@@ -283,6 +286,12 @@ static int _np_cmd_nand_erase(np_prog_t *prog)
283286
return NP_ERR_ADDR_NOT_ALIGN;
284287
}
285288

289+
if (!len)
290+
{
291+
ERROR_PRINT("Length is 0\r\n");
292+
return NP_ERR_LEN_INVALID;
293+
}
294+
286295
if (len & (prog->chip_info->block_size - 1))
287296
{
288297
ERROR_PRINT("Length 0x%lx is not aligned to block size 0x%lx\r\n",
@@ -302,13 +311,28 @@ static int _np_cmd_nand_erase(np_prog_t *prog)
302311

303312
while (len)
304313
{
305-
if (np_nand_erase(prog, page))
306-
return NP_ERR_NAND_ERASE;
314+
if (addr >= prog->chip_info->size)
315+
{
316+
ERROR_PRINT("Erase address 0x%lx is more then chip size 0x%lx\r\n",
317+
addr, prog->chip_info->size);
318+
return NP_ERR_ADDR_EXCEEDED;
319+
}
307320

308-
if (len >= prog->chip_info->block_size)
309-
len -= prog->chip_info->block_size;
321+
if ((is_bad = nand_bad_block_table_lookup(addr)))
322+
{
323+
DEBUG_PRINT("Skipped bad block at 0x%lx\r\n", addr);
324+
if (np_send_bad_block_info(addr))
325+
return -1;
326+
}
310327

328+
if (!is_bad && np_nand_erase(prog, page))
329+
return NP_ERR_NAND_ERASE;
330+
331+
addr += prog->chip_info->block_size;
311332
page += pages_in_block;
333+
/* On partial erase do not count bad blocks */
334+
if (!is_bad || (is_bad && erase_cmd->len == prog->chip_info->size))
335+
len -= prog->chip_info->block_size;
312336
}
313337

314338
return np_send_ok_status();
@@ -676,6 +700,7 @@ static int np_cmd_nand_select(np_prog_t *prog)
676700
if (!chip_select(select_cmd->chip_num))
677701
{
678702
nand_init();
703+
nand_bad_block_table_init();
679704
prog->chip_info = chip_info_selected_get();
680705
}
681706
else
@@ -717,6 +742,8 @@ static int np_read_bad_block_info_from_page(np_prog_t *prog, uint32_t block,
717742
*is_bad = true;
718743
if (np_send_bad_block_info(addr))
719744
return -1;
745+
if (nand_bad_block_table_add(addr))
746+
return -1;
720747
}
721748
else
722749
*is_bad = false;

0 commit comments

Comments
 (0)