AM335X平台下的mcspi源代碼詳解---中斷模式下的初始化、收發數據


AM335X簡介:

AM335X是TI(德州儀器)基於 ARM Cortex-A8內核的AM335X微處理器在圖像、圖形處理、外設和諸如 EtherCAT 和 PROFIBUS 的工業接口選項方面進行了增強。AM335X的優點有如下幾個:
第一:該器件是最便宜的Cortex A8 處理芯片,這個對中國市場至關重要 ,甚至是決定性的因素。
第二:TI 史上公開資料最全的一個芯片,包含starterware裸機系統,android2.3-4.1系統,linux3.2系統。
第三:產品定位最清晰的一個,工業控制MCU
第四:唯一一個集成2個MAC的 MCU.
第五:目前唯一支持Androd 4.0, 而且同時支持3個操作系統 Linux,Android,WinCE.另外支持第三方實時操作系統如QNX、VxWorks等系統

以下源碼來源於TI提供的starterware工程中的spiflash例子。

內容通過翻譯總結,加上自己的理解試驗而成。單片機挺好玩的,比起信息系統開發,工作量並不大。

mcspi模塊:

mcspi即SPI接口的flash,支持從芯片選擇引腳最大頻率為48MHzmcspi可以配置,生成DMA事件到EDMA控制器,用於傳輸數據mcspi設備抽象層提供一些

接口API,來配置和使用mcspi模塊進行數據傳輸。傳輸數據可以用中斷模式或DMA模式。今天學習Mcspi中斷模式的源碼看看如何使用

一、初始化配置:

1,mcspi外圍時鍾使能,調用McSPI0ModuleClkConfig().

2,引腳復用spi_clkspi_d0spi_d1,調用mcspipinmuxsetup()

3,引腳復用CS,調用mcspi0cspinmuxsetup()

4,MCSPI本地復位,調用McSPIReset().

5,mcspi可以配置在4針模式(CLKD0D1CS),即CS使能,調用mcspicsenable()

6,操作主模式啟用,調用mcspimastermodeenable()

7,配置單/多通道模式發送/接收模式,設置 IS, DPE0, DPE1dpe0dpe1。調mcspimastermodeconfig() APIdpe0dpe1將配置方向

spid0spid1引腳為輸入或輸出請參閱驗證SPI數據引腳連接並做相應設置。這個函數是主模式下必須要配置的。

8,spi總線時鍾配置,調用mcspiclkconfig()。粒度可設定1個時鍾周期或2 ^ n時鍾周期,時鍾極性也在這里配置

9,mcspi字長,用mcspiwordlengthset()

10,極性spien芯片選擇),mcspicspolarityconfig()

