Skip to content

Commit

Permalink
modify SPINANDBlockDevice.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
rogeryou committed Mar 10, 2022
1 parent f1589ac commit 6866fbf
Showing 1 changed file with 49 additions and 38 deletions.
87 changes: 49 additions & 38 deletions storage/blockdevice/COMPONENT_SPINAND/source/SPINANDBlockDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)

uint8_t status_reg;
if (QSPI_STATUS_OK != _qspi_send_general_command(SPINAND_INST_GET_FEATURE, FEATURES_ADDR_STATUS,
NULL, 0, (char *) &status_reg, 1)) {
NULL, 0, (char *) &status_reg, 1)) {
tr_error("Reading Status Register failed");
read_failed = true;
status = SPINAND_BD_ERROR_DEVICE_ERROR;
Expand All @@ -316,7 +316,7 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
}
} else {
uint8_t ecc_steps = _ecc_steps;
uint8_t *p = (uint8_t*)_page_buf;
uint8_t *p = (uint8_t *)_page_buf;

if (QSPI_STATUS_OK != _qspi_send_read_command(_read_instruction, (void *)_page_buf, addr & SPINAND_PAGE_MASK, _page_size + _oob_size)) {
tr_error("Read Command failed");
Expand All @@ -326,24 +326,23 @@ int SPINANDBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
}

// calculate the software ECC
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
_bch_calculate_ecc(p, _ecc_calc + i);
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
_bch_calculate_ecc(p, _ecc_calc + i);
}

memcpy(_ecc_code, _page_buf + _page_size + _ecc_layout_pos, _ecc_bytes * _ecc_steps);

p = (uint8_t*)_page_buf;
p = (uint8_t *)_page_buf;
ecc_steps = _ecc_steps;
for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
int res = _bch_correct_data(p, _ecc_code + i, _ecc_calc + i);
if (res < 0) {
for (uint8_t i = 0 ; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
int res = _bch_correct_data(p, _ecc_code + i, _ecc_calc + i);
if (res < 0) {
tr_error("Reading data failed");
status = SPINAND_BD_ERROR_DEVICE_ERROR;
read_failed = true;
goto exit_point;
}
}

}
memcpy(buffer, _page_buf + offset, read_bytes);
}

Expand Down Expand Up @@ -410,27 +409,25 @@ int SPINANDBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t si

// prepare data
memset(_page_buf, 0xff, _page_size + _oob_size);
memcpy(_page_buf + offset, (uint8_t*)buffer, written_bytes);
memcpy(_page_buf + offset, (uint8_t *)buffer, written_bytes);

// calculate the software ECC
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
_bch_calculate_ecc(p, _ecc_calc + i);
for (uint8_t i = 0; ecc_steps; ecc_steps--, i += _ecc_bytes, p += _ecc_size) {
_bch_calculate_ecc(p, _ecc_calc + i);
}

// prepare ECC code
memcpy(_page_buf + _page_size + _ecc_layout_pos, _ecc_calc, _ecc_bytes * _ecc_steps);
memcpy(_page_buf + _page_size + _ecc_layout_pos, _ecc_calc, _ecc_bytes * _ecc_steps);

written_bytes = _page_size + _oob_size;
result = _qspi_send_program_command(_program_instruction, (void *)_page_buf, addr & SPINAND_PAGE_MASK, &written_bytes);
if ((result != QSPI_STATUS_OK)) {
if ((result != QSPI_STATUS_OK)) {
tr_error("Write failed");
program_failed = true;
status = SPINAND_BD_ERROR_DEVICE_ERROR;
goto exit_point;
}
}


}

buffer = static_cast<const uint8_t *>(buffer) + chunk;
addr += SPINAND_PAGE_OFFSET;
Expand Down Expand Up @@ -627,7 +624,7 @@ bool SPINANDBlockDevice::_read_otp_onfi()
tr_error("Writing Security Register failed");
return 0;
}
if (QSPI_STATUS_OK != _qspi_send_read_command(SPINAND_INST_READ_CACHE, onfi_table, 1<<_page_shift, sizeof(onfi_table))) {
if (QSPI_STATUS_OK != _qspi_send_read_command(SPINAND_INST_READ_CACHE, onfi_table, 1 << _page_shift, sizeof(onfi_table))) {
tr_error("Writing Security Register failed");
return 0;
}
Expand All @@ -641,13 +638,23 @@ bool SPINANDBlockDevice::_read_otp_onfi()
_block_num = onfi_table[96] + (onfi_table[97] << 8);
_block_size = _page_size * _page_num;
switch (_page_size) {
case 2048 : _page_shift = 12; break;
case 4096 : _page_shift = 13; break;
case 2048 :
_page_shift = 12;
break;
case 4096 :
_page_shift = 13;
break;
}
switch (_page_num) {
case 64 : _block_shift = _page_shift + 6; break;
case 128 : _block_shift = _page_shift + 7; break;
case 256 : _block_shift = _page_shift + 8; break;
case 64 :
_block_shift = _page_shift + 6;
break;
case 128 :
_block_shift = _page_shift + 7;
break;
case 256 :
_block_shift = _page_shift + 8;
break;
}
_flash_size = _block_size * _block_num;
_ecc_bits = onfi_table[112];
Expand All @@ -666,7 +673,7 @@ bool SPINANDBlockDevice::_read_otp_onfi()
return 0;
}
secur_reg &= ~SPINAND_SECURE_BIT_OTP_EN;
_qspi_send_general_command(SPINAND_INST_SET_FEATURE, FEATURES_ADDR_SECURE_OTP,(char *) &secur_reg, 1, NULL, 0);
_qspi_send_general_command(SPINAND_INST_SET_FEATURE, FEATURES_ADDR_SECURE_OTP, (char *) &secur_reg, 1, NULL, 0);
return 1;
}

