LCD 화면에 task1와 task2가 동시에 출력하려면
shared data problem으로 인하여
글씨가 깨진다
이는 두 task가
LCD API를 호출할 때마다 systick interrupt에 의해
선점되기 때문이다
그래서 shared data에 접근할 때
1) interrupt를 껐다가 켜줘야 한다.
//Disable/Enable interrupt in FreeRTOS
taskENTER_CRITICAL(); // disable
taskEXIT_CRITICAL(); // enable
// Handling Shared Data Problem in FreeRTOS
void Task1( void *pvParameters )
{
int i=0;
char buffer[64];
while (1)
{
sprintf(buffer,"Task1: %3d", i++);
taskENTER_CRITICAL();
Graphics_drawString(&g_sContext,
(int8_t *)buffer,
AUTO_STRING_LENGTH,
12,
24,
OPAQUE_TEXT);
taskEXIT_CRITICAL();
if (i==100) i=1;
}
}
void Task2( void *pvParameters )
{
int i=0;
char buffer[64];
while (1)
{
sprintf(buffer,"Task2: %3d", i++);
taskENTER_CRITICAL();
Graphics_drawString(&g_sContext,
(int8_t *)buffer,
AUTO_STRING_LENGTH,
12,
32,
OPAQUE_TEXT);
taskEXIT_CRITICAL();
if (i==100) i=1;
}
}
아니면 2) synchronization primitives를 사용한다
Synchronization Primitives in FreeRTOS
<queue: FIFO>
항목을 full queue로 보내는 과정은
queue가 꽉 찼거나 시간 초과가 만료되기 전까지 blocked됨
empty queue에서 가져오려고 하면
queue가 비어있지 않을 때까지, 또는 시간초과가 만료될 때까지 blocked 됨
Binary Semaphore
이는 길이가 1인 큐와 비슷함
(하나에 full, 이 반대는 empty)
- task는 semaphore에서 제공될 때까지 blocked state로 대기
- ISR이 발생하면 이러한 방식으로 blocked를 해제한 뒤 semaphore 제공
- task는 semaphore를 가져와서 지연처리를 수행
- xSemaphoreTake() : semaphore가 낮아질 때까지 semaphore 대기. (즉, task가 blocked 상태로 쭉). 낮아지지 않는다면 진행하여 sempahore를 내림
- xSemaphoreGive() : semaphore 올리기
#include <semphr.h>
SemaphoreHandle_t xSemaphoreCreateBinary( void );
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait );
BaseType_t xSemaphoreGive( SemaphoreHandle_t xSemaphore);
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
- xTicksToWait
- 0: semaphore를 이용할 수 없다면 즉시 반환
- portMAX_DELAY 는 timeout 없이, 계속 task가 대기하도록 하게 함
문제점
만약 ISR에서 보류 중인 (pending) task가 blocked 되면 어떻게 해야하나?
- ISR의 응답시간이 지연됨
그래서 이 방식은 Real-time(실시간) system에 적합하지 않음
심지어 시스템이 halting state(정지 상태)에 있게 될 수도 있음
그래서 blocking operation은 ISR에서 허용되지 않음
Task Signaling
semaphore로 event 발생 여부를 알리는 flag로 사용해보자
그 이벤트가 다른 task일 수도 ISR일 수도
실습
위의 그림에서 task 간 상황에 대해서 해보자
Task 1
- Poll S1 button
- button을 땠을 때 task2에게 signal 보내기
Task 2
- signal 기다리기
- signal 받으면 Red LED on/off
Bilateral Rendezvous
이것만 보고 button에 대해서만 semaphore signalling을 하면 작동이 안 됨
led on/off에 대해서도 signalling이 필요
Bilateral Rendezvous란
두 task가 2개의 semaphore를 사용하여 그들의 활동을 synchronize 하는 것
(이 방법은 task와 ISR 간에서는 불가능. 왜냐면 ISR은 blocked되어 버려서. 그럼 안 되는데)
/* global variables */
Graphics_Context g_sContext;
SemaphoreHandle_t s1but_sem; // 추가
SemaphoreHandle_t leddone_sem; // 추가 (led done)
...
void main(void)
{
...
s1but_sem=xSemaphoreCreateBinary(); // 추가
leddone_sem=xSemaphoreCreateBinary(); // 추가
...
}
void Task1( void *pvParameters )
{
int s1but_bs=BS_INIT;
while (1) {
if (S1BUT) { // button down
s1but_bs=BS_DOWN;
} else { // button up
if (s1but_bs==BS_DOWN) {
xSemaphoreGive(s1but_sem); // 수정 - Task2의 xSemaphoreTake()로 signal 전송
xSemaphoreTake(leddone_sem, portMAX_DELAY); // 추가 - Task2의 xSemaphoreGive()에게 signal 받음
}
s1but_bs=BS_UP;
}
}
}
void Task2( void *pvParameters )
{
while (1)
{
xSemaphoreTake(s1but_sem, portMAX_DELAY); // 수정
P1->OUT^=BIT0;
xSemaphoreGive(leddone_sem); // 추가
}
}
Mutual Exclusion Semaphore
task와 ISR은 변수처럼 공동 resource를 공유할 수 있다
- 둘 이상의 task 또는 ISR이 동시에 shared resource를 사용하려고 할 때, 일치하지 않는 잘못된 결과가 발생할 수 있음
- shared resource에 접근하는 코드의 critical section이 resource에 대한 독점적(exclusive) 접근권한을 갖는지 확인하자
- semaphore로 상호 배제(mutual exclusion)을 보장
- FreeRTOS는 mutual exclusion을 위한 mutex semaphore를 제공함
#include <semphr.h>
SemaphoreHandle_t xSemaphoreCreateMutex( void );
SemaphoreHandle_t mtx;
int main(void) {
...
mtx = xSemaphoreCreateMutex(); // mutex semaphore 생성 함수
...
vTaskStartScheduler();
...
}
void vTaskA(void *pv) {
while(1) {
xSemaphoreTake(mtx, portMAX_DELAY);
// The critical section begins
...
// The critical section ends
xSemaphoreGive(mtx);
}
}
void vTaskB(void *pv) {
while(1) {
xSemaphoreTake(mtx, portMAX_DELAY);
// The critical section begins
...
// The critical section ends
xSemaphoreGive(mtx);
}
}
/* Driver configuration */
#include <ti/devices/msp432p4xx/inc/msp.h>
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/drivers/Board.h>
#include <ti/grlib/grlib.h>
#include "LcdDriver/Crystalfontz128x128_ST7735.h"
#include "LcdDriver/msp432p4111_classic.h"
/* RTOS header files */
#include <FreeRTOS.h>
#include <task.h>
#include <semphr.h>
/* function prototypes */
void Task1( void *pvParameters );
void Task2( void *pvParameters );
/* global variables */
Graphics_Context g_sContext;
SemaphoreHandle_t mtx;
void main(void)
{
...
xTaskCreate( Task1, /* The function that implements the task. */
"Task 1", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE,/* The size of the stack to allocate to the task. */
( void * ) 0, /* The parameter passed to the task - just to check the functionality. */
5, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( Task2, /* The function that implements the task. */
"Task 2", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE,/* The size of the stack to allocate to the task. */
( void * ) 0, /* The parameter passed to the task - just to check the functionality. */
5, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
mtx = xSemaphoreCreateMutex();
/* Start the tasks and timer running. */
vTaskStartScheduler();
while (1)
{
}
}
void Task1( void *pvParameters )
{
int i=0;
char buffer[64];
while (1)
{
sprintf(buffer,"Task1: %3d", i++);
xSemaphoreTake(mtx, portMAX_DELAY);
Graphics_drawString(&g_sContext,
(int8_t *)buffer,
AUTO_STRING_LENGTH,
12,
24,
OPAQUE_TEXT);
xSemaphoreGive(mtx);
if (i==100) i=1;
}
}
void Task2( void *pvParameters )
{
int i=0;
char buffer[64];
while (1)
{
sprintf(buffer,"Task2: %3d",i++);
xSemaphoreTake(mtx, portMAX_DELAY);
Graphics_drawString(&g_sContext,
(int8_t *)buffer,
AUTO_STRING_LENGTH,
12,
32,
OPAQUE_TEXT);
xSemaphoreGive(mtx);
if (i==100) i=1;
}
}
'CS > Embedded System' 카테고리의 다른 글
FreeRTOS - Task Management (0) | 2021.12.08 |
---|---|
Real-Time Operating Systems - Semaphore (0) | 2021.12.07 |
Programming Devices - LCD, S1&S2 btn, Joystick (0) | 2021.12.07 |
[실습] Interrupt & SysTick timer (0) | 2021.12.07 |
SW Architecture - RR, Interupt, func-queue scheduling, RTOS (0) | 2021.12.07 |