~ruther/qmk_firmware

1a68feb842ebcc6a7d1aef7cd7f83865cc18fab1 — Joel Challis 4 years ago 6cb8a65
Implement F4 eeprom (#14195)

M common_features.mk => common_features.mk +7 -1
@@ 177,8 177,14 @@ else
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
        OPT_DEFS += -DEEPROM_EMU_STM32F072xB
      else ifneq ($(filter $(MCU_SERIES)_$(MCU_LDSCRIPT),STM32F4xx_STM32F401xC STM32F4xx_STM32F411xE),)
        OPT_DEFS += -DEEPROM_DRIVER
        COMMON_VPATH += $(DRIVER_PATH)/eeprom
        SRC += eeprom_driver.c
        SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c
        SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
        OPT_DEFS += -DEEPROM_EMU_STM32F401xC
      else ifeq ($(MCU_SERIES)_$(MCU_LDSCRIPT), STM32F0xx_STM32F042x6)

        # Stack sizes: Since this chip has limited RAM capacity, the stack area needs to be reduced.
        # This ensures that the EEPROM page buffer fits into RAM
        USE_PROCESS_STACKSIZE = 0x600

A platforms/chibios/boards/common/ld/STM32F401xC.ld => platforms/chibios/boards/common/ld/STM32F401xC.ld +85 -0
@@ 0,0 1,85 @@
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/*
 * STM32F401xC memory setup.
 */
MEMORY
{
    flash0 (rx) : org = 0x08000000, len = 16k        /* Sector 0    - Init code as ROM bootloader assumes application starts here */
    flash1 (rx) : org = 0x08004000, len = 16k        /* Sector 1    - Emulated eeprom */
    flash2 (rx) : org = 0x08008000, len = 256k - 32k /* Sector 2..6 - Rest of firmware */
    flash3 (rx) : org = 0x00000000, len = 0
    flash4 (rx) : org = 0x00000000, len = 0
    flash5 (rx) : org = 0x00000000, len = 0
    flash6 (rx) : org = 0x00000000, len = 0
    flash7 (rx) : org = 0x00000000, len = 0
    ram0   (wx) : org = 0x20000000, len = 64k
    ram1   (wx) : org = 0x00000000, len = 0
    ram2   (wx) : org = 0x00000000, len = 0
    ram3   (wx) : org = 0x00000000, len = 0
    ram4   (wx) : org = 0x00000000, len = 0
    ram5   (wx) : org = 0x00000000, len = 0
    ram6   (wx) : org = 0x00000000, len = 0
    ram7   (wx) : org = 0x00000000, len = 0
}

/* For each data/text section two region are defined, a virtual region
   and a load region (_LMA suffix).*/

/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);

/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash2);
REGION_ALIAS("XTORS_FLASH_LMA", flash2);

/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash2);
REGION_ALIAS("TEXT_FLASH_LMA", flash2);

/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash2);
REGION_ALIAS("RODATA_FLASH_LMA", flash2);

/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash2);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);

/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);

/* RAM region to be used for Main stack. This stack accommodates the processing
   of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);

/* RAM region to be used for the process stack. This is the stack used by
   the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);

/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash2);

/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);

/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);

/* Generic rules inclusion.*/
INCLUDE rules.ld

A platforms/chibios/boards/common/ld/STM32F411xE.ld => platforms/chibios/boards/common/ld/STM32F411xE.ld +85 -0
@@ 0,0 1,85 @@
/*
    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/*
 * STM32F411xE memory setup.
 */
MEMORY
{
    flash0 (rx) : org = 0x08000000, len = 16k        /* Sector 0    - Init code as ROM bootloader assumes application starts here */
    flash1 (rx) : org = 0x08004000, len = 16k        /* Sector 1    - Emulated eeprom */
    flash2 (rx) : org = 0x08008000, len = 512k - 32k /* Sector 2..7 - Rest of firmware */
    flash3 (rx) : org = 0x00000000, len = 0
    flash4 (rx) : org = 0x00000000, len = 0
    flash5 (rx) : org = 0x00000000, len = 0
    flash6 (rx) : org = 0x00000000, len = 0
    flash7 (rx) : org = 0x00000000, len = 0
    ram0   (wx) : org = 0x20000000, len = 128k
    ram1   (wx) : org = 0x00000000, len = 0
    ram2   (wx) : org = 0x00000000, len = 0
    ram3   (wx) : org = 0x00000000, len = 0
    ram4   (wx) : org = 0x00000000, len = 0
    ram5   (wx) : org = 0x00000000, len = 0
    ram6   (wx) : org = 0x00000000, len = 0
    ram7   (wx) : org = 0x00000000, len = 0
}

/* For each data/text section two region are defined, a virtual region
   and a load region (_LMA suffix).*/

/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);

/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash2);
REGION_ALIAS("XTORS_FLASH_LMA", flash2);

