Part Number: LAUNCHXL-F28P65X
Other Parts Discussed in Thread: C2000WARE, SYSCONFIG
Tool/software:
Hi everyone,
I'm currently working on interfacing my 65x board with a GNSS module using the Serial Communication Interface (SCI). I'm encountering several issues that I'm hoping to resolve with your help. Here's a brief overview of my setup and the challenges I'm facing:
I need to reliably receive approximately 70 bytes of GNSS data from the module. The data frequency and size can vary, so I've implemented interrupts and FIFO buffers to ensure consistent data handling. Given the time-critical nature of my application, it's essential that the data remains accurate, as it affects multiple subsystems.
To manage data flow, I've enabled FIFO interrupts for reception with a threshold set at the FIFO level full. Consequently, for 70 bytes of data, the RX FIFO generates 4 interrupts to read 64 bytes. However, this leaves 6 bytes remaining in the FIFO buffer. To retrieve the last 6 bytes, I check the RX FIFO status using the API SCI_getRxFIFOStatus(SCI0_BASE).
Here are the specific issues I'm encountering:
-
ISR Issues with FIFO Status Check: The
SCI_getRxFIFOStatusfunction does not seem to work within the RX FIFO ISR. I attempted to access the FIFO status directly using(HWREGH(base_addr + SCI_O_FFRX) & SCI_FFRX_RXFFST_M) >> SCI_FFRX_RXFFST_S;, but this also fails. Is there a reason why direct hardware access wouldn't work inside the ISR, or am I missing something? -
Inconsistent RX Data: The SCI RX data I'm receiving is inconsistent; I often only receive the last 32 bytes or so of the transmitted data. This inconsistency appears to arise when I send data continuously. However, when I transmit just once, the data is accurate. I'm puzzled as to why this behavior occurs.
-
Interrupt Nesting: Is interrupt nesting enabled in the board or in C2000ware? Is there anything specific I need to do to enable nested interrupts?
I've attached relevant code snippets and the sysconfig for reference. Any insights or suggestions would be greatly appreciated!
Thank you for your help
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "c2000ware_libraries.h"
#include "stdio.h"
#define BUFFER_SIZE 70
#define CHUNK_SIZE 16
#define base_addr 0x00007210U
//
// Main
//
char txmsg[] = "$GNRMC,123456.00,A,3751.65,N,12225.55,W,0.00,180.00,230920,0.00,E,D";
char rxmsg[BUFFER_SIZE];
char *pos;
volatile uint32_t currentPos = 0;
int check = 0;
volatile uint16_t scitxcount = 0;
volatile uint16_t scirxcount = 0;
volatile uint16_t timerinterruptfreq = 0;
volatile uint32_t scirxlvl;
void buffercntl(char data);
void INT_SCI0_RX_ISR(void);
void INT_SCI0_TX_ISR(void);
void error(void);
void INT_myCPUTIMER0_ISR(void);
//void buffercntl(char data){
// uint32_t nexthead = (head+16)%BUFFER_SIZE;
// if (nexthead != tail) {
// rxmsg[msg] = data;
// head = nexthead;
// }
//}
__interrupt void INT_SCI0_RX_ISR(void){
uint32_t rxintstat = SCI_getInterruptStatus(SCI0_BASE);
switch(rxintstat){
case SCI_INT_PE:
SCI_writeCharNonBlocking(SCI1_BASE, 'P');
error();
break;
case SCI_INT_OE:
SCI_writeCharNonBlocking(SCI1_BASE, 'O');
error();
break;
case SCI_INT_FE:
SCI_writeCharNonBlocking(SCI1_BASE, 'F');
error();
break;
case SCI_INT_RXERR:
SCI_writeCharNonBlocking(SCI1_BASE, 'R');
error();
break;
default:
//error();
break;
}
//
// received data handling
//
//
uint16_t bytesToRead = CHUNK_SIZE;
if (currentPos + bytesToRead > BUFFER_SIZE) {
bytesToRead = BUFFER_SIZE - currentPos;
}
SCI_readCharArray(SCI0_BASE, (uint16_t*)&rxmsg[currentPos], bytesToRead);
currentPos += bytesToRead;
scirxlvl = (SCI_RxFIFOLevel)(HWREGH(base_addr + SCI_O_FFRX) & SCI_FFRX_RXFFST_M) >> SCI_FFRX_RXFFST_S;
if((BUFFER_SIZE-currentPos)< CHUNK_SIZE){
while(scirxlvl){
rxmsg[currentPos++] = SCI_readCharNonBlocking(SCI0_BASE);
check++;
}
}
if (currentPos >= BUFFER_SIZE) {
// SCI_writeCharArray(SCI1_BASE, (uint16_t*)rxmsg, sizeof(rxmsg));
currentPos = 0; // Reset position
}
scirxcount++;
GPIO_togglePin(myLED1_GPIO);
//overflow condition check?
SCI_clearOverflowStatus(SCI0_BASE);
SCI_clearInterruptStatus(SCI0_BASE, SCI_INT_RXFF);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
__interrupt void INT_SCI0_TX_ISR(void){
GPIO_togglePin(myLED0_GPIO);
scitxcount++;
SCI_clearInterruptStatus(SCI0_BASE, SCI_INT_TXFF);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
__interrupt void INT_myCPUTIMER0_ISR(void){ //cpu timer to simulate data transmission every 1 second
timerinterruptfreq++;
SCI_writeCharArray(SCI1_BASE,(uint16_t*)txmsg,sizeof(txmsg));
Interrupt_clearACKGroup(INT_myCPUTIMER0_INTERRUPT_ACK_GROUP);
}
void error(void)
{
asm(" ESTOP0"); // Test failed
for (;;);
}
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Disable pin locks and enable internal pull-ups.
//
Device_initGPIO();
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// PinMux and Peripheral Initialization
//
Board_init();
//
// C2000Ware Library initialization
//
C2000Ware_libraries_init();
//
// Enable Global Interrupt (INTM) and real time interrupt (DBGM)
//
EINT;
ERTM;
//SCI_writeCharArray(SCI0_BASE,(uint16_t*)txmsg,sizeof(txmsg));
while(1)
{
scirxlvl = SCI_getRxFIFOStatus(SCI0_BASE);
// sprintf(pos,"%d",(int)currentPos);
// SCI_writeCharBlockingNonFIFO(SCI1_BASE,(uint16_t)*pos);
// sprintf(buff,"%d",)
// SCI_writeCharNonBlocking(SCI1_BASE, scitxlvl);
// SCI_writeCharNonBlocking(SCI1_BASE, scirxlvl);
}
}
//
// End of File
//

How best can i implement this application so i can transmit and receive data in full duplex and still maintain reliable and consistent data.
This is still in development so any suggestions are welcome.
Thank you in advance
Ashwin Bhaskar A