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/LAUNCHXL-F28069M: Merging I2C & SCI

Part Number: LAUNCHXL-F28069M


Tool/software: Code Composer Studio

Hello all,

I use Launchxl-F28069m kit.

I read and write values from/to my pc with sci communication. There is a "WRITE EEPROM" button on my pc interface and when I press that, I deactivate sci, activate i2c parts to write to eeprom.

After writing to eeprom, vice versa. I deactivate i2c and reactivate sci.

But, this is not working. As I understand, SciaRegs.SCIFFRX.bit.RXFFST and I2caRegs.I2CFFRX.all are the problem. 

For sci, I used a little different version of sci_echoback, for i2c, more or less i2c_eeprom example.

If I configure switching sci - i2c event with a gpio, for example GpioDataRegs.GPADAT.bit.GPIO18, the plan works perfect. But I dont want to use a hardware switch. (Talking about If GpioDataRegs.GPADAT.bit.GPIO18 == 0 go for i2c,  if GpioDataRegs.GPADAT.bit.GPIO18 == 1 go for sci stuff.)

Normally SciaRegs.SCIFFRX.bit.RXFFST is 0. If it is 0, everything works smoothly. When I switch with WRITE EEPROM software signal from sci, SciaRegs.SCIFFRX.bit.RXFFST becomes 3. (Receive FIFO has 3 words.) Or 4.

My i2c and sci configurations are shown below :

I2C

void I2CA_Init(void)
{
        I2caRegs.I2CMDR.all     = 0x0000;
       // Initialize I2C
       I2caRegs.I2CSAR = 0x0050;        // Slave address - EEPROM control code

       // I2CCLK = SYSCLK/(I2CPSC+1)

         I2caRegs.I2CPSC.all = 8;  //6     // 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.I2CFFTX.all = 0x6000;   // Enable FIFO mode and TXFIFO
       I2caRegs.I2CFFRX.all = 0x2040;   // Enable RXFIFO, clear RXFFINT,

   return;
}

Uint16 ReadEeprom(Uint16 e2promaddress)
{
    Uint16 addresslow;
    Uint16 addresshigh;

    I2caRegs.I2CMDR.bit.IRS = 1;                // reset I2C
    while (I2caRegs.I2CSTR.bit.BB == 1);        // busy loop
    I2caRegs.I2CSTR.bit.SCD = 1;                // Clear the SCD bit (stop condition bit)
    while(I2caRegs.I2CMDR.bit.STP == 1);        // stop bit loop

    addresshigh         = e2promaddress>>8;
    addresslow          = e2promaddress;

    I2caRegs.I2CSAR     = 0x0050;

    while (I2caRegs.I2CSTR.bit.BB == 1);
    I2caRegs.I2CMDR.all = 0x2620;               // start, no stop bit, master, tx, reset I2C
    I2caRegs.I2CCNT     = 0x0002;
    I2caRegs.I2CDXR     = addresshigh;
    I2caRegs.I2CDXR     = addresslow;

    while(!I2caRegs.I2CSTR.bit.ARDY);           // all ready?

    I2caRegs.I2CMDR.all = 0x2C20;               // start, stop bit when CNT =0, master, rx, reset I2C
    I2caRegs.I2CCNT     = 1;

    if(I2caRegs.I2CSTR.bit.NACK == 1)
    {
         I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;    // 0x0002
    }
         I2caRegs.I2CMDR.bit.STP = 1;                    // stop bit when CNT=0

    while(!I2caRegs.I2CSTR.bit.SCD);                // stop bit detected?

    dataReadSample[e2promaddress] = I2caRegs.I2CDRR; // read data

    DELAY_US(100);

    return(dataReadSample[e2promaddress]);
}


