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.

RTOS/EK-TM4C123GXL: SPI and I2C Task integration failed

Part Number: EK-TM4C123GXL

Tool/software: TI-RTOS

Dear Team,

 I have two tasks one with I2C Transaction and other with SPI Transaction. when I disable SPI task I2C task is running smoothly, transaction reads data from the sensor. Even when I enable the SPI Task , I2C task working fine. But when I connect MISO and MOSI lines to the microcontroller. I2C Transaction going to Bad I2C Transfer. 

To be short: when I connect the MISO and MOSI lines to microcontroller and enable SPI task . I2C task making the system_abort.

Please give your valuable suggestion that where I'm going wrong in the connections.

Here are the code snippets for each module:

I2C Pin configuration:

 GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_3);
    GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_2);
    while (GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_3) != GPIO_PIN_3)
    {
        GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, 0);
        GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_2, GPIO_PIN_2);
    }

    // Configure the GPIO Pin Mux for PB2 - I2C0SCL

    GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);

    // Configure the GPIO Pin Mux for PB3 - I2C0SDA

    GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

I2C Channel opening:

 // I2C Channel0 opening

    I2C_Params_init(&signal.i2c0Params);
    signal.i2c0Params.bitRate = I2C_100kHz;
    signal.i2c0 = I2C_open(I2C_IMU_LEFT_DIAGONALS, &signal.i2c0Params);
    if (signal.i2c0 == NULL)
    {
        System_abort("Error Initializing I2C channel0\n");
    }
    else
    {
        System_printf("I2C Channel 0 Initialized!\n");

    }
#define I2C_IMU_LEFT_DIAGONALS      I2C0_IMU_LEFT_DIAGONALS

const I2CTiva_HWAttrs i2cTivaHWAttrs[I2CCOUNT] = {
    {
        .baseAddr = I2C0_BASE,
        .intNum = INT_I2C0,
        .intPriority = (~0)
   },
    {
        .baseAddr = I2C1_BASE,
        .intNum = INT_I2C1,
        .intPriority = (~0)
    }

};

const I2C_Config I2C_config[] = {
    {
        .fxnTablePtr = &I2CTiva_fxnTable,
        .object = &i2cTivaObjects[0],
        .hwAttrs = &i2cTivaHWAttrs[0]
    },
    {
        .fxnTablePtr = &I2CTiva_fxnTable,
        .object = &i2cTivaObjects[1],
        .hwAttrs = &i2cTivaHWAttrs[1]
    },
    {NULL, NULL, NULL}

};

WriteRegister code:

void CSupport::i2c_writeRegister(I2C_Handle handle,unsigned char slaveAddr,uint16_t regAddr, uint32_t value,I2C_TRANSFER_TYPE transferType)
{

    I2C_Handle  i2cChannel1;
    I2C_Params currI2cParams;

    uint8_t             txBuffer[4];
    I2C_Transaction     i2cTransaction;

    i2cTransaction.slaveAddress = slaveAddr;
    i2cTransaction.writeBuf = txBuffer;

    switch(transferType)
    {
        case IMU_TRANSACTION :
        //Write to a 8-bit status register
        i2cTransaction.writeCount = 2;
        i2cTransaction.readCount = 0;

        txBuffer[0] = regAddr & 0xFF;//LB Addr
        txBuffer[1] = value & 0xFF;
        break;
        case CURRENT_TRANSACTION :

        i2cTransaction.writeCount = 3;
        i2cTransaction.readCount = 0;

        txBuffer[0] = regAddr & 0xFF;// 8- Bit address
        txBuffer[1] = value >> 8;// HB Addr
        txBuffer[2] = value & 0xFF;// LB Addr
        break;

        default:

        //Write to a 16-bit status register
        i2cTransaction.writeCount = 4;
        i2cTransaction.readCount = 0;

        txBuffer[0] = (regAddr >> 8) & 0xFF;//HB Addr
        txBuffer[1] = regAddr & 0xFF;//LB Addr
        txBuffer[2] = value & 0xFF;
        txBuffer[3] = (value >> 8) & 0xFF;
        break;

    }

    if (!I2C_transfer(handle, &i2cTransaction)) {
        /*GPIO_write(Board_LED_RED, Board_LED_ON);*/
        System_abort("Bad I2C transfer!");
    }
}

