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.

CCS/TM4C129ENCPDT: SPI Transfer issue

Part Number: TM4C129ENCPDT

Tool/software: Code Composer Studio

Hi,
I am using CCS 9.3 with TI-RTOS. Controller used is TM4C129ENCPDT. I am trying to interface AD7616 over SPI to controller. For initializing AD7616, registers need to be configured, by writing its registers. It is done using api: SPI_Transfer(). But only first SPI transfer for write is getting success. When I read back the registers ,only first write is successful. For spi I am not using Fss. Chip select is configured as GPIO.  Below is the code part. I am not sure if its hardware  or software issue. Is there anything to change if SPI is in  3 wire mode for CCS 9.3? I also tried : SPI_Open(), First transfer, SPI_Close(),SPI_Open(), second transfer, SPI_Close(). Here also second fails.

en_transferStat_t Adc_Init(){

SPI_Params slaveSpiParams;
en_transferStat_t en_transferOk;
SPI_Params_init(&slaveSpiParams);
slaveSpiParams.mode = SPI_MASTER;

/* Initialize SPI handle as default master for ADC*/
masterAdc1 = SPI_open(Board_SPI3, NULL);
if (masterAdc1 == NULL)
{
System_abort("Error initializing SPI ADC1\n");
return TRANSFER_FAILURE;
}
else
{
System_printf("SPI initialized ADC1\n");
}

/* Initiate SPI transfer for configuration register */

bl_transferOk = adc_spi_write(masterAdc1,CONFIGREG_ADDRESS,u16_command1);

Adc_ReadReg(masterAdc1,CONFIGREG_ADDRESS, pu16_result);

bl_transferOk = adc_spi_write(masterAdc1,RANGE_REGISTER,u16_command2);

Adc_ReadReg(masterAdc1,RANGE_REGISTER, pu16_result);


SPI_close(masterAdc1);

}

/******************************************************************************
.Purpose : To write data into register over SPI
.Arguments : masterSpi : SPI Handler
u8_regAddress : Register address to write data
u16_regData : Data to write
.Returns : Success/ Failure
.Note : Returns 1 byte Transfer status
******************************************************************************/
uint8_t adc_spi_write(SPI_Handle masterSpi,
uint8_t u8_regAddress,
uint16_t u16_regData)
{
uint8_t au8_buf[2], u8_ret = 1;

/*Arrange register address and data to send over SPI*/
au8_buf[0] = REGISTER_WRITE | ((u8_regAddress & 0x3F) << LOGICAL_SHIFT_ONE) | ((u16_regData & MASK_0x100) >> LOGICAL_SHIFT_EIGHT);
au8_buf[1] = (u16_regData & MASK_0xFF);


spi_write_and_read(masterSpi, au8_buf, 2);
return u8_ret;
}

/******************************************************************************
.Purpose : To read and write data from/into register over SPI
.Arguments : masterSpi : SPI Handler
uint8_t bytes_number :No. of bytes to write
u16_regData : 
.Returns : Success/ Failure
.Note : Returns 1 byte Transfer status
******************************************************************************/

