mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 160:d5399cc887bb 1 /* mbed Microcontroller Library
<> 160:d5399cc887bb 2 * Copyright (c) 2017 ARM Limited
AnnaBridge 189:f392fc9709a3 3 * SPDX-License-Identifier: Apache-2.0
<> 160:d5399cc887bb 4 *
<> 160:d5399cc887bb 5 * Licensed under the Apache License, Version 2.0 (the "License");
<> 160:d5399cc887bb 6 * you may not use this file except in compliance with the License.
<> 160:d5399cc887bb 7 * You may obtain a copy of the License at
<> 160:d5399cc887bb 8 *
<> 160:d5399cc887bb 9 * http://www.apache.org/licenses/LICENSE-2.0
<> 160:d5399cc887bb 10 *
<> 160:d5399cc887bb 11 * Unless required by applicable law or agreed to in writing, software
<> 160:d5399cc887bb 12 * distributed under the License is distributed on an "AS IS" BASIS,
<> 160:d5399cc887bb 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<> 160:d5399cc887bb 14 * See the License for the specific language governing permissions and
<> 160:d5399cc887bb 15 * limitations under the License.
<> 160:d5399cc887bb 16 */
<> 160:d5399cc887bb 17
<> 160:d5399cc887bb 18 #include "flash_api.h"
<> 160:d5399cc887bb 19 #include "flash_data.h"
<> 160:d5399cc887bb 20 #include "mbed_critical.h"
Anna Bridge 186:707f6e361f3e 21 #include "mbed_toolchain.h"
Anna Bridge 186:707f6e361f3e 22
Anna Bridge 186:707f6e361f3e 23 #ifndef DOMAIN_NS
Anna Bridge 186:707f6e361f3e 24
Anna Bridge 186:707f6e361f3e 25 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 26 #include <arm_cmse.h>
Anna Bridge 186:707f6e361f3e 27 #endif
<> 160:d5399cc887bb 28
<> 160:d5399cc887bb 29 #define MBED_FLASH_ALGO_ERASE 1UL
<> 160:d5399cc887bb 30 #define MBED_FLASH_ALGO_PROGRAM 2UL
<> 160:d5399cc887bb 31
<> 160:d5399cc887bb 32 extern uint32_t SystemCoreClock;
<> 160:d5399cc887bb 33
<> 160:d5399cc887bb 34 /*
<> 160:d5399cc887bb 35 This binary blob (thumb code) sets r9 (static base) as the code we are jumping to
<> 160:d5399cc887bb 36 is PIC (position independent code).
<> 160:d5399cc887bb 37
<> 160:d5399cc887bb 38 These are the instructions (r0 is a pointer to arg_t):
<> 160:d5399cc887bb 39 push {r5, lr, r4}
<> 160:d5399cc887bb 40 mov r5, r9
<> 160:d5399cc887bb 41 push {r5}
<> 160:d5399cc887bb 42 ldr r5, [r0, #20]
<> 160:d5399cc887bb 43 ldr r3, [r0, #16]
<> 160:d5399cc887bb 44 mov r9, r3
<> 160:d5399cc887bb 45 ldr r3, [r0, #12]
<> 160:d5399cc887bb 46 ldr r2, [r0, #8]
<> 160:d5399cc887bb 47 ldr r1, [r0, #4]
<> 160:d5399cc887bb 48 ldr r0, [r0, #0]
<> 160:d5399cc887bb 49 blx r5
<> 160:d5399cc887bb 50 pop {r5}
<> 160:d5399cc887bb 51 mov r9, r5
<> 160:d5399cc887bb 52 pop {r4-r5, pc}
<> 160:d5399cc887bb 53 bx r14
<> 160:d5399cc887bb 54 */
<> 160:d5399cc887bb 55 static uint32_t jump_to_flash_algo[] = {
<> 160:d5399cc887bb 56 0x464DB530,
<> 160:d5399cc887bb 57 0x6945B420,
<> 160:d5399cc887bb 58 0x46996903,
<> 160:d5399cc887bb 59 0x688268C3,
<> 160:d5399cc887bb 60 0x68006841,
<> 160:d5399cc887bb 61 0xBC2047A8,
<> 160:d5399cc887bb 62 0xBD3046A9
<> 160:d5399cc887bb 63 };
<> 160:d5399cc887bb 64
<> 160:d5399cc887bb 65 // should be called within critical section
<> 160:d5399cc887bb 66 static int32_t flash_algo_init(flash_t *obj, uint32_t address, uint32_t function)
<> 160:d5399cc887bb 67 {
<> 160:d5399cc887bb 68 args_t arguments = {
<> 160:d5399cc887bb 69 .r0 = address,
<> 160:d5399cc887bb 70 .r1 = SystemCoreClock,
<> 160:d5399cc887bb 71 .r2 = function,
<> 160:d5399cc887bb 72 .r3 = 0,
<> 160:d5399cc887bb 73 .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base,
<> 160:d5399cc887bb 74 .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->init
<> 160:d5399cc887bb 75 };
<> 160:d5399cc887bb 76 return ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments);
<> 160:d5399cc887bb 77 }
<> 160:d5399cc887bb 78
<> 160:d5399cc887bb 79 // should be called within critical section
<> 160:d5399cc887bb 80 static int32_t flash_algo_uninit(flash_t *obj, uint32_t address, uint32_t function)
<> 160:d5399cc887bb 81 {
<> 160:d5399cc887bb 82 args_t arguments = {
<> 160:d5399cc887bb 83 .r0 = address,
<> 160:d5399cc887bb 84 .r1 = SystemCoreClock,
<> 160:d5399cc887bb 85 .r2 = function,
<> 160:d5399cc887bb 86 .r3 = 0,
<> 160:d5399cc887bb 87 .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base,
<> 160:d5399cc887bb 88 .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->uninit
<> 160:d5399cc887bb 89 };
<> 160:d5399cc887bb 90 return ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments);
<> 160:d5399cc887bb 91 }
<> 160:d5399cc887bb 92
Anna Bridge 186:707f6e361f3e 93 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 94 /* Check if address range [start_addr, end_addr] is in non-secure flash
Anna Bridge 186:707f6e361f3e 95 *
Anna Bridge 186:707f6e361f3e 96 * @param obj The flash object
Anna Bridge 186:707f6e361f3e 97 * @param start_addr Start address to check
Anna Bridge 186:707f6e361f3e 98 * @param end_addr End address to check. Could be the same as start_addr to just check start_addr
Anna Bridge 186:707f6e361f3e 99 * for e.g. flash_erase_sector.
Anna Bridge 186:707f6e361f3e 100 * @return 0 for success, -1 for error
AnnaBridge 187:0387e8f68319 101 */
Anna Bridge 186:707f6e361f3e 102 static int32_t flash_check_nonsecure(flash_t *obj, uint32_t start_addr, uint32_t end_addr)
Anna Bridge 186:707f6e361f3e 103 {
Anna Bridge 186:707f6e361f3e 104 /* Check if end address wraps around */
Anna Bridge 186:707f6e361f3e 105 if (end_addr < start_addr) {
Anna Bridge 186:707f6e361f3e 106 return -1;
Anna Bridge 186:707f6e361f3e 107 }
<> 160:d5399cc887bb 108
Anna Bridge 186:707f6e361f3e 109 /* Check if start address is in non-secure flash */
Anna Bridge 186:707f6e361f3e 110 if ((start_addr < obj->target_config_ns->flash_start) ||
AnnaBridge 187:0387e8f68319 111 (start_addr >= (obj->target_config_ns->flash_start + obj->target_config_ns->flash_size))) {
Anna Bridge 186:707f6e361f3e 112 return -1;
Anna Bridge 186:707f6e361f3e 113 }
Anna Bridge 186:707f6e361f3e 114
Anna Bridge 186:707f6e361f3e 115 /* Check if end address is in non-secure flash */
Anna Bridge 186:707f6e361f3e 116 if (end_addr != start_addr) {
Anna Bridge 186:707f6e361f3e 117 if ((end_addr < obj->target_config_ns->flash_start) ||
AnnaBridge 187:0387e8f68319 118 (end_addr >= (obj->target_config_ns->flash_start + obj->target_config_ns->flash_size))) {
Anna Bridge 186:707f6e361f3e 119 return -1;
Anna Bridge 186:707f6e361f3e 120 }
Anna Bridge 186:707f6e361f3e 121 }
Anna Bridge 186:707f6e361f3e 122
Anna Bridge 186:707f6e361f3e 123 return 0;
Anna Bridge 186:707f6e361f3e 124 }
Anna Bridge 186:707f6e361f3e 125 #endif
Anna Bridge 186:707f6e361f3e 126
Anna Bridge 186:707f6e361f3e 127 MBED_NONSECURE_ENTRY int32_t flash_init(flash_t *obj)
<> 160:d5399cc887bb 128 {
<> 160:d5399cc887bb 129 flash_set_target_config(obj);
<> 160:d5399cc887bb 130 return 0;
<> 160:d5399cc887bb 131 }
<> 160:d5399cc887bb 132
Anna Bridge 186:707f6e361f3e 133 MBED_NONSECURE_ENTRY int32_t flash_free(flash_t *obj)
<> 160:d5399cc887bb 134 {
<> 160:d5399cc887bb 135 return 0;
<> 160:d5399cc887bb 136 }
<> 160:d5399cc887bb 137
Anna Bridge 186:707f6e361f3e 138 MBED_NONSECURE_ENTRY int32_t flash_erase_sector(flash_t *obj, uint32_t address)
<> 160:d5399cc887bb 139 {
Anna Bridge 186:707f6e361f3e 140 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 141 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 142 // Confine non-secure access to non-secure flash
Anna Bridge 186:707f6e361f3e 143 if (flash_check_nonsecure(obj, address, address)) {
Anna Bridge 186:707f6e361f3e 144 return -1;
Anna Bridge 186:707f6e361f3e 145 }
Anna Bridge 186:707f6e361f3e 146 }
Anna Bridge 186:707f6e361f3e 147 #endif
Anna Bridge 186:707f6e361f3e 148
<> 160:d5399cc887bb 149 core_util_critical_section_enter();
<> 160:d5399cc887bb 150 flash_algo_init(obj, address, MBED_FLASH_ALGO_ERASE);
<> 160:d5399cc887bb 151
<> 160:d5399cc887bb 152 args_t arguments = {
<> 160:d5399cc887bb 153 .r0 = address,
<> 160:d5399cc887bb 154 .r1 = 0,
<> 160:d5399cc887bb 155 .r2 = 0,
<> 160:d5399cc887bb 156 .r3 = 0,
<> 160:d5399cc887bb 157 .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base,
<> 160:d5399cc887bb 158 .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->erase_sector
<> 160:d5399cc887bb 159 };
<> 160:d5399cc887bb 160 int32_t ret = ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments);
<> 160:d5399cc887bb 161
<> 160:d5399cc887bb 162 flash_algo_uninit(obj, address, MBED_FLASH_ALGO_ERASE);
<> 160:d5399cc887bb 163 core_util_critical_section_exit();
<> 160:d5399cc887bb 164 return ret ? -1 : 0;
<> 160:d5399cc887bb 165 }
<> 160:d5399cc887bb 166
Anna Bridge 186:707f6e361f3e 167 MBED_NONSECURE_ENTRY int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
Anna Bridge 186:707f6e361f3e 168 {
Anna Bridge 186:707f6e361f3e 169 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 170 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 171 // Confine non-secure access to non-secure flash
Anna Bridge 186:707f6e361f3e 172 if (flash_check_nonsecure(obj, address, address + size - 1)) {
Anna Bridge 186:707f6e361f3e 173 return -1;
Anna Bridge 186:707f6e361f3e 174 }
Anna Bridge 186:707f6e361f3e 175 }
Anna Bridge 186:707f6e361f3e 176 #endif
<> 160:d5399cc887bb 177
<> 160:d5399cc887bb 178 core_util_critical_section_enter();
<> 160:d5399cc887bb 179 flash_algo_init(obj, address, MBED_FLASH_ALGO_PROGRAM);
<> 160:d5399cc887bb 180
<> 160:d5399cc887bb 181 args_t arguments = {
<> 160:d5399cc887bb 182 .r0 = address,
<> 160:d5399cc887bb 183 .r1 = size,
<> 160:d5399cc887bb 184 .r2 = (uint32_t)data,
<> 160:d5399cc887bb 185 .r3 = 0,
<> 160:d5399cc887bb 186 .r9 = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->static_base,
<> 160:d5399cc887bb 187 .pc = (uint32_t)obj->flash_algo->algo_blob + obj->flash_algo->program_page
<> 160:d5399cc887bb 188 };
<> 160:d5399cc887bb 189 int32_t ret = ((flash_algo_jump_t)(((uint32_t)&jump_to_flash_algo) | 1))(&arguments);
<> 160:d5399cc887bb 190
<> 160:d5399cc887bb 191 flash_algo_uninit(obj, address, MBED_FLASH_ALGO_PROGRAM);
<> 160:d5399cc887bb 192 core_util_critical_section_exit();
<> 160:d5399cc887bb 193 return ret ? -1 : 0;
<> 160:d5399cc887bb 194 }
<> 160:d5399cc887bb 195
Anna Bridge 186:707f6e361f3e 196 MBED_NONSECURE_ENTRY uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
Anna Bridge 186:707f6e361f3e 197 {
Anna Bridge 186:707f6e361f3e 198 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 199 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 200 const sector_info_t *sectors = obj->target_config_ns->sectors;
<> 160:d5399cc887bb 201
Anna Bridge 186:707f6e361f3e 202 if (address >= obj->target_config_ns->flash_start + obj->target_config_ns->flash_size) {
Anna Bridge 186:707f6e361f3e 203 return MBED_FLASH_INVALID_SIZE;
Anna Bridge 186:707f6e361f3e 204 }
Anna Bridge 186:707f6e361f3e 205
Anna Bridge 186:707f6e361f3e 206 int sector_index = obj->target_config_ns->sector_info_count - 1;
Anna Bridge 186:707f6e361f3e 207 for (; sector_index >= 0; sector_index--) {
Anna Bridge 186:707f6e361f3e 208 if (address >= sectors[sector_index].start) {
Anna Bridge 186:707f6e361f3e 209 return sectors[sector_index].size;
Anna Bridge 186:707f6e361f3e 210 }
Anna Bridge 186:707f6e361f3e 211 }
Anna Bridge 186:707f6e361f3e 212 return MBED_FLASH_INVALID_SIZE;
Anna Bridge 186:707f6e361f3e 213 }
Anna Bridge 186:707f6e361f3e 214 #endif
Anna Bridge 186:707f6e361f3e 215
<> 160:d5399cc887bb 216 const sector_info_t *sectors = obj->target_config->sectors;
<> 160:d5399cc887bb 217
<> 160:d5399cc887bb 218 if (address >= obj->target_config->flash_start + obj->target_config->flash_size) {
<> 160:d5399cc887bb 219 return MBED_FLASH_INVALID_SIZE;
<> 160:d5399cc887bb 220 }
<> 160:d5399cc887bb 221
<> 160:d5399cc887bb 222 int sector_index = obj->target_config->sector_info_count - 1;
<> 160:d5399cc887bb 223 for (; sector_index >= 0; sector_index--) {
<> 160:d5399cc887bb 224 if (address >= sectors[sector_index].start) {
<> 160:d5399cc887bb 225 return sectors[sector_index].size;
<> 160:d5399cc887bb 226 }
<> 160:d5399cc887bb 227 }
<> 160:d5399cc887bb 228 return MBED_FLASH_INVALID_SIZE;
<> 160:d5399cc887bb 229 }
<> 160:d5399cc887bb 230
Anna Bridge 186:707f6e361f3e 231 MBED_NONSECURE_ENTRY uint32_t flash_get_page_size(const flash_t *obj)
<> 160:d5399cc887bb 232 {
Anna Bridge 186:707f6e361f3e 233 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 234 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 235 return obj->target_config_ns->page_size;
Anna Bridge 186:707f6e361f3e 236 }
Anna Bridge 186:707f6e361f3e 237 #endif
Anna Bridge 186:707f6e361f3e 238
<> 160:d5399cc887bb 239 return obj->target_config->page_size;
<> 160:d5399cc887bb 240 }
<> 160:d5399cc887bb 241
Anna Bridge 186:707f6e361f3e 242 MBED_NONSECURE_ENTRY uint32_t flash_get_start_address(const flash_t *obj)
<> 160:d5399cc887bb 243 {
Anna Bridge 186:707f6e361f3e 244 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 245 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 246 return obj->target_config_ns->flash_start;
Anna Bridge 186:707f6e361f3e 247 }
Anna Bridge 186:707f6e361f3e 248 #endif
Anna Bridge 186:707f6e361f3e 249
<> 160:d5399cc887bb 250 return obj->target_config->flash_start;
<> 160:d5399cc887bb 251 }
<> 160:d5399cc887bb 252
Anna Bridge 186:707f6e361f3e 253 MBED_NONSECURE_ENTRY uint32_t flash_get_size(const flash_t *obj)
<> 160:d5399cc887bb 254 {
Anna Bridge 186:707f6e361f3e 255 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
Anna Bridge 186:707f6e361f3e 256 if (cmse_nonsecure_caller()) {
Anna Bridge 186:707f6e361f3e 257 return obj->target_config_ns->flash_size;
Anna Bridge 186:707f6e361f3e 258 }
Anna Bridge 186:707f6e361f3e 259 #endif
Anna Bridge 186:707f6e361f3e 260
<> 160:d5399cc887bb 261 return obj->target_config->flash_size;
<> 160:d5399cc887bb 262 }
Anna Bridge 186:707f6e361f3e 263
AnnaBridge 189:f392fc9709a3 264 MBED_NONSECURE_ENTRY uint8_t flash_get_erase_value(const flash_t *obj)
AnnaBridge 189:f392fc9709a3 265 {
AnnaBridge 189:f392fc9709a3 266 (void)obj;
AnnaBridge 189:f392fc9709a3 267
AnnaBridge 189:f392fc9709a3 268 return 0xFF;
AnnaBridge 189:f392fc9709a3 269 }
AnnaBridge 189:f392fc9709a3 270
Anna Bridge 186:707f6e361f3e 271 #endif // #ifndef DOMAIN_NS