Merge pull request #113 from konkers/pr/stm32f0xx-native-rcc-uart-gpio

stm32f0xx: Convert rcc, uart, and gpio to native drivers.
This commit is contained in:
Brian Swetland
2016-02-28 17:05:56 -08:00
5 changed files with 361 additions and 97 deletions

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012 Travis Geiselbrecht
* Copyright (c) 2016 Erik Gilling
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -20,15 +21,42 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <debug.h>
#include <assert.h>
#include <dev/gpio.h>
#include <platform/stm32.h>
#include <platform/gpio.h>
#include <stm32f0xx_gpio.h>
#include <stm32f0xx_rcc.h>
static GPIO_TypeDef *port_to_pointer(unsigned int port)
#include <assert.h>
#include <debug.h>
#include <dev/gpio.h>
#include <platform/gpio.h>
#include <platform/rcc.h>
#include <platform/stm32.h>
#include <stm32f0xx.h>
typedef GPIO_TypeDef stm32_gpio_t;
typedef enum {
STM32_GPIO_SPEED_2_MHZ = 0x0,
STM32_GPIO_SPEED_20_MHZ = 0x1,
STM32_GPIO_SPEED_50_MHZ = 0x3,
} stm32_goio_speed_t;
typedef enum {
STM32_GPIO_OTYPE_PP = 0x0,
STM32_GPIO_OTYPE_OD = 0x1,
} stm32_gpio_otype_t;
typedef enum {
STM32_GPIO_MODE_IN = 0x0,
STM32_GPIO_MODE_OUT = 0x1,
STM32_GPIO_MODE_AF = 0x2,
STM32_GPIO_MODE_AN = 0x3,
} stm32_gpio_mode_t;
typedef enum {
STM32_GPIO_PUPD_NONE = 0x0,
STM32_GPIO_PUPD_UP = 0x1,
STM32_GPIO_PUPD_DOWN = 0x2,
} stm32_gpio_pupd_t;
static stm32_gpio_t *stm32_gpio_port_to_pointer(unsigned int port)
{
switch (port) {
default:
@@ -47,63 +75,119 @@ static GPIO_TypeDef *port_to_pointer(unsigned int port)
}
}
static void enable_port(unsigned int port)
static void stm32_gpio_enable_port(unsigned int port)
{
DEBUG_ASSERT(port <= GPIO_PORT_F);
/* happens to be the RCC ids are sequential bits, so we can start from A and shift */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA << port, ENABLE);
switch (port) {
default:
case GPIO_PORT_A:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPA, true);
break;
case GPIO_PORT_B:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPB, true);
break;
case GPIO_PORT_C:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPC, true);
break;
case GPIO_PORT_D:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPD, true);
break;
case GPIO_PORT_E:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPE, true);
break;
case GPIO_PORT_F:
stm32_rcc_set_enable(STM32_RCC_CLK_IOPF, true);
break;
}
}
void stm32_gpio_early_init(void)
{
}
static void stm32_gpio_af_config(stm32_gpio_t *gpio, uint32_t pin,
uint32_t af_num) {
// 8 AF entries per register
uint32_t reg_index = pin >> 3;
uint32_t entry_shift = (pin & 0x7) * 4;
gpio->AFR[reg_index] &= ~(0xf << entry_shift);
gpio->AFR[reg_index] |= (af_num & 0xf) << entry_shift;
}
int gpio_config(unsigned nr, unsigned flags)
{
uint port = GPIO_PORT(nr);
uint pin = GPIO_PIN(nr);
uint32_t port = GPIO_PORT(nr);
uint32_t pin = GPIO_PIN(nr);
stm32_gpio_t *gpio = stm32_gpio_port_to_pointer(port);
enable_port(port);
assert(pin < 16);
GPIO_InitTypeDef init;
init.GPIO_Speed = GPIO_Speed_50MHz;
init.GPIO_Pin = (1 << pin);
init.GPIO_PuPd = GPIO_PuPd_NOPULL;
stm32_gpio_enable_port(port);
if (flags & GPIO_INPUT) {
init.GPIO_Mode = GPIO_Mode_IN;
} else if (flags & GPIO_OUTPUT) {
init.GPIO_Mode = GPIO_Mode_OUT;
if (flags & GPIO_STM32_AF) {
stm32_gpio_af_config(gpio, pin, GPIO_AFNUM(flags));
}
if ((flags & GPIO_OUTPUT) || (flags & GPIO_STM32_AF)) {
// All pins configured to 50MHz.
gpio->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pin * 2));
gpio->OSPEEDR |= STM32_GPIO_SPEED_50_MHZ << (pin * 2);
// Output mode configuration
gpio->OTYPER &= ~((GPIO_OTYPER_OT_0) << pin);
if (flags & GPIO_STM32_OD) {
gpio->OTYPER |= STM32_GPIO_OTYPE_OD << pin;
} else {
gpio->OTYPER |= STM32_GPIO_OTYPE_PP << pin;
}
}
stm32_gpio_mode_t mode;
if (flags & GPIO_OUTPUT) {
mode = STM32_GPIO_MODE_OUT;
} else if (flags & GPIO_STM32_AF) {
init.GPIO_Mode = GPIO_Mode_AF;
GPIO_PinAFConfig(port_to_pointer(port), pin, GPIO_AFNUM(flags));
}
if (flags & GPIO_PULLUP) {
init.GPIO_PuPd = GPIO_PuPd_UP;
} else if (flags & GPIO_PULLDOWN) {
init.GPIO_PuPd = GPIO_PuPd_DOWN;
}
if (flags & GPIO_STM32_OD) {
init.GPIO_OType = GPIO_OType_OD;
mode = STM32_GPIO_MODE_AF;
} else {
init.GPIO_OType = GPIO_OType_PP;
mode = STM32_GPIO_MODE_IN;
}
GPIO_Init(port_to_pointer(port), &init);
gpio->MODER &= ~(GPIO_MODER_MODER0 << (pin * 2));
gpio->MODER |= (mode << (pin * 2));
stm32_gpio_pupd_t pupd = STM32_GPIO_PUPD_NONE;
if (flags & GPIO_PULLUP) {
pupd = STM32_GPIO_PUPD_UP;
} else if (flags & GPIO_PULLDOWN) {
pupd = STM32_GPIO_PUPD_DOWN;
}
gpio->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << (pin * 2));
gpio->PUPDR |= pupd << (pin * 2);
return 0;
}
void gpio_set(unsigned nr, unsigned on)
{
GPIO_WriteBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr), on);
stm32_gpio_t *gpio = stm32_gpio_port_to_pointer(nr);
if (on) {
gpio->BSRR = 1 << GPIO_PIN(nr);
} else {
gpio->BRR = 1 << GPIO_PIN(nr);
}
}
int gpio_get(unsigned nr)
{
return GPIO_ReadInputDataBit(port_to_pointer(GPIO_PORT(nr)), 1 << GPIO_PIN(nr));
stm32_gpio_t *gpio = stm32_gpio_port_to_pointer(nr);
return (gpio->IDR & (1 << GPIO_PIN(nr))) != 0;
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2016 Erik Gilling
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __PLATFORM_STM32_RCC_H
#define __PLATFORM_STM32_RCC_H
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <stm32f0xx.h>
enum {
STM32_RCC_REG_AHB = 0,
STM32_RCC_REG_APB1 = 1,
STM32_RCC_REG_APB2 = 2,
};
#define STM32_RCC_CLK(reg, index) (((reg) << 16) | (index))
#define STM32_RCC_CLK_AHB(index) STM32_RCC_CLK(STM32_RCC_REG_AHB, index)
#define STM32_RCC_CLK_APB1(index) STM32_RCC_CLK(STM32_RCC_REG_APB1, index)
#define STM32_RCC_CLK_APB2(index) STM32_RCC_CLK(STM32_RCC_REG_APB2, index)
#define STM32_RCC_CLK_REG(clk) ((clk) >> 16)
#define STM32_RCC_CLK_INDEX(clk) ((clk) & 0xffff)
typedef enum {
// AHB clocks.
STM32_RCC_CLK_DMA = STM32_RCC_CLK_AHB(0),
STM32_RCC_CLK_DMA2 = STM32_RCC_CLK_AHB(1),
STM32_RCC_CLK_SRAM = STM32_RCC_CLK_AHB(2),
STM32_RCC_CLK_FLITF = STM32_RCC_CLK_AHB(4),
STM32_RCC_CLK_CRC = STM32_RCC_CLK_AHB(6),
STM32_RCC_CLK_IOPA = STM32_RCC_CLK_AHB(17),
STM32_RCC_CLK_IOPB = STM32_RCC_CLK_AHB(18),
STM32_RCC_CLK_IOPC = STM32_RCC_CLK_AHB(19),
STM32_RCC_CLK_IOPD = STM32_RCC_CLK_AHB(20),
STM32_RCC_CLK_IOPE = STM32_RCC_CLK_AHB(21),
STM32_RCC_CLK_IOPF = STM32_RCC_CLK_AHB(22),
STM32_RCC_CLK_TSC = STM32_RCC_CLK_AHB(24),
// APB1 clocks.
STM32_RCC_CLK_TIM2 = STM32_RCC_CLK_APB1(0),
STM32_RCC_CLK_TIM3 = STM32_RCC_CLK_APB1(1),
STM32_RCC_CLK_TIM6 = STM32_RCC_CLK_APB1(4),
STM32_RCC_CLK_TIM7 = STM32_RCC_CLK_APB1(5),
STM32_RCC_CLK_TIM14 = STM32_RCC_CLK_APB1(8),
STM32_RCC_CLK_WWDG = STM32_RCC_CLK_APB1(11),
STM32_RCC_CLK_SPI2 = STM32_RCC_CLK_APB1(14),
STM32_RCC_CLK_USART2 = STM32_RCC_CLK_APB1(17),
STM32_RCC_CLK_USART3 = STM32_RCC_CLK_APB1(18),
STM32_RCC_CLK_USART4 = STM32_RCC_CLK_APB1(19),
STM32_RCC_CLK_USART5 = STM32_RCC_CLK_APB1(20),
STM32_RCC_CLK_I2C1 = STM32_RCC_CLK_APB1(21),
STM32_RCC_CLK_I2C2 = STM32_RCC_CLK_APB1(22),
STM32_RCC_CLK_USB = STM32_RCC_CLK_APB1(23),
STM32_RCC_CLK_CAN = STM32_RCC_CLK_APB1(25),
STM32_RCC_CLK_CRS = STM32_RCC_CLK_APB1(27),
STM32_RCC_CLK_PWR = STM32_RCC_CLK_APB1(28),
STM32_RCC_CLK_DAC = STM32_RCC_CLK_APB1(29),
STM32_RCC_CLK_CEC = STM32_RCC_CLK_APB1(30),
// APB2 clocks.
STM32_RCC_CLK_SYSCFGCOMP = STM32_RCC_CLK_APB2(0),
STM32_RCC_CLK_USART6 = STM32_RCC_CLK_APB2(5),
STM32_RCC_CLK_USART7 = STM32_RCC_CLK_APB2(6),
STM32_RCC_CLK_USART8 = STM32_RCC_CLK_APB2(7),
STM32_RCC_CLK_ADC = STM32_RCC_CLK_APB2(9),
STM32_RCC_CLK_TIM1 = STM32_RCC_CLK_APB2(11),
STM32_RCC_CLK_SPI1 = STM32_RCC_CLK_APB2(12),
STM32_RCC_CLK_USART1 = STM32_RCC_CLK_APB2(14),
STM32_RCC_CLK_TIM15 = STM32_RCC_CLK_APB2(16),
STM32_RCC_CLK_TIM16 = STM32_RCC_CLK_APB2(17),
STM32_RCC_CLK_TIM17 = STM32_RCC_CLK_APB2(18),
STM32_RCC_CLK_DBG_MUC = STM32_RCC_CLK_APB2(22),
} stm32_rcc_clk_t;
void stm32_rcc_set_enable(stm32_rcc_clk_t clock, bool enable);
void stm32_rcc_set_reset(stm32_rcc_clk_t clock, bool reset);
#endif // __PLATFORM_STM32_RCC_H

68
platform/stm32f0xx/rcc.c Normal file
View File

@@ -0,0 +1,68 @@
#include "platform/rcc.h"
#include <stm32f0xx.h>
static __IO uint32_t *stm32_rcc_get_clock_en_reg(stm32_rcc_clk_t clock) {
switch (STM32_RCC_CLK_REG(clock)) {
case STM32_RCC_REG_AHB:
return &RCC->AHBENR;
case STM32_RCC_REG_APB1:
return &RCC->APB1ENR;
case STM32_RCC_REG_APB2:
return &RCC->APB2ENR;
default:
return NULL;
}
}
static __IO uint32_t *stm32_rcc_get_clock_rst_reg(stm32_rcc_clk_t clock) {
switch (STM32_RCC_CLK_REG(clock)) {
case STM32_RCC_REG_AHB:
return &RCC->AHBRSTR;
case STM32_RCC_REG_APB1:
return &RCC->APB1RSTR;
case STM32_RCC_REG_APB2:
return &RCC->APB2RSTR;
default:
return NULL;
}
}
void stm32_rcc_set_enable(stm32_rcc_clk_t clock, bool enable) {
__IO uint32_t *reg = stm32_rcc_get_clock_en_reg(clock);
if (enable) {
*reg |= 1 << STM32_RCC_CLK_INDEX(clock);
} else {
*reg &= ~(1 << STM32_RCC_CLK_INDEX(clock));
}
}
void stm32_rcc_set_reset(stm32_rcc_clk_t clock, bool reset) {
switch(clock) {
// These clocks to not have reset bits.
case STM32_RCC_CLK_DMA:
case STM32_RCC_CLK_DMA2:
case STM32_RCC_CLK_SRAM:
case STM32_RCC_CLK_FLITF:
case STM32_RCC_CLK_CRC:
return;
default:
break;
}
__IO uint32_t *reg = stm32_rcc_get_clock_rst_reg(clock);
if (reset) {
*reg |= 1 << STM32_RCC_CLK_INDEX(clock);
} else {
*reg &= ~(1 << STM32_RCC_CLK_INDEX(clock));
}
}

View File

@@ -31,6 +31,7 @@ MODULE_SRCS += \
$(LOCAL_DIR)/dma.c \
$(LOCAL_DIR)/gpio.c \
$(LOCAL_DIR)/init.c \
$(LOCAL_DIR)/rcc.c \
$(LOCAL_DIR)/spi.c \
$(LOCAL_DIR)/timer.c \
$(LOCAL_DIR)/uart.c \

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012 Kent Ryhorchuk
* Copyright (c) 2016 Erik Gilling
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -20,41 +21,37 @@
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdarg.h>
#include <reg.h>
#include <debug.h>
#include <stdio.h>
#include <assert.h>
#include <lib/cbuf.h>
#include <kernel/thread.h>
#include <platform/debug.h>
#include <arch/ops.h>
#include <dev/uart.h>
#include <target/debugconfig.h>
#include <stm32f0xx_rcc.h>
#include <stm32f0xx_usart.h>
#include <arch/arm/cm.h>
#include <assert.h>
#include <dev/uart.h>
#include <lib/cbuf.h>
#include <platform/rcc.h>
#include <stdint.h>
#include <stm32f0xx.h>
typedef USART_TypeDef stm32_usart_t;
#define RXBUF_SIZE 16
#ifdef ENABLE_UART1
cbuf_t uart1_rx_buf;
#ifndef UART1_FLOWCONTROL
#define UART1_FLOWCONTROL USART_HardwareFlowControl_None
#define UART1_FLOWCONTROL 0x0
#endif
#endif
#ifdef ENABLE_UART2
cbuf_t uart2_rx_buf;
#ifndef UART2_FLOWCONTROL
#define UART2_FLOWCONTROL USART_HardwareFlowControl_None
#define UART2_FLOWCONTROL 0x0
#endif
#endif
#ifdef ENABLE_UART3
cbuf_t uart3_rx_buf;
#ifndef UART3_FLOWCONTROL
#define UART3_FLOWCONTROL USART_HardwareFlowControl_None
#define UART3_FLOWCONTROL 0x0
#endif
#endif
@@ -65,84 +62,99 @@ cbuf_t uart3_rx_buf;
#ifdef ENABLE_UART3
#endif
static void usart_init1_early(USART_TypeDef *usart, uint16_t flowcontrol, int irqn)
static void stm32_usart_init1_early(stm32_usart_t *usart,
uint16_t flow_control, int irqn)
{
USART_InitTypeDef init;
uint32_t baud_rate = 115200;
init.USART_BaudRate = 115200;
init.USART_WordLength = USART_WordLength_8b;
init.USART_StopBits = USART_StopBits_1;
init.USART_Parity = USART_Parity_No;
init.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
init.USART_HardwareFlowControl = flowcontrol;
// Ensure USART is disabled before configuring it.
usart->CR1 = 0;
USART_Init(usart, &init);
USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
// Set stop bits to 1 (CR2[13:12] = 00b)
usart->CR2 = 0;
// Go with the defaults of:
// word length: 8 bits
// parity: disabled
// Enable TX and RX.
usart->CR1 = USART_CR1_TE | USART_CR1_RE;
usart->CR3 = flow_control;
// TODO(konkers): Add rcc API for querying clock freq.
uint32_t apb_clock = 48000000;
usart->BRR = (apb_clock + baud_rate / 2) / baud_rate;
// Leave IRQs disabled until init.
NVIC_DisableIRQ(irqn);
USART_Cmd(usart, ENABLE);
// Enable UART.
usart->CR1 |= USART_CR1_UE;
}
static void usart_init1(USART_TypeDef *usart, int irqn, cbuf_t *rxbuf)
static void stm32_usart_init1(stm32_usart_t *usart, int irqn, cbuf_t *rxbuf)
{
cbuf_initialize(rxbuf, RXBUF_SIZE);
USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
// Enable RX not empty interrupt.
usart->CR1 |= USART_CR1_RXNEIE;
NVIC_EnableIRQ(irqn);
USART_Cmd(usart, ENABLE);
}
void uart_init_early(void)
{
#ifdef ENABLE_UART1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
stm32_rcc_set_enable(STM32_RCC_CLK_USART1, true);
#endif
#ifdef ENABLE_UART2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
stm32_rcc_set_enable(STM32_RCC_CLK_USART2, true);
#endif
#ifdef ENABLE_UART3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
stm32_rcc_set_enable(STM32_RCC_CLK_USART3, true);
#endif
#ifdef ENABLE_UART1
usart_init1_early(USART1, UART1_FLOWCONTROL, USART1_IRQn);
stm32_usart_init1_early(USART1, UART1_FLOWCONTROL, USART1_IRQn);
#endif
#ifdef ENABLE_UART2
usart_init1_early(USART2, UART2_FLOWCONTROL, USART2_IRQn);
stm32_usart_init1_early(USART2, UART2_FLOWCONTROL, USART2_IRQn);
#endif
#ifdef ENABLE_UART3
usart_init1_early(USART3, UART3_FLOWCONTROL, USART3_IRQn);
stm32_usart_init1_early(USART3, UART3_FLOWCONTROL, USART3_IRQn);
#endif
}
void uart_init(void)
{
#ifdef ENABLE_UART1
usart_init1(USART1, USART1_IRQn, &uart1_rx_buf);
stm32_usart_init1(USART1, USART1_IRQn, &uart1_rx_buf);
#endif
#ifdef ENABLE_UART2
usart_init1(USART2, USART2_IRQn, &uart2_rx_buf);
stm32_usart_init1(USART2, USART2_IRQn, &uart2_rx_buf);
#endif
#ifdef ENABLE_UART3
usart_init1(USART3, USART3_IRQn, &uart3_rx_buf);
stm32_usart_init1(USART3, USART3_IRQn, &uart3_rx_buf);
#endif
}
// I'm seeing a weird issue with my nucleo-f072rb board where rx interrupts
// don't fire right after a reset by the on board programmer. If I hit
// the reset button, rx works fine. I can live with this. YMMV.
void uart_rx_irq(USART_TypeDef *usart, cbuf_t *rxbuf)
static void stm32_uart_rx_irq(stm32_usart_t *usart, cbuf_t *rxbuf)
{
arm_cm_irq_entry();
bool resched = false;
while (USART_GetFlagStatus(usart, USART_FLAG_RXNE)) {
while (usart->ISR & USART_ISR_RXNE) {
if (!cbuf_space_avail(rxbuf)) {
// Overflow - let flow control do its thing by not
// reading the from the FIFO.
USART_ITConfig(usart, USART_IT_RXNE, DISABLE);
usart->CR1 &= ~USART_CR1_RXNEIE;
break;
}
char c = USART_ReceiveData(usart);
char c = usart->RDR;
cbuf_write_char(rxbuf, c, false);
resched = true;
}
@@ -153,43 +165,43 @@ void uart_rx_irq(USART_TypeDef *usart, cbuf_t *rxbuf)
#ifdef ENABLE_UART1
void stm32_USART1_IRQ(void)
{
uart_rx_irq(USART1, &uart1_rx_buf);
stm32_uart_rx_irq(USART1, &uart1_rx_buf);
}
#endif
#ifdef ENABLE_UART2
void stm32_USART2_IRQ(void)
{
uart_rx_irq(USART2, &uart2_rx_buf);
stm32_uart_rx_irq(USART2, &uart2_rx_buf);
}
#endif
#ifdef ENABLE_UART3
void stm32_USART3_IRQ(void)
{
uart_rx_irq(USART3, &uart3_rx_buf);
stm32_uart_rx_irq(USART3, &uart3_rx_buf);
}
#endif
static void usart_putc(USART_TypeDef *usart, char c)
static void stm32_usart_putc(stm32_usart_t *usart, char c)
{
while (USART_GetFlagStatus(usart, USART_FLAG_TXE) == 0);
USART_SendData(usart, c);
while (USART_GetFlagStatus(usart, USART_FLAG_TC) == 0);
while ((usart->ISR & USART_ISR_TXE) == 0);
usart->TDR = c;
while ((usart->ISR & USART_ISR_TC) == 0);
}
static int usart_getc(USART_TypeDef *usart, cbuf_t *rxbuf, bool wait)
static int stm32_usart_getc(stm32_usart_t *usart, cbuf_t *rxbuf, bool wait)
{
char c;
cbuf_read_char(rxbuf, &c, wait);
if (cbuf_space_avail(rxbuf) > RXBUF_SIZE/2)
USART_ITConfig(usart, USART_IT_RXNE, ENABLE);
usart->CR1 |= USART_CR1_RXNEIE;
return c;
}
static USART_TypeDef *get_usart(int port)
static stm32_usart_t *stm32_get_usart(int port)
{
switch (port) {
#ifdef ENABLE_UART1
@@ -211,7 +223,7 @@ static USART_TypeDef *get_usart(int port)
}
static cbuf_t *get_rxbuf(int port)
static cbuf_t *stm32_get_rxbuf(int port)
{
switch (port) {
#ifdef ENABLE_UART1
@@ -235,17 +247,17 @@ static cbuf_t *get_rxbuf(int port)
int uart_putc(int port, char c)
{
USART_TypeDef *usart = get_usart(port);
usart_putc(usart, c);
stm32_usart_t *usart = stm32_get_usart(port);
stm32_usart_putc(usart, c);
return 1;
}
int uart_getc(int port, bool wait)
{
cbuf_t *rxbuf = get_rxbuf(port);
USART_TypeDef *usart = get_usart(port);
cbuf_t *rxbuf = stm32_get_rxbuf(port);
stm32_usart_t *usart = stm32_get_usart(port);
return usart_getc(usart, rxbuf, wait);
return stm32_usart_getc(usart, rxbuf, wait);
}
void uart_flush_tx(int port) {}