uint8_t spi_write_and_read(SPI_Handle masterSpi,
uint8_t *data,
uint8_t bytes_number)
{

uint32_t i;
uint8_t tx[2];
uint8_t rx[2];

for(i = 0; i < bytes_number; i++){
tx[i] = data[i];
}

SPI_Transaction masterTransaction;
masterTransaction.count = bytes_number;
masterTransaction.txBuf = (Ptr)tx;
masterTransaction.rxBuf = (Ptr)rx;

GPIO_write(ADC_CS,Board_GPIO_OFF);

SPI_transfer(masterSpi, &masterTransaction);

GPIO_write(ADC_CS,Board_GPIO_ON);

for (i = 0; i < bytes_number; i++)
data[i] = rx[i];

return 1;
}

  • Hi,

    Are you using a LaunchPad or your custom hardware? Can you attach the SPI configuration from the "Board.c" file?

    Todd

  • I am using custom board.  I am using SPI3

    /*
    * =============================== SPI ===============================
    */
    /* Place into subsections to allow the TI linker to remove items properly */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_SECTION(SPI_config, ".const:SPI_config")
    #pragma DATA_SECTION(spiTivaDMAHWAttrs, ".const:spiTivaDMAHWAttrs")
    #endif

    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPITivaDMA.h>

    SPITivaDMA_Object spiTivaDMAObjects[EK_TM4C129EXL_SPICOUNT];

    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN(spiTivaDMAscratchBuf, 32)
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment=32
    #elif defined(__GNUC__)
    __attribute__ ((aligned (32)))
    #endif
    uint32_t spiTivaDMAscratchBuf[EK_TM4C129EXL_SPICOUNT];

    const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[EK_TM4C129EXL_SPICOUNT] = {
    {
    .baseAddr = SSI2_BASE,
    .intNum = INT_SSI2,
    .intPriority = (~0),
    .scratchBufPtr = &spiTivaDMAscratchBuf[0],
    .defaultTxBufValue = 0,
    .rxChannelIndex = UDMA_SEC_CHANNEL_UART2RX_12,
    .txChannelIndex = UDMA_SEC_CHANNEL_UART2TX_13,
    .channelMappingFxn = uDMAChannelAssign,
    .rxChannelMappingFxnArg = UDMA_CH12_SSI2RX,
    .txChannelMappingFxnArg = UDMA_CH13_SSI2TX
    },
    {
    .baseAddr = SSI3_BASE,
    .intNum = INT_SSI3,
    .intPriority = (~0),
    .scratchBufPtr = &spiTivaDMAscratchBuf[1],
    .defaultTxBufValue = 0,
    .rxChannelIndex = UDMA_SEC_CHANNEL_TMR2A_14,
    .txChannelIndex = UDMA_SEC_CHANNEL_TMR2B_15,
    .channelMappingFxn = uDMAChannelAssign,
    .rxChannelMappingFxnArg = UDMA_CH14_SSI3RX,
    .txChannelMappingFxnArg = UDMA_CH15_SSI3TX
    }
    };

    const SPI_Config SPI_config[] = {
    {
    .fxnTablePtr = &SPITivaDMA_fxnTable,
    .object = &spiTivaDMAObjects[0],
    .hwAttrs = &spiTivaDMAHWAttrs[0]
    },
    {
    .fxnTablePtr = &SPITivaDMA_fxnTable,
    .object = &spiTivaDMAObjects[1],
    .hwAttrs = &spiTivaDMAHWAttrs[1]
    },
    {NULL, NULL, NULL}
    };

    /*
    * ======== EK_TM4C129EXL_initSPI ========
    */
    void EK_TM4C129EXL_initSPI(void)
    {
    /* SSI2 */
    /*
    * NOTE: TI-RTOS examples configure pins PD0 & PD1 for SSI2 or I2C7. Thus,
    * a conflict occurs when the I2C & SPI drivers are used simultaneously in
    * an application. Modify the pin mux settings in this file and resolve the
    * conflict before running your the application.
    */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

    GPIOPinConfigure(GPIO_PD3_SSI2CLK);
    GPIOPinConfigure(GPIO_PD2_SSI2FSS);
    GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
    GPIOPinConfigure(GPIO_PD0_SSI2XDAT1);

    GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
    GPIO_PIN_2 | GPIO_PIN_3);

    /* SSI3 *///CHANGED WITH NEW SCHEME
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3);

    GPIOPinConfigure(GPIO_PF3_SSI3CLK);
    //GPIOPinConfigure(GPIO_PF2_SSI3FSS);
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);

    GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_2 | GPIO_PIN_3);
    GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_3 );
    //GPIOPinTypeSSI(GPIO_PORTF_BASE, GPIO_PIN_3 | GPIO_PIN_2);
    #if 0
    GPIOPinConfigure(GPIO_PQ0_SSI3CLK);
    GPIOPinConfigure(GPIO_PQ1_SSI3FSS);
    GPIOPinConfigure(GPIO_PQ2_SSI3XDAT0);
    GPIOPinConfigure(GPIO_PQ3_SSI3XDAT1);

    GPIOPinTypeSSI(GPIO_PORTQ_BASE, GPIO_PIN_0 | GPIO_PIN_1 |
    GPIO_PIN_2 | GPIO_PIN_3);
    #endif
    EK_TM4C129EXL_initDMA();
    SPI_init();
    }

  • Thanks. Can you confirm that Board_SPI3 is defined as 1.

    What do you see on the actual wire? Is anything being sent out?

    Todd

  • Hi Todd,

    BOARD_SPI3 is 1. SPI transfer is taking place but in unusual way. I used default data size as 8. for transferring 16 bit data, I split it into 2. But msb of second byte is not getting write into register.That is, I write second byte as 0xBB, when I read back it is read as 0x3B.

    au8_buf[0] = REGISTER_WRITE | ((u8_regAddress & 0x3F) << LOGICAL_SHIFT_ONE) | ((u16_regData & MASK_0x100) >> LOGICAL_SHIFT_EIGHT);
    au8_buf[1] = (u16_regData & MASK_0xFF);

    /* Initialize SPI transaction structure */
    masterTransaction.count = 2;
    masterTransaction.txBuf = (Ptr)au8_buf;

    masterTransaction.rxBuf = (Ptr)NULL;

    /*Chip select low to enable SPI transfer*/
    GPIO_write(u8_adcCs, Board_GPIO_OFF);
    /* Initiate SPI transfer */
    u8_ret = SPI_transfer(masterSpi, &masterTransaction);
    /*Chip select high to disable SPI transfer*/
    GPIO_write(u8_adcCs, Board_GPIO_ON);

  • Sorry for the delay.

    What do you see on the wires (e.g. logic analyzer)?

    Todd

  • Hi,

    Spi device connected gives output data at rising edge of the clock. It is evident by probing the pin to oscilloscope and Controller has to read the data on falling edge .But it is seen that controller reads data on falling edge of previous clock. So a shift in value occur.

    Regards

    Jamshi

  • Jamshi,

    It is okay to use your own GPIO chip select and not use Fss. Have you tried adding a delay between asserting the chip select and the SPI_transfer() call to make sure the slave is ready for the transaction?

    Jas

  • jamshi pj said:
    Spi device connected gives output data at rising edge of the clock. It is evident by probing the pin to oscilloscope and Controller has to read the data on falling edge .But it is seen that controller reads data on falling edge of previous clock. So a shift in value occur.

    The AD7616 SPI timing is:

    Which means the TM4C SPI configuration to use is:

    To set the TM4C mode the required SPI parameters need to be set and passed as the 2nd argument to the the SPI_open function. I.e. try:

    SPI_Params slaveSpiParams;
    en_transferStat_t en_transferOk;
    SPI_Params_init(&slaveSpiParams);
    slaveSpiParams.mode = SPI_MASTER;
    slaveSpiParams.frameFormat = SPI_POL1_PHA1; /* SPI mode Polarity 1 Phase 1 */
    
    /* Initialize SPI handle as default master for ADC*/
    masterAdc1 = SPI_open(Board_SPI3, &slaveSpiParams);

    Your original code was passing NULL as the 2nd argument to SPI_open(), meaning default SPI parameters were used for which the default frameFormat is SPI_POL0_PHA0 /* SPI mode Polarity 0 Phase 0 */

    You might also need to set the slaveSpiParams.bitRate to the required BIT rate in Hz. The default is 1 MHz.

  • Hi,

    I changed to

    masterAdc1 = SPI_open(Board_SPI3, &slaveSpiParams);

    and with SPI mode Polarity 0 Phase 0,I write register and with SPI mode Polarity 0 Phase 1 Read the converted result. I am not able to perform all with same polarity.

    
    

  • Jamshi,

    I'm not sure what you mean by writing and reading the register with different polarities here, but you can't change the polarity once you open a SPI instance. I believe the polarity and phase settings you are looking for are SPO=1 and SPH=0.

    Jas