1 /*
2  * Copyright (c) 2017 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_os.h>
10 
11 struct sample_data {
12 	int		data1;
13 	unsigned char	data2;
14 	unsigned int	data3;
15 };
16 
17 #define MAIL1_DATA1	75663
18 #define MAIL1_DATA2	156
19 #define MAIL1_DATA3	1000001
20 
21 #define MAIL2_DATA1	93567
22 #define MAIL2_DATA2	255
23 #define MAIL2_DATA3	1234567
24 
25 #define TIMEOUT		500
26 #define Q_LEN		5
27 
28 osMailQDef(mail, Q_LEN, struct sample_data);
29 osMailQId  mail_id;
30 
send_thread(void const * argument)31 void send_thread(void const *argument)
32 {
33 	int i;
34 	struct sample_data *tx_ptr;
35 	struct sample_data zeroblock;
36 	osStatus status;
37 
38 	/* This is used for comparison later in the function */
39 	memset(&zeroblock, 0, sizeof(struct sample_data));
40 
41 	status = osMailPut(mail_id, NULL);
42 	zassert_true(status == osErrorValue,
43 	 "Something's wrong with osMailPut. It is passing for NULL mail!");
44 
45 	/* Wait for mail_recv to complete initial checks */
46 	osDelay(TIMEOUT);
47 
48 	/* Prepare and send 1st mail */
49 	tx_ptr = osMailAlloc(mail_id, osWaitForever);
50 	zassert_true(tx_ptr != NULL, "Mail1 alloc failed");
51 	tx_ptr->data1 = MAIL1_DATA1;
52 	tx_ptr->data2 = MAIL1_DATA2;
53 	tx_ptr->data3 = MAIL1_DATA3;
54 	status = osMailPut(mail_id, tx_ptr);
55 	zassert_true(status == osOK, "osMailPut failure for mail1");
56 
57 	/* Fill the queue with blocks of mails */
58 	for (i = 0; i < Q_LEN; i++) {
59 
60 		/* Alternately use osMailAlloc and osMailCAlloc to ensure
61 		 * both the APIs are tested.
62 		 */
63 		if (i & 1) {
64 			tx_ptr = osMailCAlloc(mail_id, osWaitForever);
65 		} else {
66 			tx_ptr = osMailAlloc(mail_id, osWaitForever);
67 		}
68 		zassert_true(tx_ptr != NULL, "Mail alloc failed");
69 
70 		tx_ptr->data1 = i;
71 		tx_ptr->data2 = i+1;
72 		tx_ptr->data3 = i+2;
73 
74 		status = osMailPut(mail_id, tx_ptr);
75 		zassert_true(status == osOK,
76 				"osMailPut failure for mail!");
77 	}
78 
79 	/* Try allocating mail to a full queue immediately
80 	 * before it is emptied out and assert failure
81 	 */
82 	tx_ptr = osMailAlloc(mail_id, 0);
83 	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
84 	tx_ptr = osMailCAlloc(mail_id, 0);
85 	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");
86 
87 	/* Try allocating mail to a full queue within a duration
88 	 * less than TIMEOUT, before the queue is emptied out
89 	 */
90 	tx_ptr = osMailAlloc(mail_id, TIMEOUT/3);
91 	zassert_true(tx_ptr == NULL, "MailAlloc passed. Something's wrong");
92 	tx_ptr = osMailCAlloc(mail_id, TIMEOUT/3);
93 	zassert_true(tx_ptr == NULL, "MailCAlloc passed. Something's wrong");
94 
95 	/* Send another mail after the queue is emptied */
96 	tx_ptr = osMailCAlloc(mail_id, TIMEOUT*2);
97 	zassert_true(tx_ptr != NULL, "Mail alloc failed");
98 	zassert_equal(memcmp(tx_ptr, &zeroblock, sizeof(struct sample_data)), 0,
99 		"osMailCAlloc returned memory not initialized to 0");
100 
101 	tx_ptr->data1 = MAIL2_DATA1;
102 	tx_ptr->data2 = MAIL2_DATA2;
103 	tx_ptr->data3 = MAIL2_DATA3;
104 	status = osMailPut(mail_id, tx_ptr);
105 	zassert_true(status == osOK, "osMailPut failure for mail");
106 }
107 
mail_recv(void)108 void mail_recv(void)
109 {
110 	int i;
111 	struct sample_data  *rx_ptr;
112 	osEvent  evt;
113 	osStatus status;
114 
115 	/* Try getting mail immediately before the queue is populated */
116 	evt = osMailGet(mail_id, 0);
117 	zassert_true(evt.status == osOK,
118 			"Something's wrong with osMailGet!");
119 
120 	/* Try receiving mail within a duration of TIMEOUT */
121 	evt = osMailGet(mail_id, TIMEOUT);
122 	zassert_true(evt.status == osEventTimeout,
123 		"Something's wrong with osMailGet!");
124 
125 	/* Receive 1st mail */
126 	evt = osMailGet(mail_id, osWaitForever);
127 	zassert_true(evt.status == osEventMail, "osMailGet failure");
128 
129 	rx_ptr = evt.value.p;
130 	zassert_equal(rx_ptr->data1, MAIL1_DATA1);
131 	zassert_equal(rx_ptr->data2, MAIL1_DATA2);
132 	zassert_equal(rx_ptr->data3, MAIL1_DATA3);
133 
134 	status = osMailFree(mail_id, rx_ptr);
135 	zassert_true(status == osOK, "osMailFree failure");
136 
137 	/* Wait for queue to get filled */
138 	osDelay(TIMEOUT);
139 
140 	/* Empty the queue */
141 	for (i = 0; i < Q_LEN; i++) {
142 		evt = osMailGet(mail_id, osWaitForever);
143 		zassert_true(evt.status == osEventMail, "osMailGet failure");
144 
145 		rx_ptr = evt.value.p;
146 		zassert_equal(rx_ptr->data1, i);
147 		zassert_equal(rx_ptr->data2, i + 1);
148 		zassert_equal(rx_ptr->data3, i + 2);
149 
150 		status = osMailFree(mail_id, rx_ptr);
151 		zassert_true(status == osOK, "osMailFree failure");
152 	}
153 
154 	/* Receive the next mail */
155 	evt = osMailGet(mail_id, osWaitForever);
156 	zassert_true(evt.status == osEventMail, "osMailGet failure");
157 
158 	rx_ptr = evt.value.p;
159 	zassert_equal(rx_ptr->data1, MAIL2_DATA1);
160 	zassert_equal(rx_ptr->data2, MAIL2_DATA2);
161 	zassert_equal(rx_ptr->data3, MAIL2_DATA3);
162 
163 	status = osMailFree(mail_id, rx_ptr);
164 	zassert_true(status == osOK, "osMailFree failure");
165 }
166 
167 osThreadDef(send_thread, osPriorityNormal, 1, 0);
168 
ZTEST(cmsis_mailq,test_mailq)169 ZTEST(cmsis_mailq, test_mailq)
170 {
171 	osThreadId tid;
172 
173 	mail_id = osMailCreate(osMailQ(mail), NULL);
174 	zassert_true(mail_id != NULL, "Mail creation failed");
175 
176 	tid = osThreadCreate(osThread(send_thread), NULL);
177 	zassert_true(tid != NULL, "Thread creation failed");
178 
179 	mail_recv();
180 }
181 ZTEST_SUITE(cmsis_mailq, NULL, NULL, NULL, NULL, NULL);
182