void WriteEeprom(Uint16 e2promaddress, Uint16 data)
{
        Uint16 addresslow;
        Uint16 addresshigh;

        I2caRegs.I2CMDR.bit.IRS = 1;            // reset I2C

        addresshigh         = (e2promaddress>>8)&0x00FF;
        addresslow          = e2promaddress&0x00FF;
        I2caRegs.I2CSAR     = 0x0050;           // EEPROM control bits + address (A0-A2). for 24LC256, 0 1 0 1 0 A0 A1 A2

        while (I2caRegs.I2CSTR.bit.BB == 1);

        I2caRegs.I2CCNT     = 3 ;
        I2caRegs.I2CMDR.all = 0x6E20;               //start, stop, no rm, reset i2c
        I2caRegs.I2CDXR     = addresshigh;
        I2caRegs.I2CDXR     = addresslow;
      //I2caRegs.I2CDXR     = (data >> 8) & 0x00FF; // high byte data
        I2caRegs.I2CDXR     = data;                 // low byte data
        dataWriteSample[e2promaddress] = I2caRegs.I2CDXR;

        I2caRegs.I2CMDR.bit.STP = 1;                // stop bit when CNT=0

        while(!I2caRegs.I2CSTR.bit.SCD);            // stop bit detected?

        DELAY_US(5000);                             // 5ms = write cycle time of 24LC256 - based on datasheet 24LC256

    return;
}

SCI

while(SciaRegs.SCIFFRX.bit.RXFFST !=1 && GpioDataRegs.GPADAT.bit.GPIO18 == 0 && sendParameterToPc != 1)
                            {
                                //
                                // wait for XRDY =1 for empty state
                                //
                            }
void
scia_fifo_init()
{
    SciaRegs.SCIFFTX.all=0xE040;
    SciaRegs.SCIFFRX.all=0x2044;
    SciaRegs.SCIFFCT.all=0x0;
}

//###########################################################################
//
// FILE:	F2806x_Sci.c
//
// TITLE:	F2806x SCI Initialization & Support Functions.
//
//###########################################################################
// $TI Release: F2806x C/C++ Header Files and Peripheral Examples V151 $
// $Release Date: February  2, 2016 $
// $Copyright: Copyright (C) 2011-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

#include "F2806x_Device.h"     // F2806x Headerfile Include File
#include "F2806x_Examples.h"   // F2806x Examples Include File

//---------------------------------------------------------------------------
// InitSci:
//---------------------------------------------------------------------------
// This function initializes the SCI(s) to a known state.
//
void InitSci(void)
{
	// Initialize SCI-A/B:

	//tbd...

}

//---------------------------------------------------------------------------
// Example: InitSciGpio:
//---------------------------------------------------------------------------
// This function initializes GPIO pins to function as SCI pins
//
// Each GPIO pin can be configured as a GPIO pin or up to 3 different
// peripheral functional pins. By default all pins come up as GPIO
// inputs after reset.
//
// Caution:
// Only one GPIO pin should be enabled for SCITXDA/B operation.
// Only one GPIO pin shoudl be enabled for SCIRXDA/B operation.
// Comment out other unwanted lines.

void InitSciGpio()
{
   #if DSP28_SCIA
       InitSciaGpio();
   #endif // endif DSP28_SCIA
   #if DSP28_SCIB
       InitScibGpio();
   #endif // endif DSP28_SCIB
}

