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.

SPI control with psp and edma

I am trying to drive an SPI serial DAC from SPI1 of a C6748 DSP on a Zoom EVM. I am using DSP BIOS 5, psp 1.30.00.05 with edma lld 1.10.00.01.

I have managed to provide clock, data & chip select signals using the SPI psp in interrupt mode but, because the device requires 24 bits of data, there are gaps in the chip select where the signal is deactivated.

I am now attempting to use the edma API to try to overcome this. I have modified the example program provided with the psp utimately using GIO_write or GIO_submit to send the data. When using GIO_submit with a callback the callback is never reached and hence the semiphore always times out. In both cases, write or submit, no signals are seen at the device.

The following shows parts of the relevant code:

void start_spi_sample()
{

    GIO_Attrs           gioAttrs            = GIO_ATTRS;
    Spi_ChanParams      chanParams;
    /* if the edma support is required then we need to configure edma         */
    EDMA3_DRV_Result    edmaResult      = 0;

    if (NULL == hEdma[0])
    {
        edmaResult = edma3init();
        if (EDMA3_DRV_SOK != edmaResult)
        {
            /* Error in configuring the edma driver                       */
            LOG_printf(&trace,"\r\nEDMA3 : edma3init() failed\r\n");
        }
        else
        {
            LOG_printf(&trace,"\r\nEDMA3 : edma3init() passed\r\n");
        }
    }

    chanParams.hEdma = hEdma[0];
 spiParams.edmaHandle = hEdma[0];

    /* create SPI channel for transmission */
    spiHandle =  GIO_create("/Spi1",IOM_INOUT,NULL,&chanParams,&gioAttrs);

 hCBSemHandle = SEM_create(0,NULL);

    if (NULL != spiHandle)
    {
  TxCallback.fxn = (GIO_TappCallback)&Spi1TxCallBack;
  TxCallback.arg = NULL;
  resetDAC();
  directWriteSetDAC();
  while(1)
  {
         spi_Test();
  }
    }
    else
    {
        LOG_printf(&trace,"\r\n SPI Driver Handle creation Failed ");
    }

    return;
}

/*
 *  \fn    static Int spi_Test(Error_block *eb)
 *
 *  \brief function That will test the SPI device by reading and writing from the
 *         SPI flash device.
 *
 *  \param  eb    [OUT]  error block given by the upper layers
 *
 *  \return
 *          DriverTypes_Completed - if sucessful
 *          Error code            - in case of error
 */
void spi_Test()
{
 DACout( 0,50.0 );
}

Void Spi1TxCallBack( Void )
{
 SEM_postBinary( hCBSemHandle );
}

void WriteDAC( long data )
{
    Spi_DataParam      dataparam;
 size_t size;
 Int ret;

 outDac[0] = data&0xff;
 outDac[1] = (data&0xff00)>>8;
 outDac[2] = (data&0xff0000)>>16;

    dataparam.bufLen       = 3;
    dataparam.inBuffer     = NULL;
    dataparam.outBuffer    = &outDac[0];
    dataparam.flags        &= ~(Spi_CSHOLD|Spi_GPIO_CS); //no CSHOLD or GPIO CS
    dataparam.dataFormat   = Spi_DataFormat_1;
 dataparam.chipSelect = 1<<SPI1_DAC_CS;

    size = dataparam.bufLen;
    GIO_submit(spiHandle, IOM_WRITE, &dataparam, &size, &TxCallback );
// while (SEM_pendBinary( hCBSemHandle,0 )==FALSE);
//    GIO_write(spiHandle, &dataparam, &size );
 SEM_pendBinary( hCBSemHandle,10 );
}

void DACout( int axis,float demand )
{
    long tmpDemand;
    long DACdata;

    tmpDemand = (unsigned int)(demand*32767.0F/100.0F + 32767.0F);
    tmpDemand = tmpDemand<0 ? 0 : tmpDemand;
    tmpDemand = tmpDemand>65535 ? 65535 : tmpDemand;
    DACdata = tmpDemand;
    DACdata += (long)(0x18 + axis)<<16;
   
    WriteDAC( DACdata );
      
}

