Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_internalFlash.c Source File

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)