Daiki Kato / mbed-os-lychee

Dependents:   mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... more

Committer:
dkato
Date:
Fri Feb 02 05:42:23 2018 +0000
Revision:
0:f782d9c66c49
mbed-os for GR-LYCHEE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:f782d9c66c49 1 /*
dkato 0:f782d9c66c49 2 * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
dkato 0:f782d9c66c49 3 * SPDX-License-Identifier: Apache-2.0
dkato 0:f782d9c66c49 4 * Licensed under the Apache License, Version 2.0 (the License); you may
dkato 0:f782d9c66c49 5 * not use this file except in compliance with the License.
dkato 0:f782d9c66c49 6 * You may obtain a copy of the License at
dkato 0:f782d9c66c49 7 *
dkato 0:f782d9c66c49 8 * http://www.apache.org/licenses/LICENSE-2.0
dkato 0:f782d9c66c49 9 *
dkato 0:f782d9c66c49 10 * Unless required by applicable law or agreed to in writing, software
dkato 0:f782d9c66c49 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
dkato 0:f782d9c66c49 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dkato 0:f782d9c66c49 13 * See the License for the specific language governing permissions and
dkato 0:f782d9c66c49 14 * limitations under the License.
dkato 0:f782d9c66c49 15 */
dkato 0:f782d9c66c49 16 #include <string.h>
dkato 0:f782d9c66c49 17 #include "ns_types.h"
dkato 0:f782d9c66c49 18 #include "ns_list.h"
dkato 0:f782d9c66c49 19 #include "eventOS_event.h"
dkato 0:f782d9c66c49 20 #include "eventOS_scheduler.h"
dkato 0:f782d9c66c49 21 #include "timer_sys.h"
dkato 0:f782d9c66c49 22 #include "nsdynmemLIB.h"
dkato 0:f782d9c66c49 23 #include "ns_timer.h"
dkato 0:f782d9c66c49 24
dkato 0:f782d9c66c49 25 #include "platform/arm_hal_interrupt.h"
dkato 0:f782d9c66c49 26
dkato 0:f782d9c66c49 27
dkato 0:f782d9c66c49 28 typedef struct arm_core_tasklet_list_s {
dkato 0:f782d9c66c49 29 int8_t id; /**< Event handler Tasklet ID */
dkato 0:f782d9c66c49 30 void (*func_ptr)(arm_event_s *);
dkato 0:f782d9c66c49 31 ns_list_link_t link;
dkato 0:f782d9c66c49 32 } arm_core_tasklet_list_s;
dkato 0:f782d9c66c49 33
dkato 0:f782d9c66c49 34 typedef struct arm_core_event_s {
dkato 0:f782d9c66c49 35 arm_event_s data;
dkato 0:f782d9c66c49 36 ns_list_link_t link;
dkato 0:f782d9c66c49 37 } arm_core_event_s;
dkato 0:f782d9c66c49 38
dkato 0:f782d9c66c49 39 static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_list_s, link);
dkato 0:f782d9c66c49 40 static NS_LIST_DEFINE(event_queue_active, arm_core_event_s, link);
dkato 0:f782d9c66c49 41 static NS_LIST_DEFINE(free_event_entry, arm_core_event_s, link);
dkato 0:f782d9c66c49 42
dkato 0:f782d9c66c49 43 /** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */
dkato 0:f782d9c66c49 44 int8_t curr_tasklet = 0;
dkato 0:f782d9c66c49 45
dkato 0:f782d9c66c49 46
dkato 0:f782d9c66c49 47 static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void);
dkato 0:f782d9c66c49 48 static arm_core_event_s *event_dynamically_allocate(void);
dkato 0:f782d9c66c49 49 static arm_core_event_s *event_core_get(void);
dkato 0:f782d9c66c49 50 static void event_core_write(arm_core_event_s *event);
dkato 0:f782d9c66c49 51
dkato 0:f782d9c66c49 52 static arm_core_tasklet_list_s *event_tasklet_handler_get(uint8_t tasklet_id)
dkato 0:f782d9c66c49 53 {
dkato 0:f782d9c66c49 54 ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) {
dkato 0:f782d9c66c49 55 if (cur->id == tasklet_id) {
dkato 0:f782d9c66c49 56 return cur;
dkato 0:f782d9c66c49 57 }
dkato 0:f782d9c66c49 58 }
dkato 0:f782d9c66c49 59 return NULL;
dkato 0:f782d9c66c49 60 }
dkato 0:f782d9c66c49 61
dkato 0:f782d9c66c49 62 // XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least
dkato 0:f782d9c66c49 63 // curr_tasklet is reset to 0 in various places.
dkato 0:f782d9c66c49 64 static int8_t tasklet_get_free_id(void)
dkato 0:f782d9c66c49 65 {
dkato 0:f782d9c66c49 66 /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
dkato 0:f782d9c66c49 67 for (uint8_t i = 0; i <= INT8_MAX; i++) {
dkato 0:f782d9c66c49 68 if (!event_tasklet_handler_get(i)) {
dkato 0:f782d9c66c49 69 return i;
dkato 0:f782d9c66c49 70 }
dkato 0:f782d9c66c49 71 }
dkato 0:f782d9c66c49 72 return -1;
dkato 0:f782d9c66c49 73 }
dkato 0:f782d9c66c49 74
dkato 0:f782d9c66c49 75
dkato 0:f782d9c66c49 76 int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type)
dkato 0:f782d9c66c49 77 {
dkato 0:f782d9c66c49 78 arm_core_event_s *event_tmp;
dkato 0:f782d9c66c49 79
dkato 0:f782d9c66c49 80 // XXX Do we really want to prevent multiple tasklets with same function?
dkato 0:f782d9c66c49 81 ns_list_foreach(arm_core_tasklet_list_s, cur, &arm_core_tasklet_list) {
dkato 0:f782d9c66c49 82 if (cur->func_ptr == handler_func_ptr) {
dkato 0:f782d9c66c49 83 return -1;
dkato 0:f782d9c66c49 84 }
dkato 0:f782d9c66c49 85 }
dkato 0:f782d9c66c49 86
dkato 0:f782d9c66c49 87 //Allocate new
dkato 0:f782d9c66c49 88 arm_core_tasklet_list_s *new = tasklet_dynamically_allocate();
dkato 0:f782d9c66c49 89 if (!new) {
dkato 0:f782d9c66c49 90 return -2;
dkato 0:f782d9c66c49 91 }
dkato 0:f782d9c66c49 92
dkato 0:f782d9c66c49 93 event_tmp = event_core_get();
dkato 0:f782d9c66c49 94 if (!event_tmp) {
dkato 0:f782d9c66c49 95 ns_dyn_mem_free(new);
dkato 0:f782d9c66c49 96 return -2;
dkato 0:f782d9c66c49 97 }
dkato 0:f782d9c66c49 98
dkato 0:f782d9c66c49 99 //Fill in tasklet; add to list
dkato 0:f782d9c66c49 100 new->id = tasklet_get_free_id();
dkato 0:f782d9c66c49 101 new->func_ptr = handler_func_ptr;
dkato 0:f782d9c66c49 102 ns_list_add_to_end(&arm_core_tasklet_list, new);
dkato 0:f782d9c66c49 103
dkato 0:f782d9c66c49 104 //Queue "init" event for the new task
dkato 0:f782d9c66c49 105 event_tmp->data.receiver = new->id;
dkato 0:f782d9c66c49 106 event_tmp->data.sender = 0;
dkato 0:f782d9c66c49 107 event_tmp->data.event_type = init_event_type;
dkato 0:f782d9c66c49 108 event_tmp->data.event_data = 0;
dkato 0:f782d9c66c49 109 event_core_write(event_tmp);
dkato 0:f782d9c66c49 110
dkato 0:f782d9c66c49 111 return new->id;
dkato 0:f782d9c66c49 112 }
dkato 0:f782d9c66c49 113
dkato 0:f782d9c66c49 114 /**
dkato 0:f782d9c66c49 115 * \brief Send event to event scheduler.
dkato 0:f782d9c66c49 116 *
dkato 0:f782d9c66c49 117 * \param event pointer to pushed event.
dkato 0:f782d9c66c49 118 *
dkato 0:f782d9c66c49 119 * \return 0 Event push OK
dkato 0:f782d9c66c49 120 * \return -1 Memory allocation Fail
dkato 0:f782d9c66c49 121 *
dkato 0:f782d9c66c49 122 */
dkato 0:f782d9c66c49 123 int8_t eventOS_event_send(arm_event_s *event)
dkato 0:f782d9c66c49 124 {
dkato 0:f782d9c66c49 125 int8_t retval = -1;
dkato 0:f782d9c66c49 126 if (event_tasklet_handler_get(event->receiver)) {
dkato 0:f782d9c66c49 127 arm_core_event_s *event_tmp = event_core_get();
dkato 0:f782d9c66c49 128 if (event_tmp) {
dkato 0:f782d9c66c49 129 event_tmp->data = *event;
dkato 0:f782d9c66c49 130 event_core_write(event_tmp);
dkato 0:f782d9c66c49 131 retval = 0;
dkato 0:f782d9c66c49 132 }
dkato 0:f782d9c66c49 133 }
dkato 0:f782d9c66c49 134 return retval;
dkato 0:f782d9c66c49 135 }
dkato 0:f782d9c66c49 136
dkato 0:f782d9c66c49 137
dkato 0:f782d9c66c49 138 static arm_core_event_s *event_dynamically_allocate(void)
dkato 0:f782d9c66c49 139 {
dkato 0:f782d9c66c49 140 return ns_dyn_mem_alloc(sizeof(arm_core_event_s));
dkato 0:f782d9c66c49 141 }
dkato 0:f782d9c66c49 142
dkato 0:f782d9c66c49 143 static arm_core_tasklet_list_s *tasklet_dynamically_allocate(void)
dkato 0:f782d9c66c49 144 {
dkato 0:f782d9c66c49 145 return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_list_s));
dkato 0:f782d9c66c49 146 }
dkato 0:f782d9c66c49 147
dkato 0:f782d9c66c49 148
dkato 0:f782d9c66c49 149 arm_core_event_s *event_core_get(void)
dkato 0:f782d9c66c49 150 {
dkato 0:f782d9c66c49 151 arm_core_event_s *event;
dkato 0:f782d9c66c49 152 platform_enter_critical();
dkato 0:f782d9c66c49 153 event = ns_list_get_first(&free_event_entry);
dkato 0:f782d9c66c49 154 if (event) {
dkato 0:f782d9c66c49 155 ns_list_remove(&free_event_entry, event);
dkato 0:f782d9c66c49 156 } else {
dkato 0:f782d9c66c49 157 event = event_dynamically_allocate();
dkato 0:f782d9c66c49 158 }
dkato 0:f782d9c66c49 159 if (event) {
dkato 0:f782d9c66c49 160 event->data.data_ptr = NULL;
dkato 0:f782d9c66c49 161 event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT;
dkato 0:f782d9c66c49 162 }
dkato 0:f782d9c66c49 163 platform_exit_critical();
dkato 0:f782d9c66c49 164 return event;
dkato 0:f782d9c66c49 165 }
dkato 0:f782d9c66c49 166
dkato 0:f782d9c66c49 167 static void event_core_free_push(arm_core_event_s *free)
dkato 0:f782d9c66c49 168 {
dkato 0:f782d9c66c49 169 platform_enter_critical();
dkato 0:f782d9c66c49 170 ns_list_add_to_start(&free_event_entry, free);
dkato 0:f782d9c66c49 171 platform_exit_critical();
dkato 0:f782d9c66c49 172 }
dkato 0:f782d9c66c49 173
dkato 0:f782d9c66c49 174
dkato 0:f782d9c66c49 175 static arm_core_event_s *event_core_read(void)
dkato 0:f782d9c66c49 176 {
dkato 0:f782d9c66c49 177 arm_core_event_s *event;
dkato 0:f782d9c66c49 178 platform_enter_critical();
dkato 0:f782d9c66c49 179 event = ns_list_get_first(&event_queue_active);
dkato 0:f782d9c66c49 180 if (event) {
dkato 0:f782d9c66c49 181 ns_list_remove(&event_queue_active, event);
dkato 0:f782d9c66c49 182 }
dkato 0:f782d9c66c49 183 platform_exit_critical();
dkato 0:f782d9c66c49 184 return event;
dkato 0:f782d9c66c49 185 }
dkato 0:f782d9c66c49 186
dkato 0:f782d9c66c49 187 void event_core_write(arm_core_event_s *event)
dkato 0:f782d9c66c49 188 {
dkato 0:f782d9c66c49 189 platform_enter_critical();
dkato 0:f782d9c66c49 190 bool added = false;
dkato 0:f782d9c66c49 191 ns_list_foreach(arm_core_event_s, event_tmp, &event_queue_active) {
dkato 0:f782d9c66c49 192 // note enum ordering means we're checking if event_tmp is LOWER priority than event
dkato 0:f782d9c66c49 193 if (event_tmp->data.priority > event->data.priority) {
dkato 0:f782d9c66c49 194 ns_list_add_before(&event_queue_active, event_tmp, event);
dkato 0:f782d9c66c49 195 added = true;
dkato 0:f782d9c66c49 196 break;
dkato 0:f782d9c66c49 197 }
dkato 0:f782d9c66c49 198 }
dkato 0:f782d9c66c49 199 if (!added) {
dkato 0:f782d9c66c49 200 ns_list_add_to_end(&event_queue_active, event);
dkato 0:f782d9c66c49 201 }
dkato 0:f782d9c66c49 202
dkato 0:f782d9c66c49 203 /* Wake From Idle */
dkato 0:f782d9c66c49 204 platform_exit_critical();
dkato 0:f782d9c66c49 205 eventOS_scheduler_signal();
dkato 0:f782d9c66c49 206 }
dkato 0:f782d9c66c49 207
dkato 0:f782d9c66c49 208 /**
dkato 0:f782d9c66c49 209 *
dkato 0:f782d9c66c49 210 * \brief Initialize Nanostack Core.
dkato 0:f782d9c66c49 211 *
dkato 0:f782d9c66c49 212 * Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined.
dkato 0:f782d9c66c49 213 *
dkato 0:f782d9c66c49 214 */
dkato 0:f782d9c66c49 215 void eventOS_scheduler_init(void)
dkato 0:f782d9c66c49 216 {
dkato 0:f782d9c66c49 217 /* Reset Event List variables */
dkato 0:f782d9c66c49 218 ns_list_init(&free_event_entry);
dkato 0:f782d9c66c49 219 ns_list_init(&event_queue_active);
dkato 0:f782d9c66c49 220 ns_list_init(&arm_core_tasklet_list);
dkato 0:f782d9c66c49 221
dkato 0:f782d9c66c49 222 //Allocate 10 entry
dkato 0:f782d9c66c49 223 for (uint8_t i = 0; i < 10; i++) {
dkato 0:f782d9c66c49 224 arm_core_event_s *event = event_dynamically_allocate();
dkato 0:f782d9c66c49 225 if (event) {
dkato 0:f782d9c66c49 226 ns_list_add_to_start(&free_event_entry, event);
dkato 0:f782d9c66c49 227 }
dkato 0:f782d9c66c49 228 }
dkato 0:f782d9c66c49 229
dkato 0:f782d9c66c49 230 /* Init Generic timer module */
dkato 0:f782d9c66c49 231 timer_sys_init(); //initialize timer
dkato 0:f782d9c66c49 232 /* Set Tasklett switcher to Idle */
dkato 0:f782d9c66c49 233 curr_tasklet = 0;
dkato 0:f782d9c66c49 234
dkato 0:f782d9c66c49 235 }
dkato 0:f782d9c66c49 236
dkato 0:f782d9c66c49 237
dkato 0:f782d9c66c49 238 int8_t eventOS_scheduler_get_active_tasklet(void)
dkato 0:f782d9c66c49 239 {
dkato 0:f782d9c66c49 240 return curr_tasklet;
dkato 0:f782d9c66c49 241 }
dkato 0:f782d9c66c49 242
dkato 0:f782d9c66c49 243 void eventOS_scheduler_set_active_tasklet(int8_t tasklet)
dkato 0:f782d9c66c49 244 {
dkato 0:f782d9c66c49 245 curr_tasklet = tasklet;
dkato 0:f782d9c66c49 246 }
dkato 0:f782d9c66c49 247
dkato 0:f782d9c66c49 248 int eventOS_scheduler_timer_stop(void)
dkato 0:f782d9c66c49 249 {
dkato 0:f782d9c66c49 250 timer_sys_disable();
dkato 0:f782d9c66c49 251 if (ns_timer_sleep() != 0) {
dkato 0:f782d9c66c49 252 return 1;
dkato 0:f782d9c66c49 253 }
dkato 0:f782d9c66c49 254 return 0;
dkato 0:f782d9c66c49 255 }
dkato 0:f782d9c66c49 256
dkato 0:f782d9c66c49 257 int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks)
dkato 0:f782d9c66c49 258 {
dkato 0:f782d9c66c49 259 //Update MS to 10ms ticks
dkato 0:f782d9c66c49 260 sleep_ticks /= 10;
dkato 0:f782d9c66c49 261 sleep_ticks++;
dkato 0:f782d9c66c49 262 system_timer_tick_update(sleep_ticks);
dkato 0:f782d9c66c49 263 if (timer_sys_wakeup() == 0) {
dkato 0:f782d9c66c49 264 return 0;
dkato 0:f782d9c66c49 265 }
dkato 0:f782d9c66c49 266 return -1;
dkato 0:f782d9c66c49 267 }
dkato 0:f782d9c66c49 268
dkato 0:f782d9c66c49 269 /**
dkato 0:f782d9c66c49 270 *
dkato 0:f782d9c66c49 271 * \brief Infinite Event Read Loop.
dkato 0:f782d9c66c49 272 *
dkato 0:f782d9c66c49 273 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
dkato 0:f782d9c66c49 274 *
dkato 0:f782d9c66c49 275 */
dkato 0:f782d9c66c49 276 bool eventOS_scheduler_dispatch_event(void)
dkato 0:f782d9c66c49 277 {
dkato 0:f782d9c66c49 278 arm_core_tasklet_list_s *tasklet;
dkato 0:f782d9c66c49 279 arm_core_event_s *cur_event;
dkato 0:f782d9c66c49 280 arm_event_s event;
dkato 0:f782d9c66c49 281
dkato 0:f782d9c66c49 282 curr_tasklet = 0;
dkato 0:f782d9c66c49 283
dkato 0:f782d9c66c49 284 cur_event = event_core_read();
dkato 0:f782d9c66c49 285 if (cur_event) {
dkato 0:f782d9c66c49 286 event = cur_event->data;
dkato 0:f782d9c66c49 287 event_core_free_push(cur_event);
dkato 0:f782d9c66c49 288 tasklet = event_tasklet_handler_get(event.receiver);
dkato 0:f782d9c66c49 289 if (tasklet) {
dkato 0:f782d9c66c49 290 curr_tasklet = event.receiver;
dkato 0:f782d9c66c49 291 /* Tasklet Scheduler Call */
dkato 0:f782d9c66c49 292 tasklet->func_ptr(&event);
dkato 0:f782d9c66c49 293 /* Set Current Tasklet to Idle state */
dkato 0:f782d9c66c49 294 curr_tasklet = 0;
dkato 0:f782d9c66c49 295 }
dkato 0:f782d9c66c49 296 return true;
dkato 0:f782d9c66c49 297 } else {
dkato 0:f782d9c66c49 298 return false;
dkato 0:f782d9c66c49 299 }
dkato 0:f782d9c66c49 300 }
dkato 0:f782d9c66c49 301
dkato 0:f782d9c66c49 302 void eventOS_scheduler_run_until_idle(void)
dkato 0:f782d9c66c49 303 {
dkato 0:f782d9c66c49 304 while (eventOS_scheduler_dispatch_event());
dkato 0:f782d9c66c49 305 }
dkato 0:f782d9c66c49 306
dkato 0:f782d9c66c49 307 /**
dkato 0:f782d9c66c49 308 *
dkato 0:f782d9c66c49 309 * \brief Infinite Event Read Loop.
dkato 0:f782d9c66c49 310 *
dkato 0:f782d9c66c49 311 * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
dkato 0:f782d9c66c49 312 *
dkato 0:f782d9c66c49 313 */
dkato 0:f782d9c66c49 314 NS_NORETURN void eventOS_scheduler_run(void)
dkato 0:f782d9c66c49 315 {
dkato 0:f782d9c66c49 316 while (1) {
dkato 0:f782d9c66c49 317 if (!eventOS_scheduler_dispatch_event()) {
dkato 0:f782d9c66c49 318 eventOS_scheduler_idle();
dkato 0:f782d9c66c49 319 }
dkato 0:f782d9c66c49 320 }
dkato 0:f782d9c66c49 321 }