Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
flash_manager.c
00001 /** 00002 * @file flash_manager.c 00003 * @brief Implementation of flash_manager.h 00004 * 00005 * DAPLink Interface Firmware 00006 * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved 00007 * Copyright 2019, Cypress Semiconductor Corporation 00008 * or a subsidiary of Cypress Semiconductor Corporation. 00009 * SPDX-License-Identifier: Apache-2.0 00010 * 00011 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00012 * not use this file except in compliance with the License. 00013 * You may obtain a copy of the License at 00014 * 00015 * http://www.apache.org/licenses/LICENSE-2.0 00016 * 00017 * Unless required by applicable law or agreed to in writing, software 00018 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00019 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 * See the License for the specific language governing permissions and 00021 * limitations under the License. 00022 */ 00023 00024 #include "flash_manager.h" 00025 #include "util.h" 00026 #include "error.h" 00027 #include "settings.h" 00028 00029 // Set to 1 to enable debugging 00030 #define DEBUG_FLASH_MANAGER 0 00031 00032 #if DEBUG_FLASH_MANAGER 00033 #include "daplink_debug.h" 00034 #define flash_manager_printf debug_msg 00035 #else 00036 #define flash_manager_printf(...) 00037 #endif 00038 00039 typedef enum { 00040 STATE_CLOSED, 00041 STATE_OPEN, 00042 STATE_ERROR 00043 } state_t; 00044 00045 // Target programming expects buffer 00046 // passed in to be 4 byte aligned 00047 __attribute__((aligned(4))) 00048 static uint8_t buf[1024]; 00049 static bool buf_empty; 00050 static bool current_sector_valid; 00051 static bool page_erase_enabled = false; 00052 static uint32_t current_write_block_addr; 00053 static uint32_t current_write_block_size; 00054 static uint32_t current_sector_addr; 00055 static uint32_t current_sector_size; 00056 static uint32_t last_addr; 00057 static const flash_intf_t *intf; 00058 static state_t state = STATE_CLOSED; 00059 00060 static bool flash_intf_valid(const flash_intf_t *flash_intf); 00061 static error_t flush_current_block(uint32_t addr); 00062 static error_t setup_next_sector(uint32_t addr); 00063 00064 error_t flash_manager_init(const flash_intf_t *flash_intf) 00065 { 00066 error_t status; 00067 // Assert that interface has been properly uninitialized 00068 flash_manager_printf("flash_manager_init()\r\n"); 00069 00070 if (state != STATE_CLOSED) { 00071 util_assert(0); 00072 return ERROR_INTERNAL; 00073 } 00074 00075 // Check for a valid flash interface 00076 if (!flash_intf_valid(flash_intf)) { 00077 util_assert(0); 00078 return ERROR_INTERNAL; 00079 } 00080 00081 // Initialize variables 00082 memset(buf, 0xFF, sizeof(buf)); 00083 buf_empty = true; 00084 current_sector_valid = false; 00085 current_write_block_addr = 0; 00086 current_write_block_size = 0; 00087 current_sector_addr = 0; 00088 current_sector_size = 0; 00089 last_addr = 0; 00090 intf = flash_intf; 00091 // Initialize flash 00092 status = intf->init(); 00093 flash_manager_printf(" intf->init ret=%i\r\n", status); 00094 00095 if (ERROR_SUCCESS != status) { 00096 return status; 00097 } 00098 00099 if (!page_erase_enabled) { 00100 // Erase flash and unint if there are errors 00101 status = intf->erase_chip(); 00102 flash_manager_printf(" intf->erase_chip ret=%i\r\n", status); 00103 00104 if (ERROR_SUCCESS != status) { 00105 intf->uninit(); 00106 return status; 00107 } 00108 } 00109 00110 state = STATE_OPEN; 00111 return status; 00112 } 00113 00114 error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size) 00115 { 00116 uint32_t size_left; 00117 uint32_t copy_size; 00118 uint32_t pos; 00119 error_t status = ERROR_SUCCESS; 00120 flash_manager_printf("flash_manager_data(addr=0x%x size=0x%x)\r\n", addr, size); 00121 00122 if (state != STATE_OPEN) { 00123 util_assert(0); 00124 return ERROR_INTERNAL; 00125 } 00126 00127 // Setup the current sector if it is not setup already 00128 if (!current_sector_valid) { 00129 status = setup_next_sector(addr); 00130 00131 if (ERROR_SUCCESS != status) { 00132 state = STATE_ERROR; 00133 return status; 00134 } 00135 current_sector_valid = true; 00136 last_addr = addr; 00137 } 00138 00139 //non-increasing address support 00140 if (ROUND_DOWN(addr, current_write_block_size) != ROUND_DOWN(last_addr, current_write_block_size)) { 00141 status = flush_current_block(addr); 00142 if (ERROR_SUCCESS != status) { 00143 state = STATE_ERROR; 00144 return status; 00145 } 00146 } 00147 00148 if (ROUND_DOWN(addr, current_sector_size) != ROUND_DOWN(last_addr, current_sector_size)) { 00149 status = setup_next_sector(addr); 00150 if (ERROR_SUCCESS != status) { 00151 state = STATE_ERROR; 00152 return status; 00153 } 00154 } 00155 00156 while (true) { 00157 // flush if necessary 00158 if (addr >= current_write_block_addr + current_write_block_size) { 00159 status = flush_current_block(addr); 00160 if (ERROR_SUCCESS != status) { 00161 state = STATE_ERROR; 00162 return status; 00163 } 00164 } 00165 00166 // Check for end 00167 if (size <= 0) { 00168 break; 00169 } 00170 00171 // Change sector if necessary 00172 if (addr >= current_sector_addr + current_sector_size) { 00173 status = setup_next_sector(addr); 00174 00175 if (ERROR_SUCCESS != status) { 00176 state = STATE_ERROR; 00177 return status; 00178 } 00179 } 00180 00181 // write buffer 00182 pos = addr - current_write_block_addr; 00183 size_left = current_write_block_size - pos; 00184 copy_size = MIN(size, size_left); 00185 memcpy(buf + pos, data, copy_size); 00186 buf_empty = copy_size == 0; 00187 // Update variables 00188 addr += copy_size; 00189 data += copy_size; 00190 size -= copy_size; 00191 } 00192 00193 last_addr = addr; 00194 return status; 00195 } 00196 00197 error_t flash_manager_uninit(void) 00198 { 00199 error_t flash_uninit_error; 00200 error_t flash_write_error = ERROR_SUCCESS; 00201 flash_manager_printf("flash_manager_uninit()\r\n"); 00202 00203 if (STATE_CLOSED == state) { 00204 util_assert(0); 00205 return ERROR_INTERNAL; 00206 } 00207 00208 // Flush last buffer if its not empty 00209 if (STATE_OPEN == state) { 00210 flash_write_error = flush_current_block(0); 00211 flash_manager_printf(" last flush_current_block ret=%i\r\n",flash_write_error); 00212 } 00213 // Close flash interface (even if there was an error during program_page) 00214 flash_uninit_error = intf->uninit(); 00215 flash_manager_printf(" intf->uninit() ret=%i\r\n", flash_uninit_error); 00216 // Reset variables to catch accidental use 00217 memset(buf, 0xFF, sizeof(buf)); 00218 buf_empty = true; 00219 current_sector_valid = false; 00220 current_write_block_addr = 0; 00221 current_write_block_size = 0; 00222 current_sector_addr = 0; 00223 current_sector_size = 0; 00224 last_addr = 0; 00225 state = STATE_CLOSED; 00226 00227 // Make sure an error from a page write or from an 00228 // uninit gets propagated 00229 if (flash_uninit_error != ERROR_SUCCESS) { 00230 return flash_uninit_error; 00231 } 00232 00233 if (flash_write_error != ERROR_SUCCESS) { 00234 return flash_write_error; 00235 } 00236 00237 return ERROR_SUCCESS; 00238 } 00239 00240 void flash_manager_set_page_erase(bool enabled) 00241 { 00242 config_ram_set_page_erase(enabled); 00243 page_erase_enabled = enabled; 00244 } 00245 00246 static bool flash_intf_valid(const flash_intf_t *flash_intf) 00247 { 00248 // Check for all requried members 00249 if (0 == flash_intf) { 00250 return false; 00251 } 00252 00253 if (0 == flash_intf->uninit) { 00254 return false; 00255 } 00256 00257 if (0 == flash_intf->program_page) { 00258 return false; 00259 } 00260 00261 if (0 == flash_intf->erase_sector) { 00262 return false; 00263 } 00264 00265 if (0 == flash_intf->erase_chip) { 00266 return false; 00267 } 00268 00269 if (0 == flash_intf->program_page_min_size) { 00270 return false; 00271 } 00272 00273 if (0 == flash_intf->erase_sector_size) { 00274 return false; 00275 } 00276 00277 if (0 == flash_intf->flash_busy) { 00278 return false; 00279 } 00280 00281 return true; 00282 } 00283 00284 static error_t flush_current_block(uint32_t addr){ 00285 // Write out current buffer if there is data in it 00286 error_t status = ERROR_SUCCESS; 00287 if (!buf_empty) { 00288 status = intf->program_page(current_write_block_addr, buf, current_write_block_size); 00289 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); 00290 buf_empty = true; 00291 } 00292 00293 // Setup for next block 00294 memset(buf, 0xFF, current_write_block_size); 00295 current_write_block_addr = ROUND_DOWN(addr,current_write_block_size); 00296 return status; 00297 } 00298 00299 static error_t setup_next_sector(uint32_t addr) 00300 { 00301 uint32_t min_prog_size; 00302 uint32_t sector_size; 00303 error_t status; 00304 min_prog_size = intf->program_page_min_size(addr); 00305 sector_size = intf->erase_sector_size(addr); 00306 00307 if ((min_prog_size <= 0) || (sector_size <= 0)) { 00308 // Either of these conditions could cause divide by 0 error 00309 util_assert(0); 00310 return ERROR_INTERNAL; 00311 } 00312 00313 // Assert required size and alignment 00314 util_assert(sizeof(buf) >= min_prog_size); 00315 util_assert(sizeof(buf) % min_prog_size == 0); 00316 util_assert(sector_size >= min_prog_size); 00317 util_assert(sector_size % min_prog_size == 0); 00318 // Setup global variables 00319 current_sector_addr = ROUND_DOWN(addr, sector_size); 00320 current_sector_size = sector_size; 00321 current_write_block_addr = current_sector_addr; 00322 current_write_block_size = MIN(sector_size, sizeof(buf)); 00323 00324 //check flash algo every sector change, addresses with different flash algo should be sector aligned 00325 if (intf->flash_algo_set) { 00326 status = intf->flash_algo_set(current_sector_addr); 00327 if (ERROR_SUCCESS != status) { 00328 intf->uninit(); 00329 return status; 00330 } 00331 } 00332 00333 if (page_erase_enabled) { 00334 // Erase the current sector 00335 status = intf->erase_sector(current_sector_addr); 00336 flash_manager_printf(" intf->erase_sector(addr=0x%x) ret=%i\r\n", current_sector_addr); 00337 if (ERROR_SUCCESS != status) { 00338 intf->uninit(); 00339 return status; 00340 } 00341 } 00342 00343 // Clear out buffer in case block size changed 00344 memset(buf, 0xFF, current_write_block_size); 00345 flash_manager_printf(" setup_next_sector(addr=0x%x) sect_addr=0x%x, write_addr=0x%x,\r\n", 00346 addr, current_sector_addr, current_write_block_addr); 00347 flash_manager_printf(" actual_write_size=0x%x, sector_size=0x%x, min_write=0x%x\r\n", 00348 current_write_block_size, current_sector_size, min_prog_size); 00349 return ERROR_SUCCESS; 00350 }
Generated on Tue Jul 12 2022 15:37:17 by
1.7.2