void spi_initParams(void)
{

    spiParams = Spi_PARAMS;

    spiParams.hwiNumber = 8;
    spiParams.spiHWCfgData.intrLevel = FALSE;
    spiParams.opMode = Spi_OpMode_DMAINTERRUPT;

    spiParams.outputClkFreq     = 4000000;
    spiParams.loopbackEnabled   = FALSE;
    spiParams.edmaHandle        = NULL;

 spiParams.spiHWCfgData.masterOrSlave = Spi_CommMode_MASTER;
 spiParams.spiHWCfgData.pinOpModes = Spi_PinOpMode_SPISCS_4PIN;
    spiParams.spiHWCfgData.configDatafmt[0].charLength   = 16;
    spiParams.spiHWCfgData.configDatafmt[0].clkHigh      = TRUE ;
    spiParams.spiHWCfgData.configDatafmt[0].lsbFirst     = FALSE;
    spiParams.spiHWCfgData.configDatafmt[0].oddParity    = FALSE;
    spiParams.spiHWCfgData.configDatafmt[0].parityEnable = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[0].phaseIn      = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[0].waitEnable   = FALSE;
    //spiParams.spiHWCfgData.configDatafmt[0].wdelay       = 0;
    spiParams.spiHWCfgData.configDatafmt[1].charLength   = 8;
    spiParams.spiHWCfgData.configDatafmt[1].clkHigh      = TRUE ;
    spiParams.spiHWCfgData.configDatafmt[1].lsbFirst     = FALSE;
    spiParams.spiHWCfgData.configDatafmt[1].oddParity    = FALSE;
    spiParams.spiHWCfgData.configDatafmt[1].parityEnable = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[1].phaseIn      = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[1].waitEnable   = FALSE;
    spiParams.spiHWCfgData.configDatafmt[1].wDelay       = 0;

    spiParams.spiHWCfgData.intrLevel     = TRUE;

    /* power on the spi device in the Power sleep controller                  */
    Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_SPI1, TRUE);
    /* enable the EDMA in the PSC module  */
    Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_CC0, TRUE);
    Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC0, TRUE);
    Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC1, TRUE);
    Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_CC1, TRUE);   
    Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_GPIO, TRUE);
}

void configureSpi1(void)
{
    Uint32 savePinmux5 = 0;
   
    /* Unlock BOOTCFG module before pinmux configuration                      */
    KICK0 = KICK0_UNLOCK_CODE;
    KICK1 = KICK1_UNLOCK_CODE;

    /* enable the pinmux registers for Spi                                    */
    /* Only ENA, CLK, SIMO and CS0 are used                                   */
    savePinmux5 = (sysCfgRegs->PINMUX5 &
                  ~(CSL_SYSCFG_PINMUX5_PINMUX5_3_0_MASK |
                   CSL_SYSCFG_PINMUX5_PINMUX5_7_4_MASK  |
                    CSL_SYSCFG_PINMUX5_PINMUX5_11_8_MASK|
                    CSL_SYSCFG_PINMUX5_PINMUX5_19_16_MASK |
                    CSL_SYSCFG_PINMUX5_PINMUX5_23_20_MASK));
    sysCfgRegs->PINMUX5 = (PINMUX5_SPI1_ENABLE | savePinmux5);
}

