1. 简化OS操作
  2. 对于跑蓝牙协议栈,uart的操作一定要在线程中完成,不然会出现指针异常。
    使用ATCMD时,请一定要去图像化界面–BLE–ICALL数量加+1,两个都要哦
  3. 重定义标准库堆栈: Options–Linker–Extra Options-- 增加:–redirect malloc=os_malloc
    –redirect free=os_free
// 【请在全局区调用】
 // 声明线程
 #pragma data_alignment=8
 OS_THREAD_DECLARE(edebug, 2048);// 声明事件组
 OS_EVENT_DECLARE(edebug);// 声明消息的队列对象
 OS_MSG_DECLARE(edebug);// 从堆栈模块传递的应用程序事件。该类型由应用程序定义,因为它可以随意将事件排队到自己。
 typedef struct __PACKED { // object data type
 uint8_t *data;
 uint8_t len;
 queue_msg_event_t event;
 } edebug_queue_t;// 声明软件定时器
 OS_TIMER_DECLARE_N(test);// 【请在函数中使用】
 // 创建事件组
 OS_EVENT_CREATE(edebug);// 创建消息队列
 OS_MSG_CREATE(edebug);// 创建软件定时器
 OS_TIMER_CREATE(test, OS_TIMER_PERIODIC, 500, NULL);
 OS_TIMER_START(test);static void timer_test_cb(UArg arg) {
 if (GPIO_read(CONFIG_GPIO_UWB_RDY) == 0) {
 LOGD(“0”);
 GPIO_write(CONFIG_GPIO_UWB_RDY, 1);
 } else {
 LOGD(“1”);
 GPIO_write(CONFIG_GPIO_UWB_RDY, 0);
 }
 }

完整demo

/********************************************************************************
* @file    edebug_cc26xx.c
* @author  jianqiang.xue
* @version V2.0.0
* @date    2023-03-08
* @brief   对于跑蓝牙协议栈,uart的操作一定要在线程中完成,不然会出现指针异常。
           使用ATCMD时,请一定要去图像化界面--BLE--ICALL数量加+1,两个都要哦
重定义标准库堆栈: Options--Linker--Extra Options-- 增加:--redirect malloc=os_malloc
                                                        --redirect free=os_free
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#include "os_api.h"
#include <ti_drivers_config.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/gpio/GPIOCC26XX.h>


/* Private Includes ----------------------------------------------------------*/
#include "edebug.h"

/* Private Define ------------------------------------------------------------*/
#define USE_WAKEUP_PIN
#ifdef USE_WAKEUP_PIN
#define WAKEUP_PIN(state) GPIO_write(CONFIG_GPIO_INT5, state); // 低电平--唤醒  高电平--睡眠
#else
#define WAKEUP_PIN(state)
#endif

#define EDEBUG_WRITE_EVT       UTIL_QUEUE_EVENT_ID // Event_Id_30
#define EDEBUG_MOVE_DATA_EVT   Event_Id_27

#define ET_ALL_EVENTS          (EDEBUG_WRITE_EVT | EDEBUG_MOVE_DATA_EVT)
/* Private Variables ---------------------------------------------------------*/
#if defined(ATCMD_EN) || defined(UART_OUT)
#include <ti/drivers/UART.h>
#include <ti/drivers/uart/UARTCC26XX.h>
#include "ti_drivers_config.h"

static UART_Handle g_uart_handle = NULL;

#ifdef ATCMD_EN
static char g_tx_buff[RX_MAX_LEN] = {0};
static char g_rx_buff[RX_MAX_LEN] = {0};
static bool g_init = false;

// 声明线程
#pragma data_alignment=8
OS_THREAD_DECLARE(edebug, 2048);
// 声明事件组
OS_EVENT_DECLARE(edebug);
// 声明消息的队列对象
OS_MSG_DECLARE(edebug);
// 声明软件定时器
//OS_TIMER_DECLARE_N(test);


// 从堆栈模块传递的应用程序事件。该类型由应用程序定义,因为它可以随意将事件排队到自己。
typedef struct __PACKED { // object data type
    uint8_t *data;
    uint8_t len;
    queue_msg_event_t event;
} edebug_queue_t;

extern atcmd_info_t atcmd$$Base;
extern atcmd_info_t atcmd$$Limit;