/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash2);
REGION_ALIAS("TEXT_FLASH_LMA", flash2);

/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash2);
REGION_ALIAS("RODATA_FLASH_LMA", flash2);

/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash2);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);

/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);

/* RAM region to be used for Main stack. This stack accommodates the processing
   of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);

/* RAM region to be used for the process stack. This is the stack used by
   the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);

/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash2);

/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);

/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);

/* Generic rules inclusion.*/
INCLUDE rules.ld

M tmk_core/common/chibios/eeprom_stm32_defs.h => tmk_core/common/chibios/eeprom_stm32_defs.h +13 -4
@@ 32,6 32,13 @@
#        ifndef FEE_PAGE_COUNT
#            define FEE_PAGE_COUNT 4  // How many pages are used
#        endif
#    elif defined(STM32F401xC) || defined(STM32F411xE)
#        ifndef FEE_PAGE_SIZE
#            define FEE_PAGE_SIZE 0x4000  // Page size = 16KByte
#        endif
#        ifndef FEE_PAGE_COUNT
#            define FEE_PAGE_COUNT 1  // How many pages are used
#        endif
#    endif
#endif



@@ 40,17 47,19 @@
#        define FEE_MCU_FLASH_SIZE 32  // Size in Kb
#    elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB)
#        define FEE_MCU_FLASH_SIZE 128  // Size in Kb
#    elif defined(STM32F303xC)
#    elif defined(STM32F303xC) || defined(STM32F401xC)
#        define FEE_MCU_FLASH_SIZE 256  // Size in Kb
#    elif defined(STM32F103xE)
#    elif defined(STM32F103xE) || defined(STM32F411xE)
#        define FEE_MCU_FLASH_SIZE 512  // Size in Kb
#    endif
#endif

/* Start of the emulated eeprom */
#if !defined(FEE_PAGE_BASE_ADDRESS)
#    if 0
/* TODO: Add support for F4 */
#    if defined(STM32F401xC) || defined(STM32F411xE)
#        ifndef FEE_PAGE_BASE_ADDRESS
#            define FEE_PAGE_BASE_ADDRESS 0x08004000  // bodge to force 2nd 16k page
#        endif
#    else
#        ifndef FEE_FLASH_BASE
#            define FEE_FLASH_BASE 0x8000000

M tmk_core/common/chibios/flash_stm32.c => tmk_core/common/chibios/flash_stm32.c +40 -1
@@ 23,6 23,29 @@
#    define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
#endif

#if defined(EEPROM_EMU_STM32F401xC)
#    define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)

#    define FLASH_KEY1 0x45670123U
#    define FLASH_KEY2 0xCDEF89ABU

static uint8_t ADDR2PAGE(uint32_t Page_Address) {
    switch (Page_Address) {
        case 0x08000000 ... 0x08003FFF:
            return 0;
        case 0x08004000 ... 0x08007FFF:
            return 1;
        case 0x08008000 ... 0x0800BFFF:
            return 2;
        case 0x0800C000 ... 0x0800FFFF:
            return 3;
    }

    // TODO: bad times...
    return 7;
}
#endif

/* Delay definition */
#define EraseTimeout ((uint32_t)0x00000FFF)
#define ProgramTimeout ((uint32_t)0x0000001F)


@@ 53,7 76,9 @@ FLASH_Status FLASH_GetStatus(void) {

    if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;

#if defined(FLASH_OBR_OPTERR)
    if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
#endif

    return FLASH_COMPLETE;
}


@@ 95,15 120,24 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {

    if (status == FLASH_COMPLETE) {
        /* if the previous operation is completed, proceed to erase the page */
#if defined(FLASH_CR_SNB)
        FLASH->CR &= ~FLASH_CR_SNB;
        FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
#else
        FLASH->CR |= FLASH_CR_PER;
        FLASH->AR = Page_Address;
#endif
        FLASH->CR |= FLASH_CR_STRT;

        /* Wait for last operation to be completed */
        status = FLASH_WaitForLastOperation(EraseTimeout);
        if (status != FLASH_TIMEOUT) {
            /* if the erase operation is completed, disable the PER Bit */
            /* if the erase operation is completed, disable the configured Bits */
#if defined(FLASH_CR_SNB)
            FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
#else
            FLASH->CR &= ~FLASH_CR_PER;
#endif
        }
        FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
    }


@@ 126,6 160,11 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
        status = FLASH_WaitForLastOperation(ProgramTimeout);
        if (status == FLASH_COMPLETE) {
            /* if the previous operation is completed, proceed to program the new data */

#if defined(FLASH_CR_PSIZE)
            FLASH->CR &= ~FLASH_CR_PSIZE;
            FLASH->CR |= FLASH_CR_PSIZE_0;
#endif
            FLASH->CR |= FLASH_CR_PG;
            *(__IO uint16_t*)Address = Data;
            /* Wait for last operation to be completed */