Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
m480_fmc.c
00001 /**************************************************************************//** 00002 * @file fmc.c 00003 * @version V1.00 00004 * @brief M480 series FMC driver source file 00005 * 00006 * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without modification, 00009 * are permitted provided that the following conditions are met: 00010 * 1. Redistributions of source code must retain the above copyright notice, 00011 * this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright notice, 00013 * this list of conditions and the following disclaimer in the documentation 00014 * and/or other materials provided with the distribution. 00015 * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00024 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00026 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00027 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00028 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 *****************************************************************************/ 00030 00031 #include <stdio.h> 00032 00033 #include "NuMicro.h" 00034 00035 00036 /** @addtogroup Standard_Driver Standard Driver 00037 @{ 00038 */ 00039 00040 /** @addtogroup FMC_Driver FMC Driver 00041 @{ 00042 */ 00043 00044 00045 /** @addtogroup FMC_EXPORTED_FUNCTIONS FMC Exported Functions 00046 @{ 00047 */ 00048 00049 00050 /** 00051 * @brief Disable FMC ISP function. 00052 * @return None 00053 */ 00054 void FMC_Close(void) 00055 { 00056 FMC->ISPCTL &= ~FMC_ISPCTL_ISPEN_Msk; 00057 } 00058 00059 00060 /** 00061 * @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase a flash page. The page size is 4096 bytes. 00062 * @param[in] u32PageAddr Address of the flash page to be erased. 00063 * It must be a 4096 bytes aligned address. 00064 * @return ISP page erase success or not. 00065 * @retval 0 Success 00066 * @retval -1 Erase failed 00067 */ 00068 int32_t FMC_Erase(uint32_t u32PageAddr) 00069 { 00070 int32_t ret = 0; 00071 00072 if (u32PageAddr == FMC_SPROM_BASE) { 00073 ret = FMC_Erase_SPROM(); 00074 } 00075 00076 if (ret == 0) { 00077 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; 00078 FMC->ISPADDR = u32PageAddr; 00079 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00080 00081 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00082 00083 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) { 00084 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; 00085 ret = -1; 00086 } 00087 } 00088 00089 return ret; 00090 } 00091 00092 00093 /** 00094 * @brief Execute FMC_ISPCMD_PAGE_ERASE command to erase SPROM. The page size is 4096 bytes. 00095 * @return SPROM page erase success or not. 00096 * @retval 0 Success 00097 * @retval -1 Erase failed 00098 */ 00099 int32_t FMC_Erase_SPROM(void) 00100 { 00101 int32_t ret = 0; 00102 FMC->ISPCMD = FMC_ISPCMD_PAGE_ERASE; 00103 FMC->ISPADDR = FMC_SPROM_BASE; 00104 FMC->ISPDAT = 0x0055AA03UL; 00105 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00106 00107 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00108 00109 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) { 00110 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; 00111 ret = -1; 00112 } 00113 00114 return ret; 00115 } 00116 00117 /** 00118 * @brief Execute FMC_ISPCMD_BLOCK_ERASE command to erase a flash block. The block size is 4 pages. 00119 * @param[in] u32BlockAddr Address of the flash block to be erased. 00120 * It must be a 4 pages aligned address. 00121 * @return ISP page erase success or not. 00122 * @retval 0 Success 00123 * @retval -1 Erase failed 00124 */ 00125 int32_t FMC_Erase_Block(uint32_t u32BlockAddr) 00126 { 00127 int32_t ret = 0; 00128 FMC->ISPCMD = FMC_ISPCMD_BLOCK_ERASE; 00129 FMC->ISPADDR = u32BlockAddr; 00130 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00131 00132 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00133 00134 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) { 00135 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; 00136 ret = -1; 00137 } 00138 00139 return ret; 00140 } 00141 00142 /** 00143 * @brief Execute FMC_ISPCMD_BANK_ERASE command to erase a flash block. 00144 * @param[in] u32BankAddr Base address of the flash bank to be erased. 00145 * @return ISP page erase success or not. 00146 * @retval 0 Success 00147 * @retval -1 Erase failed 00148 */ 00149 int32_t FMC_Erase_Bank(uint32_t u32BankAddr) 00150 { 00151 int32_t ret = 0; 00152 FMC->ISPCMD = FMC_ISPCMD_BANK_ERASE; 00153 FMC->ISPADDR = u32BankAddr; 00154 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00155 00156 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00157 00158 if (FMC->ISPCTL & FMC_ISPCTL_ISPFF_Msk) { 00159 FMC->ISPCTL |= FMC_ISPCTL_ISPFF_Msk; 00160 ret = -1; 00161 } 00162 00163 return ret; 00164 } 00165 00166 /** 00167 * @brief Get the current boot source. 00168 * @return The current boot source. 00169 * @retval 0 Is boot from APROM. 00170 * @retval 1 Is boot from LDROM. 00171 */ 00172 int32_t FMC_GetBootSource(void) 00173 { 00174 int32_t ret = 0; 00175 00176 if (FMC->ISPCTL & FMC_ISPCTL_BS_Msk) { 00177 ret = 1; 00178 } 00179 00180 return ret; 00181 } 00182 00183 00184 /** 00185 * @brief Enable FMC ISP function 00186 * @return None 00187 */ 00188 void FMC_Open(void) 00189 { 00190 FMC->ISPCTL |= FMC_ISPCTL_ISPEN_Msk; 00191 } 00192 00193 00194 /** 00195 * @brief Execute FMC_ISPCMD_READ command to read a word from flash. 00196 * @param[in] u32Addr Address of the flash location to be read. 00197 * It must be a word aligned address. 00198 * @return The word data read from specified flash address. 00199 */ 00200 uint32_t FMC_Read(uint32_t u32Addr) 00201 { 00202 FMC->ISPCMD = FMC_ISPCMD_READ; 00203 FMC->ISPADDR = u32Addr; 00204 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00205 00206 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00207 00208 return FMC->ISPDAT; 00209 } 00210 00211 00212 /** 00213 * @brief Execute FMC_ISPCMD_READ_64 command to read a double-word from flash. 00214 * @param[in] u32addr Address of the flash location to be read. 00215 * It must be a double-word aligned address. 00216 * @param[out] u32data0 Place holder of word 0 read from flash address u32addr. 00217 * @param[out] u32data1 Place holder of word 0 read from flash address u32addr+4. 00218 * @return 0 Success 00219 * @return -1 Failed 00220 */ 00221 int32_t FMC_Read_64(uint32_t u32addr, uint32_t *u32data0, uint32_t *u32data1) 00222 { 00223 int32_t ret = 0; 00224 FMC->ISPCMD = FMC_ISPCMD_READ_64; 00225 FMC->ISPADDR = u32addr; 00226 FMC->ISPDAT = 0x0UL; 00227 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00228 00229 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00230 00231 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00232 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00233 ret = -1; 00234 } else { 00235 *u32data0 = FMC->MPDAT0; 00236 *u32data1 = FMC->MPDAT1; 00237 } 00238 00239 return ret; 00240 } 00241 00242 00243 /** 00244 * @brief Get the base address of Data Flash if enabled. 00245 * @retval The base address of Data Flash 00246 */ 00247 uint32_t FMC_ReadDataFlashBaseAddr(void) 00248 { 00249 return FMC->DFBA; 00250 } 00251 00252 /** 00253 * @brief Set boot source from LDROM or APROM after next software reset 00254 * @param[in] i32BootSrc 00255 * 1: Boot from LDROM 00256 * 0: Boot from APROM 00257 * @return None 00258 * @details This function is used to switch APROM boot or LDROM boot. User need to call 00259 * FMC_SetBootSource to select boot source first, then use CPU reset or 00260 * System Reset Request to reset system. 00261 */ 00262 void FMC_SetBootSource(int32_t i32BootSrc) 00263 { 00264 if (i32BootSrc) { 00265 FMC->ISPCTL |= FMC_ISPCTL_BS_Msk; /* Boot from LDROM */ 00266 } else { 00267 FMC->ISPCTL &= ~FMC_ISPCTL_BS_Msk;/* Boot from APROM */ 00268 } 00269 } 00270 00271 /** 00272 * @brief Execute ISP FMC_ISPCMD_PROGRAM to program a word to flash. 00273 * @param[in] u32Addr Address of the flash location to be programmed. 00274 * It must be a word aligned address. 00275 * @param[in] u32Data The word data to be programmed. 00276 * @return None 00277 */ 00278 void FMC_Write(uint32_t u32Addr, uint32_t u32Data) 00279 { 00280 FMC->ISPCMD = FMC_ISPCMD_PROGRAM; 00281 FMC->ISPADDR = u32Addr; 00282 FMC->ISPDAT = u32Data; 00283 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00284 00285 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00286 } 00287 00288 /** 00289 * @brief Execute ISP FMC_ISPCMD_PROGRAM_64 to program a double-word to flash. 00290 * @param[in] u32addr Address of the flash location to be programmed. 00291 * It must be a double-word aligned address. 00292 * @param[in] u32data0 The word data to be programmed to flash address u32addr. 00293 * @param[in] u32data1 The word data to be programmed to flash address u32addr+4. 00294 * @return 0 Success 00295 * @return -1 Failed 00296 */ 00297 int32_t FMC_Write8Bytes(uint32_t u32addr, uint32_t u32data0, uint32_t u32data1) 00298 { 00299 int32_t ret = 0; 00300 FMC->ISPCMD = FMC_ISPCMD_PROGRAM_64; 00301 FMC->ISPADDR = u32addr; 00302 FMC->MPDAT0 = u32data0; 00303 FMC->MPDAT1 = u32data1; 00304 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00305 00306 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00307 00308 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00309 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00310 ret = -1; 00311 } 00312 00313 return ret; 00314 } 00315 00316 00317 /** 00318 * @brief Program Multi-Word data into specified address of flash. 00319 * @param[in] u32Addr Start flash address in APROM where the data chunk to be programmed into. 00320 * This address must be 8-bytes aligned to flash address. 00321 * @param[in] pu32Buf Buffer that carry the data chunk. 00322 * @param[in] u32Len Length of the data chunk in bytes. 00323 * @retval >=0 Number of data bytes were programmed. 00324 * @return -1 Invalid address. 00325 */ 00326 int32_t FMC_WriteMultiple(uint32_t u32Addr, uint32_t pu32Buf[], uint32_t u32Len) 00327 { 00328 int i, idx, retval = 0; 00329 00330 if ((u32Addr >= FMC_APROM_END) || ((u32Addr % 8) != 0)) { 00331 return -1; 00332 } 00333 00334 u32Len = u32Len - (u32Len % 8); /* u32Len must be multiple of 8. */ 00335 idx = 0; 00336 00337 while (u32Len >= 8) { 00338 FMC->ISPADDR = u32Addr; 00339 FMC->MPDAT0 = pu32Buf[idx++]; 00340 FMC->MPDAT1 = pu32Buf[idx++]; 00341 FMC->MPDAT2 = pu32Buf[idx++]; 00342 FMC->MPDAT3 = pu32Buf[idx++]; 00343 FMC->ISPCMD = FMC_ISPCMD_PROGRAM_MUL; 00344 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00345 00346 for (i = 16; i < FMC_MULTI_WORD_PROG_LEN;) { 00347 while (FMC->MPSTS & (FMC_MPSTS_D0_Msk | FMC_MPSTS_D1_Msk)) 00348 ; 00349 00350 retval += 8; 00351 u32Len -= 8; 00352 00353 if (u32Len < 8) { 00354 return retval; 00355 } 00356 00357 if (!(FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) { 00358 /* printf(" [WARNING] busy cleared after D0D1 cleared!\n"); */ 00359 i += 8; 00360 break; 00361 } 00362 00363 FMC->MPDAT0 = pu32Buf[idx++]; 00364 FMC->MPDAT1 = pu32Buf[idx++]; 00365 00366 if (i == FMC_MULTI_WORD_PROG_LEN / 4) { 00367 break; // done 00368 } 00369 00370 while (FMC->MPSTS & (FMC_MPSTS_D2_Msk | FMC_MPSTS_D3_Msk)) 00371 ; 00372 00373 retval += 8; 00374 u32Len -= 8; 00375 00376 if (u32Len < 8) { 00377 return retval; 00378 } 00379 00380 if (!(FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk)) { 00381 /* printf(" [WARNING] busy cleared after D2D3 cleared!\n"); */ 00382 i += 8; 00383 break; 00384 } 00385 00386 FMC->MPDAT2 = pu32Buf[idx++]; 00387 FMC->MPDAT3 = pu32Buf[idx++]; 00388 } 00389 00390 if (i != FMC_MULTI_WORD_PROG_LEN) { 00391 /* printf(" [WARNING] Multi-word program interrupted at 0x%x !!\n", i); */ 00392 return retval; 00393 } 00394 00395 while (FMC->MPSTS & FMC_MPSTS_MPBUSY_Msk) ; 00396 00397 u32Addr += FMC_MULTI_WORD_PROG_LEN; 00398 } 00399 00400 return retval; 00401 } 00402 00403 00404 /** 00405 * @brief Program a 64-bits data to the specified OTP. 00406 * @param[in] otp_num The OTP number. 00407 * @param[in] low_word Low word of the 64-bits data. 00408 * @param[in] high_word Low word of the 64-bits data. 00409 * @retval 0 Success 00410 * @retval -1 Program failed. 00411 * @retval -2 Invalid OTP number. 00412 */ 00413 int32_t FMC_Write_OTP(uint32_t otp_num, uint32_t low_word, uint32_t high_word) 00414 { 00415 int32_t ret = 0; 00416 00417 if (otp_num > 255UL) { 00418 ret = -2; 00419 } 00420 00421 if (ret == 0) { 00422 FMC->ISPCMD = FMC_ISPCMD_PROGRAM; 00423 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL; 00424 FMC->ISPDAT = low_word; 00425 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00426 00427 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00428 00429 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00430 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00431 ret = -1; 00432 } 00433 } 00434 00435 if (ret == 0) { 00436 FMC->ISPCMD = FMC_ISPCMD_PROGRAM; 00437 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL + 4UL; 00438 FMC->ISPDAT = high_word; 00439 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00440 00441 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00442 00443 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00444 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00445 ret = -1; 00446 } 00447 } 00448 00449 return ret; 00450 } 00451 00452 /** 00453 * @brief Read the 64-bits data from the specified OTP. 00454 * @param[in] otp_num The OTP number. 00455 * @param[in] low_word Low word of the 64-bits data. 00456 * @param[in] high_word Low word of the 64-bits data. 00457 * @retval 0 Success 00458 * @retval -1 Read failed. 00459 * @retval -2 Invalid OTP number. 00460 */ 00461 int32_t FMC_Read_OTP(uint32_t otp_num, uint32_t *low_word, uint32_t *high_word) 00462 { 00463 int32_t ret = 0; 00464 00465 if (otp_num > 255UL) { 00466 ret = -2; 00467 } 00468 00469 if (ret == 0) { 00470 FMC->ISPCMD = FMC_ISPCMD_READ_64; 00471 FMC->ISPADDR = FMC_OTP_BASE + otp_num * 8UL ; 00472 FMC->ISPDAT = 0x0UL; 00473 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00474 00475 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00476 00477 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00478 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00479 ret = -1; 00480 } else { 00481 *low_word = FMC->MPDAT0; 00482 *high_word = FMC->MPDAT1; 00483 } 00484 } 00485 00486 return ret; 00487 } 00488 00489 /** 00490 * @brief Lock the specified OTP. 00491 * @param[in] otp_num The OTP number. 00492 * @retval 0 Success 00493 * @retval -1 Failed to write OTP lock bits. 00494 * @retval -2 Invalid OTP number. 00495 */ 00496 int32_t FMC_Lock_OTP(uint32_t otp_num) 00497 { 00498 int32_t ret = 0; 00499 00500 if (otp_num > 255UL) { 00501 ret = -2; 00502 } 00503 00504 if (ret == 0) { 00505 FMC->ISPCMD = FMC_ISPCMD_PROGRAM; 00506 FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL; 00507 FMC->ISPDAT = 0UL; 00508 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00509 00510 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00511 00512 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00513 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00514 ret = -1; 00515 } 00516 } 00517 00518 return ret; 00519 } 00520 00521 /** 00522 * @brief Check the OTP is locked or not. 00523 * @param[in] otp_num The OTP number. 00524 * @retval 1 OTP is locked. 00525 * @retval 0 OTP is not locked. 00526 * @retval -1 Failed to read OTP lock bits. 00527 * @retval -2 Invalid OTP number. 00528 */ 00529 int32_t FMC_Is_OTP_Locked(uint32_t otp_num) 00530 { 00531 int32_t ret = 0; 00532 00533 if (otp_num > 255UL) { 00534 ret = -2; 00535 } 00536 00537 if (ret == 0) { 00538 FMC->ISPCMD = FMC_ISPCMD_READ; 00539 FMC->ISPADDR = FMC_OTP_BASE + 0x800UL + otp_num * 4UL; 00540 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00541 00542 while (FMC->ISPTRG & FMC_ISPTRG_ISPGO_Msk) { } 00543 00544 if (FMC->ISPSTS & FMC_ISPSTS_ISPFF_Msk) { 00545 FMC->ISPSTS |= FMC_ISPSTS_ISPFF_Msk; 00546 ret = -1; 00547 } else { 00548 if (FMC->ISPDAT != 0xFFFFFFFFUL) { 00549 ret = 1; /* Lock work was progrmmed. OTP was locked. */ 00550 } 00551 } 00552 } 00553 00554 return ret; 00555 } 00556 00557 /** 00558 * @brief Execute FMC_ISPCMD_READ command to read User Configuration. 00559 * @param[out] u32Config A two-word array. 00560 * u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1. 00561 * @param[in] u32Count Available word count in u32Config. 00562 * @return Success or not. 00563 * @retval 0 Success. 00564 * @retval -1 Invalid parameter. 00565 */ 00566 int32_t FMC_ReadConfig(uint32_t u32Config[], uint32_t u32Count) 00567 { 00568 int32_t ret = 0; 00569 u32Config[0] = FMC_Read(FMC_CONFIG_BASE); 00570 00571 if (u32Count < 2UL) { 00572 ret = -1; 00573 } else { 00574 u32Config[1] = FMC_Read(FMC_CONFIG_BASE + 4UL); 00575 } 00576 00577 return ret; 00578 } 00579 00580 00581 /** 00582 * @brief Execute ISP commands to erase then write User Configuration. 00583 * @param[in] u32Config A two-word array. 00584 * u32Config[0] holds CONFIG0, while u32Config[1] holds CONFIG1. 00585 * @param[in] u32Count Always be 2 in this BSP. 00586 * @return Success or not. 00587 * @retval 0 Success. 00588 * @retval -1 Invalid parameter. 00589 */ 00590 int32_t FMC_WriteConfig(uint32_t u32Config[], uint32_t u32Count) 00591 { 00592 FMC_ENABLE_CFG_UPDATE(); 00593 FMC_Erase(FMC_CONFIG_BASE); 00594 FMC_Write(FMC_CONFIG_BASE, u32Config[0]); 00595 FMC_Write(FMC_CONFIG_BASE + 4UL, u32Config[1]); 00596 FMC_DISABLE_CFG_UPDATE(); 00597 return 0; 00598 } 00599 00600 00601 /** 00602 * @brief Run CRC32 checksum calculation and get result. 00603 * @param[in] u32addr Starting flash address. It must be a page aligned address. 00604 * @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes. 00605 * @return Success or not. 00606 * @retval 0 Success. 00607 * @retval 0xFFFFFFFF Invalid parameter. 00608 */ 00609 uint32_t FMC_GetChkSum(uint32_t u32addr, uint32_t u32count) 00610 { 00611 uint32_t ret; 00612 00613 if ((u32addr % 512UL) || (u32count % 512UL)) { 00614 ret = 0xFFFFFFFF; 00615 } else { 00616 FMC->ISPCMD = FMC_ISPCMD_RUN_CKS; 00617 FMC->ISPADDR = u32addr; 00618 FMC->ISPDAT = u32count; 00619 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00620 00621 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00622 00623 FMC->ISPCMD = FMC_ISPCMD_READ_CKS; 00624 FMC->ISPADDR = u32addr; 00625 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00626 00627 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00628 00629 ret = FMC->ISPDAT; 00630 } 00631 00632 return ret; 00633 } 00634 00635 00636 /** 00637 * @brief Run flash all one verification and get result. 00638 * @param[in] u32addr Starting flash address. It must be a page aligned address. 00639 * @param[in] u32count Byte count of flash to be calculated. It must be multiple of 512 bytes. 00640 * @retval READ_ALLONE_YES The contents of verified flash area are 0xFFFFFFFF. 00641 * @retval READ_ALLONE_NOT Some contents of verified flash area are not 0xFFFFFFFF. 00642 * @retval READ_ALLONE_CMD_FAIL Unexpected error occurred. 00643 */ 00644 uint32_t FMC_CheckAllOne(uint32_t u32addr, uint32_t u32count) 00645 { 00646 uint32_t ret = READ_ALLONE_CMD_FAIL; 00647 FMC->ISPSTS = 0x80UL; /* clear check all one bit */ 00648 FMC->ISPCMD = FMC_ISPCMD_RUN_ALL1; 00649 FMC->ISPADDR = u32addr; 00650 FMC->ISPDAT = u32count; 00651 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00652 00653 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00654 00655 do { 00656 FMC->ISPCMD = FMC_ISPCMD_READ_ALL1; 00657 FMC->ISPADDR = u32addr; 00658 FMC->ISPTRG = FMC_ISPTRG_ISPGO_Msk; 00659 00660 while (FMC->ISPSTS & FMC_ISPSTS_ISPBUSY_Msk) { } 00661 } while (FMC->ISPDAT == 0UL); 00662 00663 if (FMC->ISPDAT == READ_ALLONE_YES) { 00664 ret = FMC->ISPDAT; 00665 } 00666 00667 if (FMC->ISPDAT == READ_ALLONE_NOT) { 00668 ret = FMC->ISPDAT; 00669 } 00670 00671 return ret; 00672 } 00673 00674 00675 /** 00676 * @brief Setup security key. 00677 * @param[in] key Key 0~2 to be setup. 00678 * @param[in] kpmax Maximum unmatched power-on counting number. 00679 * @param[in] kemax Maximum unmatched counting number. 00680 * @param[in] lock_CONFIG 1: Security key lock CONFIG to write-protect. 0: Don't lock CONFIG. 00681 * @param[in] lock_SPROM 1: Security key lock SPROM to write-protect. 0: Don't lock SPROM. 00682 * @retval 0 Success. 00683 * @retval -1 Key is locked. Cannot overwrite the current key. 00684 * @retval -2 Failed to erase flash. 00685 * @retval -3 Failed to program key. 00686 * @retval -4 Key lock function failed. 00687 * @retval -5 CONFIG lock function failed. 00688 * @retval -6 SPROM lock function failed. 00689 * @retval -7 KPMAX function failed. 00690 * @retval -8 KEMAX function failed. 00691 */ 00692 int32_t FMC_SetSPKey(uint32_t key[3], uint32_t kpmax, uint32_t kemax, 00693 const int32_t lock_CONFIG, const int32_t lock_SPROM) 00694 { 00695 uint32_t lock_ctrl = 0UL; 00696 uint32_t u32KeySts; 00697 int32_t ret = 0; 00698 00699 if (FMC->KPKEYSTS != 0x200UL) { 00700 ret = -1; 00701 } 00702 00703 if (FMC_Erase(FMC_KPROM_BASE)) { 00704 ret = -2; 00705 } 00706 00707 if (FMC_Erase(FMC_KPROM_BASE + 0x200UL)) { 00708 ret = -3; 00709 } 00710 00711 if (!lock_CONFIG) { 00712 lock_ctrl |= 0x1UL; 00713 } 00714 00715 if (!lock_SPROM) { 00716 lock_ctrl |= 0x2UL; 00717 } 00718 00719 if (ret == 0) { 00720 FMC_Write(FMC_KPROM_BASE, key[0]); 00721 FMC_Write(FMC_KPROM_BASE + 0x4UL, key[1]); 00722 FMC_Write(FMC_KPROM_BASE + 0x8UL, key[2]); 00723 FMC_Write(FMC_KPROM_BASE + 0xCUL, kpmax); 00724 FMC_Write(FMC_KPROM_BASE + 0x10UL, kemax); 00725 FMC_Write(FMC_KPROM_BASE + 0x14UL, lock_ctrl); 00726 00727 while (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk) { } 00728 00729 u32KeySts = FMC->KPKEYSTS; 00730 00731 if (!(u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk)) { 00732 /* Security key lock failed! */ 00733 ret = -4; 00734 } else if ((lock_CONFIG && (!(u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk))) || 00735 ((!lock_CONFIG) && (u32KeySts & FMC_KPKEYSTS_CFGFLAG_Msk))) { 00736 /* CONFIG lock failed! */ 00737 ret = -5; 00738 } else if ((lock_SPROM && (!(u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk))) || 00739 ((!lock_SPROM) && (u32KeySts & FMC_KPKEYSTS_SPFLAG_Msk))) { 00740 /* CONFIG lock failed! */ 00741 ret = -6; 00742 } else if (((FMC->KPCNT & FMC_KPCNT_KPMAX_Msk) >> FMC_KPCNT_KPMAX_Pos) != kpmax) { 00743 /* KPMAX failed! */ 00744 ret = -7; 00745 } else if (((FMC->KPKEYCNT & FMC_KPKEYCNT_KPKEMAX_Msk) >> FMC_KPKEYCNT_KPKEMAX_Pos) != kemax) { 00746 /* KEMAX failed! */ 00747 ret = -8; 00748 } 00749 } 00750 00751 return ret; 00752 } 00753 00754 00755 /** 00756 * @brief Execute security key comparison. 00757 * @param[in] key Key 0~2 to be compared. 00758 * @retval 0 Key matched. 00759 * @retval -1 Forbidden. Times of key comparison mismatch reach the maximum count. 00760 * @retval -2 Key mismatched. 00761 * @retval -3 No security key lock. Key comparison is not required. 00762 */ 00763 int32_t FMC_CompareSPKey(uint32_t key[3]) 00764 { 00765 uint32_t u32KeySts; 00766 int32_t ret = 0; 00767 00768 if (FMC->KPKEYSTS & FMC_KPKEYSTS_FORBID_Msk) { 00769 /* FMC_CompareSPKey - FORBID! */ 00770 ret = -1; 00771 } 00772 00773 if (!(FMC->KPKEYSTS & FMC_KPKEYSTS_KEYLOCK_Msk)) { 00774 /* FMC_CompareSPKey - key is not locked! */ 00775 ret = -3; 00776 } 00777 00778 if (ret == 0) { 00779 FMC->KPKEY0 = key[0]; 00780 FMC->KPKEY1 = key[1]; 00781 FMC->KPKEY2 = key[2]; 00782 FMC->KPKEYTRG = FMC_KPKEYTRG_KPKEYGO_Msk | FMC_KPKEYTRG_TCEN_Msk; 00783 00784 while (FMC->KPKEYSTS & FMC_KPKEYSTS_KEYBUSY_Msk) { } 00785 00786 u32KeySts = FMC->KPKEYSTS; 00787 00788 if (!(u32KeySts & FMC_KPKEYSTS_KEYMATCH_Msk)) { 00789 /* Key mismatched! */ 00790 ret = -2; 00791 } else if (u32KeySts & FMC_KPKEYSTS_KEYLOCK_Msk) { 00792 /* Key matched, but still be locked! */ 00793 ret = -2; 00794 } 00795 } 00796 00797 return ret; 00798 } 00799 00800 00801 /*@}*/ /* end of group FMC_EXPORTED_FUNCTIONS */ 00802 00803 /*@}*/ /* end of group FMC_Driver */ 00804 00805 /*@}*/ /* end of group Standard_Driver */ 00806 00807 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ 00808 00809
Generated on Tue Jul 12 2022 15:37:20 by
