From 89ecc32b90565ace078c4a84d4406a4d1f86821a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Dec 2016 20:58:36 -0800 Subject: altos/arm: Align data so that gcc 5.4 doesn't do byte-accesses. Add -Wcast-align Gcc 5.4.1 tracks alignment of data through assignments, so that a uint32_t pointer which comes from byte-aligned uint8_t data: extern uint8_t foo[]; uint32_t *q = (void *) foo; Fetches and stores through this pointer are done bytewise. This is slow (meh), but if q references a device register, things to bad very quickly. This patch works around this bug in the compiler by adding __attribute__((aligned(4))) tags to some variables, or changing them from uint8_t to uint32_t. Places doing this will now be caught as I've added -Wcast-align to the compiler flags. That required adding (void *) casts, after the relevant code was checked to make sure the compiler could tell that the addresses were aligned. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stm/stm32l.h') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 463125e2..be1e1d65 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1961,7 +1961,7 @@ union stm_usb_bdt { #define STM_USB_BDT_SIZE 8 -extern uint8_t stm_usb_sram[]; +extern uint8_t stm_usb_sram[] __attribute__ ((aligned(4))); struct stm_exti { vuint32_t imr; -- cgit v1.2.3 From a487d2fcba57141f6b083d5612c76bac5ad1ac7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 20 Feb 2017 12:15:45 -0800 Subject: altos/stm: Add nvic priority register fields. Add more TIM234 defines. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/stm/stm32l.h') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index be1e1d65..a20efa8a 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -518,7 +518,7 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_CFGR_MCOPRE_DIV_4 2 #define STM_RCC_CFGR_MCOPRE_DIV_8 3 #define STM_RCC_CFGR_MCOPRE_DIV_16 4 -#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7 +#define STM_RCC_CFGR_MCOPRE_MASK 7 #define STM_RCC_CFGR_MCOSEL (24) #define STM_RCC_CFGR_MCOSEL_DISABLE 0 @@ -897,7 +897,11 @@ struct stm_nvic { vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */ vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */ - uint8_t _unusedc18[0xe00 - 0xc18]; + vuint32_t shpr7_4; /* 0xc18 0xe000ed18 System Hander Priority Registers */ + vuint32_t shpr11_8; /* 0xc1c */ + vuint32_t shpr15_12; /* 0xc20 */ + + uint8_t _unusedc18[0xe00 - 0xc24]; vuint32_t stir; /* 0xe00 */ }; @@ -1594,6 +1598,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CR2_FREQ_4_MHZ 4 #define STM_I2C_CR2_FREQ_8_MHZ 8 #define STM_I2C_CR2_FREQ_16_MHZ 16 +#define STM_I2C_CR2_FREQ_24_MHZ 24 #define STM_I2C_CR2_FREQ_32_MHZ 32 #define STM_I2C_CR2_FREQ_MASK 0x3f @@ -1740,6 +1745,12 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 #define STM_TIM234_SMCR_SMS_MASK 7 +#define STM_TIM234_DIER_CC4IE 4 +#define STM_TIM234_DIER_CC3IE 3 +#define STM_TIM234_DIER_CC2IE 2 +#define STM_TIM234_DIER_CC1IE 1 +#define STM_TIM234_DIER_UIE 0 + #define STM_TIM234_SR_CC4OF 12 #define STM_TIM234_SR_CC3OF 11 #define STM_TIM234_SR_CC2OF 10 @@ -1840,15 +1851,23 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CCER_CC4NP 15 #define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC4P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC4E 12 #define STM_TIM234_CCER_CC3NP 11 #define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC3P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC3E 8 #define STM_TIM234_CCER_CC2NP 7 #define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC2P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC2E 4 #define STM_TIM234_CCER_CC1NP 3 #define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC1P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC1E 0 struct stm_usb { -- cgit v1.2.3 From 0197157a295d848bac65cf7f4457dd5a99af24e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 3 Apr 2017 11:37:21 -0700 Subject: stm: Add a few more GPIO functions to make dealing with the 1802 easier ao_gpio_set_mask and ao_gpio_get_all Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 3 +++ src/stm/stm32l.h | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'src/stm/stm32l.h') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index b294c379..15741505 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -202,8 +202,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits) +#define ao_gpio_set_mask(port, bits, mask) stm_gpio_set_mask(port, bits, mask) + #define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits); +#define ao_gpio_get_all(port) stm_gpio_get_all(port) #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index a20efa8a..4f966e3e 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -167,6 +167,12 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); } +static inline void +stm_gpio_set_mask(struct stm_gpio *gpio, uint16_t bits, uint16_t mask) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (~bits & mask) << 16) | ((uint32_t) (bits & mask)); +} + static inline void stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) { gpio->bsrr = bits; -- cgit v1.2.3 From 301b724d2169f4ac46d921f518455c783e1dd894 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 4 Apr 2017 16:04:25 -0700 Subject: stm: Add more mask-based GPIO controls Lets cortexelf do more things with groups of pins, rather than one pin at a time. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 79 ++++++++++++++++++++++++++++++++++++++----------- src/stm/stm32l.h | 53 +++++++++++++++++++++++++++++---- 2 files changed, 109 insertions(+), 23 deletions(-) (limited to 'src/stm/stm32l.h') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 15741505..522059bc 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -214,6 +214,12 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) +#define ao_enable_output_mask(port,bits,mask) do { \ + ao_enable_port(port); \ + ao_gpio_set_mask(port, bits, mask); \ + ao_set_output_mask(port, mask); \ + } while (0) + #define AO_OUTPUT_PUSH_PULL STM_OTYPER_PUSH_PULL #define AO_OUTPUT_OPEN_DRAIN STM_OTYPER_OPEN_DRAIN @@ -229,35 +235,72 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ } while (0) +#define ao_gpio_set_mode_mask(port,mask,mode) do { \ + if (mode == AO_EXTI_MODE_PULL_UP) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_UP); \ + else if (mode == AO_EXTI_MODE_PULL_DOWN) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_DOWN); \ + else \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_NONE); \ + } while (0) + +#define ao_set_input(port, bit) do { \ + stm_moder_set(port, bit, STM_MODER_INPUT); \ + } while (0) + +#define ao_set_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_output_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_input_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_INPUT); \ + } while (0) + #define ao_enable_input(port,bit,mode) do { \ ao_enable_port(port); \ - stm_moder_set(port, bit, STM_MODER_INPUT); \ + ao_set_input(port, bit); \ ao_gpio_set_mode(port, bit, mode); \ } while (0) -#define ao_enable_cs(port,bit) do { \ +#define ao_enable_input_mask(port,mask,mode) do { \ + ao_enable_port(port); \ + ao_gpio_set_mode_mask(port, mask, mode); \ + ao_set_input_mask(port, mask); \ + } while (0) + +#define _ao_enable_cs(port, bit) do { \ stm_gpio_set((port), bit, 1); \ stm_moder_set((port), bit, STM_MODER_OUTPUT); \ } while (0) +#define ao_enable_cs(port,bit) do { \ + ao_enable_port(port); \ + _ao_enable_cs(port, bit); \ + } while (0) + #define ao_spi_init_cs(port, mask) do { \ ao_enable_port(port); \ - if ((mask) & 0x0001) ao_enable_cs(port, 0); \ - if ((mask) & 0x0002) ao_enable_cs(port, 1); \ - if ((mask) & 0x0004) ao_enable_cs(port, 2); \ - if ((mask) & 0x0008) ao_enable_cs(port, 3); \ - if ((mask) & 0x0010) ao_enable_cs(port, 4); \ - if ((mask) & 0x0020) ao_enable_cs(port, 5); \ - if ((mask) & 0x0040) ao_enable_cs(port, 6); \ - if ((mask) & 0x0080) ao_enable_cs(port, 7); \ - if ((mask) & 0x0100) ao_enable_cs(port, 8); \ - if ((mask) & 0x0200) ao_enable_cs(port, 9); \ - if ((mask) & 0x0400) ao_enable_cs(port, 10);\ - if ((mask) & 0x0800) ao_enable_cs(port, 11);\ - if ((mask) & 0x1000) ao_enable_cs(port, 12);\ - if ((mask) & 0x2000) ao_enable_cs(port, 13);\ - if ((mask) & 0x4000) ao_enable_cs(port, 14);\ - if ((mask) & 0x8000) ao_enable_cs(port, 15);\ + if ((mask) & 0x0001) _ao_enable_cs(port, 0); \ + if ((mask) & 0x0002) _ao_enable_cs(port, 1); \ + if ((mask) & 0x0004) _ao_enable_cs(port, 2); \ + if ((mask) & 0x0008) _ao_enable_cs(port, 3); \ + if ((mask) & 0x0010) _ao_enable_cs(port, 4); \ + if ((mask) & 0x0020) _ao_enable_cs(port, 5); \ + if ((mask) & 0x0040) _ao_enable_cs(port, 6); \ + if ((mask) & 0x0080) _ao_enable_cs(port, 7); \ + if ((mask) & 0x0100) _ao_enable_cs(port, 8); \ + if ((mask) & 0x0200) _ao_enable_cs(port, 9); \ + if ((mask) & 0x0400) _ao_enable_cs(port, 10);\ + if ((mask) & 0x0800) _ao_enable_cs(port, 11);\ + if ((mask) & 0x1000) _ao_enable_cs(port, 12);\ + if ((mask) & 0x2000) _ao_enable_cs(port, 13);\ + if ((mask) & 0x4000) _ao_enable_cs(port, 14);\ + if ((mask) & 0x8000) _ao_enable_cs(port, 15);\ } while (0) /* ao_dma_stm.c diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 4f966e3e..201f4f36 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -52,7 +52,32 @@ stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | value << STM_MODER_SHIFT(pin)); } - + +static inline uint32_t +stm_spread_mask(uint16_t mask) { + uint32_t m = mask; + + /* 0000000000000000mmmmmmmmmmmmmmmm */ + m = (m & 0xff) | ((m & 0xff00) << 8); + /* 00000000mmmmmmmm00000000mmmmmmmm */ + m = (m & 0x000f000f) | ((m & 0x00f000f0) << 4); + /* 0000mmmm0000mmmm0000mmmm0000mmmm */ + m = (m & 0x03030303) | ((m & 0x0c0c0c0c) << 2); + /* 00mm00mm00mm00mm00mm00mm00mm00mm */ + m = (m & 0x11111111) | ((m & 0x22222222) << 2); + /* 0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m */ + return m; +} + +static inline void +stm_moder_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->moder = ((gpio->moder & ~mask32) | value32); +} + static inline uint32_t stm_moder_get(struct stm_gpio *gpio, int pin) { return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; @@ -69,7 +94,7 @@ stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | value << STM_OTYPER_SHIFT(pin)); } - + static inline uint32_t stm_otyper_get(struct stm_gpio *gpio, int pin) { return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; @@ -83,12 +108,21 @@ stm_otyper_get(struct stm_gpio *gpio, int pin) { #define STM_OSPEEDR_40MHz 3 static inline void -stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { +stm_ospeedr_set(struct stm_gpio *gpio, int pin, uint32_t value) { gpio->ospeedr = ((gpio->ospeedr & ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | value << STM_OSPEEDR_SHIFT(pin)); } - + +static inline void +stm_ospeedr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->ospeedr = ((gpio->ospeedr & ~mask32) | value32); +} + static inline uint32_t stm_ospeedr_get(struct stm_gpio *gpio, int pin) { return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; @@ -107,7 +141,16 @@ stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | value << STM_PUPDR_SHIFT(pin)); } - + +static inline void +stm_pupdr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->pupdr = (gpio->pupdr & ~mask32) | value32; +} + static inline uint32_t stm_pupdr_get(struct stm_gpio *gpio, int pin) { return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; -- cgit v1.2.3