Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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 #if DEVICE_FLASH
00018 
00019 #include "FlashIAPBlockDevice.h"
00020 #include "mbed_atomic.h"
00021 #include "mbed_error.h"
00022 
00023 using namespace mbed;
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     if ((address == 0xFFFFFFFF) || (size == 0)) {
00043         MBED_ERROR(MBED_ERROR_INVALID_ARGUMENT,
00044                    "Base address and size need to be set in flashiap-block-device configuration in order to use default constructor");
00045     }
00046 }
00047 
00048 FlashIAPBlockDevice::~FlashIAPBlockDevice()
00049 {
00050     deinit();
00051 }
00052 
00053 int FlashIAPBlockDevice::init()
00054 {
00055     DEBUG_PRINTF("init\r\n");
00056 
00057     if (!_is_initialized) {
00058         _init_ref_count = 0;
00059     }
00060 
00061     uint32_t val = core_util_atomic_incr_u32 (&_init_ref_count, 1);
00062 
00063     if (val != 1) {
00064         return BD_ERROR_OK;
00065     }
00066 
00067     int ret = _flash.init();
00068 
00069     if (ret) {
00070         core_util_atomic_decr_u32 (&_init_ref_count, 1);
00071         return ret;
00072     }
00073 
00074     if (_size + _base > _flash.get_flash_size() + _flash.get_flash_start()) {
00075         core_util_atomic_decr_u32 (&_init_ref_count, 1);
00076         return BD_ERROR_DEVICE_ERROR;
00077     }
00078 
00079     if (_base < _flash.get_flash_start()) {
00080         core_util_atomic_decr_u32 (&_init_ref_count, 1);
00081         return BD_ERROR_DEVICE_ERROR;
00082     }
00083 
00084     if (!_base) {
00085         _base = _flash.get_flash_start();
00086     }
00087 
00088     if (!_size) {
00089         _size = _flash.get_flash_size() - (_base - _flash.get_flash_start());
00090     }
00091 
00092     _is_initialized = true;
00093     return ret;
00094 }
00095 
00096 int FlashIAPBlockDevice::deinit()
00097 {
00098     DEBUG_PRINTF("deinit\r\n");
00099 
00100     if (!_is_initialized) {
00101         _init_ref_count = 0;
00102         return 0;
00103     }
00104 
00105     uint32_t val = core_util_atomic_decr_u32 (&_init_ref_count, 1);
00106 
00107     if (val) {
00108         return 0;
00109     }
00110 
00111     _is_initialized = false;
00112 
00113     return _flash.deinit();
00114 }
00115 
00116 int FlashIAPBlockDevice::read(void *buffer,
00117                               bd_addr_t virtual_address,
00118                               bd_size_t size)
00119 {
00120     DEBUG_PRINTF("read: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00121 
00122     /* Default to error return code; success must be set explicitly. */
00123     int result = BD_ERROR_DEVICE_ERROR;
00124 
00125     /* Check that the address and size are properly aligned and fit. */
00126     if (_is_initialized && is_valid_read(virtual_address, size)) {
00127 
00128         /* Convert virtual address to the physical address for the device. */
00129         bd_addr_t physical_address = _base + virtual_address;
00130 
00131         /* Read data using the internal flash driver. */
00132         result = _flash.read(buffer, physical_address, size);
00133 
00134         DEBUG_PRINTF("physical: %" PRIX64 "\r\n", physical_address);
00135     }
00136 
00137     return result;
00138 }
00139 
00140 int FlashIAPBlockDevice::program(const void *buffer,
00141                                  bd_addr_t virtual_address,
00142                                  bd_size_t size)
00143 {
00144     DEBUG_PRINTF("program: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00145 
00146     /* Default to error return code; success must be set explicitly. */
00147     int result = BD_ERROR_DEVICE_ERROR;
00148 
00149     /* Check that the address and size are properly aligned and fit. */
00150     if (_is_initialized && is_valid_program(virtual_address, size)) {
00151 
00152         /* Convert virtual address to the physical address for the device. */
00153         bd_addr_t physical_address = _base + virtual_address;
00154 
00155         /* Write data using the internal flash driver. */
00156         result = _flash.program(buffer, physical_address, size);
00157 
00158         DEBUG_PRINTF("physical: %" PRIX64 " %" PRIX64 "\r\n",
00159                      physical_address,
00160                      size);
00161     }
00162 
00163     return result;
00164 }
00165 
00166 int FlashIAPBlockDevice::erase(bd_addr_t virtual_address,
00167                                bd_size_t size)
00168 {
00169     DEBUG_PRINTF("erase: %" PRIX64 " %" PRIX64 "\r\n", virtual_address, size);
00170 
00171     /* Default to error return code; success must be set explicitly. */
00172     int result = BD_ERROR_DEVICE_ERROR;
00173 
00174     /* Check that the address and size are properly aligned and fit. */
00175     if (_is_initialized && is_valid_erase(virtual_address, size)) {
00176 
00177         /* Convert virtual address to the physical address for the device. */
00178         bd_addr_t physical_address = _base + virtual_address;
00179 
00180         /* Erase sector */
00181         result = _flash.erase(physical_address, size);
00182     }
00183 
00184     return result;
00185 }
00186 
00187 bd_size_t FlashIAPBlockDevice::get_read_size() const
00188 {
00189     DEBUG_PRINTF("get_read_size: %d\r\n", FLASHIAP_READ_SIZE);
00190 
00191     return FLASHIAP_READ_SIZE;
00192 }
00193 
00194 bd_size_t FlashIAPBlockDevice::get_program_size() const
00195 {
00196     if (!_is_initialized) {
00197         return 0;
00198     }
00199 
00200     uint32_t page_size = _flash.get_page_size();
00201 
00202     DEBUG_PRINTF("get_program_size: %" PRIX32 "\r\n", page_size);
00203 
00204     return page_size;
00205 }
00206 
00207 bd_size_t FlashIAPBlockDevice::get_erase_size() const
00208 {
00209     if (!_is_initialized) {
00210         return 0;
00211     }
00212 
00213     uint32_t erase_size = _flash.get_sector_size(_base);
00214 
00215     DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size);
00216 
00217     return erase_size;
00218 }
00219 
00220 bd_size_t FlashIAPBlockDevice::get_erase_size(bd_addr_t addr) const
00221 {
00222     if (!_is_initialized) {
00223         return 0;
00224     }
00225 
00226     uint32_t erase_size = _flash.get_sector_size(_base + addr);
00227 
00228     DEBUG_PRINTF("get_erase_size: %" PRIX32 "\r\n", erase_size);
00229 
00230     return erase_size;
00231 }
00232 
00233 int FlashIAPBlockDevice::get_erase_value() const
00234 {
00235     if (!_is_initialized) {
00236         return -1;
00237     }
00238 
00239     uint8_t erase_val = _flash.get_erase_value();
00240 
00241     DEBUG_PRINTF("get_erase_value: %" PRIX8 "\r\n", erase_val);
00242 
00243     return erase_val;
00244 }
00245 
00246 
00247 bd_size_t FlashIAPBlockDevice::size() const
00248 {
00249     DEBUG_PRINTF("size: %" PRIX64 "\r\n", _size);
00250 
00251     return _size;
00252 }
00253 
00254 const char *FlashIAPBlockDevice::get_type() const
00255 {
00256     return "FLASHIAP";
00257 }
00258 
00259 bool FlashIAPBlockDevice::is_valid_erase(bd_addr_t addr, bd_size_t size) const
00260 {
00261     /* Calculate address alignment for the full flash */
00262     bd_addr_t base_addr = addr + (_base - _flash.get_flash_start());
00263 
00264     return (
00265                addr + size <= this->size() &&
00266                base_addr % get_erase_size(addr) == 0 &&
00267                (base_addr + size) % get_erase_size(addr + size - 1) == 0);
00268 }
00269 #endif /* DEVICE_FLASH */