Read Register :

/*
* This function used for read operation in I2C Transaction of 8 and 16 bit registers
* "transferType" need to  mention for type of transfer
* IMU_TRANSACTION       - 8 Bit
* CURRENT_TRANSACTION   - 16 Bit
*/

void CSupport::i2c_readRegister(I2C_Handle handle, unsigned char slaveAddr,
                                uint8_t regAddr, uint16_t *data, size_t length,
                                I2C_TRANSFER_TYPE transferType)
{
    uint8_t             txBuffer[2];
    I2C_Transaction     i2cTransaction;

    i2cTransaction.slaveAddress = slaveAddr;
    i2cTransaction.writeBuf = txBuffer;
    i2cTransaction.readBuf = data;
    i2cTransaction.readCount = length;


    switch(transferType)
    {
        case IMU_TRANSACTION :
        //Write to a 8-bit status register
        i2cTransaction.writeCount = 1;
        txBuffer[0] = regAddr & 0xFF;//LB Addr
        break;
        case CURRENT_TRANSACTION :
        i2cTransaction.writeCount = 1;
        txBuffer[0] = regAddr & 0xFF;// 8- Bit address
        break;
        default: // 16- Bit address
        i2cTransaction.writeCount = 2;
        txBuffer[0] = regAddr >> 8;//HB Addr
        txBuffer[1] = regAddr & 0xFF;//LB Addr
        break;

    }
    if (!I2C_transfer(handle, &i2cTransaction)) {
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 1);
        System_abort("Bad I2C transfer!");
    }
}

I2C Task:

void get_imu()
{
    uint16_t pwr = 0x00;
    CSupport support;
    support.i2c_writeRegister(signal.i2c0,MPU6050_I2C_ADDRESS,0x6B,0x80,IMU_TRANSACTION);
    support.i2c_readRegister(signal.i2c0,MPU6050_I2C_ADDRESS, 0x6B, &pwr, 1, IMU_TRANSACTION);
    do
    {
        support.i2c_readRegister(signal.i2c0,MPU6050_I2C_ADDRESS, 0x6B, &pwr, 1, IMU_TRANSACTION);
    }
    while ((pwr & 0x40) != 0x40);

    // Use PLL with X axis gyroscope reference
    support.i2c_writeRegister(signal.i2c0,MPU6050_I2C_ADDRESS,0x6B,0x01,IMU_TRANSACTION);
    // Enable I2C Master mode
    support.i2c_writeRegister(signal.i2c0,MPU6050_I2C_ADDRESS,0x6A,0x20,IMU_TRANSACTION);
    // Set sample rate divider
    support.i2c_writeRegister(signal.i2c0,MPU6050_I2C_ADDRESS,0x19,0x13,IMU_TRANSACTION);
    support.i2c_writeRegister(signal.i2c0,MPU6050_I2C_ADDRESS,0x67,0x11,IMU_TRANSACTION);
    while (1)
    {
        Semaphore_pend(IMUSem, BIOS_WAIT_FOREVER);
        support.i2c_readRegister(signal.i2c0,MPU6050_I2C_ADDRESS, 0x3B, (uint16_t *) &signal.imu.mpu6050, 14, IMU_TRANSACTION);
        signal.imu.AcX = signal.imu.mpu6050.AccelXH << 8 | signal.imu.mpu6050.AccelXL;
        signal.imu.AcY = signal.imu.mpu6050.AccelYH << 8 | signal.imu.mpu6050.AccelYL;
        signal.imu.AcZ = signal.imu.mpu6050.AccelZH << 8 | signal.imu.mpu6050.AccelZL;
        signal.imu.temperature = (((signal.imu.mpu6050.TempH << 8) | signal.imu.mpu6050.TempL) / 340)+36.5;
        signal.imu.GyX = signal.imu.mpu6050.GyroXH << 8 | signal.imu.mpu6050.GyroXL;
        signal.imu.GyY = signal.imu.mpu6050.GyroYH << 8 | signal.imu.mpu6050.GyroYL;
        signal.imu.GyZ = signal.imu.mpu6050.GyroZH << 8 | signal.imu.mpu6050.GyroZL;

    }
    I2C_close(signal.i2c0);  //Deinitialized I2C
    System_printf("I2C Channel 0 closed!\n");
    System_flush();
}