#if DSP28_SCIA
void InitSciaGpio()
{
   EALLOW;

/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled disabled by the user.
// This will enable the pullups for the specified pins.

	GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0;    // Enable pull-up for GPIO28 (SCIRXDA)
//	GpioCtrlRegs.GPAPUD.bit.GPIO7 = 0;     // Enable pull-up for GPIO7  (SCIRXDA)

	GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0;	   // Enable pull-up for GPIO29 (SCITXDA)
//	GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;	   // Enable pull-up for GPIO12 (SCITXDA)

/* Set qualification for selected pins to asynch only */
// Inputs are synchronized to SYSCLKOUT by default.
// This will select asynch (no qualification) for the selected pins.

	GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3;  // Asynch input GPIO28 (SCIRXDA)
//	GpioCtrlRegs.GPAQSEL1.bit.GPIO7 = 3;   // Asynch input GPIO7 (SCIRXDA)

/* Configure SCI-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SCI functional pins.

	GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1;   // Configure GPIO28 for SCIRXDA operation
//	GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 2;    // Configure GPIO7  for SCIRXDA operation

	GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1;   // Configure GPIO29 for SCITXDA operation
//	GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 2;   // Configure GPIO12 for SCITXDA operation

    EDIS;
}
#endif // endif DSP28_SCIA

#if DSP28_SCIB
void InitScibGpio()
{
   EALLOW;

/* Enable internal pull-up for the selected pins */
// Pull-ups can be enabled or disabled disabled by the user.
// This will enable the pullups for the specified pins.

	GpioCtrlRegs.GPAPUD.bit.GPIO11 = 0;    // Enable pull-up for GPIO11 (SCIRXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO15 = 0;    // Enable pull-up for GPIO15 (SCIRXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO19 = 0;    // Enable pull-up for GPIO19 (SCIRXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO23 = 0;    // Enable pull-up for GPIO23 (SCIRXDB)
//	GpioCtrlRegs.GPBPUD.bit.GPIO41 = 0;    // Enable pull-up for GPIO41 (SCIRXDB)
//	GpioCtrlRegs.GPBPUD.bit.GPIO44 = 0;    // Enable pull-up for GPIO44 (SCIRXDB)

	GpioCtrlRegs.GPAPUD.bit.GPIO9 = 0;	   // Enable pull-up for GPIO9 (SCITXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO14 = 0;	   // Enable pull-up for GPIO14 (SCITXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;	   // Enable pull-up for GPIO18 (SCITXDB)
//	GpioCtrlRegs.GPAPUD.bit.GPIO22 = 0;	   // Enable pull-up for GPIO22 (SCITXDB)
//	GpioCtrlRegs.GPBPUD.bit.GPIO40 = 0;	   // Enable pull-up for GPIO40 (SCITXDB)
//	GpioCtrlRegs.GPBPUD.bit.GPIO58 = 0;	   // Enable pull-up for GPIO58 (SCITXDB)

/* Set qualification for selected pins to asynch only */
// Inputs are synchronized to SYSCLKOUT by default.
// This will select asynch (no qualification) for the selected pins.

	GpioCtrlRegs.GPAQSEL1.bit.GPIO11 = 3;  // Asynch input GPIO11 (SCIRXDB)
//	GpioCtrlRegs.GPAQSEL1.bit.GPIO15 = 3;  // Asynch input GPIO15 (SCIRXDB)
//	GpioCtrlRegs.GPAQSEL2.bit.GPIO19 = 3;  // Asynch input GPIO19 (SCIRXDB)
//	GpioCtrlRegs.GPAQSEL2.bit.GPIO23 = 3;  // Asynch input GPIO23 (SCIRXDB)
//	GpioCtrlRegs.GPBQSEL1.bit.GPIO41 = 3;  // Asynch input GPIO41 (SCIRXDB)
//	GpioCtrlRegs.GPBQSEL1.bit.GPIO44 = 3;  // Asynch input GPIO44 (SCIRXDB)


/* Configure SCI-B pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SCI functional pins.

	GpioCtrlRegs.GPAMUX1.bit.GPIO11 = 2;   // Configure GPIO11 for SCIRXDB operation
//  GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 2;   // Configure GPIO15 for SCIRXDB operation
//	GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 2;   // Configure GPIO19 for SCIRXDB operation
//	GpioCtrlRegs.GPAMUX2.bit.GPIO23 = 3;   // Configure GPIO23 for SCIRXDB operation
//	GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2;   // Configure GPIO41 for SCIRXDB operation
//	GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2;   // Configure GPIO44 for SCIRXDB operation


	GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 2;   // Configure GPIO9 for SCITXDB operation
//	GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 2;   // Configure GPIO14 for SCITXDB operation
//	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 2;   // Configure GPIO18 for SCITXDB operation
//	GpioCtrlRegs.GPAMUX2.bit.GPIO22 = 3;   // Configure GPIO22 for SCITXDB operation
//	GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2;   // Configure GPIO40 for SCITXDB operation
//	GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2;   // Configure GPIO58 for SCITXDB operation


    EDIS;
}
#endif // endif DSP28_SCIB

//===========================================================================
// End of file.
//===========================================================================

I2caRegs.I2CMDR.all is also suspicious. 

This can be a bit detailed question so feel free to ask me any details to clarify. There should be a simple detail because with GPIO it works. (NPN. I touch GPIO with a cable connected to gnd.)

I should change my communication method with soft signals. FIFO should let me. 

P.S: I tried adding delay, it does not solve the problem.

P.S 2: Using WriteEprom causes the problem. Not ReadEeprom.

void WriteEeprom(Uint16 e2promaddress, Uint16 data)
{
        Uint16 addresslow;
        Uint16 addresshigh;

        I2caRegs.I2CMDR.bit.IRS = 1;            // reset I2C

        addresshigh         = (e2promaddress>>8)&0x00FF;
        addresslow          = e2promaddress&0x00FF;
        I2caRegs.I2CSAR     = 0x0050;           // EEPROM control bits + address (A0-A2). for 24LC256, 0 1 0 1 0 A0 A1 A2

        while (I2caRegs.I2CSTR.bit.BB == 1);

        I2caRegs.I2CCNT     = 3 ;
        I2caRegs.I2CMDR.all = 0x6E20;               //start, stop, no rm, reset i2c
        I2caRegs.I2CDXR     = addresshigh;
        I2caRegs.I2CDXR     = addresslow;
      //I2caRegs.I2CDXR     = (data >> 8) & 0x00FF; // high byte data
        I2caRegs.I2CDXR     = data;                 // low byte data
        dataWriteSample[e2promaddress] = I2caRegs.I2CDXR;

        I2caRegs.I2CMDR.bit.STP = 1;                // stop bit when CNT=0

        while(!I2caRegs.I2CSTR.bit.SCD);            // stop bit detected?

        DELAY_US(5000);                             // 5ms = write cycle time of 24LC256 - based on datasheet 24LC256

    return;
}

Thank you.

  • Troodon,

    I have not explicitly looked through your code, but have a few concerns and questions:

    How are you protecting the EEPROM during SCI activity? and vice versa, how is the UART protected during I2C activity?
    How is the I2C able to work with a push/pull transceiver or other components connected to the I2C bus? I am concerned that just switching the mux option will not yield correct results under all conditions. I would suggest incorporating a switch to physically swap what the GPIOs are connected to.

    Ignoring the HW concerns, I would like to understand your desired mechanism for switching between the modules. How are you planning to achieve this if you do not use an additional GPIO? Are there messages messages back and forth for the F2806x to detect when it needs to change mode? Is there a state machine that the connected UART can use to recognize when I2C activity is done? What do the signals look like in either mode?

    Are you so pin limited that you cannot afford two extra GPIOs in order to dedicate SCI and I2C activity? This is not a common, nor is it recommended. I am surprised that it is working even in some conditions. I highly recommend some timing characterization on the system to ensure that the Setup/hold times are satisfied under the your use case conditions.

    Thanks,
    Mark
  • Hello Mark,

    Thanks for your answer. 

    I have designed a C# interface communicating with launchxl via sci. Pc is connected to kit's mini usb. Sci is done from here.

    EEPROM is connected to GPIO32 anf GPIO33 with the circuit below.

    And this is the controller

    Briefly, I will use my interface to control my system. When I am online, I read values from ram, write to ram etc. But ram is volatile so there is a "Write To Eeprom" button that makes my parameters retentive. 

    When I press that button, with my sci interpreter protocol f28069m understands that as "writeToEepromButton".  So if I am able to use software buttons, I thought I don't need to use hardware switches etc. I am not pin limited, actually I have many unused pins but I didn't know it is not recommended. The plan is below:

    :

    for(;;)
                {
    //********************** COMMUNICATION LOOP ****************************************
    
                    if(writeToEepromButton == 1)
                    {
                        Comparator(Uint16 whatToCheck, Uint16 indexNum, Uint16 firstScan); //i2c eeprom value comparison. if the value is not equal, write.
    firstScanOver = 1; } //********************** COMMUNICATION LOOP **************************************** if(writeToEepromButton == 0) { // // Wait for inc character // while(SciaRegs.SCIFFRX.bit.RXFFST !=1 && writeToEepromButton == 0 && sendParameterToPc != 1) { // // wait for XRDY =1 for empty state // } // // Get character // RxChar = SciaRegs.SCIRXBUF.all; sciInterpreter(); LoopCount++; } //****************************** CONTROL LOOP ***************************************************** processControl(); }

    Comparator(Uint16 whatToCheck, Uint16 indexNum, Uint16 firstScan)
    {
    Buffer1 = whatToCheck;
    if (Buffer1 != Buffer2)
    {
    valueChanged=1;
    }
    Buffer2 = whatToCheck;
    
    
    
    /*if (valueChanged==1 && firstScan == 1)
    {
    
    
    }*/
    
    writeToEeprom();
    writeToEepromButton=0;
    
    }

    Desired mechanism for switching between the modules is like that. System normally on sci mode. Waits for character series and understands them as commends. I press the "write eeprom" button, sci mode stops (but not fifo configuration), system does not wait for command but does the other processes. When the process finishes, sci mode starts again and waits for new commands.

    I just disable and enable sci, i2c or other processes from the software. I am not protecting the EEPROM during SCI activity or vice versa with hardware. But GPIO mux probably protects as you mentioned. Aren't sci and i2c different channels?  

    "? Are there messages messages back and forth for the F2806x to detect when it needs to change mode? "

    Yes

    "Is there a state machine that the connected UART can use to recognize when I2C activity is done? "

    No. Not a state machine feedback to recognize.

    SCI is being done from "mini usb" and i2c is from GPIO32 and GPIO33. Are they using the same UART line? Sorry for lack of my hardware knowledge.

    So I definitely should incorporate a switch to physically swap what the GPIOs are connected to? 

  • I misunderstood your original intent. I had thought you were using I2C and SCI on the SAME pins. This was my mistake. For the issue at hand, you can ignore my entire original post :) SCI is using GPIO28 and GPIO29, or GPIO15 and GPIO58 depending on JP7 and JP6 configurations. SCI is then routed through the XDS110 v2 debug probe to the PC through USB. I2C is using GPIO32 and GPIO33. You mention a lack of hardware knowledge but have the full Schematic and your code to verify with. This is really step 1 of working with HW in embedded systems.

    Really, this appears to be a program flow issue.
    Normally SciaRegs.SCIFFRX.bit.RXFFST is 0. If it is 0, everything works smoothly. When I switch with WRITE EEPROM software signal from sci, SciaRegs.SCIFFRX.bit.RXFFST becomes 3. (Receive FIFO has 3 words.) Or 4.

    This is telling me that the UART is receiving some characters while you are off doing I2C activity. I recommend observing on the scope during your different program phases to ensure that no stray messages are being transferred. What data is in the SCI FIFO? is it a message that you might expect the PC to send? can you prevent the PC application from transmitting additional data after clicking the "eeprom write" command?

    This device is fully capable of doing what you are trying to accomplish, and I have done something similar myself. It sounds like you are not quite sure all of the messages that are being sent around. grab your scope and start observing every interaction!

    -Mark
  • When I check with scope, I saw an unwanted character that makes SciaRegs.SCIFFRX.bit.RXFFST 4. Then I realized a mistake at my sci protocol algorithm.
    Now everything is working smoothly. It is awesome that Launchxl-f28069m is capable of changing communication type via software, without any hardware switch. Now I have several plans about this.

    Thank you! :)