qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

legacy_flash_ops.c (6488B)


      1 /*
      2  * This software is experimental and a work in progress.
      3  * Under no circumstances should these files be used in relation to any critical system(s).
      4  * Use of these files is at your own risk.
      5  *
      6  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
      7  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
      8  * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      9  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     10  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     11  * DEALINGS IN THE SOFTWARE.
     12  *
     13  * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
     14  * https://github.com/leaflabs/libmaple
     15  *
     16  * Modifications for QMK and STM32F303 by Yiancar
     17  */
     18 
     19 #include <hal.h>
     20 #include "legacy_flash_ops.h"
     21 
     22 #if defined(STM32F1XX)
     23 #    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
     24 #endif
     25 
     26 #if defined(MCU_GD32V)
     27 /* GigaDevice GD32VF103 is a STM32F103 clone at heart. */
     28 #    include "gd32v_compatibility.h"
     29 #endif
     30 
     31 #if defined(STM32F4XX)
     32 #    define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)
     33 
     34 #    define FLASH_KEY1 0x45670123U
     35 #    define FLASH_KEY2 0xCDEF89ABU
     36 
     37 static uint8_t ADDR2PAGE(uint32_t Page_Address) {
     38     switch (Page_Address) {
     39         case 0x08000000 ... 0x08003FFF:
     40             return 0;
     41         case 0x08004000 ... 0x08007FFF:
     42             return 1;
     43         case 0x08008000 ... 0x0800BFFF:
     44             return 2;
     45         case 0x0800C000 ... 0x0800FFFF:
     46             return 3;
     47     }
     48 
     49     // TODO: bad times...
     50     return 7;
     51 }
     52 #endif
     53 
     54 /* Delay definition */
     55 #define EraseTimeout ((uint32_t)0x00000FFF)
     56 #define ProgramTimeout ((uint32_t)0x0000001F)
     57 
     58 #define ASSERT(exp) (void)((0))
     59 
     60 /**
     61  * @brief  Inserts a time delay.
     62  * @param  None
     63  * @retval None
     64  */
     65 static void delay(void) {
     66     __IO uint32_t i = 0;
     67     for (i = 0xFF; i != 0; i--) {
     68     }
     69 }
     70 
     71 /**
     72  * @brief  Returns the FLASH Status.
     73  * @param  None
     74  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
     75  *   FLASH_ERROR_WRP or FLASH_COMPLETE
     76  */
     77 FLASH_Status FLASH_GetStatus(void) {
     78     if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) return FLASH_BUSY;
     79 
     80     if ((FLASH->SR & FLASH_SR_PGERR) != 0) return FLASH_ERROR_PG;
     81 
     82     if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
     83 
     84 #if defined(FLASH_OBR_OPTERR)
     85     if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
     86 #endif
     87 
     88     return FLASH_COMPLETE;
     89 }
     90 
     91 /**
     92  * @brief  Waits for a Flash operation to complete or a TIMEOUT to occur.
     93  * @param  Timeout: FLASH progamming Timeout
     94  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
     95  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
     96  */
     97 FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
     98     FLASH_Status status;
     99 
    100     /* Check for the Flash Status */
    101     status = FLASH_GetStatus();
    102     /* Wait for a Flash operation to complete or a TIMEOUT to occur */
    103     while ((status == FLASH_BUSY) && (Timeout != 0x00)) {
    104         delay();
    105         status = FLASH_GetStatus();
    106         Timeout--;
    107     }
    108     if (Timeout == 0) status = FLASH_TIMEOUT;
    109     /* Return the operation status */
    110     return status;
    111 }
    112 
    113 /**
    114  * @brief  Erases a specified FLASH page.
    115  * @param  Page_Address: The page address to be erased.
    116  * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
    117  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
    118  */
    119 FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
    120     FLASH_Status status = FLASH_COMPLETE;
    121     /* Check the parameters */
    122     ASSERT(IS_FLASH_ADDRESS(Page_Address));
    123     /* Wait for last operation to be completed */
    124     status = FLASH_WaitForLastOperation(EraseTimeout);
    125 
    126     if (status == FLASH_COMPLETE) {
    127         /* if the previous operation is completed, proceed to erase the page */
    128 #if defined(FLASH_CR_SNB)
    129         FLASH->CR &= ~FLASH_CR_SNB;
    130         FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
    131 #else
    132         FLASH->CR |= FLASH_CR_PER;
    133         FLASH->AR = Page_Address;
    134 #endif
    135         FLASH->CR |= FLASH_CR_STRT;
    136 
    137         /* Wait for last operation to be completed */
    138         status = FLASH_WaitForLastOperation(EraseTimeout);
    139         if (status != FLASH_TIMEOUT) {
    140             /* if the erase operation is completed, disable the configured Bits */
    141 #if defined(FLASH_CR_SNB)
    142             FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
    143 #else
    144             FLASH->CR &= ~FLASH_CR_PER;
    145 #endif
    146         }
    147         FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
    148     }
    149     /* Return the Erase Status */
    150     return status;
    151 }
    152 
    153 /**
    154  * @brief  Programs a half word at a specified address.
    155  * @param  Address: specifies the address to be programmed.
    156  * @param  Data: specifies the data to be programmed.
    157  * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
    158  *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
    159  */
    160 FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
    161     FLASH_Status status = FLASH_BAD_ADDRESS;
    162 
    163     if (IS_FLASH_ADDRESS(Address)) {
    164         /* Wait for last operation to be completed */
    165         status = FLASH_WaitForLastOperation(ProgramTimeout);
    166         if (status == FLASH_COMPLETE) {
    167             /* if the previous operation is completed, proceed to program the new data */
    168 
    169 #if defined(FLASH_CR_PSIZE)
    170             FLASH->CR &= ~FLASH_CR_PSIZE;
    171             FLASH->CR |= FLASH_CR_PSIZE_0;
    172 #endif
    173             FLASH->CR |= FLASH_CR_PG;
    174             *(__IO uint16_t *)Address = Data;
    175             /* Wait for last operation to be completed */
    176             status = FLASH_WaitForLastOperation(ProgramTimeout);
    177             if (status != FLASH_TIMEOUT) {
    178                 /* if the program operation is completed, disable the PG Bit */
    179                 FLASH->CR &= ~FLASH_CR_PG;
    180             }
    181             FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
    182         }
    183     }
    184     return status;
    185 }
    186 
    187 /**
    188  * @brief  Unlocks the FLASH Program Erase Controller.
    189  * @param  None
    190  * @retval None
    191  */
    192 void FLASH_Unlock(void) {
    193     if (FLASH->CR & FLASH_CR_LOCK) {
    194         /* Authorize the FPEC Access */
    195         FLASH->KEYR = FLASH_KEY1;
    196         FLASH->KEYR = FLASH_KEY2;
    197     }
    198 }
    199 
    200 /**
    201  * @brief  Locks the FLASH Program Erase Controller.
    202  * @param  None
    203  * @retval None
    204  */
    205 void FLASH_Lock(void) {
    206     /* Set the Lock Bit to lock the FPEC and the FCR */
    207     FLASH->CR |= FLASH_CR_LOCK;
    208 }