分享

AM335X平台下的mcspi源代码详解

 XeonGate 2015-09-03

http://www.cnblogs.com/zkp2010/archive/2013/05/30/3107437.html

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()

按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 

三、中断处理:

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。

WriteToFlash

四、从Flash读取:

 1,和写入类似,前四个字节,为命令+地址,FLASH_DATA_READ,地址高8位,地址中8位,地址低8位

ReadFromFlash

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

 至此,例子分析完毕,用到实际项目中,需要适应改写一下。我的AM335X测试平台,要实现如下接口:

B32 D_DF_Read( U8* p, U32 addr, U32 Size ),把addr处Size大小的内容读到* p中。因为是最底层的驱动,按页面读取。SIZE固定为256byte(这里是8位byte,用字节有歧义),上层调用者传入指针 p和地址即可。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多