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.

RTOS/CC2642R: debugging problem by adding a task to the sample project (ble5_simple_peripheral_cc26x2r1lp_app)

Part Number: CC2642R


Tool/software: TI-RTOS

Bonjour, 

I started a project from the example (ble5_simple_peripheral_cc26x2r1lp_app), it works well and I can debug. But as soon as I add an extra task, I can debug once, after which the project will not run anymore. without the debug mode, the program always runs.

I tried several things (ICall max entities and tasks, heap size) but without success.

when I debug, I arrive regularly in the while(j) of ICall_abort() function

you will find the project as an attachment.

ble5_simple_peripheral_cc26x2r1lp_stack_library.zip

  • Hello Sarah,

    I'd first like to clarify a few things. Can you please identify which version of the SDK you are getting the example from?

    Also, You mention you have tried modifying ICall max entities. I believe you were on the right track! Can you take a look at this link to the User's Guide.

    This will go over the steps needed to add an ICAll Task. I think this will be of great help!

    Best,

    Kris

  • Hello, 

    thanks for the links, I use the SDK 2.30.00.34.

    I defined the following symbols:
    APP: ICALL_MAX_NUM_TASKS=4 and ICALL_MAX_NUM_ENTITIES=8
    STACK: OSAL_MAX_NUM_PROXY_TASKS=4

    some code part:

    #define TASKUARTSTACKSIZE 1000

    // Internal Events for RTOS application
    #define SP_ICALL_EVT ICALL_MSG_EVENT_ID // Event_Id_31
    #define SP_QUEUE_EVT UTIL_QUEUE_EVENT_ID // Event_Id_30

    // Bitwise OR of all RTOS events to pend on
    #define SP_ALL_EVENTS (SP_ICALL_EVT | \
    SP_QUEUE_EVT)

    Void Task2CreateTask(void){

    Task_Params taskParams;

    /* Construct heartBeat Task thread */
    Task_Params_init(&taskParams);
    taskParams.arg0 = 1000 / Clock_tickPeriod;
    taskParams.stackSize = TASKUARTSTACKSIZE;
    taskParams.stack = &taskUartStack;
    Task_construct(&taskuartStruct, (Task_FuncPtr)uartManager_taskFxn, &taskParams, NULL);

    }

    void task2_init(void)
    {
    ICall_registerApp(&selfEntity, &syncEvent);

    }

    Void uartManager_taskFxn(UArg arg0, UArg arg1)

    {

    unsigned int ledPinValue;

    task2_init();
    // dataManagerInit();
    isInit = true;

    for (;;)
    {

    uint32_t events;

    // Waits for an event to be posted associated with the calling thread.
    // Note that an event associated with a thread is posted when a
    // message is queued to the message receive queue of the thread
    events = Event_pend(syncEvent, Event_Id_NONE, SP_ALL_EVENTS,
    ICALL_TIMEOUT_FOREVER);

    if(events){

    // dataManagerTaskFxn();//run periodic task

    /* Toggle LED */
    //

    }

    }

    }

    I still have the problem

  • Sarah,

    I've set up a simple example based on SDK 2.40.00.81. Please see this thread if you have not already about this SDK release. If you do not have the hardware to test this the code should still work in the 2.30 SDK.

    Here are two files second_task.c and second_task.h

    /*
     * second_task.c
     *
     *  Created on: Jan 31, 2019
     *      Author: a0226836
     */
    
    #include <ti/sysbios/knl/Task.h>
    
    #include <icall.h>
    #include "util.h"
    #include "comdef.h"
    
    
    typedef uint8_t status_t;
    
    static void SecondTask_taskFxn(UArg a0, UArg a1);
    static void SecondTask_init(void);
    static void SecondTask_clockHandler(UArg arg);
    static status_t SecondTask_enqueueMsg(uint8_t event, void *pData);
    
    
    
    
    #define PERIODIC_EVT                      0
    
    
    // Internal Events for RTOS application
    #define QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30
    
    // Bitwise OR of all RTOS events to pend on
    #define ALL_EVENTS                        (QUEUE_EVT)
    
    
    
    // How often to perform periodic event (in ms)
    #define PERIODIC_EVT_PERIOD               5000
    
    
    
    // App event passed from stack modules. This type is defined by the application
    // since it can queue events to itself however it wants.
    typedef struct
    {
      uint8_t event;                // event type
      void    *pData;               // pointer to message
    } stEvt_t;
    
    // Entity ID globally used to check for source and/or destination of messages
    static ICall_EntityID selfEntity;
    // Event globally used to post local events and pend on system and
    // local events.
    static ICall_SyncHandle syncEvent;
    
    // Queue object used for app messages
    static Queue_Struct appMsgQueue;
    static Queue_Handle appMsgQueueHandle;
    
    // Clock instance for internal periodic events.
    static Clock_Struct clkPeriodic;
    
    static volatile uint16_t periodicCounter = 0;
    
    Task_Struct task;
    uint8_t taskStack[1024];
    
    
    
    
    
    
    
    
    void SecondTask_createTask(void)
    {
      Task_Params taskParams;
    
      // Configure task
      Task_Params_init(&taskParams);
      taskParams.stack = taskStack;
      taskParams.stackSize = 1024;
      taskParams.priority = 1;
    
      Task_construct(&task, SecondTask_taskFxn, &taskParams, NULL);
    }
    
    
    
    
    static void SecondTask_taskFxn(UArg a0, UArg a1)
    {
      // Initialize application
        SecondTask_init();
    
      // Application main loop
      for (;;)
      {
        uint32_t events;
    
        // Waits for an event to be posted associated with the calling thread.
        // Note that an event associated with a thread is posted when a
        // message is queued to the message receive queue of the thread
        events = Event_pend(syncEvent, Event_Id_NONE, ALL_EVENTS,
                            ICALL_TIMEOUT_FOREVER);
    
        if (events)
        {
          // If RTOS queue is not empty, process app message.
          if (events & QUEUE_EVT)
          {
            while (!Queue_empty(appMsgQueueHandle))
            {
              stEvt_t *pMsg = (stEvt_t *)Util_dequeueMsg(appMsgQueueHandle);
              if (pMsg)
              {
                    switch (pMsg->event)
                    {
                      case PERIODIC_EVT:
                          periodicCounter++;
    
    
                        break;
    
                      default:
                        // Do nothing.
                        break;
                    }
    
                // Free the space from the message.
                ICall_free(pMsg);
              }
            }
          }
        }
      }
    }
    
    
    static void SecondTask_init(void)
    {
      // ******************************************************************
      // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
      // ******************************************************************
      // Register the current thread as an ICall dispatcher application
      // so that the application can send and receive messages.
      ICall_registerApp(&selfEntity, &syncEvent);
    
      // Create an RTOS queue for message from profile to be sent to app.
      appMsgQueueHandle = Util_constructQueue(&appMsgQueue);
    
      // Create 5s clock for internal periodic events.
      Util_constructClock(&clkPeriodic, SecondTask_clockHandler,
                          PERIODIC_EVT_PERIOD, PERIODIC_EVT_PERIOD, true, NULL);
    
    }
    
    static void SecondTask_clockHandler(UArg arg)
    {
       // Post event to read the current RPA
       SecondTask_enqueueMsg(PERIODIC_EVT, NULL);
    }
    
    static status_t SecondTask_enqueueMsg(uint8_t event, void *pData)
    {
      uint8_t success;
      stEvt_t *pMsg = ICall_malloc(sizeof(stEvt_t));
    
      // Create dynamic pointer to message.
      if(pMsg)
      {
        pMsg->event = event;
        pMsg->pData = pData;
    
        // Enqueue the message.
        success = Util_enqueueMsg(appMsgQueueHandle, syncEvent, (uint8_t *)pMsg);
        return (success) ? SUCCESS : FAILURE;
      }
    
      return(FAILURE);
    }
    

    second_task.h

    This second task is heavily based off of the simple peripheral task from simple_peripheral.c. The task is incredibly simple as your example is. In my example it has a single reoccurring clock on a 5s period that will post an event. The event will be processed in the task's for(;;) loop. The event simple increments a static volatile variable so that we can see it increment in the debugger.

    I would like you to perform the same test I have set up so you can get experience and have a working example to base your project off of.

    Please import a fresh simple_peripheral project. Then right click the project and select "Add  Files..." Add the two files I have included in this post.

    In main.c Make the following additions.

    Add an include directive for the new second_task.h file.

    #include "second_task.h"

    Add a call to SecondTask_createTask() directly below the existing SimplePeripheral_createTask() within main()

      SimplePeripheral_createTask();
      SecondTask_createTask();
    
      /* enable interrupts and start SYS/BIOS */
      BIOS_start();
    
      return 0;
    }

    Then build the project and debug it. Then run the example. Add the "periodiccounter" variable to the Expressions window and select refresh continuously.

    Now, every 5 seconds the periodicCounter value will be incremented. As you can see I've had mine running for a little bit of time and it is working fine. Critically, the simple_peripheral task that has always been there is unaffected and a BLE connection can still be made via my smartphone.

    I suggest you take a look at the files I have provided to help you understand what is required to create a new task based in the simple_peripheral project. You can then modify it as you see fit!

    I hope this is helpful!

    Best,

    Kris

  • Hello,

    thanks for the file.

    OK, my ble application works in debug mode also with the second task.
    But when I add all my code in the second task, the singlePeripheral task does not boot anymore. it does not pass the function
    (in SimplePeripheral_init) :

     // Create an RTOS queue for message from profile to be sent to app.
    appMsgQueueHandle = Util_constructQueue(&appMsgQueue);

    I feel that the size of the heap is not enough to work in debug. Is it possible that it turns when there is no debug. and that poses problem when we want to debug?
    when i'm in debug mode and i'm putting the program on pause i get this:

    I have HEAPMGR_CONFIG = 0x80 // osal Heap manager, with auto-size
    and I can see in Expressions watch HEAPMGR_SIZE 63284, this value seems very hight.. what is the max value?

  • Sarah,

    It would appear that your added code as added a memory leak to the application. I would take a look at the Debugging section of the User's Guide to understand how to best debug a Heap/Memory issue in your BLE application. dev.ti.com/.../ble-index.html

    Assuming correct memory management, auto-size heap should be plenty of space. Looking at the comments in the ble_release.cfg we can see that using 0x80 for the osal Heap manager as you have mentioned states "with auto-size: The remaining RAM (not used by the system) will be fully assigned to the Heap"


    Best,
    Kris