Hi all,
我最近在写6670的SPI驱动。6670 SPI总线上挂了两片flash,一片是直接接到DSP上,另外一片通过CPLD接到DSP上。问题出现在后一个flash上:
我在初始化SPI时,将cs端的默认状态设置为没有数据传输时cs端为高电平。但是程序一跑完这条语句,cs就始终处于低电平状态,回不到高电平。由于向flash写指令
时,必须要cs回到高电平才能将指令写进去,所以现在没法控制flash的读写。请问这是怎么回事?
Thx
Nick
Michael Luo:
一般来说,cs片选信号是从高拉低表示选中slave device,一直到所有信息发送/接收完毕后再次拉高表示释放slave device。在配置好寄存器之后,enable SPI模块就可以让片选信号变化,并向slave device写指令和数据。没法控制flash的读写还有可能是时序等其它问题,不一定是cs的问题。下面是SPI初始化配置寄存器的代码参考:
/* SPI soft reset procedure. */
SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_IN_RESET;
spi_delay (2000);
SPI_SPIGCR0 = CSL_SPI_SPIGCR0_RESET_OUT_OF_RESET;
/* Set master mode, powered up but not activated */
SPI_SPIGCR1 = (CSL_SPI_SPIGCR1_MASTER_MASTER << CSL_SPI_SPIGCR1_MASTER_SHIFT) |
(CSL_SPI_SPIGCR1_CLKMOD_INTERNAL << CSL_SPI_SPIGCR1_CLKMOD_SHIFT);
/* Set functional pins by the value of cs. */
if (cs == 0) {
SPI_SPIPC0 = (CSL_SPI_SPIPC0_SCS0FUN0_SPI << CSL_SPI_SPIPC0_SCS0FUN0_SHIFT) |
(CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT) |
(CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT) |
(CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT);
} else if (cs == 1) {
SPI_SPIPC0 = (CSL_SPI_SPIPC0_SCS0FUN1_SPI << CSL_SPI_SPIPC0_SCS0FUN1_SHIFT) |
(CSL_SPI_SPIPC0_CLKFUN_SPI << CSL_SPI_SPIPC0_CLKFUN_SHIFT) |
(CSL_SPI_SPIPC0_SIMOFUN_SPI << CSL_SPI_SPIPC0_SIMOFUN_SHIFT) |
(CSL_SPI_SPIPC0_SOMIFUN_SPI << CSL_SPI_SPIPC0_SOMIFUN_SHIFT);
}
/* Setup format. Format should be the same except CHAR length. */
scalar = ((SPI_MODULE_CLK / freq) – 1 ) & 0xFF; //There's a calc bug here. Just set freq to 1000000.
if ( bit_sel == 0) {
SPI_SPIFMT0 = (8 << CSL_SPI_SPIFMT_CHARLEN_SHIFT) |
(scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT) |
(CSL_SPI_SPIFMT_PHASE_NO_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT) |
(CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
(CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
}else if ( bit_sel == 1) {
SPI_SPIFMT0 = (16 << CSL_SPI_SPIFMT_CHARLEN_SHIFT) |
(scalar << CSL_SPI_SPIFMT_PRESCALE_SHIFT) |
(CSL_SPI_SPIFMT_PHASE_NO_DELAY << CSL_SPI_SPIFMT_PHASE_SHIFT) |
(CSL_SPI_SPIFMT_POLARITY_LOW << CSL_SPI_SPIFMT_POLARITY_SHIFT) |
(CSL_SPI_SPIFMT_SHIFTDIR_MSB << CSL_SPI_SPIFMT_SHIFTDIR_SHIFT);
}
/* hold cs active at end of transfer until explicitly de-asserted */
data1_reg_val = (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
(0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
SPI_SPIDAT1 = (CSL_SPI_SPIDAT1_CSHOLD_ENABLE << CSL_SPI_SPIDAT1_CSHOLD_SHIFT) |
(0x02 << CSL_SPI_SPIDAT1_CSNR_SHIFT);
/* including a minor delay. No science here. Should be good even with no delay. */
SPI_SPIDELAY = (8 << CSL_SPI_SPIDELAY_C2TDELAY_SHIFT) |
(8 << CSL_SPI_SPIDELAY_T2CDELAY_SHIFT);
/* default chip select register */
SPI_SPIDEF = CSL_SPI_SPIDEF_RESETVAL;
/* no interrupts */
SPI_SPIINT0 = CSL_SPI_SPIINT0_RESETVAL;
SPI_SPILVL = CSL_SPI_SPILVL_RESETVAL;
/* enable SPI */
SPI_SPIGCR1 |= ( CSL_SPI_SPIGCR1_ENABLE_ENABLE << CSL_SPI_SPIGCR1_ENABLE_SHIFT );