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.

SCI RX Interrupt issues -- previously working code no longer functions

Hi, I have a rather odd situation. I'm working on getting comms between a PC and a F28377D using the SCI, and a while ago built a quick test bench just to ensure that the MCU could send and receive values in an interrupt driven manner. The idea was to just regularly push incremented characters (A through Z) and upon receipt of a character send "You sent: " with the received character. This was working, and I moved on to more advanced behavior. However, the RX interrupt (and in fact most of the entire RX FIFO) has ceased to operate correctly -- upon starting, the RX interrupt will fire twice in rapid succession, and then no more. The register indicates anywhere from 0 to 3 characters in the FIFO (seems not to be deterministic), but the value "received" is always 0h. If I send data to the MCU, I can see the RX LED blinking with each keypress, but the interrupt never fires and checking the RX register shows no data (again just 0h).

Here's the odd thing: I branched from a previous commit  (the basic testbench) in Git to verify I understood how everything was working, and it no longer works. I see the same firing of the RX interrupt twice and then no more, and no data being received in the FIFO. Nothing in the old code has changed. This been tested across 2 separate boards in both Windows 10 and Linux Mint, and with several USB cables, and the behavior is the same across all configurations. I am using PuTTY on both platforms.

Code for the basic testbench is as follows (warts and all):

#include "F28x_Project.h"     // Device Headerfile and Examples Include File
#include "77D_sci.h"		  // Device specific SCI functions

#define CPU_FREQ    60E6
#define LSPCLK_FREQ CPU_FREQ/4
#define SCI_FREQ    100E3
#define SCI_PRD     (LSPCLK_FREQ/(SCI_FREQ*8))-1

// Prototype statements for functions found within this file.
interrupt void sciaTxFifoIsr(void);
interrupt void sciaRxFifoIsr(void);
__interrupt void cpu_timer0_isr(void);
void scia_fifo_init(void);
void error(void);
//void scia_xmit(int a);
//void scia_msg(char * msg);

// Global variables
Uint16 ReceivedChar; // Used for checking the received data

int RXRCV_flag = 0;
int TXRDY_flag = 0;

void main(void)
{
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
   InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
   InitGpio();

//  Init the pins for the SCI-A port.
//  GPIO_SetupPinMux() - Sets the GPxMUX1/2 and GPyMUX1/2 register bits
//  GPIO_SetupPinOptions() - Sets the direction and configuration of the GPIOS
// These functions are found in the F2837xD_Gpio.c file.
   GPIO_SetupPinMux(28, GPIO_MUX_CPU1, 1);
   GPIO_SetupPinOptions(28, GPIO_INPUT, GPIO_PUSHPULL);
   GPIO_SetupPinMux(29, GPIO_MUX_CPU1, 1);
   GPIO_SetupPinOptions(29, GPIO_OUTPUT, GPIO_ASYNC);

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
   EALLOW;  // This is needed to write to EALLOW protected registers
   PieVectTable.SCIA_RX_INT = &sciaRxFifoIsr;
   PieVectTable.SCIA_TX_INT = &sciaTxFifoIsr;
   PieVectTable.TIMER0_INT = &cpu_timer0_isr;//assign ISR's, add more if needed
   EDIS;   // This is needed to disable write to EALLOW protected registers

//Initialize and Configure the timers
	InitCpuTimers();
	ConfigCpuTimer(&CpuTimer0, 200, 400000); //initial configuration
	CpuTimer0Regs.TCR.all = 0x4000; //write only instruction to set TSS bit = 0

	PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
	DINT;

// Step 4. Initialize the Device Peripherals:
   scia_fifo_init();  // Init SCI-A

// Step 5. User specific code, enable interrupts:


   //ReceivedChar = sdataA[0];
// Enable interrupts required for this example
   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
   PieCtrlRegs.PIEIER9.bit.INTx1=1;     // PIE Group 9, INT1; corresponds to SCIA_RX
   PieCtrlRegs.PIEIER9.bit.INTx2=1;     // PIE Group 9, INT2; corresponds to SCIA_TX
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;   // Enable TINT0 in the PIE, group 1 interrupt 7
   //IER = 0x101; // Enable CPU INT
   IER |= 0x0101; //enable cpu int1 which is connected to cpu timer 0
   EINT;

// Step 6. IDLE loop. Just sit and loop forever (optional):
   for(;;);

}

