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.
Dependencies: MAX44000 PWM_Tone_Library nexpaq_mdk
Fork of LED_Demo by
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 ns_timer_init(); 00232 timer_sys_init(); //initialize timer 00233 /* Set Tasklett switcher to Idle */ 00234 curr_tasklet = 0; 00235 00236 } 00237 00238 00239 int8_t eventOS_scheduler_get_active_tasklet(void) 00240 { 00241 return curr_tasklet; 00242 } 00243 00244 void eventOS_scheduler_set_active_tasklet(int8_t tasklet) 00245 { 00246 curr_tasklet = tasklet; 00247 } 00248 00249 int eventOS_scheduler_timer_stop(void) 00250 { 00251 timer_sys_disable(); 00252 if (ns_timer_sleep() != 0) { 00253 return 1; 00254 } 00255 return 0; 00256 } 00257 00258 int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks) 00259 { 00260 //Update MS to 10ms ticks 00261 sleep_ticks /= 10; 00262 sleep_ticks++; 00263 system_timer_tick_update(sleep_ticks); 00264 if (timer_sys_wakeup() == 0) { 00265 return 0; 00266 } 00267 return -1; 00268 } 00269 00270 /** 00271 * 00272 * \brief Infinite Event Read Loop. 00273 * 00274 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep 00275 * 00276 */ 00277 bool eventOS_scheduler_dispatch_event(void) 00278 { 00279 arm_core_tasklet_list_s *tasklet; 00280 arm_core_event_s *cur_event; 00281 arm_event_s event; 00282 00283 curr_tasklet = 0; 00284 00285 cur_event = event_core_read(); 00286 if (cur_event) { 00287 event = cur_event->data; 00288 event_core_free_push(cur_event); 00289 tasklet = event_tasklet_handler_get(event.receiver); 00290 if (tasklet) { 00291 curr_tasklet = event.receiver; 00292 /* Tasklet Scheduler Call */ 00293 tasklet->func_ptr(&event); 00294 /* Set Current Tasklet to Idle state */ 00295 curr_tasklet = 0; 00296 } 00297 return true; 00298 } else { 00299 return false; 00300 } 00301 } 00302 00303 void eventOS_scheduler_run_until_idle(void) 00304 { 00305 while (eventOS_scheduler_dispatch_event()); 00306 } 00307 00308 /** 00309 * 00310 * \brief Infinite Event Read Loop. 00311 * 00312 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep 00313 * 00314 */ 00315 NS_NORETURN void eventOS_scheduler_run(void) 00316 { 00317 while (1) { 00318 if (!eventOS_scheduler_dispatch_event()) { 00319 eventOS_scheduler_idle(); 00320 } 00321 } 00322 }
Generated on Tue Jul 12 2022 12:28:30 by
