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.

LAUNCHXL-F28379D: Running FreeRTOS project on F28379D launchpad

Part Number: LAUNCHXL-F28379D

Hello Community,

I am trying to run a basic FreeRTOS project (blinking an LED) on my F28379D launchpad. I have copied and included all the necessary freeRTOS files from C2000 ware freeRTOS demo for F2838x_C28x_CCS. I am using the default linker cmd file i.e. 2837xD_FLASH_lnk_CPU1.cmd in the project and not the one provided in the freeRTOS demo (2838x_FreeRTOS_FLASH_lnk_cpu1). The project compiles without error but on debugging, the task never gets executed and code enters the while loop in main(). Here is the code snippet:

///////////////////////////////////////////////////////////////code start///////////////////////////////////////////////////////////////////////////////////////

#include "driverlib.h"
#include "device.h"
#include "FreeRTOS.h"
#include "task.h"
#include<stdio.h>

#define myBoardLED0_GPIO 34

uint32_t count = 0;
void myBoardLED0_GPIO_init(){
    GPIO_setPadConfig(myBoardLED0_GPIO, GPIO_PIN_TYPE_STD);
    GPIO_setQualificationMode(myBoardLED0_GPIO, GPIO_QUAL_SYNC);
    GPIO_setDirectionMode(myBoardLED0_GPIO, GPIO_DIR_MODE_OUT);
    GPIO_setControllerCore(myBoardLED0_GPIO, GPIO_CORE_CPU1);
}

TaskHandle_t  myTask1Handle = NULL;


void myTask1(void *p)
{
    while(1)
    {
        count++;
        GPIO_togglePin(myBoardLED0_GPIO);
        vTaskDelay(1000); // 1 sec delay
    }
 }
void main(void)
{
    myBoardLED0_GPIO_init();
    xTaskCreate(myTask1,"task1", 225, (void*) 0, 1,&myTask1Handle);
    vTaskStartScheduler();

    while(1)
    {

    }
}

///////////////////////////////////////////////////////////////code end///////////////////////////////////////////////////////////////////////////////////////

It would be great if someone can tell me what am i missing here?