static atcmd_pack_t* g_pack = NULL;
#endif

#endif

#include <inc/hw_types.h>
#define IOID2PIN(ioid)  (1 << ioid)
extern const GPIOCC26XX_Config GPIOCC26XX_config;
typedef struct {
    uint8_t ioid;
    uint8_t added;  /* 0 = pin has not been added to gpioPinState */
    uint16_t config;
} PinConfig;
uint_fast8_t GPIO_read2(uint_least8_t index)
{
    unsigned int value;

    PinConfig *config = (PinConfig *) &GPIOCC26XX_config.pinConfigs[index];
    uint16_t type = config->config & 0x07;
    if (type % 2) { // 奇数-输入脚
      value = GPIO_readMultiDio(IOID2PIN(config->ioid));
      value = value & (IOID2PIN(config->ioid)) ? 1 : 0;
    } else { // 偶数-输出脚
      value = (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) >> config->ioid) & 1;
    }
    // LOGD("%d,%d,%x,%x,%x", index, config->ioid, value, type, IOID2PIN(config->ioid));
    return (value);
}

static void timer_test_cb(UArg arg) {
    //GPIO_toggle(CONFIG_GPIO_WAKEUP);
    //LOGD("IO:%d", GPIO_read2(CONFIG_GPIO_WAKEUP));
}

#if defined(ATCMD_EN) || defined(UART_OUT)
/**
 * @brief  发送AT指令,不需要应答
 * @note   举例: AT+TEST=123 ecu_ble_send_atcmd("AT+TEST=", "123", strlen("123"));
 * @param  at_head: AT指令头
 * @param  data: 数据
 * @param  len: 长度
 * @retval 0--成功 -1 --申请pool失败 -2 --线程不存在 -3 --没有分配块区
 *         -4 --没有创建msg队列 -5 --堆区剩余空间不足 -6 --put队列失败(队列满)
 */
int8_t edebug_send_atcmd(char* at_head, uint8_t* data, uint8_t len) {
    uint8_t *p = malloc(len + strlen(at_head) + strlen("\r\n") + 1); // 开辟空间存放数据
    uint8_t p_len = 0;
    if (p == NULL) return -5;
    memcpy(p, at_head, strlen(at_head));  // 写报头
    p_len = strlen(at_head);
    memcpy(p + p_len, data, len);  // 写数据
    p_len += len;
    memcpy(p + p_len, "\r\n", strlen("\r\n"));
    // 写报尾
    p_len += strlen("\r\n");
    int8_t ret = edebug_enqueue_msg(QUEUE_MSG_EVENT_SEND, p, p_len);
    free(p);
    return ret;
}

/**
 * @brief  消息入队,然后由线程发送
 * @param  pData: 待发送数据
 * @param  len: 数据长度
 * @param  event:  queue_msg_event_t
 * @retval 0--成功 -1 --条件不满足 -2 --线程不存在 -3 --队列创建失败(空间不足)
 *         -4 --没有创建msg队列 -5 --堆区剩余空间不足 -6 --put队列失败(队列满)
 */
int8_t edebug_enqueue_msg(queue_msg_event_t event, void* data, uint8_t len) {
    if (g_uart_handle == NULL && event == QUEUE_MSG_EVENT_SEND)
        return -1;
    if (OS_EVENT_HANDLE(edebug) == NULL)
        return -2;
    if (OS_MSG_QUEUE_HANDLE(edebug) == NULL)
        return -4;
    uint8_t *p = NULL;
    if (event < 0x80) {
        p = malloc(len);
        if (p == NULL) return -5;
        memcpy(p, data, len);
    }
    edebug_queue_t* pMsg = malloc(sizeof(edebug_queue_t));
    // Create dynamic pointer to message.
    if (pMsg) {
        pMsg->len = len;
        pMsg->data = p;
        pMsg->event = event;
        // Enqueue the message.
        uint8_t success = OS_MSG_ENQUEUE_MSG_N(edebug, pMsg);
        if (success) return 0;
        free(pMsg);
    }
    if (event < 0x80) free(p);
    return -3;
}

