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.

TMS320F28388D: Problems with I2C, GPIO and CPU2

Part Number: TMS320F28388D

Tool/software:

Good morning,
I would like to ask a technical question. I wanted to manage an I2C module (i2ca) from the CPU2 to read the time of a RTC. The problem is that when I debug the code, the i2c stays continuously in BUSY (bit BB of CMDR register).
The issue is that the code is the same as in another project where all the code was in CPU1, and it worked fine. Then I started to worry about the fact that the migration to CPU2 can't be done. First, I have seen that GPIOCTRREGS is not accessible from CPU2 (so you can't configure the pins from CPU2), even so, initializing the pins from CPU1 still doesn't work.
Then already, regarding the I2C, the I2CAREGS is supposed to be accessible from CPU1 and CPU2, and in fact I see that the I2C configuration registers are written correctly. However, it still does not work.
What was on my mind is the possibility that by declaring the GPIOs of the SDA and SCL signals as INPUT (GPxDIR=0), the I2CA module declared on CPU2 can change the GPIO of SDA and SCL as OUTPUT? The CPU2 certainly cannot because it cannot write to GPIOCTRLREGS but the I2C module can?????

I hope you can help me with this problem.

Best regards,
Pedro

  • Hi Pedro,

    Have you configured CPU2 to control the I2C module and GPIOs like in this thread? CCS/TMS320F28388D: Configure I2C on CPU2

    Since we know the code works fine with CPU1, the issue is most likely that the peripherals are getting improperly accessed by CPU2. In addition, you should be able to see the I2CAREGS and GPIOCTRLREGS in the Register View when connected to both CPU1 and CPU2.

    Best Regards,

    Aishwarya

  • Good morning Aishwarya,

    Thank you for your answer. Yes, for sure I did, I gave the control of the GPIO SDA and SCL to the CPU2 (GPIO_setControllerCore(X, GPIO_CORE_CPU2);) and I gave the control of the peripheral to the CPU2 as SysCtl_selectCPUForPeripheral(SYSCTL_CPUSEL7_I2C, 1, SYSCTL_CPUSEL_CPU2).

    What I have seen is that hte problem is not only attached to the CPU2, now I changed it to use it with CP1 and I get the same problem. I don't know what problem could be, I used like the same code from an old code that my partners said that used to work well but it doesn't. 

    I will show you how is the code structured:

    First: I configure the Interruptions ->

    Interrupt_register(INT_I2CA, &i2c_int1a_isr);
    Interrupt_enable(INT_I2CA);
    
    
    //DEFINITION OF THE ISR
    interrupt void i2c_int1a_isr(void)  {
    
        uint16_t IntSource, i;
    
        // Read interrupt source
        IntSource = I2caRegs.I2CISRC.all;
    
        // Interrupt source = stop condition detected
        if (IntSource == 0x0006)     {  //I2C_SCD_ISRC
            // If completed message was writing data, reset msg to write completed state
            if ( StatusRTC == WRITE_DATA_RTC)     {
                StatusRTC = RTC_WRITE_COMPLETED;
            }
            else if (StatusRTC == READY_READ_RTC)  {    // estaba escrita la direccion de comienzo de lectura y ha llegado la condicion de STOP
                // If completed message was reading RTC data, reset msg to inactive state and read data from FIFO.
                StatusRTC = RTC_LEIDO;
                for (i=0; i < 7; i++) {     // recoge los primeros 7 bytes del RTC
                    DataReadRTC[i] = I2caRegs.I2CDRR.all;
                }
            }
        }
    
        // Interrupt source = Register Access Ready
        // This interrupt is used to determine when the RTC address setup portion of the read data communication is complete.
        // Since no stop bit is commanded, this flag tells us when the message has been sent instead of the SCD flag.
        // If a NACK is received, clear the NACK bit and command a stop. Otherwise, move on to the read data portion of the communication.
        else if (IntSource == 0x0003)     { //I2C_ARDY_ISRC
            if (I2caRegs.I2CSTR.bit.NACK == 1)         {
                I2caRegs.I2CMDR.bit.STP = 1;
                I2caRegs.I2CSTR.all = 0x0002;   //I2C_CLR_NACK_BIT
            }
            else if (StatusRTC == WRITE_ADDRESS_RTC)    {
                StatusRTC = READY_READ_RTC;
            }
        }
    
        // Enable future I2C (PIE Group 8) __interrupts
    //    PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP8);
    }
    

    Then, I configure the GPIOs and the I2CA as the following (I used structures of I2caRegs changing the RAM.cmd file and adding the library f2838x_device.h)

        GPIO_setPinConfig(GPIO_104_I2CA_SDA);
        GPIO_setQualificationMode(104, GPIO_QUAL_SYNC);
        GPIO_setPadConfig(104, GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_OD | GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(104, 0);
        GPIO_setDirectionMode(104, GPIO_DIR_MODE_IN);
    
       // GPIO_setControllerCore(104, GPIO_CORE_CPU2);
    
        GPIO_setPinConfig(GPIO_33_I2CA_SCL);
        GPIO_setQualificationMode(33, GPIO_QUAL_SYNC);
        GPIO_setPadConfig(33, GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_OD | GPIO_PIN_TYPE_PULLUP);
        GPIO_writePin(33, 0);
        GPIO_setDirectionMode(33, GPIO_DIR_MODE_IN);
    
       // GPIO_setControllerCore(33, GPIO_CORE_CPU2);
       
       //I2CAinit
       
        I2caRegs.I2CSAR.all = 0x006F;     // Slave address - RTCC control code
    
        I2caRegs.I2CPSC.all = 32;         // Prescaler - need 7-12 Mhz on module clk
        I2caRegs.I2CCLKL = 10;            // NOTE: must be non zero
        I2caRegs.I2CCLKH = 5;             // NOTE: must be non zero
        I2caRegs.I2CIER.all = 0x24;       // Enable SCD & ARDY __interrupts
    
        I2caRegs.I2CMDR.all = 0x0020;     // Take I2C out of reset
                                          // Stop I2C when suspended
        I2caRegs.I2CMDR.all = 0x0400;
    
        I2caRegs.I2CFFTX.all = 0x6000;    // Enable FIFO mode and TXFIFO
        I2caRegs.I2CFFRX.all = 0x2040;    // Enable RXFIFO, clear RXFFINT,

    (I have commented the part of setControllerCore)

    Then, I would give the management of the I2CA to the CPU2 with the SysCtl_selectCPUForPeripheral(SYSCTL_CPUSEL7_I2C, 1, SYSCTL_CPUSEL_CPU2), but as now I'm seeing the problem with I2C with CPU1 too, lets forget about CPU2.

    Then I initialize the variable of StatusRTC (this code has the proposal to communicate with a RTC model MCP7940M) and I add the following function:

    StatusRTC = INACTIVE;
    
    if (StatusRTC == INACTIVE) {
                    if (WriteADDRTC() == I2C_EXITOSO) {
                        StatusRTC = WRITE_ADDRESS_RTC;
                    }
                    
                    
    //definition of WriteADDRTC()
    uint16_t WriteADDRTC(void) {
    
        // Wait until the STP bit and BB bit are cleared from any previous master communication. Clearing of STP bit by the module is delayed until after the SCD bit is set.
        // If these bits are not checked prior to initiating a new message, the I2C could get confused.
        if ((I2caRegs.I2CMDR.bit.STP == 1) || (I2caRegs.I2CSTR.bit.BB == 1))  {
            return I2C_NOT_READY_ERROR;
        }
    
        I2caRegs.I2CSAR.all = 0x006F;     // Slave address - RTCC control code
    
        // Setup number of bytes to send: only address (0)
        I2caRegs.I2CCNT = 1;
    
        // Setup data to send
        I2caRegs.I2CDXR.all = 0;    // empieza a escribir en la direccion 0
    
        // Send start as master transmitter but not STP
        I2caRegs.I2CMDR.all = 0x6620;
    
        return I2C_EXITOSO;
    }

    What I see is that the STR.BB bit is set as 1 and the I2CCNT stays at 1, so the I2C is not writting to the RTC and it should do it. I'm not seeing where is the problem with this code. The schematic of the setup with the RTC I'am using is:

    I'm sure that the setup is good because I used it with an Arduino at it worked well with I2C. The Docking Card Pins I'am using are 169 (gpio 104) for SDA and 87 (gpio33) for SCL. 

    I don't see where the problem would be happening. What I see is thatit does not write in the RTC because the CNT doesn't decrement 1 byte and the BB bit is set and never is put in 0. 

    I expect you could help me with this issue.

    Have a nice day,

    Pedro

  • Pedro,

    Thanks for describing the issue in detail, that is helpful. Can you also explain where in the code you are seeing the BB bit being set as well what other registers are being set and where? There is a lot of code attached, so honing on the issue, cause, and symptoms is key.

    Assuming you are talking about the C28x I2C and not CM I2C, quick glance at the GPIO configurations looks like it could be one of the causes of the issue. I2C is a synchronous peripheral, so there is no need to qualify it as synchronous again. In addition, for F2838x I2C, it should be push-pull configuration (though you can do open drain if needed), refer to this post: (+) SYSCONFIG: F2838x: I2C Module: Default GPIO configuration wrongly set to Open Drain

    Best Regards,

    Aishwarya