Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers target_flash.c Source File

target_flash.c

Go to the documentation of this file.
00001 /**
00002  * @file    target_flash.c
00003  * @brief   Implementation of target_flash.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 #ifdef DRAG_N_DROP_SUPPORT
00024 #include <string.h>
00025 
00026 #include "target_config.h"
00027 #include "gpio.h"
00028 #include "target_config.h"
00029 #include "intelhex.h"
00030 #include "swd_host.h"
00031 #include "flash_intf.h"
00032 #include "util.h"
00033 #include "settings.h"
00034 #include "target_family.h"
00035 #include "target_board.h"
00036 
00037 #define DEFAULT_PROGRAM_PAGE_MIN_SIZE   (256u)
00038 
00039 typedef enum {
00040     STATE_CLOSED,
00041     STATE_OPEN,
00042     STATE_ERROR
00043 } state_t;
00044 
00045 static error_t target_flash_init(void);
00046 static error_t target_flash_uninit(void);
00047 static error_t target_flash_program_page(uint32_t adr, const uint8_t *buf, uint32_t size);
00048 static error_t target_flash_erase_sector(uint32_t addr);
00049 static error_t target_flash_erase_chip(void);
00050 static uint32_t target_flash_program_page_min_size(uint32_t addr);
00051 static uint32_t target_flash_erase_sector_size(uint32_t addr);
00052 static uint8_t target_flash_busy(void);
00053 static error_t target_flash_set(uint32_t addr);
00054 
00055 static const flash_intf_t flash_intf = {
00056     target_flash_init,
00057     target_flash_uninit,
00058     target_flash_program_page,
00059     target_flash_erase_sector,
00060     target_flash_erase_chip,
00061     target_flash_program_page_min_size,
00062     target_flash_erase_sector_size,
00063     target_flash_busy,
00064     target_flash_set,
00065 };
00066 
00067 static state_t state = STATE_CLOSED;
00068 
00069 const flash_intf_t *const flash_intf_target = &flash_intf;
00070 
00071 static flash_func_t last_flash_func = FLASH_FUNC_NOP;
00072 
00073 //saved flash algo
00074 static program_target_t * current_flash_algo = NULL;
00075 
00076 //saved default region for default flash algo
00077 static region_info_t * default_region = NULL;
00078 
00079 //saved flash start from flash algo
00080 static uint32_t flash_start = 0;
00081 
00082 static program_target_t * get_flash_algo(uint32_t addr)
00083 {
00084     region_info_t * flash_region = g_board_info.target_cfg->flash_regions;
00085 
00086     for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) {
00087         if (addr >= flash_region->start && addr <= flash_region->end) {
00088             flash_start = flash_region->start; //save the flash start
00089             if (flash_region->flash_algo) {
00090                 return flash_region->flash_algo;
00091             }else{
00092                 return NULL;
00093             }
00094         }
00095     }
00096 
00097     //could not find a flash algo for the region; use default
00098     if (default_region) {
00099         flash_start = default_region->start;
00100         return default_region->flash_algo;
00101     } else {
00102         return NULL;
00103     }
00104 }
00105 
00106 static error_t flash_func_start(flash_func_t func)
00107 {
00108     program_target_t * flash = current_flash_algo;
00109 
00110     if (last_flash_func != func)
00111     {
00112         // Finish the currently active function.
00113         if (FLASH_FUNC_NOP != last_flash_func &&
00114             ((flash->algo_flags & kAlgoSingleInitType ) == 0 || FLASH_FUNC_NOP == func ) &&
00115             0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->uninit, last_flash_func, 0, 0, 0, FLASHALGO_RETURN_BOOL)) {
00116             return ERROR_UNINIT;
00117         }
00118 
00119         // Start a new function.
00120         if (FLASH_FUNC_NOP != func &&
00121             ((flash->algo_flags & kAlgoSingleInitType ) == 0 || FLASH_FUNC_NOP == last_flash_func ) &&
00122             0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->init, flash_start, 0, func, 0, FLASHALGO_RETURN_BOOL)) {
00123             return ERROR_INIT;
00124         }
00125 
00126         last_flash_func = func;
00127     }
00128 
00129     return ERROR_SUCCESS;
00130 }
00131 
00132 static error_t target_flash_set(uint32_t addr)
00133 {
00134     program_target_t * new_flash_algo = get_flash_algo(addr);
00135     if (new_flash_algo == NULL) {
00136         return ERROR_ALGO_MISSING;
00137     }
00138     if(current_flash_algo != new_flash_algo){
00139         //run uninit to last func
00140         error_t status = flash_func_start(FLASH_FUNC_NOP);
00141         if (status != ERROR_SUCCESS) {
00142             return status;
00143         }
00144         // Download flash programming algorithm to target
00145         if (0 == swd_write_memory(new_flash_algo->algo_start, (uint8_t *)new_flash_algo->algo_blob, new_flash_algo->algo_size)) {
00146             return ERROR_ALGO_DL;
00147         }
00148 
00149         current_flash_algo = new_flash_algo;
00150 
00151     }
00152     return ERROR_SUCCESS;
00153 }
00154 
00155 static error_t target_flash_init()
00156 {
00157     if (g_board_info.target_cfg) {
00158         last_flash_func = FLASH_FUNC_NOP;
00159 
00160         current_flash_algo = NULL;
00161 
00162         if (0 == target_set_state(RESET_PROGRAM)) {
00163             return ERROR_RESET;
00164         }
00165 
00166         //get default region
00167         region_info_t * flash_region = g_board_info.target_cfg->flash_regions;
00168         for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) {
00169             if (flash_region->flags & kRegionIsDefault ) {
00170                 default_region = flash_region;
00171                 break;
00172             }
00173         }
00174 
00175         state = STATE_OPEN;
00176         return ERROR_SUCCESS;
00177     } else {
00178         return ERROR_FAILURE;
00179     }
00180 
00181 }
00182 
00183 static error_t target_flash_uninit(void)
00184 {
00185     if (g_board_info.target_cfg) {
00186         error_t status = flash_func_start(FLASH_FUNC_NOP);
00187         if (status != ERROR_SUCCESS) {
00188             return status;
00189         }
00190         if (config_get_auto_rst()) {
00191             // Resume the target if configured to do so
00192             target_set_state(RESET_RUN);
00193         } else {
00194             // Leave the target halted until a reset occurs
00195             target_set_state(RESET_PROGRAM);
00196         }
00197         // Check to see if anything needs to be done after programming.
00198         // This is usually a no-op for most targets.
00199         target_set_state(POST_FLASH_RESET);
00200 
00201         state = STATE_CLOSED;
00202         swd_off();
00203         return ERROR_SUCCESS;
00204     } else {
00205         return ERROR_FAILURE;
00206     }
00207 }
00208 
00209 static error_t target_flash_program_page(uint32_t addr, const uint8_t *buf, uint32_t size)
00210 {
00211     if (g_board_info.target_cfg) {
00212         error_t status = ERROR_SUCCESS;
00213         program_target_t * flash = current_flash_algo;
00214 
00215         if (!flash) {
00216             return ERROR_INTERNAL;
00217         }
00218 
00219         // check if security bits were set
00220         if (g_target_family && g_target_family->security_bits_set ){
00221             if (1 == g_target_family->security_bits_set (addr, (uint8_t *)buf, size)) {
00222                 return ERROR_SECURITY_BITS;
00223             }
00224         }
00225 
00226         status = flash_func_start(FLASH_FUNC_PROGRAM);
00227 
00228         if (status != ERROR_SUCCESS) {
00229             return status;
00230         }
00231 
00232         while (size > 0) {
00233             uint32_t write_size = MIN(size, flash->program_buffer_size);
00234 
00235             // Write page to buffer
00236             if (!swd_write_memory(flash->program_buffer, (uint8_t *)buf, write_size)) {
00237                 return ERROR_ALGO_DATA_SEQ;
00238             }
00239 
00240             // Run flash programming
00241             if (!swd_flash_syscall_exec(&flash->sys_call_s,
00242                                         flash->program_page,
00243                                         addr,
00244                                         write_size,
00245                                         flash->program_buffer,
00246                                         0,
00247                                         FLASHALGO_RETURN_BOOL)) {
00248                 return ERROR_WRITE;
00249             }
00250 
00251             if (config_get_automation_allowed()) {
00252                 // Verify data flashed if in automation mode
00253                 if (flash->verify != 0) {
00254                     status = flash_func_start(FLASH_FUNC_VERIFY);
00255                     if (status != ERROR_SUCCESS) {
00256                         return status;
00257                     }
00258                     flash_algo_return_t return_type;
00259                     if ((flash->algo_flags & kAlgoVerifyReturnsAddress ) != 0) {
00260                         return_type = FLASHALGO_RETURN_POINTER;
00261                     } else {
00262                         return_type = FLASHALGO_RETURN_BOOL;
00263                     }
00264                     if (!swd_flash_syscall_exec(&flash->sys_call_s,
00265                                         flash->verify,
00266                                         addr,
00267                                         write_size,
00268                                         flash->program_buffer,
00269                                         0,
00270                                         return_type)) {
00271                         return ERROR_WRITE_VERIFY;
00272                     }
00273                 } else {
00274                     while (write_size > 0) {
00275                         uint8_t rb_buf[16];
00276                         uint32_t verify_size = MIN(write_size, sizeof(rb_buf));
00277                         if (!swd_read_memory(addr, rb_buf, verify_size)) {
00278                             return ERROR_ALGO_DATA_SEQ;
00279                         }
00280                         if (memcmp(buf, rb_buf, verify_size) != 0) {
00281                             return ERROR_WRITE_VERIFY;
00282                         }
00283                         addr += verify_size;
00284                         buf += verify_size;
00285                         size -= verify_size;
00286                         write_size -= verify_size;
00287                     }
00288                     continue;
00289                 }
00290             }
00291             addr += write_size;
00292             buf += write_size;
00293             size -= write_size;
00294 
00295         }
00296 
00297         return ERROR_SUCCESS;
00298 
00299     } else {
00300         return ERROR_FAILURE;
00301     }
00302 }
00303 
00304 static error_t target_flash_erase_sector(uint32_t addr)
00305 {
00306     if (g_board_info.target_cfg) {
00307         error_t status = ERROR_SUCCESS;
00308         program_target_t * flash = current_flash_algo;
00309 
00310         if (!flash) {
00311             return ERROR_INTERNAL;
00312         }
00313 
00314         // Check to make sure the address is on a sector boundary
00315         if ((addr % target_flash_erase_sector_size(addr)) != 0) {
00316             return ERROR_ERASE_SECTOR;
00317         }
00318 
00319         status = flash_func_start(FLASH_FUNC_ERASE);
00320 
00321         if (status != ERROR_SUCCESS) {
00322             return status;
00323         }
00324 
00325         if (0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->erase_sector, addr, 0, 0, 0, FLASHALGO_RETURN_BOOL)) {
00326             return ERROR_ERASE_SECTOR;
00327         }
00328 
00329         return ERROR_SUCCESS;
00330     } else {
00331         return ERROR_FAILURE;
00332     }
00333 }
00334 
00335 static error_t target_flash_erase_chip(void)
00336 {
00337     if (g_board_info.target_cfg){
00338         error_t status = ERROR_SUCCESS;
00339         region_info_t * flash_region = g_board_info.target_cfg->flash_regions;
00340 
00341         for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) {
00342             program_target_t *new_flash_algo = get_flash_algo(flash_region->start);
00343             if ((new_flash_algo != NULL) && ((new_flash_algo->algo_flags & kAlgoSkipChipErase ) != 0)) {
00344                 // skip flash region
00345                 continue;
00346             }
00347             status = target_flash_set(flash_region->start);
00348             if (status != ERROR_SUCCESS) {
00349                 return status;
00350             }
00351             status = flash_func_start(FLASH_FUNC_ERASE);
00352             if (status != ERROR_SUCCESS) {
00353                 return status;
00354             }
00355             if (0 == swd_flash_syscall_exec(&current_flash_algo->sys_call_s, current_flash_algo->erase_chip, 0, 0, 0, 0, FLASHALGO_RETURN_BOOL)) {
00356                 return ERROR_ERASE_ALL;
00357             }
00358         }
00359 
00360         // Reset and re-initialize the target after the erase if required
00361         if (g_board_info.target_cfg->erase_reset) {
00362             status = target_flash_init();
00363         }
00364 
00365         return status;
00366     } else {
00367         return ERROR_FAILURE;
00368     }
00369 }
00370 
00371 static uint32_t target_flash_program_page_min_size(uint32_t addr)
00372 {
00373     if (g_board_info.target_cfg){
00374         uint32_t size = DEFAULT_PROGRAM_PAGE_MIN_SIZE;
00375         if (size > target_flash_erase_sector_size(addr)) {
00376             size = target_flash_erase_sector_size(addr);
00377         }
00378         return size;
00379     } else {
00380         return 0;
00381     }
00382 }
00383 
00384 static uint32_t target_flash_erase_sector_size(uint32_t addr)
00385 {
00386     if (g_board_info.target_cfg){
00387         if(g_board_info.target_cfg->sector_info_length > 0) {
00388             int sector_index = g_board_info.target_cfg->sector_info_length - 1;
00389             for (; sector_index >= 0; sector_index--) {
00390                 if (addr >= g_board_info.target_cfg->sectors_info[sector_index].start) {
00391                     return g_board_info.target_cfg->sectors_info[sector_index].size;
00392                 }
00393             }
00394         }
00395         //sector information should be in sector_info
00396         util_assert(0);
00397         return 0;
00398     } else {
00399         return 0;
00400     }
00401 }
00402 
00403 static uint8_t target_flash_busy(void){
00404     return (state == STATE_OPEN);
00405 }
00406 #endif