CMSIS RTOS API,内核通用API接口

strongerHuang 2020-08-09 00:00

关注、星标公众,不错过精彩内容

转自:Mculover666


之前给大家分享过关于CMSIS的内容,比如:

Cortex-M微控制器软件接口标准CMSIS详细内容

CMSIS-DAP和J-Link、ST-Link是什么关系?


今天继续给大家分享由“Mculover666”整理的关于CMSIS的内容。

1. CMSIS-RTOS API

CMSIS-RTOS API是ARM公司为RTOS内核制定的一套通用接口协议,它提供了一套「标准的API接口」,可以移植到各种各样的RTOS上,使得上层的软件、中间件、库以及其他组件在不同的RTOS之上都可以正常工作。

这套API表现为两个文件:cmsis-os.h和cmsis-os.c,也就是说,不同的RTOS内核分别用自己的一套东西去适配.c文件中的接口,而用户只需要调用.h文件中给出的API编写应用。

本文会列举性的给出CMSIS-RTOS有哪些API和宏定义,并给出每类API的使用demo,学习者只需要了解这些东西,能看懂用CMSIS-RTOS API编写的应用程序即可~

在TencentOS-tiny中如下。

  • 基于TencentOS-tiny的CMSIS-RTOS API v1.02版本实现:
    • cmsis_os.h
    • cmsis_os.c
  • 基于TencentOS-tiny的CMSIS-RTOS API v2.1.3版本实现:
    • cmsis_os2.h
    • cmsis_os2.c

CMSIS-RTOS API的整体架构如下图:

2. CMSIS-RTOS API列表

下面列出了 CMSIS-RTOS API v1.02 版本提供的所有API。

CMSIS-RTOS 所有API使用的错误码(cmsis-os.h):

typedef enum {
    osOK                    =     0,       ///< function completed; no error or event occurred.
    osEventSignal           =  0x08,       ///< function completed; signal event occurred.
    osEventMessage          =  0x10,       ///< function completed; message event occurred.
    osEventMail             =  0x20,       ///< function completed; mail event occurred.
    osEventTimeout          =  0x40,       ///< function completed; timeout occurred.
    osErrorParameter        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
    osErrorResource         =  0x81,       ///< resource not available: a specified resource was not available.
    osErrorTimeoutResource  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.
    osErrorISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
    osErrorISRRecursive     =  0x83,       ///< function called multiple times from ISR with same object.
    osErrorPriority         =  0x84,       ///< system cannot determine priority or thread has illegal priority.
    osErrorNoMemory         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
    osErrorValue            =  0x86,       ///< value of a parameter is out of range.
    osErrorOS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.
    os_status_reserved      =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
} osStatus;

CMSIS-RTOS API一些可选项控制是否开启(cmsis-os.h):

#define osFeature_MainThread   1       ///< main thread      1=main can be thread, 0=not available
#define osFeature_Pool         1       ///< Memory Pools:    1=available, 0=not available
#define osFeature_MailQ        1       ///< Mail Queues:     1=available, 0=not available
#define osFeature_MessageQ     1       ///< Message Queues:  1=available, 0=not available
#define osFeature_Signals      0       ///< maximum number of Signal Flags available per thread
#define osFeature_Semaphore    30       ///< maximum count for \ref osSemaphoreCreate function
#define osFeature_Wait         0       ///< osWait function: 1=available, 0=not available
#define osFeature_SysTick      1       ///< osKernelSysTick functions: 1=available, 0=not available

2.1. 内核信息和控制

API 描述
osKernelInitialize 初始化RTOS内核
osKernelStart 启动RTOS内核
osKernelRunning Query if the RTOS kernel is running
osKernelSysTick (可选) Get RTOS kernel system timer counter
osKernelSysTickFrequency (可选) RTOS kernel system timer frequency in Hz
osKernelSysTickMicroSec (可选) Convert microseconds value to RTOS kernel system timer value
  • osKernelInitialize
osStatus osKernelInitialize(void);

返回值:status code

  • osKernelStart
