赞
踩
复习时间:貌似很遥远呀!(未定期)
Cortex微控制器软件接口标准,Cortex-M系列的RTOS接口,为需要RTOS的软件组件提供了标准化API访问内核或外设。更多API参考:
https://arm-software.github.io/CMSIS_5/RTOS2/html/index.html
是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关。
使用系统队列(FIFO)和任务资源,定时时间短优先被触发。
创建定时器:osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr);
启动定时器:osTimerStart (osTimerId_t timer_id, uint32_t ticks);
停止定时器:osTimerStop (osTimerId_t timer_id);
删除定时器:osTimerDelete (osTimerId_t timer_id);
exec1 = 1U; id1 = osTimerNew(Timer1_Callback, osTimerOnce, &exec1, NULL); if (id1 != NULL) { // Hi3861 1U=10ms,100U=1S timerDelay = 100U; //T1延时1s status = osTimerStart(id1, timerDelay); if (status != osOK) { // Timer could not be started } } osDelay(50U); //系统延时0.5s status = osTimerStop(id1); //停止T1 if(status != osOK) { printf("stop Timer1 failed\r\n"); /*停止失败(单次定时器未在延时时间内停止): 假设我在2s的时候去停止而T1只延时了1s, 其实已经停止了,这时再去停止就会停止失败*/ } else { printf("stop Timer1 success\r\n"); //停止成功(0.5s停止会成功) //单词定时器得在其运行期间去停止 } status = osTimerStart(id1, timerDelay); if (status != osOK) { printf("start Timer1 failed\r\n"); } osDelay(200U); //系统延时2s status = osTimerDelete(id1); //删除T1,定时器运行期间前后都能停止 if(status != osOK) { printf("delete Timer1 failed\r\n"); //删除失败 } else { printf("delete Timer1 success\r\n"); //删除成功 }
互斥
同步
初始化
创建
申请-1(0状态无法申请)
释放+1
删除
创建互斥锁:osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
获取互斥锁:osSemaphoreAcquire (osSemaphoreId_t semaphore_id, uint32_t timeout);
释放互斥锁:osSemaphoreRelease (osSemaphoreId_t semaphore_id);
删除互斥锁:osMutexDelete (osMutexId_t mutex_id);
实验没太明白,聪明的人可以通过拓展实验而做出另一个实用性实验,我还没达到那个能力,确实努力可以弥补一些这方面的能力,目前也只有努力这种方法了,多看看基础如51/32等,形成嵌入式方向思考的能力和举一反三(我没有举一反三的聪明天赋只能努力多看多学优秀的人的智慧结晶)的能力。
首先创建任务(osThreadNew)《P10-任务管理》设置优先级为同级
osSemaphoreNew (uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr);
sem1 = osSemaphoreNew(4, 0, NULL);
任务间通信的机制,可实现任务间的同步,事件可提供一对多、多对多的同步操作。
a任务:事件2、3逻辑或(osFlagsWaitAny)
b任务:事件2、5逻辑与(osFlagsWaitAll)
事件2发生,a任务唤醒
事件5发生,b任务才唤醒
/***** 发送事件 *****/ void Thread_EventSender (void *argument) { (void)argument; while (1) { osEventFlagsSet(evt_id, FLAGS_MSK1); osThreadYield(); // suspend thread osDelay(100); } } /***** 接收事件 *****/ void Thread_EventReceiver (void *argument) { (void)argument; uint32_t flags; while (1) { flags = osEventFlagsWait(evt_id, FLAGS_MSK1, osFlagsWaitAny, osWaitForever); printf("Receive Flags is %d\n",flags); } } /***** 创建事件 *****/ static void Event_example (void) { evt_id = osEventFlagsNew(NULL); if (evt_id == NULL) { printf("Falied to create EventFlags!\n"); } osThreadAttr_t attr; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024*4; attr.priority = 25; attr.name = "Thread_EventSender"; if (osThreadNew(Thread_EventSender, NULL, &attr) == NULL) { printf("Falied to create Thread_EventSender!\n"); } attr.name = "Thread_EventReceiver"; if (osThreadNew(Thread_EventReceiver, NULL, &attr) == NULL) { printf("Falied to create Thread_EventReceiver!\n"); } }
/***** 发送事件 *****/ void Thread_EventSender(void *argument) { (void)argument; while (1) { osEventFlagsSet(evt_id, FLAGS_MSK1); osEventFlagsSet(evt_id, FLAGS_MSK2); osEventFlagsSet(evt_id, FLAGS_MSK3); //suspend thread osThreadYield(); osDelay(100); } } /***** 接收事件 *****/ void Thread_EventReceiver(void *argument) { (void)argument; uint32_t flags; while (1) { flags = osEventFlagsWait(evt_id, FLAGS_MSK1|FLAGS_MSK2|FLAGS_MSK3, osFlagsWaitAll, osWaitForever); //多个事件对应一个任务 printf("Receive Flags is %d\n", flags); } }
互斥锁在操作系统中用于资源管理。微控制器中许多资源可以重复使用,但每次只能被一个线程使用(例如通信通道、内存和文件)。互斥锁用于保护对共享资源的访问。创建互斥锁,然后在线程之间传递(线程可以获取和释放互斥锁)。
互斥锁又称互斥型信号量,特殊的二值性信号量,对共享资源保护而实现独占式处理。
任务持有(闭锁)—任务释放(开锁)
可解决信号量存在的优先级翻转问题(优先级继承算法)。
互斥锁处理非共享资源的同步访问时,若有任务访问该资源,则互斥锁为加锁状态。其他任务访问会被阻塞,该锁任务释放,其他任务进行资源访问,再次上锁。如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。
创建互斥锁:osMutexNew (const osMutexAttr_t *attr);
获取互斥锁:osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
释放互斥锁:osMutexRelease (osMutexId_t mutex_id);
删除互斥锁:osMutexDelete (osMutexId_t mutex_id);
/***** 高优先级 *****/ void HighPrioThread(void) { osDelay(100U); // wait 1s until start actual work while(1) { osMutexAcquire(mutex_id, osWaitForever); // try to acquire mutex printf("HighPrioThread is runing.\r\n"); osDelay(300U); osMutexRelease(mutex_id); } } /***** 中优先级 *****/ void MidPrioThread(void) { osDelay(100U); // wait 1s until start actual work while(1) { printf("MidPrioThread is runing.\r\n"); osDelay(100); } } /***** 低优先级 *****/ void LowPrioThread(void) { while(1) { osMutexAcquire(mutex_id, osWaitForever); //申请 printf("LowPrioThread is runing.\r\n"); osDelay(300U); // block mutex for 5s osMutexRelease(mutex_id); //释放 } } void Mutex_example(void) { osThreadAttr_t attr; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024 * 4; attr.name = "HighPrioThread"; attr.priority = 26; if (osThreadNew((osThreadFunc_t)HighPrioThread, NULL, &attr) == NULL) { printf("Falied to create HighPrioThread!\n"); } attr.name = "MidPrioThread"; attr.priority = 25; if (osThreadNew((osThreadFunc_t)MidPrioThread, NULL, &attr) == NULL) { printf("Falied to create MidPrioThread!\n"); } attr.name = "LowPrioThread"; attr.priority = 24; if (osThreadNew((osThreadFunc_t)LowPrioThread, NULL, &attr) == NULL) { printf("Falied to create LowPrioThread!\n"); } mutex_id = osMutexNew(NULL); if (mutex_id == NULL) { printf("Falied to create Mutex!\n"); } }
问:为什么LOW首先获取申请互斥锁呢?
答:高/中优先级都osDelay(100U);可以复习下《任务管理》中的时间概念和《软件定时器》
void HighPrioThread(void) { // wait 1s until start actual work osDelay(100U); osStatus_t status; while (1) { // try to acquire mutex status = osMutexAcquire(mutex_id, osWaitForever); //申请互斥锁并返回一个状态值 if(status != osOK) { printf("acquire mutex failed\r\n"); //互斥锁申请失败 } else { printf("acquire mutex success\r\n"); //互斥锁申请成功 } printf("HighPrioThread is runing.\r\n"); osDelay(300U); status = osMutexRelease(mutex_id); //释放互斥锁 if(status != osOK) { printf("release mutex failed\r\n"); //互斥锁释放失败 } else { printf("release mutex success\r\n"); //互斥锁释放成功 } } } void LowPrioThread(void) { osStatus_t status; while (1) { status = osMutexAcquire(mutex_id, osWaitForever); printf("LowPrioThread is runing.\r\n"); if(status != osOK) { printf("acquire mutex failed\r\n"); } else { printf("acquire mutex success\r\n"); } // block mutex for 3s osDelay(300U); status = osMutexRelease(mutex_id); if(status != osOK) { printf("release mutex failed\r\n"); } else { printf("release mutex success\r\n"); } } } status = osMutexDelete(mutex_id); //删除互斥锁并返回一个状态值 if(status != osOK) { printf("delete mutex failed\r\n"); //删除互斥锁失败 } else { printf("delete mutex success\r\n"); //删除互斥锁成功 } status = osMutexDelete(mutex_id); //再次删除互斥锁并返回一个状态值,再次删除肯定失败,因为互斥锁已经不存在 if(status != osOK) { printf("delete mutex failed\r\n"); //删除互斥锁失败 } else { printf("delete mutex success\r\n"); //删除互斥锁成功 }
创建消息队列:osMutexNew (const osMutexAttr_t *attr);
发送消息:osMutexAcquire (osMutexId_t mutex_id, uint32_t timeout);
获取消息:osMutexRelease (osMutexId_t mutex_id);
删除消息队列:osMutexDelete (osMutexId_t mutex_id);
#include <stdio.h> #include <string.h> #include <unistd.h> #include "ohos_init.h" #include "cmsis_os2.h" //number of Message Queue Objects #define MSGQUEUE_OBJECTS 16 typedef struct { //object data type char *Buf; uint8_t Idx; } MSGQUEUE_OBJ_t; MSGQUEUE_OBJ_t msg; //message queue id osMessageQueueId_t mid_MsgQueue; void Thread_MsgQueue1(void *argument) { (void)argument; //do some work... msg.Buf = "Hello BearPi-HM_Nano!"; msg.Idx = 0U; while (1) { //消息队列ID、消息内容、优先级、超时时间(0表示立刻) //when timeout is 0, the function returns instantly osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U); //suspend thread osThreadYield(); osDelay(100); } } void Thread_MsgQueue2(void *argument) { (void)argument; osStatus_t status; while (1) { //Insert thread code here... //wait for message //消息队列ID、消息内容、优先级、超时时间 status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U); if (status == osOK) { //msg为结构体类型 printf("Message Queue Get msg:%s\n", msg.Buf); } } } static void Message_example(void) { //创建并初始化一个消息队列对象,返回值为消息队列ID mid_MsgQueue = osMessageQueueNew(MSGQUEUE_OBJECTS, 100, NULL); if (mid_MsgQueue == NULL) { printf("Falied to create Message Queue!\n"); } osThreadAttr_t attr; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024 * 10; attr.priority = 25; attr.name = "Thread_MsgQueue1"; if (osThreadNew(Thread_MsgQueue1, NULL, &attr) == NULL) { printf("Falied to create Thread_MsgQueue1!\n"); } attr.name = "Thread_MsgQueue2"; if (osThreadNew(Thread_MsgQueue2, NULL, &attr) == NULL) { printf("Falied to create Thread_MsgQueue2!\n"); } } APP_FEATURE_INIT(Message_example);
num和count还不明白内部原理,虽能自圆其说,但感觉仍是一知半解。num是put和get才+1,而count是当前消息队列中的数量,对其内部全然不知(挖坑+1)
void Thread_MsgQueue1(void *argument) { (void)argument; uint8_t num = 0; //do some work... msg.Buf = "Hello BearPi-HM_Nano!"; while (1) { msg.Idx = num; osMessageQueuePut(mid_MsgQueue, &msg, 0U, 0U); //消息队列内部计数(非阻塞态) num++; //suspend thread osThreadYield(); osDelay(100); } } void Thread_MsgQueue2(void *argument) { (void)argument; osStatus_t status; uint32_t count; while (1) { //Insert thread code here... //计数消息队列中的队列消息数量(包含阻塞量) count = osMessageQueueGetCount(mid_MsgQueue); printf("message queue get count: %d\r\n",count); if(count == MSGQUEUE_OBJECTS) { //若满足最大消息队列数执行Delete osMessageQueueDelete(mid_MsgQueue); } //wait for message status = osMessageQueueGet(mid_MsgQueue, &msg, NULL, 0U); if (status == osOK) { printf("Message Queue Get msg idx:%d buf:%s\n", msg.Idx,msg.Buf); } osDelay(300); } }
全文从下往上熟悉程度依次递减
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。