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.
Dependencies: FXAS21002 FXOS8700Q
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 <stdlib.h> 00019 #include <string.h> 00020 00021 #define TRACE_GROUP "PAL" 00022 00023 #if (PAL_USE_INTERNAL_FLASH) 00024 00025 #define BITS_ALIGNED_TO_32 0x3 00026 00027 //////////////////////////GLOBALS SECTION //////////////////////////// 00028 #if PAL_THREAD_SAFETY 00029 // Use semaphore and not mutex, as mutexes don't behave well when trying to delete them while taken (which may happen in our tests). 00030 static palSemaphoreID_t flashSem = 0; 00031 #endif 00032 00033 //////////////////////////END GLOBALS SECTION //////////////////////////// 00034 00035 00036 //////////////////////////START PRIVATE SECTION//////////////////////////// 00037 // Verify that the alignment to sector size 00038 // Parameters : 00039 // @param[in] address - Address to verify. 00040 // @param[in] size - Size to write 00041 // Return : None. 00042 PAL_PRIVATE bool pal_isAlignedToSector(uint32_t address, size_t size) 00043 { 00044 uint32_t currentSectorSize = pal_internalFlashGetSectorSize(address); 00045 if ((size % currentSectorSize) || (address % currentSectorSize)) 00046 { 00047 return false; 00048 } 00049 else 00050 { 00051 return true; 00052 } 00053 } 00054 00055 00056 // Program to Flash with alignments to page size 00057 // Parameters : 00058 // @param[in] buffer - pointer to the buffer to be written 00059 // @param[in] size - the size of the buffer in bytes. 00060 // @param[in] address - the address of the internal flash, must be aligned to minimum writing unit (page size). 00061 // Return : None. 00062 PAL_PRIVATE palStatus_t pal_programToFlashAligned(const size_t size, const uint32_t address, const uint32_t * buffer) 00063 { 00064 palStatus_t ret = PAL_SUCCESS; 00065 uint32_t pageSize = 0, alignmentLeft = 0; 00066 00067 pageSize = pal_internalFlashGetPageSize(); 00068 alignmentLeft = size % pageSize; //Keep the leftover to be copied separately 00069 00070 if (size >= pageSize) 00071 { 00072 ret = pal_plat_internalFlashWrite(size - alignmentLeft, address, buffer); 00073 } 00074 00075 if ((ret == PAL_SUCCESS) && (alignmentLeft != 0)) 00076 { 00077 uint32_t * pageBuffer = (uint32_t *)malloc(pageSize); 00078 if (pageBuffer == NULL) 00079 { 00080 ret = PAL_ERR_NO_MEMORY ; 00081 } 00082 else 00083 { 00084 memset(pageBuffer, 0xFF, pageSize); 00085 memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft); 00086 ret = pal_plat_internalFlashWrite(pageSize, address + (size - alignmentLeft), pageBuffer); 00087 free(pageBuffer); 00088 } 00089 } 00090 return ret; 00091 } 00092 00093 00094 //////////////////////////END PRIVATE SECTION//////////////////////////// 00095 00096 00097 size_t pal_internalFlashGetPageSize(void) 00098 { 00099 00100 size_t ret = pal_plat_internalFlashGetPageSize(); 00101 00102 00103 return ret; 00104 } 00105 00106 size_t pal_internalFlashGetSectorSize(uint32_t address) 00107 { 00108 size_t ret = pal_plat_internalFlashGetSectorSize(address); 00109 return ret; 00110 } 00111 00112 palStatus_t pal_internalFlashInit(void) 00113 { 00114 palStatus_t ret = PAL_SUCCESS; 00115 00116 #if PAL_THREAD_SAFETY 00117 ret = pal_osSemaphoreCreate(1, &flashSem); 00118 if (PAL_SUCCESS != ret) 00119 { 00120 PAL_LOG_ERR("Semaphore Create Error %" PRId32 ".", ret); 00121 } 00122 else 00123 #endif 00124 { 00125 00126 #if PAL_THREAD_SAFETY 00127 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, NULL); 00128 if (PAL_SUCCESS == ret) 00129 #endif 00130 { 00131 ret = pal_plat_internalFlashInit(); 00132 00133 #if PAL_THREAD_SAFETY 00134 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00135 if (PAL_SUCCESS != error) 00136 { 00137 PAL_LOG_ERR("SemaphoreRelease Error %" PRId32 ".", error); 00138 } 00139 #endif 00140 } 00141 00142 if (PAL_SUCCESS != ret) 00143 {//Clean resources, including the flash semaphore 00144 pal_internalFlashDeInit(); 00145 } 00146 } 00147 00148 return ret; 00149 } 00150 00151 00152 palStatus_t pal_internalFlashDeInit(void) 00153 { 00154 palStatus_t ret = PAL_SUCCESS; 00155 00156 #if PAL_THREAD_SAFETY 00157 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, NULL); 00158 if (PAL_SUCCESS != ret) 00159 { 00160 return ret; 00161 } 00162 #endif 00163 if (PAL_SUCCESS == ret) 00164 { 00165 ret = pal_plat_internalFlashDeInit(); 00166 00167 #if PAL_THREAD_SAFETY 00168 ret = pal_osSemaphoreRelease(flashSem); 00169 if (PAL_SUCCESS != ret) { 00170 PAL_LOG_ERR("SemaphoreRelease Error %" PRId32 ".", ret); 00171 } 00172 ret = pal_osSemaphoreDelete(&flashSem); 00173 if (PAL_SUCCESS != ret) { 00174 PAL_LOG_ERR("pal_osSemaphoreDelete Error %" PRId32 ".", ret); 00175 } 00176 #endif 00177 } 00178 return ret; 00179 } 00180 00181 palStatus_t pal_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer) 00182 { 00183 palStatus_t ret = PAL_SUCCESS; 00184 00185 PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00186 PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00187 00188 #if PAL_THREAD_SAFETY 00189 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, NULL); 00190 if (PAL_SUCCESS != ret) 00191 { 00192 return ret; 00193 } 00194 #endif 00195 00196 ret = pal_plat_internalFlashRead(size, address, buffer); 00197 00198 #if PAL_THREAD_SAFETY 00199 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00200 if (PAL_SUCCESS != error) 00201 { 00202 PAL_LOG_ERR("SemaphoreRelease Error %" PRId32 ".", error); 00203 } 00204 #endif 00205 00206 return ret; 00207 } 00208 00209 00210 palStatus_t pal_internalFlashErase(uint32_t address, size_t size) 00211 { 00212 palStatus_t ret = PAL_SUCCESS; 00213 00214 PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00215 PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit 00216 PAL_VALIDATE_ARG_RLZ ((!pal_isAlignedToSector(address,size)),PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED)//not aligned to sector 00217 00218 #if PAL_THREAD_SAFETY 00219 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, NULL); 00220 if (PAL_SUCCESS != ret) 00221 { 00222 return ret; 00223 } 00224 #endif 00225 00226 size_t sectorSize = 0; 00227 sectorSize = pal_internalFlashGetSectorSize(address); 00228 while (size) 00229 { 00230 ret = pal_plat_internalFlashErase(address, size); 00231 size -= sectorSize; 00232 address += pal_internalFlashGetSectorSize(address + sectorSize); 00233 sectorSize = pal_internalFlashGetSectorSize(address); 00234 } 00235 00236 #if PAL_THREAD_SAFETY 00237 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00238 if (PAL_SUCCESS != error) 00239 { 00240 PAL_LOG_ERR("SemaphoreRelease Error %" PRId32 ".", error); 00241 } 00242 #endif 00243 return ret; 00244 } 00245 00246 00247 palStatus_t pal_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer) 00248 { 00249 palStatus_t ret = PAL_SUCCESS; 00250 uint32_t pageSize = 0; 00251 00252 PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00253 PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit 00254 PAL_VALIDATE_ARG_RLZ ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE) 00255 00256 pageSize = pal_internalFlashGetPageSize(); 00257 if (address % pageSize) 00258 { 00259 ret = PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED; 00260 } 00261 else 00262 { 00263 #if PAL_THREAD_SAFETY 00264 ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, NULL); 00265 if (PAL_SUCCESS != ret) 00266 { 00267 return ret; 00268 } 00269 #endif 00270 size_t sizeLeft = size; 00271 uint32_t tempAddress = address; 00272 uint32_t sectorSize = pal_internalFlashGetSectorSize(address); 00273 00274 //This section handles writing on cross sectors 00275 while (((tempAddress % sectorSize) + sizeLeft) > sectorSize) 00276 { 00277 size_t tmpSize = sectorSize - (tempAddress % sectorSize); 00278 ret = pal_programToFlashAligned(tmpSize, tempAddress, buffer); //Fill the sector to the end 00279 if (PAL_SUCCESS != ret) 00280 { 00281 break; 00282 } 00283 sizeLeft -= tmpSize; 00284 tempAddress += tmpSize; 00285 buffer += tmpSize / sizeof(uint32_t); 00286 //Read sector size again because Sector size can change when crossing sectors. 00287 sectorSize = pal_internalFlashGetSectorSize(address); 00288 } 00289 00290 //Write part of a sector (remainder of the buffer) 00291 if ((PAL_SUCCESS == ret) && (sizeLeft > 0)) 00292 { 00293 ret = pal_programToFlashAligned(sizeLeft, tempAddress, buffer); 00294 } 00295 #if PAL_THREAD_SAFETY 00296 palStatus_t error = pal_osSemaphoreRelease(flashSem); 00297 if (PAL_SUCCESS != error) 00298 { 00299 PAL_LOG_ERR("SemaphoreRelease Error %" PRId32 ".", error); 00300 } 00301 #endif 00302 00303 } 00304 return ret; 00305 } 00306 00307 00308 palStatus_t pal_internalFlashGetAreaInfo(uint8_t section, palSotpAreaData_t *data) 00309 { 00310 palStatus_t ret = PAL_SUCCESS; 00311 const palSotpAreaData_t internalFlashArea[] = 00312 { 00313 {PAL_INTERNAL_FLASH_SECTION_1_ADDRESS, PAL_INTERNAL_FLASH_SECTION_1_SIZE}, 00314 {PAL_INTERNAL_FLASH_SECTION_2_ADDRESS, PAL_INTERNAL_FLASH_SECTION_2_SIZE} 00315 }; 00316 00317 PAL_VALIDATE_CONDITION_WITH_ERROR ((data == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED) 00318 00319 data->address = internalFlashArea[section].address; 00320 data->size = internalFlashArea[section].size; 00321 return ret; 00322 } 00323 00324 #endif //(PAL_USE_INTERNAL_FLASH)
Generated on Tue Jul 12 2022 20:21:01 by
