Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file flash_manager.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief Implementation of flash_manager.h
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * Copyright 2019, Cypress Semiconductor Corporation
Pawel Zarembski 0:01f31e923fe2 8 * or a subsidiary of Cypress Semiconductor Corporation.
Pawel Zarembski 0:01f31e923fe2 9 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 10 *
Pawel Zarembski 0:01f31e923fe2 11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 12 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 13 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 16 *
Pawel Zarembski 0:01f31e923fe2 17 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 20 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 21 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 22 */
Pawel Zarembski 0:01f31e923fe2 23
Pawel Zarembski 0:01f31e923fe2 24 #include "flash_manager.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "error.h"
Pawel Zarembski 0:01f31e923fe2 27 #include "settings.h"
Pawel Zarembski 0:01f31e923fe2 28
Pawel Zarembski 0:01f31e923fe2 29 // Set to 1 to enable debugging
Pawel Zarembski 0:01f31e923fe2 30 #define DEBUG_FLASH_MANAGER 0
Pawel Zarembski 0:01f31e923fe2 31
Pawel Zarembski 0:01f31e923fe2 32 #if DEBUG_FLASH_MANAGER
Pawel Zarembski 0:01f31e923fe2 33 #include "daplink_debug.h"
Pawel Zarembski 0:01f31e923fe2 34 #define flash_manager_printf debug_msg
Pawel Zarembski 0:01f31e923fe2 35 #else
Pawel Zarembski 0:01f31e923fe2 36 #define flash_manager_printf(...)
Pawel Zarembski 0:01f31e923fe2 37 #endif
Pawel Zarembski 0:01f31e923fe2 38
Pawel Zarembski 0:01f31e923fe2 39 typedef enum {
Pawel Zarembski 0:01f31e923fe2 40 STATE_CLOSED,
Pawel Zarembski 0:01f31e923fe2 41 STATE_OPEN,
Pawel Zarembski 0:01f31e923fe2 42 STATE_ERROR
Pawel Zarembski 0:01f31e923fe2 43 } state_t;
Pawel Zarembski 0:01f31e923fe2 44
Pawel Zarembski 0:01f31e923fe2 45 // Target programming expects buffer
Pawel Zarembski 0:01f31e923fe2 46 // passed in to be 4 byte aligned
Pawel Zarembski 0:01f31e923fe2 47 __attribute__((aligned(4)))
Pawel Zarembski 0:01f31e923fe2 48 static uint8_t buf[1024];
Pawel Zarembski 0:01f31e923fe2 49 static bool buf_empty;
Pawel Zarembski 0:01f31e923fe2 50 static bool current_sector_valid;
Pawel Zarembski 0:01f31e923fe2 51 static bool page_erase_enabled = false;
Pawel Zarembski 0:01f31e923fe2 52 static uint32_t current_write_block_addr;
Pawel Zarembski 0:01f31e923fe2 53 static uint32_t current_write_block_size;
Pawel Zarembski 0:01f31e923fe2 54 static uint32_t current_sector_addr;
Pawel Zarembski 0:01f31e923fe2 55 static uint32_t current_sector_size;
Pawel Zarembski 0:01f31e923fe2 56 static uint32_t last_addr;
Pawel Zarembski 0:01f31e923fe2 57 static const flash_intf_t *intf;
Pawel Zarembski 0:01f31e923fe2 58 static state_t state = STATE_CLOSED;
Pawel Zarembski 0:01f31e923fe2 59
Pawel Zarembski 0:01f31e923fe2 60 static bool flash_intf_valid(const flash_intf_t *flash_intf);
Pawel Zarembski 0:01f31e923fe2 61 static error_t flush_current_block(uint32_t addr);
Pawel Zarembski 0:01f31e923fe2 62 static error_t setup_next_sector(uint32_t addr);
Pawel Zarembski 0:01f31e923fe2 63
Pawel Zarembski 0:01f31e923fe2 64 error_t flash_manager_init(const flash_intf_t *flash_intf)
Pawel Zarembski 0:01f31e923fe2 65 {
Pawel Zarembski 0:01f31e923fe2 66 error_t status;
Pawel Zarembski 0:01f31e923fe2 67 // Assert that interface has been properly uninitialized
Pawel Zarembski 0:01f31e923fe2 68 flash_manager_printf("flash_manager_init()\r\n");
Pawel Zarembski 0:01f31e923fe2 69
Pawel Zarembski 0:01f31e923fe2 70 if (state != STATE_CLOSED) {
Pawel Zarembski 0:01f31e923fe2 71 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 72 return ERROR_INTERNAL;
Pawel Zarembski 0:01f31e923fe2 73 }
Pawel Zarembski 0:01f31e923fe2 74
Pawel Zarembski 0:01f31e923fe2 75 // Check for a valid flash interface
Pawel Zarembski 0:01f31e923fe2 76 if (!flash_intf_valid(flash_intf)) {
Pawel Zarembski 0:01f31e923fe2 77 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 78 return ERROR_INTERNAL;
Pawel Zarembski 0:01f31e923fe2 79 }
Pawel Zarembski 0:01f31e923fe2 80
Pawel Zarembski 0:01f31e923fe2 81 // Initialize variables
Pawel Zarembski 0:01f31e923fe2 82 memset(buf, 0xFF, sizeof(buf));
Pawel Zarembski 0:01f31e923fe2 83 buf_empty = true;
Pawel Zarembski 0:01f31e923fe2 84 current_sector_valid = false;
Pawel Zarembski 0:01f31e923fe2 85 current_write_block_addr = 0;
Pawel Zarembski 0:01f31e923fe2 86 current_write_block_size = 0;
Pawel Zarembski 0:01f31e923fe2 87 current_sector_addr = 0;
Pawel Zarembski 0:01f31e923fe2 88 current_sector_size = 0;
Pawel Zarembski 0:01f31e923fe2 89 last_addr = 0;
Pawel Zarembski 0:01f31e923fe2 90 intf = flash_intf;
Pawel Zarembski 0:01f31e923fe2 91 // Initialize flash
Pawel Zarembski 0:01f31e923fe2 92 status = intf->init();
Pawel Zarembski 0:01f31e923fe2 93 flash_manager_printf(" intf->init ret=%i\r\n", status);
Pawel Zarembski 0:01f31e923fe2 94
Pawel Zarembski 0:01f31e923fe2 95 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 96 return status;
Pawel Zarembski 0:01f31e923fe2 97 }
Pawel Zarembski 0:01f31e923fe2 98
Pawel Zarembski 0:01f31e923fe2 99 if (!page_erase_enabled) {
Pawel Zarembski 0:01f31e923fe2 100 // Erase flash and unint if there are errors
Pawel Zarembski 0:01f31e923fe2 101 status = intf->erase_chip();
Pawel Zarembski 0:01f31e923fe2 102 flash_manager_printf(" intf->erase_chip ret=%i\r\n", status);
Pawel Zarembski 0:01f31e923fe2 103
Pawel Zarembski 0:01f31e923fe2 104 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 105 intf->uninit();
Pawel Zarembski 0:01f31e923fe2 106 return status;
Pawel Zarembski 0:01f31e923fe2 107 }
Pawel Zarembski 0:01f31e923fe2 108 }
Pawel Zarembski 0:01f31e923fe2 109
Pawel Zarembski 0:01f31e923fe2 110 state = STATE_OPEN;
Pawel Zarembski 0:01f31e923fe2 111 return status;
Pawel Zarembski 0:01f31e923fe2 112 }
Pawel Zarembski 0:01f31e923fe2 113
Pawel Zarembski 0:01f31e923fe2 114 error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 115 {
Pawel Zarembski 0:01f31e923fe2 116 uint32_t size_left;
Pawel Zarembski 0:01f31e923fe2 117 uint32_t copy_size;
Pawel Zarembski 0:01f31e923fe2 118 uint32_t pos;
Pawel Zarembski 0:01f31e923fe2 119 error_t status = ERROR_SUCCESS;
Pawel Zarembski 0:01f31e923fe2 120 flash_manager_printf("flash_manager_data(addr=0x%x size=0x%x)\r\n", addr, size);
Pawel Zarembski 0:01f31e923fe2 121
Pawel Zarembski 0:01f31e923fe2 122 if (state != STATE_OPEN) {
Pawel Zarembski 0:01f31e923fe2 123 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 124 return ERROR_INTERNAL;
Pawel Zarembski 0:01f31e923fe2 125 }
Pawel Zarembski 0:01f31e923fe2 126
Pawel Zarembski 0:01f31e923fe2 127 // Setup the current sector if it is not setup already
Pawel Zarembski 0:01f31e923fe2 128 if (!current_sector_valid) {
Pawel Zarembski 0:01f31e923fe2 129 status = setup_next_sector(addr);
Pawel Zarembski 0:01f31e923fe2 130
Pawel Zarembski 0:01f31e923fe2 131 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 132 state = STATE_ERROR;
Pawel Zarembski 0:01f31e923fe2 133 return status;
Pawel Zarembski 0:01f31e923fe2 134 }
Pawel Zarembski 0:01f31e923fe2 135 current_sector_valid = true;
Pawel Zarembski 0:01f31e923fe2 136 last_addr = addr;
Pawel Zarembski 0:01f31e923fe2 137 }
Pawel Zarembski 0:01f31e923fe2 138
Pawel Zarembski 0:01f31e923fe2 139 //non-increasing address support
Pawel Zarembski 0:01f31e923fe2 140 if (ROUND_DOWN(addr, current_write_block_size) != ROUND_DOWN(last_addr, current_write_block_size)) {
Pawel Zarembski 0:01f31e923fe2 141 status = flush_current_block(addr);
Pawel Zarembski 0:01f31e923fe2 142 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 143 state = STATE_ERROR;
Pawel Zarembski 0:01f31e923fe2 144 return status;
Pawel Zarembski 0:01f31e923fe2 145 }
Pawel Zarembski 0:01f31e923fe2 146 }
Pawel Zarembski 0:01f31e923fe2 147
Pawel Zarembski 0:01f31e923fe2 148 if (ROUND_DOWN(addr, current_sector_size) != ROUND_DOWN(last_addr, current_sector_size)) {
Pawel Zarembski 0:01f31e923fe2 149 status = setup_next_sector(addr);
Pawel Zarembski 0:01f31e923fe2 150 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 151 state = STATE_ERROR;
Pawel Zarembski 0:01f31e923fe2 152 return status;
Pawel Zarembski 0:01f31e923fe2 153 }
Pawel Zarembski 0:01f31e923fe2 154 }
Pawel Zarembski 0:01f31e923fe2 155
Pawel Zarembski 0:01f31e923fe2 156 while (true) {
Pawel Zarembski 0:01f31e923fe2 157 // flush if necessary
Pawel Zarembski 0:01f31e923fe2 158 if (addr >= current_write_block_addr + current_write_block_size) {
Pawel Zarembski 0:01f31e923fe2 159 status = flush_current_block(addr);
Pawel Zarembski 0:01f31e923fe2 160 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 161 state = STATE_ERROR;
Pawel Zarembski 0:01f31e923fe2 162 return status;
Pawel Zarembski 0:01f31e923fe2 163 }
Pawel Zarembski 0:01f31e923fe2 164 }
Pawel Zarembski 0:01f31e923fe2 165
Pawel Zarembski 0:01f31e923fe2 166 // Check for end
Pawel Zarembski 0:01f31e923fe2 167 if (size <= 0) {
Pawel Zarembski 0:01f31e923fe2 168 break;
Pawel Zarembski 0:01f31e923fe2 169 }
Pawel Zarembski 0:01f31e923fe2 170
Pawel Zarembski 0:01f31e923fe2 171 // Change sector if necessary
Pawel Zarembski 0:01f31e923fe2 172 if (addr >= current_sector_addr + current_sector_size) {
Pawel Zarembski 0:01f31e923fe2 173 status = setup_next_sector(addr);
Pawel Zarembski 0:01f31e923fe2 174
Pawel Zarembski 0:01f31e923fe2 175 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 176 state = STATE_ERROR;
Pawel Zarembski 0:01f31e923fe2 177 return status;
Pawel Zarembski 0:01f31e923fe2 178 }
Pawel Zarembski 0:01f31e923fe2 179 }
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 // write buffer
Pawel Zarembski 0:01f31e923fe2 182 pos = addr - current_write_block_addr;
Pawel Zarembski 0:01f31e923fe2 183 size_left = current_write_block_size - pos;
Pawel Zarembski 0:01f31e923fe2 184 copy_size = MIN(size, size_left);
Pawel Zarembski 0:01f31e923fe2 185 memcpy(buf + pos, data, copy_size);
Pawel Zarembski 0:01f31e923fe2 186 buf_empty = copy_size == 0;
Pawel Zarembski 0:01f31e923fe2 187 // Update variables
Pawel Zarembski 0:01f31e923fe2 188 addr += copy_size;
Pawel Zarembski 0:01f31e923fe2 189 data += copy_size;
Pawel Zarembski 0:01f31e923fe2 190 size -= copy_size;
Pawel Zarembski 0:01f31e923fe2 191 }
Pawel Zarembski 0:01f31e923fe2 192
Pawel Zarembski 0:01f31e923fe2 193 last_addr = addr;
Pawel Zarembski 0:01f31e923fe2 194 return status;
Pawel Zarembski 0:01f31e923fe2 195 }
Pawel Zarembski 0:01f31e923fe2 196
Pawel Zarembski 0:01f31e923fe2 197 error_t flash_manager_uninit(void)
Pawel Zarembski 0:01f31e923fe2 198 {
Pawel Zarembski 0:01f31e923fe2 199 error_t flash_uninit_error;
Pawel Zarembski 0:01f31e923fe2 200 error_t flash_write_error = ERROR_SUCCESS;
Pawel Zarembski 0:01f31e923fe2 201 flash_manager_printf("flash_manager_uninit()\r\n");
Pawel Zarembski 0:01f31e923fe2 202
Pawel Zarembski 0:01f31e923fe2 203 if (STATE_CLOSED == state) {
Pawel Zarembski 0:01f31e923fe2 204 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 205 return ERROR_INTERNAL;
Pawel Zarembski 0:01f31e923fe2 206 }
Pawel Zarembski 0:01f31e923fe2 207
Pawel Zarembski 0:01f31e923fe2 208 // Flush last buffer if its not empty
Pawel Zarembski 0:01f31e923fe2 209 if (STATE_OPEN == state) {
Pawel Zarembski 0:01f31e923fe2 210 flash_write_error = flush_current_block(0);
Pawel Zarembski 0:01f31e923fe2 211 flash_manager_printf(" last flush_current_block ret=%i\r\n",flash_write_error);
Pawel Zarembski 0:01f31e923fe2 212 }
Pawel Zarembski 0:01f31e923fe2 213 // Close flash interface (even if there was an error during program_page)
Pawel Zarembski 0:01f31e923fe2 214 flash_uninit_error = intf->uninit();
Pawel Zarembski 0:01f31e923fe2 215 flash_manager_printf(" intf->uninit() ret=%i\r\n", flash_uninit_error);
Pawel Zarembski 0:01f31e923fe2 216 // Reset variables to catch accidental use
Pawel Zarembski 0:01f31e923fe2 217 memset(buf, 0xFF, sizeof(buf));
Pawel Zarembski 0:01f31e923fe2 218 buf_empty = true;
Pawel Zarembski 0:01f31e923fe2 219 current_sector_valid = false;
Pawel Zarembski 0:01f31e923fe2 220 current_write_block_addr = 0;
Pawel Zarembski 0:01f31e923fe2 221 current_write_block_size = 0;
Pawel Zarembski 0:01f31e923fe2 222 current_sector_addr = 0;
Pawel Zarembski 0:01f31e923fe2 223 current_sector_size = 0;
Pawel Zarembski 0:01f31e923fe2 224 last_addr = 0;
Pawel Zarembski 0:01f31e923fe2 225 state = STATE_CLOSED;
Pawel Zarembski 0:01f31e923fe2 226
Pawel Zarembski 0:01f31e923fe2 227 // Make sure an error from a page write or from an
Pawel Zarembski 0:01f31e923fe2 228 // uninit gets propagated
Pawel Zarembski 0:01f31e923fe2 229 if (flash_uninit_error != ERROR_SUCCESS) {
Pawel Zarembski 0:01f31e923fe2 230 return flash_uninit_error;
Pawel Zarembski 0:01f31e923fe2 231 }
Pawel Zarembski 0:01f31e923fe2 232
Pawel Zarembski 0:01f31e923fe2 233 if (flash_write_error != ERROR_SUCCESS) {
Pawel Zarembski 0:01f31e923fe2 234 return flash_write_error;
Pawel Zarembski 0:01f31e923fe2 235 }
Pawel Zarembski 0:01f31e923fe2 236
Pawel Zarembski 0:01f31e923fe2 237 return ERROR_SUCCESS;
Pawel Zarembski 0:01f31e923fe2 238 }
Pawel Zarembski 0:01f31e923fe2 239
Pawel Zarembski 0:01f31e923fe2 240 void flash_manager_set_page_erase(bool enabled)
Pawel Zarembski 0:01f31e923fe2 241 {
Pawel Zarembski 0:01f31e923fe2 242 config_ram_set_page_erase(enabled);
Pawel Zarembski 0:01f31e923fe2 243 page_erase_enabled = enabled;
Pawel Zarembski 0:01f31e923fe2 244 }
Pawel Zarembski 0:01f31e923fe2 245
Pawel Zarembski 0:01f31e923fe2 246 static bool flash_intf_valid(const flash_intf_t *flash_intf)
Pawel Zarembski 0:01f31e923fe2 247 {
Pawel Zarembski 0:01f31e923fe2 248 // Check for all requried members
Pawel Zarembski 0:01f31e923fe2 249 if (0 == flash_intf) {
Pawel Zarembski 0:01f31e923fe2 250 return false;
Pawel Zarembski 0:01f31e923fe2 251 }
Pawel Zarembski 0:01f31e923fe2 252
Pawel Zarembski 0:01f31e923fe2 253 if (0 == flash_intf->uninit) {
Pawel Zarembski 0:01f31e923fe2 254 return false;
Pawel Zarembski 0:01f31e923fe2 255 }
Pawel Zarembski 0:01f31e923fe2 256
Pawel Zarembski 0:01f31e923fe2 257 if (0 == flash_intf->program_page) {
Pawel Zarembski 0:01f31e923fe2 258 return false;
Pawel Zarembski 0:01f31e923fe2 259 }
Pawel Zarembski 0:01f31e923fe2 260
Pawel Zarembski 0:01f31e923fe2 261 if (0 == flash_intf->erase_sector) {
Pawel Zarembski 0:01f31e923fe2 262 return false;
Pawel Zarembski 0:01f31e923fe2 263 }
Pawel Zarembski 0:01f31e923fe2 264
Pawel Zarembski 0:01f31e923fe2 265 if (0 == flash_intf->erase_chip) {
Pawel Zarembski 0:01f31e923fe2 266 return false;
Pawel Zarembski 0:01f31e923fe2 267 }
Pawel Zarembski 0:01f31e923fe2 268
Pawel Zarembski 0:01f31e923fe2 269 if (0 == flash_intf->program_page_min_size) {
Pawel Zarembski 0:01f31e923fe2 270 return false;
Pawel Zarembski 0:01f31e923fe2 271 }
Pawel Zarembski 0:01f31e923fe2 272
Pawel Zarembski 0:01f31e923fe2 273 if (0 == flash_intf->erase_sector_size) {
Pawel Zarembski 0:01f31e923fe2 274 return false;
Pawel Zarembski 0:01f31e923fe2 275 }
Pawel Zarembski 0:01f31e923fe2 276
Pawel Zarembski 0:01f31e923fe2 277 if (0 == flash_intf->flash_busy) {
Pawel Zarembski 0:01f31e923fe2 278 return false;
Pawel Zarembski 0:01f31e923fe2 279 }
Pawel Zarembski 0:01f31e923fe2 280
Pawel Zarembski 0:01f31e923fe2 281 return true;
Pawel Zarembski 0:01f31e923fe2 282 }
Pawel Zarembski 0:01f31e923fe2 283
Pawel Zarembski 0:01f31e923fe2 284 static error_t flush_current_block(uint32_t addr){
Pawel Zarembski 0:01f31e923fe2 285 // Write out current buffer if there is data in it
Pawel Zarembski 0:01f31e923fe2 286 error_t status = ERROR_SUCCESS;
Pawel Zarembski 0:01f31e923fe2 287 if (!buf_empty) {
Pawel Zarembski 0:01f31e923fe2 288 status = intf->program_page(current_write_block_addr, buf, current_write_block_size);
Pawel Zarembski 0:01f31e923fe2 289 flash_manager_printf(" intf->program_page(addr=0x%x, size=0x%x) ret=%i\r\n", current_write_block_addr, current_write_block_size, status);
Pawel Zarembski 0:01f31e923fe2 290 buf_empty = true;
Pawel Zarembski 0:01f31e923fe2 291 }
Pawel Zarembski 0:01f31e923fe2 292
Pawel Zarembski 0:01f31e923fe2 293 // Setup for next block
Pawel Zarembski 0:01f31e923fe2 294 memset(buf, 0xFF, current_write_block_size);
Pawel Zarembski 0:01f31e923fe2 295 current_write_block_addr = ROUND_DOWN(addr,current_write_block_size);
Pawel Zarembski 0:01f31e923fe2 296 return status;
Pawel Zarembski 0:01f31e923fe2 297 }
Pawel Zarembski 0:01f31e923fe2 298
Pawel Zarembski 0:01f31e923fe2 299 static error_t setup_next_sector(uint32_t addr)
Pawel Zarembski 0:01f31e923fe2 300 {
Pawel Zarembski 0:01f31e923fe2 301 uint32_t min_prog_size;
Pawel Zarembski 0:01f31e923fe2 302 uint32_t sector_size;
Pawel Zarembski 0:01f31e923fe2 303 error_t status;
Pawel Zarembski 0:01f31e923fe2 304 min_prog_size = intf->program_page_min_size(addr);
Pawel Zarembski 0:01f31e923fe2 305 sector_size = intf->erase_sector_size(addr);
Pawel Zarembski 0:01f31e923fe2 306
Pawel Zarembski 0:01f31e923fe2 307 if ((min_prog_size <= 0) || (sector_size <= 0)) {
Pawel Zarembski 0:01f31e923fe2 308 // Either of these conditions could cause divide by 0 error
Pawel Zarembski 0:01f31e923fe2 309 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 310 return ERROR_INTERNAL;
Pawel Zarembski 0:01f31e923fe2 311 }
Pawel Zarembski 0:01f31e923fe2 312
Pawel Zarembski 0:01f31e923fe2 313 // Assert required size and alignment
Pawel Zarembski 0:01f31e923fe2 314 util_assert(sizeof(buf) >= min_prog_size);
Pawel Zarembski 0:01f31e923fe2 315 util_assert(sizeof(buf) % min_prog_size == 0);
Pawel Zarembski 0:01f31e923fe2 316 util_assert(sector_size >= min_prog_size);
Pawel Zarembski 0:01f31e923fe2 317 util_assert(sector_size % min_prog_size == 0);
Pawel Zarembski 0:01f31e923fe2 318 // Setup global variables
Pawel Zarembski 0:01f31e923fe2 319 current_sector_addr = ROUND_DOWN(addr, sector_size);
Pawel Zarembski 0:01f31e923fe2 320 current_sector_size = sector_size;
Pawel Zarembski 0:01f31e923fe2 321 current_write_block_addr = current_sector_addr;
Pawel Zarembski 0:01f31e923fe2 322 current_write_block_size = MIN(sector_size, sizeof(buf));
Pawel Zarembski 0:01f31e923fe2 323
Pawel Zarembski 0:01f31e923fe2 324 //check flash algo every sector change, addresses with different flash algo should be sector aligned
Pawel Zarembski 0:01f31e923fe2 325 if (intf->flash_algo_set) {
Pawel Zarembski 0:01f31e923fe2 326 status = intf->flash_algo_set(current_sector_addr);
Pawel Zarembski 0:01f31e923fe2 327 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 328 intf->uninit();
Pawel Zarembski 0:01f31e923fe2 329 return status;
Pawel Zarembski 0:01f31e923fe2 330 }
Pawel Zarembski 0:01f31e923fe2 331 }
Pawel Zarembski 0:01f31e923fe2 332
Pawel Zarembski 0:01f31e923fe2 333 if (page_erase_enabled) {
Pawel Zarembski 0:01f31e923fe2 334 // Erase the current sector
Pawel Zarembski 0:01f31e923fe2 335 status = intf->erase_sector(current_sector_addr);
Pawel Zarembski 0:01f31e923fe2 336 flash_manager_printf(" intf->erase_sector(addr=0x%x) ret=%i\r\n", current_sector_addr);
Pawel Zarembski 0:01f31e923fe2 337 if (ERROR_SUCCESS != status) {
Pawel Zarembski 0:01f31e923fe2 338 intf->uninit();
Pawel Zarembski 0:01f31e923fe2 339 return status;
Pawel Zarembski 0:01f31e923fe2 340 }
Pawel Zarembski 0:01f31e923fe2 341 }
Pawel Zarembski 0:01f31e923fe2 342
Pawel Zarembski 0:01f31e923fe2 343 // Clear out buffer in case block size changed
Pawel Zarembski 0:01f31e923fe2 344 memset(buf, 0xFF, current_write_block_size);
Pawel Zarembski 0:01f31e923fe2 345 flash_manager_printf(" setup_next_sector(addr=0x%x) sect_addr=0x%x, write_addr=0x%x,\r\n",
Pawel Zarembski 0:01f31e923fe2 346 addr, current_sector_addr, current_write_block_addr);
Pawel Zarembski 0:01f31e923fe2 347 flash_manager_printf(" actual_write_size=0x%x, sector_size=0x%x, min_write=0x%x\r\n",
Pawel Zarembski 0:01f31e923fe2 348 current_write_block_size, current_sector_size, min_prog_size);
Pawel Zarembski 0:01f31e923fe2 349 return ERROR_SUCCESS;
Pawel Zarembski 0:01f31e923fe2 350 }