void edebug_send(uint8_t* data, uint16_t len) {
    if (g_init) {
        int8_t ret = edebug_enqueue_msg(QUEUE_MSG_EVENT_SEND, data, len);
        if (ret != 0) {
#ifdef UART_OUT
            WAKEUP_PIN(0);
            if (g_uart_handle == NULL) return;
            UART_write(g_uart_handle, data, (int)len);
            WAKEUP_PIN(1);
#endif
            return;
        }
    }
}
#endif

#ifdef ATCMD_EN
static void uart_read_callback(UART_Handle handle, void* rx_buff, size_t size) {
    edebug_enqueue_msg(QUEUE_MSG_EVENT_RECEIVE, rx_buff, size);
    UART_read(handle, g_rx_buff, RX_MAX_LEN);
}

bool atcmd_msg_handle(atcmd_pack_t* pack) {
    bool match = false;
    atcmd_info_t* atcmd;
    for (atcmd = &atcmd$$Base; atcmd < &atcmd$$Limit; atcmd++) {
      if (atcmd->name != (char *)0xFFFFFFFF) { // 针对FLASH默认值为0xFFFFFFFFF时,不进行比较
        if (strncmp((char*)(pack->data), atcmd->name, strlen(atcmd->name)) == 0) {
            match = true;
            break;
        }
      }
    }
    if (match) {
        // 裁剪  AT^XXXX=(保留)\r\n
        pack->len -= (strlen(atcmd->name) + 2); // 3 == \r\n
        pack->data += strlen(atcmd->name); // 移除前面的内容,并包含'=' or '?' or '=?'
        pack->data[pack->len + 1] = '\0';
        if (atcmd->callback(pack) == 2) {
            g_pack = pack;
        }
        return 0;
    }
    return -1;
}

bool atcmd_asysn_response(uint8_t *data, uint8_t len) {
    if (g_pack) g_pack->reply(data, len);
    return 0;
}
#endif

static void uart_init(void) {
#if defined(ATCMD_EN) || defined(UART_OUT)
    if (g_uart_handle) return;
    /* Call driver init functions */
    UART_init();
    UART_Params params;
    /* Create a UART with data processing off. */
    UART_Params_init(¶ms);
    params.writeMode      = UART_MODE_BLOCKING;
    params.writeDataMode  = UART_DATA_BINARY;
    params.readMode       = UART_MODE_CALLBACK;
    params.readDataMode   = UART_DATA_BINARY;
    params.baudRate       = 256000;
#ifdef ATCMD_EN
    params.readCallback   = uart_read_callback;
#endif

    // Open the UART and initiate the first read
#ifdef CONFIG_DISPLAY_UART
    g_uart_handle = UART_open(CONFIG_DISPLAY_UART, ¶ms);
#else
    g_uart_handle = UART_open(CONFIG_UART_0, ¶ms);
#endif

    if (!g_uart_handle) while(1);
    g_init = true;
#endif

#ifdef ATCMD_EN
    UART_control(g_uart_handle, UARTCC26XX_CMD_RX_FIFO_FLUSH, NULL); // 清空接收缓存区
    UART_control(g_uart_handle, UARTCC26XX_CMD_RETURN_PARTIAL_ENABLE, NULL); // 开启空闲接收回调
    UART_read(g_uart_handle, g_rx_buff, RX_MAX_LEN);
#endif
}

static void uart_deinit(void) {
    if (g_uart_handle == NULL) return;
    UART_writeCancel(g_uart_handle);
    UART_readCancel(g_uart_handle);
    UART_close(g_uart_handle);
    g_uart_handle = NULL;
}

/**
 * @brief  初始化 线程事件组/RTT/UART
 * @note   硬件外设初始化
 */
static void _init(void) {
#ifdef RTT_OUT
    SEGGER_RTT_Init();
    SEGGER_RTT_SetTerminal(0);
#else
    uart_init();
#endif
}

#ifdef ATCMD_EN
static void edebug_task_init(void) {
    // 创建事件组
    OS_EVENT_CREATE(edebug);
    // 创建消息队列
    OS_MSG_CREATE(edebug);
    // 创建软件定时器
    //OS_TIMER_CREATE(test, OS_TIMER_PERIODIC, 500, NULL);
    //OS_TIMER_START(test);
    _init();
}

