RTOS信号量
概述
信号量就是一个带事件控制块的计数器,在其上定义了三个操作:
- 可以被初始化为一个非负数。
- wait操作:若该信号量值为0,则将当前任务阻塞在该信号量上,否则将计数值减1。
- post操作:若有任务阻塞在改信号量上,则唤醒其中一个任务,否则计数加一。
实现
信号量就是一个事件控制块加上一个计数值,同时可以设置一个最大值,定义非常简单:
1
2
3
4
5
6
// 信号量的定义
typedef struct _semaphore {
eventCtrlBlock_t event;
uint32_t counter;
uint32_t maxCount;
}sem_t;
初始化操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
void semInit(sem_t* semaphore, uint32_t initCount, uint32_t maxCount) {
eventInit(&semaphore->event, EVENT_TYPE_SEMAPHORE);
semaphore->maxCount = maxCount;
if (maxCount == 0) {
semaphore->counter = initCount;
}else {
semaphore->counter = (maxCount > initCount) ? initCount : maxCount;
}
}
wait
操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
uint32_t semWait(sem_t* semaphore, uint32_t waitTime) {
uint32_t st = enterCritical();
if (semaphore->counter > 0) {
--semaphore->counter;
leaveCritical(st);
return NO_ERROR;
}
eventWait(&semaphore->event, currentTask, NULL, TASK_STATUS_WAIT_SEMAPHORE, waitTime);
leaveCritical(st);
taskSched();
return currentTask->eventWaitResult;
}
post
操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void semPost(sem_t* semaphore) {
uint32_t st = enterCritical();
if (eventGetWaitNum(&semaphore->event) > 0) {
task_t* task = eventWakeUp(&semaphore->event, NULL, NO_ERROR);
if (task->priority < currentTask->priority) {
taskSched();
}
}else {
++semaphore->counter;
if ((semaphore->maxCount != 0) && (semaphore->counter > semaphore->maxCount)) {
semaphore->counter = semaphore->maxCount;
}
}
leaveCritical(st);
}
END
本文由作者按照 CC BY 4.0 进行授权