mbed

Fork of mbed-dev by mbed official

Committer:
Anna Bridge
Date:
Wed Jan 17 15:23:54 2018 +0000
Revision:
181:96ed750bd169
mbed-dev libray. Release version 158

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 181:96ed750bd169 1 /* mbed Microcontroller Library
Anna Bridge 181:96ed750bd169 2 * Copyright (c) 2017 ARM Limited
Anna Bridge 181:96ed750bd169 3 *
Anna Bridge 181:96ed750bd169 4 * Licensed under the Apache License, Version 2.0 (the "License");
Anna Bridge 181:96ed750bd169 5 * you may not use this file except in compliance with the License.
Anna Bridge 181:96ed750bd169 6 * You may obtain a copy of the License at
Anna Bridge 181:96ed750bd169 7 *
Anna Bridge 181:96ed750bd169 8 * http://www.apache.org/licenses/LICENSE-2.0
Anna Bridge 181:96ed750bd169 9 *
Anna Bridge 181:96ed750bd169 10 * Unless required by applicable law or agreed to in writing, software
Anna Bridge 181:96ed750bd169 11 * distributed under the License is distributed on an "AS IS" BASIS,
Anna Bridge 181:96ed750bd169 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Anna Bridge 181:96ed750bd169 13 * See the License for the specific language governing permissions and
Anna Bridge 181:96ed750bd169 14 * limitations under the License.
Anna Bridge 181:96ed750bd169 15 */
Anna Bridge 181:96ed750bd169 16
Anna Bridge 181:96ed750bd169 17 #include "flash_api.h"
Anna Bridge 181:96ed750bd169 18 #include "mbed_critical.h"
Anna Bridge 181:96ed750bd169 19
Anna Bridge 181:96ed750bd169 20 #if DEVICE_FLASH
Anna Bridge 181:96ed750bd169 21 #include "mbed_assert.h"
Anna Bridge 181:96ed750bd169 22 #include "cmsis.h"
Anna Bridge 181:96ed750bd169 23
Anna Bridge 181:96ed750bd169 24 #ifndef FLASH_SIZE
Anna Bridge 181:96ed750bd169 25 #define FLASH_SIZE (uint32_t)(*((uint16_t *)FLASHSIZE_BASE) * 1024U)
Anna Bridge 181:96ed750bd169 26 #endif
Anna Bridge 181:96ed750bd169 27
Anna Bridge 181:96ed750bd169 28 // Minimum number of bytes to be programmed at a time
Anna Bridge 181:96ed750bd169 29 #define MIN_PROG_SIZE (4U)
Anna Bridge 181:96ed750bd169 30
Anna Bridge 181:96ed750bd169 31 static int32_t flash_unlock(void)
Anna Bridge 181:96ed750bd169 32 {
Anna Bridge 181:96ed750bd169 33 /* Allow Access to Flash control registers and user Flash */
Anna Bridge 181:96ed750bd169 34 if (HAL_FLASH_Unlock()) {
Anna Bridge 181:96ed750bd169 35 return -1;
Anna Bridge 181:96ed750bd169 36 } else {
Anna Bridge 181:96ed750bd169 37 return 0;
Anna Bridge 181:96ed750bd169 38 }
Anna Bridge 181:96ed750bd169 39 }
Anna Bridge 181:96ed750bd169 40
Anna Bridge 181:96ed750bd169 41 static int32_t flash_lock(void)
Anna Bridge 181:96ed750bd169 42 {
Anna Bridge 181:96ed750bd169 43 /* Disable the Flash option control register access (recommended to protect
Anna Bridge 181:96ed750bd169 44 the option Bytes against possible unwanted operations) */
Anna Bridge 181:96ed750bd169 45 if (HAL_FLASH_Lock()) {
Anna Bridge 181:96ed750bd169 46 return -1;
Anna Bridge 181:96ed750bd169 47 } else {
Anna Bridge 181:96ed750bd169 48 return 0;
Anna Bridge 181:96ed750bd169 49 }
Anna Bridge 181:96ed750bd169 50 }
Anna Bridge 181:96ed750bd169 51
Anna Bridge 181:96ed750bd169 52 int32_t flash_init(flash_t *obj)
Anna Bridge 181:96ed750bd169 53 {
Anna Bridge 181:96ed750bd169 54 return 0;
Anna Bridge 181:96ed750bd169 55 }
Anna Bridge 181:96ed750bd169 56
Anna Bridge 181:96ed750bd169 57 int32_t flash_free(flash_t *obj)
Anna Bridge 181:96ed750bd169 58 {
Anna Bridge 181:96ed750bd169 59 return 0;
Anna Bridge 181:96ed750bd169 60 }
Anna Bridge 181:96ed750bd169 61
Anna Bridge 181:96ed750bd169 62 int32_t flash_erase_sector(flash_t *obj, uint32_t address)
Anna Bridge 181:96ed750bd169 63 {
Anna Bridge 181:96ed750bd169 64 uint32_t PAGEError = 0;
Anna Bridge 181:96ed750bd169 65 FLASH_EraseInitTypeDef EraseInitStruct;
Anna Bridge 181:96ed750bd169 66 int32_t status = 0;
Anna Bridge 181:96ed750bd169 67
Anna Bridge 181:96ed750bd169 68 if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
Anna Bridge 181:96ed750bd169 69 return -1;
Anna Bridge 181:96ed750bd169 70 }
Anna Bridge 181:96ed750bd169 71
Anna Bridge 181:96ed750bd169 72 if (flash_unlock() != HAL_OK) {
Anna Bridge 181:96ed750bd169 73 return -1;
Anna Bridge 181:96ed750bd169 74 }
Anna Bridge 181:96ed750bd169 75
Anna Bridge 181:96ed750bd169 76 // Clear Flash status register's flags
Anna Bridge 181:96ed750bd169 77 __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR | FLASH_FLAG_OPTVERR);
Anna Bridge 181:96ed750bd169 78
Anna Bridge 181:96ed750bd169 79 /* MBED HAL erases 1 sector at a time */
Anna Bridge 181:96ed750bd169 80 /* Fill EraseInit structure*/
Anna Bridge 181:96ed750bd169 81 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
Anna Bridge 181:96ed750bd169 82 EraseInitStruct.PageAddress = address;
Anna Bridge 181:96ed750bd169 83 EraseInitStruct.NbPages = 1;
Anna Bridge 181:96ed750bd169 84
Anna Bridge 181:96ed750bd169 85 /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
Anna Bridge 181:96ed750bd169 86 you have to make sure that these data are rewritten before they are accessed during code
Anna Bridge 181:96ed750bd169 87 execution. If this cannot be done safely, it is recommended to flush the caches by setting the
Anna Bridge 181:96ed750bd169 88 DCRST and ICRST bits in the FLASH_CR register. */
Anna Bridge 181:96ed750bd169 89
Anna Bridge 181:96ed750bd169 90 if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
Anna Bridge 181:96ed750bd169 91 status = -1;
Anna Bridge 181:96ed750bd169 92 }
Anna Bridge 181:96ed750bd169 93
Anna Bridge 181:96ed750bd169 94 flash_lock();
Anna Bridge 181:96ed750bd169 95
Anna Bridge 181:96ed750bd169 96 return status;
Anna Bridge 181:96ed750bd169 97 }
Anna Bridge 181:96ed750bd169 98
Anna Bridge 181:96ed750bd169 99 int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
Anna Bridge 181:96ed750bd169 100 {
Anna Bridge 181:96ed750bd169 101 uint32_t StartAddress = 0;
Anna Bridge 181:96ed750bd169 102 int32_t status = 0;
Anna Bridge 181:96ed750bd169 103
Anna Bridge 181:96ed750bd169 104 if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
Anna Bridge 181:96ed750bd169 105 return -1;
Anna Bridge 181:96ed750bd169 106 }
Anna Bridge 181:96ed750bd169 107
Anna Bridge 181:96ed750bd169 108 if ((size % MIN_PROG_SIZE) != 0) {
Anna Bridge 181:96ed750bd169 109 return -1;
Anna Bridge 181:96ed750bd169 110 }
Anna Bridge 181:96ed750bd169 111
Anna Bridge 181:96ed750bd169 112 if (flash_unlock() != HAL_OK) {
Anna Bridge 181:96ed750bd169 113 return -1;
Anna Bridge 181:96ed750bd169 114 }
Anna Bridge 181:96ed750bd169 115
Anna Bridge 181:96ed750bd169 116 /* Program the user Flash area word by word */
Anna Bridge 181:96ed750bd169 117 StartAddress = address;
Anna Bridge 181:96ed750bd169 118
Anna Bridge 181:96ed750bd169 119 /* HW needs an aligned address to program flash, which data parameter doesn't ensure */
Anna Bridge 181:96ed750bd169 120 if ((uint32_t) data % 4 != 0) {
Anna Bridge 181:96ed750bd169 121
Anna Bridge 181:96ed750bd169 122 volatile uint32_t data32;
Anna Bridge 181:96ed750bd169 123 while (address < (StartAddress + size) && (status == 0)) {
Anna Bridge 181:96ed750bd169 124 for (uint8_t i = 0; i < MIN_PROG_SIZE; i++) {
Anna Bridge 181:96ed750bd169 125 *(((uint8_t *) &data32) + i) = *(data + i);
Anna Bridge 181:96ed750bd169 126 }
Anna Bridge 181:96ed750bd169 127
Anna Bridge 181:96ed750bd169 128 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data32) == HAL_OK) {
Anna Bridge 181:96ed750bd169 129 address = address + MIN_PROG_SIZE;
Anna Bridge 181:96ed750bd169 130 data = data + MIN_PROG_SIZE;
Anna Bridge 181:96ed750bd169 131 } else {
Anna Bridge 181:96ed750bd169 132 status = -1;
Anna Bridge 181:96ed750bd169 133 }
Anna Bridge 181:96ed750bd169 134 }
Anna Bridge 181:96ed750bd169 135 } else { /* case where data is aligned, so let's avoid any copy */
Anna Bridge 181:96ed750bd169 136 while ((address < (StartAddress + size)) && (status == 0)) {
Anna Bridge 181:96ed750bd169 137 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, *((uint32_t*) data)) == HAL_OK) {
Anna Bridge 181:96ed750bd169 138 address = address + MIN_PROG_SIZE;
Anna Bridge 181:96ed750bd169 139 data = data + MIN_PROG_SIZE;
Anna Bridge 181:96ed750bd169 140 } else {
Anna Bridge 181:96ed750bd169 141 status = -1;
Anna Bridge 181:96ed750bd169 142 }
Anna Bridge 181:96ed750bd169 143 }
Anna Bridge 181:96ed750bd169 144 }
Anna Bridge 181:96ed750bd169 145
Anna Bridge 181:96ed750bd169 146 flash_lock();
Anna Bridge 181:96ed750bd169 147
Anna Bridge 181:96ed750bd169 148 return status;
Anna Bridge 181:96ed750bd169 149 }
Anna Bridge 181:96ed750bd169 150
Anna Bridge 181:96ed750bd169 151 uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
Anna Bridge 181:96ed750bd169 152 {
Anna Bridge 181:96ed750bd169 153 if (!(IS_FLASH_PROGRAM_ADDRESS(address))) {
Anna Bridge 181:96ed750bd169 154 return MBED_FLASH_INVALID_SIZE;
Anna Bridge 181:96ed750bd169 155 } else {
Anna Bridge 181:96ed750bd169 156 return FLASH_PAGE_SIZE;
Anna Bridge 181:96ed750bd169 157 }
Anna Bridge 181:96ed750bd169 158 }
Anna Bridge 181:96ed750bd169 159
Anna Bridge 181:96ed750bd169 160 uint32_t flash_get_page_size(const flash_t *obj)
Anna Bridge 181:96ed750bd169 161 {
Anna Bridge 181:96ed750bd169 162 return MIN_PROG_SIZE;
Anna Bridge 181:96ed750bd169 163 }
Anna Bridge 181:96ed750bd169 164
Anna Bridge 181:96ed750bd169 165 uint32_t flash_get_start_address(const flash_t *obj)
Anna Bridge 181:96ed750bd169 166 {
Anna Bridge 181:96ed750bd169 167 return FLASH_BASE;
Anna Bridge 181:96ed750bd169 168 }
Anna Bridge 181:96ed750bd169 169
Anna Bridge 181:96ed750bd169 170 uint32_t flash_get_size(const flash_t *obj)
Anna Bridge 181:96ed750bd169 171 {
Anna Bridge 181:96ed750bd169 172 return FLASH_SIZE;
Anna Bridge 181:96ed750bd169 173 }
Anna Bridge 181:96ed750bd169 174
Anna Bridge 181:96ed750bd169 175 #endif