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

« Back to documentation index

Show/hide line numbers FlashPrg.c Source File

FlashPrg.c

00001 /* CMSIS-DAP Interface Firmware
00002  * Copyright (c) 2009-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "FlashOS.h"
00018 #include "max32620.h"
00019 #include "flc_regs.h"
00020 
00021 /******************************************************************************/
00022 static inline int FLC_Busy(void)
00023 {
00024     return (MXC_FLC->ctrl & (MXC_F_FLC_CTRL_WRITE | MXC_F_FLC_CTRL_MASS_ERASE | MXC_F_FLC_CTRL_PAGE_ERASE));
00025 }
00026 
00027 /******************************************************************************/
00028 uint32_t Init(uint32_t adr, uint32_t clk, uint32_t fnc)
00029 {
00030     /* Check if the flash controller is busy */
00031     if (FLC_Busy()) {
00032         return 1;
00033     }
00034 
00035     /* Enable automatic calculation of the clock divider to generate a 1MHz clock from the APB clock */
00036     MXC_FLC->perform |= MXC_F_FLC_PERFORM_AUTO_CLKDIV;
00037 
00038     /* The flash controller will stall any reads while flash operations are in
00039      * progress. Disable the legacy failure detection logic that would flag reads
00040      * during flash operations as errors.
00041      */
00042     MXC_FLC->perform |= MXC_F_FLC_PERFORM_EN_PREVENT_FAIL;
00043 
00044     return 0;
00045 }
00046 
00047 /******************************************************************************/
00048 uint32_t UnInit(uint32_t fnc)
00049 {
00050     /* Lock flash */
00051     MXC_FLC->ctrl &= ~MXC_F_FLC_CTRL_FLSH_UNLOCK;
00052 
00053     return  0;  // Finished without Errors
00054 }
00055 
00056 /******************************************************************************/
00057 /*
00058  *  Erase complete Flash Memory
00059  *    Return Value:   0 - OK,  1 - Failed
00060  */
00061 int EraseChip(void)
00062 {
00063     /* Check if the flash controller is busy */
00064     if (FLC_Busy()) {
00065         return 1;
00066     }
00067 
00068     /* Clear stale errors. Interrupt flags can only be written to zero, so this is safe */
00069     MXC_FLC->intr &= ~MXC_F_FLC_INTR_FAILED_IF;
00070 
00071     /* Unlock flash */
00072     MXC_FLC->ctrl = (MXC_FLC->ctrl & ~MXC_F_FLC_CTRL_FLSH_UNLOCK) | (MXC_V_FLC_FLSH_UNLOCK_KEY << MXC_F_FLC_CTRL_FLSH_UNLOCK_POS);
00073 
00074     /* Write the Erase Code */
00075     MXC_FLC->ctrl = (MXC_FLC->ctrl & ~MXC_F_FLC_CTRL_ERASE_CODE) | (MXC_V_FLC_ERASE_CODE_MASS_ERASE << MXC_F_FLC_CTRL_ERASE_CODE_POS);
00076 
00077     /* Start the mass erase */
00078     MXC_FLC->ctrl |= MXC_F_FLC_CTRL_MASS_ERASE;
00079 
00080     /* Wait until flash operation is complete */
00081     while (FLC_Busy());
00082 
00083     /* Lock flash */
00084     MXC_FLC->ctrl &= ~(MXC_F_FLC_CTRL_FLSH_UNLOCK | MXC_F_FLC_CTRL_ERASE_CODE);
00085 
00086     /* Check for failures */
00087     if (MXC_FLC->intr & MXC_F_FLC_INTR_FAILED_IF) {
00088         /* Interrupt flags can only be written to zero, so this is safe */
00089         MXC_FLC->intr &= ~MXC_F_FLC_INTR_FAILED_IF;
00090         return 1;
00091     }
00092 
00093     return 0;
00094 }
00095 
00096 /******************************************************************************/
00097 /*
00098  *  Erase Sector in Flash Memory
00099  *    Parameter:      address:  Sector Address
00100  *    Return Value:   0 - OK,  1 - Failed
00101  */
00102 int EraseSector(unsigned long address)
00103 {
00104     /* Wait until flash operation is complete */
00105     while (FLC_Busy());
00106 
00107     /* Clear stale errors. Interrupt flags can only be written to zero, so this is safe */
00108     MXC_FLC->intr &= ~MXC_F_FLC_INTR_FAILED_IF;
00109 
00110     /* Unlock flash */
00111     MXC_FLC->ctrl = (MXC_FLC->ctrl & ~MXC_F_FLC_CTRL_FLSH_UNLOCK) | (MXC_V_FLC_FLSH_UNLOCK_KEY << MXC_F_FLC_CTRL_FLSH_UNLOCK_POS);
00112 
00113     /* Write page erase code */
00114     MXC_FLC->ctrl = (MXC_FLC->ctrl & ~MXC_F_FLC_CTRL_ERASE_CODE) | (MXC_V_FLC_ERASE_CODE_PAGE_ERASE << MXC_F_FLC_CTRL_ERASE_CODE_POS);
00115 
00116     /* Erase the request page */
00117     MXC_FLC->faddr = address;
00118     MXC_FLC->ctrl |= MXC_F_FLC_CTRL_PAGE_ERASE;
00119 
00120     /* Wait until flash operation is complete */
00121     while (FLC_Busy());
00122 
00123     /* Lock flash */
00124     MXC_FLC->ctrl &= ~(MXC_F_FLC_CTRL_FLSH_UNLOCK | MXC_F_FLC_CTRL_ERASE_CODE);
00125 
00126     /* Check for failures */
00127     if (MXC_FLC->intr & MXC_F_FLC_INTR_FAILED_IF) {
00128         /* Interrupt flags can only be written to zero, so this is safe */
00129         MXC_FLC->intr &= ~MXC_F_FLC_INTR_FAILED_IF;
00130         return 1;
00131     }
00132 
00133     return 0;
00134 }
00135 
00136 /******************************************************************************/
00137 /*
00138  *  Program Page in Flash Memory
00139  *    Parameter:      address:  Page Start Address
00140  *                    size:     Page Size
00141  *                    buffer:   Page Data
00142  *    Return Value:   0 - OK,  1 - Failed
00143  */
00144 int ProgramPage(unsigned long address, unsigned long size, unsigned char *buffer8)
00145 {
00146     unsigned long remaining = size;
00147     unsigned long *buffer = (unsigned long *)buffer8;
00148 
00149     // Only accept 32-bit aligned pointers
00150     if ((unsigned long)buffer8 & 0x3) {
00151         return 1;
00152     }
00153     buffer = (unsigned long *)buffer8;
00154 
00155     /* Check if the flash controller is busy */
00156     if (FLC_Busy()) {
00157         return 1;
00158     }
00159 
00160     /* Unlock flash */
00161     MXC_FLC->ctrl = (MXC_FLC->ctrl & ~MXC_F_FLC_CTRL_FLSH_UNLOCK) | (MXC_V_FLC_FLSH_UNLOCK_KEY << MXC_F_FLC_CTRL_FLSH_UNLOCK_POS);
00162 
00163     while (remaining >= 4) {
00164         MXC_FLC->faddr = address;
00165         MXC_FLC->fdata = *buffer++;
00166         MXC_FLC->ctrl |= MXC_F_FLC_CTRL_WRITE_ENABLE;
00167         MXC_FLC->ctrl |= MXC_F_FLC_CTRL_WRITE;
00168 
00169         /* Wait until flash operation is complete */
00170         while (FLC_Busy());
00171 
00172         address += 4;
00173         remaining -= 4;
00174     }
00175 
00176     if (remaining > 0) {
00177         uint32_t last_word;
00178         uint32_t mask;
00179 
00180         last_word = 0xffffffff;
00181         mask = 0xff;
00182 
00183         while (remaining > 0) {
00184             last_word &= (*buffer | ~mask);
00185             mask <<= 8;
00186             remaining--;
00187         }
00188 
00189         MXC_FLC->faddr = address;
00190         MXC_FLC->fdata = last_word;
00191         MXC_FLC->ctrl |= MXC_F_FLC_CTRL_WRITE_ENABLE;
00192 
00193         /* Wait until flash operation is complete */
00194         while (FLC_Busy());
00195     }
00196 
00197     /* Lock flash */
00198     MXC_FLC->ctrl &= ~MXC_F_FLC_CTRL_FLSH_UNLOCK;
00199 
00200     /* Check for failures */
00201     if (MXC_FLC->intr & MXC_F_FLC_INTR_FAILED_IF) {
00202         /* Interrupt flags can only be written to zero, so this is safe */
00203         MXC_FLC->intr &= ~MXC_F_FLC_INTR_FAILED_IF;
00204         return 1;
00205     }
00206 
00207     return  0;
00208 }