对于全局变量:
uint32_t sum = 0;
两个任务,task1和task2,如果task1用于修改变量,而task2用while(sum ==1)来访问变量,会导致task2后面的任务不成功;因为这时候的sum已经被编译器优化到寄存器里了,后面死循环的while都是访问寄存器的值而不直接访问到内存,但是task1修改的值放在了内存ram中;
这时候需要volatile uint32_t sum = 0;防止编译器优化。
但是使用全局变量来控制资源访问有缺陷
当taskA刚好执行了if就被taskB抢占,就会导致双task使用同一个资源,这种情况需要使用cpu的原子锁。
任务的实际切换动作,是在一条汇编指令执行完之后才发生的,而不是在执行完一行C语言代码后;所以你无法通过简单的c语言指令来修改新信号量的值以期望完美控制资源的访问。

而如果考虑到关闭中断后修改信号量,再修改完成后再打开信号量,那确实可以实现资源的控制;但是会导致会使用这个信号量的任务依旧会抢占cpu资源,导致cpu效率降低。
这里选择修改信号量后就恢复中断,而不是完成整个任务后恢复,是因为需要保证其他不使用到当前信号量的任务也正常工作。
int LCD_PrintString(int x, int y, char *str)
{
static int bCanUse = 1;
disable_irq();
if (bCanUse)
{
bCanUse = 0;
enable_irq();
/使用LCD*/
bCanUse = 1;
return 0;
}
enable_irq();
return -1;
}
对于信号量
上面的全局变量就相当于信号量,不过freertos中,有为信号量打造了一套函数。
创建信号量的函数:
| 函数名 | 功能描述 | 参数说明 | 返回值 | |
|---|---|---|---|---|
xSemaphoreCreateBinary() | 创建二值信号量。创建后信号量初始为“空”,需要先调用 xSemaphoreGive() 才能使用 xSemaphoreTake() 获取。 | 无 | 成功返回信号量句柄 (SemaphoreHandle_t),失败返回 NULL。 | |
xSemaphoreCreateCounting(uxMaxCount, uxInitialCount) | 创建计数信号量。适用于事件计数或资源管理。 | uxMaxCount:最大计数值;uxInitialCount:初始计数值。 | 成功返回信号量句柄,失败返回 NULL。 | |
xSemaphoreCreateMutex() | 创建互斥量。与二值信号量类似,但包含了用于解决优先级反转问题的优先级继承机制。 | 无 | 成功返回互斥量句柄,失败返回 NULL。 | |
xSemaphoreCreateRecursiveMutex() | 创建递归互斥量。允许拥有它的任务重复获取(即嵌套使用),获取多少次就必须释放多少次。 | 无 | 成功返回递归互斥量句柄,失败返回 NULL。 |
访问信号量的函数:
| 函数名 | 功能描述 | 参数说明 | 返回值 | |
|---|---|---|---|---|
xSemaphoreGive(xSemaphore) | 释放信号量或互斥量(宏)。用于增加信号量的计数值。 | xSemaphore:要释放的信号量句柄。 | 成功返回 pdTRUE。 | |
xSemaphoreTake(xSemaphore, xTicksToWait) | 获取信号量或互斥量(宏)。用于减少信号量的计数值。 | xSemaphore:要获取的信号量句柄;xTicksToWait:阻塞等待的最大时间(Tick 数),portMAX_DELAY 表示无限等待。 | 成功获取返回 pdTRUE,超时返回 pdFALSE。 | |
xSemaphoreGiveFromISR(xSemaphore, pxHigherPriorityTaskWoken) | 在中断服务程序中释放信号量。是 xSemaphoreGive 的中断安全版本。 | xSemaphore:信号量句柄;pxHigherPriorityTaskWoken:用于标记是否需要进行上下文切换。 | 成功返回 pdTRUE。 | |
xSemaphoreTakeFromISR(xSemaphore, pxHigherPriorityTaskWoken) | 在中断服务程序中获取信号量。很少使用。 | xSemaphore:信号量句柄;pxHigherPriorityTaskWoken:用于标记是否需要进行上下文切换。 | 成功获取返回 pdTRUE,失败返回 errQUEUE_EMPTY。 | |
xSemaphoreGiveRecursive(xRecursiveMutex) | 释放递归互斥量。必须与 xSemaphoreTakeRecursive 配对使用。 | xRecursiveMutex:递归互斥量句柄。 | 成功返回 pdTRUE。 | |
xSemaphoreTakeRecursive(xRecursiveMutex, xTicksToWait) | 获取递归互斥量。任务可以多次获取同一个递归互斥量。 | xRecursiveMutex:递归互斥量句柄;xTicksToWait:阻塞等待时间。 | 成功获取返回 pdTRUE,超时返回 pdFALSE。 |
同步和互斥
同步:特指任务的执行顺序。比如taskA采集原始数据后,再交给taskB进行处理。
互斥:特指对资源的竞争访问。比如对厕所的使用,厕所同一时间只允许一个人用。虽然看上去这也像是顺序,但这里并不讲究执行顺序,而是资源竞争。
2600

被折叠的 条评论
为什么被折叠?