Ha anyone seen something like this with the SPI psp before? Any help on this would be appreciated.

  • Further investigation of the SPI1 registers is indicating that the parameters passed via GIO_write are not getting through, such as the chip select bit and the transmit data.

    I am really struggling with this so can someone please reply.

  • Hi Iain,

    Since the device requires 24 bits of data, you are observing gaps in the chip select which is why the signal is deactivated. I think, this is the first task to be resolved. Switching to DMA mode would not help you resolve the issue is what i believe.

    Iain Scott said:
    I have managed to provide clock, data & chip select signals using the SPI psp in interrupt mode but, because the device requires 24 bits of data, there are gaps in the chip select where the signal is deactivated.


    If you refer the SPI User Guide section 1.2 says that the SPI supports only character length (2-16)bits. Probably this is why you are observing gaps/breaks. Can you try by enabling the CSHOLD and check its behavior?. For this, please refer section 2.5.1.4 of the userguide.

    Please correct me if my understanding of the issue is wrong..

    Can you please share the slave(SPI serial DAC) document?. And, also try configuring slave in 16 bit(if feature provided) and check if it makes any difference. 

    Since there is no successfull transaction happening, you are not getting a callback(completion). Do try all the above options in interrupt mode itself and let us know the results..

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    I did try the CSHOLD option as you suggest and the gap shows in the clock and data signals. The other problem with this is that I have to hang at least one other device on the same SPI channel(1) because SPI0 is unavailable so there would be contention between the signals of the two devices.

    The device is an AD5644 quad serial SPI DAC.

    This was an issue on another SOC device I have used in the past and using DMA did resolve the issue then.

    Also I know that using 16 bits only in interrupt mode works because I have already successfully integrated a serial ADC to the EVM.

    Regards Iain

  • Hi Iain,

     

    Can you please clarify one thing for me here: How much are you configuring the character length of SPI(Master)? - 8 bit, 16bit, or 24bit(this is not supported!!)

    Try configuring SPI for 8 bit(char len), interrupt mode, and set bufLen to 3 bytes and enable the CS HOLD. For this experiment, you should possibly not see any gaps. 

    You can even try this in DMA mode and let us know the results..

     

    Thanks & regards,

    Raghavendra 

  • I am using 8 bit data length and buflen = 3.

    There is no gap in the cs but there are gaps in the clock and data signals and as I said before how can I prevent contention with the ADC when they are both on SPI1.

    The problem with DMA seems to be that the GIO_write is not passing the Spi_DataParam structure. eg. SPIPC0 bit 0 is not being set to select CS0 and there is no data passing through SPIDAT0.

    Regards Iain

  • Hi Iain,

    Iain Scott said:
    The problem with DMA seems to be that the GIO_write is not passing the Spi_DataParam structure. eg. SPIPC0 bit 0 is not being set to select CS0 and there is no data passing through SPIDAT0.

    I do not have the exact setup as that of yours. But I did try running the spi sample application which comes with the psp in DMA mode by changing the dataparam.chipselect value. I could see the SPIPC0 changing!. Looks like the dataparam structure values passed through GIO_write is successfully reflecting in the SPI registers. One suggestion here is, can you please check the dataparam structure just before calling GIO_write and confirm its appropriate to what is being passed?. All these settings are done in function Spi_localControlDataConfig(...) of SPI driver. Do verify here..

    Since you are using SPI1, could you also verify/check the (instHandle->deviceInfo.rxDmaEventNumber) and (instHandle->deviceInfo.txDmaEventNumber) values (It should be 18 and 19 respectively)before calling Spi_localEdmaTransfer(...) in SPI driver. If all these settings are appropriate, you should be able to complete the IO. 

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    I was using an array defined by myself which had the data placed in it before calling GIO_write. I changed it for the array used in the sample ie. loopWrite. Strangely the cs select started to work in SPIPC0. I thought that might be to do with data alignment of the buffer so I made my array the same alignment as  loopWrite but that still did not select cs correctly. However, even with the cs correct there is still no data passed through SPIDAT0.

    As to the other settings you asked for, I am unable to access them. I am presuming the handle is the Edma handle set by edma3init(). Just says "cannot load from non-primitive location".

    Regards Iain

  • Iain,

    Iain Scott said:
    I changed it for the array used in the sample ie. loopWrite. Strangely the cs select started to work in SPIPC0.

    Just to isolate the issue, can you please use the array used in the sample and check if the data is passed through SPIDAT0?.  For the other settings, you should be able to open the Spi.c source file(placed in: pspdrivers_1_30_00_05\packages\ti\pspiom\spi\src) in the CCS debug window first. Then, you should place a breakpoint in the function Spi_localControlDataConfig(...) of the SPI driver. When this brakepoint is hit, check for the values mentioned above..

    Secondly, how do you know whether the cs select has started to work or not?.

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    I am using the array used in the sample and no data is passed through SPIDAT0 as seen at address 0x1f0e038. I am monitoring chip select at address 0x1f0e014 b0. That is now being set where it wasn't with the other array. There is still no activity, however, on the SPI1 lines.

    rxDmaEventNumber is showing as 18 and txDmaEventNumber is showing as 19 as you said earlier.

    Regards Iain

  • Iain,

     

    Thanks for the update.. I want to confirm few things here:

    So, with the exact settings and just by changing the "spiParams.opMode = Spi_OpMode_INTERRUPT" the application is working fine but gaps observed. But when  "spiParams.opMode = Spi_OpMode_DMAINTERRUPT" there is no activity at all in SPIDAT0(the sample application is not working/total halt). Is my understanding correct?.

    And, since you do not have SPI0, you cannot to test the sample application provided by PSP in DMA mode..correct?. 

    If the exact setup and settings works in interrupt mode, it should also work in DMA mode. Well, would it be possible for you to share your sample application?. It would be surely helpful in debugging further.

     

    Thanks & regards,

    Raghavendra

  • So, with the exact settings and just by changing the "spiParams.opMode = Spi_OpMode_INTERRUPT" the application is working fine but gaps observed. But when  "spiParams.opMode = Spi_OpMode_DMAINTERRUPT" there is no activity at all in SPIDAT0(the sample application is not working/total halt). Is my understanding correct?.  Your understanding is correct.

    And, since you do not have SPI0, you cannot to test the sample application provided by PSP in DMA mode..correct?.  Again your understanding is correct.

    You are certainly very welcome to have the application. Have you an e_mail I can send it to?

    Iain

  • Answering for Raghavendra as he might be done for the day...

    Can you simply zip up your project and attach it to this thread?

    Dave

  • Hi Iain,

     

    When configuring SPI in DMA mode of operation, it is very important that the input/output Buffers are aligned appropriately. Without which, the DMA may not respond correctly (Please refer "global variables" section of spiSample_io.c file of SPI sample application which comes with the PSP). In your case, the outDac and inDac buffers must be aligned. 

    It should be:

    #pragma DATA_ALIGN(outDac, 128);

    Uint8  outDac[SPI_TEST_STRING_LEN +SPI_MAX_CMD_LEN ];

    #pragma DATA_ALIGN(inDac, 128);

    Uint8  loopRead[SPI_TEST_STRING_LEN + SPI_MAX_CMD_LEN];

     

    Are you doing this?. If not, please try this and let us know the results..

    One more question : It looks like you are using "Spi_DataFormat_1" any specific reason for this?. And after using the array of the sample application, the chip select issue is resolved right?.

     

    Thanks & regards,

    Raghavendra

     

  • Hi Raghavendra

    Thanks for your suggestions, Iain is actually now on leave now until the 28th June but will be picking this up again as soon as he returns and will let you know the results.

    Thanks

    Chris

     

  • Hi Raghavendra,

    I had used aligned buffers as you described but as a precaution I set them up as you suggest without any success.

    I used Spi_DataFormat_1 because I was already using Spi_DataFormat_0 for a serial ADC which uses 16 bit data reads. Spi_DataFormat_1 has 8 bit data writes.

    Again as a precaution I changed to Spi_DataFormat_0 but with no success.

    I have zipped the project and attached it to this message.

    Regards Iain

    FHR35_SPI_EDMA2.zip
  • Hi Iain,

    I looked into the sample application you provided, the initialization sequence seems to be correct with appropriate parameters but i have not looked into it deeply yet(configuring DAC related stuff!!)

    I have a quick suggestion to make here - Since you are using SPI 1 of C6748, I request you to run/test the sample application(edma) provided by the psp 1.30.00.05 release. If you look into the spiSample.tci file(placed in: pspdrivers_01_30_00_05\packages\ti\pspiom\examples\evm6748\spi\edma\build\) of the sample application, they are creating a SPI instance '1'(deviceId =1) and not SPI instance '0'! donot go by the name "Spi0" which is a typo. The SPI device will be created depending on the deviceId. Testing this, you can confirm SPI 1 in dma mode working(all is good with SPI1 and DMA), and then can go ahead in debugging the DAC side config. Please try this and let us know your observations.

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    I have tried this before without success but I thought I was accessing SPI0. I tried it again this morning but there is no activity on the MOSI, CLK os CS0 for SPI1. I also looked in the SPI1 memory base 0x1f0e000 and there is no sign of any data being transmitted.

    The application hangs after the first GIO_write in spi_Test.

    Regards Iain

  • Iain,

    Are you using the C6748 EVM or a custom EVM?. Did you try the sample application binaries which comes with the PSP release itself?. The sample application communicates with the SPI flash(M25P64) available on the C6748 EVM and performs read/write operations. Is this flash available on your EVM?. You can even try the interrupt mode application to verify this! and let us know the results.. All this is important because if the edma sample application itself is failing, then it is something to do with the setup.

     

    Thanks & regards,

    Raghavendra

  • Hi Raghavendra,

    Yes I am using the C6748 EVM with the SPI flash.

    I have found the root of my problem. As I said I was unable to get the SPI flash example to work at all. However, I have a breadboard connected to the EVM through the 100 way connectors which contains our circuitry for ADC, DAC etc. This morning I removed this and ran only the EVM. The SPI flash application then ran correctly.

    Replacing the breadboard and scoping the SPI clock showed considerable distortion. This was traced to a bad connection. After correcting this, the SPI flash application ran correctly and, more to the point, my DAC application also provides the correct signals, 24 clock cycles without gaps.

    Thanks for your help on this. We went all round the houses on software when the problem was hardware all along.

    Regards Iain