test

Committer:
elijahsj
Date:
Mon Nov 09 00:02:47 2020 -0500
Revision:
1:8a094db1347f
test

Who changed what in which revision?

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