static int flashcmd_cmd_2640_read(flashcmd_pack_t* pack) {
    uint8_t buff[20] = "nonsupport\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int flashcmd_cmd_tbox_read(flashcmd_pack_t* pack) {
    uint8_t buff[20] = "nonsupport\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int flashcmd_cmd_2642_read(flashcmd_pack_t* pack) {
    uint8_t buff[20] = "nonsupport\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int flashcmd_cmd_se_applet_read(flashcmd_pack_t* pack) {
    uint8_t buff[20] = "nonsupport\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int flashcmd_cmd_se_cos_read(flashcmd_pack_t* pack) {
    uint8_t buff[20] = "nonsupport\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int flashcmd_cmd_ee_data_read(flashcmd_pack_t* pack) {
    return 0;
}

/**
 * @brief flash命令 接收处理
 * @note flash管理_V1.4_20211027.xls  通过串口向2642的外部flash读取数据
 * @param  *pack: 数据指针
 * @retval 0--失败 1--成功
 */
static bool flashcmd_msg_handle(flashcmd_pack_t *pack) {
    if (pack == NULL) return false;
    if (pack->len < 7) return false;
    if (pack->data[0] == 0x3C && pack->data[1] == 0xC3) {
        // CMD_2640_READ 2640 img升级文件,取出
        if (pack->data[2] == 0x00 && pack->data[3] == 0x01) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_2640_read(pack);
            return true;
        }
        // CMD_S9_READ(在BOOT中有效,通过ECU刷写S9) CMD_TBOX_READ(在APP中有效)
        else if (pack->data[2] == 0x00 && pack->data[3] == 0x03) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_tbox_read(pack);
            return true;
        }
        // CMD_2642_READ 2642 img升级文件,取出
        else if (pack->data[2] == 0x00 && pack->data[3] == 0x05) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_2642_read(pack);
            return true;
        }
        // CMD_SE_APPLET_READ se_applet img升级文件,取出
        else if (pack->data[2] == 0x00 && pack->data[3] == 0x07) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_se_applet_read(pack);
            return true;
        }
        // CMD_SE_COS_READ se_cos img升级文件,取出
        else if (pack->data[2] == 0x00 && pack->data[3] == 0x09) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_se_cos_read(pack);
            return true;
        }
        // CMD_EE_DATA_READ ee_data 2642辅助存储的ee数据,取出
        else if (pack->data[2] == 0x00 && pack->data[3] == 0x0B) {
            // 裁剪  0x3CC3 CMD(2byte)(保留)\r\n
            pack->len -= (4 + 2); // 2 == \r\n
            pack->data += 4; // 移除前面的内容
            pack->data[pack->len + 1] = '\0';
            flashcmd_cmd_ee_data_read(pack);
            return true;
        }
    }
    return false;
}

static void queue_dispose(void) {
    while (! OS_MSG_IS_EMPTY(edebug)) {
        edebug_queue_t* pmsg = (edebug_queue_t*) OS_MSG_DEQUEUE_MSG(edebug);
        if (pmsg == NULL) continue;
        switch (pmsg->event) {
            case QUEUE_MSG_EVENT_DEINIT:
                WAKEUP_PIN(1);
                uart_deinit();
                break;
            case QUEUE_MSG_EVENT_INIT:
                WAKEUP_PIN(0);
                uart_init();
                break;
            case QUEUE_MSG_EVENT_RECEIVE:
                if (strncmp((char *)pmsg->data, "AT+", 3) == 0) {
                    atcmd_pack_t pack;
                    pack.data = pmsg->data;
                    pack.len = pmsg->len;
                    pack.reply = edebug_send;
                    atcmd_msg_handle(&pack);
                } else if (pmsg->len > 2 && pmsg->data[0] == 0x3c && pmsg->data[1] == 0xc3) {
                    flashcmd_pack_t pack;
                    pack.data = pmsg->data;
                    pack.len = pmsg->len;
                    pack.reply = edebug_send;
                    flashcmd_msg_handle(&pack);
                }
                break;
            case QUEUE_MSG_EVENT_RX_TIMEOUT:
                break;
            // 最低优先级处理
            case QUEUE_MSG_EVENT_SEND:
                if (g_uart_handle == NULL) return;
                WAKEUP_PIN(0);
                UART_write(g_uart_handle, pmsg->data, (int)pmsg->len);
                WAKEUP_PIN(1);
                break;

            default:
                break;
        }
        if (pmsg->event < 0x80) free(pmsg->data);
        free(pmsg);
    }
}

