Kev Mann / mbed-dev-OS5_10_4
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FlashIAPBlockDevice.cpp Source File

FlashIAPBlockDevice.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2016 ARM Limited
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 
00017 #ifdef DEVICE_FLASH
00018 
00019 #include "FlashIAPBlockDevice.h"
00020 #include "mbed_critical.h"
00021 
00022 #include "mbed.h"
00023 
00024 #include <inttypes.h>
00025 
00026 #define FLASHIAP_READ_SIZE 1
00027 
00028 // Debug available
00029 #ifndef FLASHIAP_DEBUG
00030 #define FLASHIAP_DEBUG      0
00031 #endif
00032 
00033 #if FLASHIAP_DEBUG
00034 #define DEBUG_PRINTF(...) printf(__VA_ARGS__)
00035 #else
00036 #define DEBUG_PRINTF(...)
00037 #endif
00038 
00039 FlashIAPBlockDevice::FlashIAPBlockDevice(uint32_t address, uint32_t size)
00040     : _flash(), _base(address), _size(size), _is_initialized(false), _init_ref_count(0)
00041 {
00042 
00043 }
00044 
00045 FlashIAPBlockDevice::~FlashIAPBlockDevice()
00046 {
00047     deinit();
00048 }
00049 
00050 int FlashIAPBlockDevice::init()
00051 {
00052     DEBUG_PRINTF("init\r\n");
00053 
00054     if (!_is_initialized) {
00055         _init_ref_count = 0;
00056     }
00057 
00058     uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1);
00059 
00060     if (val != 1) {
00061         return BD_ERROR_OK;
00062     }
00063 
00064     int ret = _flash.init();
00065 
00066     if (ret) {
00067         core_util_atomic_decr_u32(&_init_ref_count, 1);
00068         return ret;
00069     }
00070 
00071     if (_size + _base > _flash.get_flash_size() + _flash.get_flash_start()) {
00072         core_util_atomic_decr_u32(&_init_ref_count, 1);
00073         return BD_ERROR_DEVICE_ERROR;
00074     }
00075 
00076     if (_base < _flash.get_flash_start()) {
00077         core_util_atomic_decr_u32(&_init_ref_count, 1);
00078         return BD_ERROR_DEVICE_ERROR;
00079     }
00080 
00081     if (!_base) {
00082         _base = _flash.get_flash_start();
00083     }
00084 
00085     if (!_size) {
00086         _size = _flash.get_flash_size() - (_base - _flash.get_flash_start());
00087     }
00088 
00089     _is_initialized = true;
00090     return ret;
00091 }
00092 
00093 int FlashIAPBlockDevice::deinit()
00094 {
00095     DEBUG_PRINTF("deinit\r\n");
00096 
00097     if (!_is_initialized) {
00098         _init_ref_count = 0;
00099         return 0;
00100     }
00101 
00102     uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1);
00103 
00104     if (val) {
00105         return 0;
00106     }
00107 
00108     _is_initialized = false;
00109 
00110     return _flash.deinit();
00111 }
00112 
00113 int FlashIAPBlockDevice::read(void *buffer,
00114                               bd_addr_t virtual_address,
00115                               bd_size_t size)
00116 {
00117     DEBUG_PRINTF("read: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00118 
00119     /* Default to error return code; success must be set explicitly. */
00120     int result = BD_ERROR_DEVICE_ERROR;
00121 
00122     /* Check that the address and size are properly aligned and fit. */
00123     if (_is_initialized && is_valid_read(virtual_address, size)) {
00124 
00125         /* Convert virtual address to the physical address for the device. */
00126         bd_addr_t physical_address = _base + virtual_address;
00127 
00128         /* Read data using the internal flash driver. */
00129         result = _flash.read(buffer, physical_address, size);
00130 
00131         DEBUG_PRINTF("physical: %" PRIX64 "\r\n", physical_address);
00132     }
00133 
00134     return result;
00135 }
00136 
00137 int FlashIAPBlockDevice::program(const void *buffer,
00138                                  bd_addr_t virtual_address,
00139                                  bd_size_t size)
00140 {
00141     DEBUG_PRINTF("program: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00142 
00143     /* Default to error return code; success must be set explicitly. */
00144     int result = BD_ERROR_DEVICE_ERROR;
00145 
00146     /* Check that the address and size are properly aligned and fit. */
00147     if (_is_initialized && is_valid_program(virtual_address, size)) {
00148 
00149         /* Convert virtual address to the physical address for the device. */
00150         bd_addr_t physical_address = _base + virtual_address;
00151 
00152         /* Write data using the internal flash driver. */
00153         result = _flash.program(buffer, physical_address, size);
00154 
00155         DEBUG_PRINTF("physical: %" PRIX64 " %" PRIX64 "\r\n",
00156                      physical_address,
00157                      size);
00158     }
00159 
00160     return result;
00161 }
00162 
00163 int FlashIAPBlockDevice::erase(bd_addr_t virtual_address,
00164                                bd_size_t size)
00165 {
00166     DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00167 
00168     /* Default to error return code; success must be set explicitly. */
00169     int result = BD_ERROR_DEVICE_ERROR;
00170 
00171     /* Check that the address and size are properly aligned and fit. */
00172     if (_is_initialized && is_valid_erase(virtual_address, size)) {
00173 
00174         /* Convert virtual address to the physical address for the device. */
00175         bd_addr_t physical_address = _base + virtual_address;
00176 
00177         /* Erase sector */
00178         result = _flash.erase(physical_address, size);
00179     }
00180 
00181     return result;
00182 }
00183 
00184 bd_size_t FlashIAPBlockDevice::get_read_size() const
00185 {
00186     DEBUG_PRINTF("get_read_size: %d\r\n", FLASHIAP_READ_SIZE);
00187 
00188     return FLASHIAP_READ_SIZE;
00189 }
00190 
00191 bd_size_t FlashIAPBlockDevice::get_program_size() const
00192 {
00193     if (!_is_initialized) {
00194         return 0;
00195     }
00196 
00197     uint32_t page_size = _flash.get_page_size();
00198 
00199     DEBUG_PRINTF("get_program_size: %" PRIX32 "\r\n", page_size);
00200 
00201     return page_size;
00202 }
00203 
00204 bd_size_t FlashIAPBlockDevice::get_erase_size() const
00205 {
00206     if (!_is_initialized) {
00207         return 0;
00208     }
00209 
00210     uint32_t erase_size = _flash.get_sector_size(_base);
00211 
00212     DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size);
00213 
00214     return erase_size;
00215 }
00216 
00217 bd_size_t FlashIAPBlockDevice::get_erase_size(bd_addr_t addr) const
00218 {
00219     if (!_is_initialized) {
00220         return 0;
00221     }
00222 
00223     uint32_t erase_size = _flash.get_sector_size(_base + addr);
00224 
00225     DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size);
00226 
00227     return erase_size;
00228 }
00229 
00230 bd_size_t FlashIAPBlockDevice::size() const
00231 {
00232     DEBUG_PRINTF("size: %" PRIX64 "\r\n", _size);
00233 
00234     return _size;
00235 }
00236 
00237 #endif /* DEVICE_FLASH */