Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
pal_internalFlash.c
00001 /******************************************************************************* 00002 * Copyright 2016, 2017 ARM Ltd. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 *******************************************************************************/ 00016 #include "pal.h" 00017 #include "pal_plat_internalFlash.h" 00018 #include "stdio.h" 00019 00020 #if (PAL_USE_INTERNAL_FLASH) 00021 00022 #define BITS_ALIGNED_TO_32 0x3 00023 #define PAL_MAX_PAGE_SIZE 16 00024 00025 //////////////////////////GLOBALS SECTION //////////////////////////// 00026 #if PAL_THREAD_SAFETY 00027 // Use semaphore and not mutex, as mutexes don't behave well when trying to delete them while taken (which may happen in our tests). 00028 static palSemaphoreID_t flashSem = NULLPTR; 00029 #endif 00030 00031 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00032 PAL_PRIVATE palFileDescriptor_t g_fd = 0; 00033 #endif 00034 //////////////////////////END GLOBALS SECTION //////////////////////////// 00035 00036 00037 //////////////////////////START PRIVATE SECTION//////////////////////////// 00038 // Verify that the alignment to sector size 00039 // Parameters : 00040 // @param[in] address - Address to verify. 00041 // @param[in] size - Size to write 00042 // Return : None. 00043 PAL_PRIVATE bool pal_isAlignedToSector(uint32_t address, size_t size) 00044 { 00045 uint32_t currentSectorSize = pal_internalFlashGetSectorSize(address); 00046 if ((size % currentSectorSize) || (address % currentSectorSize)) 00047 { 00048 return false; 00049 } 00050 else 00051 { 00052 return true; 00053 } 00054 } 00055 00056 00057 00058 #if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00059 00060 // Program to Flash with alignments to page size 00061 // Parameters : 00062 // @param[in] buffer - pointer to the buffer to be written 00063 // @param[in] size - the size of the buffer in bytes. 00064 // @param[in] address - the address of the internal flash, must be aligned to minimum writing unit (page size). 00065 // Return : None. 00066 PAL_PRIVATE palStatus_t pal_programToFlashAligned(const size_t size, const uint32_t address, const uint32_t * buffer) 00067 { 00068 palStatus_t ret = PAL_SUCCESS; 00069 uint32_t pageSize = 0, alignmentLeft = 0; 00070 00071 pageSize = pal_internalFlashGetPageSize(); 00072 alignmentLeft = size % pageSize; //Keep the leftover to be copied separately 00073 00074 if (size >= pageSize) 00075 { 00076 ret = pal_plat_internalFlashWrite(size - alignmentLeft, address, buffer); 00077 } 00078 00079 if ((ret == PAL_SUCCESS) && (alignmentLeft != 0)) 00080 { 00081 uint32_t * pageBuffer = (uint32_t *)malloc(pageSize); 00082 if (pageBuffer == NULL) 00083 { 00084 ret = PAL_ERR_NO_MEMORY ; 00085 } 00086 else 00087 { 00088 memset(pageBuffer, 0xFF, pageSize); 00089 memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft); 00090 ret = pal_plat_internalFlashWrite(pageSize, address + (size - alignmentLeft), pageBuffer); 00091 free(pageBuffer); 00092 } 00093 } 00094 return ret; 00095 } 00096 00097 #else //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00098 00099 // Append root folder to path 00100 // Parameters : 00101 // @param[in] input - string to add the root prefix 00102 // @param[out] path - output buffer 00103 // Return : None. 00104 PAL_PRIVATE palStatus_t pal_addRootToPath(const char* input, char* path) 00105 { 00106 char root[PAL_MAX_FILE_AND_FOLDER_LENGTH] = { 0 }; 00107 palStatus_t status = PAL_SUCCESS; 00108 00109 memset(path, 0, PAL_MAX_FILE_AND_FOLDER_LENGTH); 00110 status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, root); 00111 if(PAL_SUCCESS == status) 00112 { 00113 snprintf(path, PAL_MAX_FILE_AND_FOLDER_LENGTH -1,"%s/%s", root, input); 00114 } 00115 00116 return status; 00117 } 00118 00119 // Check whether area file exists. Create it if not. 00120 // Parameters : 00121 // @param[in] area - Flash area. 00122 // Return : None. 00123 // Note - If file does not exist create and fill with 0xFF this simulate erased flash 00124 PAL_PRIVATE palStatus_t pal_verifyAndCreateFlashFile(void) 00125 { 00126 uint32_t index; 00127 uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0}; 00128 char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; 00129 palStatus_t ret = PAL_SUCCESS; 00130 size_t numOfBytes = 0; 00131 palSotpAreaData_t areaData_1, areaData_2; 00132 00133 pal_internalFlashGetAreaInfo(0, &areaData_1); 00134 pal_internalFlashGetAreaInfo(1, &areaData_2); 00135 00136 ret = pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, buffer); 00137 if(PAL_SUCCESS == ret ) 00138 { 00139 ret = pal_fsFopen(buffer, PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd); 00140 if(PAL_ERR_FS_NAME_ALREADY_EXIST == ret) 00141 { 00142 return PAL_SUCCESS; //file exist nothing else to do 00143 } 00144 else if(PAL_SUCCESS == ret) 00145 { 00146 memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE); 00147 for (index = 0; index < (areaData_1.size + areaData_2.size) / SIMULATE_FLASH_PAGE_SIZE; index++) 00148 { 00149 ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes); 00150 if(PAL_SUCCESS != ret) 00151 { 00152 break; 00153 } 00154 } 00155 pal_fsFclose(&g_fd); 00156 } 00157 } 00158 return ret; 00159 } 00160 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00161 00162 00163 //////////////////////////END PRIVATE SECTION//////////////////////////// 00164 00165 00166 size_t pal_internalFlashGetPageSize(void) 00167 { 00168 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00169 size_t ret = SIMULATE_FLASH_PAGE_SIZE; 00170 #else 00171 size_t ret = pal_plat_internalFlashGetPageSize(); 00172 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00173 if(ret > PAL_MAX_PAGE_SIZE) 00174 { 00175 ret = PAL_MAX_PAGE_SIZE; 00176 } 00177 return ret; 00178 } 00179 00180 size_t pal_internalFlashGetSectorSize(uint32_t address) 00181 { 00182 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00183 size_t ret = SIMULATE_FLASH_SECTOR_SIZE; 00184 #else 00185 size_t ret = pal_plat_internalFlashGetSectorSize(address); 00186 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00187 return ret; 00188 } 00189 00190 palStatus_t pal_internalFlashInit(void) 00191 { 00192 palStatus_t ret = PAL_SUCCESS; 00193 #if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00194 ret = pal_plat_internalFlashInit(); 00195 #endif 00196 if(PAL_SUCCESS == ret) 00197 { 00198 #if PAL_THREAD_SAFETY 00199 ret = pal_osSemaphoreCreate(1, &flashSem); 00200 if (PAL_SUCCESS != ret) 00201 { 00202 PAL_LOG(ERR, "Semaphore Create Error %" PRId32 ".", ret); 00203 } 00204 else 00205 #endif 00206 { 00207 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00208 char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; 00209 int32_t ctrs = 0; 00210 00211 if(SIMULATE_FLASH_DIR[0] != '\0') 00212 { 00213 ret = pal_addRootToPath(SIMULATE_FLASH_DIR, buffer); 00214 if (PAL_SUCCESS == ret ) 00215 { 00216 ret = pal_fsMkDir(buffer); //Create Directory 00217 if ((PAL_ERR_FS_NAME_ALREADY_EXIST == ret)) 00218 { 00219 ret = PAL_SUCCESS; 00220 } 00221 } 00222 } 00223 if (PAL_SUCCESS == ret ) 00224 { 00225 #if PAL_THREAD_SAFETY 00226 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs); 00227 if (PAL_SUCCESS == ret) 00228 #endif 00229 { 00230 ret = pal_verifyAndCreateFlashFile(); 00231 #if PAL_THREAD_SAFETY 00232 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00233 if(PAL_SUCCESS != error) 00234 { 00235 PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error); 00236 } 00237 #endif 00238 } 00239 } 00240 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00241 } 00242 } 00243 00244 #if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00245 if(PAL_SUCCESS != ret) 00246 {//Clean resources 00247 pal_plat_internalFlashDeInit(); 00248 } 00249 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00250 00251 return ret; 00252 } 00253 00254 00255 palStatus_t pal_internalFlashDeInit(void) 00256 { 00257 palStatus_t ret = PAL_SUCCESS; 00258 #if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00259 ret = pal_plat_internalFlashDeInit(); 00260 #endif 00261 00262 // Semaphore may be taken, so deleting it would fail. Try releasing (without checking return code). 00263 if(PAL_SUCCESS == ret) 00264 { 00265 #if PAL_THREAD_SAFETY 00266 pal_osSemaphoreRelease(flashSem); 00267 ret = pal_osSemaphoreDelete(&flashSem); 00268 #endif 00269 } 00270 return ret; 00271 } 00272 00273 palStatus_t pal_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer) 00274 { 00275 palStatus_t ret = PAL_SUCCESS; 00276 int32_t ctrs = 0; 00277 00278 00279 PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00280 PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00281 00282 #if PAL_THREAD_SAFETY 00283 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs); 00284 if (PAL_SUCCESS != ret) 00285 { 00286 return ret; 00287 } 00288 #endif 00289 00290 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00291 size_t numberOfBytesRead = 0; 00292 char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; 00293 00294 pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer); 00295 ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READONLY, &g_fd); 00296 if(PAL_SUCCESS == ret) 00297 { 00298 ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET); 00299 if(PAL_SUCCESS == ret) 00300 { 00301 ret = pal_fsFread(&g_fd, buffer, size, &numberOfBytesRead); 00302 } 00303 pal_fsFclose(&g_fd); 00304 } 00305 #else 00306 ret = pal_plat_internalFlashRead(size, address, buffer); 00307 #endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00308 00309 #if PAL_THREAD_SAFETY 00310 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00311 if(PAL_SUCCESS != error) 00312 { 00313 PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error); 00314 } 00315 #endif 00316 00317 return ret; 00318 } 00319 00320 00321 palStatus_t pal_internalFlashErase(uint32_t address, size_t size) 00322 { 00323 palStatus_t ret = PAL_SUCCESS; 00324 00325 int32_t ctrs = 0; 00326 00327 PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00328 PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit 00329 PAL_VALIDATE_ARG_RLZ ((!pal_isAlignedToSector(address,size)),PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED)//not aligned to sector 00330 00331 #if PAL_THREAD_SAFETY 00332 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs); 00333 if (PAL_SUCCESS != ret) 00334 { 00335 return ret; 00336 } 00337 #endif 00338 00339 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00340 char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; 00341 size_t numOfBytes = 0, index = 0; 00342 uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0}; 00343 00344 pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer); 00345 ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd); 00346 if (PAL_SUCCESS == ret) 00347 { 00348 ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET); 00349 if (PAL_SUCCESS == ret) 00350 { 00351 memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE); 00352 for (index = 0; index < size / SIMULATE_FLASH_PAGE_SIZE; index++) 00353 { 00354 ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes); 00355 if(PAL_SUCCESS != ret) 00356 { 00357 break; 00358 } 00359 } 00360 } 00361 pal_fsFclose(&g_fd); 00362 } 00363 #else 00364 size_t sectorSize = 0; 00365 sectorSize = pal_internalFlashGetSectorSize(address); 00366 while(size) 00367 { 00368 ret = pal_plat_internalFlashErase(address, size); 00369 size -= sectorSize; 00370 address += pal_internalFlashGetSectorSize(address + sectorSize); 00371 sectorSize = pal_internalFlashGetSectorSize(address); 00372 } 00373 #endif 00374 00375 #if PAL_THREAD_SAFETY 00376 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00377 if(PAL_SUCCESS != error) 00378 { 00379 PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error); 00380 } 00381 #endif 00382 return ret; 00383 } 00384 00385 00386 palStatus_t pal_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer) 00387 { 00388 palStatus_t ret = PAL_SUCCESS; 00389 uint32_t pageSize = 0; 00390 int32_t ctrs = 0; 00391 00392 PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00393 PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit 00394 PAL_VALIDATE_ARG_RLZ ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00395 00396 00397 pageSize = pal_internalFlashGetPageSize(); 00398 if (address % pageSize) 00399 { 00400 ret = PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED; 00401 } 00402 else 00403 { 00404 #if PAL_THREAD_SAFETY 00405 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs); 00406 if (PAL_SUCCESS != ret) 00407 { 00408 return ret; 00409 } 00410 #endif 00411 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 00412 char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; 00413 uint32_t alignmentLeft = 0; 00414 size_t numOfBytes = 0; 00415 00416 pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer); 00417 ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd); 00418 if (PAL_SUCCESS == ret) 00419 { 00420 alignmentLeft = size % pageSize; //Keep the leftover to be copied separately 00421 if (size >= pageSize) 00422 { 00423 ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET); 00424 if (PAL_SUCCESS == ret) 00425 { 00426 ret = pal_fsFwrite(&g_fd, (void *)buffer, size - alignmentLeft, &numOfBytes); 00427 } 00428 } 00429 00430 if ((ret == PAL_SUCCESS) && (alignmentLeft != 0)) 00431 { 00432 uint32_t * pageBuffer = (uint32_t *)malloc(pageSize); 00433 if (pageBuffer == NULL) 00434 { 00435 ret = PAL_ERR_NO_MEMORY ; 00436 } 00437 else 00438 { 00439 memset(pageBuffer, 0xFF, pageSize); 00440 memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft); 00441 ret = pal_fsFseek(&g_fd, address + (size - alignmentLeft), PAL_FS_OFFSET_SEEKSET); 00442 if(PAL_SUCCESS == ret) 00443 { 00444 ret = pal_fsFwrite(&g_fd, (void *)pageBuffer, pageSize, &numOfBytes); 00445 } 00446 free(pageBuffer); 00447 } 00448 } 00449 pal_fsFclose(&g_fd); 00450 } 00451 #else 00452 size_t sizeLeft = size; 00453 uint32_t tempAddress = address; 00454 uint32_t sectorSize = pal_internalFlashGetSectorSize(address); 00455 00456 //This section handles writing on cross sectors 00457 while (((tempAddress % sectorSize) + sizeLeft) > sectorSize) 00458 { 00459 size_t tmpSize = sectorSize - (tempAddress % sectorSize); 00460 ret = pal_programToFlashAligned(tmpSize, tempAddress, buffer); //Fill the sector to the end 00461 if( PAL_SUCCESS != ret) 00462 { 00463 break; 00464 } 00465 sizeLeft -= tmpSize; 00466 tempAddress += tmpSize; 00467 buffer += tmpSize / sizeof(uint32_t); 00468 //Read sector size again because Sector size can change when crossing sectors. 00469 sectorSize = pal_internalFlashGetSectorSize(address); 00470 } 00471 00472 //Write part of a sector (remainder of the buffer) 00473 if ((PAL_SUCCESS == ret) && (sizeLeft > 0)) 00474 { 00475 ret = pal_programToFlashAligned(sizeLeft, tempAddress, buffer); 00476 } 00477 #endif 00478 #if PAL_THREAD_SAFETY 00479 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00480 if(PAL_SUCCESS != error) 00481 { 00482 PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error); 00483 } 00484 #endif 00485 00486 } 00487 return ret; 00488 } 00489 00490 00491 palStatus_t pal_internalFlashGetAreaInfo(uint8_t section, palSotpAreaData_t *data) 00492 { 00493 palStatus_t ret = PAL_SUCCESS; 00494 const palSotpAreaData_t internalFlashArea[] = 00495 { 00496 {PAL_INTERNAL_FLASH_SECTION_1_ADDRESS, PAL_INTERNAL_FLASH_SECTION_1_SIZE}, 00497 {PAL_INTERNAL_FLASH_SECTION_2_ADDRESS, PAL_INTERNAL_FLASH_SECTION_2_SIZE} 00498 }; 00499 00500 PAL_VALIDATE_CONDITION_WITH_ERROR ((data == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00501 00502 data->address = internalFlashArea[section].address; 00503 data->size = internalFlashArea[section].size; 00504 return ret; 00505 } 00506 00507 #endif //(PAL_USE_INTERNAL_FLASH)
Generated on Tue Jul 12 2022 19:01:36 by 1.7.2