mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Thu Sep 06 13:40:20 2018 +0100
Revision:
187:0387e8f68319
Parent:
186:707f6e361f3e
Child:
189:f392fc9709a3
mbed-dev library. Release version 163

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