00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "chip.h"
00040
00041 static SmcStatus smcStatus;
00042
00043
00044
00045
00046
00047
00048
00049
00050 static unsigned char CountBitsInByte(unsigned char byte)
00051 {
00052 unsigned char count = 0;
00053 while (byte > 0) {
00054 if (byte & 1) {
00055 count++;
00056 }
00057 byte >>= 1;
00058 }
00059
00060 return count;
00061 }
00062
00063
00064
00065
00066
00067 static unsigned char CountBitsInCode(unsigned char *code)
00068 {
00069 return CountBitsInByte(code[0])
00070 + CountBitsInByte(code[1])
00071 + CountBitsInByte(code[2]);
00072 }
00073
00074
00075
00076
00077 static void SMC_Clear_Status (void)
00078 {
00079 smcStatus.BStatus = 0;
00080 }
00081
00082
00083
00084
00085 static void SMC_Handler(void)
00086 {
00087 uint32_t status;
00088 status = SMC->SMC_SR;
00089 #if 0
00090 if ((status & SMC_SR_SMCSTS) == SMC_SR_SMCSTS)
00091
00092 smcStatus.bStatus.smcSts = 1;
00093 #endif
00094 if ((status & SMC_SR_XFRDONE) == SMC_SR_XFRDONE)
00095
00096
00097 smcStatus.bStatus.xfrDone = 1;
00098 if ((status & SMC_SR_CMDDONE) == SMC_SR_CMDDONE)
00099
00100
00101 smcStatus.bStatus.cmdDone = 1;
00102 if ((status & (1<<24)) == (1<<24))
00103
00104
00105
00106
00107 smcStatus.bStatus.rbEdge = 1;
00108 if ((status & SMC_SR_ECCRDY) == SMC_SR_ECCRDY)
00109
00110
00111
00112 smcStatus.bStatus.hammingReady = 1;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 void SMC_NFC_Configure(uint32_t cfg)
00124 {
00125 SMC->SMC_CFG = cfg;
00126 }
00127
00128
00129
00130
00131 void SMC_NFC_Reset(void)
00132 {
00133
00134 SMC->SMC_IDR = 0xFFFFFFFF;
00135 SMC->SMC_CTRL = 0;
00136 }
00137
00138
00139
00140
00141 void SMC_NFC_EnableNfc(void)
00142 {
00143 SMC->SMC_CTRL |= SMC_CTRL_NFCEN;
00144 }
00145
00146
00147
00148
00149 void SMC_NFC_EnableSpareRead(void)
00150 {
00151 SMC->SMC_CFG |= SMC_CFG_RSPARE;
00152 }
00153
00154
00155
00156
00157 void SMC_NFC_DisableSpareRead(void)
00158 {
00159 SMC->SMC_CFG &= (~SMC_CFG_RSPARE);
00160 }
00161
00162
00163
00164
00165 void SMC_NFC_EnableSpareWrite(void)
00166 {
00167 SMC->SMC_CFG |= SMC_CFG_WSPARE;
00168 }
00169
00170
00171
00172
00173 void SMC_NFC_DisableSpareWrite(void)
00174 {
00175 SMC->SMC_CFG &= (~SMC_CFG_WSPARE);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 uint8_t SMC_NFC_isSpareRead(void)
00185 {
00186 return (((SMC->SMC_CFG) >> 9) & 0x1);
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 uint8_t SMC_NFC_isSpareWrite(void)
00196 {
00197 return (((SMC->SMC_CFG) >> 8) & 0x1);
00198 }
00199
00200
00201
00202
00203
00204
00205 uint8_t SMC_NFC_isTransferComplete(void)
00206 {
00207 return ((SMC->SMC_SR & SMC_SR_XFRDONE) == SMC_SR_XFRDONE);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 uint8_t SMC_NFC_isReadyBusy(void)
00217 {
00218 return ((SMC->SMC_SR & SMC_SR_RB_EDGE0) == SMC_SR_RB_EDGE0);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 uint8_t SMC_NFC_isNfcBusy(void)
00228 {
00229 return ((SMC->SMC_SR & SMC_SR_NFCBUSY) == SMC_SR_NFCBUSY);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239 uint32_t SMC_NFC_GetStatus(void)
00240 {
00241 return SMC->SMC_SR;
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 static uint8_t SMC_NFC_isHostBusy(void)
00253 {
00254 return (((*((volatile uint32_t *) (NFC_CMD_BASE_ADDR + NFCADDR_CMD_NFCCMD)))
00255 & 0x8000000) == 0x8000000);
00256 }
00257
00258
00259
00260
00261 void SMC_NFC_Wait_CommandDone(void)
00262 {
00263 while (smcStatus.bStatus.cmdDone == 0)
00264 {
00265 SMC_Handler();
00266 }
00267 }
00268
00269
00270
00271
00272 void SMC_NFC_Wait_XfrDone(void)
00273 {
00274 while (smcStatus.bStatus.xfrDone == 0)
00275 {
00276 SMC_Handler();
00277 }
00278 }
00279
00280
00281
00282
00283 void SMC_NFC_Wait_HammingReady(void)
00284 {
00285 while (smcStatus.bStatus.hammingReady ==0)
00286 {
00287 SMC_Handler();
00288 }
00289 }
00290
00291
00292
00293
00294 void SMC_NFC_Wait_RBbusy(void)
00295 {
00296 while (smcStatus.bStatus.rbEdge == 0)
00297 {
00298 SMC_Handler();
00299 }
00300 }
00301
00302
00303
00304
00305
00306
00307
00308 void SMC_NFC_SendCommand(uint32_t cmd, uint32_t addressCycle, uint32_t cycle0)
00309 {
00310 volatile uint32_t *pCommandAddress;
00311 SMC_Clear_Status();
00312
00313 while(SMC_NFC_isHostBusy());
00314
00315 pCommandAddress = (volatile uint32_t *) (cmd + NFC_CMD_BASE_ADDR);
00316 SMC->SMC_ADDR = cycle0;
00317 *pCommandAddress = addressCycle;
00318 SMC_NFC_Wait_CommandDone();
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 static void _smc_ecc_GetW9BitPer512Ecc(uint32_t pageDataSize, uint8_t *code)
00332 {
00333 uint8_t i;
00334 uint8_t numEcc;
00335 uint32_t eccParity;
00336 uint32_t ecc[16];
00337
00338 SMC_ECC_GetValue(ecc);
00339 numEcc = pageDataSize / 512;
00340
00341
00342
00343 for (i = 0; i < numEcc; i++) {
00344
00345 eccParity = ecc[i];
00346 eccParity = ~eccParity;
00347 code[i * 3] = eccParity & 0xff;
00348 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00349 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static void _smc_ecc_GetW8BitPer256Ecc(uint32_t pageDataSize, uint8_t *code)
00362 {
00363 uint8_t i;
00364 uint8_t numEcc;
00365 uint32_t eccParity;
00366 uint32_t ecc[16];
00367
00368 SMC_ECC_GetValue(ecc);
00369 numEcc = pageDataSize / 256;
00370
00371
00372
00373
00374 for (i = 0; i < numEcc; i++) {
00375
00376 eccParity = ecc[i];
00377 eccParity = ~eccParity;
00378 TRACE_DEBUG("ecc Parity%d is 0x%08x \n\r", (int)i, (uint32_t)eccParity);
00379 code[i * 3] = eccParity & 0xff;
00380 code[i * 3 + 1] = (eccParity >> 8) & 0xff;
00381 code[i * 3 + 2] = (eccParity >> 16) & 0xff;
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 static void _smc_ecc_GetW12BitPerPageEcc(uint32_t pageDataSize, uint8_t *code)
00394 {
00395 uint32_t eccParity;
00396 uint32_t eccNparity;
00397 uint32_t ecc[16];
00398
00399 pageDataSize = pageDataSize;
00400
00401 SMC_ECC_GetValue(ecc);
00402
00403
00404
00405
00406
00407
00408
00409 eccParity = ecc[0];
00410 eccNparity = ecc[1];
00411 code[0] = eccParity & 0xff;
00412 code[1] = (eccParity >> 8 )& 0xff;
00413 code[2] = eccNparity & 0xff;
00414 code[3] = (eccNparity >> 8 )& 0xff;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423 void SMC_ECC_Configure(uint32_t type, uint32_t pageSize)
00424 {
00425
00426 SMC->SMC_ECC_CTRL = (0x1 << 1) ;
00427 SMC->SMC_ECC_MD = type | pageSize;
00428 }
00429
00430
00431
00432
00433
00434
00435 uint32_t SMC_ECC_GetCorrectoinType(void)
00436 {
00437 return ((SMC->SMC_ECC_MD)& SMC_ECC_MD_TYPCORREC_Msk);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 uint8_t SMC_ECC_GetStatus(uint8_t eccNumber)
00447 {
00448 uint32_t status;
00449
00450 if (eccNumber < 8){
00451 status = SMC->SMC_ECC_SR1;
00452 } else {
00453 status = SMC->SMC_ECC_SR2;
00454 eccNumber -=8;
00455 }
00456 return ((status >> (eccNumber * 4)) & 0x07);
00457 }
00458
00459
00460
00461
00462 void SMC_ECC_GetValue(uint32_t *ecc)
00463 {
00464 ecc[0] = SMC->SMC_ECC_PR0;
00465 ecc[1] = SMC->SMC_ECC_PR1;
00466 ecc[2] = SMC->SMC_ECC_PR2;
00467 ecc[3] = SMC->SMC_ECC_PR3;
00468 ecc[4] = SMC->SMC_ECC_PR4;
00469 ecc[5] = SMC->SMC_ECC_PR5;
00470 ecc[6] = SMC->SMC_ECC_PR6;
00471 ecc[7] = SMC->SMC_ECC_PR7;
00472 ecc[8] = SMC->SMC_ECC_PR8;
00473 ecc[9] = SMC->SMC_ECC_PR9;
00474 ecc[10] = SMC->SMC_ECC_PR10;
00475 ecc[11] = SMC->SMC_ECC_PR11;
00476 ecc[12] = SMC->SMC_ECC_PR12;
00477 ecc[13] = SMC->SMC_ECC_PR13;
00478 ecc[14] = SMC->SMC_ECC_PR14;
00479 ecc[15] = SMC->SMC_ECC_PR15;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 static uint8_t _smc_ecc_VerifyW12BitPerPageEcc(
00494 uint8_t *data,
00495 const uint8_t *originalCode,
00496 const uint8_t *verifyCode)
00497 {
00498 uint8_t correctionCode[4];
00499 uint8_t bitCount;
00500
00501 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00502 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00503 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00504 correctionCode[3] = verifyCode[3] ^ originalCode[3];
00505 TRACE_DEBUG("Correction code = %02X %02X %02X %02X\n\r",
00506 correctionCode[0], correctionCode[1], correctionCode[2], correctionCode[3]);
00507
00508 if ((correctionCode[0] == 0)
00509 && (correctionCode[1] == 0)
00510 && (correctionCode[2] == 0)
00511 && (correctionCode[3] == 0)) {
00512
00513 return 0;
00514 }
00515
00516 bitCount = CountBitsInByte(correctionCode[0]) +
00517 CountBitsInByte(correctionCode[1]) +
00518 CountBitsInByte(correctionCode[2]) +
00519 CountBitsInByte(correctionCode[3]);
00520 if (bitCount == 15) {
00521
00522 uint16_t byte = (correctionCode[0] & 0xf0) >> 4;
00523 byte |= (correctionCode[1] & 0xff) << 4;
00524 uint8_t bit = correctionCode[0] & 0x0f;
00525
00526 printf("Correcting byte #%d at bit %d\n\r", byte, bit);
00527 data[byte] ^= (1 << bit);
00528
00529 return Hsiao_ERROR_SINGLEBIT;
00530 }
00531
00532
00533 if (bitCount == 1) {
00534 return Hsiao_ERROR_ECC;
00535 }
00536
00537 else {
00538 return Hsiao_ERROR_MULTIPLEBITS;
00539 }
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 static uint8_t _smc_ecc_VerifyW8BitPer256Ecc(
00554 uint8_t *data,
00555 uint32_t size,
00556 const uint8_t *originalCode,
00557 const uint8_t *verifyCode)
00558 {
00559 uint8_t correctionCode[3];
00560 uint32_t position = 0;
00561 uint8_t byte;
00562 uint8_t bit;
00563 uint8_t error = 0;
00564
00565 TRACE_DEBUG("_smc_ecc_VerifyW8BitPer256Ecc()\n\r");
00566 while (position < size) {
00567
00568 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00569 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00570 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00571 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00572 correctionCode[0], correctionCode[1], correctionCode[2]);
00573
00574
00575 if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00576
00577 if (CountBitsInCode(correctionCode) == 11) {
00578
00579 byte = (correctionCode[0] & 0xf8) >> 3;
00580 byte |= (correctionCode[1] & 0x07) << 5;
00581 bit = correctionCode[0] & 0x07;
00582
00583 printf("Correcting byte #%u at bit %u\n\r", (unsigned int)(position + byte), (unsigned int)bit);
00584 data[byte] ^= (1 << bit);
00585 error = Hsiao_ERROR_SINGLEBIT;
00586 }
00587
00588 else if (CountBitsInCode(correctionCode) == 1) {
00589 return Hsiao_ERROR_ECC;
00590 } else {
00591
00592 return Hsiao_ERROR_MULTIPLEBITS;
00593 }
00594 }
00595 data += 256;
00596 originalCode += 3;
00597 verifyCode += 3;
00598 position += 256;
00599 }
00600 return error;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static uint8_t _smc_ecc_VerifyW9BitPer512Ecc(
00615 uint8_t *data,
00616 uint32_t size,
00617 const uint8_t *originalCode,
00618 const uint8_t *verifyCode)
00619 {
00620 uint8_t correctionCode[3];
00621 uint32_t position = 0;
00622 uint16_t byte;
00623 uint8_t bit;
00624 uint8_t error = 0;
00625
00626 TRACE_DEBUG("_smc_ecc_VerifyW9BitPer512Ecc()\n\r");
00627 while (position < size) {
00628
00629 correctionCode[0] = verifyCode[0] ^ originalCode[0];
00630 correctionCode[1] = verifyCode[1] ^ originalCode[1];
00631 correctionCode[2] = verifyCode[2] ^ originalCode[2];
00632 TRACE_DEBUG("Correction code = %02X %02X %02X\n\r",
00633 correctionCode[0], correctionCode[1], correctionCode[2]);
00634
00635
00636 if ( correctionCode[0] || correctionCode[1] || correctionCode[2]) {
00637
00638 if (CountBitsInCode(correctionCode) == 12) {
00639
00640 byte = (correctionCode[0] & 0xf8) >> 3;
00641 byte |= (correctionCode[1] & 0x0f) << 5;
00642 bit = correctionCode[0] & 0x07;
00643
00644 printf("Correcting byte #%u at bit %u\n\r",
00645 (unsigned int)(position + byte), (unsigned int)bit);
00646 data[byte] ^= (1 << bit);
00647 error = Hsiao_ERROR_SINGLEBIT;
00648 }
00649
00650 else if (CountBitsInCode(correctionCode) == 1) {
00651 return Hsiao_ERROR_ECC;
00652 } else {
00653
00654 return Hsiao_ERROR_MULTIPLEBITS;
00655 }
00656 }
00657 data += 512;
00658 originalCode += 3;
00659 verifyCode += 3;
00660 position += 512;
00661 }
00662 return error;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 void SMC_ECC_GetEccParity(uint32_t pageDataSize, uint8_t *code, uint8_t busWidth)
00675 {
00676 uint8_t correctionType;
00677
00678 correctionType = SMC_ECC_GetCorrectoinType();
00679
00680 if (busWidth == 16 && correctionType == SMC_ECC_MD_TYPCORREC_CPAGE )
00681 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00682
00683 else {
00684 switch (correctionType){
00685 case SMC_ECC_MD_TYPCORREC_CPAGE:
00686 _smc_ecc_GetW12BitPerPageEcc(pageDataSize, code);
00687 break;
00688 case SMC_ECC_MD_TYPCORREC_C256B:
00689 _smc_ecc_GetW8BitPer256Ecc(pageDataSize, code);
00690 break;
00691 case SMC_ECC_MD_TYPCORREC_C512B:
00692 _smc_ecc_GetW9BitPer512Ecc(pageDataSize, code);
00693 break;
00694 }
00695 }
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 uint8_t SMC_ECC_VerifyHsiao(
00713 uint8_t *data,
00714 uint32_t size,
00715 const uint8_t *originalCode,
00716 const uint8_t *verifyCode,
00717 uint8_t busWidth)
00718 {
00719 uint8_t correctionType;
00720 uint8_t error = 0;
00721 correctionType = SMC_ECC_GetCorrectoinType();
00722
00723 if (busWidth == 16 && (correctionType == SMC_ECC_MD_TYPCORREC_CPAGE) ) {
00724 error = _smc_ecc_VerifyW12BitPerPageEcc((uint8_t*)data, originalCode, verifyCode);
00725 }
00726
00727 else {
00728 switch (correctionType){
00729 case SMC_ECC_MD_TYPCORREC_CPAGE:
00730 error = _smc_ecc_VerifyW12BitPerPageEcc(data, originalCode, verifyCode);
00731 break;
00732 case SMC_ECC_MD_TYPCORREC_C256B:
00733 error = _smc_ecc_VerifyW8BitPer256Ecc(data, size, originalCode, verifyCode);
00734 break;
00735 case SMC_ECC_MD_TYPCORREC_C512B:
00736 error = _smc_ecc_VerifyW9BitPer512Ecc(data, size, originalCode, verifyCode);
00737 break;
00738 }
00739 }
00740 return error;
00741 }