11,啟用/禁用transmitter and receiver FIFOs,mcspitxfifoconfig()mcspirxfifoconfig()

 

 1 int main(void)
 2 {
 3     volatile unsigned int count = 0x0FFFu;
 4     unsigned int retVal = FALSE;
 5     unsigned char choice = 0;
 6 
 7     /* Enable the clocks for McSPI0 module.*/
 8     McSPI0ModuleClkConfig();
 9 
10     /* Perform Pin-Muxing for SPI0 Instance */
11     McSPIPinMuxSetup(0);
12 
13     /* Perform Pin-Muxing for CS0 of SPI0 Instance */
14     McSPI0CSPinMuxSetup(chNum);
15 
16     /* Initialize the UART utility functions */
17     UARTStdioInit();
18 
19     UARTPuts("Here the McSPI controller on the SoC communicates with", -1);
20     UARTPuts(" the SPI Flash.\r\n\r\n", -1);
21 
22     /* Enable IRQ in CPSR.*/
23     IntMasterIRQEnable();
24 
25     /* Map McSPI Interrupts to AINTC */
26     McSPI0AintcConfigure();
27                     
28     /* Do the necessary set up configurations for McSPI.*/
29     McSPISetUp();
30 
31     /* Pass the write enable command to flash.*/
32     WriteEnable();
33 
34     /* Wait until write enable command is successfully written to flash.*/
35     while(FALSE == retVal)
36     {
37         retVal = IsWriteSuccess();
38     }
39 
40     retVal = FALSE;
41 
42     UARTPuts("Do you want to erase a sector of the flash before ", -1);
43     UARTPuts("writing to it ?.", -1);
44     UARTPuts("\r\nInput y(Y)/n(N) to proceed.\r\n", -1);
45 
46     choice = UARTGetc();
47     UARTPutc(choice);
48 
49     if(('Y' == choice) || ('y' == choice))
50     {
51         /* Erase a sector of flash.*/
52         SectorErase();
53     }
54 
55     /* Pass the write enable command to flash.*/
56     WriteEnable();
57 
58     /* Wait until write enable command is successfully written to flash.*/
59     while(FALSE == retVal)
60     {
61         retVal = IsWriteSuccess();
62     }
63 
64     /* Write data of 1 page size to flash.*/
65     WriteToFlash();
66 
67     while(count--);
68     count = 0x0FFFu;
69 
70     /* Read data of 1 page size from flash.*/
71     ReadFromFlash();
72 
73     while(count--);
74 
75     /* Verify the data written to and read from flash are same or not.*/
76     VerifyData();
77 
78     while(1);
79 }
View Code
 1 /*
 2 ** This function will call the necessary McSPI APIs which will configure the 
 3 ** McSPI controller. 
 4 */
 5 static void McSPISetUp(void)
 6 {
 7 
 8     /* Reset the McSPI instance.*/
 9     McSPIReset(SOC_SPI_0_REGS);
10 
11     /* Enable chip select pin.*/
12     McSPICSEnable(SOC_SPI_0_REGS);
13 
14     /* Enable master mode of operation.*/
15     McSPIMasterModeEnable(SOC_SPI_0_REGS);
16 
17     /* Perform the necessary configuration for master mode.*/
18     McSPIMasterModeConfig(SOC_SPI_0_REGS, MCSPI_SINGLE_CH, 
19                           MCSPI_TX_RX_MODE, MCSPI_DATA_LINE_COMM_MODE_1,
20                           chNum);
21 
22     /* Configure the McSPI bus clock depending on clock mode. */
23     McSPIClkConfig(SOC_SPI_0_REGS, MCSPI_IN_CLK, MCSPI_OUT_FREQ, chNum, 
24                    MCSPI_CLK_MODE_0);
25 
26     /* Configure the word length.*/
27     McSPIWordLengthSet(SOC_SPI_0_REGS, MCSPI_WORD_LENGTH(8), chNum);
28 
29     /* Set polarity of SPIEN to low.*/
30     McSPICSPolarityConfig(SOC_SPI_0_REGS, MCSPI_CS_POL_LOW, chNum);
31 
32     /* Enable the transmitter FIFO of McSPI peripheral.*/
33     McSPITxFIFOConfig(SOC_SPI_0_REGS, MCSPI_TX_FIFO_ENABLE, chNum);
34 
35     /* Enable the receiver FIFO of McSPI peripheral.*/
36     McSPIRxFIFOConfig(SOC_SPI_0_REGS, MCSPI_RX_FIFO_ENABLE, chNum);
37 }
McSPISetUp

 

 

二、傳輸數據:

初始化完畢后,可以傳輸數據了,看看發送數據的實現

1,spien強制拉低(即處於活動狀態),mcspicsassert()

2.中斷使能,調用mcspiintenable()

3,mcspi通道使能,mcspichannelenable(),mcspi一調用這個函數就會產生中斷,取決於設置

4,while(flag);//前面產生了中斷,等待中斷處理。中斷的處理見McSPIIsr中斷處理代碼塊

5,在第三塊中斷處理結束后,返回flag=0,然后執行前面相反的工作,恢復為發送數據時的狀態。即SPIEN拉高(禁止狀態)mcspicsdeassert(),mcspi通道禁用mcspichanneldisable()

 1 /*
 2 ** This function will activate/deactivate CS line and also enable Tx and Rx
 3 ** interrupts of McSPI peripheral.
 4 */
 5 static void McSPITransfer(void)
 6 {
 7     p_tx = txBuffer;
 8     p_rx = rxBuffer;
 9 
10     /* SPIEN line is forced to low state.*/
11     McSPICSAssert(SOC_SPI_0_REGS, chNum);
12 
13     /* Enable the Tx/Rx interrupts of McSPI.*/
14     McSPIIntEnable(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum) | 
15                    MCSPI_INT_RX_FULL(chNum));
16 
17     /* Enable the McSPI channel for communication.*/
18     McSPIChannelEnable(SOC_SPI_0_REGS, chNum);
19 
20     /* Wait until control returns back from McSPI ISR.*/
21     while(flag);
22 
23     flag = 1;
24 
25     /* Force SPIEN line to the inactive state.*/
26     McSPICSDeAssert(SOC_SPI_0_REGS, chNum);
27 
28     /* Disable the McSPI channel.*/
29     McSPIChannelDisable(SOC_SPI_0_REGS, chNum);
30 }
McSPITransfer

 

三、中斷處理:

1,獲取中斷狀態,mcspiintstatusget()

