This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EDMA problem servicing SPI

Other Parts Discussed in Thread: OMAP-L138

hello Engineers

I am working on Omap-l138 experimental kit the DSP side (so its equivalent to C6748, I geuss). I am trying to get the EDMA to handle the transmitted data through SPI port.

the data I am sending is a 1D array. I set up the PARAM fields (PARAM 15) and (PARAM 31) for reloading purpose. SPI port configuration is all ok since it outputs data when using the bsl fxn (spi_xfer), but when commenting the fxn to let the DMA handle the transfer nothing comes out neither the clk nor data bits,

here is the code I used and I hope you help me identify the problem

void main (void)
{
SPI_init(SPI0,&spi0_config);
setup_EDMA();
SETBIT(SPI0->SPIINT,1 << 16);//spi EDMA service enable

while(1) {
// SPI_xfer(SPI0,pingSrcBuffer_2,NULL,2400, SPI_HOLD_CLR);
}
}
//-----------------------------
static void setup_EDMA (void)
{
// Clear Event Registers
edmaInit();
// Enable Channel 15 to DSP (Region 1)
EDMA3_0_CC0->DRA[CSL_EDMA3_REGION_1].DRAE|=CSL_EDMA3CC_DRAE_E15_MASK | CSL_EDMA3CC_DRAE_E31_MASK; //SPI0 xmt event

// Initialize PaRAM Transfer Context for Events 10 - 11
init_PaRAM_event15();
init_PaRAM_event31();
// init_PaRAM_event11();

// Enable Channel 15 Event Register and Assign to Queue 0
EdmaEnableChannel(EDMA_chan15,EDMAQNUM_0);
}/* setup_EDMA */
//--------------------------
void edmaInit()
{
edmaCcRegs->ECR = 0xffffffff; // clear events 0 -> 31
edmaCcRegs->EECR = 0xffffffff;
edmaCcRegs->SECR = 0xffffffff; // clear secondary events 0 -> 31
edmaCcRegs->IECR = 0xffffffff; // disable all interrupts
edmaCcRegs->ICR = 0xffffffff; // clear all pending interrupts
}
//----------------------------------

void init_PaRAM_event15 (void)
{
// Reset EDMA PaRAM OPT Register
EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT = 0x0;

// Config PaRAM OPT (disable chaining, AB_sync)
EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT =CSL_EDMA3CC_OPT_DAM_MASK | 1<< 12;

// Initialize EDMA Event Src and Dst Addresses
EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC = (uint32_t)&pingSrcBuffer_2;//dds_txbuf
EDMA3_0_CC0->PARAMSET[EDMA_chan15].DST = (uint32_t)&SPI0->SPIDAT0;//spi0 xmt reg.

// Set EDMA Event PaRAM A,B,C CNT
EDMA3_0_CC0->PARAMSET[EDMA_chan15].A_B_CNT = 2400 << Bcnt_shift | 1;

EDMA3_0_CC0->PARAMSET[EDMA_chan15].CCNT = 1;

// Set EDMA Event PaRAM SRC/DST BIDX
EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX = 0 << 16 | 1;

// Set EDMA Event PaRAM SRC/DST CIDX
EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_CIDX = 0x0;

// Set EDMA Event PaRAM LINK and BCNTRLD
EDMA3_0_CC0->PARAMSET[EDMA_chan15].LINK_BCNTRLD = 15 <<16 |(0x43E0) ;//Bcnt=15 bytes

}/* init_PaRAM_event15 */

void init_PaRAM_event31(void)
{
// Reset EDMA PaRAM OPT Register
EDMA3_0_CC0->PARAMSET[EDMA_chan31].OPT = 0x0;

// Config PaRAM OPT (disable chaining, A_sync)
EDMA3_0_CC0->PARAMSET[EDMA_chan31].OPT =CSL_EDMA3CC_OPT_DAM_MASK | 1<< 12;

// Initialize EDMA Event Src and Dst Addresses
EDMA3_0_CC0->PARAMSET[EDMA_chan31].SRC = (uint32_t)&pingSrcBuffer_2;//dds_txbuf
EDMA3_0_CC0->PARAMSET[EDMA_chan31].DST = (uint32_t)&SPI0->SPIDAT0;//spi0 xmt reg.
// Set EDMA Event PaRAM A,B,C CNT
EDMA3_0_CC0->PARAMSET[EDMA_chan31].A_B_CNT = 2400 << Bcnt_shift | 1;

EDMA3_0_CC0->PARAMSET[EDMA_chan31].CCNT = dds_Ccnt;

// Set EDMA Event PaRAM SRC/DST BIDX
EDMA3_0_CC0->PARAMSET[EDMA_chan31].SRC_DST_BIDX = 0 << 15 | 1;

// Set EDMA Event PaRAM SRC/DST CIDX
EDMA3_0_CC0->PARAMSET[EDMA_chan31].SRC_DST_CIDX = 0x0;

// Set EDMA Event PaRAM LINK and BCNTRLD
EDMA3_0_CC0->PARAMSET[EDMA_chan31].LINK_BCNTRLD = 15 <<16 |(0x4E10) ;//Bcnt=15 bytes
}/* init_PaRAM_event31 */

