STM32網絡控制器框圖如下:
前面的文章我們已經講解了:
①External PHY Intereface:《STM32網絡電路設計》
②MAC控制器:《STM32MAC控制器》
下面我們講解第③部分,STM32網絡的DMA控制器。
01、DMA控制器操作
DMA具有自主的發送和接收引擎,還有一個CSR(控制和狀態寄存器)空間。發送引擎將數據從系統存儲器傳送到 TxFIFO,而接收引擎將數據從Rx FIFO傳送到系統存儲器。
控制器(也就是DMA)利用描述符有效的將數據從源地址移動到目的地,很小的CPU干預。DMA專為面向包的數據傳送(如以太網中的幀)而設計。
控制器可以編程去打斷CPU,例如完成幀發送和接收傳送操作時以及其它正常/錯誤條件下。
DMA和STM32F20x 和STM32F21x通過以下兩種數據結構進行通信:
-
控制和狀態寄存器 (CSR)
-
描述符列表和數據緩沖區。
DMA控制器發送接收到的數據幀到STM32F20x的接收緩存中和STM32F21x存儲器中,也可以發送數據幀從STM32F20x的存儲器的發送緩存,位於STM32F20x存儲器的描述符指向這些緩存。
這里有兩個描述符列表:一個用於接收,一個用於發送。
DMA描述符如下圖,左邊是環形結構,右邊是鏈式結構。
02、DMA描述符
在ST提供的以太網驅動庫stm32f2x7_eth.c中使用是鏈接結構,鏈接結構如下:
描述符注意事項:
1、一個以太網數據包可以跨越一個或多個DMA描述符
2、一個DMA描述符只能用於一個以太網數據包
3、DMA描述符列表中的最后一個描述符指向第一個,形成鏈式結構!
描述符有分為增強描述符和常規描述符,我們只講常規描述符!因為我們的網絡例程只使用到了常規描述符。常規描述符和增強描述符的結構體成員變量不同。常規描述符只使用了描述符的前4個成員變量。
注意:這里說的描述符,沒有硬件結構,不是寄存器,它完全是純軟件的概念。
那么描述符怎么和硬件關聯的呢?
描述符的本質就是我們自己用結構體來實現這個描述符,然后將描述符的首地址寫入到【ETH_DMATDLAR】寄存器中,STM32就知道這片內存是用來作為發送描述符了。
常規描述符和增強描述符又有發送描述符和接收描述符兩種。
下圖是常規TxDMA描述符:
TDES0主要用來表示描述符的狀態和控制信息。
TDES1表示該描述符緩沖區數據的有效長度。
TDES2表示描述符緩沖區的地址,我們要發送的數據,就是放在這個地址所指向的內存中。
TDES3表示下一個描述符的地址。
重要的信息有:
TDES 0中的OWN位:
0:表示CPU占有描述符,CPU可以從DMA中提取數據,但是DMA不能從FIFO從接收數據。
1:表示DMA占有描述符,CPU不可以從DMA中提取數據,DMA可以從FIFO從接收數據。
DMA在傳輸完整個幀或者這個緩存里的數據全部讀出以后把該位清0'。每個幀的第一個緩存描述符的占有位,必須在后面緩存描述符的占有位全部置'1'以后,才能置"1'。
發送過程:
1、當OWN位為0的時候,表示CPU可以將要發送的數據拷貝到描述符中,拷貝完成以后,我們手動將描述符的OWN位設置為1,以此來告訴DMA控制器,我已經拷貝完數據了,你可以從描述符中取出數據進行發送了。
2、這時候DMA就會取出描述符中的數據,將數據發送出去,DMA在操作完描述符以后,自動將OWN位設置為0,告訴CPU,我DMA已經發送完數據啦,你可以拷貝下一幀數據到描述符上了。
3、這個時候OWN為0了,重復步驟1
整個發送的過程就是這樣配合的。這樣DMA和CPU之間就不會搶占數據了。
DES 0中的位20 TCH:鏈接的第二個地址(Second address chained)
用來表示描述符中的第二個地址是用來保存下一個描述符地址還是第二個緩沖區的地址。
該位置1時,表示描述符中的第二個地址是下一個描述符地址,而非第二個緩沖區地址。也就是上ST使用的鏈式結構。
常規RxDMA描述符如下
常規RxDMA描述符中RDES1的bit14用來表示描述符中的第二個地址是用來保存一個描述符地址還是第二個緩沖區的地址。
描述符在代碼中的表現,在stm32f2x7_eth.h文件中。
/**--------------------------------------------------------------------------**/ /** * @brief DMA descriptors types */ /**--------------------------------------------------------------------------**/ /** * @brief ETH DMA Descriptors data structure definition */ typedef struct { __IO uint32_t Status; /*!< Status */ uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ /* Enhanced ETHERNET DMA PTP Descriptors */ #ifdef USE_ENHANCED_DMA_DESCRIPTORS uint32_t ExtendedStatus; /* Extended status for PTP receive descriptor */ uint32_t Reserved1; /* Reserved */ uint32_t TimeStampLow; /* Time Stamp Low value for transmit and receive */ uint32_t TimeStampHigh; /* Time Stamp High value for transmit and receive */ #endif /* USE_ENHANCED_DMA_DESCRIPTORS */ } ETH_DMADESCTypeDef;
03、ST提供的庫中描述符
ST官方以太網庫stm32f2x7中使用鏈接結構的DMA描述符,那么在以太網描述符結構體ETH_DMADESCTypeDef中Buffer1Addr就是緩沖區的地址,Buffer2NextDescAddr就是下一個描述符的地址,
如下圖。
在stm32f2x7_eth.c中定義了兩個DMA描述符數組,一個用於DMA接收,一個用於DMA發送,如下:
接收和發送描述的大小通過宏ETH_RXBUFNB和ETH_TXBUFNB來定義,默認都為5。
我們知道以鏈接結構太網描述符的Buffer1Addr成員用來存放緩沖區地址,那么數據緩沖區在哪里?這個數據緩沖區也是定義為數組的,如下:
把他們聯系在一起的代碼,把描述符和緩沖區聯系起來,也就是下面的函數把描述符標構成鏈式結構。
在ethernetif.c的low_level_init函數中
解析如下
全局描述符指針,用來記錄當前使用的描述符
描述數據包的描述符(英文:用於保存最后一個接收的包描述符信息的結構。)
結構體
第一個表示數據包的第一個描述符,第二個表示數據包的最后一個描述符,第三個表示數據包描述符的個數。
最終的效果如下:
04、FIFO
從STM32網絡控制器框圖中可以看到兩個2KB的FIFO,一個發送FIFO,一個接收FIFO。
發送FIFO
提供兩種FIFO數據模式用於幀傳輸
-
閾值模式:當達到閾值后,盡快傳輸數據。
-
Store-and-Forward mode:FIFO中會存儲一個完整的幀結構。
STM32的發送FIFO采用Store-and-Forwardmode模式。
接收FIFO
接收FIFO采用Store-and-Forwardmode模式。
點擊查看本文所在的專輯,STM32F207網絡開發