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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 11:02:37 by
