一、同步定义
同步(Synchronization),用于任务间同步及通信。
SYS/BIOS系统中用于线程同步的组件:
信号量(Semaphore)、事件(Event Module)、门(Gate)、邮箱(Mailboxe)、队列(Queue)
二、信号量
信号量通常用于协调一些处于竞争关系的任务之间对于共享资源的访问。
如图,信号量分为两种类型,一种是二进制型信号量,另外一种是计数型信号量。这两种类型一般用于不同的两种情况。例如,二进制型信号量通常用于LED灯的开启/关闭(两个任务之间),而计数型信号量常用于假如一个16kB的存储空间,每往外读1kB的值,计数值就减一(多个任务之间)。当使用Semaphore_pend(sem)语句后,信号量的计数值变为0,任务挂起;当使用Semaphore_post(sem)语句后,信号量的计数值大于等于1,任务恢复。
Semaphore_pend用于等待信号量。当计数值等于0,Semaphore_pend等待直到信号量被Semaphore_post()释放;当计数值大于0,Semaphore_pend只是将计数值递减并返回。
超时参数为timeout,允许任务等待设定的时间直到超时。等待时间可以设置为一个计数器timeout长度,也可以设置为一直等待(BIOS_WAIT_FOREVER)或根本不等待(BIOS_NO_WAIT)。Semaphore_pend()的返回值为获取信号量是否成功。
SYS/BIOS系统的应用程序当前只有一个线程执行,线程执行的顺序是确定的,不是Linux系统轮询(相同优先级的线程随机排序)处理的方式。
信号量计数值为0,任务A使用Semaphore_pend(sem,BIOS_WAIT_FOREVER)等待获取信号量,未获取信号量就一直等待。任务B对共享资源进行修改后,Semaphore_post(sem)释放信号量。任务B释放信号量后,任务A获得信号量从而获得共享资源的访问权。
静态配置(使用Semaphore信号量组件,并创建句柄sem,设置为全局变量,初始值为1):
var Semaphore = xdc.useModule('ti.sysbios.knl.Semaphore');
Program.global.sem = Semaphore.create(1);
动态配置:
#include <ti/sysbios/knl/Semaphore.h>
Semaphore_Handle sem;
Semaphore_Params semParams;
Semaphore_Params_init(&semParams);
semParams.mode = Semaphore_Mode_BINARY;
sem = Semaphore_create(1,&semParams,NULL);
SYS/BIOS系统可以有多个.cfg文件,如果工程比较复杂的话,每个.cfg文件分别可以放不同的组件,只要不产生冲突就可以。错误块,主要用于出现错误时,通过错误块捕获更为详细的错误信息。
在C源文件中操作对象句柄需要引用(例如上文配置中的句柄sem):
#include <xdc/cfg/global.h>
信号量相关函数:
三、实验结果
1、实验一
代码:
/*
* task.c
*
* Created on: 2024-3-11
* Author: ouc
*/
#include <stdio.h>
#include <xdc/std.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Memory.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/IHeap.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>
#define task1addr 0x80000000
#define task2addr 0x80000005
Task_Handle task1;
Task_Handle task2;
Semaphore_Handle sem;
uint8_t *buffer1 = (uint8_t *) task1addr, *buffer2 = (uint8_t *) task2addr;
void Delay(unsigned int n)
{
unsigned int i;
for(i = n; i > 0; i--);
};
// Task 1
void TaskMain1()
{
System_printf("Enter the TaskMain1!\n");
System_flush();
for(;;)
{
if(Semap