osStatus osKernelStart(void);

返回值:status code

  • osKernelRunning
int32_t osKernelRunning(void);

返回值:0表示RTOS未启动,1表示RTOS已经启动

  • osKernelSysTick
uint32_t osKernelSysTick(void);

返回值:RTOS内核系统当前的时间

2.2. 线程管理

##连接符的作用是连接两个字符串,合为一个字符串。

CMSIS-RTOS API 存放线程参数管理的结构体如下:

typedef struct os_thread_def {
    char           *name;       ///< Thread name
    os_pthread      pthread;    ///< start address of thread function
    osPriority      tpriority;  ///< initial thread priority
    uint32_t        instances;  ///< maximum number of instances of that thread function
    k_stack_t      *stackbase;  ///< base address of task
    uint32_t        stacksize;  ///< stack size requirements in bytes; 0 is default stack size
    k_timeslice_t   timeslice;  ///< timeslice
    k_task_t       *task;
} osThreadDef_t;

CMSIS-RTOS API 定义线程的宏如下:

#define osThreadDef(name, priority, instances, stacksz)  \
    k_task_t task_handler_##name; \
    k_stack_t task_stack_##name[(stacksz)]; \
    const osThreadDef_t os_thread_def_##name = \
        { #name, (os_pthread)(name), (osPriority)(priority), (instances), \
        (&((task_stack_##name)[0])), (stacksz), ((k_timeslice_t)0u), (&(task_handler_##name)) }

宏定义中的 instances 表示基于此任务参数,创建出几个任务实例,比如instances为2,则会创建出两个任务。

CMSIS-RTOS API定义的获取线程参数结构体的宏如下:

#define osThread(name)  \
    &os_thread_def_##name

管理线程参数的API如下:

API 描述
osThreadCreate 创建线程并开始执行
osThreadTerminate 停止线程执行
osThreadYield 线程主动让出
osThreadGetID 获取当前正在运行线程的ID
osThreadSetPriority 改变线程优先级
osThreadGetPriority 获取线程优先级
  • osThreadCreate
osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument);

其中osThreadId被定义为k_task_t指针类型:

typedef k_task_t *osThreadId;

返回值:TencentOS-tiny中的任务控制块类型指针。

  • osThreadTerminate
osStatus osThreadTerminate(osThreadId thread_id);

返回值:osStatus

  • osThreadYield
osStatus osThreadYield(void);

返回值:osStatus

  • osThreadGetID
osThreadId osThreadGetId(void);
  • osThreadSetPriority
osStatus osThreadSetPriority(osThreadId thread_id, osPriority priority);
  • osThreadGetPriority
osPriority osThreadGetPriority(osThreadId thread_id);

使用时需要特别注意,在TencentOS-tiny中,调用CMSIS-RTOS API提供的优先级选项设置之后,实际设置的任务值是不同的。

CMSIS-RTOS API提供的线程优先级宏定义如下:

typedef enum {
    osPriorityIdle          = -3,          ///< priority: idle (lowest)
    osPriorityLow           = -2,          ///< priority: low
    osPriorityBelowNormal   = -1,          ///< priority: below normal
    osPriorityNormal        =  0,          ///< priority: normal (default)
    osPriorityAboveNormal   = +1,          ///< priority: above normal
    osPriorityHigh          = +2,          ///< priority: high
    osPriorityRealtime      = +3,          ///< priority: realtime (highest)
    osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority
} osPriority;

在TecentOS-tiny中实现的时候进行了转化:

static k_prio_t priority_cmsis2knl(osPriority prio)
{
    if (prio == osPriorityError) {
        return K_TASK_PRIO_INVALID;
    }

    return (k_prio_t)(3 - prio);
}

static osPriority priority_knl2cmsis(k_prio_t prio)
{
    return (osPriority)(3 - prio);
}

比如创建线程时设置为 osPriorityNormal=0,则「实际设置的任务优先级为3」

2.3. 通用等待函数

CMSIS-RTOS提供的等待函数API如下:

API 描述
osDelay 等待指定的时间
osWait(可选) 等待信号、消息、邮箱的某个事件
  • osDelay
osStatus osDelay(uint32_t millisec);

返回值:osStatus。

2.4. 软件定时器管理

CMSIS-RTOS API提供的存储定时器参数的结构体如下:

typedef struct os_timer_def {
    os_ptimer                 cb;   ///< start address of a timer function
    k_timer_t                *timer;
} osTimerDef_t;

CMSIS-RTOS API提供的定义一个软件定时器的宏定义如下:

#define osTimerDef(name, function)  \
    k_timer_t timer_handler_##name; \
    const osTimerDef_t os_timer_def_##name = \
        { (os_ptimer)(function), (&(timer_handler_##name)) }

CMSIS-RTOS API定义的获取软件定时器参数结构体的宏如下:

#define osTimer(name) \
    &os_timer_def_##name

CMSIS-RTOS API提供的软件定时器管理API如下:

API 描述
osTimerCreate 创建一个软件定时器
osTimerStart 启动软件定时器
osTimerStop 停止软件定时器
osTimerDelete 删除软件定时器
  • osTimerCreate
osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type, void *argument);

其中osTimerId被定义为k_timer_t指针类型:

typedef k_timer_t *osTimerId;

type参数为 os_timer_type 类型,表示软件定时器的类型为单次触发或者周期触发:

typedef enum  {
    osTimerOnce             =     0,       ///< one-shot timer
    osTimerPeriodic         =     1        ///< repeating timer
} os_timer_type;
  • osTimerStart
osStatus osTimerStart(osTimerId timer_id, uint32_t millisec);

返回值:osStatus。

  • osTimerStop
osStatus osTimerStop(osTimerId timer_id)

返回值:osStatus。

  • osTimerDelete
osStatus osTimerDelete(osTimerId timer_id);

返回值:osStatus。

2.5. 信号量管理

CMSIS-RTOS API提供的存储信号量参数的结构体如下:

typedef struct os_semaphore_def {
    uint32_t                    dummy;  ///< dummy value.
    k_sem_t                    *sem;
} osSemaphoreDef_t;

CMSIS-RTOS API提供的定义一个信号量的宏定义如下:

#define osSemaphoreDef(name)  \
    k_sem_t sem_handler_##name; \
    const osSemaphoreDef_t os_semaphore_def_##name = { 0, (&(sem_handler_##name)) }

CMSIS-RTOS API定义的获取信号量参数结构体的宏如下:

#define osSemaphore(name)  \
    &os_semaphore_def_##name

CMSIS-RTOS API提供的信号量管理API如下:

API 描述
osSemaphoreCreate 创建一个信号量
osSemaphoreWait 等待信号量
osSemaphoreRelease 释放信号量
osSemaphoreDelete 删除信号量
  • osSemaphoreCreate
osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, int32_t count);

其中 osSemaphoreId 被定义为k_sem_t指针类型:

typedef k_sem_t *osSemaphoreId;
  • osSemaphoreWait
int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec);

返回值:int32_t ,正常返回当前count数,失败返回-1。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value
  • osSemaphoreRelease
osStatus osSemaphoreRelease(osSemaphoreId semaphore_id);

返回值:osStatus。

  • osSemaphoreDelete
osStatus osSemaphoreDelete(osSemaphoreId semaphore_id);

返回值:osStatus。

2.6. 互斥锁管理

CMSIS-RTOS API提供的存储互斥锁参数的结构体如下:

typedef struct os_mutex_def {
    uint32_t                    dummy;  ///< dummy value.
    k_mutex_t                  *mutex;
} osMutexDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#define osMutexDef(name)  \
    k_mutex_t mutex_handler_##name; \
    const osMutexDef_t os_mutex_def_##name = { 0, (&(mutex_handler_##name)) }

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#define osMutex(name)  \
    &os_mutex_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osMutexCreate 创建一个互斥锁
osMutexWait 等待获取互斥锁
osMutexRelease 释放互斥锁
osMutexDelete 删除互斥锁
  • osMutexCreate
osMutexId osMutexCreate(const osMutexDef_t *mutex_def);

其中 osMutexId 被定义为k_mutex_t指针类型:

typedef k_mutex_t *osMutexId;
  • osMutexWait
osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec);

返回值:osStatus 。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value
  • osMutexRelease
osStatus osMutexRelease(osMutexId mutex_id);

返回值:osStatus。

  • osMutexDelete
osStatus osMutexDelete(osMutexId mutex_id);

返回值:osStatus。

2.7. 静态内存池管理

CMSIS-RTOS API提供的存储静态内存池参数的结构体如下:

typedef struct os_pool_def {
    uint32_t                    pool_sz;    ///< number of items (elements) in the pool
    uint32_t                    item_sz;    ///< size of an item
    void                       *pool;       ///< pointer to memory for pool
    k_mmblk_pool_t             *mmblk_pool; ///< memory blk pool handler
} osPoolDef_t;

CMSIS-RTOS API提供的定义一个互斥锁的宏定义如下:

#define osPoolDef(name, no, type)   \
    k_mmblk_pool_t mmblk_pool_handler_##name; \
    uint8_t mmblk_pool_buf_##name[(no) * sizeof(type)]; \
    const osPoolDef_t os_pool_def_##name = \
        { (no), sizeof(type), (&((mmblk_pool_buf_##name)[0])), (&(mmblk_pool_handler_##name)) }

CMSIS-RTOS API定义的获取互斥锁参数结构体的宏如下:

#define osPool(name) \
 &os_pool_def_##name

CMSIS-RTOS API提供的互斥锁管理API如下:

API 描述
osPoolCreate 创建一块固定大小的静态内存池
osPoolAlloc 申请分配内存
osPoolCAlloc 申请分配一块内存并全部初始化为0
osPoolFree 申请回收内存
  • osPoolCreate
osPoolId osPoolCreate(const osPoolDef_t *pool_def);

其中 osPoolId 被定义为 k_mmblk_pool_t 指针类型:

typedef k_mmblk_pool_t *osPoolId;
  • osPoolAlloc
void *osPoolAlloc(osPoolId pool_id);
  • osPoolCAlloc
void *osPoolCAlloc(osPoolId pool_id);
  • osPoolFree
osStatus osPoolFree(osPoolId pool_id, void *block);

返回值:osStatus。

2.8. 消息队列管理

CMSIS-RTOS API提供的存储消息队列参数的结构体如下:

typedef struct os_messageQ_def {
    uint32_t                    queue_sz;   ///< number of elements in the queue
    uint32_t                    item_sz;    ///< size of an item
    void                       *pool;       ///< memory array for messages
    k_msg_q_t                  *queue;      ///< queue handler
} osMessageQDef_t;

CMSIS-RTOS API提供的定义一个消息队列的宏定义如下:

#define osMessageQDef(name, queue_sz, type)   \
    k_msg_q_t msg_q_handler_##name; \
    const osMessageQDef_t os_messageQ_def_##name = \
        { (queue_sz), sizeof(type), NULL, (&(msg_q_handler_##name)) }

CMSIS-RTOS API定义的获取消息队列参数结构体的宏如下:

#define osMessageQ(name) \
    &os_messageQ_def_##name

CMSIS-RTOS API提供的消息队列管理API如下:

API 描述
osMessageCreate 初始化一个消息队列
osMessagePut 向消息队列中加入数据
osMessageGet 从消息队列中取出数据
  • osMessageCreate
osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, osThreadId thread_id);

其中 osMessageQId 被定义为 k_msg_q_t 指针类型:

typedef k_msg_q_t *osMessageQId;
  • osMessagePut
osStatus osMessagePut(osMessageQId queue_id, uint32_t info, uint32_t millisec);

返回值:osStatus 。

因为TencentOS-tiny中消息队列实现机制的不同,此API中的 millisec 参数未用到。

  • osMessageGet
osEvent osMessageGet(osMessageQId queue_id, uint32_t millisec);

返回值:osEvent ,其中包含了事件信息和错误码,以及消息队列收到的值。

如果需要阻塞延时,参数应该设置为CMSIS-RTOS API提供的宏定义 osWaitForever :

#define osWaitForever     0xFFFFFFFF     ///< wait forever timeout value

3. 使用示例

3.1. 任务创建示例

#include <cmsis_os.h>

void task1_entry(void *arg)
{
    while(1)
    {
        printf("task1 is running...\r\n");
        osDelay(1000);
    }
}
osThreadDef(task1_entry, osPriorityNormal, 1512);

void task2_entry(void *arg)
{
    
    while(1)
    {
        printf("task2 is running...\r\n");
        osDelay(1000);
    }
}
osThreadDef(task2_entry, osPriorityNormal, 1512);

void application_entry(void *arg)
{

    osThreadCreate(osThread(task1_entry), NULL);
    osThreadCreate(osThread(task2_entry), NULL);
    
    return;
}

任务运行结果如下:

task1 is running...
task2 is running...
task1 is running...
task2 is running...
task1 is running...
task2 is running...

3.2. 软件定时器使用示例

#include <cmsis_os.h>

void timer1_cb(void *arg)
{
    printf("timer1 is timeout!\r\n");
}

void timer2_cb(void *arg)
{
    printf("timer2 is timeout!\r\n");
}

osTimerDef(timer1, timer1_cb);
osTimerDef(timer2, timer2_cb);

void application_entry(void *arg)
{
    osTimerId timer1;
    osTimerId timer2;
    
    timer1 = osTimerCreate(osTimer(timer1), osTimerOnce, NULL);
    timer2 = osTimerCreate(osTimer(timer2), osTimerPeriodic, NULL);
    
    osTimerStart(timer1, 5000);
    osTimerStart(timer2, 1000);
    
    return;
}

运行结果如下:

timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer1 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!
timer2 is timeout!

3.3. 信号量使用示例

#include <cmsis_os.h>

osSemaphoreId sync_sem_id;
osSemaphoreDef(sync_sem);

void task1_entry(void *arg)
{
    while(1)
    {
        printf("task1 is waiting sem forever...\r\n");
        osSemaphoreWait(sync_sem_id, osWaitForever);
        printf("task1 get sem!\r\n");
    }
}
osThreadDef(task1_entry, osPriorityNormal, 1512);

void task2_entry(void *arg)
{
    
    while(1)
    {
        printf("task2 will release a sem...\r\n");
        osSemaphoreRelease(sync_sem_id);
        osDelay(1000);
    }
}
osThreadDef(task2_entry, osPriorityNormal, 1512);

void application_entry(void *arg)
{
    sync_sem_id = osSemaphoreCreate(osSemaphore(sync_sem), 0);

    osThreadCreate(osThread(task1_entry), NULL);
    osThreadCreate(osThread(task2_entry), NULL);
    
    return;
}

运行结果为:

task1 is waiting sem forever...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...
task2 will release a sem...
task1 get sem!
task1 is waiting sem forever...

3.4. 互斥锁使用示例

#include <cmsis_os.h>

osMutexId sync_mutex_id;
osMutexDef(sync_mutex);

void task1_entry(void *arg)
{
    while(1)
    {
        osMutexWait(sync_mutex_id, osWaitForever);
        
        printf("task1 get mutex,doing sth...\r\n");
        HAL_Delay(1000);    //死循环占用CPU
        printf("task1 finish do sth!\r\n");
        
        osMutexRelease(sync_mutex_id);
        
        osDelay(1000);
    }
}
osThreadDef(task1_entry, osPriorityHigh, 1512);

void task2_entry(void *arg)
{
    
    while(1)
    {
        osMutexWait(sync_mutex_id, osWaitForever);
        
        printf("task2 get mutex,doing sth...\r\n");
        HAL_Delay(2000);    //死循环占用CPU
        printf("task2 finish do sth!\r\n");
        
        osMutexRelease(sync_mutex_id);
        
        osDelay(1000);
    }
}
osThreadDef(task2_entry, osPriorityNormal, 1512);

void application_entry(void *arg)
{
    sync_mutex_id = osMutexCreate(osMutex(sync_mutex));

    osThreadCreate(osThread(task1_entry), NULL);
    osThreadCreate(osThread(task2_entry), NULL);
    
    return;
}

运行结果为:

task1 get mutex,doing sth...
task1 finish do sth!
task2 get mutex,doing sth...
task2 finish do sth!
task1 get mutex,doing sth...
task1 finish do sth!
task1 get mutex,doing sth...
task1 finish do sth!
task2 get mutex,doing sth...

3.5. 动态内存使用示例

#include <cmsis_os.h>

typedef struct blk_st {
    int   id;
    char* payload;
blk_t;

#define MMBLK_BLK_NUM 10

osPoolDef (MemPool, MMBLK_BLK_NUM, blk_t);
osPoolId mem_pool_id;

void task1_entry(void *arg)
{   
    
    blk_t *ptr = NULL;
    osStatus err;
    
    /* 打印出一个块的大小 */
    printf("block size is %d bytes\r\n"sizeof(blk_t));
    
    /* 申请一个块 */
    ptr = osPoolAlloc(mem_pool_id);
    if (ptr == NULL) {
        printf("a mmblk alloc fail\r\n");
        return;
    }
    else {
        printf("a mmblk alloc success\r\n");
    }
    
    /* 使用该块 */
    ptr->id = 1;
    ptr->payload = "hello";
    printf("mmblk id:%d payload:%s\r\n", ptr->id, ptr->payload);
    
    /* 使用完毕之后释放 */
    err = osPoolFree(mem_pool_id, ptr);
    if (err != osOK) {
        printf("a mmblk free fail, err = %d\r\n", err);
        return;
    }
    else {
        printf("a mmblk free success\r\n");
    }
    
    while (1) {
        tos_task_delay(1000);
    }
}

#define STK_SIZE_TASK1      1024
osThreadDef(task1_entry, osPriorityNormal, 1, STK_SIZE_TASK1);

void application_entry(void *arg)
{
    //初始化静态内存池
    mem_pool_id = osPoolCreate(osPool(MemPool));
    if (mem_pool_id == NULL) {
        printf("mmblk pool create fail\r\n");
        return;
    }
    else {
        printf("mmblk pool create success\r\n");
    }

    //创建任务
    osThreadCreate(osThread(task1_entry), NULL);

    return;
}

运行结果为:

mmblk pool create success
block size is 8 bytes
a mmblk alloc success
mmblk id:1 payload:hello
a mmblk free success

3.6. 消息队列使用示例

#include <cmsis_os.h>

#define STK_SIZE_TASK_RECEIVER      512
#define STK_SIZE_TASK_SENDER        512

#define MESSAGE_MAX     10

osMessageQId msg_q_id;
osMessageQDef(msg_q,MESSAGE_MAX,uint32_t);

void task_receiver_entry(void *arg)
{
    osEvent event;
    osStatus ret;
    uint32_t value;

    while (1)
    {
        event = osMessageGet(msg_q_id, osWaitForever);
        ret = event.status;
        if (ret == osOK)
        {
            value = event.value.v;
            printf("receiver: msg incoming[%s]\r\n", (char*)value);
        }
    }
}
osThreadDef(task_receiver_entry, osPriorityNormal, 1, STK_SIZE_TASK_RECEIVER);

void task_sender_entry(void *arg)
{
    char *msg_prio_0 = "msg 0";
    char *msg_prio_1 = "msg 1";
    char *msg_prio_2 = "msg 2";

    printf("sender: post a messgae:[%s]\r\n", msg_prio_2);
    osMessagePut(msg_q_id,(uint32_t)msg_prio_2,0);
    
    printf("sender: post a messgae:[%s]\r\n", msg_prio_1);
    osMessagePut(msg_q_id,(uint32_t)msg_prio_1,0);
    
    printf("sender: post a messgae:[%s]\r\n", msg_prio_0);
    osMessagePut(msg_q_id,(uint32_t)msg_prio_0,0);

}
osThreadDef(task_sender_entry, osPriorityNormal, 1, STK_SIZE_TASK_SENDER);

void application_entry(void *arg)
{
    msg_q_id = osMessageCreate(osMessageQ(msg_q),NULL);

    osThreadCreate(osThread(task_receiver_entry), NULL);
    osThreadCreate(osThread(task_sender_entry), NULL);
    
    return;
}

运行结果为:

sender: post a messgae:[msg 2]
sender: post a messgae:[msg 1]
sender: post a messgae:[msg 0]
receiver: msg incoming[msg 2]
receiver: msg incoming[msg 1]
receiver: msg incoming[msg 0]


推荐阅读:

文本或代码中 \n 和 \r 的区别

几个类似 VS Code的开源编辑器工具

STM32中CRC计算单元,及CRC校验的应用


关注 微信公众号『strongerHuang』,后台回复“1024”查看更多内容,回复“加群”按规则加入技术交流群。


长按前往图中包含的公众号关注

strongerHuang 作者黄工,高级嵌入式软件工程师,分享嵌入式软硬件、物联网、单片机、开发工具、电子等内容。
评论
  • 天问Block和Mixly是两个不同的编程工具,分别在单片机开发和教育编程领域有各自的应用。以下是对它们的详细比较: 基本定义 天问Block:天问Block是一个基于区块链技术的数字身份验证和数据交换平台。它的目标是为用户提供一个安全、去中心化、可信任的数字身份验证和数据交换解决方案。 Mixly:Mixly是一款由北京师范大学教育学部创客教育实验室开发的图形化编程软件,旨在为初学者提供一个易于学习和使用的Arduino编程环境。 主要功能 天问Block:支持STC全系列8位单片机,32位
    丙丁先生 2024-12-11 13:15 63浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-12 10:13 40浏览
  • 一、SAE J1939协议概述SAE J1939协议是由美国汽车工程师协会(SAE,Society of Automotive Engineers)定义的一种用于重型车辆和工业设备中的通信协议,主要应用于车辆和设备之间的实时数据交换。J1939基于CAN(Controller Area Network)总线技术,使用29bit的扩展标识符和扩展数据帧,CAN通信速率为250Kbps,用于车载电子控制单元(ECU)之间的通信和控制。小北同学在之前也对J1939协议做过扫盲科普【科普系列】SAE J
    北汇信息 2024-12-11 15:45 112浏览
  • 在智能化技术快速发展当下,图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进步,对于图像数据的采集、处理和分析的需求日益增长,这不仅要求我们拥有高性能的相机硬件,还要求我们能够高效地集成和测试各种算法。我们探索了一种多源相机数据采集与算法集成测试方案,能够满足不同应用场景下对图像采集和算法测试的多样化需求,确保数据的准确性和算法的有效性。一、相机组成相机一般由镜头(Lens),图像传感器(Image
    康谋 2024-12-12 09:45 75浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-11 17:58 86浏览
  • 时源芯微——RE超标整机定位与解决详细流程一、 初步测量与问题确认使用专业的电磁辐射测量设备,对整机的辐射发射进行精确测量。确认是否存在RE超标问题,并记录超标频段和幅度。二、电缆检查与处理若存在信号电缆:步骤一:拔掉所有信号电缆,仅保留电源线,再次测量整机的辐射发射。若测量合格:判定问题出在信号电缆上,可能是电缆的共模电流导致。逐一连接信号电缆,每次连接后测量,定位具体哪根电缆或接口导致超标。对问题电缆进行处理,如加共模扼流圈、滤波器,或优化电缆布局和屏蔽。重新连接所有电缆,再次测量
    时源芯微 2024-12-11 17:11 109浏览
  • 应用环境与极具挑战性的测试需求在服务器制造领域里,系统整合测试(System Integration Test;SIT)是确保产品质量和性能的关键步骤。随着服务器系统的复杂性不断提升,包括:多种硬件组件、操作系统、虚拟化平台以及各种应用程序和服务的整合,服务器制造商面临着更有挑战性的测试需求。这些挑战主要体现在以下五个方面:1. 硬件和软件的高度整合:现代服务器通常包括多个处理器、内存模块、储存设备和网络接口。这些硬件组件必须与操作系统及应用软件无缝整合。SIT测试可以帮助制造商确保这些不同组件
    百佳泰测试实验室 2024-12-12 17:45 53浏览
  • 全球智能电视时代来临这年头若是消费者想随意地从各个通路中选购电视时,不难发现目前市场上的产品都已是具有智能联网功能的智能电视了,可以宣告智能电视的普及时代已到临!Google从2021年开始大力推广Google TV(即原Android TV的升级版),其他各大品牌商也都跟进推出搭载Google TV操作系统的机种,除了Google TV外,LG、Samsung、Panasonic等大厂牌也开发出自家的智能电视平台,可以看出各家业者都一致地看好这块大饼。智能电视的Wi-Fi连线怎么消失了?智能电
    百佳泰测试实验室 2024-12-12 17:33 53浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-12 10:27 62浏览
  • 近日,搭载紫光展锐W517芯片平台的INMO GO2由影目科技正式推出。作为全球首款专为商务场景设计的智能翻译眼镜,INMO GO2 以“快、准、稳”三大核心优势,突破传统翻译产品局限,为全球商务人士带来高效、自然、稳定的跨语言交流体验。 INMO GO2内置的W517芯片,是紫光展锐4G旗舰级智能穿戴平台,采用四核处理器,具有高性能、低功耗的优势,内置超微高集成技术,采用先进工艺,计算能力相比同档位竞品提升4倍,强大的性能提供更加多样化的应用场景。【视频见P盘链接】 依托“
    紫光展锐 2024-12-11 11:50 72浏览
  • 铁氧体芯片是一种基于铁氧体磁性材料制成的芯片,在通信、传感器、储能等领域有着广泛的应用。铁氧体磁性材料能够通过外加磁场调控其导电性质和反射性质,因此在信号处理和传感器技术方面有着独特的优势。以下是对半导体划片机在铁氧体划切领域应用的详细阐述: 一、半导体划片机的工作原理与特点半导体划片机是一种使用刀片或通过激光等方式高精度切割被加工物的装置,是半导体后道封测中晶圆切割和WLP切割环节的关键设备。它结合了水气电、空气静压高速主轴、精密机械传动、传感器及自动化控制等先进技术,具有高精度、高
    博捷芯划片机 2024-12-12 09:16 85浏览
  • 首先在gitee上打个广告:ad5d2f3b647444a88b6f7f9555fd681f.mp4 · 丙丁先生/香河英茂工作室中国 - Gitee.com丙丁先生 (mr-bingding) - Gitee.com2024年对我来说是充满挑战和机遇的一年。在这一年里,我不仅进行了多个开发板的测评,还尝试了多种不同的项目和技术。今天,我想分享一下这一年的故事,希望能给大家带来一些启发和乐趣。 年初的时候,我开始对各种开发板进行测评。从STM32WBA55CG到瑞萨、平头哥和平海的开发板,我都
    丙丁先生 2024-12-11 20:14 73浏览
  • RK3506 是瑞芯微推出的MPU产品,芯片制程为22nm,定位于轻量级、低成本解决方案。该MPU具有低功耗、外设接口丰富、实时性高的特点,适合用多种工商业场景。本文将基于RK3506的设计特点,为大家分析其应用场景。RK3506核心板主要分为三个型号,各型号间的区别如下图:​图 1  RK3506核心板处理器型号场景1:显示HMIRK3506核心板显示接口支持RGB、MIPI、QSPI输出,且支持2D图形加速,轻松运行QT、LVGL等GUI,最快3S内开
    万象奥科 2024-12-11 15:42 88浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