2023.06.03 - [임베디드 소프트웨어/Zephyr] - [nRF52840 + Zephyr] #11. Inter-task communication A
이전에서 FIFO랑 Queue만 해봤는데
이번에는 Message Queue랑, Mail box를 해볼거야.
그럼 Message Queue부터 시작!
Message Queue의 기본적인 동작은 그냥 Queue와 다를 바 없어.
차이점은 Queue가 포인터만 전달했다면
Message Queue는 고정된 크기의 데이터를 전달한다는 거지.
바로 예제 ㄱㄱ
#include <zephyr/kernel.h>
#define MY_STACK_SIZE 500
#define MY_PRIORITY 5
typedef struct {
uint8_t field1;
uint8_t field2;
}msgq_data_t;
K_MSGQ_DEFINE(my_msgq, sizeof(msgq_data_t), 10, 4);
void my_entry_point(void *, void *, void *){
int ret;
msgq_data_t msgq_data;
for(;;){
k_sleep(K_MSEC(1000));
ret = k_msgq_get(&my_msgq, &msgq_data, K_FOREVER);
printk("data1: %d,data2: %d\n",msgq_data.field1, msgq_data.field2);
}
}
K_THREAD_DEFINE(my_tid, MY_STACK_SIZE,
my_entry_point, NULL, NULL, NULL,
MY_PRIORITY, 0, 0);
void main(void)
{
msgq_data_t msgq_data;
uint8_t data1 = 0,data2= 127;
int ret;
for(;;){
msgq_data.field1 = data1++;
msgq_data.field2 = data2++;
k_sleep(K_MSEC(500));
ret = k_msgq_put(&my_msgq, &msgq_data, K_NO_WAIT);
if(ret){
printk("msgq is full. Purge all messages.\n");
k_msgq_purge(&my_msgq);
} else {
printk("Sucesefully queued: %d,%d\n",msgq_data.field1, msgq_data.field2);
}
}
}
main에서 계속 500ms 단위로 message queue에 넣고
다른 쓰레드에서 1초 마다 읽어봐서 message queue에서 읽어오는 예제야.
읽어오는 속도보다 넣는 속도가 더 빠르니 당연히 queue가 가득차서 못 넣겠지.
그때 purge 시켜버렸어. queue를 다 비우는 거지 ㅎ
다음은 mail box?
mailbox도 기본적으로 Queue!
그런데 ISR(interrupt service routine)에서는 사용할 수 없어.
데이터 크기가 고정일 필요도 없고 타겟 thread를 지정할 수도 있어.
약간 진보된 Queue 느낌이랄까?
바로 예제 고고
#include <zephyr/kernel.h>
#define MY_STACK_SIZE 500
#define MY_PRIORITY 5
K_MBOX_DEFINE(my_mbox);//mail box 선언
void my_entry_point(void *, void *, void *){
int ret;
struct k_mbox_msg rx_msg;//rx_msg
for(;;){
rx_msg.rx_source_thread = K_ANY;//아무한테서나 받는다!
k_mbox_get(&my_mbox, &rx_msg, NULL, K_FOREVER);//메일 올때까지 기다림!
printk("Received message: %d\n", rx_msg.info);
}
}
K_THREAD_DEFINE(my_tid, MY_STACK_SIZE,
my_entry_point, NULL, NULL, NULL,
MY_PRIORITY, 0, 0);
void main(void)
{
int ret;
struct k_mbox_msg tx_msg;
uint8_t info = 0;
for(;;){
tx_msg.info = info++;
tx_msg.size = 0;
tx_msg.tx_data = 0;
tx_msg.tx_block.data = NULL;
tx_msg.tx_target_thread = K_ANY;//아무나 받아라!
k_mbox_put(&my_mbox,&tx_msg, K_FOREVER);//메일 받을때까지 기다림!
k_sleep(K_MSEC(1000));
}
}
첫번째 maibox 예제는 비어있는 메일을 보내는 거야.
그래서 오직 k_mbox_msg 구조체 중에 info값만 의미가 있을거야.
이걸 보니 zephyr에 flag가 없는게 이해가 감. mailbox를 쓰면 됨!
아래는 결과인데 info만 출력하도록 해놨어.
info 말고 긴 데이터도 보내보자구.
#include <zephyr/kernel.h>
#define MY_STACK_SIZE 500
#define MY_PRIORITY 5
K_MBOX_DEFINE(my_mbox);
void my_entry_point(void *, void *, void *){
int ret;
char buffer[100];// 100개 짜리 버퍼~
struct k_mbox_msg rx_msg;
for(;;){
rx_msg.rx_source_thread = K_ANY;//아무한테서나 받아왔!
rx_msg.size=100;
k_mbox_get(&my_mbox, &rx_msg, buffer, K_FOREVER); // 메일 기다렷!
printk("Received message: %s\n", buffer);//출력
}
}
K_THREAD_DEFINE(my_tid, MY_STACK_SIZE,
my_entry_point, NULL, NULL, NULL,
MY_PRIORITY, 0, 0);
void main(void)
{
int ret;
char buffer[100];
int size;
struct k_mbox_msg tx_msg;
uint8_t info = 0;
for(;;){
size = sprintf(buffer, "어머니는 짜장면이 싫다고 하셨어. 탕수육이 좋다고 하셨어~ 이야야~", NULL);
tx_msg.info = info++;
tx_msg.size = size;
tx_msg.tx_data = buffer; //전송할 데이터
tx_msg.tx_block.data = NULL;
tx_msg.tx_target_thread = K_ANY;// 아무한테나 줘버렷!
k_mbox_put(&my_mbox,&tx_msg, K_FOREVER); //받을 때까지 기다렷!
k_sleep(K_MSEC(1000));
}
}
char 100개짜리 버퍼를 만들고 임의의 데이터를 넣고 전송해봤어.
당연한 말이지만 잘 전송되고 잘 받아서 출력해.
👇👇
인코딩 문제인지 vscode 터미널에서는 한글이 조금씩 깨져서
nRF connect 프로그램으로 터미널 실행했음.
마지막으로 아주 큰 block 데이터를 전송하는 기능이 있는데 음...
딱히 두 번째 예제와 다를 바가 없을 듯. 그래서 과감하게 생략!
해보고 싶은 사람들은 아래 링크를 참고하도록!
https://docs.zephyrproject.org/3.1.0/kernel/services/data_passing/mailboxes.html
mailbox는 타겟을 지정할 수 있다는 점에서 실제 프로젝트에서 꽤 유용할 듯 해.
물론 mailbox를 쓸 수 있을 만큼 thread 갯수가 많아야 겠지만 ㅎㅎ
원래는 pipe도 같이 해보려고 했는데;;;
너무 글이 길어져서 pipe는 다음 시간에!! ㅋㅋ
안녕!
👋👋👋
'임베디드 소프트웨어 > Zephyr' 카테고리의 다른 글
[nRF5 + Zephyr] #14. Bluetooth 처음부터 시작하기! (0) | 2023.06.11 |
---|---|
[nRF52840 + Zephyr] #12. Synchronization (0) | 2023.06.03 |
[nRF52840 + Zephyr] #11. Inter-task communication A (0) | 2023.06.03 |
[nRF52840 + Zephyr] #10. Time management (0) | 2023.06.03 |
[nRF52840 + Zephyr] #9. Memory Management (0) | 2023.06.02 |