RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /* mbed Microcontroller Library
kevman 0:38ceb79fef03 2 * Copyright (c) 2017 ARM Limited
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
kevman 0:38ceb79fef03 5 * of this software and associated documentation files (the "Software"), to deal
kevman 0:38ceb79fef03 6 * in the Software without restriction, including without limitation the rights
kevman 0:38ceb79fef03 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
kevman 0:38ceb79fef03 8 * copies of the Software, and to permit persons to whom the Software is
kevman 0:38ceb79fef03 9 * furnished to do so, subject to the following conditions:
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * The above copyright notice and this permission notice shall be included in
kevman 0:38ceb79fef03 12 * all copies or substantial portions of the Software.
kevman 0:38ceb79fef03 13 *
kevman 0:38ceb79fef03 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
kevman 0:38ceb79fef03 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
kevman 0:38ceb79fef03 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
kevman 0:38ceb79fef03 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
kevman 0:38ceb79fef03 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kevman 0:38ceb79fef03 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
kevman 0:38ceb79fef03 20 * SOFTWARE.
kevman 0:38ceb79fef03 21 */
kevman 0:38ceb79fef03 22
kevman 0:38ceb79fef03 23 #include <stdio.h>
kevman 0:38ceb79fef03 24 #include <string.h>
kevman 0:38ceb79fef03 25 #include <algorithm>
kevman 0:38ceb79fef03 26 #include "FlashIAP.h"
kevman 0:38ceb79fef03 27 #include "platform/mbed_assert.h"
kevman 0:38ceb79fef03 28
kevman 0:38ceb79fef03 29
kevman 0:38ceb79fef03 30 #ifdef DEVICE_FLASH
kevman 0:38ceb79fef03 31
kevman 0:38ceb79fef03 32 namespace mbed {
kevman 0:38ceb79fef03 33
kevman 0:38ceb79fef03 34 SingletonPtr<PlatformMutex> FlashIAP::_mutex;
kevman 0:38ceb79fef03 35
kevman 0:38ceb79fef03 36 static inline bool is_aligned(uint32_t number, uint32_t alignment)
kevman 0:38ceb79fef03 37 {
kevman 0:38ceb79fef03 38 if ((number % alignment) != 0) {
kevman 0:38ceb79fef03 39 return false;
kevman 0:38ceb79fef03 40 } else {
kevman 0:38ceb79fef03 41 return true;
kevman 0:38ceb79fef03 42 }
kevman 0:38ceb79fef03 43 }
kevman 0:38ceb79fef03 44
kevman 0:38ceb79fef03 45 FlashIAP::FlashIAP()
kevman 0:38ceb79fef03 46 {
kevman 0:38ceb79fef03 47
kevman 0:38ceb79fef03 48 }
kevman 0:38ceb79fef03 49
kevman 0:38ceb79fef03 50 FlashIAP::~FlashIAP()
kevman 0:38ceb79fef03 51 {
kevman 0:38ceb79fef03 52
kevman 0:38ceb79fef03 53 }
kevman 0:38ceb79fef03 54
kevman 0:38ceb79fef03 55 int FlashIAP::init()
kevman 0:38ceb79fef03 56 {
kevman 0:38ceb79fef03 57 int ret = 0;
kevman 0:38ceb79fef03 58 _mutex->lock();
kevman 0:38ceb79fef03 59 if (flash_init(&_flash)) {
kevman 0:38ceb79fef03 60 ret = -1;
kevman 0:38ceb79fef03 61 }
kevman 0:38ceb79fef03 62 uint32_t page_size = get_page_size();
kevman 0:38ceb79fef03 63 _page_buf = new uint8_t[page_size];
kevman 0:38ceb79fef03 64
kevman 0:38ceb79fef03 65 _mutex->unlock();
kevman 0:38ceb79fef03 66 return ret;
kevman 0:38ceb79fef03 67 }
kevman 0:38ceb79fef03 68
kevman 0:38ceb79fef03 69 int FlashIAP::deinit()
kevman 0:38ceb79fef03 70 {
kevman 0:38ceb79fef03 71 int ret = 0;
kevman 0:38ceb79fef03 72 _mutex->lock();
kevman 0:38ceb79fef03 73 if (flash_free(&_flash)) {
kevman 0:38ceb79fef03 74 ret = -1;
kevman 0:38ceb79fef03 75 }
kevman 0:38ceb79fef03 76 delete[] _page_buf;
kevman 0:38ceb79fef03 77 _mutex->unlock();
kevman 0:38ceb79fef03 78 return ret;
kevman 0:38ceb79fef03 79 }
kevman 0:38ceb79fef03 80
kevman 0:38ceb79fef03 81
kevman 0:38ceb79fef03 82 int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size)
kevman 0:38ceb79fef03 83 {
kevman 0:38ceb79fef03 84 int32_t ret = -1;
kevman 0:38ceb79fef03 85 _mutex->lock();
kevman 0:38ceb79fef03 86 ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
kevman 0:38ceb79fef03 87 _mutex->unlock();
kevman 0:38ceb79fef03 88 return ret;
kevman 0:38ceb79fef03 89 }
kevman 0:38ceb79fef03 90
kevman 0:38ceb79fef03 91 int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
kevman 0:38ceb79fef03 92 {
kevman 0:38ceb79fef03 93 uint32_t page_size = get_page_size();
kevman 0:38ceb79fef03 94 uint32_t flash_size = flash_get_size(&_flash);
kevman 0:38ceb79fef03 95 uint32_t flash_start_addr = flash_get_start_address(&_flash);
kevman 0:38ceb79fef03 96 uint32_t chunk, prog_size;
kevman 0:38ceb79fef03 97 const uint8_t *buf = (uint8_t *) buffer;
kevman 0:38ceb79fef03 98 const uint8_t *prog_buf;
kevman 0:38ceb79fef03 99
kevman 0:38ceb79fef03 100 // addr should be aligned to page size
kevman 0:38ceb79fef03 101 if (!is_aligned(addr, page_size) || (!buffer) ||
kevman 0:38ceb79fef03 102 ((addr + size) > (flash_start_addr + flash_size))) {
kevman 0:38ceb79fef03 103 return -1;
kevman 0:38ceb79fef03 104 }
kevman 0:38ceb79fef03 105
kevman 0:38ceb79fef03 106 int ret = 0;
kevman 0:38ceb79fef03 107 _mutex->lock();
kevman 0:38ceb79fef03 108 while (size) {
kevman 0:38ceb79fef03 109 uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
kevman 0:38ceb79fef03 110 bool unaligned_src = (((size_t) buf / sizeof(uint32_t) * sizeof(uint32_t)) != (size_t) buf);
kevman 0:38ceb79fef03 111 chunk = std::min(current_sector_size - (addr % current_sector_size), size);
kevman 0:38ceb79fef03 112 // Need to use the internal page buffer in any of these two cases:
kevman 0:38ceb79fef03 113 // 1. Size is not page aligned
kevman 0:38ceb79fef03 114 // 2. Source buffer is not aligned to uint32_t. This is not supported by many targets (although
kevman 0:38ceb79fef03 115 // the pointer they accept is of uint8_t).
kevman 0:38ceb79fef03 116 if (unaligned_src || (chunk < page_size)) {
kevman 0:38ceb79fef03 117 chunk = std::min(chunk, page_size);
kevman 0:38ceb79fef03 118 memcpy(_page_buf, buf, chunk);
kevman 0:38ceb79fef03 119 if (chunk < page_size) {
kevman 0:38ceb79fef03 120 memset(_page_buf + chunk, 0xFF, page_size - chunk);
kevman 0:38ceb79fef03 121 }
kevman 0:38ceb79fef03 122 prog_buf = _page_buf;
kevman 0:38ceb79fef03 123 prog_size = page_size;
kevman 0:38ceb79fef03 124 } else {
kevman 0:38ceb79fef03 125 chunk = chunk / page_size * page_size;
kevman 0:38ceb79fef03 126 prog_buf = buf;
kevman 0:38ceb79fef03 127 prog_size = chunk;
kevman 0:38ceb79fef03 128 }
kevman 0:38ceb79fef03 129 if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
kevman 0:38ceb79fef03 130 ret = -1;
kevman 0:38ceb79fef03 131 break;
kevman 0:38ceb79fef03 132 }
kevman 0:38ceb79fef03 133 size -= chunk;
kevman 0:38ceb79fef03 134 addr += chunk;
kevman 0:38ceb79fef03 135 buf += chunk;
kevman 0:38ceb79fef03 136 }
kevman 0:38ceb79fef03 137 _mutex->unlock();
kevman 0:38ceb79fef03 138
kevman 0:38ceb79fef03 139 return ret;
kevman 0:38ceb79fef03 140 }
kevman 0:38ceb79fef03 141
kevman 0:38ceb79fef03 142 bool FlashIAP::is_aligned_to_sector(uint32_t addr, uint32_t size)
kevman 0:38ceb79fef03 143 {
kevman 0:38ceb79fef03 144 uint32_t current_sector_size = flash_get_sector_size(&_flash, addr);
kevman 0:38ceb79fef03 145 if (!is_aligned(size, current_sector_size) ||
kevman 0:38ceb79fef03 146 !is_aligned(addr, current_sector_size)) {
kevman 0:38ceb79fef03 147 return false;
kevman 0:38ceb79fef03 148 } else {
kevman 0:38ceb79fef03 149 return true;
kevman 0:38ceb79fef03 150 }
kevman 0:38ceb79fef03 151 }
kevman 0:38ceb79fef03 152
kevman 0:38ceb79fef03 153 int FlashIAP::erase(uint32_t addr, uint32_t size)
kevman 0:38ceb79fef03 154 {
kevman 0:38ceb79fef03 155 uint32_t current_sector_size;
kevman 0:38ceb79fef03 156 uint32_t flash_size = flash_get_size(&_flash);
kevman 0:38ceb79fef03 157 uint32_t flash_start_addr = flash_get_start_address(&_flash);
kevman 0:38ceb79fef03 158 uint32_t flash_end_addr = flash_start_addr + flash_size;
kevman 0:38ceb79fef03 159 uint32_t erase_end_addr = addr + size;
kevman 0:38ceb79fef03 160
kevman 0:38ceb79fef03 161 if (erase_end_addr > flash_end_addr) {
kevman 0:38ceb79fef03 162 return -1;
kevman 0:38ceb79fef03 163 } else if (erase_end_addr < flash_end_addr) {
kevman 0:38ceb79fef03 164 uint32_t following_sector_size = flash_get_sector_size(&_flash, erase_end_addr);
kevman 0:38ceb79fef03 165 if (!is_aligned(erase_end_addr, following_sector_size)) {
kevman 0:38ceb79fef03 166 return -1;
kevman 0:38ceb79fef03 167 }
kevman 0:38ceb79fef03 168 }
kevman 0:38ceb79fef03 169
kevman 0:38ceb79fef03 170 int32_t ret = 0;
kevman 0:38ceb79fef03 171 _mutex->lock();
kevman 0:38ceb79fef03 172 while (size) {
kevman 0:38ceb79fef03 173 ret = flash_erase_sector(&_flash, addr);
kevman 0:38ceb79fef03 174 if (ret != 0) {
kevman 0:38ceb79fef03 175 ret = -1;
kevman 0:38ceb79fef03 176 break;
kevman 0:38ceb79fef03 177 }
kevman 0:38ceb79fef03 178 current_sector_size = flash_get_sector_size(&_flash, addr);
kevman 0:38ceb79fef03 179 size -= current_sector_size;
kevman 0:38ceb79fef03 180 addr += current_sector_size;
kevman 0:38ceb79fef03 181 }
kevman 0:38ceb79fef03 182 _mutex->unlock();
kevman 0:38ceb79fef03 183 return ret;
kevman 0:38ceb79fef03 184 }
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 uint32_t FlashIAP::get_page_size() const
kevman 0:38ceb79fef03 187 {
kevman 0:38ceb79fef03 188 return flash_get_page_size(&_flash);
kevman 0:38ceb79fef03 189 }
kevman 0:38ceb79fef03 190
kevman 0:38ceb79fef03 191 uint32_t FlashIAP::get_sector_size(uint32_t addr) const
kevman 0:38ceb79fef03 192 {
kevman 0:38ceb79fef03 193 return flash_get_sector_size(&_flash, addr);
kevman 0:38ceb79fef03 194 }
kevman 0:38ceb79fef03 195
kevman 0:38ceb79fef03 196 uint32_t FlashIAP::get_flash_start() const
kevman 0:38ceb79fef03 197 {
kevman 0:38ceb79fef03 198 return flash_get_start_address(&_flash);
kevman 0:38ceb79fef03 199 }
kevman 0:38ceb79fef03 200
kevman 0:38ceb79fef03 201 uint32_t FlashIAP::get_flash_size() const
kevman 0:38ceb79fef03 202 {
kevman 0:38ceb79fef03 203 return flash_get_size(&_flash);
kevman 0:38ceb79fef03 204 }
kevman 0:38ceb79fef03 205
kevman 0:38ceb79fef03 206 }
kevman 0:38ceb79fef03 207
kevman 0:38ceb79fef03 208 #endif