Skip to content

Commit 7944b64

Browse files
alexpaschoalettoAlexander pinheiro paschoaletto
authored andcommitted
sample: msgq: adding a sample code for message queue base usage
this commit adds a sample code to illustrate the base usage of message queues. a producer and a consumer thread work together, exchanging messages in the normal (FIFO) and urgent (LIFO) ways. Signed-off-by: Alexander Paschoaletto <axelpinheiro@gmail.com>
1 parent aa19327 commit 7944b64

File tree

5 files changed

+144
-0
lines changed

5 files changed

+144
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(msg_queue)
7+
8+
target_sources(app PRIVATE src/main.c)

samples/kernel/msg_queue/README.rst

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
.. zephyr:code-sample:: msg_queue
2+
:name: Message Queue
3+
4+
Implements a basic message queue producer/consumer thread pair.
5+
6+
Overview
7+
********
8+
9+
A simple sample to demonstrate the basic usage of Zephyr message queues.
10+
a producer thread sends both normal and urgent messages.
11+
12+
Building and Running
13+
********************
14+
15+
This application can be built and executed on QEMU as follows:
16+
17+
.. zephyr-app-commands::
18+
:zephyr-app: samples/kernel/msg_queue
19+
:host-os: unix
20+
:board: qemu_x86
21+
:goals: run
22+
:compact:
23+
24+
To build for another board, change "qemu_x86" above to that board's name.
25+
26+
Sample Output
27+
=============
28+
29+
Every normal message sending implies sending the message to the end of the
30+
queue, and the first message to go is the first to be delivered. Every "urgent"
31+
message, at its turn, implies sending the message to the beginning of the queue.
32+
33+
In this sample, one producer thread sends 1 urgent message for each 2 regular
34+
ones. Note that message C is the first retrieved because it was the last one
35+
sent as "urgent".
36+
37+
.. code-block:: console
38+
39+
[producer] sending: 0
40+
[producer] sending: 1
41+
[producer] sending: A (urgent)
42+
[producer] sending: 2
43+
[producer] sending: 3
44+
[producer] sending: B (urgent)
45+
[producer] sending: 4
46+
[producer] sending: 5
47+
[producer] sending: C (urgent)
48+
[consumer] got sequence: CBA012345
49+
50+
Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.

samples/kernel/msg_queue/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# nothing here

samples/kernel/msg_queue/sample.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sample:
2+
description: A message queue usage sample
3+
name: message queue sample
4+
common:
5+
tags:
6+
- message_queue
7+
tests:
8+
sample.kernel.msgqueue:
9+
integration_platforms:
10+
- native_sim
11+
tags:
12+
- message_queue
13+
harness: console
14+
harness_config:
15+
type: one_line
16+
regex:
17+
- ".*CBA012345"

samples/kernel/msg_queue/src/main.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2025 Instituto Superior de Engenharia do Porto (ISEP).
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
9+
#define BUF_SIZE 10
10+
#define INACTIVE -1
11+
#define PRIORITY 5
12+
13+
K_MSGQ_DEFINE(my_msgq, sizeof(char), BUF_SIZE, 1);
14+
15+
void producer_function(void *rec, void *p2, void *p3)
16+
{
17+
k_tid_t receiving_thread = (k_tid_t) rec;
18+
19+
char normal_data = '0';
20+
char urgent_data = 'A';
21+
int total_sent = 0;
22+
23+
/*
24+
* sends messages every 100 msec, in repeating
25+
* sequence normal, normal, urgent, ...
26+
*/
27+
while (total_sent < (BUF_SIZE - 1)) {
28+
for (int i = 0; i < 2; i++) {
29+
printk("[producer] sending: %c\n", normal_data);
30+
k_msgq_put(&my_msgq, &normal_data, K_NO_WAIT);
31+
k_sleep(K_MSEC(100));
32+
normal_data++;
33+
}
34+
printk("[producer] sending: %c (urgent)\n", urgent_data);
35+
k_msgq_put_front(&my_msgq, &urgent_data, K_NO_WAIT);
36+
k_sleep(K_MSEC(100));
37+
urgent_data++;
38+
39+
total_sent += 3;
40+
}
41+
42+
/*
43+
* finished sending messages, now start the receiving thread.
44+
* keep in mind both threads can be running at the same time,
45+
* but in this example we wish to see the queue accumulate some
46+
* messages before the receiver thread starts reading them out.
47+
*/
48+
k_thread_start(receiving_thread);
49+
}
50+
51+
void consumer_function(void *p1, void *p2, void *p3)
52+
{
53+
char received[BUF_SIZE];
54+
55+
for (int i = 0; i < (BUF_SIZE - 1); i++) {
56+
k_msgq_get(&my_msgq, &received[i], K_NO_WAIT);
57+
}
58+
59+
received[BUF_SIZE - 1] = '\0';
60+
/* we expect to see CBA012345... */
61+
printk("[consumer] got sequence: %s\n", received);
62+
}
63+
64+
K_THREAD_DEFINE(consumer_thread, 2048, consumer_function,
65+
NULL, NULL, NULL, PRIORITY, 0, INACTIVE);
66+
67+
K_THREAD_DEFINE(producer_thread, 2048, producer_function,
68+
((void *) consumer_thread), NULL, NULL, PRIORITY, 0, 0);

0 commit comments

Comments
 (0)