SPI Pin configuration:

    // Configure the GPIO Pin Mux for PA2 - SSI0CLK


    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2);


    // Configure the GPIO Pin Mux for PA3 - SSI0FSS
    GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_0); // To pull the Chip select line low . As the driver CS is not giving desired result

    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_3);

    // Configure the GPIO Pin Mux for PA4 - SSI0RX

    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_4);

    // Configure the GPIO Pin Mux for PA5 - SSI0TX

    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5);

SPI channel Opening:

    SPI_Params_init(&rightSpiParams);
    rightSpi = SPI_open(RIGHT_DIAGONAL_SPI0, &rightSpiParams);
    if (rightSpi == NULL)  System_abort("Error initializing Right SPI\n");
    else  System_printf("Right SPI initialized\n");
#define SPI_RIGHT_DIAGONALS         RIGHT_DIAGONAL_SPI0
const SPITivaDMA_HWAttrs spiTivaDMAHWAttrs[SPICOUNT] = {
    {
        .baseAddr = SSI0_BASE,
        .intNum = INT_SSI0,
        .intPriority = (~0),
        .scratchBufPtr = &spiTivaDMAscratchBuf[0],
        .defaultTxBufValue = 0,
        .rxChannelIndex = UDMA_CHANNEL_SSI0RX,
        .txChannelIndex = UDMA_CHANNEL_SSI0TX,
        .channelMappingFxn = uDMAChannelAssign,
        .rxChannelMappingFxnArg = UDMA_CH10_SSI0RX,
        .txChannelMappingFxnArg = UDMA_CH11_SSI0TX
    },
    {
        .baseAddr = SSI1_BASE,
        .intNum = INT_SSI1,
        .intPriority = (~0),
        .scratchBufPtr = &spiTivaDMAscratchBuf[1],
        .defaultTxBufValue = 0,
        .rxChannelIndex = UDMA_CHANNEL_SSI1RX,
        .txChannelIndex = UDMA_CHANNEL_SSI1TX,
        .channelMappingFxn = uDMAChannelAssign,
        .rxChannelMappingFxnArg = UDMA_CH10_SSI1RX,
        .txChannelMappingFxnArg = UDMA_CH11_SSI1TX
    }
};

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},
};
SPI Task:
void get_height(){

     // Buffers for transactions
     unsigned char rightRxBuffer[8] = {0};
     unsigned char rightTxBuffer[] = {0x00,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x00};// For 2 counters - 24 bit

    SPI_Handle rightSpi,leftSpi,frontSpi;
    SPI_Params rightSpiParams,leftSpiParams,frontSpiParams;
    SPI_Transaction rightSpiTrans,leftSpiTrans,frontSpiTrans;
    bool rightConfigure,leftConfigure,frontConfigure;
    bool rightReceive,leftReceive,frontReceive;

    SPI_Params_init(&rightSpiParams);
    rightSpi = SPI_open(RIGHT_DIAGONAL_SPI0, &rightSpiParams);
    if (rightSpi == NULL)  System_abort("Error initializing Right SPI\n");
    else  System_printf("Right SPI initialized\n");

    /* Initialize right SPI transaction structure */
    rightSpiTrans.count = sizeof(rightTxBuffer);
    rightSpiTrans.txBuf = (Ptr)rightTxBuffer;
    rightSpiTrans.rxBuf = NULL;


    /* Configure Encoder*/
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
    rightConfigure = SPI_transfer(rightSpi, &rightSpiTrans);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);

    if (rightConfigure)  System_printf("succesfully configured Right SPI\n");
    else System_abort("Unsuccessful configuration of Right SPI\n");
    System_flush();

    rightTxBuffer[0] = {0x30}; // To reset counters before counting
    rightTxBuffer[1] = {0x03};
    rightSpiTrans.rxBuf = (Ptr)rightRxBuffer;
    rightSpiTrans.count = 2;
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);
    rightConfigure = SPI_transfer(rightSpi, &rightSpiTrans);
    GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);

    rightTxBuffer[0] = {0x88}; // To read counter values
    rightSpiTrans.rxBuf = (Ptr)rightRxBuffer;
    rightSpiTrans.count = 7;

    counter_48bit rightEncoder;

    while (1){
         Semaphore_pend(ENCSem, BIOS_WAIT_FOREVER);

         GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 0);          // Suggested to use 2:1 MUX for Chip select between different SPI Slaves
         rightReceive = SPI_transfer(rightSpi, &rightSpiTrans);
         GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, 1);
         if(!rightReceive) System_abort("Right SPI Receive failed :(");

         signal.rightEncoder.counter1 = (rightRxBuffer[1])<<16|(rightRxBuffer[2]<<8)|(rightRxBuffer[3]);
         signal.rightEncoder.counter0 = (rightRxBuffer[4])<<16|(rightRxBuffer[5]<<8)|(rightRxBuffer[6]);
}
}

  • Hi,

    Not sure what was wrong. I have some questions though.
    0. Which line of System_abort are you calling? You have System_abort("Error Initializing I2C channel0\n") and System_abort("Bad I2C transfer!").
    1. When you connect the MISO and MOSI pins, does the SPI transaction continue to work or you don't know since you already took the abort due to the I2C?
    2. What happened if only SPI is enabled but not I2C? Will the SPI work by itself?
    3. With a slower SPI clock, will it make a difference to the I2C abort? Try with a much slower SPI clock so the interrupt comes slower.
    4. Can you use the ROV to find out if you have any stack issue?
    5. Are you using HWI? Is it a interrupt priority issue as the SSI0 has default priority than I2C0? What if you manually change
  • Hello Charles,

    Answer for the questions as :

    Charles Tsai said:


    0. Which line of System_abort are you calling? You have System_abort("Error Initializing I2C channel0\n") and System_abort("Bad I2C transfer!").

    System_abort("Bad I2C transfer!") in readRegister, writeRegister It happening randomly (Mostly in i2c_readRegister()).

    Charles Tsai said:

    1. When you connect the MISO and MOSI pins, does the SPI transaction continue to work or you don't know since you already took the abort due to the I2C? 

    I feel SPI works as I'm able to see few jump of waves in oscilloscope . But Didn't saw very clearly.

    Charles Tsai said:

    2. What happened if only SPI is enabled but not I2C? Will the SPI work by itself?

    Yeah. SPI is working well If enable only SPI task. ( and vice versa i.e., I2C also works if enable only I2C task).  

    Charles Tsai said:

    3. With a slower SPI clock, will it make a difference to the I2C abort? Try with a much slower SPI clock so the interrupt comes slower. 

    I tried with 500 ms configuration but didn't have any postive result.\

    Charles Tsai said:

    4. Can you use the ROV to find out if you have any stack issue?

     I'm giving 2048 as stacksize Hope its not be a problem

    Charles Tsai said:

    5. Are you using HWI? Is it a interrupt priority issue as the SSI0 has default priority than I2C0? What if you manually change

    No I'm not using any HWI in the system. So Hope no need to change anything?

    Majorly system fails when I try to connect the MISO and MOSI of the SPI channel . The system is not failing even both tasks are enabled. So any problem with connections?( I haven't connect any pull up resistors in any of the communicaiton channels(SPI,I2C).

    Thanks for taking and analysis the problem and framing questions in structured.

    Best Regards,

    Yashwanth Kumar Gandeti.

  • HI,

    Yashwanth Gandeti said:
    Majorly system fails when I try to connect the MISO and MOSI of the SPI channel . The system is not failing even both tasks are enabled. So any problem with connections?( I haven't connect any pull up resistors in any of the communicaiton channels(SPI,I2C).

      For proper I2C operation you must have proper pull up resistors on the I2C_SCL and I2C_SDA bus. No need of pullups on the SPI. I will suggest you first add correct pullup to the bus first and see if of any different results.

  • Hi Charles,

    I'll try with pull up resistors and let you know the status.

    Regards,
    Yashwanth Kumar.
  • Hi Yashwanth,
    I have not heard back from you. I assume your issue is somehow resolved after proper pull up resistor is put in place as this is critical to the correct operation of the I2C. I will close this thread for now. If you have new questions you can open a new thread or reopen this thread if your issue is not resolved.