mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

UserRevisionLine numberNew contents of line
be_bryan 0:b74591d5ab33 1 /* mbed Microcontroller Library
be_bryan 0:b74591d5ab33 2 * Copyright (c) 2017 ARM Limited
be_bryan 0:b74591d5ab33 3 *
be_bryan 0:b74591d5ab33 4 * Licensed under the Apache License, Version 2.0 (the "License");
be_bryan 0:b74591d5ab33 5 * you may not use this file except in compliance with the License.
be_bryan 0:b74591d5ab33 6 * You may obtain a copy of the License at
be_bryan 0:b74591d5ab33 7 *
be_bryan 0:b74591d5ab33 8 * http://www.apache.org/licenses/LICENSE-2.0
be_bryan 0:b74591d5ab33 9 *
be_bryan 0:b74591d5ab33 10 * Unless required by applicable law or agreed to in writing, software
be_bryan 0:b74591d5ab33 11 * distributed under the License is distributed on an "AS IS" BASIS,
be_bryan 0:b74591d5ab33 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
be_bryan 0:b74591d5ab33 13 * See the License for the specific language governing permissions and
be_bryan 0:b74591d5ab33 14 * limitations under the License.
be_bryan 0:b74591d5ab33 15 */
be_bryan 0:b74591d5ab33 16
be_bryan 0:b74591d5ab33 17 #include "flash_api.h"
be_bryan 0:b74591d5ab33 18 #include "mbed_critical.h"
be_bryan 0:b74591d5ab33 19
be_bryan 0:b74591d5ab33 20 #if DEVICE_FLASH
be_bryan 0:b74591d5ab33 21 #include "mbed_assert.h"
be_bryan 0:b74591d5ab33 22 #include "cmsis.h"
be_bryan 0:b74591d5ab33 23
be_bryan 0:b74591d5ab33 24 /**
be_bryan 0:b74591d5ab33 25 * @brief Gets the page of a given address
be_bryan 0:b74591d5ab33 26 * @param Addr: Address of the FLASH Memory
be_bryan 0:b74591d5ab33 27 * @retval The page of a given address
be_bryan 0:b74591d5ab33 28 */
be_bryan 0:b74591d5ab33 29 static uint32_t GetPage(uint32_t Addr)
be_bryan 0:b74591d5ab33 30 {
be_bryan 0:b74591d5ab33 31 uint32_t page = 0;
be_bryan 0:b74591d5ab33 32
be_bryan 0:b74591d5ab33 33 if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
be_bryan 0:b74591d5ab33 34 /* Bank 1 */
be_bryan 0:b74591d5ab33 35 page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
be_bryan 0:b74591d5ab33 36 } else {
be_bryan 0:b74591d5ab33 37 /* Bank 2 */
be_bryan 0:b74591d5ab33 38 page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
be_bryan 0:b74591d5ab33 39 }
be_bryan 0:b74591d5ab33 40
be_bryan 0:b74591d5ab33 41 return page;
be_bryan 0:b74591d5ab33 42 }
be_bryan 0:b74591d5ab33 43
be_bryan 0:b74591d5ab33 44 /**
be_bryan 0:b74591d5ab33 45 * @brief Gets the bank of a given address
be_bryan 0:b74591d5ab33 46 * @param Addr: Address of the FLASH Memory
be_bryan 0:b74591d5ab33 47 * @retval The bank of a given address
be_bryan 0:b74591d5ab33 48 */
be_bryan 0:b74591d5ab33 49 static uint32_t GetBank(uint32_t Addr)
be_bryan 0:b74591d5ab33 50 {
be_bryan 0:b74591d5ab33 51 uint32_t bank = 0;
be_bryan 0:b74591d5ab33 52 #if defined(SYSCFG_MEMRMP_FB_MODE)
be_bryan 0:b74591d5ab33 53 if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0) {
be_bryan 0:b74591d5ab33 54 /* No Bank swap */
be_bryan 0:b74591d5ab33 55 if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
be_bryan 0:b74591d5ab33 56 bank = FLASH_BANK_1;
be_bryan 0:b74591d5ab33 57 } else {
be_bryan 0:b74591d5ab33 58 bank = FLASH_BANK_2;
be_bryan 0:b74591d5ab33 59 }
be_bryan 0:b74591d5ab33 60 } else {
be_bryan 0:b74591d5ab33 61 /* Bank swap */
be_bryan 0:b74591d5ab33 62 if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
be_bryan 0:b74591d5ab33 63 bank = FLASH_BANK_2;
be_bryan 0:b74591d5ab33 64 } else {
be_bryan 0:b74591d5ab33 65 bank = FLASH_BANK_1;
be_bryan 0:b74591d5ab33 66 }
be_bryan 0:b74591d5ab33 67 }
be_bryan 0:b74591d5ab33 68 #else
be_bryan 0:b74591d5ab33 69 /* Device like L432KC */
be_bryan 0:b74591d5ab33 70 bank = FLASH_BANK_1;
be_bryan 0:b74591d5ab33 71 #endif
be_bryan 0:b74591d5ab33 72
be_bryan 0:b74591d5ab33 73 return bank;
be_bryan 0:b74591d5ab33 74 }
be_bryan 0:b74591d5ab33 75
be_bryan 0:b74591d5ab33 76 /** Initialize the flash peripheral and the flash_t object
be_bryan 0:b74591d5ab33 77 *
be_bryan 0:b74591d5ab33 78 * @param obj The flash object
be_bryan 0:b74591d5ab33 79 * @return 0 for success, -1 for error
be_bryan 0:b74591d5ab33 80 */
be_bryan 0:b74591d5ab33 81 int32_t flash_init(flash_t *obj)
be_bryan 0:b74591d5ab33 82 {
be_bryan 0:b74591d5ab33 83 return 0;
be_bryan 0:b74591d5ab33 84 }
be_bryan 0:b74591d5ab33 85
be_bryan 0:b74591d5ab33 86 /** Uninitialize the flash peripheral and the flash_t object
be_bryan 0:b74591d5ab33 87 *
be_bryan 0:b74591d5ab33 88 * @param obj The flash object
be_bryan 0:b74591d5ab33 89 * @return 0 for success, -1 for error
be_bryan 0:b74591d5ab33 90 */
be_bryan 0:b74591d5ab33 91 int32_t flash_free(flash_t *obj)
be_bryan 0:b74591d5ab33 92 {
be_bryan 0:b74591d5ab33 93 return 0;
be_bryan 0:b74591d5ab33 94 }
be_bryan 0:b74591d5ab33 95
be_bryan 0:b74591d5ab33 96 static int32_t flash_unlock(void)
be_bryan 0:b74591d5ab33 97 {
be_bryan 0:b74591d5ab33 98 /* Allow Access to Flash control registers and user Falsh */
be_bryan 0:b74591d5ab33 99 if (HAL_FLASH_Unlock()) {
be_bryan 0:b74591d5ab33 100 return -1;
be_bryan 0:b74591d5ab33 101 } else {
be_bryan 0:b74591d5ab33 102 return 0;
be_bryan 0:b74591d5ab33 103 }
be_bryan 0:b74591d5ab33 104 }
be_bryan 0:b74591d5ab33 105
be_bryan 0:b74591d5ab33 106 static int32_t flash_lock(void)
be_bryan 0:b74591d5ab33 107 {
be_bryan 0:b74591d5ab33 108 /* Disable the Flash option control register access (recommended to protect
be_bryan 0:b74591d5ab33 109 the option Bytes against possible unwanted operations) */
be_bryan 0:b74591d5ab33 110 if (HAL_FLASH_Lock()) {
be_bryan 0:b74591d5ab33 111 return -1;
be_bryan 0:b74591d5ab33 112 } else {
be_bryan 0:b74591d5ab33 113 return 0;
be_bryan 0:b74591d5ab33 114 }
be_bryan 0:b74591d5ab33 115 }
be_bryan 0:b74591d5ab33 116
be_bryan 0:b74591d5ab33 117 /** Erase one sector starting at defined address
be_bryan 0:b74591d5ab33 118 *
be_bryan 0:b74591d5ab33 119 * The address should be at sector boundary. This function does not do any check for address alignments
be_bryan 0:b74591d5ab33 120 * @param obj The flash object
be_bryan 0:b74591d5ab33 121 * @param address The sector starting address
be_bryan 0:b74591d5ab33 122 * @return 0 for success, -1 for error
be_bryan 0:b74591d5ab33 123 */
be_bryan 0:b74591d5ab33 124 int32_t flash_erase_sector(flash_t *obj, uint32_t address)
be_bryan 0:b74591d5ab33 125 {
be_bryan 0:b74591d5ab33 126 uint32_t FirstPage = 0, BankNumber = 0;
be_bryan 0:b74591d5ab33 127 uint32_t PAGEError = 0;
be_bryan 0:b74591d5ab33 128 FLASH_EraseInitTypeDef EraseInitStruct;
be_bryan 0:b74591d5ab33 129 int32_t status = 0;
be_bryan 0:b74591d5ab33 130
be_bryan 0:b74591d5ab33 131 if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
be_bryan 0:b74591d5ab33 132
be_bryan 0:b74591d5ab33 133 return -1;
be_bryan 0:b74591d5ab33 134 }
be_bryan 0:b74591d5ab33 135
be_bryan 0:b74591d5ab33 136 if (flash_unlock() != HAL_OK) {
be_bryan 0:b74591d5ab33 137 return -1;
be_bryan 0:b74591d5ab33 138 }
be_bryan 0:b74591d5ab33 139
be_bryan 0:b74591d5ab33 140 /* Clear OPTVERR bit set on virgin samples */
be_bryan 0:b74591d5ab33 141 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
be_bryan 0:b74591d5ab33 142 /* Get the 1st page to erase */
be_bryan 0:b74591d5ab33 143 FirstPage = GetPage(address);
be_bryan 0:b74591d5ab33 144 /* MBED HAL erases 1 page / sector at a time */
be_bryan 0:b74591d5ab33 145 /* Get the bank */
be_bryan 0:b74591d5ab33 146 BankNumber = GetBank(address);
be_bryan 0:b74591d5ab33 147 /* Fill EraseInit structure*/
be_bryan 0:b74591d5ab33 148 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
be_bryan 0:b74591d5ab33 149 EraseInitStruct.Banks = BankNumber;
be_bryan 0:b74591d5ab33 150 EraseInitStruct.Page = FirstPage;
be_bryan 0:b74591d5ab33 151 EraseInitStruct.NbPages = 1;
be_bryan 0:b74591d5ab33 152
be_bryan 0:b74591d5ab33 153 /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
be_bryan 0:b74591d5ab33 154 you have to make sure that these data are rewritten before they are accessed during code
be_bryan 0:b74591d5ab33 155 execution. If this cannot be done safely, it is recommended to flush the caches by setting the
be_bryan 0:b74591d5ab33 156 DCRST and ICRST bits in the FLASH_CR register. */
be_bryan 0:b74591d5ab33 157
be_bryan 0:b74591d5ab33 158 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
be_bryan 0:b74591d5ab33 159 status = -1;
be_bryan 0:b74591d5ab33 160 }
be_bryan 0:b74591d5ab33 161
be_bryan 0:b74591d5ab33 162 flash_lock();
be_bryan 0:b74591d5ab33 163
be_bryan 0:b74591d5ab33 164 return status;
be_bryan 0:b74591d5ab33 165 }
be_bryan 0:b74591d5ab33 166
be_bryan 0:b74591d5ab33 167 /** Program one page starting at defined address
be_bryan 0:b74591d5ab33 168 *
be_bryan 0:b74591d5ab33 169 * The page should be at page boundary, should not cross multiple sectors.
be_bryan 0:b74591d5ab33 170 * This function does not do any check for address alignments or if size
be_bryan 0:b74591d5ab33 171 * is aligned to a page size.
be_bryan 0:b74591d5ab33 172 * @param obj The flash object
be_bryan 0:b74591d5ab33 173 * @param address The sector starting address
be_bryan 0:b74591d5ab33 174 * @param data The data buffer to be programmed
be_bryan 0:b74591d5ab33 175 * @param size The number of bytes to program
be_bryan 0:b74591d5ab33 176 * @return 0 for success, -1 for error
be_bryan 0:b74591d5ab33 177 */
be_bryan 0:b74591d5ab33 178 int32_t flash_program_page(flash_t *obj, uint32_t address,
be_bryan 0:b74591d5ab33 179 const uint8_t *data, uint32_t size)
be_bryan 0:b74591d5ab33 180 {
be_bryan 0:b74591d5ab33 181 uint32_t StartAddress = 0;
be_bryan 0:b74591d5ab33 182 int32_t status = 0;
be_bryan 0:b74591d5ab33 183
be_bryan 0:b74591d5ab33 184 if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
be_bryan 0:b74591d5ab33 185 return -1;
be_bryan 0:b74591d5ab33 186 }
be_bryan 0:b74591d5ab33 187
be_bryan 0:b74591d5ab33 188 if ((size % 8) != 0) {
be_bryan 0:b74591d5ab33 189 /* L4 flash devices can only be programmed 64bits/8 bytes at a time */
be_bryan 0:b74591d5ab33 190 return -1;
be_bryan 0:b74591d5ab33 191 }
be_bryan 0:b74591d5ab33 192
be_bryan 0:b74591d5ab33 193 if (flash_unlock() != HAL_OK) {
be_bryan 0:b74591d5ab33 194 return -1;
be_bryan 0:b74591d5ab33 195 }
be_bryan 0:b74591d5ab33 196
be_bryan 0:b74591d5ab33 197 /* Program the user Flash area word by word */
be_bryan 0:b74591d5ab33 198 StartAddress = address;
be_bryan 0:b74591d5ab33 199
be_bryan 0:b74591d5ab33 200 /* HW needs an aligned address to program flash, which data
be_bryan 0:b74591d5ab33 201 * parameters doesn't ensure */
be_bryan 0:b74591d5ab33 202 if ((uint32_t) data % 4 != 0) {
be_bryan 0:b74591d5ab33 203 volatile uint64_t data64;
be_bryan 0:b74591d5ab33 204 while ((address < (StartAddress + size)) && (status == 0)) {
be_bryan 0:b74591d5ab33 205 for (uint8_t i =0; i < 8; i++) {
be_bryan 0:b74591d5ab33 206 *(((uint8_t *) &data64) + i) = *(data + i);
be_bryan 0:b74591d5ab33 207 }
be_bryan 0:b74591d5ab33 208
be_bryan 0:b74591d5ab33 209 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data64)
be_bryan 0:b74591d5ab33 210 == HAL_OK) {
be_bryan 0:b74591d5ab33 211 address = address + 8;
be_bryan 0:b74591d5ab33 212 data = data + 8;
be_bryan 0:b74591d5ab33 213 } else {
be_bryan 0:b74591d5ab33 214 status = -1;
be_bryan 0:b74591d5ab33 215 }
be_bryan 0:b74591d5ab33 216 }
be_bryan 0:b74591d5ab33 217 } else { /* case where data is aligned, so let's avoid any copy */
be_bryan 0:b74591d5ab33 218 while ((address < (StartAddress + size)) && (status == 0)) {
be_bryan 0:b74591d5ab33 219 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address,
be_bryan 0:b74591d5ab33 220 *((uint64_t*) data))
be_bryan 0:b74591d5ab33 221 == HAL_OK) {
be_bryan 0:b74591d5ab33 222 address = address + 8;
be_bryan 0:b74591d5ab33 223 data = data + 8;
be_bryan 0:b74591d5ab33 224 } else {
be_bryan 0:b74591d5ab33 225 status = -1;
be_bryan 0:b74591d5ab33 226 }
be_bryan 0:b74591d5ab33 227 }
be_bryan 0:b74591d5ab33 228 }
be_bryan 0:b74591d5ab33 229
be_bryan 0:b74591d5ab33 230 flash_lock();
be_bryan 0:b74591d5ab33 231
be_bryan 0:b74591d5ab33 232 return status;
be_bryan 0:b74591d5ab33 233 }
be_bryan 0:b74591d5ab33 234
be_bryan 0:b74591d5ab33 235 /** Get sector size
be_bryan 0:b74591d5ab33 236 *
be_bryan 0:b74591d5ab33 237 * @param obj The flash object
be_bryan 0:b74591d5ab33 238 * @param address The sector starting address
be_bryan 0:b74591d5ab33 239 * @return The size of a sector
be_bryan 0:b74591d5ab33 240 */
be_bryan 0:b74591d5ab33 241 uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address) {
be_bryan 0:b74591d5ab33 242 /* considering 1 sector = 1 page */
be_bryan 0:b74591d5ab33 243 if ((address >= (FLASH_BASE + FLASH_SIZE)) || (address < FLASH_BASE)) {
be_bryan 0:b74591d5ab33 244 return MBED_FLASH_INVALID_SIZE;
be_bryan 0:b74591d5ab33 245 } else {
be_bryan 0:b74591d5ab33 246 return FLASH_PAGE_SIZE;
be_bryan 0:b74591d5ab33 247 }
be_bryan 0:b74591d5ab33 248 }
be_bryan 0:b74591d5ab33 249
be_bryan 0:b74591d5ab33 250 /** Get page size
be_bryan 0:b74591d5ab33 251 *
be_bryan 0:b74591d5ab33 252 * @param obj The flash object
be_bryan 0:b74591d5ab33 253 * @param address The page starting address
be_bryan 0:b74591d5ab33 254 * @return The size of a page
be_bryan 0:b74591d5ab33 255 */
be_bryan 0:b74591d5ab33 256 uint32_t flash_get_page_size(const flash_t *obj) {
be_bryan 0:b74591d5ab33 257 /* Page size is the minimum programable size, which 8 bytes */
be_bryan 0:b74591d5ab33 258 return 8;
be_bryan 0:b74591d5ab33 259 }
be_bryan 0:b74591d5ab33 260
be_bryan 0:b74591d5ab33 261 /** Get start address for the flash region
be_bryan 0:b74591d5ab33 262 *
be_bryan 0:b74591d5ab33 263 * @param obj The flash object
be_bryan 0:b74591d5ab33 264 * @return The start address for the flash region
be_bryan 0:b74591d5ab33 265 */
be_bryan 0:b74591d5ab33 266 uint32_t flash_get_start_address(const flash_t *obj) {
be_bryan 0:b74591d5ab33 267 return FLASH_BASE;
be_bryan 0:b74591d5ab33 268 }
be_bryan 0:b74591d5ab33 269
be_bryan 0:b74591d5ab33 270 /** Get the flash region size
be_bryan 0:b74591d5ab33 271 *
be_bryan 0:b74591d5ab33 272 * @param obj The flash object
be_bryan 0:b74591d5ab33 273 * @return The flash region size
be_bryan 0:b74591d5ab33 274 */
be_bryan 0:b74591d5ab33 275 uint32_t flash_get_size(const flash_t *obj) {
be_bryan 0:b74591d5ab33 276 return FLASH_SIZE;
be_bryan 0:b74591d5ab33 277 }
be_bryan 0:b74591d5ab33 278
be_bryan 0:b74591d5ab33 279 #endif