TI RTOS BLE 添加任务,队列,事件,定时器

环境

  1. 系统:Windows 10
  2. SDK:simplelink_cc13x2_26x2_sdk_4_30_00_54
  3. IDE:Code Composer Studio, Version: 10.1.1.00004
  4. 例程:simple_peripheral_oad_offchip_CC26X2R1_LAUNCHXL_tirtos_ccs (已删除不必要的代码,请看:删除simple_peripheral_oad_offchip工程多余的代码)

1. 创建流程

1.1 变量、常量准备


// How often to perform periodic event (in ms)
#define USER_PERIODIC_EVT_PERIOD               2000
// Task configuration
#define USER_TASK_PRIORITY                     1

#ifndef USER_TASK_STACK_SIZE
#define USER_TASK_STACK_SIZE                   1408
#endif

// Internal Events for RTOS application
#define USER_ICALL_EVT                         ICALL_MSG_EVENT_ID  // Event_Id_31
#define USER_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30

// Bitwise OR of all RTOS events to pend on
#define USER_ALL_EVENTS                        (USER_ICALL_EVT  | \
                                                USER_QUEUE_EVT  )

/**********************************************************************************/

// Container to store information from clock expiration using a flexible array
// since data is not always needed
typedef struct
{
  uint8_t event;
  uint8_t data[];
} userClockEventData_t;

// Task configuration
Task_Struct userTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(userTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t userTaskStack[USER_TASK_STACK_SIZE];

/*********************************************************************
 * LOCAL VARIABLES
 */

static Event_Struct userEvtStruct;
static Event_Handle userEvtHandle;

// Queue object used for app messages
static Queue_Struct userMsgQueue;
static Queue_Handle userMsgQueueHandle;


static Clock_Struct userClkPeriodic;

// Memory to pass periodic event ID to clock handler
static userClockEventData_t userArgPeriodic = { .event = USER_EVT_PERIODIC };

1.2 任务创建

user_task_createTask() 函数需要放到main函数中(已删除部分代码),如下:

int main()
{
  /* Register Application callback to trap asserts raised in the Stack */
  RegisterAssertCback(AssertHandler);

  Board_initGeneral();

  SimplePeripheral_createTask();

  user_task_createTask();
  /* enable interrupts and start SYS/BIOS */
  BIOS_start();

  return (0);
}
void user_task_createTask(void)
{
    Task_Params taskParams;

    // Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = userTaskStack;
    taskParams.stackSize = USER_TASK_STACK_SIZE;
    taskParams.priority = USER_TASK_PRIORITY;

    Task_construct(&userTask, user_task_taskFxn, &taskParams, NULL);
}

1.3 队列,事件,定时器初始化

static void user_task_init(void)
{
	Event_Params userEvtParams;
	
    Event_Params_init(&userEvtParams);
    Event_construct(&userEvtStruct, &userEvtParams);
    userEvtHandle = Event_handle(&userEvtStruct);

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

    // Create clock for internal periodic events.
    Util_constructClock(&userClkPeriodic, user_clockHandler,
    USER_PERIODIC_EVT_PERIOD, 1000, true, (UArg) &userArgPeriodic);
}

1.4 任务循环

static void user_task_taskFxn(UArg a0, UArg a1)
{
    // Initialize application
    user_task_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(userEvtHandle, Event_Id_NONE, USER_ALL_EVENTS, ICALL_TIMEOUT_FOREVER);
        
        if (events)
        {

            // If RTOS queue is not empty, process app message.
            if (events & USER_QUEUE_EVT)
            {
                while (!Queue_empty(userMsgQueueHandle))
                {
                    userEvt_t *pMsg = (userEvt_t*) Util_dequeueMsg(
                            userMsgQueueHandle);
                    if (pMsg)
                    {
                        // Process message.
                        user_task_processAppMsg(pMsg);

                        // Free the space from the message.
                        ICall_free(pMsg);
                    }
                }
            }

        }
    }
}

2. 全部代码

2.1 C文件

/*********************************************************************
 * INCLUDES
 */

#include "user/user_task.h"
#include "user/debug/debug.h"

#include "user/drivers/buzzer.h"
#include "user/hal/hal_buzzer.h"
#include "user/hal/hal_button.h"
#include "user/hal/hal_uart.h"

#include <string.h>

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>

#include <icall.h>
#include "util.h"
/* Module Header */
#include <ti/drivers/apps/LED.h>
#include <ti/drivers/UART.h>
#include <ti/display/Display.h>
#include <ti/devices/cc13x2_cc26x2/driverlib/sys_ctrl.h>

