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等函數


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章