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.
Tool/software:
Hey C2000 SW Team,
I have a customer evaluating the TMS320F28375D for a new platform design and they are running into issues with using basic code examples to get a simple set of tasks up and running on the LAUNCHXL-F28379D Launchpad. Please see a summary below of the expected results for the application code in addition to the actual SW code that is causing problems. Looking forward to your guidance on what the root cause of the issue could be and please let us know if you have any follow-up questions!
The basic idea was to generate code in CCS that:
We expected this to be simple but cannot get it to work.
Can you please help us to understand what it is that we are doing wrong. For example, here is the code we have:
/****************************************************************************** * File: Using the default sci_ex2_loopback_interrupts.c and overriding with new code * Title: SCIA FIFO Loopback with Interrupt + LED Blink (F28379D, DriverLib) * * Description: * - Initializes the F28379D system clock and peripherals via DriverLib. * - Configures SCIA for 8-bit data, 1 stop bit, no parity, 300 baud. * - Enables FIFO mode, triggers interrupt when 16 bytes are received. * - By default uses internal loopback. If you define EXT_LOOPBACK, * it disables internal loopback (so you'd wire TX->RX externally). * - On each interrupt, reads the RX FIFO into rdataA, blinks GPIO31 (LED), * and sets messageArrived=true. * - In main(), we toggle a second LED (GPIO34) to show we're alive * and send data out SCIA, which loops back (internally or externally). * - Both LEDs start OFF. * - Adds a 250ms delay at the beginning to show LEDs are off. * * Requirements: * 1) Link driverlib.lib (or driverlib_coff/eabi.lib if your project is COFF/EABI). * 2) Proper driverlib include paths in Project Properties > C2000 Compiler > Include Options. * 3) A valid.cmd linker file (e.g. 2837xD_flash_lnk_cpu1.cmd). * 4) #define CPU1 (or CPU2) in project properties OR let code define it here. ******************************************************************************/ // // 1) If the project hasn't defined CPU1, define it here. // #ifndef CPU1 #define CPU1 1 #endif // // 2) Include DriverLib and device headers // #include "driverlib.h" #include "device.h" // // 3) According to Google, some older DriverLib versions do not define SCI_CONFIG_LOOPBACK. // This just in case // #ifndef SCI_CONFIG_LOOPBACK #define SCI_CONFIG_LOOPBACK 0x0004U #endif // // 4) Uncomment for "external" loopback mode (no internal loopback). // That means you must physically connect SCIA TX->RX to see data echoed. // Comment it out to use internal loopback (no wiring needed). // #define EXT_LOOPBACK // // 5) FIFO / Buffer size // #define FIFO_SIZE 16 // // 6) Globals // // We'll store what we transmit (sdataA), what we receive (rdataA), and a flag // to tell main() that new data arrived. // static uint16_t sdataA[FIFO_SIZE]; // Transmit buffer static uint16_t rdataA[FIFO_SIZE]; // Receive buffer static bool messageArrived = false; // Flag to indicate data received // // 7) Forward Declarations // static void configureSCIA(void); // Function to configure SCIA static void initLEDPin(void); // Function to initialize LED pin static void initHeartbeatPin(void); // Function to initialize heartbeat pin static void blinkLED(void); // Function to blink LED static void toggleHeartbeatLED(void); // Function to toggle heartbeat LED __interrupt static void sciaRXFIFOISR(void); // SCIA RX FIFO interrupt service routine static void delay(uint32_t delay_value); // Delay function prototype // // main() // void main(void) { // A) Initialize system with driverlib. Device_init(); // Initialize device clock and peripherals // B) Initialize and unlock all GPIO Device_initGPIO(); // Initialize GPIO // C) Initialize GPIO31 (LED1) and GPIO34 (LED2) initLEDPin(); // Initialize LED1 pin initHeartbeatPin(); // Initialize LED2 pin // D) Ensure LEDs are initially OFF GPIO_writePin(31, 0); // Turn off LED1 GPIO_writePin(34, 0); // Turn off LED2 // E) Add 250ms delay to show LEDs are off delay(2000); // 250ms delay // F) Configure SCIA (pins, FIFO, loopback) configureSCIA(); // Configure SCIA // G) Clear & init interrupts, register SCIA RX ISR Interrupt_initModule(); // Reset CPU interrupt settings Interrupt_initVectorTable(); // Populate default ISR table Interrupt_register(INT_SCIA_RX, sciaRXFIFOISR); // Register SCIA RX ISR Interrupt_enable(INT_SCIA_RX); // Enable SCIA RX interrupt EINT; // Enable global interrupt ERTM; // Enable real-time debug interrupt // H) Fill transmit buffer with test data { uint16_t i; for(i = 0; i < FIFO_SIZE; i++) { sdataA[i] = i; // Fill transmit buffer with data } } // I) Main loop: repeatedly send 16 bytes out of SCIA while(1) { // Toggle heartbeat LED in main so we know CPU is alive toggleHeartbeatLED(); // Toggle heartbeat LED // Simple delay between sends { uint32_t delay_value; for(delay_value = 0; delay_value < 100000; delay_value++) { __asm(" NOP"); // Delay } } // Send 16 bytes (blocking call). If internal LB => triggers an RX interrupt. { uint16_t i; for(i = 0; i < FIFO_SIZE; i++) { SCI_writeCharBlockingFIFO(SCIA_BASE, sdataA[i]); // Send data via SCIA } } // Example usage of rdataA / messageArrived if(messageArrived) { // Just for show, read the first received byte volatile uint16_t firstByte = *rdataA; // Read received data (void)firstByte; // Do something with the received data (optional) // Acknowledge we've seen the message messageArrived = false; // Reset data received flag } } } // // configureSCIA - sets up SCIA for 300 baud, FIFO interrupt, loopback or not // static void configureSCIA(void) { // 1) Enable SCIA peripheral clock SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SCIA); // Enable SCIA clock // 2) Configure SCIA pins: On F28379D LaunchPad, GPIO_setPinConfig(GPIO_84_SCITXDA); // Configure GPIO84 as SCITXDA GPIO_setPinConfig(GPIO_85_SCIRXDA); // Configure GPIO85 as SCIRXDA // Optional: set pad config, e.g. push-pull GPIO_setPadConfig(84, GPIO_PIN_TYPE_STD); // Set pad configuration for GPIO84 GPIO_setPadConfig(85, GPIO_PIN_TYPE_STD); // Set pad configuration for GPIO85 // 3) Disable SCIA module before config, then do a software reset SCI_disableModule(SCIA_BASE); // Disable SCIA module SCI_performSoftwareReset(SCIA_BASE); // Perform software reset // 4) Configure SCIA for 8-bit data, 1 stop bit, no parity, 300 baud // As slow as it can be #ifdef EXT_LOOPBACK SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 300, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); // Configure SCIA #else SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 300, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE | SCI_CONFIG_LOOPBACK)); // Configure SCIA with loopback #endif // 5) Enable SCIA module SCI_enableModule(SCIA_BASE); // Enable SCIA module // 6) Enable FIFO, set TX=0 and RX=16 thresholds SCI_enableFIFO(SCIA_BASE); // Enable FIFO SCI_setFIFOInterruptLevel(SCIA_BASE, SCI_FIFO_TX0, SCI_FIFO_RX16); // Set FIFO interrupt levels // 7) Enable the RX FIFO interrupt SCI_enableInterrupt(SCIA_BASE, SCI_INT_RXFF); // Enable RX FIFO interrupt // 8) Reset the SCIA channels SCI_resetChannels(SCIA_BASE); // Reset SCIA channels } // // sciaRXFIFOISR - fires when 16 bytes are in RX FIFO // __interrupt static void sciaRXFIFOISR(void) { // A) Check how many bytes are waiting in the RX FIFO uint16_t rxCount = SCI_getRxFIFOStatus(SCIA_BASE); // Get RX FIFO status // B) Read them out { uint16_t i; for(i = 0; i < rxCount; i++) { rdataA[i] = SCI_readCharNonBlocking(SCIA_BASE); // Read received data } } // C) Indicate new data arrived messageArrived = true; // Set data received flag // D) Blink LED on GPIO31 to show interrupt occurred blinkLED(); // Blink LED1 // E) Clear FIFO interrupt flag AND overrun flag if set SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_RXFF | SCI_INT_RXERR); // Clear interrupt flags // F) Reset the RX FIFO to clear any remaining data SCI_resetRxFIFO(SCIA_BASE); // Reset RX FIFO // G) Acknowledge interrupt group 9 in PIE Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); // Acknowledge interrupt group } // // initLEDPin - set GPIO31 for LED usage (F28379D LaunchPad has LED1 on GPIO31). // static void initLEDPin(void) { GPIO_setMasterCore(31, GPIO_CORE_CPU1); // Set master core for GPIO31 GPIO_setPinConfig(GPIO_31_GPIO31); // Configure GPIO31 GPIO_setDirectionMode(31, GPIO_DIR_MODE_OUT); // Set GPIO31 as output GPIO_setPadConfig(31, GPIO_PIN_TYPE_STD); // Set pad configuration for GPIO31 } // // initHeartbeatPin - set GPIO34 as a second LED (LED2 on F28379D LaunchPad). // static void initHeartbeatPin(void) { GPIO_setMasterCore(34, GPIO_CORE_CPU1); // Set master core for GPIO34 GPIO_setPinConfig(GPIO_34_GPIO34); // Configure GPIO34 GPIO_setDirectionMode(34, GPIO_DIR_MODE_OUT); // Set GPIO34 as output GPIO_setPadConfig(34, GPIO_PIN_TYPE_STD); // Set pad configuration for GPIO34 } // // toggleHeartbeatLED - flips GPIO34 on/off each time it's called. // static void toggleHeartbeatLED(void) { uint16_t currentVal = GPIO_readPin(34); // Read current state of GPIO34 GPIO_writePin(34, currentVal ^ 1); // Toggle GPIO34 } // // blinkLED - turn LED (GPIO31) on briefly, then off. // static void blinkLED(void) { GPIO_writePin(31, 1); // Turn on LED1 // ~0.5 second busy-wait at 200 MHz { volatile uint32_t d; for(d = 0; d < 100000000; d++) { __asm(" NOP"); // Delay } } GPIO_writePin(31, 0); // Turn off LED1 } // // delay - creates a delay of specified milliseconds // static void delay(uint32_t delay_value) { uint32_t i; for (i = 0; i < delay_value * 20000; i++) // Adjust the multiplier for accurate timing { __asm(" NOP"); // Delay } }
-Matt Calvo
Hey Arnav,
I already pinged you over email but also wanted to reach out on this thread for my customer's awareness. We know it is currently the weekend so once you return to office on Monday can you please help to prioritize providing feedback ASAP so that we can get my customer the support they need? Feel free to let us know if you have any follow-up questions on their HW/SW setup or if anything needs further clarification.
Looking forward to your reply!
-Matt
Hi Matt,
A few notes regarding the code:
1) The method they're using to set SCI loopback is configuring the wrong bits. Use the SCI_enableLoopback API from driverlib
2) Having a big delay inside an interrupt is never recommended. It would make more sense to have that LED blink in the main loop or replace it with a single toggle. SCI_clearOverflowStatus would also need to be called at the end to avoid potential overflow related errors
3) The if() block starting at line 146 may not be entered immediately, since SCI transmission will take some time. This may take multiple iterations of the main loop to complete, which will lead to overflows. The main loop can instead wait till messageReceived is set (in a while() loop for example), then execute the block
4) For ease of use, customers can use the SysCtl_delay and DEVICE_DELAY_US APIs for inserting delays instead of creating a custom implementation
The code should work as expected once these issues are taken care of. Let me know if there are any other queries.
Regards,
Arnav
Thank you so much for taking the time to go through my customer's code and helping identify the issues to address!
I'll go ahead and pass this along to my customer and will have them comment back on this thread directly with any additional issues or follow-up questions that they have.
Best regards,
Matt