티스토리 뷰

심화

megaOS - 13. Mailbox

Just4Fun 2016. 11. 13. 12:57

이번 글에서는 mailbox에 대해서 설명하도록 하겠다.  앞의 글에서 설명한 semaphore나 flag는 이벤트가 발생했다는 것만을 알려주는것이었다면, mailbox는 어떤 이벤트가 발생했는지 그 내용을 전달해주는 기능을 제공한다.

자세한 내용은 소스를 구현해 나가면서 설명하도록 하겠다.


역시 mailbox를 구현하기 위하여 os.h에 mailbox를 위한 구조체를 선언하여야 한다.

위의 구조체에서 item이라는 항목이 이벤트의 내용을 저장하기 위한 포인터 배열이다.

size는 mailbox가 몇개의 이벤트를 저장할 수 있는지 그 크기를 기록해 두기 위하여 사용된다.

base는 이벤트 정보가 저장되어 있는 item의 위치를 알려주기 위하여 사용된다.

count는 처리되지 않은 이벤트가 몇개나 쌓여 있는지 알려주기 위하여 사용된다.

get_list는 이벤트를 처리하기 원하는 타스크를 링크 시키기 위하여 사용되고,

put_list는 어떤 타스크가 이벤트를 알려주기 위하여 mailbox_put()을 불렀는데, mailbox가 full 상태여서 더이상 put이 불가능할 때 mailbox에 여유가 생길때까지 기다리기 위해서 사용되는 list이다.


mailbox를 생성시키는 함수는 os_mbox_create()이다.

maibox 구조체를 하나 생성한 후 초기화를 시키고, 10번줄에서처럼 이벤트 정보를 저장하기 위한 포인터 배열을 생성한다.


wakeup_waiter()는 put_list나 get_list에 연결되어 있는 타스크를 깨우는 시점에 사용된다.


mailbox이벤트를 기다리기 위해서 os_mbox_get()을 사용한다.

9~22는 mailbox에 발생한 이벤트가 없는 상황일 때 이벤트를 기다리기 위한 절차를 수행하는 코드이다.

이벤트가 발생하거나, timeout에 의하여 sleep에 있던 타스크가 깨어나면 24번 줄부터 프로그램을 이어나간다.

혹시 timeout을 설정하기 위하여 tick의 값이 0이 아니면 사용했던 timer를 clear 해준다.

Timeout이 발생되기 전에 mailbox에 이벤트가 들어오면 27~37번 줄이 수행된다.

36번 줄은 혹시 이벤트를 전달하려 했지만 빈 mailbox가 없어서 put_list에서 대기중인 타스크가 있다면, 이제 maibox에 여유가 생겼으므로 타스크를 깨워서 mailbox에 이벤트 정보를 전달할 수 있도록 해준다.


발생한 이벤트가 있는지 확인해서 있으면 처리하고, 발생된 이벤트가 없으면 그냥 다른 일을 수행하고 싶을때가 있다.  이때 사용하는 함수가 os_mbox_tryget()이다.  


이벤트가 발생하여서 이 정보를 전달하기 위하여 os_mbox_put()을 사용한다.

8~21까지는 mailbox에 이벤트를 전달할 공간이 없을때, 공간이 생길때까지 sleep상태로 들어가기 위한 코드이다.

mailbox에 공간이 있거나, timeout이 발생하여 sleep에서 깨어나게 되면 23번 줄부터 프로그램을 이어나가게 된다.

26~35까지는 전달하고 싶은 이벤트를 mailbox에 기록한 다음, 이 이벤트를 기다리는 타스크가 있을경우 그 타스크를 깨워서 이벤트를 처리할 수 있도록 하는 코드이다.


os_mbox_put()과 달리 굳이 sleep상태로까지 들어갈 필요가 없을 경우에는 os_mbox_tryput()을 사용하면 된다.


이제, 위에서 구현한 mailbox를 이용하여 실제로 어떻게 동작되는지 확인하기 위한 코드를 만들어 보도록 하겠다.

UART를 통해서 데이터가 수신되면 uart_data[] 배열에 순차적으로 기록한다.

링버퍼로 동작시키기 위하여 header_index, tail_index를 사용한다.


33~34에서처럼 8개의 이벤트를 저장할 수 있는 uart_mbox를 생성하고, 링버퍼 동작을 위하여 header_index, tail_index를 초기화 한다.


uart_isr에서는 UART RX인터럽트가 발생하면, 수신한 데이터를 uart_data[]에 차례로 저장한다.

uart_dsr에서는 처리되지 않은 UART 데이터가 들어있는 주소를 uart_mbox mailbox를 통해서 알려준다.  UART 데이터를 직접 전달하는 것이 아니라, 그 데이터가 저장되어 있는 위치를 알려주는 것임을 유의하여야 한다.


38번줄에 있는 코드는 UART 데이터 수신 이벤트가 발생하여 인터럽트 루틴에서 데이터가 있는 위치를 알려주고, uart_task가 그 위치를 읽어 그 안에서 데이터를 추출해내는 코드이다.


위의 코드를 입력하여 프로젝트를 빌드한 후 실제 보드에서 어떻게 동작되는 확인해 본다.


키보드로 입력한 글자들이 제대로 처리되었음을 확인할 수 있다.


위의 예에서는 단순히 하나의 글자를 전달하기 위하여 mailbox를 사용하였지만, mailbox는 포인터를 전달해 주는 기능을 하므로 얼마든지 다양한 정보를 타스크간에 혹은 인터럽트에서 타스크로 전달할 수 있다.


결론은 단순히 이벤트가 발생했다는것만을 알려주기 위해서는 semaphore를 사용하고,

이벤트를 좀더 세분화 할 필요가 있을때는 flag를 사용하면 된다.

마지막으로 타스크간에 정보를 교환하기 위해서는 mailbox를 사용하면 된다.


이로써 megaOS의 주요 기능과 이벤트 처리를 위한 세가지 synchronization 기능을 모두 설명하였다.

실제로는 이보다 많은 다양한 기능이 필요할 수가 있겠지만 AVR에서는 이정도의 기능만으로도 대부분의 동작을 수행할 수 있을것이다.



megaOS.zip


심화 과정 목차

'심화' 카테고리의 다른 글

User Interface - UART 문자열 입력  (0) 2017.06.29
User Interface - UART 특수키 처리  (0) 2017.06.24
megaOS - 12. Flag  (0) 2016.11.08
megaOS - 11. Semaphore  (0) 2016.11.07
megaOS - 10. System Timer  (0) 2016.10.31
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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
글 보관함