static void task_edebug(UArg arg0, UArg arg1) {
    edebug_task_init();
    LOGD("start");
    for (;;) {
        uint32_t events;
        events = OS_EVENT_PEND(edebug);
        if (events & EDEBUG_WRITE_EVT) {
            queue_dispose();
        }
        if (events & EDEBUG_MOVE_DATA_EVT) {
        }
    }
}
#endif

//*****************************
bool edebug_is_normal(void) {
    return g_uart_handle ? true : false;
}

void edebug_init(void) {
#ifdef ATCMD_EN
    OS_THREAD_CREATE(edebug, OS_PRIORITY_LOW);
#endif
}

static uint8_t g_mode = 0;
static bool lock = 0;
void log_trace(const char* format, ...) {
    va_list p;
    int len;
    if (g_mode) goto s;
    if (lock) return;
    lock = true;
s:
    va_start(p, format);
    len = vsprintf(g_tx_buff, format, p);
    va_end(p);
    edebug_send((uint8_t *)g_tx_buff, len);
    lock = false;
}


void edebug_set_mode(uint8_t mode) {
    g_mode = mode;
}

#ifdef ATCMD_EN
// 在功能模块中定义一个标准函数
static int test0(atcmd_pack_t *pack) {
    uint8_t buff[20] = "test0\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int test1(atcmd_pack_t *pack) {
    uint8_t buff[20] = "test1\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

static int test2(atcmd_pack_t *pack) {
    if (pack->len == 0)
        return -1;
    uint8_t argc = 1; //'='后面如果有长度,就一定有1个参数
    // 计算参数个数
    for (uint16_t i = 0; i < pack->len; i++) {
        if (pack->data[i] == ',')
            argc++;
    }
    if (argc != 2) return -1;
    uint8_t buff[20] = "";
    uint32_t num = 0, num1 = 0;

    sscanf((char*)(pack->data), "%d,%d", &num, &num1);
    snprintf((char*)buff, 20, "%d,%d"AT_OK, num, num1);
    pack->reply(buff, strlen((char*)buff));
    return 1;
}

static int test3(atcmd_pack_t *pack) {
    uint8_t buff[20] = "test3\r\n";
    strcat((char*)buff, AT_OK);
    pack->reply(buff, strlen((char*)buff));
    return 0;
}

// 注册AT指令,传入标准函数
ATCMD_INIT("AT+TEST=?", test0);
ATCMD_INIT("AT+TEST?", test1);
ATCMD_INIT("AT+TEST=", test2);
ATCMD_INIT("AT+TEST", test3);
#endif
/********************************************************************************
* @file    os_api.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-03-07
* @brief   支持 TI_OS
********************************************************************************/

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "os_api.h"
/* Public function prototypes -----------------------------------------------*/
/*********************************OS_KERNEL***********************************/
os_status os_kernel_initialize(void) {
    /* Initialize ICall module */
    ICall_init();
    return OS_OK;
}

os_status os_kernel_start(void) {
    /* enable interrupts and start SYS/BIOS */
    BIOS_start();
    return OS_OK;
}

uint32_t os_kernel_stop(void) {
    BIOS_exit(0);
    return OS_OK;
}

os_status os_delay(uint32_t ms) {
    Task_sleep(ms);
    return OS_OK;
}

uint32_t os_get_tick(void) {
    return Clock_getTicks();
}

uint32_t os_get_state(void) {
    return OS_OK;
}

void* os_malloc(uint32_t size) {
    return ICall_malloc((uint16_t)size);
}

void* os_calloc(uint32_t size) {
    return ICall_malloc((uint16_t)size);
}

uint8_t os_free(void* p) {
    ICall_free(p);
    return 0;
}
/********************************************************************************
* @file    os_api.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-03-07
* @brief   支持 TI_OS
********************************************************************************/
#ifndef OS_API_H_
#define OS_API_H_
#include <stdint.h>
#include <stdbool.h>

#include <ti/sysbios/BIOS.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 <ti/sysbios/knl/Semaphore.h>
#include <icall.h>
#include "util.h"

/// Timeout value.
#define OS_WAIT_FOREVER     0xFFFFFFFFU    ///< wait forever timeout value

/************************************OS_KERNEL************************************/
typedef enum {
    OS_OK                     =     0,       ///< function completed; no error or event occurred.
    OS_EVENT_SIGNAL           =  0x08,       ///< function completed; signal event occurred.
    OS_EVENT_MESSAGE          =  0x10,       ///< function completed; message event occurred.
    OS_EVENT_MAIL             =  0x20,       ///< function completed; mail event occurred.
    OS_EVENT_TIMEOUT          =  0x40,       ///< function completed; timeout occurred.
    OS_ERROR_PARAMETER        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
    OS_ERROR_RESOURCE         =  0x81,       ///< resource not available: a specified resource was not available.
    OS_ERROR_TIMEOUTRESOURCE  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.
    OS_ERROR_ISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
    OS_ERROR_ISRRECURSIVE     =  0x83,       ///< function called multiple times from ISR with same object.
    OS_ERROR_PRIORITY         =  0x84,       ///< system cannot determine priority or thread has illegal priority.
    OS_ERROR_NOMEMORY         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
    OS_ERROR_VALUE            =  0x86,       ///< value of a parameter is out of range.
    OS_ERROR_OS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.
} os_status;

os_status os_kernel_initialize (void);
os_status os_kernel_start(void);
uint32_t os_kernel_stop(void);

os_status os_delay(uint32_t ms);
uint32_t os_get_tick(void);
uint32_t os_get_state(void);

void* os_malloc(uint32_t size);
void* os_calloc(uint32_t size);
uint8_t os_free(void *p);

/************************************OS_THREAD************************************/
typedef enum {
    OS_PRIORITY_IDLE          = 0,          // idle (lowest)
    OS_PRIORITY_LOW           = 1,          // low
    OS_PRIORITY_BELOWNORMAL   = 2,          // below normal
    OS_PRIORITY_NORMAL        = 3,          // normal (default)
    OS_PRIORITY_ABOVENORMAL   = 4,          // above normal
    OS_PRIORITY_HIGH          = 5,          // high 【BLE协议栈任务】
    OS_PRIORITY_REALTIME      = 6,          // realtime (highest)
    OS_PRIORITY_ERROR         =  0x84       // system cannot determine priority or thread has illegal priority
} os_priority_t;

// 定义线程所需的变量和回调声明(请在全局区调用)
#define OS_THREAD_DECLARE(name, stacksz)               \
    static uint8_t g_task_##name##_stack[stacksz];     \
    static void task_##name(UArg arg0, UArg arg1);     \
    static const uint16_t g_task_##name##_stacksz = stacksz; \
    Task_Struct g_task_##name##_t;

// 创建线程(请在函数中使用)
#define OS_THREAD_CREATE(name, PRIORITY) {                    \
    Task_Params task_##name##_params;                         \
    Task_Params_init(&task_##name##_params);                  \
    task_##name##_params.stack     = g_task_##name##_stack;   \
    task_##name##_params.stackSize = g_task_##name##_stacksz; \
    task_##name##_params.priority  = PRIORITY;                \
    Task_construct(&g_task_##name##_t, task_##name, &task_##name##_params, NULL); \
}

/************************************OS_TIMER************************************/
typedef enum {
    OS_TIMER_ONCE     = 0,    ///< one-shot timer
    OS_TIMER_PERIODIC = 1     ///< repeating timer
} os_timer_t;

#define OS_TIMER_STRUCT(name) g_##name##_timer_struct

// 定义软定时器所需的变量和回调声明(请在全局区调用)
#define OS_TIMER_DECLARE_N(name)                 \
    Clock_Struct g_##name##_timer_struct; \
    static void timer_##name##_cb(UArg arg);

// 创建软定时器并指定周期类型(单次/循环)(请在函数中使用)
#define OS_TIMER_CREATE(name, cycle_t, cycle_ms, arg) {      \
    if (cycle_t == OS_TIMER_ONCE) {                                      \
        Util_constructClock(&g_##name##_timer_struct, timer_##name##_cb, \
                            cycle_ms, 0, false, (UArg)arg);              \
    } else {                                                             \
        Util_constructClock(&g_##name##_timer_struct, timer_##name##_cb, \
                            cycle_ms, cycle_ms, false, (UArg)arg);       \
    }                                                                    \
}

// 软定时器是运行状态吗
#define OS_TIMER_IS_RUNNING()  Util_isActive(&g_##name##_timer_struct)

// 启动软定时器(请在函数中使用)
#define OS_TIMER_START(name) {                 \
    Util_startClock(&g_##name##_timer_struct); \
}

// 启动软定时器(请在函数中使用)
#define OS_TIMER_RESTART(name, ms) {                 \
    Util_restartClock(&g_##name##_timer_struct, ms); \
}

// 停止软定时器(请在函数中使用)
#define OS_TIMER_STOP(name) {                 \
    Util_stopClock(&g_##name##_timer_struct); \
}

/************************************OS_QUEUE************************************/
#define OS_MSG_QUEUE_STRUCT(name) g_##name##_queue_struct
#define OS_MSG_QUEUE_HANDLE(name) g_##name##_queue_handle
// 定义消息队列所需的变量和回调声明(请在全局区调用)
#define OS_MSG_DECLARE(name)                     \
    Queue_Struct g_##name##_queue_struct; \
    Queue_Handle g_##name##_queue_handle;

// 创建消息队列(请在函数中使用)
#define OS_MSG_CREATE(name)  g_##name##_queue_handle = Util_constructQueue(&g_##name##_queue_struct)

// 消息入队
#define OS_MSG_ENQUEUE_MSG(name, sync_handle, pmsg) Util_enqueueMsg(g_##name##_queue_handle, sync_handle, (uint8_t*)pmsg);
// 消息入队(使用默认线程ID)
#define OS_MSG_ENQUEUE_MSG_N(name, pmsg) Util_enqueueMsg(g_##name##_queue_handle, g_##name##_event, (uint8_t*)pmsg);

// 消息出队
#define OS_MSG_DEQUEUE_MSG(name) Util_dequeueMsg(g_##name##_queue_handle)

// 消息队列(数量)是空吗
#define OS_MSG_IS_EMPTY(name) Queue_empty(g_##name##_queue_handle)

/************************************OS_EVENT************************************/
#define OS_EVENT_HANDLE(name) g_##name##_event
#define OS_EVENT_ID(name)     g_##name##_entity_id

// 定义事件所需的变量和回调声明(请在全局区调用)
#define OS_EVENT_DECLARE(name) \
    ICall_SyncHandle g_##name##_event; /* 用于全局检查消息的源和/或目的地的实体ID*/ \
    ICall_EntityID g_##name##_entity_id; /* 用于全局检查消息的源和/或目的地的实体ID */

// 创建事件组(请在函数中使用)
#define OS_EVENT_CREATE(name) ICall_registerApp(&g_##name##_entity_id, &g_##name##_event)
// 发送事件
#define OS_EVENT_POST(name, event) Event_post(g_##name##_event, event)
// 等待事件
#define OS_EVENT_PEND(name) Event_pend(g_##name##_event, Event_Id_NONE, ET_ALL_EVENTS, ICALL_TIMEOUT_FOREVER)

/************************************OS_SEM************************************/
#define OS_SEM_STRUCT(name) g_##name##_sem_struct
#define OS_SEM_HANDLE(name) g_##name##_sem_handle

// 定义事件所需的变量和回调声明(请在全局区调用)
#define OS_SEM_DECLARE(name) \
    Semaphore_Struct g_##name##_sem_struct; \
    Semaphore_Handle g_##name##_sem_handle;

// 创建信号量(请在函数中使用) 构造一个用作资源锁的信号量对象,初始计数为num
#define OS_SEM_CREATE(name, num) {                                        \
    Semaphore_Params sem_params_##name;                                   \
    Semaphore_Params_init(&sem_params_##name);                            \
    Semaphore_construct(&g_##name##_sem_struct, num, &sem_params_##name); \
    g_##name##_sem_handle = Semaphore_handle(&g_##name##_sem_struct);     \
}

// 发送信号量
#define OS_SEM_POST(name) Semaphore_post(g_##name##_sem_handle)
// 等待信号量  ms=-1 无限等待  ms=0 不等待  返回值:false-timeout true--ok
#define OS_SEM_PEND(name, ms) Semaphore_pend(g_##name##_sem_handle, ms)
#endif