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.

TMS320F28379D: incorrect fifo occupation from SCI.TXFFST

Part Number: TMS320F28379D


Tool/software:

Hi,

I use SCI with enabled tx fifo (9600 bps). Due to design requirements I cannot use interrupts nor dma.
In order to send some log message I have a function that is called multiple times in a loop.

Inside the function I check how much space is in tx fifo and fill it up to 16 characters:

while(SciRegs->SCIFFTX.bit.TXFFST < 16 && transmit_index < data_out_length)
{
     SciRegs->SCITXBUF.all = data_out[transmit_index++];
}

The problem is that I observe random missing characters.

I prepared an experiment with logic analyser where:

  1. TXD line is observed,
  2. each write to SCITXBUF is signaled on specific gpio by state change (6th green signal below),
  3. initial contents of sent buffer is printed on another serial

The correct behaviour is that:

  • on first function call, when fifo is empty, there are 17 writes (I assume that there are 16 inside fifo and 1 in tx register) in one 'while' loop (~0,35 per one write to fifo),
  • after each character is transmitted, 'while' loop adds only one character.

In moment of error, there is missing character that was expected on TXD.
The problem is preceded by two writes to fifo, that of course results in fifo overflow - see double write to FIFO (1st vertical green marker 2xWR) (between writes there is 17 or 32us gap).
Number of writes to fifo are controlled by TXFFST in condition of the 'while' loop.

My conclusion is that reading TXFFST can result in incorrect value.

Is there a race hazard problem in SCI hardware?

Regards,

Piotr Romaniuk

 

  • Hi Piotr,

    Can you send me your SCI initializations so I can understand how it is configured in your use case?

    Best Regards,

    Allison

  • Hi Allison,

    SCI initialization is like this:

            GPIO_Setup(RX_pin);
            GPIO_Setup(DERE_pin);
    
            EALLOW;
            CpuSysRegs.PCLKCR7.all |= 1<<(SciRegs - &SciaRegs);
            EDIS;
    
            SciRegs->SCICTL1.bit.SWRESET = 0;
            SciRegs->SCIFFTX.bit.SCIRST = 0;
            SciRegs->SCIFFTX.bit.TXFIFORESET = 0;
            SciRegs->SCIFFRX.bit.RXFIFORESET = 0;
    
            SciRegs->SCICCR.all = 0x0007;      // 1 stop bit,  No loopback
                                             // No parity,8 char bits,
                                             // async mode, idle-line protocol
            SciRegs->SCICTL1.bit.TXENA = 1;
            SciRegs->SCICTL1.bit.RXENA = 1;
    
            Uint16 Baudrate_reg = CALC_BAUDRATE(baudrate);
            SciRegs->SCIHBAUD.bit.BAUD = Baudrate_reg >> 8;
            SciRegs->SCILBAUD.bit.BAUD = Baudrate_reg;
            SciRegs->SCICCR.bit.PARITYENA = 0;
            
            SciRegs->SCIFFTX.bit.SCIFFENA = 1;
    
            SciRegs->SCICTL1.bit.SWRESET = 1;
            SciRegs->SCIFFTX.bit.SCIRST = 1;
            SciRegs->SCIFFTX.bit.TXFIFORESET = 1;
            SciRegs->SCIFFRX.bit.RXFIFORESET = 1;
    
            SciRegs->SCITXBUF.all = 0xA;
    
            EALLOW;
            CpuSysRegs.PCLKCR3.all |= 1<<(ECapRegs - &ECap1Regs);
            EDIS;
    
            EALLOW;
            *(&InputXbarRegs.INPUT7SELECT + (ECapRegs - &ECap1Regs)) = RX_pin;         // Set eCAPx source to GPIO-pin
            EDIS;
    
            // Configure peripheral registers
            //
            ECapRegs->ECCTL2.bit.CONT_ONESHT = 0;   // Continuous
            ECapRegs->ECCTL2.bit.STOP_WRAP = 1;     // Stop at 2 events
            ECapRegs->ECCTL1.bit.CAP1POL = 0;       // Rising edge
            ECapRegs->ECCTL1.bit.CAP2POL = 1;       // Falling edge
            ECapRegs->ECCTL1.bit.CTRRST1 = 1;       // Reset counter after latch
            ECapRegs->ECCTL1.bit.CTRRST2 = 1;       // Reset counter after latch
            ECapRegs->ECCTL1.bit.CAPLDEN = 1;       // Enable capture units
    
            ECapRegs->ECCTL2.bit.TSCTRSTOP = 1;     // Start Counter
            ECapRegs->ECCTL2.bit.REARM = 1;         // arm one-shot
            ECapRegs->ECCTL1.bit.CAPLDEN = 1;       // Enable CAP1-CAP4 register loads
    
            Sci_words_x35 = ((float)CPU_CLK / (float)baudrate) * 3.5f * 10.0f;//3.5 times 10bits
            Sci_words_x1 = ((float)CPU_CLK / (float)baudrate) * 1.0f * 10.0f;//1.0 times 10bits
    
            while(!SciRegs->SCICTL2.bit.TXRDY);
            GPIO_Setup(TX_pin);

    Regards,

    Piotr Romaniuk

  • Hi Alison,

    I found out that I call the function from interrupt as well.
    It is not reentrant,This may be the reason.

    I post test results.

    Regards,

    Piotr Romaniuk

  • Hi Piotr, 

    Feel free to update here with findings once you complete testing.

    Best Regards,

    Allison

  • Hi Alison,

    The problem was caused by calling interrupt_task() from two contexts: main loop and interrupt.
    When interrupt appeared between TXFFST read and write to fifo, it happened that in main loop context old value remained. In interrupt fifo was filled up and after return second write was performed.

    ==== main loop ctx ====                                      ==== intr ctx ====
    while(SciRegs->SCIFFTX.bit.TXFFST < 16 && ...)
    {
        ------------------ INTERRUPT ------------------------------>
        
                                                                while(SciRegs->SCIFFTX.bit.TXFFST < 16 && ...) {
                                                                     SciRegs->SCITXBUF.all = data_out[transmit_index++];
                                                                }
        <-----------------------------------------------------------                                                            
        
         SciRegs->SCITXBUF.all = data_out[transmit_index++];
    }

    Regards,

    Piotr Romaniuk