From 7c0a4b839000f6839e66631713051896972938a4 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 30 May 2023 12:55:29 +0200 Subject: [PATCH 1/4] cpu/stm32/periph_timer: Support timers with channels != 4 The assumption that all STM32 timers have exactly four channels no longer holds. E.g. the STM32L4 has the following general purpose timers: - TIM2: 32 bit, 4 channels - TIM15: 16 bit, 2 channels - TIM16: 16 bit, 1 channel Hence, a new field is added to the timer configuration to also contain the number of timer channels. Due to alignment the `struct` previously was padded by 16 bit, so adding another 8 bit field doesn't increase its size. For backward compatibility, a value of `0` is considered as alias for `TIMER_CHANNEL_NUMOF` (or 4), so that the number of timer channels only needs to be set when the timer is different from the typical 4 channel timer. This helps backward compatibility. --- cpu/stm32/include/periph/cpu_timer.h | 4 +++- cpu/stm32/periph/timer.c | 23 +++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/cpu/stm32/include/periph/cpu_timer.h b/cpu/stm32/include/periph/cpu_timer.h index 83ed1c6821..252be33e70 100644 --- a/cpu/stm32/include/periph/cpu_timer.h +++ b/cpu/stm32/include/periph/cpu_timer.h @@ -30,7 +30,7 @@ extern "C" { #endif /** - * @brief All STM timers have 4 capture-compare channels + * @brief All STM timers have at most 4 capture-compare channels */ #define TIMER_CHANNEL_NUMOF (4U) @@ -53,6 +53,8 @@ typedef struct { uint32_t rcc_mask; /**< corresponding bit in the RCC register */ uint8_t bus; /**< APBx bus the timer is clock from */ uint8_t irqn; /**< global IRQ channel */ + uint8_t channel_numof; /**< number of channels, 0 is alias for + @ref TIMER_CHANNEL_NUMOF */ } timer_conf_t; #ifdef __cplusplus diff --git a/cpu/stm32/periph/timer.c b/cpu/stm32/periph/timer.c index 92660fa755..3ea8fb85e7 100644 --- a/cpu/stm32/periph/timer.c +++ b/cpu/stm32/periph/timer.c @@ -36,6 +36,21 @@ static inline TIM_TypeDef *dev(tim_t tim) return timer_config[tim].dev; } +/** + * @brief Get the number of channels of the timer device + */ +static unsigned channel_numof(tim_t tim) +{ + if (timer_config[tim].channel_numof) { + return timer_config[tim].channel_numof; + } + + /* backwards compatibility with older periph_conf.h files when all STM32 + * had exactly 4 channels */ + return TIMER_CHANNEL_NUMOF; +} + + #ifdef MODULE_PERIPH_TIMER_PERIODIC /** @@ -121,7 +136,7 @@ int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg) int timer_set_absolute(tim_t tim, int channel, unsigned int value) { - if (channel >= (int)TIMER_CHANNEL_NUMOF) { + if ((unsigned)channel >= channel_numof(tim)) { return -1; } @@ -150,7 +165,7 @@ int timer_set(tim_t tim, int channel, unsigned int timeout) { unsigned value = (dev(tim)->CNT + timeout) & timer_config[tim].max; - if (channel >= (int)TIMER_CHANNEL_NUMOF) { + if ((unsigned)channel >= channel_numof(tim)) { return -1; } @@ -188,7 +203,7 @@ int timer_set(tim_t tim, int channel, unsigned int timeout) #ifdef MODULE_PERIPH_TIMER_PERIODIC int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags) { - if (channel >= (int)TIMER_CHANNEL_NUMOF) { + if ((unsigned)channel >= channel_numof(tim)) { return -1; } @@ -227,7 +242,7 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags int timer_clear(tim_t tim, int channel) { - if (channel >= (int)TIMER_CHANNEL_NUMOF) { + if ((unsigned)channel >= channel_numof(tim)) { return -1; } From a6e8e1ff7e7863f0c15f9959b9d910b742e243d4 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 30 May 2023 13:03:19 +0200 Subject: [PATCH 2/4] boards/common/stm32: Add timer config based on TIM2,15,16 This adds the three general purpose timers on STM32L4 boards in a central place so that STM32L4 boards can just include it. Some other families may also have TIM15 and TIM16 and could use this, but likely some generalization is needed to use this for other families as well. This can be added later on. --- .../include/cfg_timer_tim2_tim15_tim16.h | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 boards/common/stm32/include/cfg_timer_tim2_tim15_tim16.h diff --git a/boards/common/stm32/include/cfg_timer_tim2_tim15_tim16.h b/boards/common/stm32/include/cfg_timer_tim2_tim15_tim16.h new file mode 100644 index 0000000000..2f2ad1e4e8 --- /dev/null +++ b/boards/common/stm32/include/cfg_timer_tim2_tim15_tim16.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 Otto-von-Guericke-Universität Magdeburg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup boards_common_stm32 + * @{ + * + * @file + * @brief Common configuration for STM32 Timer peripheral based on TIM2, + * TIM15, and TIM16 + * + * @author Marian Buschsieweke + */ + +#ifndef CFG_TIMER_TIM2_TIM15_TIM16_H +#define CFG_TIMER_TIM2_TIM15_TIM16_H + +#include "periph_cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Please note: This likely needs some generalization for use in STM32 families + * other than L4. */ +/** + * @name Timer configuration + * @{ + */ +static const timer_conf_t timer_config[] = { + { + .dev = TIM2, + .max = 0xffffffff, + .rcc_mask = RCC_APB1ENR1_TIM2EN, + .bus = APB1, + .irqn = TIM2_IRQn + }, + { + .dev = TIM15, + .max = 0x0000ffff, + .rcc_mask = RCC_APB2ENR_TIM15EN, + .bus = APB2, + .irqn = TIM1_BRK_TIM15_IRQn, + .channel_numof = 2, + }, + { + .dev = TIM16, + .max = 0x0000ffff, + .rcc_mask = RCC_APB2ENR_TIM16EN, + .bus = APB2, + .irqn = TIM1_UP_TIM16_IRQn, + .channel_numof = 1, + }, +}; + +#define TIMER_0_ISR isr_tim2 /**< IRQ of timer at idx 0 */ +#define TIMER_1_ISR isr_tim1_brk_tim15 /**< IRQ of timer at idx 1 */ +#define TIMER_2_ISR isr_tim1_up_tim16 /**< IRQ of timer at idx 2 */ + +#define TIMER_NUMOF ARRAY_SIZE(timer_config) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* CFG_TIMER_TIM2_TIM15_TIM16_H */ +/** @} */ From 0051d4148cfe0c187322438fc02e406031d5fc54 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 30 May 2023 13:05:38 +0200 Subject: [PATCH 3/4] boards/nucleo-l432kc: provide three periph_timer instances --- boards/nucleo-l432kc/include/periph_conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/nucleo-l432kc/include/periph_conf.h b/boards/nucleo-l432kc/include/periph_conf.h index 40fd526183..af45e7ac4a 100644 --- a/boards/nucleo-l432kc/include/periph_conf.h +++ b/boards/nucleo-l432kc/include/periph_conf.h @@ -30,7 +30,7 @@ #include "clk_conf.h" #include "cfg_i2c1_pb6_pb7.h" #include "cfg_rtt_default.h" -#include "cfg_timer_tim2.h" +#include "cfg_timer_tim2_tim15_tim16.h" #ifdef __cplusplus extern "C" { From faf8be39c68db6dab00a99e4bbad74d214852975 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Tue, 30 May 2023 15:41:24 +0200 Subject: [PATCH 4/4] cpu/sam0_eth: clean up init() - don't enable PHY twice - properly set NCFGR register - sam0_read_phy() does not return a signed value --- cpu/sam0_common/periph/eth.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cpu/sam0_common/periph/eth.c b/cpu/sam0_common/periph/eth.c index c00c89b61e..a69c67904f 100644 --- a/cpu/sam0_common/periph/eth.c +++ b/cpu/sam0_common/periph/eth.c @@ -159,7 +159,7 @@ static void _init_desc_buf(void) GMAC->TBQB.reg = (uint32_t) tx_desc; } -int sam0_read_phy(uint8_t phy, uint8_t addr) +unsigned sam0_read_phy(uint8_t phy, uint8_t addr) { GMAC->MAN.reg = GMAC_MAN_REGA(addr) | GMAC_MAN_PHYA(phy) | GMAC_MAN_CLTTO | GMAC_MAN_WTN(0x2) @@ -353,9 +353,6 @@ int sam0_eth_init(void) memset(rx_desc, 0, sizeof(rx_desc)); memset(tx_desc, 0, sizeof(tx_desc)); - /* Enable PHY */ - gpio_set(sam_gmac_config[0].rst_pin); - /* Initialize buffers descriptor */ _init_desc_buf(); /* Disable RX and TX */ @@ -373,9 +370,9 @@ int sam0_eth_init(void) /* Set TxBase-100-FD by default */ /* TODO: implement auto negotiation */ - GMAC->NCFGR.reg |= (GMAC_NCFGR_SPD | GMAC_NCFGR_FD | GMAC_NCFGR_MTIHEN | - GMAC_NCFGR_RXCOEN | GMAC_NCFGR_MAXFS | GMAC_NCFGR_CAF | - GMAC_NCFGR_LFERD | GMAC_NCFGR_RFCS | GMAC_NCFGR_CLK(3)); + GMAC->NCFGR.reg = GMAC_NCFGR_SPD | GMAC_NCFGR_FD | GMAC_NCFGR_MTIHEN + | GMAC_NCFGR_RXCOEN | GMAC_NCFGR_MAXFS | GMAC_NCFGR_CAF + | GMAC_NCFGR_LFERD | GMAC_NCFGR_RFCS | GMAC_NCFGR_CLK(3); /* Enable all multicast addresses */ GMAC->HRB.reg = 0xffffffff;