Hello,
I need to setup SPI slave with EDMA on the C6748 processor, SYS/BIOS bios_6_34_02_18, EDMA driver edma3_lld_02_11_04_01.
I have special synchronization GPIO signal coming approximately 100 microsec before CS, so I can prepare communication (restart SPI and reinit EDMA parameters) in it's interrupt (so don't use any EDMA linking, all EDMA parameters are reinited in that signal interrupt). SPI1 used.
Code:
1) init at startup:
Just request EDMA channels...
{...
edmaChanSpiRecv = E3M_EVT_SPI1_RX; // 18
unsigned int recv_tcc = edmaChanSpiRecv;
EDMA3_DRV_requestChannel(gEdma3Manager.getDrvHandle(),
&edmaChanSpiRecv, &recv_tcc, (EDMA3_RM_EventQueue)0, &g_edmaSpiRecv, NULL);
edmaChanSpiSend = E3M_EVT_SPI1_TX; // 19
unsigned int send_tcc = edmaChanSpiSend;
EDMA3_DRV_requestChannel(gEdma3Manager.getDrvHandle(),
&edmaChanSpiSend, &send_tcc, (EDMA3_RM_EventQueue)0, &g_edmaSpiSend, NULL);
...}
2) sync signal (HW interrupt):
Just reset SPI and re-init EDMA channels...
{
SPI_c674x_Config();
EDMA3_DRV_clearErrorBits(gEdma3Manager.getDrvHandle(), edmaChanSpiRecv);
EDMA3_DRV_setPaRAM(gEdma3Manager.getDrvHandle(), edmaChanSpiRecv, &edmaParamsetSpiRecv);
EDMA3_DRV_enableTransfer(gEdma3Manager.getDrvHandle(), edmaChanSpiRecv, EDMA3_DRV_TRIG_MODE_EVENT);
edma_result = EDMA3_DRV_clearErrorBits(gEdma3Manager.getDrvHandle(), edmaChanSpiSend);
edma_result = EDMA3_DRV_setPaRAM(gEdma3Manager.getDrvHandle(), edmaChanSpiSend, &edmaParamsetSpiSend);
edma_result = EDMA3_DRV_enableTransfer(gEdma3Manager.getDrvHandle(), edmaChanSpiSend, EDMA3_DRV_TRIG_MODE_EVENT);
//edma_result = EDMA3_DRV_enableTransfer(gEdma3Manager.getDrvHandle(), edmaChanSpiSend, EDMA3_DRV_TRIG_MODE_MANUAL);
SPI_c674x_EdmaEnable();
}
3) SPI_c674x_Config() function
Reset and config SPI, data must be written directly to SPIDAT0 by EDMA, but DMAREQEN is not enabled here.
{
/* spi configuration register overlay */
CSL_SpiRegsOvly spiRegs = (CSL_SpiRegsOvly)CSL_SPI_1_REGS;
/* system configuration registers overlay */
CSL_SyscfgRegsOvly sysRegs = (CSL_SyscfgRegsOvly)(CSL_SYSCFG_0_REGS);
/* power and sleep Controller register overlay */
CSL_PscRegsOvly psc1Regs = (CSL_PscRegsOvly)(CSL_PSC_1_REGS);
volatile U32 pscTimeoutCount = 10240u;
/* enable the pinmux for the SPI1 pins (4-pin mode), SPI1_SIMO, SPI1_SOMI and SPI1_CLK, NSPI1_SCS0 */
sysRegs->PINMUX5 |= CSL_FMKT( SYSCFG_PINMUX5_PINMUX5_23_20, SPI1_SIMO0 )
| CSL_FMKT( SYSCFG_PINMUX5_PINMUX5_19_16, SPI1_SOMI0 )
| CSL_FMKT( SYSCFG_PINMUX5_PINMUX5_11_8, SPI1_CLK )
| CSL_FMKT( SYSCFG_PINMUX5_PINMUX5_7_4, NSPI1_SCS0 );
/* deassert SPI1 local PSC reset and set NEXT state to ENABLE */
psc1Regs->MDCTL[CSL_PSC_SPI1] = CSL_FMKT( PSC_MDCTL_NEXT, ENABLE )
| CSL_FMKT( PSC_MDCTL_LRST, DEASSERT );
/* move SPI1 PSC to Next state */
CSL_FINST( psc1Regs->PTCMD, PSC_PTCMD_GO0, SET );
/* wait for transition */
while( (CSL_FEXT( psc1Regs->MDSTAT[CSL_PSC_SPI1], PSC_MDSTAT_STATE ) != CSL_PSC_MDSTAT_STATE_ENABLE )
&& (pscTimeoutCount > 0) )
{
pscTimeoutCount--;
}
/* check if PSC state transition timed out */
if( 0 == pscTimeoutCount )
{
System_printf ("SPI1 PSC transition to ON state timed out\n");
}
/* reset the SPI */
spiRegs->SPIGCR0 = CSL_FMKT( SPI_SPIGCR0_RESET, IN_RESET );
/* bring out of reset state */
spiRegs->SPIGCR0 = CSL_FMKT( SPI_SPIGCR0_RESET, OUT_OF_RESET );
/* enable the CLKMOD and SLAVE bits in the SPI global control register */
spiRegs->SPIGCR1 = CSL_FMKT( SPI_SPIGCR1_MASTER, SLAVE )
| CSL_FMKT( SPI_SPIGCR1_CLKMOD, EXTERNAL );
/* enable the pins so that they are used for the SPI interface (Multiplex) */
spiRegs->SPIPC0 = CSL_FMKT( SPI_SPIPC0_SCS0FUN0, SPI )
| CSL_FMKT( SPI_SPIPC0_CLKFUN, SPI )
| CSL_FMKT( SPI_SPIPC0_SOMIFUN, SPI )
| CSL_FMKT( SPI_SPIPC0_SIMOFUN, SPI );
/* configure the data format in SPIFMTn */
spiRegs->SPIFMT[0] = CSL_FMK( SPI_SPIFMT_CHARLEN, SPI_NUM_OF_TXBITS )
| CSL_FMK( SPI_SPIFMT_PRESCALE, SPI_PRESCALE );
/* set the preconfigure data format as 0 which is already set above */
spiRegs->SPIDAT1 = CSL_FMKT( SPI_SPIDAT1_DFSEL, FORMAT0 );
spiRegs->SPIGCR1 |= CSL_FMKT( SPI_SPIGCR1_ENABLE, ENABLE );
}
4) SPI_c674x_EdmaEnable() function
Just enable DMAREQEN...
{
/* spi configuration register overlay */
CSL_SpiRegsOvly spiRegs = (CSL_SpiRegsOvly)CSL_SPI_1_REGS;
/* enable interrupt DMA */
spiRegs->SPIINT0 = CSL_FMKT( SPI_SPIINT0_DMAREQEN, ENABLE );
}
The problem is: sync signal (HW interrupt) works only once in free-running, and under breakpoint inside works as needed (if permanently push Run button). If make SW interrupt insted of HW, and sync signal (HW interrupt) will just post that SW interrupt - it will work once in both free-running and breakpoint modes. I defined that problem is calling of EDMA3_DRV_enableTransfer() function: if comment it - interrupt works (but sure EDMA doesn't work). Debugging that function shows that only EDMA registers are set - no any other job like logging... Registers checked for SPI, EDMA and DSP - seem to be OK.
Also, it seems that EDMA for sending (binded to E3M_EVT_SPI1_TX; // 19 event) doesn't work until something is written to SPI TX buffer manually first, or EDMA is triggered manually once. Can this be true?
Can anybody help me with these questions? Thank you for any ideas.