原子哥,最近遇到了一个BUG,麻烦帮忙看下,这是网上比较流行的UARTRX+DMA接受不定长数据的驱动
平台:stm32f103RET6
OS:裸跑
背景:需要USART2接受蓝牙芯片的音频流数据,蓝牙音乐44.1KHz的1s数据量为:44100*16*2/8= 176400Byte,由于蓝牙音乐是有压缩,所以1s的数据量为40KB左右,115200的波特率最大的传输是1s14KB左右,所以采用921600的波特率,由于蓝牙音乐建立连接,发现一直丢数据,所以弄stm32F103直接通过通过串口助手和PC通讯,来进行压力测试
问题点1:在间隔5ms,一直持续发啊送640byte,发现totalsize会丢数据
如图:发送了11584000Byte的数据,只接收到11465496,丢了118504byte的数据
问题点2:
每次发送640byte的时候,发现有的时候空闲中断来不及,所以就出现如图所示的size
程序:
[mw_shl_code=c,true]
uint8_t hw_uart2_init(uint32_t baud_rate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable USART2,GPIOA,DMA1 RCC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Initialize the GPIOA0,GPIOA1,GPIOA2,GPIOA3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Data format :1:8:1, no parity check, hardware flow control */
USART_InitStructure.USART_BaudRate = baud_rate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
/* Enable USART interrupts, mainly for idle interrupts */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Initializes USART2 to enable USART,USART idle interrupts, and USART RX DMA */
USART_Init(USART2, &USART_InitStructure);
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
USART_Cmd(USART2, ENABLE);
/* Initializes DMA and enables it */
memset(&DMA_UART2,0,sizeof(DMA_InitTypeDef));
DMA_DeInit(DMA1_Channel6);
DMA_UART2.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
DMA_UART2.DMA_MemoryBaseAddr = (uint32_t)bt_dma_rx_buf;
DMA_UART2.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_UART2.DMA_BufferSize = BT_DMA_BUF_SIZE;
DMA_UART2.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_UART2.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_UART2.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_UART2.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_UART2.DMA_Mode = DMA_Mode_Normal;
DMA_UART2.DMA_Priority = DMA_Priority_Medium;
DMA_UART2.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_UART2);
DMA_Cmd(DMA1_Channel6, ENABLE);
return 0;
}
[/mw_shl_code][mw_shl_code=c,true]void uart2_dma_enable(DMA_Channel_TypeDef*DMA_CHx)
{
DMA_Cmd(DMA_CHx, DISABLE);
DMA_UART2.DMA_MemoryBaseAddr = (uint32_t)bt_dma_rx_buf;
DMA_UART2.DMA_BufferSize = BT_DMA_BUF_SIZE;
DMA_Init(DMA1_Channel6, &DMA_UART2);
DMA_Cmd(DMA_CHx, ENABLE);
}[/mw_shl_code][mw_shl_code=c,true]uint32_t total_len = 0;
/******************************************************************************
* func name : USART2_IRQHandler
* para : NULL
* return : NULL
* description : Interrupt handler for usart2
******************************************************************************/
void USART2_IRQHandler(void)
{
uint32_t recv_len;
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
{
/* Without this, the interrupt cannot be cleared and continues into the interrupt */
USART_ReceiveData(USART2);
/* Clear the interrupt and reset DMA */
USART_ClearITPendingBit(USART2,USART_IT_IDLE);
recv_len = BT_DMA_BUF_SIZE - DMA_GetCurrDataCounter(DMA1_Channel6);
total_len += recv_len;
printf("len %d total len %d
",recv_len,total_len);
uart2_dma_enable(DMA1_Channel6);
}
}[/mw_shl_code]
一周热门 更多>