Expand Down Expand Up @@ -990,38 +997,41 @@ void SPINANDBlockDevice::_bch_init(uint8_t ecc_bits)
t = (eccbytes * 8) / m;

_nbc.bch = init_bch(m, t, 0);
if (!_nbc.bch)
if (!_nbc.bch) {
return;
}

/* verify that eccbytes has the expected value */
if (_nbc.bch->ecc_bytes != eccbytes) {
tr_error("invalid eccbytes %u, should be %u\n",
eccbytes, _nbc.bch->ecc_bytes);
eccbytes, _nbc.bch->ecc_bytes);
return;
}

_page_buf = (uint8_t *)malloc(_page_size + _oob_size);
_ecc_calc = (uint8_t *)malloc(_ecc_steps * _ecc_bytes);
_ecc_code = (uint8_t *)malloc(_ecc_steps * _ecc_bytes);
_nbc.eccmask = (unsigned char*)malloc(eccbytes);
_nbc.errloc = (unsigned int*)malloc(t*sizeof(*_nbc.errloc));
_nbc.eccmask = (unsigned char *)malloc(eccbytes);
_nbc.errloc = (unsigned int *)malloc(t * sizeof(*_nbc.errloc));
if (!_nbc.eccmask || !_nbc.errloc) {
return;
}
/*
* compute and store the inverted ecc of an erased ecc block
*/
erased_page = (unsigned char*)malloc(eccsize);
if (!erased_page)
erased_page = (unsigned char *)malloc(eccsize);
if (!erased_page) {
return;
}
memset(_page_buf, 0xff, _page_size + _oob_size);
memset(erased_page, 0xff, eccsize);
memset(_nbc.eccmask, 0, eccbytes);
encode_bch(_nbc.bch, erased_page, eccsize, _nbc.eccmask);
free(erased_page);

for (i = 0; i < eccbytes; i++)
for (i = 0; i < eccbytes; i++) {
_nbc.eccmask[i] ^= 0xff;
}
}

void SPINANDBlockDevice::_bch_free()
Expand All @@ -1034,7 +1044,7 @@ void SPINANDBlockDevice::_bch_free()
free(_ecc_code);
}

int SPINANDBlockDevice::_bch_calculate_ecc(unsigned char* buf, unsigned char* code)
int SPINANDBlockDevice::_bch_calculate_ecc(unsigned char *buf, unsigned char *code)
{
unsigned int i;

Expand All @@ -1050,21 +1060,22 @@ int SPINANDBlockDevice::_bch_calculate_ecc(unsigned char* buf, unsigned char* co
return 0;
}

int SPINANDBlockDevice::_bch_correct_data(unsigned char* buf, unsigned char* read_ecc, unsigned char* calc_ecc)
int SPINANDBlockDevice::_bch_correct_data(unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc)
{
unsigned int *errloc = _nbc.errloc;
int i, count;

count = decode_bch(_nbc.bch, NULL, _ecc_size, read_ecc, calc_ecc,
NULL, errloc);
NULL, errloc);
if (count > 0) {
for (i = 0; i < count; i++) {
if (errloc[i] < (_ecc_size*8))
if (errloc[i] < (_ecc_size * 8)) {
/* error is located in data, correct it */
buf[(errloc[i] >> 3) ^ 3] ^= (1 << (errloc[i] & 7));
/* else error in ecc, no action needed */
}

tr_error("corrected bitflip %04x:%d\n", (errloc[i]>>3)^3, errloc[i]&7);
/* else error in ecc, no action needed */
tr_error("corrected bitflip %04x:%d\n", (errloc[i] >> 3) ^ 3, errloc[i] & 7);
}
} else if (count < 0) {
tr_error("ecc unrecoverable error\n");
Expand Down

0 comments on commit 6866fbf

Please sign in to comment.