Skip to content

Commit 34efba2

Browse files
alexpaschoalettocfriedt
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 a FIFO (for normal payloads) and LIFO (for higher priority payloads) schemes. Signed-off-by: Alexander Paschoaletto <[email protected]>
1 parent 1698684 commit 34efba2

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: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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 sample demonstrating the basic usage of Zephyr message queues.
10+
A producer thread sends both normal and urgent messages to be retrieved
11+
by a consumer thread.
12+
13+
Building and Running
14+
********************
15+
16+
This application can be built and executed on QEMU as follows:
17+
18+
.. zephyr-app-commands::
19+
:zephyr-app: samples/kernel/msg_queue
20+
:host-os: unix
21+
:board: qemu_x86
22+
:goals: run
23+
:compact:
24+
25+
To build for another board target, replace "qemu_x86" above with it.
26+
27+
Sample Output
28+
=============
29+
30+
Every normal message is put at the end of the queue, and they are delivered
31+
in FIFO order. Every "urgent" message is put at the beginning of the queue,
32+
and it is delivered first as long as no other "urgent" message comes in after
33+
it.
34+
35+
In this sample, one producer thread sends 1 urgent message for each 2 normal
36+
ones. Note that message C is the first retrieved because it was the last one
37+
sent as "urgent".
38+
39+
.. code-block:: console
40+
41+
[producer] sending: 0
42+
[producer] sending: 1
43+
[producer] sending: A (urgent)
44+
[producer] sending: 2
45+
[producer] sending: 3
46+
[producer] sending: B (urgent)
47+
[producer] sending: 4
48+
[producer] sending: 5
49+
[producer] sending: C (urgent)
50+
[consumer] got sequence: CBA012345
51+
52+
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
sample:
2+
description: Message queue demo sample
3+
name: message queue
4+
common:
5+
tags:
6+
- message_queue
7+
tests:
8+
sample.kernel.msgqueue:
9+
integration_platforms:
10+
- native_sim
11+
harness: console
12+
harness_config:
13+
type: one_line
14+
regex:
15+
- ".*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)