Linux下基于最新稳定版ESP-IDF5.3.2开发esp32s3入门任务间的通讯-信号量【入门三】
继续上一篇任务创建
【Linux下基于最新稳定版ESP-IDF5.3.2开发esp32s3入门任务创建【入门二】-CSDN博客】
今天要实现再创建一个任务。【二值和互斥都进行测试】
①、通过任务A发送一个信号量,另一个任务得到信号量后再发送helloworld。
②、两个任务通过互斥信号量打印消息。
一、创建任务。
这和上一篇一样,我们再创建一个同样优先级的任务SendSemTask
xTaskCreatePinnedToCore(SendSemTask,
"SendSemTask",
2048,
NULL,
4,
NULL,
1);
二、先来看下我们要用到的API
1、xSemaphoreCreateBinary()创建二值信号量
2、xSemaphoreTake(xSemaphore, xBlockTime)等待一个信号量【形参:xSemaphore信号量句柄,xBlockTime等等时间】【返回:pdTRUE才是获取到】
3、xSemaphoreGive(xSemaphore)发送一个信号量
注意:我们这里是任务间的通讯所以使用以上的三个API,如果你要在中断中使用需要使用带FromISR结尾的API。
如:xSemaphoreTakeFromISR。
三、创建二值信号量【因为参数有句柄->所以我们需要先定义一个信号量句柄】
SemaphoreHandle_t s_tSem;
创建信号量,这个信号量创建需要再任务创建前就创建好。因为任务中要用。
s_tSem = xSemaphoreCreateBinary();
四、任务中发送信号量
1000ms发送一个信号量
xSemaphoreGive(s_tSem);
五、获取信号量,获取到信号量打印get semaphore
获取信号量,我们等等时间使用一直等等。也就是得到一个信号量才往下执行输出
xSemaphoreTake(s_tSem, portMAX_DELAY)
注意:我这里是使用一直等等,所以没有vTaskDelay。如果你使用0。那就必须要等等,否则优先级比该任务低的任务都不能得到执行。
六、编译下载验证【和预期的一样1000ms打印一次】
===========================以下测试互斥信号量===============================
为什么我们要使用互斥信号量?
实际项目中我们的系统往往是多个任务运行的,而且各个任务优先级是不一样的,如果多个任务刚好又需要用到同一资源的时候,这时候多个任务调用这共有资源的时刻是不确定的。
假如:低优先级的任务先使用资源的时候,如果还没有使用完,高优先级的任务也使要用这共有资源就会打断低优先级的任务,这时候可能:低优先级执行异常甚至系统奔溃。
所以我们希望的是等低优先级任务使用完这资源后,这资源再被其他任务使用。
一、重新cp一份刚才的工程【可以修改下文件名,我修改如下】
二、先来看下我们要用到的API
创建互斥锁:xSemaphoreCreateMutex()也可以用上面的信号量创建函数。
三、定义一个打印函数,这里增加延迟是为了模拟出效果。
void testPrintf(char *param)
{
printf("%s starting\r\n", param);
printf("1======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("2======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("3======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("4======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("5======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("6======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("7======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("8======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("9======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("1======2345678\r\n");
vTaskDelay(100 / portTICK_PERIOD_MS);
printf("%s end\r\n", param);
}
四、创建两个任务,两个任务的优先级需要不一样。【这里一个优先级3,一个优先级4】
// 创建一个互斥信号量
s_tMux = xSemaphoreCreateMutex();
xTaskCreatePinnedToCore(TaskA,
"TaskA",
2048,
NULL,
3,
NULL,
1);
xTaskCreatePinnedToCore(TaskB,
"TaskB",
2048,
NULL,
4,
NULL,
1);
五、两个任务都打印testPrintf【我们先不使用互斥信号量看下效果】
void TaskA(void *param)
{
while(1)
{
testPrintf("TaskA");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void TaskB(void *param)
{
while(1)
{
testPrintf("TaskB");
vTaskDelay(900 / portTICK_PERIOD_MS);
}
}
六、下载验证。看下效果
七、增加互斥信号量看下效果【这里的互斥信号量和前面的信号量是一样的】
void TaskA(void *param)
{
while(1)
{
xSemaphoreTake(s_tMux, portMAX_DELAY);
testPrintf("TaskA");
xSemaphoreGive(s_tMux);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void TaskB(void *param)
{
while(1)
{
xSemaphoreTake(s_tMux, portMAX_DELAY);
testPrintf("TaskB");
xSemaphoreGive(s_tMux);
vTaskDelay(900 / portTICK_PERIOD_MS);
}
}
这里申请一个信号量后,等使用完了,再释放。
八、下载验证。【最后的1是打印任务是1-9-1打印】
至此,实现了互斥锁。下一篇我们一起看下消息队列。