Skip to content

Commit

Permalink
cpu/stm32: Fix garbage on UART init
Browse files Browse the repository at this point in the history
- Add gpio_init_set() as STM32 internal alternative to gpio_init(), which
  already sets the pin during initialization
- Use gpio_init_set() in periph/uart to keep the TXD pin almost flicker free
    - For the Nucleo F446RE this solves the issue with one garbage byte being
      send during boot from stdout
  • Loading branch information
maribu committed Jul 2, 2020
1 parent 045874a commit adffa67
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
14 changes: 14 additions & 0 deletions cpu/stm32/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,20 @@ void periph_clk_dis(bus_t bus, uint32_t mask);
*/
void gpio_init_af(gpio_t pin, gpio_af_t af);

/**
* @brief Same as @ref gpio_init, but will set the pin as early as possible
* during initialization
*
* @param pin Pin to initialize
* @param mode Mode to initialize with
*
* @retval 0 Success
*
* This function is useful to initialize a pin almost flicker free,
* e.g. for UART
*/
int gpio_init_set(gpio_t pin, gpio_mode_t mode);

/**
* @brief Configure the given pin to be used as ADC input
*
Expand Down
16 changes: 15 additions & 1 deletion cpu/stm32/periph/gpio_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static inline int _pin_num(gpio_t pin)
return (pin & 0x0f);
}

int gpio_init(gpio_t pin, gpio_mode_t mode)
static int _gpio_init(gpio_t pin, gpio_mode_t mode, int set_on_init)
{
GPIO_TypeDef *port = _port(pin);
int pin_num = _pin_num(pin);
Expand All @@ -107,6 +107,10 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
periph_clk_en(AHB1, (RCC_AHB1ENR_GPIOAEN << _port_num(pin)));
#endif

if (set_on_init) {
gpio_set(pin);
}

/* set mode */
port->MODER &= ~(0x3 << (2 * pin_num));
port->MODER |= ((mode & 0x3) << (2 * pin_num));
Expand All @@ -122,6 +126,16 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
return 0;
}

int gpio_init(gpio_t pin, gpio_mode_t mode)
{
return _gpio_init(pin, mode, 0);
}

int gpio_init_set(gpio_t pin, gpio_mode_t mode)
{
return _gpio_init(pin, mode, 1);
}

void gpio_init_af(gpio_t pin, gpio_af_t af)
{
GPIO_TypeDef *port = _port(pin);
Expand Down
17 changes: 15 additions & 2 deletions cpu/stm32/periph/gpio_f1.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ static inline int _pin_num(gpio_t pin)
return (pin & 0x0f);
}


int gpio_init(gpio_t pin, gpio_mode_t mode)
static int _gpio_init(gpio_t pin, gpio_mode_t mode, int set_on_init)
{
GPIO_TypeDef *port = _port(pin);
int pin_num = _pin_num(pin);
Expand All @@ -88,6 +87,10 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
/* enable the clock for the selected port */
periph_clk_en(APB2, (RCC_APB2ENR_IOPAEN << _port_num(pin)));

if (set_on_init) {
gpio_set(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));
Expand All @@ -101,6 +104,16 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
return 0; /* all OK */
}

int gpio_init(gpio_t pin, gpio_mode_t mode)
{
return _gpio_init(pin, mode, 0);
}

int gpio_init_set(gpio_t pin, gpio_mode_t mode)
{
return _gpio_init(pin, mode, 1);
}

void gpio_init_af(gpio_t pin, gpio_af_t af)
{
int pin_num = _pin_num(pin);
Expand Down
6 changes: 2 additions & 4 deletions cpu/stm32/periph/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,8 @@ 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);
/* configure TX pin and directly set it, so ideally no garbage is send */
gpio_init_set(uart_config[uart].tx_pin, GPIO_OUT);
#ifdef CPU_FAM_STM32F1
gpio_init_af(uart_config[uart].tx_pin, GPIO_AF_OUT_PP);
#else
Expand Down

0 comments on commit adffa67

Please sign in to comment.