Skip to content

Commit f414fff

Browse files
committed
update BCH code and lic
1 parent 9427c4c commit f414fff

File tree

4 files changed

+316
-1401
lines changed

4 files changed

+316
-1401
lines changed

storage/blockdevice/COMPONENT_SPINAND/include/SPINAND/SPINANDBlockDevice.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "drivers/QSPI.h"
2121
#include "blockdevice/BlockDevice.h"
2222
#include "platform/Callback.h"
23+
#include "bch.h"
2324

2425
#ifndef MBED_CONF_SPINAND_QSPI_IO0
2526
#define MBED_CONF_SPINAND_QSPI_IO0 NC
@@ -356,9 +357,9 @@ class SPINANDBlockDevice : public mbed::BlockDevice {
356357
uint8_t _continuous_read;
357358

358359
struct nand_bch_control {
359-
struct bch_control *bch;
360-
unsigned int *errloc;
361-
unsigned char *eccmask;
360+
struct bch_code *bch;
361+
unsigned int *errloc;
362+
unsigned char *eccmask;
362363
};
363364
struct nand_bch_control _nbc;
364365
};
Lines changed: 22 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,43 @@
1-
/*
2-
* Generic binary BCH encoding/decoding library
3-
*
4-
* This program is free software; you can redistribute it and/or modify it
5-
* under the terms of the GNU General Public License version 2 as published by
6-
* the Free Software Foundation.
7-
*
8-
* This program is distributed in the hope that it will be useful, but WITHOUT
9-
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10-
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11-
* more details.
12-
*
13-
* You should have received a copy of the GNU General Public License along with
14-
* this program; if not, write to the Free Software Foundation, Inc., 51
15-
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16-
*
17-
* Copyright © 2011 Parrot S.A.
18-
*
19-
* Author: Ivan Djelic <ivan.djelic@parrot.com>
20-
*
21-
* Description:
22-
*
23-
* This library provides runtime configurable encoding/decoding of binary
24-
* Bose-Chaudhuri-Hocquenghem (BCH) codes.
25-
*/
26-
/* mbed Microcontroller Library
27-
* Copyright (c) 2022 ARM Limited
1+
/*
2+
* Copyright (c) 2022 Macronix International Co., Ltd.
283
* SPDX-License-Identifier: Apache-2.0
29-
*
30-
* Licensed under the Apache License, Version 2.0 (the "License");
31-
* you may not use this file except in compliance with the License.
32-
* You may obtain a copy of the License at
33-
*
34-
* http://www.apache.org/licenses/LICENSE-2.0
35-
*
36-
* Unless required by applicable law or agreed to in writing, software
37-
* distributed under the License is distributed on an "AS IS" BASIS,
38-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
39-
* See the License for the specific language governing permissions and
40-
* limitations under the License.
414
*/
5+
426
#ifndef _BCH_H
437
#define _BCH_H
448
#ifdef __cplusplus
459
extern "C" {
4610
#endif
4711
#include <stdint.h>
48-
//typedef unsigned char uint8_t;
49-
//typedef unsigned short uint16_t;
50-
//typedef unsigned int uint32_t;
5112

5213
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
53-
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
54-
/**
55-
* struct bch_control - BCH control structure
56-
* @m: Galois field order
57-
* @n: maximum codeword size in bits (= 2^m-1)
58-
* @t: error correction capability in bits
59-
* @ecc_bits: ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
60-
* @ecc_bytes: ecc max size (m*t bits) in bytes
61-
* @a_pow_tab: Galois field GF(2^m) exponentiation lookup table
62-
* @a_log_tab: Galois field GF(2^m) log lookup table
63-
* @mod8_tab: remainder generator polynomial lookup tables
64-
* @ecc_buf: ecc parity words buffer
65-
* @ecc_buf2: ecc parity words buffer
66-
* @xi_tab: GF(2^m) base for solving degree 2 polynomial roots
67-
* @syn: syndrome buffer
68-
* @cache: log-based polynomial representation buffer
69-
* @elp: error locator polynomial
70-
* @poly_2t: temporary polynomials of degree 2t
71-
*/
72-
struct bch_control {
14+
15+
struct bch_code {
7316
unsigned int m;
7417
unsigned int n;
7518
unsigned int t;
7619
unsigned int ecc_bits;
77-
unsigned int ecc_bytes;
78-
/* private: */
79-
uint16_t *a_pow_tab;
80-
uint16_t *a_log_tab;
81-
uint32_t *mod8_tab;
82-
uint32_t *ecc_buf;
83-
uint32_t *ecc_buf2;
84-
unsigned int *xi_tab;
20+
unsigned int ecc_words;
21+
unsigned int len;
22+
unsigned int *a_pow;
23+
unsigned int *a_log;
24+
unsigned int *mod_tab;
25+
unsigned int *ecc;
8526
unsigned int *syn;
86-
int *cache;
87-
struct gf_poly *elp;
88-
struct gf_poly *poly_2t[4];
27+
unsigned int *elp;
28+
unsigned int *buf;
29+
unsigned int *buf2;
30+
unsigned char *input_data;
31+
unsigned int endian;
8932
};
9033

91-
struct bch_control *init_bch(int m, int t, unsigned int prim_poly);
92-
93-
void free_bch(struct bch_control *bch);
94-
95-
void encode_bch(struct bch_control *bch, const uint8_t *data,
96-
unsigned int len, uint8_t *ecc);
97-
98-
int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
99-
const uint8_t *recv_ecc, const uint8_t *calc_ecc,
100-
const unsigned int *syn, unsigned int *errloc);
34+
struct bch_code *bch_init(unsigned int m, unsigned int t);
35+
void bch_free(struct bch_code *bch);
36+
void bch_encode(struct bch_code *bch, unsigned char *data, unsigned int *ecc);
37+
int bch_decode(struct bch_code *bch, unsigned char *data, unsigned int *ecc);
10138
int fls(int x);
102-
#ifdef _X86_
103-
#define cpu_to_be32(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)>>8)&0xff00) | (((x)>>24)&0xff))
104-
#else
105-
#define cpu_to_be32(x) x
106-
#endif
39+
10740
#ifdef __cplusplus
10841
}
10942
#endif
110-
#endif /* _BCH_H */
43+
#endif

