环境
- 系统:Windows 10
- SDK:simplelink_cc13x2_26x2_sdk_4_30_00_54
- IDE:Code Composer Studio, Version: 10.1.1.00004
- 例程: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);
}
}