flash.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include PLATFORM_HEADER
00012 #include "error.h"
00013 #include "hal/micro/cortexm3/bootloader/fib-bootloader.h"
00014 #include "hal/micro/cortexm3/mpu.h"
00015 #include "memmap.h"
00016 #include "flash.h"
00017
00018
00019
00020 static const StStatus fibToStStatus[] = {
00021 ST_SUCCESS,
00022 ST_BAD_ARGUMENT,
00023 ST_BAD_ARGUMENT,
00024 ST_BAD_ARGUMENT,
00025 ST_ERR_FLASH_PROG_FAIL,
00026 ST_ERR_FLASH_PROG_FAIL,
00027 ST_ERR_FLASH_WRITE_INHIBITED,
00028 ST_ERR_FLASH_VERIFY_FAILED
00029 };
00030
00031
00032
00033
00034
00035
00036
00037 boolean flashEraseIsActive = FALSE;
00038 boolean halFlashEraseIsActive(void)
00039 {
00040 return flashEraseIsActive;
00041 }
00042
00043
00044
00045
00046
00047 #if defined(ST_EMU_TEST)
00048
00049 static void enableFlitf(void)
00050 {
00051
00052
00053 FPEC_KEY = FPEC_KEY1;
00054 FPEC_KEY = FPEC_KEY2;
00055
00056
00057
00058 OPT_KEY = FPEC_KEY1;
00059 OPT_KEY = FPEC_KEY2;
00060
00061
00062 FPEC_CLKREQ = FPEC_CLKREQ_FIELD;
00063
00064
00065 while( (FPEC_CLKSTAT&FPEC_CLKACK) != FPEC_CLKACK) {}
00066
00067
00068 while( (FLASH_STATUS&FLASH_STATUS_FLA_BSY) == FLASH_STATUS_FLA_BSY ) {}
00069 }
00070
00071 static void disableFlitf(void)
00072 {
00073
00074 while( (FPEC_CLKSTAT&FPEC_CLKBSY) == FPEC_CLKBSY) {}
00075
00076
00077 FPEC_CLKREQ = FPEC_CLKREQ_RESET;
00078
00079
00080
00081
00082 FLASH_CTRL = FLASH_CTRL_LOCK;
00083 }
00084
00085 static FibStatus fibFlashWrite(int32u address, int8u *data, int32u length, int32u dummy)
00086 {
00087 int32u i;
00088 int16u *ptr;
00089 FibStatus status = FIB_SUCCESS;
00090
00091 if ((address & 1) || (length & 1)) {
00092 return FIB_ERR_UNALIGNED;
00093 }
00094
00095 if (!((address >= MFB_BOTTOM && address + length <= MFB_TOP + 1)
00096 || (address >= CIB_BOTTOM && address + length <= CIB_TOP + 1))) {
00097 return FIB_ERR_INVALID_ADDRESS;
00098 }
00099 enableFlitf();
00100 ptr = (int16u *)address;
00101 for (i = 0; i < length; i += 2) {
00102 int16u currentData = *ptr;
00103 int16u newData = HIGH_LOW_TO_INT(data[i + 1], data[i]);
00104
00105 if (currentData == newData) {
00106
00107 } else if (currentData == 0xFFFF || newData == 0x0000) {
00108
00109
00110
00111 if ((CIB_OB_BOTTOM <= (int32u)ptr) && ((int32u)ptr <= CIB_OB_TOP)) {
00112 FLASH_CTRL = (FLASH_CTRL_OPTWREN | FLASH_CTRL_OPTPROG);
00113 } else {
00114 FLASH_CTRL = (FLASH_CTRL_OPTWREN | FLASH_CTRL_PROG);
00115 }
00116
00117 (*ptr) = newData;
00118
00119 while ((FLASH_STATUS & FLASH_STATUS_FLA_BSY) != 0) {}
00120
00121 FLASH_STATUS = FLASH_STATUS_EOP;
00122
00123
00124 if (FLASH_STATUS & (FLASH_STATUS_WRP_ERR | FLASH_STATUS_PROG_ERR)) {
00125 if (FLASH_STATUS & FLASH_STATUS_WRP_ERR) {
00126 status = FIB_ERR_WRITE_PROTECTED;
00127 } else {
00128 status = FIB_ERR_WRITE_FAILED;
00129 }
00130 FLASH_STATUS = FLASH_STATUS_WRP_ERR;
00131 FLASH_STATUS = FLASH_STATUS_PROG_ERR;
00132 break;
00133 }
00134 } else {
00135 status = FIB_ERR_ERASE_REQUIRED;
00136 break;
00137 }
00138 ptr++;
00139 }
00140 disableFlitf();
00141 return status;
00142 }
00143
00144 static FibStatus fibFlashWriteVerify(int32u address, int8u *data, int32u length)
00145 {
00146 int32u i;
00147 int8u *ptr = (int8u *)address;
00148 for (i = 0; i < length; i++) {
00149 if (*ptr != data[i]) {
00150 return FIB_ERR_VERIFY_FAILED;
00151 }
00152 ptr++;
00153 }
00154 return FIB_SUCCESS;
00155 }
00156
00157 static FibStatus fibFlashErase(FibEraseType eraseType, int32u address)
00158 {
00159 int32u eraseOp;
00160 int32u *ptr;
00161 int32u length;
00162 FibStatus status = FIB_SUCCESS;
00163 if (BYTE_0(eraseType) == MFB_MASS_ERASE) {
00164 eraseOp = FLASH_CTRL_MASSERASE;
00165 ptr = (int32u *)MFB_BOTTOM;
00166 length = MFB_SIZE_W;
00167 } else if (BYTE_0(eraseType) == MFB_PAGE_ERASE) {
00168 if (address < MFB_BOTTOM || address > MFB_TOP) {
00169 return FIB_ERR_INVALID_ADDRESS;
00170 }
00171 eraseOp = FLASH_CTRL_PAGEERASE;
00172 ptr = (int32u *)(address & MFB_PAGE_MASK_B);
00173 length = MFB_PAGE_SIZE_W;
00174 } else if (BYTE_0(eraseType) == CIB_ERASE) {
00175 eraseOp = FLASH_CTRL_OPTWREN | FLASH_CTRL_OPTERASE;
00176 ptr = (int32u *)CIB_BOTTOM;
00177 length = CIB_SIZE_W;
00178 } else {
00179 return FIB_ERR_INVALID_TYPE;
00180 }
00181 if ((eraseType & DO_ERASE) != 0) {
00182 enableFlitf();
00183 FLASH_CTRL = eraseOp;
00184 if (BYTE_0(eraseType) == MFB_PAGE_ERASE) {
00185 FLASH_ADDR = (address & MFB_PAGE_MASK_B);
00186 }
00187 eraseOp |= FLASH_CTRL_FLA_START;
00188
00189 FLASH_CTRL = eraseOp;
00190
00191 while ((FLASH_STATUS & FLASH_STATUS_FLA_BSY) != 0) {}
00192
00193 FLASH_STATUS = FLASH_STATUS_EOP;
00194
00195 if (FLASH_STATUS & FLASH_STATUS_WRP_ERR) {
00196 FLASH_STATUS = FLASH_STATUS_WRP_ERR;
00197 status = FIB_ERR_WRITE_PROTECTED;
00198 }
00199 disableFlitf();
00200 }
00201 if (status == FIB_SUCCESS
00202 && (eraseType & DO_VERIFY) != 0) {
00203 int32u i;
00204 for (i = 0; i < length; i++) {
00205 if (*ptr != 0xFFFFFFFF) {
00206 return FIB_ERR_VERIFY_FAILED;
00207 }
00208 ptr++;
00209 }
00210 }
00211 return status;
00212 }
00213 #endif // ST_EMU_TEST
00214
00215 static boolean verifyFib(void)
00216 {
00217
00218 return ( (halFixedAddressTable.baseTable.type == FIXED_ADDRESS_TABLE_TYPE) &&
00219 ( ( (halFixedAddressTable.baseTable.version & FAT_MAJOR_VERSION_MASK)
00220 == 0x0000 ) &&
00221 (halFixedAddressTable.baseTable.version >= 0x0002)
00222 )
00223 );
00224 }
00225
00226
00227
00228 StStatus halInternalFlashErase(int8u eraseType, int32u address)
00229 {
00230 FibStatus status;
00231
00232 ATOMIC(
00233 BYPASS_MPU(
00234 flashEraseIsActive = TRUE;
00235 #if defined(ST_EMU_TEST)
00236
00237 if(verifyFib()) {
00238 status = halFixedAddressTable.fibFlashErase(
00239 (((int32u)eraseType) | DO_ERASE),
00240 address);
00241 } else {
00242 status = fibFlashErase((((int32u)eraseType) | DO_ERASE), address);
00243 }
00244 #else
00245
00246
00247
00248 assert(verifyFib());
00249 status = halFixedAddressTable.fibFlashErase(
00250 (((int32u)eraseType) | DO_ERASE),
00251 address);
00252 #endif
00253 )
00254 )
00255
00256
00257
00258
00259
00260 flashEraseIsActive = FALSE;
00261
00262 if(status!=FIB_SUCCESS) {
00263 return fibToStStatus[status];
00264 }
00265
00266 #if defined(ST_EMU_TEST)
00267
00268 if(verifyFib()) {
00269 status = halFixedAddressTable.fibFlashErase(
00270 (((int32u)eraseType) | DO_VERIFY),
00271 address);
00272 } else {
00273 status = fibFlashErase((((int32u)eraseType) | DO_VERIFY), address);
00274 }
00275 #else
00276 status = halFixedAddressTable.fibFlashErase(
00277 (((int32u)eraseType) | DO_VERIFY),
00278 address);
00279 #endif
00280 return fibToStStatus[status];
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 StStatus halInternalFlashWrite(int32u address, int16u * data, int32u length)
00292 {
00293 FibStatus status;
00294
00295 length = length * 2;
00296
00297 ATOMIC(
00298 BYPASS_MPU(
00299 #if defined(ST_EMU_TEST)
00300
00301 if(verifyFib()) {
00302 status = halFixedAddressTable.fibFlashWrite(address,
00303 (int8u *)data,
00304 length,
00305 0);
00306 } else {
00307 status = fibFlashWrite(address, (int8u *)data, length, 0);
00308 }
00309 #else
00310
00311
00312
00313
00314 assert(verifyFib());
00315 status = halFixedAddressTable.fibFlashWrite(address,
00316 (int8u *)data,
00317 length,
00318 0);
00319 #endif
00320 )
00321 )
00322
00323 if(status!=FIB_SUCCESS) {
00324 return fibToStStatus[status];
00325 }
00326
00327 #if defined(ST_EMU_TEST)
00328
00329 if(verifyFib()) {
00330 status = halFixedAddressTable.fibFlashWrite(address,
00331 (int8u *)data,
00332 0,
00333 length);
00334 } else {
00335 status = fibFlashWriteVerify(address, (int8u *)data, length);
00336 }
00337 #else
00338 status = halFixedAddressTable.fibFlashWrite(address,
00339 (int8u *)data,
00340 0,
00341 length);
00342 #endif
00343
00344 return fibToStStatus[status];
00345 }
00346
00347
00348
00349
00350
00351
00352 StStatus halInternalCibOptionByteWrite(int8u byte, int8u data)
00353 {
00354 int16u dataAndInverse = HIGH_LOW_TO_INT(~data, data);
00355
00356 if (byte > 7) {
00357 return ST_ERR_FLASH_PROG_FAIL;
00358 }
00359 return halInternalFlashWrite(CIB_OB_BOTTOM + (byte << 1), &dataAndInverse, 1);
00360 }
00361
00362