#include "ti_drivers_config.h"
#include "ti_ble_config.h"

#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

// How often to perform periodic event (in ms)
#define USER_PERIODIC_EVT_PERIOD               2000
// Task configuration
#define USER_TASK_PRIORITY                     1

#ifndef USER_TASK_STACK_SIZE
#define USER_TASK_STACK_SIZE                   1408
#endif

// Internal Events for RTOS application
#define USER_ICALL_EVT                         ICALL_MSG_EVENT_ID  // Event_Id_31
#define USER_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30


// Bitwise OR of all RTOS events to pend on
#define USER_ALL_EVENTS                        (USER_ICALL_EVT  | \
                                                USER_QUEUE_EVT  )

/**********************************************************************************/

// Container to store information from clock expiration using a flexible array
// since data is not always needed
typedef struct
{
  uint8_t event;
  uint8_t data[];
} userClockEventData_t;

// Task configuration
Task_Struct userTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(userTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t userTaskStack[USER_TASK_STACK_SIZE];

/*********************************************************************
 * LOCAL VARIABLES
 */
static Event_Struct userEvtStruct;
static Event_Handle userEvtHandle;

// Queue object used for app messages
static Queue_Struct userMsgQueue;
static Queue_Handle userMsgQueueHandle;


static Clock_Struct userClkPeriodic;

// Memory to pass periodic event ID to clock handler
static userClockEventData_t userArgPeriodic = { .event = USER_EVT_PERIODIC };

/************************************************************************/
LED_Handle ledHandle[3];
LED_Params ledParams;
/***********************************************************************/
UART_Handle uart0;
UART_Params uartParams;
/************************************************************************/

/************************************************************************/
/*********************************************************************
 * LOCAL FUNCTIONS
 */

static void user_task_init(void);
static void user_task_taskFxn(UArg a0, UArg a1);

static void user_task_processAppMsg(userEvt_t *pMsg);
static void user_clockHandler(UArg arg);
/*********************************************************************
 * EXTERN FUNCTIONS
 */

/*********************************************************************
 * PROFILE CALLBACKS
 */

/*********************************************************************
 * @fn      user_task_createTask
 *
 * @brief   Task creation function for the User App.
 */
void user_task_createTask(void)
{
    Task_Params taskParams;

    // Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = userTaskStack;
    taskParams.stackSize = USER_TASK_STACK_SIZE;
    taskParams.priority = USER_TASK_PRIORITY;

    Task_construct(&userTask, user_task_taskFxn, &taskParams, NULL);
}

/*********************************************************************
 * @fn      user_task_init
 *
 * @brief   Called during initialization and contains application
 *          specific initialization (ie. hardware initialization/setup,
 *          table initialization, power up notification, etc), and
 *          profile initialization/setup.
 */
static void user_task_init(void)
{
    Event_Params userEvtParams;
    
    Event_Params_init(&userEvtParams);
    Event_construct(&userEvtStruct, &userEvtParams);
    userEvtHandle = Event_handle(&userEvtStruct);

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

    // Create clock for internal periodic events.
    Util_constructClock(&userClkPeriodic, user_clockHandler,
    USER_PERIODIC_EVT_PERIOD, 1000, true, (UArg) &userArgPeriodic);

    /*Init Drivers*/
    // Assume our LED is configured to be a PWM LED
//    LED_Params_init(&ledParams);
//    ledHandle[CONFIG_LED_R] = LED_open(CONFIG_LED_R, &ledParams);
//    ledHandle[CONFIG_LED_G] = LED_open(CONFIG_LED_G, &ledParams);
//    ledHandle[CONFIG_LED_B] = LED_open(CONFIG_LED_B, &ledParams);
//    // Turn on, set brightness, and blink
//    LED_setOn(ledHandle[CONFIG_LED_R], 80);
//    LED_startBlinking(ledHandle[CONFIG_LED_R], 500, 5);
//
//    LED_setOn(ledHandle[CONFIG_LED_G], 80);
//    LED_startBlinking(ledHandle[CONFIG_LED_G], 500, LED_BLINK_FOREVER);
//    LED_setOn(ledHandle[CONFIG_LED_B], 80);
//    LED_startBlinking(ledHandle[CONFIG_LED_B], 500, LED_BLINK_FOREVER);

//    hal_buzzer_init();
//    hal_buzzer_start(50, 950, 3);
//    hal_button_init();
//hal_uart0_init(115200);
}

/*********************************************************************
 * @fn      user_task_taskFxn
 *
 * @brief   Application task entry point for the Simple Peripheral.
 *
 * @param   a0, a1 - not used.
 */
static void user_task_taskFxn(UArg a0, UArg a1)
{
    // Initialize application
    user_task_init();

    // Application main loop
    for (;;)
    {
        uint32_t events = 0;

        // 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(userEvtHandle, Event_Id_NONE, USER_ALL_EVENTS, ICALL_TIMEOUT_FOREVER);

//        Task_sleep(100000);
        Debug("events %08x", events);

        if (events)
        {

            // If RTOS queue is not empty, process app message.
            if (events & USER_QUEUE_EVT)
            {
                while (!Queue_empty(userMsgQueueHandle))
                {
                    userEvt_t *pMsg = (userEvt_t*) Util_dequeueMsg(
                            userMsgQueueHandle);
                    if (pMsg)
                    {
                        // Process message.
                        user_task_processAppMsg(pMsg);

                        // Free the space from the message.
                        ICall_free(pMsg);
                    }
                }
            }

        }
    }
}

/*********************************************************************
 * @fn      user_task_processAppMsg
 *
 * @brief   Process an incoming callback from a profile.
 *
 * @param   pMsg - message to process
 *
 * @return  None.
 */
static void user_task_processAppMsg(userEvt_t *pMsg)
{
    bool dealloc = TRUE;

    switch (pMsg->event)
    {

    case USER_EVT_PERIODIC:
        Debug("USER_EVT_PERIODIC\n");
        break;

    case USER_EVT_BUZZER:
        //hal_buzzer_handler();
        break;

    case USEE_EVT_UART0:
        //hal_uart0_rx(pMsg);
        break;

    default:
        // Do nothing.
        break;
    }

    // Free message data if it exists and we are to dealloc
    if ((dealloc == TRUE) && (pMsg->pData != NULL))
    {
        ICall_free(pMsg->pData);
    }
}

/*********************************************************************
 * @fn      user_task_enqueueMsg
 *
 * @brief   Creates a message and puts the message in RTOS queue.
 *
 * @param   event - message event.
 * @param   state - message state.
 */
status_t user_task_enqueueMsg(UserEvent_e event, void *pData)
{
    uint8_t success;
    userEvt_t *pMsg = ICall_malloc(sizeof(userEvt_t));

    // Create dynamic pointer to message.
    if(pMsg)
    {
      pMsg->event = event;
      pMsg->pData = pData;

      // Enqueue the message.
      success = Util_enqueueMsg(userMsgQueueHandle, userEvtHandle, (uint8_t *)pMsg);
      return (success) ? SUCCESS : FAILURE;
    }

    return(bleMemAllocError);
}

/*********************************************************************
 * @fn      user_clockHandler
 *
 * @brief   Handler function for clock timeouts.
 *
 * @param   arg - event type
 *
 * @return  None.
 */
static void user_clockHandler(UArg arg)
{

    // do not print here, it will crash.

    userClockEventData_t *pData = (userClockEventData_t*) arg;

    if (pData->event == USER_EVT_PERIODIC)
    {
        // Start the next period
        Util_startClock(&userClkPeriodic);

        // Post event to wake up the application
        user_task_enqueueMsg(USER_EVT_PERIODIC, NULL);
    }

}

2.2 头文件


#ifndef USER_USER_TASK_H_
#define USER_USER_TASK_H_

#include "stdint.h"
#include "stdbool.h"
#include <bcomdef.h>

#ifndef status_t
#define status_t bStatus_t
#endif
/**************************************************************/

// 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
} userEvt_t;


typedef enum {

    // User events
    USER_EVT_PERIODIC  =  0,
    USER_EVT_BUZZER,
    USEE_EVT_UART0,
    USER_EVT_3,
}UserEvent_e;

/**************************************************************/

void user_task_createTask(void);
status_t user_task_enqueueMsg(UserEvent_e event, void *pData);
#endif /* USER_USER_TASK_H_ */



3. 注意

在定时器的回调函数中不能跑耗时长的代码,例如不能打印log,例如:

static void user_clockHandler(UArg arg)
{

    // do not print here, it will crash.

    userClockEventData_t *pData = (userClockEventData_t*) arg;

//    Debug("USER_EVT_PERIODIC\n"); 禁止打印,否则RTOS崩溃
    if (pData->event == USER_EVT_PERIODIC)
    {
        // Start the next period
        Util_startClock(&userClkPeriodic);

        // Post event to wake up the application
        user_task_enqueueMsg(USER_EVT_PERIODIC, NULL);
    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值