• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <string.h>
17 #include "wm_mem.h"
18 #include "wm_wl_task.h"
19 #include "wm_wl_timers.h"
20 
21 struct tls_timeo {
22     struct tls_timeo *next;
23     u32 time;
24     tls_timeout_handler h;
25     void *arg;
26 };
27 
28 /** The one and only timeout list */
29 struct tls_timeo *next_timeout[TLS_TIMEO_ALL_COUONT];
30 
31 /**
32  * @brief          Wait (forever) for a message to arrive in an mbox.
33  *                 While waiting, timeouts are processed
34  *
35  * @param[in]      timeo_assigned   timer NO. by assigned
36  * @param[in]      mbox             the mbox to fetch the message from
37  * @param[out]     **msg            the place to store the message
38  *
39  * @return         None
40  *
41  * @note           None
42  */
tls_timeouts_mbox_fetch_p(u8 timeo_assigned,tls_mbox_t mbox,void ** msg)43 void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg)
44 {
45     u32 time_needed;
46     struct tls_timeo *tmptimeout;
47     tls_timeout_handler handler;
48     void *arg;
49 
50     struct tls_timeo **timeo = &next_timeout[timeo_assigned];
51 
52     again:
53     if (!(*timeo)) {
54         time_needed = tls_arch_mbox_fetch(mbox, msg, 0);
55     } else {
56         if ((*timeo)->time > 0) {
57             time_needed = tls_arch_mbox_fetch(mbox, msg, (*timeo)->time);
58         } else {
59             time_needed = SYS_ARCH_TIMEOUT;
60         }
61 
62         if (time_needed == SYS_ARCH_TIMEOUT) {
63             /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
64             could be fetched. We should now call the timeout handler and
65             deallocate the memory allocated for the timeout. */
66             tmptimeout = *timeo;
67             *timeo = tmptimeout -> next;
68             handler = tmptimeout -> h;
69             arg = tmptimeout -> arg;
70             tls_mem_free(tmptimeout);
71             if (handler != NULL) {
72                 handler(arg);
73             }
74 
75             /* We try again to fetch a message from the mbox. */
76             goto again;
77         } else {
78             /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
79             occured. The time variable is set to the number of
80             milliseconds we waited for the message. */
81             if (time_needed < (*timeo)->time) {
82                 (*timeo)->time -= time_needed;
83             } else {
84                 (*timeo)->time = 0;
85             }
86         }
87     }
88 }
89 
90 /**
91  * @brief          create a one-shot timer (aka timeout)
92  *
93  * @param[in]      timeo_assigned   timer NO. by assigned
94  * @param[in]      msecs            time in milliseconds after that the timer should expire
95  * @param[in]      handler          callback function that would be called by the timeout
96  * @param[in]      *arg             callback argument that would be passed to handler
97  *
98  * @return         None
99  *
100  * @note           while waiting for a message using sys_timeouts_mbox_fetch()
101  */
tls_timeout_p(u8 timeo_assigned,u32 msecs,tls_timeout_handler handler,void * arg)102 void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg)
103 {
104     struct tls_timeo *timeout, *t;
105     struct tls_timeo **timeo = &next_timeout[timeo_assigned];
106 
107     timeout = (struct tls_timeo *)tls_mem_alloc(sizeof(struct tls_timeo));
108     if (timeout == NULL) {
109         return;
110     }
111     timeout->next = NULL;
112     timeout->h = handler;
113     timeout->arg = arg;
114     timeout->time = msecs;
115 
116     if (*timeo == NULL) {
117         *timeo = timeout;
118         return;
119     }
120 
121     if ((*timeo)->time > msecs) {
122         (*timeo)->time -= msecs;
123         timeout->next = *timeo;
124         *timeo = timeout;
125     } else {
126         for (t = *timeo; t != NULL; t = t->next) {
127             timeout->time -= t->time;
128             if (t->next == NULL || t->next->time > timeout->time) {
129                 if (t->next != NULL) {
130                     t->next->time -= timeout->time;
131                 }
132                 timeout->next = t->next;
133                 t->next = timeout;
134                 break;
135             }
136         }
137     }
138 }
139 
140 /**
141  * @brief          Go through timeout list (for this task only) and remove the first
142  *                 matching entry, even though the timeout has not triggered yet
143  *
144  * @param[in]      timeo_assigned   timer NO. by assigned
145  * @param[in]      handler          callback function that would be called by the timeout
146  * @param[in]      *arg             callback argument that would be passed to handler
147  *
148  * @return         None
149  *
150  * @note           None
151  */
tls_untimeout_p(u8 timeo_assigned,tls_timeout_handler handler,void * arg)152 void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg)
153 {
154     struct tls_timeo *prev_t, *t;
155     struct tls_timeo **timeo = &next_timeout[timeo_assigned];
156 
157     if (*timeo == NULL) {
158         return;
159     }
160 
161     for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
162         if ((t->h == handler) && (t->arg == arg)) {
163             /* We have a match */
164             /* Unlink from previous in list */
165             if (prev_t == NULL) {
166                 *timeo = t->next;
167             } else {
168                 prev_t->next = t->next;
169             }
170             /* If not the last one, add time of this one back to next */
171             if (t->next != NULL) {
172                 t->next->time += t->time;
173             }
174             tls_mem_free(t);
175             return;
176         }
177     }
178     return;
179 }
180 
181 /**
182  * @brief          timer initialized
183  *
184  * @param          None
185  *
186  * @return         None
187  *
188  * @note           None
189  */
tls_wl_timer_init(void)190 s8 tls_wl_timer_init(void)
191 {
192     memset(next_timeout, 0, sizeof(struct tls_timeo *) *TLS_TIMEO_ALL_COUONT);
193     return 0;
194 }
195