diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index f982641ed15..f334ca32bc6 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -69,6 +69,34 @@ config STM32L4_FLASH_1024KB endchoice # Embedded FLASH size +comment "SRAM2 Options" + +config STM32L4_SRAM2_HEAP + bool "SRAM2 is used for heap" + default n + select STM32L4_SRAM2_INIT + ---help--- + The STM32L4 SRAM2 region has special properties (power, protection, parity) + which may be used by the application for special purposes. But if these + special properties are not needed, it may be instead added to the heap for + use by malloc(). + NOTE: you must also select an appropriate number of memory regions in the + 'Memory Management' section. + +config STM32L4_SRAM2_INIT + bool "SRAM2 is initialized to zero" + default n + ---help--- + The STM32L4 SRAM2 region has parity checking. However, when the system + powers on, the memory is in an unknown state, and reads from uninitialized + memory can trigger parity faults from the random data. This can be + avoided by first writing to all locations to force the parity into a valid + state. + However, if the SRAM2 is being used for it's battery-backed capability, + this may be undesireable (because it will destroy the contents). In that + case, the board should handle the initialization itself at the appropriate + time. + menu "STM32L4 Peripheral Support" # These "hidden" settings determine is a peripheral option is available for the diff --git a/arch/arm/src/stm32l4/stm32l4_allocateheap.c b/arch/arm/src/stm32l4/stm32l4_allocateheap.c index e1c2e1acafc..9e37373adfe 100644 --- a/arch/arm/src/stm32l4/stm32l4_allocateheap.c +++ b/arch/arm/src/stm32l4/stm32l4_allocateheap.c @@ -62,13 +62,13 @@ ****************************************************************************/ /* Internal SRAM is available in all members of the STM32L4 family. The * following definitions must be provided to specify the size and - * location of internal(system) SRAM: + * location of internal (system) SRAM1 and SRAM2: * * SRAM1_END 0x20018000 * SRAM2_START 0x10000000 * SRAM2_END 0x10008000 * - * In addition to internal SRAM, SRAM may also be available through the FSMC. + * In addition to internal SRAM, memory may also be available through the FSMC. * In order to use FSMC SRAM, the following additional things need to be * present in the NuttX configuration file: * @@ -80,15 +80,14 @@ * CONFIG_HEAP2_SIZE : The size of the SRAM in the FSMC * address space * CONFIG_MM_REGIONS : Must be set to a large enough value to - * include the FSMC SRAM (as determined by - * the rules provided below) + * include the additional regions. */ #ifndef CONFIG_STM32L4_FSMC # undef CONFIG_STM32L4_FSMC_SRAM #endif -/* MSTM32L4x6xx have 128Kib in two banks, both accessible to DMA: +/* STM32L4x6xx have 128Kib in two banks, both accessible to DMA: * * 1) 96KiB of System SRAM beginning at address 0x2000:0000 - 0x2001:8000 * 2) 32KiB of System SRAM beginning at address 0x1000:0000 - 0x1000:8000 @@ -105,55 +104,21 @@ #define SRAM2_START 0x10000000 #define SRAM2_END 0x10008000 -/* Allocations according to the number of memory regions: - * - * 1 region available: - * - map it to SRAM1 - * - warn that SRAM2 is not available for heap - * - if FMC is enabled, warn that it is not available for heap - * - * 2 regions available: map them to SRAM1 and SRAM2 - * - map region 1 to SRAM1 - * - map region 2 to SRAM2 - * - if FMC is enabled, warn that it is not available for heap - * - * 3 or more regions - * - * - map them to SRAM1, SRAM2, FMC - */ - -#if CONFIG_MM_REGIONS < 1 -# warning heap is not usable - -#elif CONFIG_MM_REGIONS < 2 - -# warning SRAM2 (32k) is NOT available for heap, only SRAM1 (96k) : not enough MM regions -# undef SRAM2_START -# undef SRAM2_END - -# if defined(CONFIG_STM32L4_FSMC_SRAM) -# warning FMC SRAM is NOT available for heap : not enough MM regions (1) -# undef CONFIG_STM32L4_FSMC_SRAM +#if defined(STM32L4_SRAM2_HEAP) && defined(CONFIG_STM32L4_FSMC_SRAM_HEAP) +# if CONFIG_MM_REGIONS < 3 +# error you need at least 3 memory manager regions to support SRAM2 and FSMC # endif - -#elif CONFIG_MM_REGIONS < 3 - -# if defined(CONFIG_STM32L4_FSMC_SRAM) -# warning FMC SRAM is NOT available for heap : not enough MM regions (2) -# undef CONFIG_STM32L4_FSMC_SRAM -# endif - -#elif CONFIG_MM_REGIONS > 3 - -/*Everything can be mapped but some entries wont be used -> warn and correct*/ -# warning "CONFIG_MM_REGIONS > 3 but I don't know what some of the region(s) are" -# undef CONFIG_MM_REGIONS -# define CONFIG_MM_REGIONS 3 - -#else -/*Everything can be mapped*/ #endif +#if defined(STM32L4_SRAM2_HEAP) || defined(CONFIG_STM32L4_FSMC_SRAM_HEAP) +# if CONFIG_MM_REGIONS < 2 +# error you need at least 2 memory manager regions to support SRAM2 or FSMC +# endif +#endif + +#if CONFIG_MM_REGIONS < 1 +# warning you have no heap; malloc() will fail. are you sure? +#endif /* If FSMC SRAM is going to be used as heap, then verify that the starting * address and size of the external SRAM region has been provided in the @@ -338,6 +303,8 @@ void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) void up_addregion(void) { +#ifdef CONFIG_STM32L4_SRAM2_HEAP + #if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) /* Allow user-mode access to the SRAM2 heap */ @@ -354,7 +321,9 @@ void up_addregion(void) kumm_addregion((FAR void *)SRAM2_START, SRAM2_END-SRAM2_START); -#ifdef CONFIG_STM32L4_FSMC_SRAM +#endif + +#ifdef CONFIG_STM32L4_FSMC_SRAM_HEAP #if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) /* Allow user-mode access to the FSMC SRAM user heap memory */ diff --git a/arch/arm/src/stm32l4/stm32l4_start.c b/arch/arm/src/stm32l4/stm32l4_start.c index ee1f894d8d3..6209cde5418 100644 --- a/arch/arm/src/stm32l4/stm32l4_start.c +++ b/arch/arm/src/stm32l4/stm32l4_start.c @@ -79,6 +79,8 @@ * 0x2001:7fff - End of internal SRAM and end of heap */ +#define SRAM2_START 0x10000000 +#define SRAM2_END 0x10008000 #define IDLE_STACK ((uintptr_t)&_ebss+CONFIG_IDLETHREAD_STACKSIZE-4) #define HEAP_BASE ((uintptr_t)&_ebss+CONFIG_IDLETHREAD_STACKSIZE) @@ -287,6 +289,24 @@ void __start(void) __asm__ volatile ("sub r10, sp, %0" : : "r" (CONFIG_IDLETHREAD_STACKSIZE - 64) : ); #endif +#ifdef CONFIG_STM32L4_SRAM2_INIT + /* The SRAM2 region is parity checked, but upon power up, it will be in + * a random state and probably invalid with respect to parity, potentially + * generating faults if accessed. If elected, we will write zeros to the + * memory, forcing the parity to be set to a valid state. + * NOTE: this is optional because this may be inappropriate, especially + * if the memory is being used for it's battery backed purpose. In that + * case, the first-time initialization needs to be performed by the board + * under application-specific circumstances. On the other hand, if we're + * using this memory for, say, additional heap space, then this is handy. + */ + + for (dest = (uint32_t *)SRAM2_START; dest < (uint32_t *)SRAM2_END; ) + { + *dest++ = 0; + } +#endif + /* Configure the UART so that we can get debug output as soon as possible */ stm32l4_clockconfig(); diff --git a/arch/arm/src/stm32l4/stm32l4x6xx_dma.c b/arch/arm/src/stm32l4/stm32l4x6xx_dma.c index a45d33970bf..eb91e3a7547 100644 --- a/arch/arm/src/stm32l4/stm32l4x6xx_dma.c +++ b/arch/arm/src/stm32l4/stm32l4x6xx_dma.c @@ -523,7 +523,7 @@ void stm32l4_dmasetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, /* define peripheral indicated in dmach->function */ regval = dmabase_getreg(dmach, STM32L4_DMA_CSELR_OFFSET); - regval &= (0x0f << (dmach->chan << 2)); + regval &= ~(0x0f << (dmach->chan << 2)); regval |= (dmach->function << (dmach->chan << 2)); dmabase_putreg(dmach, STM32L4_DMA_CSELR_OFFSET, regval); }