關于LiteOS UART1 DMA發(fā)送的疑問

問題描述:

  1. 采用DMA1 channel4 作為uart1發(fā)送DMA

  2. 發(fā)現如果啟動DMA1 channel4 發(fā)送后,如果不查詢等待發(fā)送結束,接收數據完整

  3. 疑問是:DMA是用來釋放CPU資源,但是現在還需要等待DMA發(fā)送完成,不能釋放CPU,DMA存在的意義在哪里?

完整代碼:

icon_rar.gifLiteOS_m.zip

代碼截取如下:

static void DMA_TX_INIT(uint16_t cnt) {

? ? DMA_InitTypeDef DMA_InitStructure = { 0 };

? ? USART_DMACmd(USART1, USART_DMAReq_Tx, DISABLE); //關閉UART1 DMA發(fā)送

? ? DMA_Cmd(DMA1_Channel4, DISABLE); /* DMA1 Channel4 關閉 */

? ? DMA_DeInit(DMA1_Channel4);

? ? DMA_InitStructure.DMA_PeripheralBaseAddr = (u32) (&USART1->DATAR);?

? ? DMA_InitStructure.DMA_MemoryBaseAddr = (u32) TxBuffer1;//發(fā)送數據地址

? ? DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

? ? DMA_InitStructure.DMA_BufferSize = cnt;//發(fā)送數據長度

? ? DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

? ? DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

? ? DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

? ? DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

? ? DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

? ? DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

? ? DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

? ? DMA_Init(DMA1_Channel4, &DMA_InitStructure);

? ? DMA_Cmd(DMA1_Channel4, ENABLE); /* 使能DMA1 Channel4 */

? ? USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); //使能UART1 DMA發(fā)送

? ? while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET) /* 等待發(fā)送完成,如果去掉這一句,接收就不完整 */

? ? ? ? {

? ? ? ? }


}

void UART1_DMA_Send(u8 *buf, u16 cnt) {

? ? if (cnt > TxSize1)

? ? ? ? return;

? ? memcpy(TxBuffer1, buf, cnt);

? ? DMA_TX_INIT(cnt);

}


VOID RFBLE_Task(VOID) {

? ? while(1) {

? ? ? ? //LOS_WAIT_FOREVER

? ? ? ? uint32_t ret=LOS_SemPend(g_semId, 100);//信號量超時

? ? ? ? if(ret==LOS_OK)

? ? ? ? ? ? UART1_DMA_Send(RxBuffer1Handle,rxDataCnt);//接收回環(huán)測試,實際上不給單片機發(fā)數據不會觸發(fā)

? ? ? ? else if(ret==LOS_ERRNO_SEM_TIMEOUT)//信號量超時,發(fā)送下面內容

? ? ? ? {

? ? ? ? ? ? u8 * RxBuffer1Handle1="hello harmonyOS\r\n";//發(fā)送內容

? ? ? ? ? ? UART1_DMA_Send(RxBuffer1Handle1,strlen(RxBuffer1Handle1));

? ? ? ? }

? ? }

}


問題復現100%:

1.去掉紅色代碼,接收亂了

[12:14:12.889]接收←hel

[12:14:13.140]接收←lo?

[12:14:14.078]接收←harmhe

[12:14:14.328]接收←llo

[12:14:15.278]接收← harhe

[12:14:15.528]接收←llo

[12:14:16.484]接收← harhe

[12:14:16.720]接收←llo

[12:14:17.675]接收← harhe

[12:14:17.925]接收←llo

[12:14:18.863]接收← harhe

[12:14:19.123]接收←llo

[12:14:20.070]接收← harhe

[12:14:20.318]接收←llo

[12:14:21.256]接收← harhe

[12:14:21.506]接收←llo


2.加上紅色代碼,接收正常

[12:15:36.330]接收←hello harmonyOS

? ? ? ? ? ? ? ? ? ??

[12:15:37.533]接收←hello harmonyOS

? ? ? ? ? ? ? ? ? ??

[12:15:38.721]接收←hello harmonyOS

? ? ? ? ? ? ? ? ? ??

[12:15:39.915]接收←hello harmonyOS




CH32V203c8t6


您好,關于你的問題,若不加查詢等待接收異常,可能是由于你程序中使用了操作系統(tǒng),進行多線程操作時,該傳輸若不加判斷可能會被其他線程或自己打斷,導致傳輸出現錯誤。此外關于DMA,正常在使用的時候都會對傳輸是否完成加個判斷,若你不想使用while方式,可以使用中斷方式,當傳輸完成之后進入傳輸完成中斷。此外,若不想查詢等待,可嘗試在傳輸過程中加個緩沖區(qū)試一下。后續(xù)若有問題,可通過郵箱(lzs@wch.cn)和我溝通,關于你的工程,若需要我這邊看一下建議將SRC文件夾一起壓縮到壓縮包發(fā)過來,否則工程缺少文件編譯報錯。


問題似乎已經找到,出在litesOS調度上,在DMA尚未完成傳輸的時候,已經進入idleTask,IdleTask又進入低功耗模式(__WIFI),導致DMA傳輸尚未完成,就被終止了,當前用while查詢方式解決,算是比較好的方式了。即使用DMA中斷方式,仍然需要告知liteOS在傳輸完成之前不能進入低功耗模式,這樣好像更復雜了。

icon_rar.gifSRC.zip



只有登錄才能回復,可以選擇微信賬號登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频