看了大家对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初始化代码。
sta
tic 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);
}
原作者:balabala