arch/arm/stm32f0l0g0: Add STM32G0 Flash driver.
Add arch files and Kconfig options to interface with the progmem driver on STM32G0 MCUs. Signed-off-by: Tyler Bennett <tbennett@2g-eng.com>
This commit is contained in:
parent
11d444403e
commit
9fca766bd4
7 changed files with 1391 additions and 39 deletions
|
|
@ -517,6 +517,7 @@ config ARCH_CHIP_STM32L0
|
|||
config ARCH_CHIP_STM32G0
|
||||
bool "STMicro STM32 G0"
|
||||
select ARCH_CORTEXM0
|
||||
select ARCH_HAVE_PROGMEM
|
||||
---help---
|
||||
STMicro STM32G0 architectures (ARM Cortex-M0+).
|
||||
|
||||
|
|
@ -1487,7 +1488,7 @@ config ARM_SEMIHOSTING_HOSTFS_CACHE_COHERENCE
|
|||
bool "Cache coherence in semihosting hostfs"
|
||||
depends on ARCH_DCACHE
|
||||
---help---
|
||||
Flush & Invalidte cache before & after bkpt instruction.
|
||||
Flush & Invalidate cache before & after bkpt instruction.
|
||||
|
||||
endif # ARM_SEMIHOSTING_HOSTFS
|
||||
|
||||
|
|
|
|||
|
|
@ -454,81 +454,193 @@ config ARCH_CHIP_STM32F098VC
|
|||
config ARCH_CHIP_STM32G070CB
|
||||
bool "STM32G070CB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G070KB
|
||||
bool "STM32G070KB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G070RB
|
||||
bool "STM32G070RB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071EB
|
||||
bool "STM32G071EB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071G8
|
||||
bool "STM32G071G8"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071GB
|
||||
bool "STM32G071GB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071G8XN
|
||||
bool "STM32G071G8XN"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071GBXN
|
||||
bool "STM32G071GBXN"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071K8
|
||||
bool "STM32G071K8"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071KB
|
||||
bool "STM32G071KB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071K8XN
|
||||
bool "STM32G071K8XN"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071KBXN
|
||||
bool "STM32G071KBXN"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071C8
|
||||
bool "STM32G071C8"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071CB
|
||||
bool "STM32G071CB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071R8
|
||||
bool "STM32G071R8"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_8
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G071RB
|
||||
bool "STM32G071RB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1KB
|
||||
bool "STM32G0B1KB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1CB
|
||||
bool "STM32G0B1CB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1RB
|
||||
bool "STM32G0B1RB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1MB
|
||||
bool "STM32G0B1MB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1VB
|
||||
bool "STM32G0B1VB"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_B
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1KC
|
||||
bool "STM32G0B1KC"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_C
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1CC
|
||||
bool "STM32G0B1CC"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_C
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1RC
|
||||
bool "STM32G0B1RC"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_C
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1MC
|
||||
bool "STM32G0B1MC"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_C
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1VC
|
||||
bool "STM32G0B1VC"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_C
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1KE
|
||||
bool "STM32G0B1KE"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1CE
|
||||
bool "STM32G0B1CE"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1RE
|
||||
bool "STM32G0B1RE"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1NE
|
||||
bool "STM32G0B1NE"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1ME
|
||||
bool "STM32G0B1ME"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1VE
|
||||
bool "STM32G0B1VE"
|
||||
select STM32F0L0G0_STM32G0
|
||||
select STM32F0L0G0_FLASH_CONFIG_E
|
||||
depends on ARCH_CHIP_STM32G0
|
||||
|
||||
config ARCH_CHIP_STM32G0B1KB
|
||||
|
|
@ -960,10 +1072,56 @@ config ARCH_CHIP_STM32C092RC
|
|||
|
||||
endchoice # ST STM32F0/L0/G0/C0 Chip Selection
|
||||
|
||||
# Flash configurations
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_4
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_6
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_8
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_B
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_C
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_D
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_E
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_F
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_G
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_I
|
||||
bool
|
||||
default n
|
||||
|
||||
config STM32F0L0G0_FLASH_OVERRIDE
|
||||
bool "Override Flash Designator"
|
||||
default n
|
||||
|
||||
choice
|
||||
prompt "Override Flash Size Designator"
|
||||
default STM32F0L0G0_FLASH_CONFIG_DEFAULT
|
||||
depends on ARCH_CHIP_STM32
|
||||
depends on STM32F0L0G0_FLASH_OVERRIDE
|
||||
default STM32F0L0G0_FLASH_OVERRIDE_B
|
||||
---help---
|
||||
STM32F series parts numbering (sans the package type) ends with a number or letter
|
||||
that designates the FLASH size.
|
||||
|
|
@ -985,44 +1143,38 @@ choice
|
|||
STM32 Chip Selection.
|
||||
|
||||
Examples:
|
||||
If the STM32F407VE is chosen, the Flash configuration would be 'E', if a variant of
|
||||
If the STM32G071RB is chosen, the Flash configuration would be 'B', if a variant of
|
||||
the part with a 2048 KiB Flash is released in the future one could simply select
|
||||
the 'I' designator here.
|
||||
|
||||
If an STM32F42xxx or Series parts is chosen the default Flash configuration will be 'G'
|
||||
and can be set herein to 'I' to choose the larger FLASH part.
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_DEFAULT
|
||||
bool "Default"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_4
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_4
|
||||
bool "4 16KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_6
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_6
|
||||
bool "6 32KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_8
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_8
|
||||
bool "8 64KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_B
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_B
|
||||
bool "B 128KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_C
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_C
|
||||
bool "C 256KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_D
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_D
|
||||
bool "D 384KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_E
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_E
|
||||
bool "E 512KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_F
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_F
|
||||
bool "F 768KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_G
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_G
|
||||
bool "G 1024KiB"
|
||||
|
||||
config STM32F0L0G0_FLASH_CONFIG_I
|
||||
config STM32F0L0G0_FLASH_OVERRIDE_I
|
||||
bool "I 2048KiB"
|
||||
|
||||
endchoice
|
||||
|
|
@ -1204,6 +1356,16 @@ config STM32F0L0G0_DFU
|
|||
Configure and position code for use with the STMicro DFU bootloader. Do
|
||||
not select this option if you will load code using JTAG/SWM.
|
||||
|
||||
config STM32F0L0G0_PROGMEM
|
||||
bool "Flash PROGMEM support"
|
||||
default n
|
||||
depends on ARCH_HAVE_PROGMEM
|
||||
select MTD
|
||||
select MTD_PROGMEM
|
||||
---help---
|
||||
Add progmem support, start block and end block options are provided to
|
||||
obtain a uniform flash memory mapping.
|
||||
|
||||
choice
|
||||
prompt "SysTick clock source"
|
||||
default STM32F0L0G0_SYSTICK_CORECLK
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y)
|
|||
CHIP_CSRCS += stm32_userspace.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STM32F0L0G0_PROGMEM),y)
|
||||
CHIP_CSRCS += stm32_flash.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STM32F0L0G0_GPIOIRQ),y)
|
||||
CHIP_CSRCS += stm32_gpioint.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -47,8 +47,16 @@
|
|||
#define STM32_FLASH_PCROP1AER_OFFSET 0x0028
|
||||
#define STM32_FLASH_WPR1AR_OFFSET 0x002c
|
||||
#define STM32_FLASH_WPR1BR_OFFSET 0x0030
|
||||
#define STM32_FLASH_WPR1BSR_OFFSET 0x0034
|
||||
#define STM32_FLASH_PCROP1BSR_OFFSET 0x0034
|
||||
#define STM32_FLASH_PCROP1BER_OFFSET 0x0038
|
||||
|
||||
#define STM32_FLASH_PCROP2ASR_OFFSET 0x0044
|
||||
#define STM32_FLASH_PCROP2AER_OFFSET 0x0048
|
||||
#define STM32_FLASH_WRP2AR_OFFSET 0x004c
|
||||
#define STM32_FLASH_WRP2BR_OFFSET 0x0050
|
||||
#define STM32_FLASH_PCROP2BSR_OFFSET 0x0054
|
||||
#define STM32_FLASH_PCROP2BER_OFFSET 0x0058
|
||||
|
||||
#define STM32_FLASH_SECR_OFFSET 0x0080
|
||||
|
||||
/* Register Addresses *******************************************************/
|
||||
|
|
@ -64,32 +72,211 @@
|
|||
#define STM32_FLASH_PCROP1AER (STM32_FLASHIF_BAER+STM32_FLASH_PCROP1AER_OFFSET)
|
||||
#define STM32_FLASH_WPR1AR (STM32_FLASHIF_BASE+STM32_FLASH_WPR1AR_OFFSET)
|
||||
#define STM32_FLASH_WPR1BR (STM32_FLASHIF_BASE+STM32_FLASH_WPR1BR_OFFSET)
|
||||
#define STM32_FLASH_WPR1BSR (STM32_FLASHIF_BASE+STM32_FLASH_WPR1BSR_OFFSET)
|
||||
#define STM32_FLASH_PCROP1BSR (STM32_FLASHIF_BASE+STM32_FLASH_WPR1BSR_OFFSET)
|
||||
#define STM32_FLASH_PCROP1BER (STM32_FLASHIF_BASE+STM32_FLASH_PCROP1BER_OFFSET)
|
||||
#define STM32_FLASH_PCROP2ASR (STM32_FLASHIF_BASE+STM32_FLASH_PCROP2ASR_OFFSET)
|
||||
#define STM32_FLASH_PCROP2AER (STM32_FLASHIF_BASE+STM32_FLASH_PCROP2AER_OFFSET)
|
||||
#define STM32_FLASH_WRP2AR (STM32_FLASHIF_BASE+STM32_FLASH_WRP2AR_OFFSET)
|
||||
#define STM32_FLASH_WRP2BR (STM32_FLASHIF_BASE+STM32_FLASH_WRP2BR_OFFSET)
|
||||
#define STM32_FLASH_PCROP2BSR (STM32_FLASHIF_BASE+STM32_FLASH_PCROP2BSR_OFFSET)
|
||||
#define STM32_FLASH_PCROP2BER (STM32_FLASHIF_BASE+STM32_FLASH_PCROP2BER_OFFSET)
|
||||
#define STM32_FLASH_SECR (STM32_FLASHIF_BASE+STM32_FLASH_SECR_OFFSET)
|
||||
|
||||
/* Register Bitfield Definitions ********************************************/
|
||||
|
||||
/* Flash Access Control Register (ACR) */
|
||||
|
||||
#define FLASH_ACR_LATENCY_SHIFT (0) /* Bits 0-2: Flash memory access latency*/
|
||||
#define FLASH_ACR_LATENCY_MASK (7 << FLASH_ACR_LATENCY_SHIFT)
|
||||
# define FLASH_ACR_LATENCY(n) ((n) << FLASH_ACR_LATENCY_SHIFT)
|
||||
# define FLASH_ACR_LATENCY_0 (0 << FLASH_ACR_LATENCY_SHIFT) /* 000: Zero wait states */
|
||||
# define FLASH_ACR_LATENCY_1 (1 << FLASH_ACR_LATENCY_SHIFT) /* 001: One wait state */
|
||||
# define FLASH_ACR_LATENCY_2 (2 << FLASH_ACR_LATENCY_SHIFT) /* 010: Two wait states */
|
||||
#define FLASH_ACR_LATENCY_SHIFT (0) /* Bits 0-2: Flash memory access latency*/
|
||||
#define FLASH_ACR_LATENCY_MASK (7 << FLASH_ACR_LATENCY_SHIFT)
|
||||
# define FLASH_ACR_LATENCY(n) ((n) << FLASH_ACR_LATENCY_SHIFT)
|
||||
# define FLASH_ACR_LATENCY_0 (0 << FLASH_ACR_LATENCY_SHIFT) /* 000: Zero wait states */
|
||||
# define FLASH_ACR_LATENCY_1 (1 << FLASH_ACR_LATENCY_SHIFT) /* 001: One wait state */
|
||||
# define FLASH_ACR_LATENCY_2 (2 << FLASH_ACR_LATENCY_SHIFT) /* 010: Two wait states */
|
||||
|
||||
/* Bits 3-7: Reserved */
|
||||
#define FLASH_ACR_PRFTEN (1 << 8) /* Bit 8: Prefetch enable */
|
||||
#define FLASH_ACR_ICEN (1 << 9) /* Bit 9: Instruction cache enable */
|
||||
/* Bit 10:Reserved */
|
||||
#define FLASH_ACR_ICRST (1 << 11) /* Bit 11:Instruction cache reset */
|
||||
/* Bits 12-15: Reserved */
|
||||
#define FLASH_ACR_EMPTY (1 << 16) /* Bit 16: Main Flash memory area empty */
|
||||
/* Bit 17: Reserved */
|
||||
#define FLASH_ACR_DBGSWEN (1 << 18) /* Bit 18: Debug access software enable */
|
||||
/* Bits 19-31: Reserved */
|
||||
/* Bits 3-7: Reserved */
|
||||
#define FLASH_ACR_PRFTEN (1 << 8) /* Bit 8: Prefetch enable */
|
||||
#define FLASH_ACR_ICEN (1 << 9) /* Bit 9: Instruction cache enable */
|
||||
/* Bit 10:Reserved */
|
||||
#define FLASH_ACR_ICRST (1 << 11) /* Bit 11:Instruction cache reset */
|
||||
/* Bits 12-15: Reserved */
|
||||
#define FLASH_ACR_EMPTY (1 << 16) /* Bit 16: Main Flash memory area empty */
|
||||
/* Bit 17: Reserved */
|
||||
#define FLASH_ACR_DBGSWEN (1 << 18) /* Bit 18: Debug access software enable */
|
||||
/* Bits 19-31: Reserved */
|
||||
|
||||
/* TODO */
|
||||
/* Flash Status Register (SR) */
|
||||
|
||||
#define FLASH_SR_EOP (1) /* Bit 0: End of operation */
|
||||
#define FLASH_SR_OPERR (1 << 1) /* Bit 1: Operation error */
|
||||
/* Bit 2: Reserved */
|
||||
#define FLASH_SR_PROGERR (1 << 3) /* Bit 3: Programming error */
|
||||
#define FLASH_SR_WRPERR (1 << 4) /* Bit 4: Write protection error */
|
||||
#define FLASH_SR_PGAERR (1 << 5) /* Bit 5: Programming alignment error */
|
||||
#define FLASH_SR_SIZERR (1 << 6) /* Bit 6: Size error */
|
||||
#define FLASH_SR_PGSERR (1 << 7) /* Bit 7: Programming sequence error */
|
||||
#define FLASH_SR_MISSERR (1 << 8) /* Bit 8: Fast programming data miss error */
|
||||
#define FLASH_SR_FASTERR (1 << 9) /* Bit 9: Fast programming error */
|
||||
/* Bits 10-13: Reserved */
|
||||
#define FLASH_SR_RDERR (1 << 14) /* Bit 14: PCROP read error */
|
||||
#define FLASH_SR_OPTVERR (1 << 15) /* Bit 15: Option and engineering bits loading validity error */
|
||||
#define FLASH_SR_BSY1 (1 << 16) /* Bit 16: Busy */
|
||||
#define FLASH_SR_BSY2 (1 << 17) /* Bit 17: Busy */
|
||||
#define FLASH_SR_CFGBSY (1 << 18) /* Bit 18: Programming or erase configuration busy */
|
||||
/* Bits 19-31: Reserved */
|
||||
|
||||
/* Flash Control Register (CR) */
|
||||
|
||||
#define FLASH_CR_PG (1) /* Bit 0: Flash memory programming enable */
|
||||
#define FLASH_CR_PER (1 << 1) /* Bit 1: Page erase enable */
|
||||
#define FLASH_CR_MER1 (1 << 2) /* Bit 2: Mass erase (Bank 1) */
|
||||
#define FLASH_CR_PNB_SHIFT (3) /* Bits 3-12: Page number selection */
|
||||
#define FLASH_CR_PNB_MASK (0x3ff << FLASH_CR_PNB_SHIFT)
|
||||
# define FLASH_CR_PNB(n) ((n) << FLASH_CR_PNB_SHIFT)
|
||||
|
||||
#define FLASH_CR_BKER (1 << 13) /* Bit 13: Bank selection for erase operation */
|
||||
/* Bit 14: Reserved */
|
||||
#define FLASH_CR_MER2 (1 << 15) /* Bit 15: Mass erase, Bank 2 */
|
||||
#define FLASH_CR_STRT (1 << 16) /* Bit 16: Start erase operation */
|
||||
#define FLASH_CR_OPTSTRT (1 << 17) /* Bit 17: Start of modification of option bytes */
|
||||
#define FLASH_CR_FSTPG (1 << 18) /* Bit 18: Fast programming enable */
|
||||
/* Bits 19-23: Reserved */
|
||||
#define FLASH_CR_EOPIE (1 << 24) /* Bit 24: End-of-operation interrupt enable */
|
||||
#define FLASH_CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */
|
||||
#define FLASH_CR_RDERRIE (1 << 26) /* Bit 26: PCROP read error interrupt enable */
|
||||
#define FLASH_CR_OBL_LAUNCH (1 << 27) /* Bit 27: Option byte load launch */
|
||||
#define FLASH_CR_SEC_PROT (1 << 28) /* Bit 28: Securable memory area protection enable (Bank 1) */
|
||||
#define FLASH_CR_SEC_PROT2 (1 << 29) /* Bit 29: Securable memory area protection enable (Bank 2) */
|
||||
#define FLASH_CR_OPTLOCK (1 << 30) /* Bit 30: Options Lock */
|
||||
#define FLASH_CR_LOCK (1 << 31) /* Bit 31: FLASH_CR Lock */
|
||||
|
||||
/* Flash ECC register (ECCR) */
|
||||
|
||||
#define FLASH_ECCR_ADDR_ECC_SHIFT (0) /* Bits 0-13: ECC fail double-word address offset */
|
||||
#define FLASH_ECCR_ADDR_ECC_MASK (0x3fff << FLASH_ECCR_ADDR_ECC_SHIFT)
|
||||
/* Bits 14-19: Reserved */
|
||||
#define FLASH_ECCR_SYSF_ECC (1 << 20) /* Bit 20: System flash memory ECC fail */
|
||||
/* Bits 21-23: Reserved */
|
||||
#define FLASH_ECCR_ECCCIE (1 << 24) /* Bit 24: ECC correction interrupt enable */
|
||||
/* Bits 25-29: Reserved */
|
||||
#define FLASH_ECCR_ECCC (1 << 30) /* Bit 30: ECC correction */
|
||||
#define FLASH_ECCR_ECCD (1 << 31) /* Bit 31: ECC detection */
|
||||
|
||||
/* Flash ECC register 2 (ECCR2) */
|
||||
|
||||
#define FLASH_ECCR2_ADDR_ECC_SHIFT (0) /* Bits 0-13: ECC fail double-word address offset */
|
||||
#define FLASH_ECCR2_ADDR_ECC_MASK (0x3fff << FLASH_ECCR2_ADDR_ECC_SHIFT)
|
||||
/* Bits 14-19: Reserved */
|
||||
#define FLASH_ECCR2_SYSF_ECC (1 << 20) /* Bit 20: System flash memory ECC fail */
|
||||
/* Bits 21-23: Reserved */
|
||||
#define FLASH_ECCR2_ECCCIE (1 << 24) /* Bit 24: ECC correction interrupt enable */
|
||||
/* Bits 25-29: Reserved */
|
||||
#define FLASH_ECCR2_ECCC (1 << 30) /* Bit 30: ECC correction */
|
||||
#define FLASH_ECCR2_ECCD (1 << 31) /* Bit 31: ECC detection */
|
||||
|
||||
/* Flash Option Register (OPTR) */
|
||||
|
||||
#define FLASH_OPTR_RDP_SHIFT (0)
|
||||
#define FLASH_OPTR_RDP_MASK (0xff << FLASH_OPTR_RDP_SHIFT)
|
||||
#define FLASH_OPTR_BOR_EN (1 << 8) /* Brown out reset enable */
|
||||
#define FLASH_OPTR_BORR_LEV_SHIFT (9) /* BOR threshold at rising Vdd supply */
|
||||
#define FLASH_OPTR_BORR_LEV_MASK (0x3 << FLASH_OPTR_BORR_LEV_SHIFT)
|
||||
#define FLASH_OPTR_BORF_LEV_SHIFT (11) /* BOR thresholda t falling Vdd supply */
|
||||
#define FLASH_OPTR_BORF_LEV_MASK (0x3 << FLASH_OPTR_BORF_LEV_SHIFT)
|
||||
#define FLASH_OPTR_NRST_STOP (1 << 13)
|
||||
#define FLASH_OPTR_NRST_STDBY (1 << 14)
|
||||
#define FLASH_OPTR_NRSTS_SHDW (1 << 15)
|
||||
#define FLASH_OPTR_IDWG_SW (1 << 16) /* Bit 16: Independent watchdog selection */
|
||||
#define FLASH_OPTR_IDWG_STOP (1 << 17) /* Bit 17: Independent watchdog counter freeze in stop mode */
|
||||
#define FLASH_OPTR_IDWG_STDBY (1 << 18) /* Bit 18: Independent watchdog counter freeze in Standby mode */
|
||||
#define FLASH_OPTR_WWDG_SW (1 << 19) /* Bit 19: Window watchdog selection */
|
||||
#define FLASH_OPTR_NSWAP_BANK (1 << 20) /* Bit 20: Empty check boot configuration */
|
||||
#define FLASH_OPTR_DUAL_BANK (1 << 21) /* Bit 21: Dual-bank on 512 Kbytes or 256 Kbytes flash memory devices */
|
||||
#define FLASH_OPTR_RAM_PARITY_CHECK (1 << 22) /* Bit 22: SRAm parity check control */
|
||||
/* Bit 23: Reserved */
|
||||
#define FLASH_OPTR_NBOOT_SEL (1 << 24)
|
||||
#define FLASH_OPTR_NBOOT1 (1 << 25)
|
||||
#define FLASH_OPTR_NBOOT0 (1 << 26)
|
||||
#define FLASH_OPTR_NRST_MODE_SHIFT (27)
|
||||
#define FLASH_OPTR_NRST_MODE_MASK (0x3 << FLASH_OPTR_NRST_MODE_SHIFT)
|
||||
#define FLASH_OPTR_IRHEN (1 << 29) /* Bit 29: Internal reset holder enable */
|
||||
|
||||
/* Flash PCROP area A start address register (PCROP1ASR) */
|
||||
|
||||
#define FLASH_PCROP1ASR_STRT_SHIFT (0)
|
||||
#define FLASH_PCROP1ASR_STRT_MASK (0x1ff << FLASH_PCROP1ASR_STRT_SHIFT)
|
||||
|
||||
/* Flash PCROP area A end address register (PCROP1AER) */
|
||||
|
||||
#define FLASH_PCROP1AER_PCROP1A_END_SHIFT (0)
|
||||
#define FLASH_PCROP1AER_PCROP1A_END_MASK (0x1ff << FLASH_PCROP1AER_PCROP1A_END_SHIFT)
|
||||
#define FLASH_PCROP1AER_PCROP_RDP (1 << 31)
|
||||
|
||||
/* Flash WRP area A address register (WRP1AR) */
|
||||
|
||||
#define FLASH_WRP1AR_WRP1A_STRT_SHIFT (0)
|
||||
#define FLASH_WRP1AR_WRP1A_STRT_MASK (0x7f << FLASH_WRP1AR_WRP1A_STRT_SHIFT)
|
||||
#define FLASH_WRP1AR_WRP1A_END_SHIFT (16)
|
||||
#define FLASH_WRP1AR_WRP1A_END_MASK (0x7f << FLASH_WRP1AR_WRP1A_END_SHIFT)
|
||||
|
||||
/* Flash WRP area B address register (WRP1BR) */
|
||||
|
||||
#define FLASH_WRP1BR_WRP1B_STRT_SHIFT (0)
|
||||
#define FLASH_WRP1BR_WRP1B_STRT_MASK (0x7f << FLASH_WRP1BR_WRP1B_STRT_SHIFT)
|
||||
#define FLASH_WRP1BR_WRP1B_END_SHIFT (16)
|
||||
#define FLASH_WRP1BR_WRP1B_END_MASK (0x7f << FLASH_WRP1BR_WRP1B_END_SHIFT)
|
||||
|
||||
/* Flash PCROP area B start address register (PCROP1BSR) */
|
||||
|
||||
#define FLASH_PCROP1BSR_PCROP1B_STRT_SHIFT (0)
|
||||
#define FLASH_PCROP1BSR_PCROP1B_STRT_MASK (0x1ff << FLASH_PCROP1BSR_PCROP1B_STRT_SHIFT)
|
||||
|
||||
/* Flash PCROP area B end address register (PCROP1BER) */
|
||||
|
||||
#define FLASH_PCROP1BER_PCROP1B_END_SHIFT (0)
|
||||
#define FLASH_PCROP1BER_PCROP1B_END_MASK (0x1ff << FLASH_PCROP1BER_PCROP1B_END_SHIFT)
|
||||
|
||||
/* Flash PCROP2 area A start address register (PCROP2ASR) */
|
||||
|
||||
#define FLASH_PCROP2ASR_PCROP2A_STRT_SHIFT (0)
|
||||
#define FLASH_PCROP2ASR_PCROP2A_STRT_MASK (0x1ff << FLASH_PCROP2ASR_PCROP2A_STRT_SHIFT)
|
||||
|
||||
/* Flash PCROP2 area A end address register (PCROP2AER) */
|
||||
|
||||
#define FLASH_PCROP2AER_PCROP2A_END_SHIFT (0)
|
||||
#define FLASH_PCROP2AER_PCROP2A_END_MASK (0x1ff << FLASH_PCROP2AER_PCROP2A_END_SHIFT)
|
||||
|
||||
/* Flash WRP area A address register (WRP2AR) */
|
||||
|
||||
#define FLASH_WRP2AR_WRP2A_STRT_SHIFT (0)
|
||||
#define FLASH_WRP2AR_WRP2A_STRT_MASK (0x7f << FLASH_WRP2AR_WRP2A_STRT_SHIFT)
|
||||
#define FLASH_WRP2AR_WRP2A_END_SHIFT (16)
|
||||
#define FLASH_WRP2AR_WRP2A_END_MASK (0x7f << FLASH_WRP2AR_WRP2A_END_SHIFT)
|
||||
|
||||
/* Flash WRP area B address register (WRP2BR) */
|
||||
|
||||
#define FLASH_WRP2BR_WRP2B_STRT_SHIFT (0)
|
||||
#define FLASH_WRP2BR_WRP2B_STRT_MASK (0x7f << FLASH_WRP2BR_WRP2B_STRT_SHIFT)
|
||||
#define FLASH_WRP2BR_WRP2B_END_SHIFT (16)
|
||||
#define FLASH_WRP2BR_WRP2B_END_MASK (0x7f << FLASH_WRP2BR_WRP2B_END_SHIFT)
|
||||
|
||||
/* Flash PCROP2 area B start address register (PCROP2BSR) */
|
||||
|
||||
#define FLASH_PCROP2BSR_PCROP2B_STRT_SHIFT (0)
|
||||
#define FLASH_PCROP2BSR_PCROP2B_STRT_MASK (0x1ff << FLASH_PCROP2BSR_PCROP2B_STRT_SHIFT)
|
||||
|
||||
/* Flash PCROP2 area B end address register (PCROP2BER) */
|
||||
|
||||
#define FLASH_PCROP2BER_PCROP2B_END_SHIFT (0)
|
||||
#define FLASH_PCROP2BER_PCROP2B_END_MASK (0x1ff << FLASH_PCROP2BER_PCROP2B_END_SHIFT)
|
||||
|
||||
/* Flash Security register (SECR) */
|
||||
|
||||
#define FLASH_SECR_SEC_SIZE_SHIFT (0) /* Bits 0-7: Securable memory area size (Bank 1) */
|
||||
#define FLASH_SECR_SEC_SIZE_MASK (0xff << FLASH_SECR_SEC_SIZE_SHIFT)
|
||||
/* Bits 8-15: Reserved */
|
||||
#define FLASH_SECR_BOOT_LOCK (1 << 16) /* Bit 16: Used to force boot from user area */
|
||||
#define FLASH_SECR_SEC_SIZE2_SHIFT (20) /* Bits 20-27: Securable memory area size (Bank 2) */
|
||||
#define FLASH_SECR_SEC_SIZE2_MASK (0xff << FLASH_SECR_SEC_SIZE2_SHIFT)
|
||||
/* Bits 28-31: Reserved */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32F0L0G0_HARDWARE_STM32G0_FLASH_H */
|
||||
|
|
|
|||
37
arch/arm/src/stm32f0l0g0/stm32_flash.c
Normal file
37
arch/arm/src/stm32f0l0g0/stm32_flash.c
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/stm32f0l0g0/stm32_flash.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#if defined(CONFIG_STM32F0L0G0_STM32G0)
|
||||
# include "stm32g0_flash.c"
|
||||
#else
|
||||
# error "Flash driver unsupported on selected chip."
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
67
arch/arm/src/stm32f0l0g0/stm32_flash.h
Normal file
67
arch/arm/src/stm32f0l0g0/stm32_flash.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/stm32f0l0g0/stm32_flash.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_STM32F0L0G0_STM32_FLASH_H
|
||||
#define __ARCH_ARM_SRC_STM32F0L0G0_STM32_FLASH_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "chip.h"
|
||||
#include "hardware/stm32_flash.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
# define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
void stm32_flash_getopt(uint32_t *opt);
|
||||
|
||||
int stm32_flash_optmodify(uint32_t clear, uint32_t set);
|
||||
|
||||
void stm32_flash_lock(void);
|
||||
|
||||
void stm32_flash_unlock(void);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32F0L0G0_STM32_FLASH_H */
|
||||
894
arch/arm/src/stm32f0l0g0/stm32g0_flash.c
Normal file
894
arch/arm/src/stm32f0l0g0/stm32g0_flash.c
Normal file
|
|
@ -0,0 +1,894 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/stm32f0l0g0/stm32g0_flash.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Provides standard flash access functions, to be used by the flash mtd
|
||||
* driver. The interface is defined in the include/nuttx/progmem.h
|
||||
*
|
||||
* Notes:
|
||||
* - Terminology: the G0xx reference manual [RM0444] refers to erase blocks
|
||||
* as 'pages'. In this file, erase blocks are referred to as 'blocks' and
|
||||
* the smallest write allowed is referred to as a 'page'. The STMicro
|
||||
* reference manuals are not consistent in naming convention.
|
||||
* - Blocking Nature: up_progmem_write() and up_progmem_eraseblock() will
|
||||
* both block without releasing (up_udelay) while waiting for flash
|
||||
* operations to complete. Take this into account for applications
|
||||
* that use these functions.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "stm32_flash.h"
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/signal.h>
|
||||
#include <arch/barriers.h>
|
||||
|
||||
#include <arm_internal.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "hardware/stm32_flash.h"
|
||||
#include "hardware/stm32_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define _K(x) ((x)*1024)
|
||||
#define FLASH_BLOCK_SIZE _K(2)
|
||||
#define FLASH_PAGE_SIZE 8
|
||||
|
||||
#if !defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_4) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_6) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_8) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_B) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_C) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_E) && \
|
||||
!defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE)
|
||||
# error "No valid flash configuration was defined."
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32F0L0G0_FLASH_OVERRIDE
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_4
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_6
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_8
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_B
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_C
|
||||
# undef CONFIG_STM32F0L0G0_FLASH_CONFIG_E
|
||||
# if defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_4)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_4
|
||||
# elif defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_6)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_6
|
||||
# elif defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_8)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_8
|
||||
# elif defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_B)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_B
|
||||
# elif defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_C)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_C
|
||||
# elif defined(CONFIG_STM32F0L0G0_FLASH_OVERRIDE_E)
|
||||
# define CONFIG_STM32F0L0G0_FLASH_CONFIG_E
|
||||
# else
|
||||
# error "Invalid flash configuration override provided"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_4)
|
||||
# define FLASH_NBLOCKS 8
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_6)
|
||||
# define FLASH_NBLOCKS 16
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_8)
|
||||
# define FLASH_NBLOCKS 32
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_B)
|
||||
# define FLASH_NBLOCKS 64
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_C)
|
||||
# define FLASH_NBLOCKS 128
|
||||
# define FLASH_DUAL_BANK 1
|
||||
# define FLASH_BANK2_BASE 0x08020000
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_E)
|
||||
# define FLASH_NBLOCKS 256
|
||||
# define FLASH_DUAL_BANK 1
|
||||
# define FLASH_BANK2_BASE 0x08040000
|
||||
#else
|
||||
# error "Invalid flash configuration defined"
|
||||
#endif
|
||||
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
# define FLASH_BANKSIZE (FLASH_NBLOCKS * FLASH_BLOCK_SIZE / 2)
|
||||
#else
|
||||
# define FLASH_BANKSIZE (FLASH_NBLOCKS * FLASH_BLOCK_SIZE)
|
||||
#endif
|
||||
|
||||
/* Dual bank G0B1 MCUs have a non-linear mapping of block number between
|
||||
* banks. Bank 2 starts at block number 256, even if bank 1 ends at 63
|
||||
* or 127.
|
||||
*/
|
||||
|
||||
#define FLASH_BANK2_START_BLOCKNUM 256
|
||||
|
||||
#define FLASH_TOTALSIZE (FLASH_NBLOCKS * FLASH_BLOCK_SIZE)
|
||||
#define FLASH_NPAGES (FLASH_NBLOCKS * FLASH_BLOCK_SIZE / FLASH_PAGE_SIZE)
|
||||
#define FLASH_KEY1 0x45670123
|
||||
#define FLASH_KEY2 0xcdef89ab
|
||||
#define FLASH_OPTKEY1 0x08192a3b
|
||||
#define FLASH_OPTKEY2 0x4c5d6e7f
|
||||
#define FLASH_ERASEDVALUE 0xffu
|
||||
#define FLASH_ERASEDVALUE_DW 0xffffffffu
|
||||
|
||||
#define FLASH_TIMEOUT 5000000 /* 5s */
|
||||
|
||||
#define FLASH_SR_CLEAR_ERROR_FLAGS (FLASH_SR_OPERR|FLASH_SR_PROGERR|FLASH_SR_WRPERR|\
|
||||
FLASH_SR_PGAERR|FLASH_SR_SIZERR|FLASH_SR_PGSERR|\
|
||||
FLASH_SR_MISSERR|FLASH_SR_FASTERR|FLASH_SR_RDERR|FLASH_SR_OPTVERR)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct stm32_flash_priv_s
|
||||
{
|
||||
uint32_t base; /* FLASH base address */
|
||||
uint32_t stblock; /* The first block number */
|
||||
uint32_t stpage; /* The first page number */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void flash_unlock_cr(void);
|
||||
static void flash_lock_cr(void);
|
||||
static bool flash_unlock_opt(void);
|
||||
static void flash_lock_opt(void);
|
||||
static int flash_israngeerased(size_t startaddress, size_t size);
|
||||
static inline struct stm32_flash_priv_s *flash_bank(size_t address);
|
||||
static int flash_wait_for_operation(void);
|
||||
static int flash_verify_blocknum(size_t block);
|
||||
static uint32_t flash_block_address(size_t block);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct stm32_flash_priv_s flash_bank1_priv =
|
||||
{
|
||||
.base = STM32_FLASH_BASE,
|
||||
.stblock = 0,
|
||||
.stpage = 0
|
||||
};
|
||||
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
static struct stm32_flash_priv_s flash_bank2_priv =
|
||||
{
|
||||
.base = FLASH_BANK2_BASE,
|
||||
.stblock = FLASH_BANK2_START_BLOCKNUM,
|
||||
.stpage = (FLASH_NPAGES / 2)
|
||||
};
|
||||
#endif
|
||||
|
||||
static mutex_t g_lock = NXMUTEX_INITIALIZER;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_bank
|
||||
*
|
||||
* Description:
|
||||
* Returns the priv pointer to the correct bank
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline struct stm32_flash_priv_s *flash_bank(size_t address)
|
||||
{
|
||||
struct stm32_flash_priv_s *priv = NULL;
|
||||
|
||||
if (address >= flash_bank1_priv.base &&
|
||||
address < flash_bank1_priv.base + FLASH_BANKSIZE)
|
||||
{
|
||||
priv = &flash_bank1_priv;
|
||||
}
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
else if (address >= flash_bank2_priv.base &&
|
||||
address < flash_bank2_priv.base + FLASH_BANKSIZE)
|
||||
{
|
||||
priv = &flash_bank2_priv;
|
||||
}
|
||||
#endif
|
||||
|
||||
return priv;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_israngeerased
|
||||
*
|
||||
* Description:
|
||||
* Returns count of non-erased words
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int flash_israngeerased(size_t startaddress, size_t size)
|
||||
{
|
||||
uint32_t *addr;
|
||||
uint8_t *baddr;
|
||||
size_t count = 0;
|
||||
size_t bwritten = 0;
|
||||
|
||||
if (!flash_bank(startaddress) || !flash_bank(startaddress + size - 1))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
addr = (uint32_t *)startaddress;
|
||||
|
||||
while (count + 4 <= size)
|
||||
{
|
||||
if (getreg32(addr) != FLASH_ERASEDVALUE_DW)
|
||||
{
|
||||
bwritten++;
|
||||
}
|
||||
|
||||
addr++;
|
||||
count += 4;
|
||||
}
|
||||
|
||||
baddr = (uint8_t *)addr;
|
||||
|
||||
while (count < size)
|
||||
{
|
||||
if (getreg8(baddr) != FLASH_ERASEDVALUE)
|
||||
{
|
||||
/* Technically counting more than once per word but OK since
|
||||
* anything that is non-zero is a failure anyways.
|
||||
*/
|
||||
|
||||
bwritten++;
|
||||
}
|
||||
|
||||
baddr++;
|
||||
count++;
|
||||
}
|
||||
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_wait_for_operation()
|
||||
*
|
||||
* Description:
|
||||
* Wait for last write/erase operation to finish
|
||||
* Return error in case of timeout
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero or error value
|
||||
*
|
||||
* -EBUSY: Timeout while waiting for previous write/erase operation to
|
||||
* complete
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int flash_wait_for_operation(void)
|
||||
{
|
||||
int i;
|
||||
bool timeout = true;
|
||||
|
||||
UP_DSB();
|
||||
|
||||
for (i = 0; i < FLASH_TIMEOUT; i += 10)
|
||||
{
|
||||
if (!(getreg32(STM32_FLASH_SR) &
|
||||
(FLASH_SR_CFGBSY | FLASH_SR_BSY1 | FLASH_SR_BSY2)))
|
||||
{
|
||||
timeout = false;
|
||||
break;
|
||||
}
|
||||
|
||||
up_udelay(10);
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_unlock_cr
|
||||
*
|
||||
* Description:
|
||||
* Unlock flash control register, if it is not already unlocked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void flash_unlock_cr(void)
|
||||
{
|
||||
/* FLASH_CR cannot be written when BSY1 flag set */
|
||||
|
||||
while (getreg32(STM32_FLASH_SR) & (FLASH_SR_BSY1 | FLASH_SR_CFGBSY))
|
||||
{
|
||||
}
|
||||
|
||||
if (getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK)
|
||||
{
|
||||
putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
|
||||
putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
|
||||
}
|
||||
|
||||
DEBUGASSERT((getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK) == 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_lock_cr
|
||||
*
|
||||
* Description:
|
||||
* Lock flash control register.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void flash_lock_cr(void)
|
||||
{
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_LOCK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_unlock_opt
|
||||
*
|
||||
* Description:
|
||||
* Unlock flash option bytes register, if it is not already unlocked.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool flash_unlock_opt(void)
|
||||
{
|
||||
bool was_locked = false;
|
||||
flash_unlock_cr();
|
||||
|
||||
if (getreg32(STM32_FLASH_CR) & FLASH_CR_OPTLOCK)
|
||||
{
|
||||
was_locked = true;
|
||||
|
||||
putreg32(FLASH_OPTKEY1, STM32_FLASH_OPTKEYR);
|
||||
putreg32(FLASH_OPTKEY2, STM32_FLASH_OPTKEYR);
|
||||
}
|
||||
|
||||
DEBUGASSERT((getreg32(STM32_FLASH_CR) & FLASH_CR_OPTLOCK) == 0);
|
||||
|
||||
return was_locked;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_lock_opt
|
||||
*
|
||||
* Description:
|
||||
* Lock flash option bytes register.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void flash_lock_opt(void)
|
||||
{
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_OPTLOCK);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_verify_blocknum
|
||||
*
|
||||
* Description:
|
||||
* Verify the provided block number is valid based on the flash
|
||||
* configuration. This is done because the reference implementation and
|
||||
* reference manual refer to non-contiguous block (page) numbers for the
|
||||
* flash layout on dual-bank devices.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero or negated errno value.
|
||||
*
|
||||
* -EFAULT: Block number provided falls outside of the ranges specified in
|
||||
* reference manual.
|
||||
****************************************************************************/
|
||||
|
||||
static int flash_verify_blocknum(size_t block)
|
||||
{
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
#if defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_C)
|
||||
if ((block < 0 || block > 63) && (block < 256 || block > 319))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
#elif defined(CONFIG_STM32F0L0G0_FLASH_CONFIG_E)
|
||||
if ((block < 0 || block > 127) && (block < 256 || block > 383))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
#else
|
||||
# error "Dual bank flash config not supported by flash driver"
|
||||
#endif
|
||||
#else
|
||||
if (block > FLASH_NBLOCKS)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: flash_block_address
|
||||
*
|
||||
* Description:
|
||||
* Find the start address for the given block number.
|
||||
*
|
||||
* Returned Value:
|
||||
* Memory address corresponding to given block number.
|
||||
*
|
||||
* Assumptions:
|
||||
* This function assumes the block number has already been verified. Take
|
||||
* care to make sure the block number is valid for the specific chip using
|
||||
* flash_verify_blocknum() first.
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t flash_block_address(size_t block)
|
||||
{
|
||||
uint32_t addr;
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
if (block >= flash_bank2_priv.stblock)
|
||||
{
|
||||
addr = flash_bank2_priv.base +
|
||||
(block - flash_bank2_priv.stblock) * FLASH_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = flash_bank1_priv.base + block * FLASH_BLOCK_SIZE;
|
||||
}
|
||||
#else
|
||||
addr = flash_bank1_priv.base + block * FLASH_BLOCK_SIZE;
|
||||
#endif
|
||||
return addr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_flash_unlock
|
||||
*
|
||||
* Description:
|
||||
* Unlock flash control register (FLASH_CR)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void stm32_flash_unlock(void)
|
||||
{
|
||||
nxmutex_lock(&g_lock);
|
||||
flash_unlock_cr();
|
||||
nxmutex_unlock(&g_lock);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_flash_lock
|
||||
*
|
||||
* Description:
|
||||
* Lock flash control register (FLASH_CR)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void stm32_flash_lock(void)
|
||||
{
|
||||
nxmutex_lock(&g_lock);
|
||||
flash_lock_cr();
|
||||
nxmutex_unlock(&g_lock);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_flash_getopt
|
||||
*
|
||||
* Description:
|
||||
* Read the current flash option bytes from FLASH_OPTR
|
||||
*
|
||||
* Input Parameters:
|
||||
* opt - location to store read of FLASH_OPTR
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void stm32_flash_getopt(uint32_t *opt)
|
||||
{
|
||||
*opt = getreg32(STM32_FLASH_OPTR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_flash_optmodify
|
||||
*
|
||||
* Description:
|
||||
* Modifies the current flash option bytes, given bits to set and clear.
|
||||
*
|
||||
* Input Parameters:
|
||||
* clear - clear bits for FLASH_OPTR
|
||||
* set - set bits for FLASH_OPTR
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero or error value
|
||||
*
|
||||
* -EBUSY: Timeout waiting for previous FLASH operation to occur, or
|
||||
* there was data in the flash data buffer.
|
||||
*
|
||||
* Notes:
|
||||
* This function WILL BLOCK and NOT release the thread. This is a sensitive
|
||||
* operation with the potential to brick the device if interrupted. So, for
|
||||
* the actual opt modify start, this function uses a tight while loop to
|
||||
* wait for completion.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int stm32_flash_optmodify(uint32_t clear, uint32_t set)
|
||||
{
|
||||
int ret;
|
||||
bool was_locked;
|
||||
|
||||
ret = flash_wait_for_operation();
|
||||
if (ret != 0)
|
||||
{
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
was_locked = flash_unlock_opt();
|
||||
modifyreg32(STM32_FLASH_SR, 0, FLASH_SR_CLEAR_ERROR_FLAGS);
|
||||
|
||||
modifyreg32(STM32_FLASH_OPTR, clear, set);
|
||||
|
||||
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY1)
|
||||
{
|
||||
}
|
||||
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_OPTSTRT);
|
||||
|
||||
while (getreg32(STM32_FLASH_SR) & FLASH_SR_BSY1)
|
||||
{
|
||||
}
|
||||
|
||||
if (was_locked)
|
||||
{
|
||||
flash_lock_opt();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_PROGMEM
|
||||
|
||||
/* up_progmem_x functions defined in nuttx/include/nuttx/progmem.h
|
||||
*
|
||||
* Notes on Implementation:
|
||||
* - The driver implementations DO NOT enforce memory address boundaries.
|
||||
* For processors with less than 2MB flash, the user is responsible for
|
||||
* not writing to memory between banks.
|
||||
*
|
||||
*/
|
||||
|
||||
size_t up_progmem_pagesize(size_t page)
|
||||
{
|
||||
return FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
ssize_t up_progmem_getpage(size_t addr)
|
||||
{
|
||||
struct stm32_flash_priv_s *priv;
|
||||
|
||||
priv = flash_bank(addr);
|
||||
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return priv->stpage + ((addr - priv->base) / FLASH_PAGE_SIZE);
|
||||
}
|
||||
|
||||
size_t up_progmem_getaddress(size_t page)
|
||||
{
|
||||
struct stm32_flash_priv_s *priv;
|
||||
|
||||
if (page >= FLASH_NPAGES)
|
||||
{
|
||||
return SIZE_MAX;
|
||||
}
|
||||
|
||||
priv = flash_bank(STM32_FLASH_BASE + (page * FLASH_PAGE_SIZE));
|
||||
|
||||
if (!priv)
|
||||
{
|
||||
return SIZE_MAX;
|
||||
}
|
||||
|
||||
return priv->base + (page - priv->stpage) * FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
size_t up_progmem_neraseblocks(void)
|
||||
{
|
||||
return FLASH_NBLOCKS;
|
||||
}
|
||||
|
||||
bool up_progmem_isuniform(void)
|
||||
{
|
||||
/* So... Every other implementation of this in STM chips returns this as
|
||||
* true. However, the description in include/nuttx/progmem.h states this to
|
||||
* mean "does size of erase 'page' == size of read/write 'page'". Which is
|
||||
* NOT true for most of these chips.
|
||||
*
|
||||
* On the G0, erase blocks are 2K and read/write page is 64 bit.
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t up_progmem_ispageerased(size_t page)
|
||||
{
|
||||
size_t addr;
|
||||
size_t count;
|
||||
size_t bwritten = 0;
|
||||
|
||||
if (page >= FLASH_NPAGES)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Verify */
|
||||
|
||||
for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page);
|
||||
count; count--, addr++)
|
||||
{
|
||||
if (getreg8(addr) != FLASH_ERASEDVALUE)
|
||||
{
|
||||
bwritten++;
|
||||
}
|
||||
}
|
||||
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
size_t up_progmem_erasesize(size_t block)
|
||||
{
|
||||
return FLASH_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
ssize_t up_progmem_eraseblock(size_t block)
|
||||
{
|
||||
int ret;
|
||||
size_t block_address;
|
||||
|
||||
ret = flash_verify_blocknum(block);
|
||||
if (ret < 0)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
block_address = flash_block_address(block);
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
}
|
||||
|
||||
if (flash_wait_for_operation())
|
||||
{
|
||||
ret = -EIO;
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
/* Get flash ready and begin erasing single block */
|
||||
|
||||
flash_unlock_cr();
|
||||
|
||||
modifyreg32(STM32_FLASH_SR, 0, FLASH_SR_CLEAR_ERROR_FLAGS);
|
||||
|
||||
/* By now, know that the block number is valid and corresponds to a
|
||||
* bank (if dual bank). So, don't need to verify that it is in bounds.
|
||||
*/
|
||||
|
||||
#ifdef FLASH_DUAL_BANK
|
||||
|
||||
/* Note to future developers: The CR register definition in the reference
|
||||
* manual [RM0444] is not clear on if bank selection is necessary. The PNB
|
||||
* definition seems to imply that writing block numbers corresponding to
|
||||
* bank 2 should just work. This is NOT the case. Writing 256 to PNB will
|
||||
* cause block (page) 0 to be erased. Therefore, must switch BKER bit to
|
||||
* match the correct bank.
|
||||
*/
|
||||
|
||||
if (block >= flash_bank2_priv.stblock)
|
||||
{
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_BKER);
|
||||
}
|
||||
else
|
||||
{
|
||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_BKER, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup erase parameters and start */
|
||||
|
||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_PNB_MASK,
|
||||
FLASH_CR_PER | (block << FLASH_CR_PNB_SHIFT));
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
|
||||
|
||||
/* Wait for erase operation to complete */
|
||||
|
||||
if (flash_wait_for_operation())
|
||||
{
|
||||
ret = -EIO;
|
||||
goto exit_with_unlock;
|
||||
}
|
||||
|
||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_PNB_MASK | FLASH_CR_PER, 0);
|
||||
|
||||
ret = 0;
|
||||
up_invalidate_dcache(block_address, block_address + FLASH_BLOCK_SIZE);
|
||||
|
||||
exit_with_unlock:
|
||||
flash_lock_cr();
|
||||
|
||||
exit_with_lock:
|
||||
nxmutex_unlock(&g_lock);
|
||||
|
||||
if (ret == 0 &&
|
||||
flash_israngeerased(block_address, up_progmem_erasesize(block)) == 0)
|
||||
{
|
||||
ret = up_progmem_erasesize(block); /* Success */
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
|
||||
{
|
||||
struct stm32_flash_priv_s *priv;
|
||||
uint32_t *fp;
|
||||
uint32_t *rp;
|
||||
uint32_t *ll = (uint32_t *)buf;
|
||||
size_t faddr;
|
||||
size_t written = count;
|
||||
int ret;
|
||||
const size_t pagesize = up_progmem_pagesize(0); /* 64-bit, 8 bytes per page */
|
||||
const size_t llperpage = pagesize / sizeof(uint32_t);
|
||||
size_t pcount = count / pagesize;
|
||||
|
||||
priv = flash_bank(addr);
|
||||
|
||||
if (priv == NULL)
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Check for valid address range */
|
||||
|
||||
if (addr < priv->base ||
|
||||
addr + count > priv->base + (FLASH_BANKSIZE))
|
||||
{
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = nxmutex_lock(&g_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (ssize_t)ret;
|
||||
}
|
||||
|
||||
/* Check address and count alignment */
|
||||
|
||||
DEBUGASSERT(!(addr % pagesize));
|
||||
DEBUGASSERT(!(count % pagesize));
|
||||
|
||||
if (flash_wait_for_operation())
|
||||
{
|
||||
written = -EIO;
|
||||
goto exit_with_lock;
|
||||
}
|
||||
|
||||
/* Get flash ready for write */
|
||||
|
||||
flash_unlock_cr();
|
||||
|
||||
modifyreg32(STM32_FLASH_SR, 0, FLASH_SR_CLEAR_ERROR_FLAGS);
|
||||
modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
|
||||
|
||||
/* Write */
|
||||
|
||||
for (ll = (uint32_t *)buf, faddr = addr; pcount;
|
||||
pcount -= 1, ll += llperpage, faddr += pagesize)
|
||||
{
|
||||
fp = (uint32_t *)faddr;
|
||||
rp = ll;
|
||||
|
||||
UP_MB();
|
||||
|
||||
/* Write 2 32 bit word and wait to complete */
|
||||
|
||||
*fp++ = *rp++;
|
||||
*fp++ = *rp++;
|
||||
|
||||
/* Data synchronous Barrier (DSB) just after the write operation. This
|
||||
* will force the CPU to respect the sequence of instruction (no
|
||||
* optimization).
|
||||
*/
|
||||
|
||||
UP_MB();
|
||||
|
||||
if (flash_wait_for_operation())
|
||||
{
|
||||
written = -EIO;
|
||||
goto exit_with_unlock;
|
||||
}
|
||||
|
||||
/* Future improvements may add ECC checking here. */
|
||||
}
|
||||
|
||||
modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
|
||||
|
||||
exit_with_unlock:
|
||||
flash_lock_cr();
|
||||
|
||||
if (written > 0)
|
||||
{
|
||||
for (ll = (uint32_t *)buf, faddr = addr, pcount = count / pagesize;
|
||||
pcount; pcount -= 1, ll += llperpage, faddr += pagesize)
|
||||
{
|
||||
fp = (uint32_t *)faddr;
|
||||
rp = ll;
|
||||
|
||||
modifyreg32(STM32_FLASH_SR, 0, FLASH_SR_CLEAR_ERROR_FLAGS);
|
||||
|
||||
if ((*fp++ != *rp++) ||
|
||||
(*fp++ != *rp++))
|
||||
{
|
||||
written = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Future improvements may add ECC checking here. */
|
||||
}
|
||||
|
||||
modifyreg32(STM32_FLASH_SR, 0, FLASH_SR_CLEAR_ERROR_FLAGS);
|
||||
}
|
||||
|
||||
exit_with_lock:
|
||||
nxmutex_unlock(&g_lock);
|
||||
return written;
|
||||
}
|
||||
|
||||
uint8_t up_progmem_erasestate(void)
|
||||
{
|
||||
return FLASH_ERASEDVALUE;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_HAVE_PROGMEM*/
|
||||
Loading…
Add table
Reference in a new issue