And the ISR's are as follows:

interrupt void sciaTxFifoIsr(void)
{
	if(RXRCV_flag == 1){
		scia_msg("You sent: \0");
		scia_xmit(ReceivedChar);
		scia_msg("\r\n\0");
		RXRCV_flag = 0;
		PieCtrlRegs.PIEACK.all|=PIEACK_GROUP9;      // Issue PIE ACK
	}
	else{
		TXRDY_flag = 1;
	}

	SciaRegs.SCIFFTX.bit.TXFFINTCLR=1;  // Clear SCI Interrupt flag
	PieCtrlRegs.PIEACK.all|=PIEACK_GROUP9;      // Issue PIE ACK
}

interrupt void sciaRxFifoIsr(void)
{
	ReceivedChar = 0;
	ReceivedChar = SciaRegs.SCIRXBUF.bit.SAR;  // Read data
	//ReceivedChar = SciaRegs.SCIRXBUF.all;
	RXRCV_flag = 1;

    SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1;   // Clear Overflow flag
    SciaRegs.SCIFFRX.bit.RXFFINTCLR=1;   // Clear Interrupt flag

    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP9;       // Issue PIE ack
}



__interrupt void cpu_timer0_isr(void){
	CpuTimer0.InterruptCount++;

	static Uint16 count = 0x41; //effectively "A"

	if(TXRDY_flag == 1){
		scia_xmit(count);
		scia_msg("\r\n\0");
		TXRDY_flag = 0;
		if(count >= 0x5A){
			count = 0x41;
		}
		else{
			count++;
		}
	}

	// Acknowledge this interrupt to receive more interrupts from group 1
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

My FIFO declaration function is as follows:

void scia_fifo_init()
{
   SciaRegs.SCICCR.all =0x0007;   // 1 stop bit,  No loopback
                                  // No parity,8 char bits,
                                  // async mode, idle-line protocol
   SciaRegs.SCICTL1.all =0x0003;  // enable TX, RX, internal SCICLK,
                                  // Disable RX ERR, SLEEP, TXWAKE
   SciaRegs.SCICTL1.bit.RXERRINTENA = 1; // Enable RX interrupts
   SciaRegs.SCICTL2.bit.TXINTENA =1; //SCITXBUF interrupt enable
   SciaRegs.SCICTL2.bit.RXBKINTENA =1; //Receiver-buffer/break interrupt enable
   /*
    * Baud rate is determined as follows:
    * BRR = (SCIHBAUD << 8) && SCILBAUD
    * Baud = LSPCLK / ((BRR+1)*8)
    * LSPCLK should be 50MHz by default (200MHz/4)
    * If BRR == 0, then Baud = LSPCLK/16 (or 3,125,000 by default)
    */
   SciaRegs.SCIHBAUD.all = 0x0002;
   SciaRegs.SCILBAUD.all = 0x008B;
   //SciaRegs.SCIHBAUD.all = 0x0000;
   //SciaRegs.SCILBAUD.all = 0x0000;
   SciaRegs.SCICCR.bit.LOOPBKENA = 0; // disable loop back
   SciaRegs.SCIFFTX.all=0xC022; //enable+rst fifo, sets TX FIFO interrupt level to 2, enables TX interrupt
   SciaRegs.SCIFFRX.all=0x0021; //set RX FIFO interrupt level to 1, enables RX interrupt
   SciaRegs.SCIFFCT.all=0x00;

   SciaRegs.SCICTL1.all =0x0023;     // Relinquish SCI from Reset
   SciaRegs.SCIFFTX.bit.TXFIFORESET=1;
   SciaRegs.SCIFFRX.bit.RXFIFORESET=1;

}

The entire repo is hosted here: https://github.com/silk2390/sci_testbench_alt I'm currently working at the "Actual portability testing and baud update" commit, and the only change I made was to set the baud rate to 9600 instead of the 3.125M it was at (I suspected the high rate may have been the issue). Please let me know if I can do anything to clarify.

  • Eric,

    It sounds like you've done some good debug around the hardware and software. When using your basic code can you ensure that any files that might not be included in your Git repository pull. For example maybe you didn't save your putty setup file, verify that the putty setup has not changed(baud rate, parity, stop bits, com port etc.).

    The F28377D's SCI module has some error flags in the SCIRXST register, have you checked these flags(RX ERROR, BRKDT, FE, OE, and PE)? The description of these bits can be found in section 19.14.2.6 of the F28377D TRM.

    Have you debugged why the ISR isn't firing? Check that the flags have been cleared correctly. Check the Vector table addresses...etc.

    Finally don't trust your GIT pull 100%, its possible you may have made a small change before pushing that broke your code.(I've personally done this, multiple times)

    Regards,
    Cody

  • I reverted even an additional step back (should be the same functionality, just some changes in a few header files related to the functionality here), and its presenting the same issue so I don't believe it is an issue with a commit mistake.

    I checked and my PuTTY settings are as follows: COM4 (confirmed on device manager, obviously in Windows), 9600 baud rate, 8 data bits, 1 stop bit, no parity, and XON/XOFF flow control. This matches the initialization in sci_fifo_init() as far as I can tell (please correct me if I'm missing something!).

    Inspecting SciaRegs, it appears that the SCIRXBUF.bit.SCIFFFE (FIFO framing error) bit is being set, even though I haven't sent any characters yet. Additionally, if I allow the two interrupts to occur, then pause and observe the registers again, SCIRXBUF will show data in the SAR field (a value of 16?) but SCIFFRX.bit.RXFFST indicates a value of 0.

    Any idea?

    P.S. I think the technical manual has a typo, the entry about the framing error and parity error seem to be swapped on page 2035.

  • Eric,

    I'm not sure why you are getting a framing error, if you reset the SCI module after receiving the error does it function normally or does another error flag appear? If you get repeated framing errors you probably have your configuration wrong, if it functions normally after the reset it maybe some sort of initialization windows or putty is transmitting that is causing the first error. Lets see what happens first then we can draw conclusions.

    Thanks for pointing out the typographical error!!! I have submitted for it to be corrected!

    Regards,
    Cody

  • Hey, sorry for the late reply!  Had a busy week and then went on Thanksgiving break (actually working while still pretty stuffed from dinner tonight haha). It would appear that resetting the SCI module and its FIFO's using the following code doesn't clear the framing bit. Even when the code first starts up, that framing error bit is set to 1.

    //Active Low resets -- set to 0, and then to 1
    SciaRegs.SCIFFTX.bit.TXFIFORESET=0;
    SciaRegs.SCIFFRX.bit.RXFIFORESET=0;
    SciaRegs.SCICTL1.bit.SWRESET = 0;
    
    SciaRegs.SCIFFTX.bit.TXFIFORESET=1;
    SciaRegs.SCIFFRX.bit.RXFIFORESET=1;
    SciaRegs.SCICTL1.bit.SWRESET = 1;

    I don't see any other way to clear the framing error bit in the reference manual?

    It also appears that if I reset the SCI using the above code after the two "You sent: " messages, it just repeats the behavior.

  • Eric,

    Are you sure that the framing error bit was not reset, is it possible that your are receiving another framing error immediately after the software reset? Can you observe the logic level of the bus? Maybe something is pulling the bus low, if the bus stays low for too long a framing error will occur. Finally when setting up PuTTY go to Connection->Serial and make sure you have the correct configuration.

    Hope this helps!
    Cody

  • So I got it figured out -- A:SW1 on the control card wasn't set correctly. Somehow, across all my devices, the second switch (ISO UART comm enable) was, at some point, set to off. Gremlins, maybe? The control card information guide indicates that this should entirely disable all UART comms, but instead it appears that it only disables them in one direction. Didn't think to check this because I knew it was supposed to be a full enable or disable, but apparently it isn't.

    Framing error issue went away as well, and everything is back to normal. Thanks for all your help, though!

  • OK, Great! I'm going to go ahead and close this post.

    Regards,
    Cody