storage/blockdevice/COMPONENT_SPINAND/source/SPINANDBlockDevice.cpp

Lines changed: 19 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -343,23 +343,22 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
343343
goto exit_point;
344344
}
345345

346-
// calculate the software ECC
347-
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
348-
_bch_calculate_ecc(p, _ecc_calc + i);
349-
}
350-
351346
memcpy(_ecc_code, _page_buf + _page_size + _ecc_layout_pos, _ecc_bytes * _ecc_steps);
352347

353348
p = (uint8_t *)_page_buf;
354349
ecc_steps = _ecc_steps;
355350
for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
356-
int res = _bch_correct_data(p, _ecc_code + i, _ecc_calc + i);
351+
memset(_nbc.bch->input_data, 0x0, (1 << _nbc.bch->m) / 8);
352+
memcpy(_nbc.bch->input_data + _ecc_bytes, p, _ecc_size);
353+
354+
int res = bch_decode(_nbc.bch, _nbc.bch->input_data, (unsigned int *)(_ecc_code + i));
357355
if (res < 0) {
358356
tr_error("Reading data failed");
359357
status = SPINAND_BD_ERROR_DEVICE_ERROR;
360358
read_failed = true;
361359
goto exit_point;
362360
}
361+
memcpy(p, _nbc.bch->input_data + _ecc_bytes, _ecc_size);
363362
}
364363
memcpy(buffer, _page_buf + offset, read_bytes);
365364
}
@@ -431,7 +430,9 @@ int SPINANDBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t si
431430

432431
// calculate the software ECC
433432
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
434-
_bch_calculate_ecc(p, _ecc_calc + i);
433+
memset(_nbc.bch->input_data, 0x0, (1 << _nbc.bch->m) / 8);
434+
memcpy(_nbc.bch->input_data + _ecc_bytes, p, _ecc_size);
435+
_bch_calculate_ecc(_nbc.bch->input_data, _ecc_calc + i);
435436
}
436437

