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

« Back to documentation index

Show/hide line numbers flash_hal_SAM3U.c Source File

flash_hal_SAM3U.c

Go to the documentation of this file.
00001 /**
00002  * @file    flash_hal_SAM3U.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 //#include "flash_hal.h"        // FlashOS Structures       //TODO - uncomment
00023 #include "target_config.h"    // target_device
00024 #include "cortex_m.h"
00025 #include "target_board.h"
00026 
00027 #define KEY_VALUE             (0x5A)
00028 #define FCMD_WP               (0x1)           // "Write page" command
00029 #define FCMD_EWP              (0x3)           // "Erase page and write page" command
00030 #define FCMD_CLB              (0x9)           // "Clear lock bit" command
00031 #define FCMD_GLB              (0xA)           // "Get lock bit" command
00032 #define FCMD_SGPB             (0xB)           // "Set General Purpose Bit" command
00033 #define FCMD_CGPB             (0xC)           // "Clear General Purpose Bit" command
00034 #define FCMD_GGPB             (0xD)           // "Get General Purpose Bit" command
00035 #define FCMD_EA               (0x5)           // "Erase all" command
00036 #define FMR_FWS               (0xF << 8)
00037 
00038 #define WDT_CR                   *(volatile uint32_t*)(0x400E1250)
00039 #define WDT_MR                   *(volatile uint32_t*)(0x400E1254)
00040 #define WDT_SR                   *(volatile uint32_t*)(0x400E1258)
00041 
00042 #define EEFC0_BASEADDR        (0x400E0800)
00043 #define EEFC1_BASEADDR        (0x400E0A00)
00044 #define FMR_FAM               (1 << 24)
00045 #define GPNVMB_BMS            (1)
00046 
00047 typedef struct {
00048     volatile uint32_t MC_FMR;
00049     volatile uint32_t MC_FCR;
00050     volatile uint32_t MC_FSR;
00051     volatile uint32_t MC_FRR;
00052 } SFR_TABLE;
00053 
00054 __attribute__((section("ram_func")))
00055 static void _FeedWDT(void)
00056 {
00057     //
00058     // Feed watchdog if enabled
00059     //
00060     if ((WDT_MR & (1 << 15)) == 0) {      // Is watchdog enabled ?
00061         WDT_CR = 0xA5000001;                // Feed it!
00062     }
00063 }
00064 
00065 /*********************************************************************
00066 *
00067 *       Static code
00068 *
00069 **********************************************************************
00070 */
00071 
00072 __attribute__((section("ram_func")))
00073 static void _WritePage(uint32_t Addr, volatile uint32_t *pSrc, int PerformErase)
00074 {
00075     SFR_TABLE *pSFRs;
00076     volatile uint32_t *pDest;
00077     uint32_t NumItemsInPageLeft;
00078     uint32_t iPage;
00079     uint32_t Status;
00080     //
00081     // Return value 0 == O.K.
00082     // Return value 1 == Error
00083     // Application assumes that this function always erases 4 KB
00084     // Application always calls this function with 4 KB aligned addresses
00085     //
00086     Addr |= 0x80000;   // Convert to physical flash address
00087     pSFRs = (SFR_TABLE *)(EEFC0_BASEADDR);
00088     pDest = (volatile uint32_t *)Addr;
00089     //
00090     // Fill page buffer use blank data in case of erase is requested
00091     //
00092     iPage = ((Addr - 0x80000) >> 8);
00093     NumItemsInPageLeft = (1 << 8) >> 2;
00094 
00095     if (PerformErase) {
00096         do {
00097             *pDest++ = 0xFFFFFFFF;
00098         } while (--NumItemsInPageLeft);
00099 
00100     } else {
00101         do {
00102             *pDest++ = *pSrc++;
00103         } while (--NumItemsInPageLeft);
00104     }
00105 
00106     //
00107     // Trigger flash operation
00108     //
00109     pSFRs->MC_FCR = (KEY_VALUE << 24) | (FCMD_EWP << 0) | (iPage << 8);  // Erase page and write with blank data
00110 
00111     do {
00112         _FeedWDT();
00113         Status = pSFRs->MC_FSR;
00114     } while ((Status & 1) == 0);
00115 }
00116 
00117 /*********************************************************************
00118 *
00119 *       Public code
00120 *
00121 **********************************************************************
00122 */
00123 __attribute__((section("ram_func")))
00124 uint32_t Init(uint32_t adr, uint32_t clk, uint32_t fnc)
00125 {
00126     //
00127     // No special init required
00128     //
00129     return (0);
00130 }
00131 
00132 __attribute__((section("ram_func")))
00133 uint32_t UnInit(uint32_t fnc)
00134 {
00135     //
00136     // No special uninit required
00137     //
00138     return (0);
00139 }
00140 
00141 __attribute__((section("ram_func")))
00142 uint32_t EraseChip(void)
00143 {
00144     if (g_board_info.target_cfg) {
00145         uint32_t Addr;
00146         //
00147         // Return value 0 == O.K.
00148         // Return value 1 == Error
00149         // Erase complete chip by erasing sector-by-sector
00150         Addr = g_board_info.target_cfg->flash_regions[0].start; //bootloader, interface flashing only concerns 1 flash region
00151 
00152         cortex_int_state_t state = cortex_int_get_and_disable();
00153         do {
00154             _WritePage(Addr, (volatile uint32_t *)0, 1);
00155             Addr += (1 << 8);
00156         } while (Addr < g_board_info.target_cfg->flash_regions[0].end);
00157         cortex_int_restore(state);
00158 
00159         return (0);  // O.K.
00160     }else {
00161         return (1);  //No flash algo
00162     }
00163 }
00164 
00165 __attribute__((section("ram_func")))
00166 uint32_t EraseSector(uint32_t adr)
00167 {
00168     uint32_t NumPagesLeft;
00169     //
00170     // Return value 0 == O.K.
00171     // Return value 1 == Error
00172     // Application assumes that this function always erases 1 KB
00173     // Application always calls this function with 1 KB aligned addresses
00174     //
00175     NumPagesLeft = 0x400 >> 8;                                         // SAM3U has 256 byte pages, DAPLink BTL/FW assumes 1 KB sectors
00176 
00177     cortex_int_state_t state = cortex_int_get_and_disable();
00178     do {
00179         _WritePage(adr, (volatile uint32_t *)0, 1);
00180         adr += (1 << 8);
00181     } while (--NumPagesLeft);
00182     cortex_int_restore(state);
00183 
00184     return (0);  // O.K.
00185 }
00186 
00187 __attribute__((section("ram_func")))
00188 uint32_t ProgramPage(uint32_t adr, uint32_t sz, uint32_t *buf)
00189 {
00190     uint32_t NumPagesLeft;
00191     unsigned char *temp_buf = (unsigned char *)buf;
00192     //
00193     // Return value 0 == O.K.
00194     // Return value 1 == Error
00195     // Seems to program page-wise
00196     // 1 page seems to be 1 KB
00197     // App always calls this function with 1 KB aligned start-adresses
00198     // Always called with multiple of 1 page to program
00199     //
00200     sz = ROUND_UP(sz, 256);    // Round up to page size
00201     NumPagesLeft = sz >> 8;    // SAM3U has 256 byte pages, DAPLink BTL/FW assumes 1 KB pages
00202 
00203     if (0 == NumPagesLeft) {
00204         return 1;
00205     }
00206 
00207     cortex_int_state_t state = cortex_int_get_and_disable();
00208     do {
00209         _WritePage(adr, (volatile uint32_t *)temp_buf, 0);
00210         adr += (1 << 8);
00211         temp_buf += (1 << 8);
00212     } while (--NumPagesLeft);
00213     cortex_int_restore(state);
00214 
00215     return (0);                                  // Finished without Errors
00216 }