Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

꾸준히

이벤트와 메시징 본문

RTOS

이벤트와 메시징

S210530 2022. 10. 22. 19:17

이벤트

이벤트는 인터럽트와 태스크 간의 연결 매체가 필요할 때 사용한다
RTOS 커널이 태스크를 관리하고 있으므로 좀 더 유연하게 동작하려면 인터럽트 핸들러의 구체적인 기능을 태스크로 옮기는 것이 좋기 때문이다
뿐만 아니라 태스크 간 연결 매체가 필요할 때도 이벤트를 사용한다

이벤트 플래그

이벤트는 개발자가 정한 어떤 값으로 전달된다 개발자가 처리할 수 있는 어떤 형태로든 이벤트를 만들 수 있다
이벤트를 비트맵으로 만들면 각각의 이벤트를 명확하게 구분할 수 있고 이벤트를 구분하는 코드를 간단하게 구현할 수 있다
이벤트를 처리할 수 있는 방법중 하나인 이벤트 플래그란 해당 비트 위치에 깃발을 올렸다 내렸다를 표시하는 것과 같아서 붙여진 이름이다

Code

이벤트 플래그 정의

typedef enum KernelEventFlag_t
{
    KernelEventFlag_UartIn      = 0x00000001,
    KernelEventFlag_CmdIn       = 0x00000002,
    KernelEventFlag_CmdOut      = 0x00000004,
    KernelEventFlag_Unlock      = 0x00000008,
    KernelEventFlag_Reserved04  = 0x00000010,
    KernelEventFlag_Reserved05  = 0x00000020,
    KernelEventFlag_Reserved06  = 0x00000040,
    KernelEventFlag_Reserved07  = 0x00000080,
    KernelEventFlag_Reserved08  = 0x00000100,
    KernelEventFlag_Reserved09  = 0x00000200,
    KernelEventFlag_Reserved10  = 0x00000400,
    KernelEventFlag_Reserved11  = 0x00000800,
    KernelEventFlag_Reserved12  = 0x00001000,
    KernelEventFlag_Reserved13  = 0x00002000,
    KernelEventFlag_Reserved14  = 0x00004000,
    KernelEventFlag_Reserved15  = 0x00008000,
    KernelEventFlag_Reserved16  = 0x00010000,
    KernelEventFlag_Reserved17  = 0x00020000,
    KernelEventFlag_Reserved18  = 0x00040000,
    KernelEventFlag_Reserved19  = 0x00080000,
    KernelEventFlag_Reserved20  = 0x00100000,
    KernelEventFlag_Reserved21  = 0x00200000,
    KernelEventFlag_Reserved22  = 0x00400000,
    KernelEventFlag_Reserved23  = 0x00800000,
    KernelEventFlag_Reserved24  = 0x01000000,
    KernelEventFlag_Reserved25  = 0x02000000,
    KernelEventFlag_Reserved26  = 0x04000000,
    KernelEventFlag_Reserved27  = 0x08000000,
    KernelEventFlag_Reserved28  = 0x10000000,
    KernelEventFlag_Reserved29  = 0x20000000,
    KernelEventFlag_Reserved30  = 0x40000000,
    KernelEventFlag_Reserved31  = 0x80000000,

    KernelEventFlag_Empty       = 0x00000000,
} KernelEventFlag_t;
 


이벤트 플래그 확인

bool Kernel_event_flag_check(KernelEventFlag_t event)
{
    if (sEventFlag & (uint32_t)event)
    {
        Kernel_event_flag_clear(event);
        return true;
    }
    return false;
}

* 발생한 이벤트를 태스크에서 확인하고 이벤트에 맞는 처리를 해준다


메시징

임의의 데이터를 메시지라는 이름으로 전송하는 기능이다
이벤트로는 매우 단편적인 정보만 전달할 수 있지만 메시징은 다량의 데이터를 전달할 수 있다
인터럽트 핸들러에서 이벤트와 메세지를 보내고 태스크에서 이벤트를 처리할 때 이벤트 핸들러에서 메세지를 읽어와서 처리하는 방식으로 사용한다

 

인터럽트와 태스크 메시지 처리 관계

1. uart 입력이 발생하면 인터럽트 핸들러에서 입력받은 문자를 메세지큐에 저장하고 Task0에게 uart 입력을 받았다는 이벤트를 발생시킨다

static void interrupt_handler(void)
{
    uint8_t ch = Hal_uart_get_char();
    Hal_uart_put_char(ch);
    
    Kernel_send_msg(KernelmsgQ_Task0, &ch, 1);
    Kernel_send_events(KernelEventFlag_UartIn);
}


2. Task0의 이벤트 핸들러에서 Task1 메세지 큐에 uart에서 입력받은 문자를 저장하고 Task1에게 이벤트를 발생시킨다

void User_task0(void)
{
    uint32_t local = 0;
    debug_printf("User Task #0 SP=0x%x\n", &local);

    uint8_t  cmdBuf[16];
    uint32_t cmdBufIdx = 0;
    uint8_t  uartch = 0;

    while(true)
    {
        KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_UartIn|KernelEventFlag_CmdOut);
        switch(handle_event)
        {
        case KernelEventFlag_UartIn:
            Kernel_recv_msg(KernelMsgQ_Task0, &uartch, 1);
            if (uartch == '\r')
            {
                cmdBuf[cmdBufIdx] = '\0';

                Kernel_send_msg(KernelMsgQ_Task1, &cmdBufIdx, 1);
                Kernel_send_msg(KernelMsgQ_Task1, cmdBuf, cmdBufIdx);
                Kernel_send_events(KernelEventFlag_CmdIn);

                cmdBufIdx = 0;
            }
            else
            {
                cmdBuf[cmdBufIdx] = uartch;
                cmdBufIdx++;
                cmdBufIdx %= 16;
            }
            break;
        case KernelEventFlag_CmdOut:
            //debug_printf("\nCmdOut Event by Task0\n");
            Test_critical_section(5, 0);
            break;
        }
        Kernel_yield();
    }
}


3. Task1의 이벤트 핸들러에서 메세지 큐에 저장되어 있는 값을 꺼내 출력한다

void User_task1(void)
{
    uint32_t local = 0;

    debug_printf("User Task #1 SP=0x%x\n", &local);

    uint8_t cmdlen = 0;
    uint8_t cmd[16] = {0};

    while(true)
    {
        KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_CmdIn|KernelEventFlag_Unlock);
        switch(handle_event)
        {
        case KernelEventFlag_CmdIn:
            memclr(cmd, 16);
            Kernel_recv_msg(KernelMsgQ_Task1, &cmdlen, 1);
            Kernel_recv_msg(KernelMsgQ_Task1, cmd, cmdlen);
            debug_printf("\nRecv Cmd: %s\n", cmd);
            break;
        case KernelEventFlag_Unlock:

            break;
        }
        Kernel_yield();
    }
}

 

'RTOS' 카테고리의 다른 글

Context Switching  (0) 2023.05.29
동기화  (0) 2022.10.22
Task  (0) 2022.10.22
인터럽트  (0) 2022.10.22
HAL  (0) 2022.10.22