Merge pull request #14426 from maribu/stm32f4_uart_init
cpu/stm32: Fix garbage on UART init
This commit is contained in:
commit
7fd25f21c9
@ -83,12 +83,9 @@ static inline int _pin_num(gpio_t pin)
|
||||
return (pin & 0x0f);
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
static inline void port_init_clock(GPIO_TypeDef *port, gpio_t pin)
|
||||
{
|
||||
GPIO_TypeDef *port = _port(pin);
|
||||
int pin_num = _pin_num(pin);
|
||||
|
||||
/* enable clock */
|
||||
(void)port; /* <-- Only used for when port G requires special handling */
|
||||
#if defined(CPU_FAM_STM32F0) || defined (CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L1)
|
||||
periph_clk_en(AHB, (RCC_AHBENR_GPIOAEN << _port_num(pin)));
|
||||
#elif defined (CPU_FAM_STM32L0)
|
||||
@ -106,10 +103,25 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
#else
|
||||
periph_clk_en(AHB1, (RCC_AHB1ENR_GPIOAEN << _port_num(pin)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void set_mode(GPIO_TypeDef *port, int pin_num, unsigned mode)
|
||||
{
|
||||
uint32_t tmp = port->MODER;
|
||||
tmp &= ~(0x3 << (2 * pin_num));
|
||||
tmp |= ((mode & 0x3) << (2 * pin_num));
|
||||
port->MODER = tmp;
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
{
|
||||
GPIO_TypeDef *port = _port(pin);
|
||||
int pin_num = _pin_num(pin);
|
||||
|
||||
/* enable clock */
|
||||
port_init_clock(port, pin);
|
||||
/* set mode */
|
||||
port->MODER &= ~(0x3 << (2 * pin_num));
|
||||
port->MODER |= ((mode & 0x3) << (2 * pin_num));
|
||||
set_mode(port, pin_num, mode);
|
||||
/* set pull resistor configuration */
|
||||
port->PUPDR &= ~(0x3 << (2 * pin_num));
|
||||
port->PUPDR |= (((mode >> 2) & 0x3) << (2 * pin_num));
|
||||
@ -127,12 +139,13 @@ void gpio_init_af(gpio_t pin, gpio_af_t af)
|
||||
GPIO_TypeDef *port = _port(pin);
|
||||
uint32_t pin_num = _pin_num(pin);
|
||||
|
||||
/* set pin to AF mode */
|
||||
port->MODER &= ~(3 << (2 * pin_num));
|
||||
port->MODER |= (2 << (2 * pin_num));
|
||||
/* enable clock */
|
||||
port_init_clock(port, pin);
|
||||
/* set selected function */
|
||||
port->AFR[(pin_num > 7) ? 1 : 0] &= ~(0xf << ((pin_num & 0x07) * 4));
|
||||
port->AFR[(pin_num > 7) ? 1 : 0] |= (af << ((pin_num & 0x07) * 4));
|
||||
/* set pin to AF mode */
|
||||
set_mode(port, pin_num, 2);
|
||||
}
|
||||
|
||||
void gpio_init_analog(gpio_t pin)
|
||||
|
||||
@ -74,6 +74,26 @@ static inline int _pin_num(gpio_t pin)
|
||||
return (pin & 0x0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the given mode is some kind of input mdoe
|
||||
* @param[in] mode Mode to check
|
||||
* @retval 1 @p mode is GPIO_IN, GPIO_IN_PD, or GPIO_IN_PU
|
||||
* @retval 0 @p mode is not an input mode
|
||||
*/
|
||||
static inline int gpio_mode_is_input(gpio_mode_t mode)
|
||||
{
|
||||
return !(mode & 3);
|
||||
}
|
||||
|
||||
static inline void set_mode_or_af(GPIO_TypeDef *port, int pin_num,
|
||||
unsigned mode_or_af)
|
||||
{
|
||||
volatile uint32_t *crl = (&port->CRL + (pin_num >> 3));
|
||||
uint32_t tmp = *crl;
|
||||
tmp &= ~(0xf << ((pin_num & 0x7) * 4));
|
||||
tmp |= ((mode_or_af & MODE_MASK) << ((pin_num & 0x7) * 4));
|
||||
*crl = tmp;
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
{
|
||||
@ -89,14 +109,15 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
periph_clk_en(APB2, (RCC_APB2ENR_IOPAEN << _port_num(pin)));
|
||||
|
||||
/* set pin mode */
|
||||
*(uint32_t *)(&port->CRL + (pin_num >> 3)) &= ~(0xf << ((pin_num & 0x7) * 4));
|
||||
*(uint32_t *)(&port->CRL + (pin_num >> 3)) |= ((mode & MODE_MASK) << ((pin_num & 0x7) * 4));
|
||||
set_mode_or_af(port, pin_num, mode);
|
||||
|
||||
/* set ODR */
|
||||
if (mode == GPIO_IN_PU)
|
||||
port->ODR |= 1 << pin_num;
|
||||
else
|
||||
port->ODR &= ~(1 << pin_num);
|
||||
/* For input modes, ODR controls pull up settings */
|
||||
if (gpio_mode_is_input(mode)) {
|
||||
if (mode == GPIO_IN_PU)
|
||||
port->ODR |= 1 << pin_num;
|
||||
else
|
||||
port->ODR &= ~(1 << pin_num);
|
||||
}
|
||||
|
||||
return 0; /* all OK */
|
||||
}
|
||||
@ -109,8 +130,7 @@ void gpio_init_af(gpio_t pin, gpio_af_t af)
|
||||
/* enable the clock for the selected port */
|
||||
periph_clk_en(APB2, (RCC_APB2ENR_IOPAEN << _port_num(pin)));
|
||||
/* configure the pin */
|
||||
*(uint32_t *)(&port->CRL + (pin_num >> 3)) &= ~(0xf << ((pin_num & 0x7) * 4));
|
||||
*(uint32_t *)(&port->CRL + (pin_num >> 3)) |= (af << ((pin_num & 0x7) * 4));
|
||||
set_mode_or_af(port, pin_num, af);
|
||||
}
|
||||
|
||||
void gpio_init_analog(gpio_t pin)
|
||||
|
||||
@ -117,9 +117,6 @@ static inline void uart_init_cts_pin(uart_t uart)
|
||||
static inline void uart_init_pins(uart_t uart, uart_rx_cb_t rx_cb)
|
||||
{
|
||||
/* configure TX pin */
|
||||
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||
/* set TX pin high to avoid garbage during further initialization */
|
||||
gpio_set(uart_config[uart].tx_pin);
|
||||
#ifdef CPU_FAM_STM32F1
|
||||
gpio_init_af(uart_config[uart].tx_pin, GPIO_AF_OUT_PP);
|
||||
#else
|
||||
@ -172,8 +169,6 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
tsrb_init(&uart_tx_rb[uart], uart_tx_rb_buf[uart], UART_TXBUF_SIZE);
|
||||
#endif
|
||||
|
||||
uart_init_pins(uart, rx_cb);
|
||||
|
||||
uart_enable_clock(uart);
|
||||
|
||||
/* reset UART configuration -> defaults to 8N1 mode */
|
||||
@ -199,6 +194,12 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
uart_init_usart(uart, baudrate);
|
||||
#endif
|
||||
|
||||
/* Attach pins to enabled UART periph. Note: It is important that the UART
|
||||
* interface is configured prior to attaching the pins, as otherwise the
|
||||
* signal level flickers during initialization resulting in garbage being
|
||||
* sent. */
|
||||
uart_init_pins(uart, rx_cb);
|
||||
|
||||
/* enable RX interrupt if applicable */
|
||||
if (rx_cb) {
|
||||
NVIC_EnableIRQ(uart_config[uart].irqn);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user