1 /*
2  * Copyright (c) 2024, Texas Instruments Incorporated
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/kernel_structs.h>
9 #include <assert.h>
10 #include <zephyr/sys/__assert.h>
11 
12 #include <inc/hw_types.h>
13 #include <inc/hw_ints.h>
14 
15 #include <driverlib/interrupt.h>
16 
17 #include <kernel/zephyr/dpl/dpl.h>
18 #include <ti/drivers/dpl/MessageQueueP.h>
19 #include <ti/drivers/dpl/ClockP.h>
20 #include <ti/drivers/dpl/HwiP.h>
21 
22 #ifdef CONFIG_DYNAMIC_DPL_OBJECTS
23 /* We can't easily dynamically allocate kernel objects */
24 #define DPL_MAX_MSGQS 4
25 K_MEM_SLAB_DEFINE(msgq_slab, sizeof(struct k_msgq) , DPL_MAX_MSGQS, MEM_ALIGN);
26 
dpl_msgq_pool_alloc()27 static struct k_msgq *dpl_msgq_pool_alloc()
28 {
29     struct k_msgq  *msgq_ptr = NULL;
30 
31     if (k_mem_slab_alloc(&msgq_slab, (void **)&msgq_ptr, K_NO_WAIT) < 0) {
32 
33          __ASSERT(0, "Increase size of DPL message queue pool");
34     }
35     return msgq_ptr;
36 }
37 
dpl_msgq_pool_free(struct k_msgq * msgq)38 static void dpl_msgq_pool_free(struct k_msgq *msgq)
39 {
40 
41     k_mem_slab_free(&msgq_slab, (void *)msgq);
42 
43     return;
44 }
45 
46 /*
47  *  ======== MessageQueueP_create ========
48  */
MessageQueueP_create(size_t msgSize,size_t msgCount)49 MessageQueueP_Handle MessageQueueP_create(size_t msgSize, size_t msgCount)
50 {
51     struct k_msgq *msgq = dpl_msgq_pool_alloc();
52     int status = k_msgq_alloc_init(msgq, msgSize, msgCount);
53     if(status != 0)
54     {
55         return NULL;
56     }
57     return (MessageQueueP_Handle) msgq;
58 }
59 
60 /*
61  *  ======== MessageQueueP_delete ========
62  */
MessageQueueP_delete(MessageQueueP_Handle handle)63 void MessageQueueP_delete(MessageQueueP_Handle handle)
64 {
65     if (handle != NULL)
66     {
67         struct k_msgq* msgq;
68         msgq = (struct k_msgq* )handle;
69         k_msgq_purge(msgq);
70         k_msgq_cleanup(msgq);
71         dpl_msgq_pool_free(msgq);
72     }
73 }
74 #endif  /* CONFIG_DYNAMIC_DPL_OBJECTS */
75 
76 /*
77  *  ======== MessageQueueP_construct ========
78  */
MessageQueueP_construct(MessageQueueP_Struct * msgStruct,size_t msgSize,size_t msgCount,void * msgBuf)79 MessageQueueP_Handle MessageQueueP_construct(MessageQueueP_Struct *msgStruct,
80                                              size_t msgSize,
81                                              size_t msgCount,
82                                              void *msgBuf)
83 {
84     struct k_msgq* msgq;
85     msgq = (struct k_msgq* )msgStruct;
86     if (msgq) {
87         k_msgq_init(msgq, msgBuf, msgSize, msgCount);
88     }
89 
90     return (MessageQueueP_Handle)msgq;
91 }
92 
93 /*
94  *  ======== MessageQueueP_destruct ========
95  */
MessageQueueP_destruct(MessageQueueP_Handle handle)96 void MessageQueueP_destruct(MessageQueueP_Handle handle)
97 {
98     k_msgq_purge((struct k_msgq* )handle);
99 }
100 
101 /*
102  *  ======== MessageQueueP_pend ========
103  */
MessageQueueP_pend(MessageQueueP_Handle handle,void * message,uint32_t timeout)104 MessageQueueP_Status MessageQueueP_pend(MessageQueueP_Handle handle, void *message, uint32_t timeout)
105 {
106     uint32_t tickPeriod;
107     k_timeout_t msgTimeout;
108 
109     /* Timeout must be K_NO_WAIT if in an ISR */
110     if ((timeout == MessageQueueP_NO_WAIT) || k_is_in_isr())
111     {
112         msgTimeout = K_NO_WAIT;
113     }
114     else if (timeout == MessageQueueP_WAIT_FOREVER)
115     {
116         msgTimeout = K_FOREVER;
117     }
118     else
119     {
120         /* If necessary, convert ClockP ticks to Zephyr ticks */
121         /* Should really be ClockP_getSystemTickPeriod() but this causes issues with ielftool post build step */
122         tickPeriod = ClockP_TICK_PERIOD;
123         msgTimeout = K_TICKS(timeout);
124     }
125     int status = k_msgq_get((struct k_msgq*) handle, message, msgTimeout);
126     if(status == 0)
127     {
128         return MessageQueueP_OK;
129     }
130     return MessageQueueP_TIMEOUT;
131 }
132 
133 /*
134  *  ======== MessageQueueP_peek ========
135  */
MessageQueueP_peek(MessageQueueP_Handle handle,void * message,uint32_t timeout)136 MessageQueueP_Status MessageQueueP_peek(MessageQueueP_Handle handle, void *message, uint32_t timeout)
137 {
138     assert(timeout == MessageQueueP_NO_WAIT);
139     /* Zephyr peek does not support timeouts*/
140     uint32_t status = k_msgq_peek((struct k_msgq*) handle, message);
141 
142     if(status == 0)
143     {
144         return MessageQueueP_OK;
145     }
146     return MessageQueueP_TIMEOUT;
147 }
148 
149 /*
150  *  ======== MessageQueueP_post ========
151  */
MessageQueueP_post(MessageQueueP_Handle handle,const void * message,uint32_t timeout)152 MessageQueueP_Status MessageQueueP_post(MessageQueueP_Handle handle, const void *message, uint32_t timeout)
153 {
154     uint32_t tickPeriod;
155     k_timeout_t msgTimeout;
156     uint64_t timeUS;
157 
158     if (timeout == MessageQueueP_NO_WAIT)
159     {
160         msgTimeout = K_NO_WAIT;
161     }
162     else if (timeout == MessageQueueP_WAIT_FOREVER)
163     {
164         msgTimeout = K_FOREVER;
165     }
166     else
167     {
168         /* if necessary, convert ClockP ticks to Zephyr ticks */
169         /* Should really be ClockP_getSystemTickPeriod() but this causes issues with ielftool post build step */
170         tickPeriod = ClockP_TICK_PERIOD;
171         if (tickPeriod != CONFIG_SYS_CLOCK_TICKS_PER_SEC)
172         {
173             timeUS  = timeout * (uint64_t)tickPeriod;
174             msgTimeout = K_USEC(timeUS);
175         }
176         else
177         {
178             msgTimeout = K_TICKS(timeout);
179         }
180     }
181 
182     int status = k_msgq_put((struct k_msgq*) handle, message, msgTimeout);
183 
184     if(status == 0)
185     {
186         return MessageQueueP_OK;
187     }
188     return MessageQueueP_TIMEOUT;
189 }
190 
191 /*
192  *  ======== MessageQueueP_postFront ========
193  */
MessageQueueP_postFront(MessageQueueP_Handle handle,const void * message,uint32_t timeout)194 MessageQueueP_Status MessageQueueP_postFront(MessageQueueP_Handle handle, const void *message, uint32_t timeout)
195 {
196     return MessageQueueP_post(handle, message, timeout);
197 }
198 
199 /*
200  *  ======== MessageQueueP_getPendingCount ========
201  */
MessageQueueP_getPendingCount(MessageQueueP_Handle handle)202 size_t MessageQueueP_getPendingCount(MessageQueueP_Handle handle)
203 {
204     size_t msgCount = k_msgq_num_used_get((struct k_msgq*) handle);
205     return msgCount;
206 }
207 
208 /*
209  *  ======== MessageQueueP_getFreeCount ========
210  */
MessageQueueP_getFreeCount(MessageQueueP_Handle handle)211 size_t MessageQueueP_getFreeCount(MessageQueueP_Handle handle)
212 {
213     size_t freeMsgCount = k_msgq_num_free_get((struct k_msgq*) handle);
214 
215     return freeMsgCount;
216 }
217 
218 /*
219  *  ======== MessageQueueP_getMessageQueueObjectSize ========
220  */
MessageQueueP_getMessageQueueObjectSize(void)221 uint32_t MessageQueueP_getMessageQueueObjectSize(void)
222 {
223     return sizeof(struct k_msgq);
224 }
225