From 1a68feb842ebcc6a7d1aef7cd7f83865cc18fab1 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Wed, 15 Sep 2021 16:30:26 +0100 Subject: [PATCH] Implement F4 eeprom (#14195) --- common_features.mk | 8 +- .../chibios/boards/common/ld/STM32F401xC.ld | 85 +++++++++++++++++++ .../chibios/boards/common/ld/STM32F411xE.ld | 85 +++++++++++++++++++ tmk_core/common/chibios/eeprom_stm32_defs.h | 17 +++- tmk_core/common/chibios/flash_stm32.c | 41 ++++++++- 5 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 platforms/chibios/boards/common/ld/STM32F401xC.ld create mode 100644 platforms/chibios/boards/common/ld/STM32F411xE.ld diff --git a/common_features.mk b/common_features.mk index ddb7112fd8..2cd78ceb66 100644 --- a/common_features.mk +++ b/common_features.mk @@ -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 diff --git a/platforms/chibios/boards/common/ld/STM32F401xC.ld b/platforms/chibios/boards/common/ld/STM32F401xC.ld new file mode 100644 index 0000000000..8fae66cec9 --- /dev/null +++ b/platforms/chibios/boards/common/ld/STM32F401xC.ld @@ -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 diff --git a/platforms/chibios/boards/common/ld/STM32F411xE.ld b/platforms/chibios/boards/common/ld/STM32F411xE.ld new file mode 100644 index 0000000000..aea8084b51 --- /dev/null +++ b/platforms/chibios/boards/common/ld/STM32F411xE.ld @@ -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 diff --git a/tmk_core/common/chibios/eeprom_stm32_defs.h b/tmk_core/common/chibios/eeprom_stm32_defs.h index 22b4ab858e..57de42c6ba 100644 --- a/tmk_core/common/chibios/eeprom_stm32_defs.h +++ b/tmk_core/common/chibios/eeprom_stm32_defs.h @@ -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 diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c index 6b80ff71c3..8f10903d3d 100644 --- a/tmk_core/common/chibios/flash_stm32.c +++ b/tmk_core/common/chibios/flash_stm32.c @@ -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 */