freeRTOS的基本使用

本文介绍了非阻塞性延时函数在Arduino中的使用,探讨了任务创建、句柄作为共享资源的标识,以及互斥量(MUTEX)在防止竞争冒险中的作用。还涉及如何将任务固定到特定核心和使用软件定时器进行定时操作。
摘要由CSDN通过智能技术生成
/* 非阻塞性延时函数
   arg:需要延迟多少tick
   portTICK_PERIOD_MS:表1个tick的时间,arduino里通常为1ms
*/
vTaskDelay(delaytime/portTICK_PERIOD_MS);

/* 创建任务
   返回值:如果任务创建成功,返回pdPASS
*/
BaseType_t xTaskCreate(	TaskFunction_t pxTaskCode,      // 传递需要任务处理的函数的地址
		                const char * const pcName,	    // 确定该任务的名字
		                const configSTACK_DEPTH_TYPE usStackDepth,   // 任务占内存大小(字节)
		                void * const pvParameters,      // 传入到处理函数的参数
		                UBaseType_t uxPriority,         // 优先级,s数值越大优先级越高
		                TaskHandle_t * const pxCreatedTask )    // 对任务操作,一般填NULL


// 杀掉该任务(进程)
vTaskDelete( xTaskHandle xTaskToDelete );

在下文中使用到了句柄这个概念,我的理解是:在多线程任务中,如果我要使用某个对象,那么需要在内存中开辟空间,每个线程或任务分配独立的对象副本,这会导致内存的浪费。为了节约资源,从而引入句柄。通过使用句柄,程序可以在内存中只存储一个对象的引用或指针,而不是为每个线程或任务创建独立的对象副本。这样,多个线程或任务可以通过共享同一个对象引用而访问同一个对象,从而节省内存空间。那么此刻的句柄就可以理解为一个地址簿,记录共享对象的内存地址。

// MUTEX 全局共享变量防止竞争冒险操作
SemaphoreHandle_t xxx;    // 创建xxx句柄

xxx = xSemaphoreCreateMutex(); //创建MUTEX

xSemaphoreTake(xxx, timeOut); // 请求权限,timeOut为请求时间
xSemaphoreGive(xMutexMPU6050); // 释放权限、
// 这里可以用if语句来尝试请求权限,如果请求成功,则执行{}内操作。
// xxx就像一把钥匙,拥有钥匙的人才能访问房间

上面这段代码的理解:

句柄(Handle)

句柄可以看作是一个“标签”或“指针”,它指向了一个具体的对象(在这个案例中是互斥量对象)。句柄本身不包含对象的全部数据,而只是指向对象在内存中的位置或提供了一种访问对象的方式。

互斥量(Mutex)

互斥量是一种同步原语,用于保护共享资源,防止多个任务或线程同时访问,造成数据混乱。

图文解释

想象一下你有一个保险箱(代表共享资源),多个人(代表多个任务或线程)都想要打开这个保险箱取东西。为了确保一次只有一个人可以打开保险箱,你使用了一把锁(代表互斥量)来锁住保险箱。

现在,每个人都知道保险箱的位置,但他们不知道锁的密码或钥匙在哪里。这时,管理员(代表操作系统或RTOS)给每个人分发了一张纸条(代表句柄),纸条上写着锁的密码或指示了钥匙的位置。

图示说明:
保险箱:代表共享资源,需要被保护以防止同时访问。
锁:代表互斥量,用于锁住保险箱。
人:代表多个任务或线程,想要访问保险箱。
纸条:代表句柄,提供了访问锁(互斥量)的方法。

 在这个例子中,每个人通过他们手中的纸条(句柄)找到了锁的密码或钥匙,然后依次打开保险箱。当一个人打开保险箱时,其他人必须等待,直到保险箱再次被锁住,下一个人才可以使用他的纸条来打开保险箱。

这就是句柄在互斥量中的作用:它提供了一种机制,让任务或线程能够有序地访问共享资源,确保数据的一致性和系统的稳定性。

// 将任务放入核心0,最后一个参数表放入核心多少
xTaskCreatePinnedToCore(task1, "Task1", 1024, NULL, 1, NULL,0);

// 查看当前执行任务在核心几
Serial.println(xPortGetCoreID());
// 绝对频率的绝对延时
TickType_t xxx = xTaskGetTickCount();    // xxx装入此时的tick计数值

const TickType_t xFrequency = 3000;      // 间隔 3000 ticks = 3 seconds

vTaskDelayUntil(&xxx, xFrequency);       // 传入计数值,和频率时间。从xxx开始延迟3s

//软件定时器
TimerHandle_t xxx;    // 创建句柄

/*创建一个定时器
  返回值:一个句柄,用于后续引用和操作这个定时器。
*/
TimerHandle_t xTimerCreate(  
    const char * const pcTimerName,      // 定时器的名称,用于标识定时器。
    TickType_t xTimerPeriodInTicks,      // 定时器的周期,以时钟节拍为单位。
    UBaseType_t uxAutoReload,            // 指定定时器是否自动重载。如果设置为pdTRUE,则当定时
                                       // 器达到其周期时,它将自动重置并重新开始计时。如果设置为
                                       // pdFALSE,则定时器只会在达到其周期时触发一次回调函数。
    void * pvTimerID,                  // 一个指针,存储与定时器关联的标识符。可以设置为 NULL。
    TimerCallbackFunction_t pxCallbackFunction  // 一个指向回调函数的指针,该函数将在定时器达到
                                                // 其周期时被调用。
);


//回调函数例子。xTimer:定时器的句柄,用于标识被触发的定时器。
void timerCallbackFunction(TimerHandle_t xTimer);


//开始定时
BaseType_t xTimerStart( TimerHandle_t xTimer,      // 要启动的定时器的句柄
                        TickType_t xTicksToWait ); // 等待启动操作的时间,以时钟节拍为单位。
                                                   // 如果设置为0,则函数会立即返回而不等待。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值