F030系列芯片UART3~UART6代码分享

看了大家对f030复用串口的疑惑,这里继续给出“当同时使用uart3~uart6中的多个串口时,由于其中断响应函数都是同一个,需要自己在中断函数usart3_6_irqhandler() 中判断是来自哪个串口的中断。”这个问题的解决办法。这里使用的是串口v2版本。
void usart3_6_irqhandler(void)
{
/* enter interrupt */
rt_interrupt_enter();
struct stm32_uart *uart3,*uart4,uart5;
uart5 = rt_container_of(&(uart_obj[uart5_index].serial), struct stm32_uart, serial);
uart3 = rt_container_of(&(uart_obj[uart3_index].serial), struct stm32_uart, serial);
uart4 = rt_container_of(&(uart_obj[uart4_index].serial), struct stm32_uart, serial);
if(__hal_uart_get_flag(&(uart3->handle), uart_flag_rxne) != reset)
uart_isr(&(uart_obj[uart3_index].serial));
if(__hal_uart_get_flag(&(uart4->handle), uart_flag_rxne) != reset)
uart_isr(&(uart_obj[uart4_index].serial));
if(__hal_uart_get_flag(&(uart5->handle), uart_flag_rxne) != reset)
uart_isr(&(uart_obj[uart5_index].serial));
/ leave interrupt */
rt_interrupt_leave();
}
其中就是加入了获取串口的判断,执行不同中断isr。还有一点需要注意,f030rc的默认dma通道是cxs 0级别的中断,如果需要使用串口的dma中断,需要在dma初始化的时候添加__hal_dma1_remap()函数,
据需要选择不同串口即可,下面是dma初始化代码。
static void stm32_dma_config(struct rt_serial_device serial, rt_ubase_t flag)
{
struct rt_serial_rx_fifo rx_fifo;
dma_handletypedef dma_handle;
struct dma_config dma_config;
struct stm32_uart uart;
rt_assert(serial != rt_null);
rt_assert(flag == rt_device_flag_dma_tx || flag == rt_device_flag_dma_rx);
uart = rt_container_of(serial, struct stm32_uart, serial);
if (rt_device_flag_dma_rx == flag)
{
dma_handle = &uart->dma_rx.handle;
dma_config = uart->config->dma_rx;
}
else / rt_device_flag_dma_tx == flag /
{
dma_handle = &uart->dma_tx.handle;
dma_config = uart->config->dma_tx;
}
log_d(%s dma config start, uart->config->name);
{
rt_uint32_t tmpreg = 0x00u;
#if defined(soc_series_stm32f1) || defined(soc_series_stm32f0) || defined(soc_series_stm32g0)
|| defined(soc_series_stm32l0)
/ enable dma clock && delay after an rcc peripheral clock enabling /
set_bit(rcc->ahbenr, dma_config->dma_rcc);
tmpreg = read_bit(rcc->ahbenr, dma_config->dma_rcc);
#elif defined(soc_series_stm32f4) || defined(soc_series_stm32f7) || defined(soc_series_stm32l4) || defined(soc_series_stm32wl)
|| defined(soc_series_stm32g4)|| defined(soc_series_stm32h7) || defined(soc_series_stm32wb)
/ enable dma clock && delay after an rcc peripheral clock enabling /
set_bit(rcc->ahb1enr, dma_config->dma_rcc);
tmpreg = read_bit(rcc->ahb1enr, dma_config->dma_rcc);
#elif defined(soc_series_stm32mp1)
/ enable dma clock && delay after an rcc peripheral clock enabling*/
set_bit(rcc->mp_ahb2ensetr, dma_config->dma_rcc);
tmpreg = read_bit(rcc->mp_ahb2ensetr, dma_config->dma_rcc);
#endif
#if defined(dmamux1) && (defined(soc_series_stm32l4) || defined(soc_series_stm32wl) || defined(soc_series_stm32g4) || defined(soc_series_stm32wb))
/* enable dmamux clock for l4+ and g4 /
__hal_rcc_dmamux1_clk_enable();
#elif defined(soc_series_stm32mp1)
__hal_rcc_dmamux_clk_enable();
#endif
unused(tmpreg); / to avoid compiler warnings /
}
if (rt_device_flag_dma_rx == flag)
{
__hal_linkdma(&(uart->handle), hdmarx, uart->dma_rx.handle);
}
else if (rt_device_flag_dma_tx == flag)
{
__hal_linkdma(&(uart->handle), hdmatx, uart->dma_tx.handle);
}
#if defined(soc_series_stm32f1) || defined(soc_series_stm32f0) || defined(soc_series_stm32l0)
dma_handle->instance = dma_config->instance;
#elif defined(soc_series_stm32f4) || defined(soc_series_stm32f7)
dma_handle->instance = dma_config->instance;
dma_handle->init.channel = dma_config->channel;
#elif defined(soc_series_stm32l4) || defined(soc_series_stm32wl) || defined(soc_series_stm32g0) || defined(soc_series_stm32g4) || defined(soc_series_stm32wb)
|| defined(soc_series_stm32h7) || defined(soc_series_stm32mp1)
dma_handle->instance = dma_config->instance;
dma_handle->init.request = dma_config->request;
#endif
dma_handle->init.periphinc = dma_pinc_disable;
dma_handle->init.meminc = dma_minc_enable;
dma_handle->init.periphdataalignment = dma_pdataalign_byte;
dma_handle->init.memdataalignment = dma_mdataalign_byte;
if (rt_device_flag_dma_rx == flag)
{
dma_handle->init.direction = dma_periph_to_memory;
dma_handle->init.mode = dma_circular;
}
else if (rt_device_flag_dma_tx == flag)
{
dma_handle->init.direction = dma_memory_to_periph;
dma_handle->init.mode = dma_normal;
}
dma_handle->init.priority = dma_priority_medium;
#if defined(soc_series_stm32f4) || defined(soc_series_stm32f7) || defined(soc_series_stm32h7) || defined(soc_series_stm32mp1)
dma_handle->init.fifomode = dma_fifomode_disable;
#endif
if (hal_dma_deinit(dma_handle) != hal_ok)
{
rt_assert(0);
}
if (hal_dma_init(dma_handle) != hal_ok)
{
rt_assert(0);
}
__hal_dma1_remap(hal_dma1_ch3_usart3_rx); //添加这两个即可
__hal_dma1_remap(hal_dma1_ch1_usart4_rx);
/ enable interrupt */
if (flag == rt_device_flag_dma_rx)
{
rx_fifo = (struct rt_serial_rx_fifo )serial->serial_rx;
rt_assert(rx_fifo != rt_null);
/ start dma transfer /
if (hal_uart_receive_dma(&(uart->handle), rx_fifo->buffer, serial->config.rx_bufsz) != hal_ok)
{
/ transfer error in reception process /
rt_assert(0);
}
clear_bit(uart->handle.instance->cr3, usart_cr3_eie);
__hal_uart_enable_it(&(uart->handle), uart_it_idle);
}
/ dma irq should set in dma tx mode, or hal_uart_txcpltcallback function will not be called */
hal_nvic_setpriority(dma_config->dma_irq, 0, 0);
hal_nvic_enableirq(dma_config->dma_irq);
hal_nvic_setpriority(uart->config->irq_type, 1, 0);
hal_nvic_enableirq(uart->config->irq_type);
log_d(%s dma %s instance: %x, uart->config->name, flag == rt_device_flag_dma_rx ? rx : tx, dma_handle->instance);
log_d(%s dma config done, uart->config->name);
}

PL2586 USB2.0高速4端口集线器控制器概述及特点
距领奖台仅一步之遥,远景电动方程式车队摩纳哥站斩获双积分
下一代通用内存会是ULTRARAM吗?
如何使用近场探头?
力科44Xi示波器可以开机,但进不了系统-安泰维修
F030系列芯片UART3~UART6代码分享
苹果美国官网卖“翻新机”?售价1869美元起
铜浇注PCB设计的优缺点
恐惧对程序员的影响
移频键控(FSK)实验
TI SensorTag套件协助蓝牙低功耗智能手机应用开发
滴滴出行正在加利福尼亚州山景城建立一个新实验室
简单介绍MOSFET的原理
微软Edge浏览器开启了夜间模式和双因素身份验证功能
激光粒度分析仪应用哪些领域
5G的到来或使未来医疗趋向智能化
【节能学院】消防应急疏散指示系统在某健身中心项目的研究应用
开关磁阻电机工作原理 开关磁阻电机的优缺点
联想ThinkPad E15首发,搭载英特尔10代酷睿处理器
物联网数据所有权存在什么争议