http://www.cnblogs.com/zkp2010/archive/2013/05/30/3107437.html AM335X简介: AM335X是TI(德州仪器)基于 ARM Cortex-A8内核的AM335X微处理器在图像、图形处理、外设和诸如 EtherCAT 和 PROFIBUS 的工业接口选项方面进行了增强。AM335X的优点有如下几个: 以下源码来源于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和地址即可。 |
|