Zephyr uart驱动及使用方法

1. 说明
参考的单板: stm32f429i_disc1
zephyr版本: zephyr v1.10.0

2. 驱动加载方法 
1) uart pinmux驱动加载
pinmux.c (boards\arm\stm32f429i_disc1) // 引脚复用驱动最上层,调用SYS_INIT注册驱动

static const struct pin_config pinconf[] = {
#ifdef CONFIG_UART_STM32_PORT_1
{STM32_PIN_PA9, STM32F4_PINMUX_FUNC_PA9_USART1_TX},
{STM32_PIN_PA10, STM32F4_PINMUX_FUNC_PA10_USART1_RX},
#endif  /* CONFIG_UART_STM32_PORT_1 */
};

pinmux_stm32_init(struct device *port)
stm32_setup_pins(pinconf, ARRAY_SIZE(pinconf))   // pinmux_stm32.c (drivers\pinmux\stm32), 该文件为通用stm32引脚复用驱动
_pinmux_stm32_set
enable_port(STM32_PORT(pin), clk)
stm32_pin_configure(pin, func, func & STM32_AFR_MASK);// soc_gpio.c (arch\arm\soc\st_stm32\stm32f4), GPIO配置最底层函数,直接操作寄存器
//soc_gpio.c包含如下函数
int stm32_gpio_configure(u32_t *base_addr, int pin, int conf, int altf)
int stm32_gpio_set(u32_t *base, int pin, int value)
int stm32_gpio_get(u32_t *base, int pin)
int stm32_gpio_enable_int(int port, int pin)
/* 驱动加载 */
SYS_INIT(pinmux_stm32_init, PRE_KERNEL_1, CONFIG_PINMUX_STM32_DEVICE_INITIALIZATION_PRIORITY);

2) uart 驱动加载
uart_stm32.c (drivers\serial)

/* uart驱动api函数示例 */
static int uart_stm32_poll_in(struct device *dev, unsigned char *c)
{
USART_TypeDef *UartInstance = UART_STRUCT(dev);
if (!LL_USART_IsActiveFlag_RXNE(UartInstance)) {
return -1;
}
*c = (unsigned char)LL_USART_ReceiveData8(UartInstance);
return 0;
}

/* 以下为uart 驱动api函数,它们将调用Stm32f4xx_ll_usart.h (ext\hal\st\stm32cube\stm32f4xx\drivers\include)中的uart操作函数,
并调用Stm32l4xx.h (ext\hal\st\stm32cube\stm32l4xx\soc)中的宏直接操作寄存器,完成uart数据收发等操作 */
static const struct uart_driver_api uart_stm32_driver_api = {
.poll_in = uart_stm32_poll_in,
.poll_out = uart_stm32_poll_out,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_stm32_fifo_fill,
.fifo_read = uart_stm32_fifo_read,
.irq_tx_enable = uart_stm32_irq_tx_enable,
.irq_tx_disable = uart_stm32_irq_tx_disable,
.irq_tx_ready = uart_stm32_irq_tx_ready,
.irq_tx_complete = uart_stm32_irq_tx_complete,
.irq_rx_enable = uart_stm32_irq_rx_enable,
.irq_rx_disable = uart_stm32_irq_rx_disable,
.irq_rx_ready = uart_stm32_irq_rx_ready,
.irq_err_enable = uart_stm32_irq_err_enable,
.irq_err_disable = uart_stm32_irq_err_disable,
.irq_is_pending = uart_stm32_irq_is_pending,
.irq_update = uart_stm32_irq_update,
.irq_callback_set = uart_stm32_irq_callback_set,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};

/* uart 初始化 */
static int uart_stm32_init(struct device *dev)
{
const struct uart_stm32_config *config = DEV_CFG(dev);
struct uart_stm32_data *data = DEV_DATA(dev);
USART_TypeDef *UartInstance = UART_STRUCT(dev);
u32_t clock_rate;

__uart_stm32_get_clock(dev);

/* enable clock */
clock_control_on(data->clock, (clock_control_subsys_t *)&config->pclken);

LL_USART_Disable(UartInstance);

/* TX/RX direction */
LL_USART_SetTransferDirection(UartInstance, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(UartInstance, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);


/* Get clock rate */
clock_control_get_rate(data->clock,  (clock_control_subsys_t *)&config->pclken,  &clock_rate);

LL_USART_SetBaudRate(UartInstance, 
clock_rate,
#ifdef USART_CR1_OVER8
LL_USART_OVERSAMPLING_16,
#endif

data->huart.Init.BaudRate);

LL_USART_Enable(UartInstance);

// 此处有省略
return 0;
}

#define UART_DEVICE_INIT_STM32(type, n, apb) \
STM32_UART_IRQ_HANDLER_DECL(n); \
\
static const struct uart_stm32_config uart_stm32_dev_cfg_##n = { \
.uconf = { \
.base = (u8_t *)CONFIG_UART_STM32_PORT_ ## n ## _BASE_ADDRESS, \
STM32_UART_IRQ_HANDLER_FUNC(n) \
}, \
STM32_CLOCK_UART(type, apb, n), \
}; \
\
static struct uart_stm32_data uart_stm32_dev_data_##n = { \
.huart = { \
.Init = { \
.BaudRate = CONFIG_UART_STM32_PORT_##n##_BAUD_RATE     \
} \
} \
}; \
\
DEVICE_AND_API_INIT(uart_stm32_##n, CONFIG_UART_STM32_PORT_##n##_NAME, \
&uart_stm32_init, /* uart 初始化,设置时钟波特率,数据位等 */ \
&uart_stm32_dev_data_##n, &uart_stm32_dev_cfg_##n, \
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&uart_stm32_driver_api); /* uart 驱动api */ \
\
STM32_UART_IRQ_HANDLER(n)

#ifdef CONFIG_UART_STM32_PORT_1   // 如果定义CONFIG_UART_STM32_PORT_1,则加载uart1的驱动
UART_DEVICE_INIT_STM32(USART, 1, APB2)
#endif /* CONFIG_UART_STM32_PORT_1 */

3. 使用方法
1) 配置
    # stm32f429i_disc1_defconfig (boards\arm\stm32f429i_disc1)
# enable USART1 - passthrough to STLINK v2 connector
CONFIG_UART_STM32_PORT_1=y
# enable pinmux
CONFIG_PINMUX=y
//stm32f429i_disc1.dts (boards\arm\stm32f429i_disc1) 566 2017/12/9
/ {
model = "STMicroelectronics STM32F429I_DISC1 board";
compatible = "st,stm32f4discovery", "st,stm32f429";
chosen {
zephyr,console = &usart1;   /* console所使用的uart */
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
};
/* uart 配置 */
&usart1 {
current-speed = <115200>;
pinctrl-0 = <&usart1_pins_a>;
pinctrl-names = "default";
status = "ok";
};
2) 使用

直接调用printk/putc/puts/fputs等函数


猜你喜欢

转载自blog.csdn.net/u012408797/article/details/80266946