Thanks!




  • Hi,

    1) Your main() is missing the function calls for initializing device and interrupt related configurations. These can be found in the F2838x example

    2) In your linker file, ensure you have .freertosStaticStack and .freertosHeap sections defined, and allocated in the lower 64K RAM memory range. configAPPLICATION_ALLOCATED_HEAP would need to bet set to 1, and you would need to declare the heap in your application and place it in the .freertosHeap section. You can refer to ex4 in the F2838x demos for exact details on how this is done.

    Thanks,

    Arnav

  • Hello Arnav,

    Thanks for your prompt response!

    I've made the changes you suggested, but I'm still facing an issue. I've added a variable "value" that receives the return value from `xTaskCreate()`, which is 1, indicating the task is created. However, the task is not being scheduled by the scheduler, and `ledTaskFunction()` is not being called to toggle the LED.
    Here's a summary of what I've done:
    1. Added the variable "value" to capture the return value of `xTaskCreate()`.
    2. Confirmed that `xTaskCreate()` returns 1 (indicating success).
    Despite this, the task is not executing. Could you please help me identify what I might have done wrong or suggest any other things I should try?
    Thank you!
    -------------------- code -----------------
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    #include <stdint.h>
    
    
    #include "FreeRTOS.h"
    #include "task.h"
    #include "driverlib.h"
    #include "device.h"
    
    //typedef int16_t  BaseType_t;
    
    
    // Macro to define stack size for LED task
    //#define LED_TASK_STACK_SIZE 256
    
    // Macro to define delay (in ticks) between LED toggle
    #define BLINK_DELAY 500
    
    // Task handle for the LED task
    TaskHandle_t ledTaskHandle;
    
    static StaticTask_t xLedTaskTCB;
    static StackType_t uxLedTaskStack[ configMINIMAL_STACK_SIZE ];
    
    #pragma DATA_SECTION(uxLedTaskStack,".freertosStaticStack")
    
    
    #pragma DATA_ALIGN(uxLedTaskStack,portBYTE_ALIGNMENT)
    
    #if(configAPPLICATION_ALLOCATED_HEAP == 1)
        uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
    
        #pragma DATA_SECTION(ucHeap,".freertosHeap")
        #pragma DATA_ALIGN (ucHeap,portBYTE_ALIGNMENT)
    
    #endif
    
    // Function prototype for the LED task
    void ledTaskFunction(void *pvParameters);
    
    int count = 0;
    int count2 = 0;
    BaseType_t value=0;
    
    
    void main(void)
    {
        // Device initialization
        Device_init();
        Interrupt_initModule();
        Interrupt_initVectorTable();
        Device_initGPIO();
            DINT;
           IER = 0x0000;
           IFR = 0x0000;
    
    
    
           //
           // Initializes the PIE vector table with pointers to the shell Interrupt
           // Service Routines (ISR).
           //
           Interrupt_initVectorTable();
    
           EINT;
           ERTM;
        count = 1;
    
        // LED pin configuration
        GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(DEVICE_GPIO_PIN_LED1, GPIO_QUAL_SYNC);
        GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
        GPIO_setControllerCore(DEVICE_GPIO_PIN_LED1, GPIO_CORE_CPU1);
    
    
        // Create the LED task
        count = 3;
    
         value = xTaskCreate(ledTaskFunction, "LED Task", configMINIMAL_STACK_SIZE, NULL,(tskIDLE_PRIORITY + 1),&ledTaskHandle);
    
        if (value != pdPASS) {
            // Task creation failed, handle error (e.g., stop execution)
            count = 5;
            while(1);
        }
    
        count = 6;
    
        // Start the FreeRTOS scheduler
        vTaskStartScheduler();
    
        count = 7;
    
        // Should never reach here
        while(1);
    }
    
    // LED task function
    void ledTaskFunction(void *pvParameters)
    {
        count2 =1 ;
        while(1)
        {
            GPIO_togglePin(DEVICE_GPIO_PIN_LED1);  // Toggle LED state
            vTaskDelay(pdMS_TO_TICKS(BLINK_DELAY)); // Delay for visibility
        }
    }
    
    
    //
    // vApplicationGetIdleTaskMemory - Application must provide an implementation
    // of vApplicationGetIdleTaskMemory() to provide the memory that is used by
    // the Idle task if configUSE_STATIC_ALLOCATION is set to 1.
    //
    
    
    void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
                                        StackType_t **ppxIdleTaskStackBuffer,
                                        uint32_t *pulIdleTaskStackSize )
    {
        /* If the buffers to be provided to the Idle task are declared inside this
        function then they must be declared static - otherwise they will be allocated on
        the stack and so not exists after this function exits. */
    
        /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
        state will be stored. */
       *ppxIdleTaskTCBBuffer = &xLedTaskTCB;
    //
    //    /* Pass out the array that will be used as the Idle task's stack. */
       *ppxIdleTaskStackBuffer = uxLedTaskStack;
    //
    //    /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
    //    Note that, as the array is necessarily of type StackType_t,
    //    configMINIMAL_STACK_SIZE is specified in words, not bytes. */
    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
    }
    
    //
    // vApplicationGetTimerTaskMemory - Application must provide an implementation
    // of vApplicationGetTimerTaskMemory() to provide the memory that is used by
    // the Timer service task if both configUSE_STATIC_ALLOCATION and
    // configUSE_TIMERS are set to 1.
    //
    void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
                                         StackType_t **ppxTimerTaskStackBuffer,
                                         uint32_t *pulTimerTaskStackSize )
    {
        /* If the buffers to be provided to the Timer task are declared inside this
        function then they must be declared static - otherwise they will be allocated
        on the stack and so not exists after this function exits. */
    
        /* Pass out a pointer to the StaticTask_t structure in which the Timer
        task's state will be stored. */
    //    *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
    //
    //    /* Pass out the array that will be used as the Timer task's stack. */
    //    *ppxTimerTaskStackBuffer = uxTimerTaskStack;
    //
    //    /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
    //    Note that, as the array is necessarily of type StackType_t,
    //    configMINIMAL_STACK_SIZE is specified in words, not bytes. */
    //    *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
    }
    
    //
    // vApplicationMallocFailedHook - Hook function for catching pvPortMalloc()
    // failures
    //
    void vApplicationMallocFailedHook( void )
    {
        /* vApplicationMallocFailedHook() will only be called if
        configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
        function that will get called if a call to pvPortMalloc() fails.
        pvPortMalloc() is called internally by the kernel whenever a task, queue,
        timer or semaphore is created.  It is also called by various parts of the
        demo application.  If heap_1.c or heap_2.c are used, then the size of the
        heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
        FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
        to query the size of free heap space that remains (although it does not
        provide information on how the remaining heap might be fragmented). */
        taskDISABLE_INTERRUPTS();
        for( ;; );
    }
    
    //
    // vApplicationIdleHook - Hook function for idle task
    //
    void vApplicationIdleHook( void )
    {
        /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
        to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the idle
        task.  It is essential that code added to this hook function never attempts
        to block in any way (for example, call xQueueReceive() with a block time
        specified, or call vTaskDelay()).  If the application makes use of the
        vTaskDelete() API function (as this demo application does) then it is also
        important that vApplicationIdleHook() is permitted to return to its calling
        function, because it is the responsibility of the idle task to clean up
        memory allocated by the kernel to any task that has since been deleted. */
    }
    
    //
    // vApplicationTickHook - Hook function for tick interrupt
    //
    void vApplicationTickHook( void )
    {
        /* vApplicationTickHook() will only be called if configUSE_TICK_HOOK is set
        to 1 in FreeRTOSConfig.h.  It will be called on each iteration of the tick ISR.
        It is essential that code added to this hook function never attempts
        to block in any way. */
    }
    
    //
    // vApplicationStackOverflowHook - Checks run time stack overflow
    //
    void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
    {
    //    ( void ) pcTaskName;
    //    ( void ) pxTask;
    //
    //    /* Run time stack overflow checking is performed if
    //    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2.  This hook
    //    function is called if a stack overflow is detected. */
       taskDISABLE_INTERRUPTS();
       for( ;; );
    }
    
    
    void vMainAssertCalled( const char *pcFileName, uint32_t ulLineNumber )
    {
    volatile BaseType_t xSetToNonZeroToStepOutOfLoop = 0;
    //
     taskENTER_CRITICAL();
       while( xSetToNonZeroToStepOutOfLoop == 0 )
       {
    //        /* Use the variables to prevent compiler warnings and in an attempt to
    //        ensure they can be viewed in the debugger.  If the variables get
    //        optimised away then set copy their values to file scope or globals then
    //        view the variables they are copied to. */
            ( void ) pcFileName;
           ( void ) ulLineNumber;
      }
    }
    
    // (Additional FreeRTOS hook functions can be added here if needed)
    
    
    
    --------------- 2837x_RAM_lnk_cpu1.cmd -----------------
    
    
    MEMORY
    {
    PAGE 0 :
       /* BEGIN is used for the "boot to SARAM" bootloader mode   */
    
       BEGIN           	: origin = 0x000000, length = 0x000002
       RAMM0           	: origin = 0x000122, length = 0x0002DE
       RAMD0           	: origin = 0x00B000, length = 0x000800
       RAMLS0          	: origin = 0x008000, length = 0x000800
       RAMLS1          	: origin = 0x008800, length = 0x000800
       RAMLS2      		: origin = 0x009000, length = 0x000800
       RAMLS3      		: origin = 0x009800, length = 0x000800
       RAMLS4      		: origin = 0x00A000, length = 0x000800
       RESET           	: origin = 0x3FFFC0, length = 0x000002
    
    PAGE 1 :
    
       BOOT_RSVD       : origin = 0x000002, length = 0x000120     /* Part of M0, BOOT rom will use this for stack */
       RAMM1           : origin = 0x000400, length = 0x000400     /* on-chip RAM block M1 */
       RAMD1           : origin = 0x00B800, length = 0x000800
    
    
       RAMLS5      : origin = 0x00A800, length = 0x000800
    
       RAMGS0      : origin = 0x00C000, length = 0x001000
       RAMGS1      : origin = 0x00D000, length = 0x001000
    
       RAMLSxDxGSx : origin = 0x00E000, length = 0x008000
    
       /*RAMGS2      : origin = 0x00E000, length = 0x001000
       RAMGS3      : origin = 0x00F000, length = 0x001000
       RAMGS4      : origin = 0x010000, length = 0x001000
       RAMGS5      : origin = 0x011000, length = 0x001000
       RAMGS6      : origin = 0x012000, length = 0x001000
       RAMGS7      : origin = 0x013000, length = 0x001000
       RAMGS8      : origin = 0x014000, length = 0x001000
       RAMGS9      : origin = 0x015000, length = 0x001000
       RAMGS10     : origin = 0x016000, length = 0x001000
       RAMGS11     : origin = 0x017000, length = 0x001000
       RAMGS12     : origin = 0x018000, length = 0x001000
       RAMGS13     : origin = 0x019000, length = 0x001000
       RAMGS14     : origin = 0x01A000, length = 0x001000
       RAMGS15     : origin = 0x01B000, length = 0x001000
       */
    
       CPU2TOCPU1RAM   : origin = 0x03F800, length = 0x000400
       CPU1TOCPU2RAM   : origin = 0x03FC00, length = 0x000400
    }
    
    
    SECTIONS
    {
       codestart        : > BEGIN,     PAGE = 0
       
    #ifdef __TI_COMPILER_VERSION__
       #if __TI_COMPILER_VERSION__ >= 15009000
        .TI.ramfunc : {} > RAMM0,      PAGE = 0
       #else
       ramfuncs         : > RAMM0      PAGE = 0   
       #endif
    #endif   
       
       .text            : >> RAMLSxDxGSx,   PAGE = 1
       .cinit           : > RAMM0,     PAGE = 0
       .pinit           : > RAMM0,     PAGE = 0
       .switch          : > RAMM0,     PAGE = 0
       .reset           : > RESET,     PAGE = 0, TYPE = DSECT /* not used, */
    
       .stack           : > RAMM1,     PAGE = 1
       .ebss            : > RAMLS5,    PAGE = 1
       .econst          : > RAMLS5,    PAGE = 1
       .esysmem         : > RAMLS5,    PAGE = 1
       Filter_RegsFile  : > RAMGS0,	   PAGE = 1
    
       ramgs0           : > RAMGS0,    PAGE = 1
       ramgs1           : > RAMGS1,    PAGE = 1
       
       // FreeRTOS Static Stacks
        .freertosStaticStack :>> RAMLSxDxGSx,   PAGE = 1
        /* Prioritize RAMM0 (lower 64k), then remaining RAMLSx on PAGE 0 */
    
        // FreeRTOS Heap
        .freertosHeap  : > RAMLSxDxGSx, PAGE = 1       // Place heap on PAGE 1
    
       /* The following section definitions are required when using the IPC API Drivers */ 
        GROUP : > CPU1TOCPU2RAM, PAGE = 1 
        {
            PUTBUFFER 
            PUTWRITEIDX 
            GETREADIDX 
        }
        
        GROUP : > CPU2TOCPU1RAM, PAGE = 1
        {
            GETBUFFER :    TYPE = DSECT
            GETWRITEIDX :  TYPE = DSECT
            PUTREADIDX :   TYPE = DSECT
        }  
    
        MSGRAM_CPU1_TO_CPU2 : > CPU1TOCPU2RAM, type=NOINIT
       MSGRAM_CPU2_TO_CPU1 : > CPU2TOCPU1RAM, type=NOINIT
    
    	
    }
    
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */
    
    -----------------------------------FreeRTOSConfig.h-----------------
    
    
    #ifndef FREERTOS_CONFIG_H
    #define FREERTOS_CONFIG_H
    
    
    #define configUSE_PORT_OPTIMISED_TASK_SELECTION  0
    #define configTICK_RATE_HZ                  ( ( portTickType ) 1000 )
    #define configUSE_PREEMPTION                1
    #define configUSE_TIME_SLICING              1
    #define configMAX_PRIORITIES                16
    #define configIDLE_SHOULD_YIELD             1
    #define configUSE_16_BIT_TICKS              0 /* Only for 8 and 16-bit hardware. */
    #define configSUPPORT_STATIC_ALLOCATION         1
    #define configSUPPORT_DYNAMIC_ALLOCATION        1
    
    #define configAPPLICATION_ALLOCATED_HEAP        1
    
    #define configCPU_CLOCK_HZ                  ( ( unsigned long ) 200000000 )
    #define configMINIMAL_STACK_SIZE                ( ( uint16_t ) 256 )
    #define configMAX_TASK_NAME_LEN                 ( 12 )
    
    /* Note heap_5.c is used so this only defines the part of the heap that is in
    the first block of RAM on the LPC device.  See the initialisation of the heap
    in main.c. */
    #define configTOTAL_HEAP_SIZE                   ( ( size_t ) ( 8192 ) )
    
    
    
    
  • Hi,

    In your linker file, the stack and heap sections would need to be in the 0x0000 - 0xFFFF range. Your currently allotted RAMLSxDxGSx extends beyond this range, so that would need to be updated.

    Are you able to pause the program and see where it stops? And what is the value of "count" and "count2" at this point?

    Thanks,

    Arnav

  • Hello Arnav,
    Thank you for your suggestion. I modified 2837x_RAM_lnk_cpu1.cmd as you mentioned. I also had to do slight modifications in my FreeRTOSConfig.h to fit my code requirements ( I had enabled software timers in the config file, even though I was not using it anywhere). After these modifications, I was able to blink the LED successfully.
    However, when I switched from using 2837x_RAM_lnk_cpu1.cmd to 2837x_FLASH_lnk_cpu1.cmd, I encountered a problem. Despite modifying the memory regions and having no build errors, I received a "No source available for _system_post_cinit()" error during debugging. Can you give any insights on what can be causing this issue?

    Thanks!
  • Hi,

    Can you link your updated main.c and linker files

    Thanks,

    Arnav