2,處理完畢自然要清除,清除中斷用mcspiintstatusclear()

3,mcspi傳輸數據,mcspitransmitdata(),讀取或接收數據,mcspireceivedata()

4,傳輸完畢,用mcspiintdisable()發送處理完畢的標識。在第二塊傳輸數據那,while(flag);flag=0,跳出了循環,繼續執行。

 1 /*
 2 ** McSPI Interrupt Service Routine. This function will clear the status of the
 3 ** Tx/Rx interrupts when generated. Will write the Tx data on transmit data
 4 ** register and also will put the received data from receive data register to
 5 ** a location in memory.
 6 */
 7 static void McSPIIsr(void)
 8 {
 9     unsigned int intCode = 0;
10 
11     intCode = McSPIIntStatusGet(SOC_SPI_0_REGS);
12 
13     while(intCode)
14     {
15         if(MCSPI_INT_TX_EMPTY(chNum) == (intCode & MCSPI_INT_TX_EMPTY(chNum)))
16         {
17             McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
18 
19             length--;
20 
21             McSPITransmitData(SOC_SPI_0_REGS,(unsigned int)(*p_tx++), chNum);
22 
23             if(!length)
24             {
25                 McSPIIntDisable(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
26 
27                 McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_TX_EMPTY(chNum));
28             }
29         }
30 
31         if(MCSPI_INT_RX_FULL(chNum) == (intCode & MCSPI_INT_RX_FULL(chNum)))
32         {
33             McSPIIntStatusClear(SOC_SPI_0_REGS, MCSPI_INT_RX_FULL(chNum));
34 
35             *p_rx++ = (unsigned char) McSPIReceiveData(SOC_SPI_0_REGS, chNum);
36 
37             if(!(length))
38             {
39                 McSPIIntDisable(SOC_SPI_0_REGS, MCSPI_INT_RX_FULL(chNum));
40 
41                 flag = 0;
42             }
43         }
44 
45         intCode = McSPIIntStatusGet(SOC_SPI_0_REGS);
46     }
47 }
48 /********************************* End Of File ******************************/
McSPIIsr中斷處理

 

 

四、寫入Flash:

 

1,有了前面的准備,就很簡單了,直接調用McSPITransfer(),要按頁寫入,測試程序flash的頁大小是256字節。稍微包裝一下即可,這里只是一個例子,地址是寫死的

24位地址(第234字節,即高中低3個8位,最大地址2^24=16M).第一個字節是命令,寫入flash是FLASH_PAGE_PROGRAM,而讀取是FLASH_DATA_READ。

 1 static void WriteToFlash(void)
 2 {
 3     unsigned int index = 0;
 4 
 5     txBuffer[0] = FLASH_PAGE_PROGRAM;
 6     txBuffer[1] = FLASH_SECTOR_ADD_HIGH;
 7     txBuffer[2] = FLASH_SECTOR_ADD_MID;
 8     txBuffer[3] = FLASH_SECTOR_ADD_LOW;
 9 
10     for(index = 0; index < 256; index++)
11     {
12         txBuffer[index + 4] = (unsigned char) index;
13         vrfyData[index] = (unsigned char) index;
14     }
15 
16     length = 260;
17     
18     McSPITransfer();
19 }
WriteToFlash

四、從Flash讀取:

 1,和寫入類似,前四個字節,為命令+地址,FLASH_DATA_READ,地址高8位,地址中8位,地址低8位

 1 /*
 2 ** This function will read data of 1 page size from a specific sector of flash.
 3 */
 4 static void ReadFromFlash(void)
 5 {
 6     unsigned int index = 0;
 7 
 8     txBuffer[0] = FLASH_DATA_READ;
 9     txBuffer[1] = FLASH_SECTOR_ADD_HIGH;
10     txBuffer[2] = FLASH_SECTOR_ADD_MID;
11     txBuffer[3] = FLASH_SECTOR_ADD_LOW;
12 
13     for(index = 4; index < 260; index++)
14     {
15         txBuffer[index] = 0;
16     }    
17 
18     length = 260;
19 
20     McSPITransfer();
21 }
ReadFromFlash

------------------------------------------------------------------------------------------------------------------------

 至此,例子分析完畢,用到實際項目中,需要適應改寫一下。我的AM335X測試平台,要實現如下接口:

B32 D_DF_Read( U8* p, U32 addr, U32 Size ),把addr處Size大小的內容讀到* p中。因為是最底層的驅動,按頁面讀取。SIZE固定為256byte(這里是8位byte,用字節有歧義),上層調用者傳入指針 p和地址即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM