Mayank Gupta / Mbed OS pelion-example-frdm

Dependencies:   FXAS21002 FXOS8700Q

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_plat_internalFlash_FlashOverFilesystem.c Source File

pal_plat_internalFlash_FlashOverFilesystem.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 
00019 #if (PAL_USE_INTERNAL_FLASH)
00020 
00021 #if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
00022 
00023 #include <stdio.h> // for snprintf
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 #define TRACE_GROUP "PAL"
00028 
00029 #define BITS_ALIGNED_TO_32  0x3
00030 
00031 PAL_PRIVATE palFileDescriptor_t g_fd = 0;
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 // Get path of the simulated flash file
00057 // Parameters :
00058 // @param[out] path        - output buffer
00059 // Return     : PAL_SUCCESS if the combined mount point and flash directory are under the maximum path limit
00060 PAL_PRIVATE palStatus_t pal_getFlashSimulationFilePath(char* path)
00061 {
00062     char root[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00063 
00064     palStatus_t status = PAL_SUCCESS;
00065 
00066     status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, root);
00067     if (PAL_SUCCESS == status)
00068     {
00069         size_t written;
00070         if (SIMULATE_FLASH_DIR[0] != 0)
00071         {
00072             written = snprintf(path, PAL_MAX_FILE_AND_FOLDER_LENGTH, "%s/%s", root, SIMULATE_FLASH_DIR);
00073         }
00074         else {
00075             written = snprintf(path, PAL_MAX_FILE_AND_FOLDER_LENGTH, "%s", root);
00076         }
00077 
00078         // verify, if the mount point and SIMULATE_FLASH_DIR fit to the hard coded maximum.
00079         if (written >= PAL_MAX_FILE_AND_FOLDER_LENGTH)
00080         {
00081             status = PAL_ERR_INVALID_ARGUMENT ;
00082         }
00083     }
00084 
00085     return status;
00086 }
00087 
00088 // Get path and filename of the simulated flash file
00089 // Parameters :
00090 // @param[out] path        - output buffer
00091 // Return     : PAL_SUCCESS if the combined filenames are under the maximum path limit
00092 PAL_PRIVATE palStatus_t pal_getFlashSimulationFilePathAndName(char* path)
00093 {
00094     char root[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00095 
00096     palStatus_t status = PAL_ERR_FS_INVALID_FILE_NAME;
00097 
00098     if (SIMULATE_FLASH_FILE_NAME[0] == '/')
00099     {
00100         status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, root);
00101         if (PAL_SUCCESS == status)
00102         {
00103             // the SIMULATE_FLASH_FILE_NAME is specified to contain also the SIMULATE_FLASH_DIR -directory
00104             // and it will begin with a '/' char, so this needs separate implementation from pal_getFlashSimulationFileDir()
00105             int written = snprintf(path, PAL_MAX_FILE_AND_FOLDER_LENGTH, "%s%s", root, SIMULATE_FLASH_FILE_NAME);
00106             if (written >= PAL_MAX_FILE_AND_FOLDER_LENGTH)
00107             {
00108                 status = PAL_ERR_INVALID_ARGUMENT ;
00109             }
00110         }
00111     }
00112 
00113     return status;
00114 }
00115 
00116 // Check whether area file exists. Create it if not.
00117 // Parameters :
00118 // @param[in]
00119 // Return     : None.
00120 // Note - If file does not exist create and fill with 0xFF this simulate erased flash
00121 PAL_PRIVATE palStatus_t pal_verifyAndCreateFlashFile(void)
00122 {
00123     uint32_t index;
00124     uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0};
00125     char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
00126     palStatus_t ret = PAL_SUCCESS;
00127     size_t numOfBytes = 0;
00128     palSotpAreaData_t areaData_1, areaData_2;
00129 
00130     pal_internalFlashGetAreaInfo(0, &areaData_1);
00131     pal_internalFlashGetAreaInfo(1, &areaData_2);
00132 
00133     ret = pal_getFlashSimulationFilePathAndName(buffer);
00134     if (PAL_SUCCESS == ret)
00135     {
00136         ret = pal_fsFopen(buffer, PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd);
00137         if (PAL_ERR_FS_NAME_ALREADY_EXIST == ret)
00138         {
00139             return PAL_SUCCESS; //file exist nothing else to do
00140         }
00141         else if (PAL_SUCCESS == ret)
00142         {
00143             memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE);
00144             for (index = 0; index < (areaData_1.size + areaData_2.size) / SIMULATE_FLASH_PAGE_SIZE; index++)
00145             {
00146                 ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes);
00147                 if (PAL_SUCCESS != ret)
00148                 {
00149                     break;
00150                 }
00151             }
00152             pal_fsFclose(&g_fd);
00153         }
00154     }
00155     return ret;
00156 }
00157 
00158 
00159 //////////////////////////END PRIVATE SECTION////////////////////////////
00160 
00161 
00162 size_t pal_plat_internalFlashGetPageSize(void)
00163 {
00164     size_t ret = SIMULATE_FLASH_PAGE_SIZE;
00165     return ret;
00166 }
00167 
00168 size_t pal_plat_internalFlashGetSectorSize(uint32_t address)
00169 {
00170 
00171     size_t ret = SIMULATE_FLASH_SECTOR_SIZE;
00172     return ret;
00173 }
00174 
00175 palStatus_t pal_plat_internalFlashInit(void)
00176 {
00177     palStatus_t ret = PAL_SUCCESS;
00178 
00179     char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00180 
00181     ret = pal_getFlashSimulationFilePath(buffer);
00182 
00183     if (PAL_SUCCESS == ret)
00184     {
00185         ret = pal_fsMkDir(buffer); //Create Directory
00186         if ((PAL_ERR_FS_NAME_ALREADY_EXIST == ret))
00187         {
00188             ret = PAL_SUCCESS;
00189         }
00190 
00191         if (PAL_SUCCESS == ret)
00192         {
00193             // Create file too, which verifies that the access rights on
00194             // the filesystem are correct and it has enough space for simulation
00195             // file.
00196             ret = pal_verifyAndCreateFlashFile();
00197         }
00198     }
00199 
00200     return ret;
00201 }
00202 
00203 
00204 palStatus_t pal_plat_internalFlashDeInit(void)
00205 {
00206     palStatus_t ret = PAL_SUCCESS;
00207     return ret;
00208 }
00209 
00210 palStatus_t pal_plat_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer)
00211 {
00212     palStatus_t ret = PAL_SUCCESS;
00213 
00214     PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED)
00215     PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
00216 
00217     size_t numberOfBytesRead = 0;
00218     char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00219 
00220     ret = pal_getFlashSimulationFilePathAndName(fileBuffer);
00221     if (PAL_SUCCESS == ret)
00222     {
00223         // XXX: why not keep the file open all the time? There is init() & deinit()
00224         // to allow that. The code even uses a global file handle for the temporary
00225         // operations.
00226         ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READONLY, &g_fd);
00227         if (PAL_SUCCESS == ret)
00228         {
00229             ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
00230             if (PAL_SUCCESS == ret)
00231             {
00232                 ret = pal_fsFread(&g_fd, buffer, size, &numberOfBytesRead);
00233             }
00234             pal_fsFclose(&g_fd);
00235         }
00236     }
00237 
00238     return ret;
00239 }
00240 
00241 
00242 palStatus_t pal_plat_internalFlashErase(uint32_t address, size_t size)
00243 {
00244     palStatus_t ret = PAL_SUCCESS;
00245 
00246     PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
00247     PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit
00248     PAL_VALIDATE_ARG_RLZ ((!pal_isAlignedToSector(address,size)),PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED)//not aligned to sector
00249 
00250     char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00251     size_t numOfBytes = 0, index = 0;
00252     uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0};
00253 
00254     ret = pal_getFlashSimulationFilePathAndName(fileBuffer);
00255     if (PAL_SUCCESS == ret)
00256     {
00257         ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd);
00258         if (PAL_SUCCESS == ret)
00259         {
00260             ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
00261             if (PAL_SUCCESS == ret)
00262             {
00263                 memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE);
00264                 for (index = 0; index < size / SIMULATE_FLASH_PAGE_SIZE; index++)
00265                 {
00266                     ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes);
00267                     if (PAL_SUCCESS != ret)
00268                     {
00269                         break;
00270                     }
00271                 }
00272             }
00273             pal_fsFclose(&g_fd);
00274         }
00275     }
00276 
00277     return ret;
00278 }
00279 
00280 
00281 palStatus_t pal_plat_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer)
00282 {
00283     palStatus_t ret = PAL_SUCCESS;
00284     uint32_t pageSize = 0;
00285 
00286     PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED)
00287     PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit
00288     PAL_VALIDATE_ARG_RLZ ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
00289 
00290     pageSize = pal_plat_internalFlashGetPageSize();
00291 
00292     char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH];
00293     uint32_t alignmentLeft = 0;
00294     size_t numOfBytes = 0;
00295 
00296     ret = pal_getFlashSimulationFilePathAndName(fileBuffer);
00297     if (PAL_SUCCESS == ret)
00298     {
00299         ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd);
00300         if (PAL_SUCCESS == ret)
00301         {
00302             alignmentLeft = size % pageSize; //Keep the leftover to be copied separately
00303             if (size >= pageSize)
00304             {
00305                 ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
00306                 if (PAL_SUCCESS == ret)
00307                 {
00308                     ret = pal_fsFwrite(&g_fd, (void *)buffer, size - alignmentLeft, &numOfBytes);
00309                 }
00310             }
00311 
00312             if ((ret == PAL_SUCCESS) && (alignmentLeft != 0))
00313             {
00314                 uint32_t * pageBuffer = (uint32_t *)malloc(pageSize);
00315                 if (pageBuffer == NULL)
00316                 {
00317                     ret = PAL_ERR_NO_MEMORY ;
00318                 }
00319                 else
00320                 {
00321                     memset(pageBuffer, 0xFF, pageSize);
00322                     memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft);
00323                     ret = pal_fsFseek(&g_fd, address + (size - alignmentLeft), PAL_FS_OFFSET_SEEKSET);
00324                     if (PAL_SUCCESS == ret)
00325                     {
00326                         ret = pal_fsFwrite(&g_fd, (void *)pageBuffer, pageSize, &numOfBytes);
00327                     }
00328                     free(pageBuffer);
00329                 }
00330             }
00331             pal_fsFclose(&g_fd);
00332         }
00333     }
00334 
00335     return ret;
00336 }
00337 
00338 
00339 #endif // PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
00340 
00341 #endif //(PAL_USE_INTERNAL_FLASH)