437438
// prepare ECC code
@@ -1251,26 +1252,26 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
12511252
{
12521253
unsigned int m, t, i;
12531254
unsigned char *erased_page;
1254-
unsigned int eccsize = 512;
1255+
unsigned int eccsize = 410;
12551256
unsigned int eccbytes = 0;
12561257

1257-
_ecc_bytes = eccbytes = DIV_ROUND_UP(ecc_bits * fls(8 * eccsize), 8);
1258+
m = fls(1 + 8 * eccsize);
1259+
t = ecc_bits;
1260+
1261+
_ecc_bytes = eccbytes = ((m * t + 31) / 32) * 4;
12581262
_ecc_size = eccsize;
12591263
_ecc_steps = _page_size / eccsize;
12601264
_ecc_layout_pos = 2; // skip the bad block mark for Macronix spi nand
12611265

1262-
m = fls(1 + 8 * eccsize);
1263-
t = (eccbytes * 8) / m;
1264-
1265-
_nbc.bch = init_bch(m, t, 0);
1266+
_nbc.bch = bch_init(m, t);
12661267
if (!_nbc.bch) {
12671268
return;
12681269
}
12691270

12701271
/* verify that eccbytes has the expected value */
1271-
if (_nbc.bch->ecc_bytes != eccbytes) {
1272+
if (_nbc.bch->ecc_words * 4 != eccbytes) {
12721273
tr_error("invalid eccbytes %u, should be %u\n",
1273-
eccbytes, _nbc.bch->ecc_bytes);
1274+
eccbytes, _nbc.bch->ecc_words);
12741275
return;
12751276
}
12761277

@@ -1292,7 +1293,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
12921293
memset(_page_buf, 0xff, _page_size + _oob_size);
12931294
memset(erased_page, 0xff, eccsize);
12941295
memset(_nbc.eccmask, 0, eccbytes);
1295-
encode_bch(_nbc.bch, erased_page, eccsize, _nbc.eccmask);
1296+
bch_encode(_nbc.bch, erased_page, (unsigned int *)_nbc.eccmask);
12961297
free(erased_page);
12971298

12981299
for (i = 0; i < eccbytes; i++) {
@@ -1302,7 +1303,7 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
13021303

13031304
void SPINANDBlockDevice::_bch_free()
13041305
{
1305-
free_bch(_nbc.bch);
1306+
bch_free(_nbc.bch);
13061307
free(_nbc.errloc);
13071308
free(_nbc.eccmask);
13081309
free(_page_buf);
@@ -1312,42 +1313,11 @@ void SPINANDBlockDevice::_bch_free()
13121313

13131314
int SPINANDBlockDevice::_bch_calculate_ecc(unsigned char *buf, unsigned char *code)
13141315
{
1315-
unsigned int i;
13161316

13171317
memset(code, 0, _ecc_bytes);
13181318

1319-
encode_bch(_nbc.bch, buf, _ecc_size, code);
1320-
1321-
/* apply mask so that an erased page is a valid codeword */
1322-
for (i = 0; i < _ecc_bytes; i++) {
1323-
code[i] ^= _nbc.eccmask[i];
1324-
}
1319+
bch_encode(_nbc.bch, buf, (unsigned int *)code);
13251320

13261321
return 0;
13271322
}
13281323

1329-
int SPINANDBlockDevice::_bch_correct_data(unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc)
1330-
{
1331-
unsigned int *errloc = _nbc.errloc;
1332-
int i, count;
1333-
1334-
count = decode_bch(_nbc.bch, NULL, _ecc_size, read_ecc, calc_ecc,
1335-
NULL, errloc);
1336-
if (count > 0) {
1337-
for (i = 0; i < count; i++) {
1338-
if (errloc[i] < (_ecc_size * 8)) {
1339-
/* error is located in data, correct it */
1340-
buf[(errloc[i] >> 3) ^ 3] ^= (1 << (errloc[i] & 7));
1341-
}
1342-
1343-
/* else error in ecc, no action needed */
1344-
tr_error("corrected bitflip %04x:%d\n", (errloc[i] >> 3) ^ 3, errloc[i] & 7);
1345-
}
1346-
} else if (count < 0) {
1347-
tr_error("ecc unrecoverable error\n");
1348-
count = -EBADMSG;
1349-
}
1350-
return count;
1351-
}
1352-
1353-

0 commit comments

Comments
 (0)