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.

L138 DSP I2C0 issue

Other Parts Discussed in Thread: SYSBIOS, OMAPL138

Hi!

I try to use the I2C 0 on the DSP of the LCDK in polled mode and have some troubles with sending data.
I use CCS5.5, SYSBIOS 6.35.4.50, and I use CSL.
Yes I checked the code of the starterware demo (actually I used parts of it), but it is IRQ-based and I want to use polled IO.

The setup of the interface is performed as followed:

- 1. pinmux
- 2. bring i2c in reset mode
- 3. setup the clock (8MHz prescaled, 100kHz sclk)
- 4: clear int stat reg
- 5: ensure ICIVR is 0
- 6:  configure slave address
- 7: write the number of bytes to transfer in the data count register (2 here)
- 8. bring i2c up again

fine up to here.

the transmit routine is :

    //   1:  wait for bus free
    while ((i2cRegSet->ICSTR & CSL_I2C_ICSTR_BB_MASK) || !(i2cRegSet->ICSTR & CSL_I2C_ICSTR_ICXRDY_MASK));
 
    //   2:  set master mode and auto stop
    i2cRegSet->ICMDR = CSL_FMKT(I2C_ICMDR_MST,MASTER_MODE) //master mode
                               | CSL_FMKT(I2C_ICMDR_STP,SET) //enable autostop
                               | CSL_FMKT(I2C_ICMDR_STT,SET) //start
                               | CSL_FMKT(I2C_ICMDR_TRX,TX_MODE) //transmitter mode
                               | CSL_FMKT(I2C_ICMDR_IRS,ENABLE);  // keep enabled

     //   3:   write the regAddr of the slave devices to the TX register
    i2cRegSet->ICDXR = regAddr;

    //   4:   wait for the TX register to be free again
    while (!(i2cRegSet->ICSTR & CSL_I2C_ICSTR_ICXRDY_MASK));

    //   5:   write the data to the TX register
    i2cRegSet->ICDXR = regData;

    //   6:   wait for the transfer to end
    while (i2cRegSet->ICSTR & CSL_I2C_ICSTR_BB_MASK);

    //   7:   clear stop condition detected bit
    CSL_FINST(i2cRegSet->ICSTR,I2C_ICSTR_SCD,CLEAR);
-------------

This procedure works fine for the first use, but hangs at step 4 when transmitting the second pair of bytes.
When it hangs the reason seems to be that in the ICMDR register the MST and STP bits are 0 (STT still 1).

The procedure seems to work if there is a breakpoint or a wait loop at or before step 1, so I assume that there must be some timing issue.

Any suggestions?

Thanks,

Alex

  • Hi Alexander,

    Thanks for your post.

    In my opinion, the CPU is polling for the ICXRDY flag bit to clear or XRDY interrupt generation which indicates the readiness to transmit data but unfortunately, this has not happened in your case.

    For the above to cause and this is because ICXRDY indicates that the data transmit register (ICDXR) which is not ready to accept new data because the previous data itself has not been movied from ICDXR to the transmit shift register (ICXSR). This shows that, the pending I2C interrupts are not cleared properly while setting the I2C peripheral before transmitting the data to the TX register. I think, you need to ensure the I2C configuration to be initialized properly before any I2C data transfer to happen (write/read transfer).

    Kindly follow the steps as referred in section 23.2.11.1 in the omapl138 TRM below to initialize I2c peripheral before writing data to the Tx. or reading data from Rx. :

    http://www.ti.com/lit/ug/spruh77a/spruh77a.pdf

    As per section 23.2.11.1 in the above doc., steps 1 to 8 indicates the I2C0 initialization part and then, I2C0 is taken out of reset for the read/write data transfer to happen when ICXRDY & ICRRDY flag bits are cleared appropriately which indicates its readiness state to Tx./Rx data.

    If you CSL API's to initialize I2C peripheral registers, please follow the below sequence while setting up I2C0:

    static void setup_I2C0 (void)
    {

     // Place I2C in Reset
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_IRS, DISABLE);
     
     // Configure I2C Mode (Select 7-Bit Addressing & Transfer 8 Bits)
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_XA, 7BIT);
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_BC, 8BIT);
     
     // Disable Other I2C Modes (Repeat, Loopback, Free Data, Start Byte)
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_RM, DISABLE);
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_DLB, DISABLE);
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_FDF, DISABLE);
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_STB, DISABLE);
     
     // Configure I2C Clock Operation Freq (MUST BE BETWEEN 6.7 AND 13.3 MHz)
     CSL_FINS(i2c0Regs->ICPSC, I2C_ICPSC_IPSC, DIVto12MHZ);
     
     // Configure Clock Low/High Time (20 kHz)
     CSL_FINS(i2c0Regs->ICCLKL, I2C_ICCLKL_ICCL, 294);
     CSL_FINS(i2c0Regs->ICCLKH, I2C_ICCLKH_ICCH, 294);
     
     // Disable and Clear Pending I2C Interrupts
     i2c0Regs->ICIMR = CSL_I2C_ICIMR_RESETVAL;
     i2c0Regs->ICSTR = i2c0Regs->ICSTR;
     
     // Remove I2C from Reset
     CSL_FINST(i2c0Regs->ICMDR, I2C_ICMDR_IRS, ENABLE);


    }/* setup_I2C0 */

    After I2C0 is taken out of reset, you can write/read data from the Tx/Rx. registers and thereby, ICXRDY & ICRRDY flags would be cleared appropriately to make data transfer happen with valid START & STOP conditions respectively.

    Thanks & regards,

    Sivaraj K

    -------------------------------------------------------------------------------------------------------
    Please click the Verify Answer button on this post if it answers your question.
    -------------------------------------------------------------------------------------------------------

     

  • Hello Sivaraj,


    thanks for your reply!


    The setup procedure I used is more or less exactly what you suggested (I just used other macros), I took section 23.2.11.1 of the omapl138 TRM as reference.

    To ensure that I did not overlook something I now use exactly the sequence you posted, with only one difference: the clock speed (operating clock) is set to 8 MHz and the i2c clk to 100kHz  (with pulse pause of 1:1) .
    The clock speeds are verified with a scope.

    When a wait loop

       for (waitcount = 200; waitcount; waitcount--);

    is inserted before

       //   1:  wait for bus free

    or

      //   2:  set master mode and auto stop

    the procedure is working fine.
    If inserted after step 2 it does not work.
    If waitcount is reduced to 180 it does not work.

    Thus I do not think that this is an setup-issue

    For me it seems that the bus and tx register are already indicated as free, but the i2c-module needs some time until it can accept the next transfer.

    Best regards,

    Alexander