mbed os with nrf51 internal bandgap enabled to read battery level

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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