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和地址即可。

你可能感兴趣的:(初始化)