takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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