1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/kernel.h>
9 #include <cmsis_os2.h>
10 
11 struct sample_data {
12 	int data1;
13 	unsigned char data2;
14 	unsigned int data3;
15 };
16 
17 #define MESSAGE1        512
18 #define MESSAGE2        123456
19 #define TIMEOUT_TICKS   50
20 #define Q_LEN           5
21 #define STACKSZ         CONFIG_CMSIS_V2_THREAD_MAX_STACK_SIZE
22 
23 osMessageQueueId_t message_id;
24 
send_msg_thread(void * argument)25 void send_msg_thread(void *argument)
26 {
27 	int i;
28 	osStatus_t status;
29 	struct sample_data sample;
30 	struct sample_data data[Q_LEN] = { { 0 } };
31 
32 	/* Wait for message_recv to complete initial checks */
33 	osDelay(TIMEOUT_TICKS);
34 
35 	/* Prepare and send the 1st message (a simple integer data) */
36 	sample.data1 = MESSAGE1;
37 	status = osMessageQueuePut(message_id, &sample, 0, osWaitForever);
38 	zassert_true(status == osOK, "osMessageQueuePut failure for Message1");
39 
40 	/* The Queue should be empty at this point */
41 	zassert_equal(osMessageQueueGetCount(message_id), 0,
42 		      "Something's wrong with osMessageQueueGetCount!");
43 	zassert_equal(osMessageQueueGetSpace(message_id), Q_LEN,
44 		      "Something's wrong with osMessageQueueGetSpace!");
45 
46 	/* Fill the queue with blocks of messages */
47 	for (i = 0; i < Q_LEN; i++) {
48 		data[i].data1 = i * 3;
49 		data[i].data2 = i * 3 + 1;
50 		data[i].data3 = i * 3 + 2;
51 		status = osMessageQueuePut(message_id, data + i,
52 					   0, osWaitForever);
53 		zassert_true(status == osOK,
54 			     "osMessageQueuePut failure for message!");
55 	}
56 
57 	/* The Queue should be full at this point */
58 	zassert_equal(osMessageQueueGetCount(message_id), Q_LEN,
59 		      "Something's wrong with osMessageQueueGetCount!");
60 	zassert_equal(osMessageQueueGetSpace(message_id), 0,
61 		      "Something's wrong with osMessageQueueGetSpace!");
62 
63 	/* Try putting message to a full queue immediately
64 	 * before it is emptied out and assert failure
65 	 */
66 	sample.data1 = MESSAGE2;
67 	status = osMessageQueuePut(message_id, &sample, 0, 0);
68 	zassert_true(status == osErrorResource,
69 		     "Something's wrong with osMessageQueuePut!");
70 
71 	/* Try putting message to a full queue within a duration
72 	 * less than TIMEOUT_TICKS, before the queue is emptied out
73 	 */
74 	sample.data1 = MESSAGE2;
75 	status = osMessageQueuePut(message_id, &sample, 0, TIMEOUT_TICKS / 2);
76 	zassert_true(status == osErrorTimeout,
77 		     "Something's wrong with osMessageQueuePut!");
78 
79 	/* Send another message after the queue is emptied */
80 	sample.data1 = MESSAGE2;
81 	status = osMessageQueuePut(message_id, &sample, 0, TIMEOUT_TICKS * 2);
82 	zassert_true(status == osOK,
83 		     "osMessageQueuePut failure for message!");
84 }
85 
message_recv(void)86 void message_recv(void)
87 {
88 	int i;
89 	osStatus_t status;
90 	struct sample_data recv_data;
91 
92 	/* Try getting message immediately before the queue is populated */
93 	status = osMessageQueueGet(message_id, (void *)&recv_data, NULL, 0);
94 	zassert_true(status == osErrorResource,
95 		     "Something's wrong with osMessageQueueGet!");
96 
97 	/* Try receiving message within a duration of TIMEOUT */
98 	status = osMessageQueueGet(message_id, (void *)&recv_data,
99 				   NULL, TIMEOUT_TICKS);
100 	zassert_true(status == osErrorTimeout,
101 		     "Something's wrong with osMessageQueueGet!");
102 
103 	zassert_equal(osMessageQueueGetCapacity(message_id), Q_LEN,
104 		      "Something's wrong with osMessageQueueGetCapacity!");
105 
106 	zassert_equal(osMessageQueueGetMsgSize(message_id),
107 		      sizeof(struct sample_data),
108 		      "Something's wrong with osMessageQueueGetMsgSize!");
109 
110 	/* Receive 1st message */
111 	status = osMessageQueueGet(message_id, (void *)&recv_data,
112 				   NULL, osWaitForever);
113 	zassert_true(status == osOK, "osMessageQueueGet failure");
114 	zassert_equal(recv_data.data1, MESSAGE1);
115 
116 	/* Wait for queue to get filled */
117 	osDelay(TIMEOUT_TICKS);
118 
119 	/* Empty the queue */
120 	for (i = 0; i < Q_LEN; i++) {
121 		status = osMessageQueueGet(message_id, (void *)&recv_data, NULL,
122 					   osWaitForever);
123 		zassert_true(status == osOK, "osMessageQueueGet failure");
124 
125 		zassert_equal(recv_data.data1, i * 3);
126 		zassert_equal(recv_data.data2, i * 3 + 1);
127 		zassert_equal(recv_data.data3, i * 3 + 2);
128 	}
129 
130 	/* Receive the next message */
131 	status = osMessageQueueGet(message_id, (void *)&recv_data,
132 				   NULL, osWaitForever);
133 	zassert_true(status == osOK, "osMessageQueueGet failure");
134 	zassert_equal(recv_data.data1, MESSAGE2);
135 }
136 
137 static K_THREAD_STACK_DEFINE(test_stack, STACKSZ);
138 osThreadAttr_t thread_attr = {
139 	.name = "send_thread",
140 	.stack_mem = &test_stack,
141 	.stack_size = STACKSZ,
142 	.priority = osPriorityNormal,
143 };
144 
145 static char __aligned(4) sample_mem[sizeof(struct sample_data) * Q_LEN];
146 static const osMessageQueueAttr_t init_mem_attrs = {
147 	.name = "TestMsgQ",
148 	.attr_bits = 0,
149 	.cb_mem = NULL,
150 	.cb_size = 0,
151 	.mq_mem = sample_mem,
152 	.mq_size = sizeof(struct sample_data) * Q_LEN,
153 };
154 
ZTEST(cmsis_msgq,test_messageq)155 ZTEST(cmsis_msgq, test_messageq)
156 {
157 	osStatus_t status;
158 	struct sample_data sample;
159 	osThreadId_t tid;
160 
161 	message_id = osMessageQueueNew(Q_LEN, sizeof(struct sample_data),
162 				       &init_mem_attrs);
163 	zassert_true(message_id != NULL, "Message creation failed");
164 
165 	tid = osThreadNew(send_msg_thread, NULL, &thread_attr);
166 	zassert_true(tid != NULL, "Thread creation failed");
167 
168 	message_recv();
169 
170 	/* Wait for the send_msg_thread to terminate before this thread
171 	 * terminates.
172 	 */
173 	osDelay(TIMEOUT_TICKS / 10);
174 
175 	/* Make sure msgq is empty */
176 	zassert_equal(osMessageQueueGetCount(message_id), 0,
177 		      "Something's wrong with osMessageQueueGetCount!");
178 
179 	sample.data1 = MESSAGE1;
180 	status = osMessageQueuePut(message_id, &sample, 0, osWaitForever);
181 	zassert_true(status == osOK, "osMessageQueuePut failure for Message1");
182 
183 	zassert_equal(osMessageQueueGetCount(message_id), 1,
184 		      "Something's wrong with osMessageQueueGetCount!");
185 
186 	status = osMessageQueueReset(message_id);
187 	zassert_true(status == osOK, "osMessageQueueReset failure");
188 
189 	/* After reset msgq must be empty */
190 	zassert_equal(osMessageQueueGetCount(message_id), 0,
191 		      "Something's wrong with osMessageQueueGetCount!");
192 
193 	status = osMessageQueueDelete(message_id);
194 	zassert_true(status == osOK, "osMessageQueueDelete failure");
195 }
196 ZTEST_SUITE(cmsis_msgq, NULL, NULL, NULL, NULL, NULL);
197