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.

CC2642R: Task synchronization

Part Number: CC2642R

Hello, 
My application is based on project_zero example and has two additional tasks Task_A and Task_B. These tasks should be able to exchange messages and also send/receive messages to/from BLE appTask (not to BLE Stack). I understand that appTask uses ICall interface to exchange messages with BLE Stack. 
1. Should Task_A and Task_B use ICall to talk with appTask? If yes, what should be done to enable this iICall for Task_A and Task_B?
2. Which events should be used? Should it be unique event for each one of target task?
3. Is Message Queue should be defined for each one of  these tasks or all of them use the same queue?
4. Is there any example of communication and synchronization of application tasks?

Thanks,

    Yakov

  • Hi Yakov,

    1. No that is not necessary.
    2-4. The communication is up to you. I'd suggest using Queue and Event from RTOS, one Event and one Queue instance per task A and B. Make a function in each task's compilation unit that accepts payload and puts this on the queue for that task, and posts to that tasks event.

    An example is how project_zero and simple_peripheral send messages to themselves from the callbacks. Those callbacks are in stack/hwi context, and its the same situation you will be in, except the calling context would be task A, B or C. Note: Make sure that you construct the event and queue objects before calling BIOS_start(), for example in a XYZ_createTask() helper function.

    Best regards,
    Aslak
  • Hello Aslak,
    Thank you for your answer!  I will follow your recommendations but want to clarify several details
    1.  I see that  project_zero and simple_peripheral send messages by function like SimplePeripheral_enqueueMsg and this function uses ICall_malloc Other functions of message processing use ICall_free, ICall_freeMsg, ICall_allocMsg. Should I use these ICall_*** functions to allocate and free memory in my tasks?

    2. You wrote that queue constructions should be done before BIOS_start() in Task creation function. But queue construction in ProjectZero is done in function ProjectZero_init after calling ICall_registerApp(&selfEntity, &syncEvent).   
    ProjectZero_init is called from ProjectZero_taskFxn(), not from ProjectZero_createTask().

    Is it OK to construct  queues of my tasks before calling ProjectZero_init?
    Thanks,
       Yakov
       
        



  • Hi Yakov,

    The default config on CC2642 BLE projects is such that you might as well use malloc/free or the RTOS Memory_alloc. They go to the same heap manager depending on which is configured. The ICall_xx path is perhaps more performant, or that is at least the intention. _alloc|freeMsg is reserved for messages from the BLE stack, don't use this.

    Yes, but this is fine since the project zero task doesn't communicate with any other tasks than itself, and the stack isn't made aware of it for callback purposes until after queue/event creation.

    When you have several tasks, one of them will necessarily start executing before the others, and if that task tries to access the not-yet-constructed queues and events in the other tasks you will have a bad time.

    Best regards,
    Aslak
  • Hello Aslak,
    I try to add new task to ProjectZero but get crash.

    1. ProjectZero modifications:
       - Queue_construct(&appMsgQueue, NULL) and  appMsgQueueHandle = Queue_handle(&appMsgQueue); are moved from ProjectZero_init to ProjectZero_createTask

    2. New task and queue are created:

    2a: Creation

    void SensorsManager_createTask(void)
    {
        Task_Params SensorsManagerTaskParams;

        // Configure task
        Task_Params_init(&SensorsManagerTaskParams);
        SensorsManagerTaskParams.stack = SensorsManagerTaskStack;
        SensorsManagerTaskParams.stackSize = SENSORS_MANAGER_TASK_STACK_SIZE; // 2048
        SensorsManagerTaskParams.priority = SENSORS_MANAGER_TASK_PRIORITY; // 1

        Task_construct(&SensorsManagerTask, SensorsManager_taskFxn, &SensorsManagerTaskParams, NULL);

        Queue_construct(&SensorsMsgQueue, NULL);
        SensorsMsgQueueHandle = Queue_handle(&SensorsMsgQueue);
    }

    2b.  Task entry point 

    static void SensorsManager_taskFxn(UArg a0, UArg a1)
    {
       // Initialize application
        SensorsManager_init();

        // Application main loop
        for(;; )
         { .........

    3. Task creation is called in main.c just before BIOS_start:

       ProjectZero_createTask();

       SensorsManager_createTask();

        BIOS_start();

        return(0);

    -------------

    When the system is running, abort is called

    /****************************************************************************/
    /* ABORT - ABNORMAL PROGRAM TERMINATION. CURRENTLY JUST HALTS EXECUTION. */
    /****************************************************************************/
    __attribute__((section(".text:abort")))
    void abort(void)
    {

    -------------

    I put 4 break points:
        1. At BIOS_start() in main.c - always called
            1a. Task_SupportProxy_swap in Task_startCore in Tasks.c - always called.  Any debugger step from this point cause abort 

       2. At  SensorsManager_init() in  SensorsManager_taskFxn -  not called
       3. At  ProjectZero_init() in  ProjectZero_taskFxn                   -  not called

    ---------------

    If   SensorsManager task is compiled but not activated  (SensorsManager_createTask() is not called from main.c)  the system is working properly

    ==============



    What is the reason of this crash? How can I debug it?

    Is there any settings that should be done before adding new task to the system?

    Thanks,
       Yakov
       



  • Hi Yakov,

    Sorry for not following up. I got unassigned during a forum reorganization.

    It's good to see that you aren't afraid of breakpoints. Have you had a chance to look at the debugging guide in our Software Developer's Guide?
    Please see dev.ti.com/.../

    You could, and should, try to use the ROV in either CCS or IAR, and use the BIOS -> Scan for errors.. option. And have a look at the Task->Detailed view as well.

    There should be two build configurations for the project: FlashROM_Release and FlashROM_Debug. The debug alternative uses an RTOS config file that should add more helpful debugging and error checking features, at the cost of some Flash space. In CCS right click -> Build Configurations -> Set Active.

    Does this work fine when you don't add the extra task?

    If I were to guess, there is an issue with memory. Just adding a task shouldn't crash. But when you assing 2kb to that new task's stack, there could possibly be insufficient memory to dynamically allocate memory for the BLE Stack's task (ICall_fxn). Have you tried a lower number?

    Best regards,
    Aslak
  • Hello Aslak,

    I did clean copy of project_zero and compiled it.   Result is OK

    After that I add my code (see below) to project_zero.c  with stack size 200 and w/o queue creation. 

    SensorsManager_createTask();   is called in main.c just   after ProjectZero_createTask();

    Result is "Abort"

    What can be a reason?

    Regards,  Yakov

    //----------------------------------------------

    #define SENSORS_MANAGER_TASK_PRIORITY 1
    #define SENSORS_MANAGER_TASK_STACK_SIZE 200 // 2048
    #define SENSORS_MANAGER_MSG_EVT Event_Id_17


    // Task configuration
    Task_Struct SensorsManagerTask;
    #if defined __TI_COMPILER_VERSION__
         #pragma DATA_ALIGN(SensorsManagerTaskStack, 8)
    #else
        #pragma data_alignment=8
    #endif

    uint8_t SensorsManagerTaskStack[SENSORS_MANAGER_TASK_STACK_SIZE];


    static Event_Handle SensorsEvent;

    static void SensorsManager_taskFxn(UArg a0, UArg a1);

    void SensorsManager_createTask(void)
    {
         Task_Params SensorsManagerTaskParams;

         // Configure task
         Task_Params_init(&SensorsManagerTaskParams);
        SensorsManagerTaskParams.stack = SensorsManagerTaskStack;
        SensorsManagerTaskParams.stackSize = SENSORS_MANAGER_TASK_STACK_SIZE; // 200
        SensorsManagerTaskParams.priority = SENSORS_MANAGER_TASK_PRIORITY; // 1

        Task_construct(&SensorsManagerTask, SensorsManager_taskFxn, &SensorsManagerTaskParams, NULL);

    }


    static void SensorsManager_taskFxn(UArg a0, UArg a1)
    {
        for(;; )
        {
            uint32_t events;

            events = Event_pend(SensorsEvent, Event_Id_NONE, SENSORS_MANAGER_MSG_EVT, 5000);

           Log_info0("-> Sensor Manager Task");
        }
    }

    //----------------------------------------------

  • Additional information:

    "Abort" happened when Hwi_excHandler is called.

    At this moment usually ICall_taskEntry is running (once I saw that SensorsManager task was marked as "preempted" and two other "blocked")

    See attached screenshot

  • Hi,

    Sorry it took a while. I used your code and could replicate your issue. You have forgotten to actually make an Event object.

    //#include <xdc/runtime/Log.h> // Comment this in to use xdc.runtime.Log
    #include <ti/common/cc26xx/uartlog/UartLog.h>  // Comment out if using xdc Log
    
    // ..
    
    #define SENSORS_MANAGER_TASK_STACK_SIZE 800 // In my test, it used 400 by doing nothing. But 2048 is fair on CC2642, I thought it was CC2640R2 originally.
    
    // ...
    
    Event_Struct sensorsEventStruct; // You need an actual object for the Event
    Event_Handle SensorsEvent;       // This is just a handle.. This needs to be non-static if you wish to send events from other .c files
    
    // ..
    
    void SensorsManager_createTask(void)
    {
    // ..
         Event_construct(&sensorsEventStruct, NULL);         // Initialize event object
         SensorsEvent = Event_handle(&sensorsEventStruct);   // Store handle in variable