Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
event.c
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <string.h> 00017 #include "ns_types.h" 00018 #include "ns_list.h" 00019 #include "eventOS_event.h" 00020 #include "eventOS_scheduler.h" 00021 #include "timer_sys.h" 00022 #include "nsdynmemLIB.h" 00023 #include "ns_timer.h" 00024 00025 #include "platform/arm_hal_interrupt.h" 00026 00027 00028 typedef struct arm_core_tasklet_list_s { 00029 int8_t id; /**< Event handler Tasklet ID */ 00030 void (*func_ptr)(arm_event_s *); 00031 ns_list_link_t link; 00032 } arm_core_tasklet_list_s; 00033 00034 typedef struct arm_core_event_s { 00035 arm_event_s data; 00036 ns_list_link_t link; 00037 } arm_core_event_s; 00038 00039 static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_list_s, link); 00040 static NS_LIST_DEFINE(event_queue_active, arm_core_event_s, link); 00041 static NS_LIST_DEFINE(free_event_entry, arm_core_event_s, link); 00042 00043 /** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */ 00044 int8_t curr_tasklet = 0; 00045 00046 00047 static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void); 00048 static arm_core_event_s *event_dynamically_allocate(void); 00049 static arm_core_event_s *event_core_get(void); 00050 static void event_core_write(arm_core_event_s *event); 00051 00052 static arm_core_tasklet_list_s *event_tasklet_handler_get(uint8_t tasklet_id) 00053 { 00054 ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) { 00055 if (cur->id == tasklet_id) { 00056 return cur; 00057 } 00058 } 00059 return NULL; 00060 } 00061 00062 // XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least 00063 // curr_tasklet is reset to 0 in various places. 00064 static int8_t tasklet_get_free_id(void) 00065 { 00066 /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/ 00067 for (uint8_t i = 0; i <= INT8_MAX; i++) { 00068 if (!event_tasklet_handler_get(i)) { 00069 return i; 00070 } 00071 } 00072 return -1; 00073 } 00074 00075 00076 int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type) 00077 { 00078 arm_core_event_s *event_tmp; 00079 00080 // XXX Do we really want to prevent multiple tasklets with same function? 00081 ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) { 00082 if (cur->func_ptr == handler_func_ptr) { 00083 return -1; 00084 } 00085 } 00086 00087 //Allocate new 00088 arm_core_tasklet_list_s *new = tasklet_dynamically_allocate(); 00089 if (!new) { 00090 return -2; 00091 } 00092 00093 event_tmp = event_core_get(); 00094 if (!event_tmp) { 00095 ns_dyn_mem_free(new); 00096 return -2; 00097 } 00098 00099 //Fill in tasklet; add to list 00100 new->id = tasklet_get_free_id(); 00101 new->func_ptr = handler_func_ptr; 00102 ns_list_add_to_end(&arm_core_tasklet_list, new); 00103 00104 //Queue "init" event for the new task 00105 event_tmp->data.receiver = new->id; 00106 event_tmp->data.sender = 0; 00107 event_tmp->data.event_type = init_event_type; 00108 event_tmp->data.event_data = 0; 00109 event_core_write(event_tmp); 00110 00111 return new->id; 00112 } 00113 00114 /** 00115 * \brief Send event to event scheduler. 00116 * 00117 * \param event pointer to pushed event. 00118 * 00119 * \return 0 Event push OK 00120 * \return -1 Memory allocation Fail 00121 * 00122 */ 00123 int8_t eventOS_event_send(arm_event_s *event) 00124 { 00125 int8_t retval = -1; 00126 if (event_tasklet_handler_get(event->receiver)) { 00127 arm_core_event_s *event_tmp = event_core_get(); 00128 if (event_tmp) { 00129 event_tmp->data = *event; 00130 event_core_write(event_tmp); 00131 retval = 0; 00132 } 00133 } 00134 return retval; 00135 } 00136 00137 00138 static arm_core_event_s *event_dynamically_allocate(void) 00139 { 00140 return ns_dyn_mem_alloc(sizeof(arm_core_event_s)); 00141 } 00142 00143 static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void) 00144 { 00145 return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_list_s)); 00146 } 00147 00148 00149 arm_core_event_s *event_core_get(void) 00150 { 00151 arm_core_event_s *event; 00152 platform_enter_critical(); 00153 event = ns_list_get_first(&free_event_entry); 00154 if (event) { 00155 ns_list_remove(&free_event_entry, event); 00156 } else { 00157 event = event_dynamically_allocate(); 00158 } 00159 if (event) { 00160 event->data.data_ptr = NULL; 00161 event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT; 00162 } 00163 platform_exit_critical(); 00164 return event; 00165 } 00166 00167 static void event_core_free_push(arm_core_event_s *free) 00168 { 00169 platform_enter_critical(); 00170 ns_list_add_to_start(&free_event_entry, free); 00171 platform_exit_critical(); 00172 } 00173 00174 00175 static arm_core_event_s *event_core_read(void) 00176 { 00177 arm_core_event_s *event; 00178 platform_enter_critical(); 00179 event = ns_list_get_first(&event_queue_active); 00180 if (event) { 00181 ns_list_remove(&event_queue_active, event); 00182 } 00183 platform_exit_critical(); 00184 return event; 00185 } 00186 00187 void event_core_write(arm_core_event_s *event) 00188 { 00189 platform_enter_critical(); 00190 bool added = false; 00191 ns_list_foreach(arm_core_event_s, event_tmp, &event_queue_active) { 00192 // note enum ordering means we're checking if event_tmp is LOWER priority than event 00193 if (event_tmp->data.priority > event->data.priority) { 00194 ns_list_add_before(&event_queue_active, event_tmp, event); 00195 added = true; 00196 break; 00197 } 00198 } 00199 if (!added) { 00200 ns_list_add_to_end(&event_queue_active, event); 00201 } 00202 00203 /* Wake From Idle */ 00204 platform_exit_critical(); 00205 eventOS_scheduler_signal(); 00206 } 00207 00208 /** 00209 * 00210 * \brief Initialize Nanostack Core. 00211 * 00212 * Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined. 00213 * 00214 */ 00215 void eventOS_scheduler_init(void) 00216 { 00217 /* Reset Event List variables */ 00218 ns_list_init(&free_event_entry); 00219 ns_list_init(&event_queue_active); 00220 ns_list_init(&arm_core_tasklet_list); 00221 00222 //Allocate 10 entry 00223 for (uint8_t i = 0; i < 10; i++) { 00224 arm_core_event_s *event = event_dynamically_allocate(); 00225 if (event) { 00226 ns_list_add_to_start(&free_event_entry, event); 00227 } 00228 } 00229 00230 /* Init Generic timer module */ 00231 timer_sys_init(); //initialize timer 00232 /* Set Tasklett switcher to Idle */ 00233 curr_tasklet = 0; 00234 00235 } 00236 00237 00238 int8_t eventOS_scheduler_get_active_tasklet(void) 00239 { 00240 return curr_tasklet; 00241 } 00242 00243 void eventOS_scheduler_set_active_tasklet(int8_t tasklet) 00244 { 00245 curr_tasklet = tasklet; 00246 } 00247 00248 int eventOS_scheduler_timer_stop(void) 00249 { 00250 timer_sys_disable(); 00251 if (ns_timer_sleep() != 0) { 00252 return 1; 00253 } 00254 return 0; 00255 } 00256 00257 int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks) 00258 { 00259 //Update MS to 10ms ticks 00260 sleep_ticks /= 10; 00261 sleep_ticks++; 00262 system_timer_tick_update(sleep_ticks); 00263 if (timer_sys_wakeup() == 0) { 00264 return 0; 00265 } 00266 return -1; 00267 } 00268 00269 /** 00270 * 00271 * \brief Infinite Event Read Loop. 00272 * 00273 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep 00274 * 00275 */ 00276 bool eventOS_scheduler_dispatch_event(void) 00277 { 00278 arm_core_tasklet_list_s *tasklet; 00279 arm_core_event_s *cur_event; 00280 arm_event_s event; 00281 00282 curr_tasklet = 0; 00283 00284 cur_event = event_core_read(); 00285 if (cur_event) { 00286 event = cur_event->data; 00287 event_core_free_push(cur_event); 00288 tasklet = event_tasklet_handler_get(event.receiver); 00289 if (tasklet) { 00290 curr_tasklet = event.receiver; 00291 /* Tasklet Scheduler Call */ 00292 tasklet->func_ptr(&event); 00293 /* Set Current Tasklet to Idle state */ 00294 curr_tasklet = 0; 00295 } 00296 return true; 00297 } else { 00298 return false; 00299 } 00300 } 00301 00302 void eventOS_scheduler_run_until_idle(void) 00303 { 00304 while (eventOS_scheduler_dispatch_event()); 00305 } 00306 00307 /** 00308 * 00309 * \brief Infinite Event Read Loop. 00310 * 00311 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep 00312 * 00313 */ 00314 NS_NORETURN void eventOS_scheduler_run(void) 00315 { 00316 while (1) { 00317 if (!eventOS_scheduler_dispatch_event()) { 00318 eventOS_scheduler_idle(); 00319 } 00320 } 00321 }
Generated on Tue Jul 12 2022 18:19:29 by
