Initial commit

Dependencies:   FastPWM

Committer:
lypinator
Date:
Wed Sep 16 01:11:49 2020 +0000
Revision:
0:bb348c97df44
Added PWM

Who changed what in which revision?

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