由原理图中可知,SPI引脚由J4引出,还有一片Flash。
从芯片手册中,可以查到spi引脚分布如下:
spi的引脚复用不是在GPIO的寄存器中,而是在SPI的SPIPC0寄存器中进行配置。
引脚配置程序,各个宏定义与上面的寄存器是相对应的,不同的是CS引脚的个数,C6655最多只有两个CS引脚。程序中使用的是spiCfg.number_SPI_pins = 4;
- spiRegs->SPIPC0 = CSL_SPI_SPIPC0_SOMIFUN_MASK
- |CSL_SPI_SPIPC0_SIMOFUN_MASK|CSL_SPI_SPIPC0_CLKFUN_MASK;
- if(spiCfg->number_SPI_pins>3)
- spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN0_MASK;
- if(spiCfg->number_SPI_pins>4)
- spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN1_MASK;
- if(spiCfg->number_SPI_pins>5)
- spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN2_MASK;
- if(spiCfg->number_SPI_pins>6)
- spiRegs->SPIPC0 |= CSL_SPI_SPIPC0_SCS0FUN3_MASK;
复制代码
然而SPI最终是中实现数据的发送与接收的,这样的一个函数就是KeyStone_SPI_TxRx了。
- Uint32 KeyStone_SPI_TxRx(Uint8 * txBuf, Uint32 firstTxByte,
- Uint32 numTxByte, Uint8 * rxBuf, Uint32 firstRxByte, Uint32 numRxByte,
- SPI_Transfer_Param * transfer)
- {
- Int32 i;
- Int32 length;
- Uint32 txData, rxData;
- Uint32 byteOfWord, dataFormat, lastDataFormat;
- //spiRegs
- /*total transfer word length is the max of the lastRxWord and lastTxWord*/
- if((firstTxByte+numTxByte)>(firstRxByte+numRxByte))
- length= (firstTxByte+numTxByte);
- else
- length= (firstRxByte+numRxByte);
- /*------data format: higher 16 bit of SPIDAT1------*/
- KeyStone_SPIDAT1_format(transfer, &dataFormat, &lastDataFormat);
- byteOfWord= transfer->byteOfWord;
- if(length==byteOfWord)
- dataFormat= lastDataFormat;
- /*--------write the first word--------*/
- if((firstTxByte==0)&&(0
- {/*only TX valid data from the "firstTxByte"*/
- if(2==byteOfWord)
- {/*two bytes*/
- txData= *(Uint16 *)txBuf;
- txBuf+=2;
- }
- else
- {/*one byte*/
- txData= *txBuf++;
- }
- }
- else
- txData= 0;
- txData |= dataFormat;
- /* Wait for room in TX buffer */
- if(0==KeyStone_SPI_wait_flag(CSL_SPI_SPIFLG_TXINTFLG_MASK, CSL_SPI_SPIFLG_TXINTFLG_MASK))
- return 0;
- /* Send the word */
- spiRegs->SPIDAT1 = txData;
- /*--------write the word n+1 while read word n--------*/
- for( i=0; i
- {
- if((firstTxByte<=i+byteOfWord)&&(i+byteOfWord
- {/*only TX valid data from the "firstTxByte"*/
- if(2==byteOfWord)
- {/*two bytes*/
- txData= *(Uint16 *)txBuf;
- txBuf+=2;
- }
- else
- {/*one byte*/
- txData= *txBuf++;
- }
- }
- else
- txData= 0;
- if(i+byteOfWord==length-byteOfWord) /*the last word*/
- txData |= lastDataFormat;
- else
- txData |= dataFormat;
- /* Wait for room in TX buffer */
- if(0==KeyStone_SPI_wait_flag(CSL_SPI_SPIFLG_TXINTFLG_MASK, CSL_SPI_SPIFLG_TXINTFLG_MASK))
- return i+byteOfWord;
- /* Send the word */
- spiRegs->SPIDAT1 = txData;
- /* Wait for data in RX buffer */
- if(0==KeyStone_SPI_wait_flag(CSL_SPI_SPIFLG_RXINTFLG_MASK, CSL_SPI_SPIFLG_RXINTFLG_MASK))
- return i;
- /* Read the next word */
- rxData = spiRegs->SPIBUF&0xFFFF;
-
- if((firstRxByte<=i)&&(i
- {/*only RX valid data from the "firstRxByte"*/
- if(2==byteOfWord)
- {/*two bytes*/
- *(Uint16 *)rxBuf= rxData;
- rxBuf+=2;
- }
- else
- {/*one byte*/
- *rxBuf++= rxData;
- }
- }
- }
- /*--------read the last word--------*/
- /* Wait for data in RX buffer */
- if(0==KeyStone_SPI_wait_flag(CSL_SPI_SPIFLG_RXINTFLG_MASK, CSL_SPI_SPIFLG_RXINTFLG_MASK))
- return length-byteOfWord;
- /* Read the next word */
- rxData = spiRegs->SPIBUF&0xFFFF;
-
- if((firstRxByte<=length-byteOfWord)&&(length-byteOfWord
- {/*only RX valid data from the "firstRxByte"*/
- if(2==byteOfWord)
- {/*two bytes*/
- *(Uint16 *)rxBuf= rxData;
- rxBuf+=2;
- }
- else
- {/*one byte*/
- *rxBuf++= rxData;
- }
- }
-
- return length;
- }
复制代码
函数参数中的SPI_Transfer_Param* transfer最初传递的是EepromTransferParam这个值,它的各成员的值如下图所示,片选使用的是CS0,4线SPI模式,而CSHOLD可以参考手册中寄存器的说明:
之后,根据要发送或接收的数据个数来判断SPI是要接收还是要发送,根据SPI状态寄存器的标志来选择是 发送:spiRegs->SPIDAT1= txData; 接收:rxData =spiRegs->SPIBUF&0xFFFF;
以N25Q032A11ESE40F为例,先看一下N25Q032A11ESE40F支持的spi模式如下:
这对应于SPIFMTn寄存器的第17与第16位。
在SPI的初始化程序中的以下部分是对这个寄存器的配置,可以看到与N25Q032A11ESE40F的SPI模式是一样的。
通过芯片的读时序,要先发一个命令:
而对应于读取的命令是:
这与程序中的SPI_EEPROM_READ被定义为0x03:
- Uint32 SPI_EEPROM_read(Uint32 data_address,
- Uint32 address_width, Uint32 uiByteCount, Uint8 * ucBuffer)
- {
- Uint8 txBuf[8];
- Uint32 byteSuccess=0;
-
- txBuf[0]= SPI_EEPROM_READ; /*instruction*/
- SPI_EEPROM_fill_address(data_address, address_width, &txBuf[1]);
- /*read data*/
- byteSuccess= KeyStone_SPI_TxRx(txBuf, 0, address_width/8+1,
- ucBuffer, address_width/8+1, uiByteCount,
- &EepromTransferParam);
- if(byteSuccess
- byteSuccess= 0;
- else
- byteSuccess -= address_width/8+1;
- return byteSuccess;
- }
复制代码
以上函数,先发读取命令0x03,再按时序通过KeyStone_SPI_TxRx函数读取芯片发回的数据。 对于写入数据也是类似的,
|