thanks....

  • Mohammed,

    It would be easier to read your code if you use the example CSL programming methods in the examples that come with the CSL. Since you use a constant with CSL in the name, I assume you have the CSL available.

    Do not use that constant, though. CSL_EDMA3CC_OPT_DAM_MASK is not intended to be used as a setting value, and the value you apply is invalid. Do not set the DAM or SAM bits. Check the datasheet for any permitted situation for the Constant Addressing mode, if any. This is not one of them.

    Your BCNTRLD value does not make sense. Why is it not 2400?

    Your LINK fields should be the same value. If they were calculated symbolically I could more quickly know which one is right. How did you come up with these two addresses?

    Check if the SPI peripheral's data port requires data accesses to be 32-bit operations. This is true on some of our communication peripherals on some devices, so it may be true here. This would be mentioned in the datasheet or in the SPI User Guide.

    Follow the initialization sequence written in the SPI User Guide in the Initialization section.

    Regards,
    RandyP

  • Randyp,

    thanks for your reply,

    RandyP said:
    I assume you have the CSL available.
    ,I do have the CSL but I intended not to use it as it was supposed to, so I extracted the values (masks) and used them directly as you can see. Actually I modified one of the examples provided with CSL.

    since the Destination is the SPI data transmit register I used "CSL_EDMA3CC_OPT_DAM_MASK"  to set it to that value; referring to datasheet (On the C674x/OMAP-L1x processors, no peripherals, memory, or memory controller support constant addressing mode), so I guess it was a mistake I made here.

    BCNTRLD= 2400, its the length of my transmitted array!!!

    the link address, as I mentioned I am using PARAM (31) for reloading

    SPI initialization is done through the BSL Fxn "spi_init(spi0, spi_param) .

    one thing I forgot to mention earlier; the event appears to be enabled in the EER, but never latched in the ER, instead I find that event (14) which is (SPI) RCV) is latched though am not using it.


  • Mohammed,

    Any repetition is done respectfully. My words may be written poorly but my intentions are sincere. I will let others help you if I am not successful.

    Your BCNTRLD value is not 2400. It should be 2400, although it does not get used when CCNT=1.

    Your LINK fields should be the same value; they are not the same value, so at least one is wrong. 0x4E10 must be wrong because it is not a multiple of 0x20.

    Follow the initialization sequence written in the SPI User Guide in the Initialization section. You may have to modify the BSL function for your new use.

    The initialization sequence is the most likely cause of your primary problem. The other items listed above are secondary problems that have not shown up, yet.

    Regards,
    RandyP

  • RandyP,

    you were right the reload field value was wrong,

    I made some modifications to my code, luckily data is coming out form the port but only once per run, the PARAM values(SRC and DST) alter each time and I don't know why. it results that both PARAMs have the same value which are not my SRC and DST values

    here is the modified code and I hope you can help me this time

    void init_PaRAM_event15 (void)
    {
    // Reset EDMA PaRAM OPT Register
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT = 0x0;
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT |= 0x00101000; //TCC=1, TCINTEN=1

    // Initialize EDMA Event Src and Dst Addresses
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC = (uint32_t)&pingSrcBuffer_2;

    EDMA3_0_CC0->PARAMSET[EDMA_chan15].DST = (uint32_t)&SPI0->SPIDAT1;//spi0 xmt reg.


    // Set EDMA Event PaRAM A,B,C CNT
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].A_B_CNT = 2400 << Bcnt_shift | 1; //ACNT=1,Bcnt=2400

    EDMA3_0_CC0->PARAMSET[EDMA_chan15].CCNT = 1;

    // Set EDMA Event PaRAM SRC/DST BIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =0;
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =1;

    // Set EDMA Event PaRAM SRC/DST CIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_CIDX = 0x0;

    // Set EDMA Event PaRAM LINK and BCNTRLD
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].LINK_BCNTRLD = 0x096003E0; //Bcnt=2400 bytes, Link->param 31


    }/* init_PaRAM_event15 */

    void init_PaRAM_event31(void)
    {
    // Reset EDMA PaRAM OPT Register
    EDMA3_0_CC0->PARAMSET[31].OPT = 0x0;
    EDMA3_0_CC0->PARAMSET[31].OPT = 0x00101000; //TCC=1, TCINTEN=1

    // Initialize EDMA Event Src and Dst Addresses
    EDMA3_0_CC0->PARAMSET[31].SRC = (uint32_t)&pingSrcBuffer_2;
    EDMA3_0_CC0->PARAMSET[31].DST = (uint32_t)&SPI0->SPIDAT1; //spi0 xmt reg.
    // Set EDMA Event PaRAM A,B,C CNT
    EDMA3_0_CC0->PARAMSET[31].A_B_CNT = 2400 << Bcnt_shift | 1; //ACNT=1,Bcnt=2400

    EDMA3_0_CC0->PARAMSET[31].CCNT = 1;

    // Set EDMA Event PaRAM SRC/DST BIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =0;
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =0x1; //SRC_BIDX=1,DST_BIDX=0

    // Set EDMA Event PaRAM SRC/DST CIDX
    EDMA3_0_CC0->PARAMSET[31].SRC_DST_CIDX = 0x0;

    // Set EDMA Event PaRAM LINK and BCNTRLD
    EDMA3_0_CC0->PARAMSET[31].LINK_BCNTRLD = 0x096003E0; //Bcnt=2400 bytes, Link->param 31
    }
    /* init_PaRAM_event31 */

    thanks

  • Mohammed,

    mohammed alzain said:

    I made some modifications to my code, luckily data is coming out form the port but only once per run, the PARAM values(SRC and DST) alter each time and I don't know why. it results that both PARAMs have the same value which are not my SRC and DST values

    I do not know what this means. You will have to give more detail.

    Your two functions appear to do the exact same thing except to two different PARAMSETs. That is the right thing to do, so you might simplify this by using a single function with an argument for the PARAMSET number.

    Why do you write 0 to OPT and BIDX before writing a new value to them? The optimizer may not remove this if these are declared volatile. You should remove those writes of 0 if they do not provide any benefit.

    Have you changed the SPI initialization from the original example to the sequence in the User's Guide?

    Regards,
    RandyP

  • Mr. RandyP, 

    Finally its working!!

    it seemed that I was missing something, but i didn't know what it was; so I went on configuring the EDMA from the beginning.

    I did as you said about the SPI initialization, though I thought of the BSL Fxn as "taken for granted" at first. I followed the initialization sequence provided in "Omap-l138 technical Reference manual", first configuring the spi and enabling it, then setting EDMA transfer settings and finally setting the "SPIINT0.DMAREQEN" to 1.

    about writing "0", I think it does no good!!!

    I changed the reloading PARAM from (31) to (16) and I don't know what is the difference, but its working perfectly and the data is being shifted out. 

    here is the working version of the code:

    static void init_PaRAM_event15 (void)
    {
    // Reset EDMA PaRAM OPT Register
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT = 0x0;
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].OPT |= 0x00101000 | (16 << 12);

    // Initialize EDMA Event Src and Dst Addresses
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC = (uint32_t)&pingSrcBuffer_2;

    EDMA3_0_CC0->PARAMSET[EDMA_chan15].DST = (uint32_t)&SPI0->SPIDAT1;//spi0 xmt reg.

    // Set EDMA Event PaRAM A,B,C CNT
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].A_B_CNT = 2400 << Bcnt_shift | 1;

    EDMA3_0_CC0->PARAMSET[EDMA_chan15].CCNT = 1;

    // Set EDMA Event PaRAM SRC/DST BIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =0;
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_BIDX =1;

    // Set EDMA Event PaRAM SRC/DST CIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_CIDX = 0x0;

    // Set EDMA Event PaRAM LINK and BCNTRLD
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].LINK_BCNTRLD = 2400 << 16 | (16 * 32);//Bcnt=15 bytes

    void init_PaRAM_event16 (void)
    {// Reset EDMA PaRAM OPT Register
    EDMA3_0_CC0->PARAMSET[16].OPT = 0x0;
    EDMA3_0_CC0->PARAMSET[16].OPT |= 0x00101000 | (16 << 12);

    // Config PaRAM OPT (disable chaining, AB_sync)

    // Initialize EDMA Event Src and Dst Addresses
    EDMA3_0_CC0->PARAMSET[16].SRC = (uint32_t)&pingSrcBuffer_2;
    EDMA3_0_CC0->PARAMSET[16].DST = (uint32_t)&SPI0->SPIDAT1;//spi0 xmt reg.

    // Set EDMA Event PaRAM A,B,C CNT
    EDMA3_0_CC0->PARAMSET[16].A_B_CNT = 2400 << Bcnt_shift | 1;

    EDMA3_0_CC0->PARAMSET[16].CCNT = 1;

    // Set EDMA Event PaRAM SRC/DST BIDX
    EDMA3_0_CC0->PARAMSET[16].SRC_DST_BIDX =0;
    EDMA3_0_CC0->PARAMSET[16].SRC_DST_BIDX =1;

    // Set EDMA Event PaRAM SRC/DST CIDX
    EDMA3_0_CC0->PARAMSET[EDMA_chan15].SRC_DST_CIDX = 0x0;

    // Set EDMA Event PaRAM LINK and BCNTRLD
    EDMA3_0_CC0->PARAMSET[16].LINK_BCNTRLD = 2400 << 16 | (16 * 32);//Bcnt=15 bytes

    thanks.....

  • Mr. RandyP, 

    One last thing I need to ask, what if I want to add some delay between transfers (say sending 5 bytes at a time) so that the CS signal will remain inactive for some time.

    the fields of (SPIDELAY register) only deals with (Chip-select-active-to-transmit-start-delay & Transmit-end-to-chip-select-inactive-delay), how about transmit to transmit delay, I tried the field (SPIFMTn->WDELAY) but it seems to extend the CHIP-SELECT signal in its active state (active low in my code), is it what it was really designed to do??? if not please tell me how it is done.

    thanks...