From e09a31c3b6c44403bddac9522ea77db867c8c0fb Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Fri, 29 Sep 2017 13:32:25 +0000 Subject: [PATCH] Merged in juniskane/nuttx_stm32l4/dfsdm_flash_pr (pull request #497) STM32L4 FLASH, DFSDM: option bytes, JEXTSEL bits, ADC1 output to DFSDM chips change * STM32L4 FLASH: add function for modifying device option bytes * STM32L4 DFSDM: add JEXTSEL bits, ADC1 output to DFSDM chips change ST's documentation hints that ADC output can be routed to DFSDM on some STM32L4X3 chips, but I got confirmation from tech support that this is just a documentation error so remove this from Kconfig. Approved-by: Gregory Nutt --- arch/arm/src/stm32l4/Kconfig | 3 +- arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h | 21 ++++++ arch/arm/src/stm32l4/stm32l4_flash.c | 80 +++++++++++++++++++++++ arch/arm/src/stm32l4/stm32l4_flash.h | 19 ++++++ 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index c593184f94d..54235044958 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -3319,8 +3319,7 @@ config STM32L4_ADC3_DMA config STM32L4_ADC1_OUTPUT_DFSDM bool "ADC1 output to DFSDM" - depends on STM32L4_ADC1 && STM32L4_DFSDM1 && (STM32L4_STM32L496XX || \ - STM32L4_STM32L451XX || STM32L4_STM32L452XX || STM32L4_STM32L462XX) + depends on STM32L4_ADC1 && STM32L4_DFSDM1 && STM32L4_STM32L496XX default n ---help--- Route ADC1 output directly to DFSDM parallel inputs. diff --git a/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h b/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h index d0858e12e89..89a843cf08f 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h +++ b/arch/arm/src/stm32l4/chip/stm32l4_dfsdm.h @@ -263,6 +263,27 @@ #define DFSDM_FLTCR1_JEXTSEL_SHIFT (8) /* Bits 8-10: External trigger selection for injected group */ #define DFSDM_FLTCR1_JEXTSEL_MASK (0x7 << DFSDM_FLTCR1_JEXTSEL_SHIFT) # define DFSDM_FLTCR1_JEXTSEL(event) ((event) << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* Event = 0..7 */ +/* Trigger selections. Note: for RM0351 devices (STM32L4X6) these are valid for FLT0 and FLT1. + * For subtle differences for FLT2 and FLT3, see the reference manual. + */ +# define DFSDM_FLTCR1_JEXTSEL_T1TRGO (0x00 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0000: Timer 1 TRGO event */ +# define DFSDM_FLTCR1_JEXTSEL_T1TRGO2 (0x01 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0001: Timer 1 TRGO2 event */ +# if !defined(CONFIG_STM32L4_STM32L4X3) +# define DFSDM_FLTCR1_JEXTSEL_T8TRGO (0x02 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0010: Timer 8 TRGO event */ +# else +# define DFSDM_FLTCR1_JEXTSEL_T3TRGO (0x02 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0010: Timer 3 TRGO event */ +# endif +# if !defined(CONFIG_STM32L4_STM32L4X3) +# define DFSDM_FLTCR1_JEXTSEL_T8TRGO2 (0x03 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0011: Timer 8 TRGO2 event */ +# else +# define DFSDM_FLTCR1_JEXTSEL_T16CC1 (0x03 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0011: Timer 16 CC1 (or OC1) event */ +# endif +# if !defined(CONFIG_STM32L4_STM32L4X3) +# define DFSDM_FLTCR1_JEXTSEL_T4TRGO (0x04 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0100: Timer 4 TRGO event */ +# endif +# define DFSDM_FLTCR1_JEXTSEL_T6TRGO (0x05 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0101: Timer 6 TRGO event */ +# define DFSDM_FLTCR1_JEXTSEL_EXTI11 (0x06 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0110: EXTI line 11 */ +# define DFSDM_FLTCR1_JEXTSEL_EXTI15 (0x07 << DFSDM_FLTCR1_JEXTSEL_SHIFT) /* 0111: EXTI line 15 */ /* Bits 11-12: Reserved */ #define DFSDM_FLTCR1_JEXTEN_SHIFT (13) /* Bits 13-14: Trigger enable and edge election for injected group */ #define DFSDM_FLTCR1_JEXTEN_MASK (3 << DFSDM_FLTCR1_JEXTEN_SHIFT) diff --git a/arch/arm/src/stm32l4/stm32l4_flash.c b/arch/arm/src/stm32l4/stm32l4_flash.c index 520f054c17b..42712006024 100644 --- a/arch/arm/src/stm32l4/stm32l4_flash.c +++ b/arch/arm/src/stm32l4/stm32l4_flash.c @@ -134,6 +134,28 @@ static void flash_lock(void) modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_LOCK); } +static void flash_optbytes_unlock(void) +{ + flash_unlock(); + + if (getreg32(STM32L4_FLASH_CR) & FLASH_CR_OPTLOCK) + { + /* Unlock Option Bytes sequence */ + + putreg32(OPTBYTES_KEY1, STM32L4_FLASH_OPTKEYR); + putreg32(OPTBYTES_KEY2, STM32L4_FLASH_OPTKEYR); + } +} + +static inline void flash_optbytes_lock(void) +{ + /* We don't need to set OPTLOCK here as it is automatically + * set by MCU when flash_lock() sets LOCK. + */ + + flash_lock(); +} + /************************************************************************************ * Public Functions ************************************************************************************/ @@ -152,6 +174,64 @@ void stm32l4_flash_lock(void) sem_unlock(); } +/**************************************************************************** + * Name: stm32l4_flash_user_optbytes + * + * Description: + * Modify the contents of the user option bytes (USR OPT) on the flash. + * This does not set OBL_LAUNCH so new options take effect only after + * next power reset. + * + * Input Parameters: + * clrbits - Bits in the option bytes to be cleared + * setbits - Bits in the option bytes to be set + * + * Returned Value: + * Option bytes after operation is completed + * + ****************************************************************************/ + +uint32_t stm32l4_flash_user_optbytes(uint32_t clrbits, uint32_t setbits) +{ + uint32_t regval; + + /* To avoid accidents, do not allow setting RDP via this function. + * Remove these asserts if want to enable changing the protection level. + * WARNING: level 2 protection is permanent! + */ + + DEBUGASSERT((clrbits & FLASH_OPTCR_RDP_MASK) == 0); + DEBUGASSERT((setbits & FLASH_OPTCR_RDP_MASK) == 0); + + sem_lock(); + flash_optbytes_unlock(); + + /* Modify Option Bytes in register. */ + + regval = getreg32(STM32L4_FLASH_OPTR); + + finfo("Flash option bytes before: 0x%x\n", regval); + + regval = (regval & ~clrbits) | setbits; + putreg32(regval, STM32L4_FLASH_OPTR); + + finfo("Flash option bytes after: 0x%x\n", regval); + + /* Start Option Bytes programming and wait for completion. */ + + modifyreg32(STM32L4_FLASH_CR, 0, FLASH_CR_OPTSTRT); + + while (getreg32(STM32L4_FLASH_SR) & FLASH_SR_BSY) + { + up_waste(); + } + + flash_optbytes_lock(); + sem_unlock(); + + return regval; +} + size_t up_progmem_pagesize(size_t page) { return STM32L4_FLASH_PAGESIZE; diff --git a/arch/arm/src/stm32l4/stm32l4_flash.h b/arch/arm/src/stm32l4/stm32l4_flash.h index afa8c7ddfd0..6316232cab4 100644 --- a/arch/arm/src/stm32l4/stm32l4_flash.h +++ b/arch/arm/src/stm32l4/stm32l4_flash.h @@ -52,4 +52,23 @@ void stm32l4_flash_lock(void); void stm32l4_flash_unlock(void); +/**************************************************************************** + * Name: stm32l4_flash_user_optbytes + * + * Description: + * Modify the contents of the user option bytes (USR OPT) on the flash. + * This does not set OBL_LAUNCH so new options take effect only after + * next power reset. + * + * Input Parameters: + * clrbits - Bits in the option bytes to be cleared + * setbits - Bits in the option bytes to be set + * + * Returned Value: + * Option bytes after operation is completed + * + ****************************************************************************/ + +uint32_t stm32l4_flash_user_optbytes(uint32_t clrbits, uint32_t setbits); + #endif /* __ARCH_ARM_SRC_STM32L4_STM32L4_FLASH_H */