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,支持從芯片選擇引腳,最大頻率為48MHz。mcspi可以配置,生成DMA事件到EDMA控制器,用於傳輸數據。mcspi設備抽象層提供一些
接口API,來配置和使用mcspi模塊進行數據傳輸。傳輸數據可以用中斷模式或DMA模式。今天學習Mcspi中斷模式的源碼看看如何使用
一、初始化配置:
1,mcspi外圍時鍾使能,調用McSPI0ModuleClkConfig().
2,引腳復用為spi_clk,spi_d0,spi_d1,調用mcspipinmuxsetup()
3,引腳復用CS,調用mcspi0cspinmuxsetup()
4,MCSPI本地復位,調用McSPIReset().
5,mcspi可以配置在4針模式(CLK,D0,D1,CS),即CS使能,調用mcspicsenable()
6,操作主模式啟用,調用mcspimastermodeenable()
7,配置單/多通道模式,發送/接收模式,設置 IS, DPE0, DPE1dpe0,dpe1。調用mcspimastermodeconfig() API。dpe0和dpe1將配置方向
spid0和spid1引腳為輸入或輸出。請參閱圖驗證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 }

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 }
二、傳輸數據:
初始化完畢后,可以傳輸數據了,看看發送數據的實現
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 }
三、中斷處理:
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 ******************************/
四、寫入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 }
四、從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 }
------------------------------------------------------------------------------------------------------------------------
至此,例子分析完畢,用到實際項目中,需要適應改寫一下。我的AM335X測試平台,要實現如下接口:
B32 D_DF_Read( U8* p, U32 addr, U32 Size ),把addr處Size大小的內容讀到* p中。因為是最底層的驅動,按頁面讀取。SIZE固定為256byte(這里是8位byte,用字節有歧義),上層調用者傳入指針 p和地址即可。