1. 程式人生 > 其它 >ADSP-BF706之UART串列埠DMA模式

ADSP-BF706之UART串列埠DMA模式

技術標籤:DSPdsp

2. ADSP-BF706之UART串列埠DMA模式

上一篇是時鐘配置,我今天會進一步驗證一下外部和內部時鐘的穩定性,對於中斷配置的話,我是在配置各個外設時順便就配置的,所以就不單獨列出來了,相關的配置會在文中提及。
今天來梳理一下uart的DMA配置模式:
UART的DMA模式配置分兩步走:
1、DMA配置。
2、UART模式配置。

DMA配置:
a. 配置傳輸地址
b. 一次傳送/接收的數量,如果是中斷模式,即接收或者傳送多少個位元組進入中斷
c. 地址增量
d. 配置DMA控制暫存器
首先在硬體手冊上找到:

首先在硬體手冊上找到相應的DMA通道,以下我使用的是UART1

在這裡插入圖片描述
其次分別配置傳送通道和接收通道:

/*
*傳送通道
*/
    *pREG_DMA12_ADDRSTART = tx_data;                         //UART0 Transmit DMA---DMA10
	*pREG_DMA12_XCNT = 12;
	*pREG_DMA12_XMOD = 1;

	*pREG_DMA12_CFG |= ENUM_DMA_CFG_MSIZE01 |
			           ENUM_DMA_CFG_STOP    |             //設定停止模式,在一次DMA完成之後,DMA通道自動停止
					   ENUM_DMA_CFG_READ    |             //Read from memory
					   ENUM_DMA_CFG_PSIZE01 |
					   ENUM_DMA_CFG_XCNT_INT|
					   ENUM_DMA_CFG_SYNC;
/*
*接收通道:
*/
    *pREG_DMA13_ADDRSTART = rx_data;                  //UART0 Receive DMA--DMA11
	*pREG_DMA13_XCNT = 1;
	*pREG_DMA13_XMOD = 1;

	*pREG_DMA13_CFG |= ENUM_DMA_CFG_MSIZE01|          //Memory Transfer Word Size
			           ENUM_DMA_CFG_AUTO   |             //在自動模式,在一次完成之後DMA立即恢復。
					   ENUM_DMA_CFG_WRITE  |            //Write/Read Channel Direction:Receive (Write to memory)
					   ENUM_DMA_CFG_PSIZE01|          //Peripheral Transfer Word Size.
					   ENUM_DMA_CFG_SYNC   |             //clears the DMA FIFO and pointers before starting
					   ENUM_DMA_CFG_XCNT_INT;         //The DMA_XCNT value = DMA_CFG.MSIZE transfers
					   
    *pREG_DMA13_CFG |= ENUM_DMA_CFG_EN;//使能接收

接收通道和傳送通道不同注意點:
接收通道是一個位元組一個位元組的接收,傳送通道的*pREG_DMA12_XCNT = 12;是可以在後期根據需求自行修改的;
傳送通道在傳送之後通道會自行關閉,需要傳送的時候再使能DMA12通道,而接收通道,要一直準備著接收,所以選擇自動模式。

UART配置:
直接上程式碼吧,思路和MCU串列埠配置類似:

*pREG_UART1_STAT = ENUM_UART_STAT_OVR_ERR          | \
				   ENUM_UART_STAT_FRAMING_ERR      | \
	               ENUM_UART_STAT_PARITY_ERR       | \
	               ENUM_UART_STAT_FRAMING_ERR      | \
	               ENUM_UART_STAT_BREAK_INT        | \
	               ENUM_UART_STAT_TX_DONE          | \
	               ENUM_UART_STAT_ADDR_HI_STKY     | \
	               ENUM_UART_STAT_ADDR_HI          | \
	               ENUM_UART_STAT_CTS_HI_STKY ;
	               
    *pREG_UART1_IMSK_CLR = 0x3FF;//關閉所有中斷

    *pREG_UART1_IMSK_SET |= BITM_UART_IMSK_SET_ETBEI|BITM_UART_IMSK_SET_ERBFI;

    ClkDivide_1 = (uint32_t) ( ((float)fsclk0 / ((float)BAUD_RATE))) );                           //115200u波特率
    *pREG_UART1_CLK = (ENUM_UART_CLK_EN_DIV_BY_ONE|(ClkDivide_1));    

    *pREG_UART1_CTL |=ENUM_UART_CTL_UART_MODE     |                 
    		          ENUM_UART_CTL_WL8BITS       |                      
					  ENUM_UART_CTL_NO_EXTRA_STBH |
					  ENUM_UART_CTL_RX_IRQ_TH7    |
					  BITM_UART_CTL_EN;
    adi_sec_EnableSource(INTR_UART1_RXDMA,true);
    adi_sec_SetPriority(INTR_UART1_RXDMA,0);                       //優先順序最高
   	adi_int_InstallHandler(INTR_UART1_RXDMA,UART1Callback,gUARTMemory,true); 

中斷在初始化配置的時候設定了等級的數量:
adi_sec_SetPriorityLevels(ADI_SEC_CORE_0,ADI_SEC_8_PRIORITY_LEVELS);
設定為總共有8個等級。
UART1Callback,回撥函式裡面是,進中斷過後需要處理接收到的命令,比如我的:

void UART1Callback(uint32_t SID, void *pCBParam)
{
	tasktype=UART_TIME_BEGIN;                       //開始空閒計時
	RecvUart[uartRecvCount++]= rx_data[0];
	if(rx_data[0]=='\n')
	{
		tasktype=IDLE_TIME_HANDLE;
	   ClearIdleTime;
	   uartRecvOk=true;
	   uartRecvCount=0;
	}
	*pREG_DMA13_STAT |= ENUM_DMA_STAT_IRQDONE | ENUM_DMA_STAT_IRQERR;           //DMA完成一次接收產生一次中斷
}

這些就根據需求來開發了。

這一部分的配置即使給出了程式碼,但是具體的還需要仔細看硬體手冊,看懂了理解才會更深,即使可能一段時間之後就忘了,哈哈。 我上面的配置只能說能用,可能還是比較累贅。

上面是關於DMA模式的,下一篇會寫UART關於中斷模式的。