common: Use asm instead of __ASM in USB_OsaEnterCritical().
[gps-watch.git] / src / common / usb_osa_bm.c
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016 NXP
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  * that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  *   of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  *   list of conditions and the following disclaimer in the documentation and/or
16  *   other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  *   contributors may be used to endorse or promote products derived from this
20  *   software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include "stdint.h"
35 #include "usb.h"
36 #include "usb_osa.h"
37 #include "stdlib.h"
38 #include "fsl_device_registers.h"
39 #include "fsl_common.h"
40
41 /*******************************************************************************
42  * Definitions
43  ******************************************************************************/
44 #define USB_OSA_BM_EVENT_COUNT (4U)
45 #define USB_OSA_BM_SEM_COUNT (1U)
46 #define USB_OSA_BM_MSGQ_COUNT (1U)
47 #define USB_OSA_BM_MSG_COUNT (8U)
48 #define USB_OSA_BM_MSG_SIZE (4U)
49
50 /* BM Event status structure */
51 typedef struct _usb_osa_event_struct
52 {
53     uint32_t value; /* Event mask */
54     uint32_t flag;  /* Event flags, includes auto clear flag */
55     uint8_t isUsed; /* Is used */
56 } usb_osa_event_struct_t;
57
58 /* BM semaphore status structure */
59 typedef struct _usb_osa_sem_struct
60 {
61     uint32_t value; /* Semaphore count */
62     uint8_t isUsed; /* Is used */
63 } usb_osa_sem_struct_t;
64
65 /* BM msg status structure */
66 typedef struct _usb_osa_msg_struct
67 {
68     uint32_t msg[USB_OSA_BM_MSG_SIZE]; /* Message entity pointer */
69 } usb_osa_msg_struct_t;
70
71 /* BM msgq status structure */
72 typedef struct _usb_osa_msgq_struct
73 {
74     usb_osa_msg_struct_t msgs[USB_OSA_BM_MSG_COUNT]; /* Message entity list */
75     uint32_t count;                                  /* Max message entity count */
76     uint32_t msgSize;                                /* Size of each message */
77     uint32_t msgCount;                               /* Valid messages */
78     uint32_t index;                                  /* The first empty message entity index */
79     uint32_t current;                                /* The vaild message index */
80     uint8_t isUsed;                                  /* Is used */
81 } usb_osa_msgq_struct_t;
82
83 /*******************************************************************************
84  * Prototypes
85  ******************************************************************************/
86
87 /*******************************************************************************
88  * Variables
89  ******************************************************************************/
90
91 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_sem_struct_t
92     s_UsbBmSemStruct[USB_OSA_BM_SEM_COUNT];
93 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_event_struct_t
94     s_UsbBmEventStruct[USB_OSA_BM_EVENT_COUNT];
95 USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static usb_osa_msgq_struct_t
96     s_UsbBmMsgqStruct[USB_OSA_BM_MSGQ_COUNT];
97
98 /*******************************************************************************
99  * Code
100  ******************************************************************************/
101
102 void *USB_OsaMemoryAllocate(uint32_t length)
103 {
104     void *p = (void *)malloc(length);
105     uint8_t *temp = (uint8_t *)p;
106     if (p)
107     {
108         for (uint32_t count = 0U; count < length; count++)
109         {
110             temp[count] = 0U;
111         }
112     }
113     return p;
114 }
115
116 void USB_OsaMemoryFree(void *p)
117 {
118     free(p);
119 }
120
121 void USB_OsaEnterCritical(uint32_t *sr)
122 {
123     *sr = DisableGlobalIRQ();
124     asm("CPSID I");
125 }
126
127 void USB_OsaExitCritical(uint32_t sr)
128 {
129     EnableGlobalIRQ(sr);
130 }
131
132 usb_osa_status_t USB_OsaEventCreate(usb_osa_event_handle *handle, uint32_t flag)
133 {
134     usb_osa_event_struct_t *event = NULL;
135     USB_OSA_SR_ALLOC();
136
137     if (!handle)
138     {
139         return kStatus_USB_OSA_Error;
140     }
141
142     USB_OSA_ENTER_CRITICAL();
143     for (uint32_t i = 0; i < USB_OSA_BM_EVENT_COUNT; i++)
144     {
145         if (0 == s_UsbBmEventStruct[i].isUsed)
146         {
147             event = &s_UsbBmEventStruct[i];
148             break;
149         }
150     }
151
152     if (NULL == event)
153     {
154         USB_OSA_EXIT_CRITICAL();
155         return kStatus_USB_OSA_Error;
156     }
157
158     event->value = 0U;
159     event->flag = flag;
160     event->isUsed = 1;
161     *handle = event;
162     USB_OSA_EXIT_CRITICAL();
163     return kStatus_USB_OSA_Success;
164 }
165
166 usb_osa_status_t USB_OsaEventDestroy(usb_osa_event_handle handle)
167 {
168     usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle;
169     USB_OSA_SR_ALLOC();
170
171     if (handle)
172     {
173         USB_OSA_ENTER_CRITICAL();
174         event->isUsed = 0;
175         USB_OSA_EXIT_CRITICAL();
176         return kStatus_USB_OSA_Success;
177     }
178     return kStatus_USB_OSA_Error;
179 }
180
181 usb_osa_status_t USB_OsaEventSet(usb_osa_event_handle handle, uint32_t bitMask)
182 {
183     usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle;
184     USB_OSA_SR_ALLOC();
185
186     if (handle)
187     {
188         USB_OSA_ENTER_CRITICAL();
189         event->value |= bitMask;
190         USB_OSA_EXIT_CRITICAL();
191         return kStatus_USB_OSA_Success;
192     }
193     return kStatus_USB_OSA_Error;
194 }
195
196 usb_osa_status_t USB_OsaEventWait(
197     usb_osa_event_handle handle, uint32_t bitMask, uint32_t flag, uint32_t timeout, uint32_t *bitSet)
198 {
199     usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle;
200     uint32_t bits;
201     USB_OSA_SR_ALLOC();
202
203     if (handle)
204     {
205         USB_OSA_ENTER_CRITICAL();
206         bits = event->value & bitMask;
207         if (flag)
208         {
209             if (bits != bitMask)
210             {
211                 USB_OSA_EXIT_CRITICAL();
212                 return kStatus_USB_OSA_TimeOut;
213             }
214         }
215         else
216         {
217             if (!bits)
218             {
219                 USB_OSA_EXIT_CRITICAL();
220                 return kStatus_USB_OSA_TimeOut;
221             }
222         }
223         if (bitSet)
224         {
225             *bitSet = bits;
226         }
227         if (event->flag)
228         {
229             event->value &= ~bits;
230         }
231         USB_OSA_EXIT_CRITICAL();
232         return kStatus_USB_OSA_Success;
233     }
234     return kStatus_USB_OSA_Error;
235 }
236
237 usb_osa_status_t USB_OsaEventCheck(usb_osa_event_handle handle, uint32_t bitMask, uint32_t *bitSet)
238 {
239     usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle;
240     uint32_t bits;
241     USB_OSA_SR_ALLOC();
242
243     if (handle)
244     {
245         USB_OSA_ENTER_CRITICAL();
246         bits = event->value & bitMask;
247
248         if (!bits)
249         {
250             USB_OSA_EXIT_CRITICAL();
251             return kStatus_USB_OSA_Error;
252         }
253
254         if (bitSet)
255         {
256             *bitSet = bits;
257         }
258         USB_OSA_EXIT_CRITICAL();
259         return kStatus_USB_OSA_Success;
260     }
261     return kStatus_USB_OSA_Error;
262 }
263
264 usb_osa_status_t USB_OsaEventClear(usb_osa_event_handle handle, uint32_t bitMask)
265 {
266     usb_osa_event_struct_t *event = (usb_osa_event_struct_t *)handle;
267     uint32_t bits;
268     USB_OSA_SR_ALLOC();
269
270     if (handle)
271     {
272         USB_OSA_ENTER_CRITICAL();
273         bits = event->value & bitMask;
274         event->value &= ~bits;
275         USB_OSA_EXIT_CRITICAL();
276         return kStatus_USB_OSA_Success;
277     }
278     return kStatus_USB_OSA_Error;
279 }
280
281 usb_osa_status_t USB_OsaSemCreate(usb_osa_sem_handle *handle, uint32_t count)
282 {
283     usb_osa_sem_struct_t *sem = NULL;
284     USB_OSA_SR_ALLOC();
285
286     if (!handle)
287     {
288         return kStatus_USB_OSA_Error;
289     }
290
291     USB_OSA_ENTER_CRITICAL();
292     for (uint32_t i = 0; i < USB_OSA_BM_SEM_COUNT; i++)
293     {
294         if (0 == s_UsbBmSemStruct[i].isUsed)
295         {
296             sem = &s_UsbBmSemStruct[i];
297             break;
298         }
299     }
300     if (NULL == sem)
301     {
302         USB_OSA_EXIT_CRITICAL();
303         return kStatus_USB_OSA_Error;
304     }
305
306     sem->value = count;
307     sem->isUsed = 1;
308     *handle = sem;
309     USB_OSA_EXIT_CRITICAL();
310     return kStatus_USB_OSA_Success;
311 }
312
313 usb_osa_status_t USB_OsaSemDestroy(usb_osa_sem_handle handle)
314 {
315     usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle;
316     USB_OSA_SR_ALLOC();
317
318     if (handle)
319     {
320         USB_OSA_ENTER_CRITICAL();
321         sem->isUsed = 0;
322         USB_OSA_EXIT_CRITICAL();
323         return kStatus_USB_OSA_Success;
324     }
325     return kStatus_USB_OSA_Error;
326 }
327
328 usb_osa_status_t USB_OsaSemPost(usb_osa_sem_handle handle)
329 {
330     usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle;
331     USB_OSA_SR_ALLOC();
332
333     if (!handle)
334     {
335         return kStatus_USB_OSA_Error;
336     }
337
338     USB_OSA_ENTER_CRITICAL();
339     sem->value++;
340     USB_OSA_EXIT_CRITICAL();
341     return kStatus_USB_OSA_Success;
342 }
343
344 usb_osa_status_t USB_OsaSemWait(usb_osa_sem_handle handle, uint32_t timeout)
345 {
346     usb_osa_sem_struct_t *sem = (usb_osa_sem_struct_t *)handle;
347     USB_OSA_SR_ALLOC();
348
349     if (!handle)
350     {
351         return kStatus_USB_OSA_Error;
352     }
353
354     USB_OSA_ENTER_CRITICAL();
355     if (sem->value)
356     {
357         sem->value--;
358     }
359     else
360     {
361         USB_OSA_EXIT_CRITICAL();
362         return kStatus_USB_OSA_TimeOut;
363     }
364     USB_OSA_EXIT_CRITICAL();
365     return kStatus_USB_OSA_Success;
366 }
367
368 usb_osa_status_t USB_OsaMutexCreate(usb_osa_mutex_handle *handle)
369 {
370     if (!handle)
371     {
372         return kStatus_USB_OSA_Error;
373     }
374     *handle = (usb_osa_mutex_handle)0xFFFF0000U;
375     return kStatus_USB_OSA_Success;
376 }
377
378 usb_osa_status_t USB_OsaMutexDestroy(usb_osa_mutex_handle handle)
379 {
380     return kStatus_USB_OSA_Success;
381 }
382 usb_osa_status_t USB_OsaMutexLock(usb_osa_mutex_handle handle)
383 {
384     return kStatus_USB_OSA_Success;
385 }
386 usb_osa_status_t USB_OsaMutexUnlock(usb_osa_mutex_handle handle)
387 {
388     return kStatus_USB_OSA_Success;
389 }
390
391 usb_osa_status_t USB_OsaMsgqCreate(usb_osa_msgq_handle *handle, uint32_t count, uint32_t size)
392 {
393     usb_osa_msgq_struct_t *msgq = NULL;
394     USB_OSA_SR_ALLOC();
395
396     if (!handle)
397     {
398         return kStatus_USB_OSA_Error;
399     }
400     USB_OSA_ENTER_CRITICAL();
401
402     for (uint32_t i = 0; i < USB_OSA_BM_MSGQ_COUNT; i++)
403     {
404         if (0 == s_UsbBmMsgqStruct[i].isUsed)
405         {
406             msgq = &s_UsbBmMsgqStruct[i];
407             break;
408         }
409     }
410     if ((NULL == msgq) || (count > USB_OSA_BM_MSG_COUNT) || (size > USB_OSA_BM_MSG_SIZE))
411     {
412         USB_OSA_EXIT_CRITICAL();
413         return kStatus_USB_OSA_Error;
414     }
415     msgq->count = count;
416     msgq->msgSize = size;
417     msgq->msgCount = 0U;
418     msgq->index = 0U;
419     msgq->current = 0U;
420     msgq->isUsed = 1;
421     *handle = msgq;
422     USB_OSA_EXIT_CRITICAL();
423     return kStatus_USB_OSA_Success;
424 }
425
426 usb_osa_status_t USB_OsaMsgqDestroy(usb_osa_msgq_handle handle)
427 {
428     usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle;
429     USB_OSA_SR_ALLOC();
430
431     if (!handle)
432     {
433         return kStatus_USB_OSA_Error;
434     }
435     USB_OSA_ENTER_CRITICAL();
436     msgq->isUsed = 0;
437     USB_OSA_EXIT_CRITICAL();
438     return kStatus_USB_OSA_Success;
439 }
440
441 usb_osa_status_t USB_OsaMsgqSend(usb_osa_msgq_handle handle, void *msg)
442 {
443     usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle;
444     usb_osa_msg_struct_t *msgEntity;
445     uint32_t *p;
446     uint32_t *q;
447     uint32_t count;
448     USB_OSA_SR_ALLOC();
449
450     if (!handle)
451     {
452         return kStatus_USB_OSA_Error;
453     }
454     USB_OSA_ENTER_CRITICAL();
455     if (msgq->msgCount >= msgq->count)
456     {
457         USB_OSA_EXIT_CRITICAL();
458         return kStatus_USB_OSA_Error;
459     }
460
461     msgEntity = &msgq->msgs[msgq->index];
462     p = (uint32_t *)&msgEntity->msg[0];
463     q = (uint32_t *)msg;
464
465     for (count = 0U; count < msgq->msgSize; count++)
466     {
467         p[count] = q[count];
468     }
469
470     if (0U == msgq->msgCount)
471     {
472         msgq->current = msgq->index;
473     }
474
475     msgq->msgCount++;
476     msgq->index++;
477     msgq->index = msgq->index % msgq->count;
478
479     USB_OSA_EXIT_CRITICAL();
480
481     return kStatus_USB_OSA_Success;
482 }
483
484 usb_osa_status_t USB_OsaMsgqRecv(usb_osa_msgq_handle handle, void *msg, uint32_t timeout)
485 {
486     usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle;
487     usb_osa_msg_struct_t *msgEntity;
488     uint32_t *p;
489     uint32_t *q;
490     uint32_t count;
491     USB_OSA_SR_ALLOC();
492
493     if (!handle)
494     {
495         return kStatus_USB_OSA_Error;
496     }
497     USB_OSA_ENTER_CRITICAL();
498     if (msgq->msgCount < 1U)
499     {
500         USB_OSA_EXIT_CRITICAL();
501         return kStatus_USB_OSA_TimeOut;
502     }
503
504     msgEntity = &msgq->msgs[msgq->current];
505     q = (uint32_t *)&msgEntity->msg[0];
506     p = (uint32_t *)msg;
507
508     for (count = 0U; count < msgq->msgSize; count++)
509     {
510         p[count] = q[count];
511     }
512
513     msgq->msgCount--;
514     msgq->current++;
515     msgq->current = msgq->current % msgq->count;
516
517     USB_OSA_EXIT_CRITICAL();
518
519     return kStatus_USB_OSA_Success;
520 }
521
522 usb_osa_status_t USB_OsaMsgqCheck(usb_osa_msgq_handle handle, void *msg)
523 {
524     usb_osa_msgq_struct_t *msgq = (usb_osa_msgq_struct_t *)handle;
525     uint32_t msgCount;
526     USB_OSA_SR_ALLOC();
527
528     if (!handle)
529     {
530         return kStatus_USB_OSA_Error;
531     }
532
533     USB_OSA_ENTER_CRITICAL();
534     msgCount = msgq->msgCount;
535     USB_OSA_EXIT_CRITICAL();
536
537     if (msgCount)
538     {
539         if (kStatus_USB_OSA_Success == USB_OsaMsgqRecv(msgq, msg, 0U))
540         {
541             return kStatus_USB_OSA_Success;
542         }
543     }
544
545     return kStatus_USB_OSA_Error;
546 }