takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /*
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
kadonotakashi 0:8fdf9a60065b 3 * SPDX-License-Identifier: Apache-2.0
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the License); you may
kadonotakashi 0:8fdf9a60065b 5 * not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
kadonotakashi 0:8fdf9a60065b 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16
kadonotakashi 0:8fdf9a60065b 17 #include "ns_types.h"
kadonotakashi 0:8fdf9a60065b 18 #include "ns_list.h"
kadonotakashi 0:8fdf9a60065b 19 #include "ns_timer.h"
kadonotakashi 0:8fdf9a60065b 20 #include "eventOS_callback_timer.h"
kadonotakashi 0:8fdf9a60065b 21 #include "platform/arm_hal_interrupt.h"
kadonotakashi 0:8fdf9a60065b 22 #include "platform/arm_hal_timer.h"
kadonotakashi 0:8fdf9a60065b 23 #include "nsdynmemLIB.h"
kadonotakashi 0:8fdf9a60065b 24
kadonotakashi 0:8fdf9a60065b 25 #ifndef NS_EXCLUDE_HIGHRES_TIMER
kadonotakashi 0:8fdf9a60065b 26 typedef enum ns_timer_state_e {
kadonotakashi 0:8fdf9a60065b 27 NS_TIMER_ACTIVE = 0, // Will run on the next HAL interrupt
kadonotakashi 0:8fdf9a60065b 28 NS_TIMER_HOLD, // Will run on a later HAL interrupt
kadonotakashi 0:8fdf9a60065b 29 NS_TIMER_RUN_INTERRUPT, // Running on the interrupt we're currently handling
kadonotakashi 0:8fdf9a60065b 30 NS_TIMER_STOP // Timer not scheduled ("start" not called since last callback)
kadonotakashi 0:8fdf9a60065b 31 } ns_timer_state_e;
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 typedef struct ns_timer_struct {
kadonotakashi 0:8fdf9a60065b 34 int8_t ns_timer_id;
kadonotakashi 0:8fdf9a60065b 35 ns_timer_state_e timer_state;
kadonotakashi 0:8fdf9a60065b 36 uint16_t slots;
kadonotakashi 0:8fdf9a60065b 37 uint16_t remaining_slots;
kadonotakashi 0:8fdf9a60065b 38 void (*interrupt_handler)(int8_t, uint16_t);
kadonotakashi 0:8fdf9a60065b 39 ns_list_link_t link;
kadonotakashi 0:8fdf9a60065b 40 } ns_timer_struct;
kadonotakashi 0:8fdf9a60065b 41
kadonotakashi 0:8fdf9a60065b 42 static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link);
kadonotakashi 0:8fdf9a60065b 43
kadonotakashi 0:8fdf9a60065b 44 #define NS_TIMER_RUNNING 1
kadonotakashi 0:8fdf9a60065b 45 static uint8_t ns_timer_state = 0;
kadonotakashi 0:8fdf9a60065b 46
kadonotakashi 0:8fdf9a60065b 47 #ifdef ATMEGA256RFR2
kadonotakashi 0:8fdf9a60065b 48 #define COMPENSATION 3
kadonotakashi 0:8fdf9a60065b 49 #define COMPENSATION_TUNE 1
kadonotakashi 0:8fdf9a60065b 50 #else
kadonotakashi 0:8fdf9a60065b 51 #define COMPENSATION 0
kadonotakashi 0:8fdf9a60065b 52 #define COMPENSATION_TUNE 0
kadonotakashi 0:8fdf9a60065b 53 #endif
kadonotakashi 0:8fdf9a60065b 54
kadonotakashi 0:8fdf9a60065b 55 static void ns_timer_interrupt_handler(void);
kadonotakashi 0:8fdf9a60065b 56 static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id);
kadonotakashi 0:8fdf9a60065b 57 static bool ns_timer_initialized = 0;
kadonotakashi 0:8fdf9a60065b 58
kadonotakashi 0:8fdf9a60065b 59 int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t))
kadonotakashi 0:8fdf9a60065b 60 {
kadonotakashi 0:8fdf9a60065b 61 int8_t retval = -1;
kadonotakashi 0:8fdf9a60065b 62
kadonotakashi 0:8fdf9a60065b 63 if (!ns_timer_initialized) {
kadonotakashi 0:8fdf9a60065b 64 /*Set interrupt handler in HAL driver*/
kadonotakashi 0:8fdf9a60065b 65 platform_timer_set_cb(ns_timer_interrupt_handler);
kadonotakashi 0:8fdf9a60065b 66 ns_timer_initialized = 1;
kadonotakashi 0:8fdf9a60065b 67 }
kadonotakashi 0:8fdf9a60065b 68
kadonotakashi 0:8fdf9a60065b 69 /*Find first free timer ID in timer list*/
kadonotakashi 0:8fdf9a60065b 70 /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
kadonotakashi 0:8fdf9a60065b 71 for (uint8_t i = 0; i <= INT8_MAX; i++) {
kadonotakashi 0:8fdf9a60065b 72 if (!ns_timer_get_pointer_to_timer_struct(i)) {
kadonotakashi 0:8fdf9a60065b 73 retval = i;
kadonotakashi 0:8fdf9a60065b 74 break;
kadonotakashi 0:8fdf9a60065b 75 }
kadonotakashi 0:8fdf9a60065b 76 }
kadonotakashi 0:8fdf9a60065b 77
kadonotakashi 0:8fdf9a60065b 78 if (retval == -1) {
kadonotakashi 0:8fdf9a60065b 79 return -1;
kadonotakashi 0:8fdf9a60065b 80 }
kadonotakashi 0:8fdf9a60065b 81
kadonotakashi 0:8fdf9a60065b 82 ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct));
kadonotakashi 0:8fdf9a60065b 83 if (!new_timer) {
kadonotakashi 0:8fdf9a60065b 84 return -1;
kadonotakashi 0:8fdf9a60065b 85 }
kadonotakashi 0:8fdf9a60065b 86
kadonotakashi 0:8fdf9a60065b 87 /*Initialise new timer*/
kadonotakashi 0:8fdf9a60065b 88 new_timer->ns_timer_id = retval;
kadonotakashi 0:8fdf9a60065b 89 new_timer->timer_state = NS_TIMER_STOP;
kadonotakashi 0:8fdf9a60065b 90 new_timer->remaining_slots = 0;
kadonotakashi 0:8fdf9a60065b 91 new_timer->interrupt_handler = timer_interrupt_handler;
kadonotakashi 0:8fdf9a60065b 92
kadonotakashi 0:8fdf9a60065b 93 // Critical section sufficient as long as list can't be reordered from
kadonotakashi 0:8fdf9a60065b 94 // interrupt, otherwise will need to cover whole routine
kadonotakashi 0:8fdf9a60065b 95 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 96 ns_list_add_to_end(&ns_timer_list, new_timer);
kadonotakashi 0:8fdf9a60065b 97 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 98
kadonotakashi 0:8fdf9a60065b 99 /*Return timer ID*/
kadonotakashi 0:8fdf9a60065b 100 return retval;
kadonotakashi 0:8fdf9a60065b 101 }
kadonotakashi 0:8fdf9a60065b 102
kadonotakashi 0:8fdf9a60065b 103 int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id)
kadonotakashi 0:8fdf9a60065b 104 {
kadonotakashi 0:8fdf9a60065b 105 ns_timer_struct *current_timer;
kadonotakashi 0:8fdf9a60065b 106
kadonotakashi 0:8fdf9a60065b 107 current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
kadonotakashi 0:8fdf9a60065b 108 if (!current_timer) {
kadonotakashi 0:8fdf9a60065b 109 return -1;
kadonotakashi 0:8fdf9a60065b 110 }
kadonotakashi 0:8fdf9a60065b 111
kadonotakashi 0:8fdf9a60065b 112 // Critical section sufficient as long as list can't be reordered from
kadonotakashi 0:8fdf9a60065b 113 // interrupt, otherwise will need to cover whole routine
kadonotakashi 0:8fdf9a60065b 114 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 115 ns_list_remove(&ns_timer_list, current_timer);
kadonotakashi 0:8fdf9a60065b 116 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 117
kadonotakashi 0:8fdf9a60065b 118 ns_dyn_mem_free(current_timer);
kadonotakashi 0:8fdf9a60065b 119 return 0;
kadonotakashi 0:8fdf9a60065b 120 }
kadonotakashi 0:8fdf9a60065b 121
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots)
kadonotakashi 0:8fdf9a60065b 124 {
kadonotakashi 0:8fdf9a60065b 125 /*Don't start timer with 0 slots*/
kadonotakashi 0:8fdf9a60065b 126 if (!pl_timer_start_slots) {
kadonotakashi 0:8fdf9a60065b 127 pl_timer_start_slots = 1;
kadonotakashi 0:8fdf9a60065b 128 }
kadonotakashi 0:8fdf9a60065b 129
kadonotakashi 0:8fdf9a60065b 130 /*Start HAL timer*/
kadonotakashi 0:8fdf9a60065b 131 platform_timer_start(pl_timer_start_slots);
kadonotakashi 0:8fdf9a60065b 132 /*Set HAL timer state to running*/
kadonotakashi 0:8fdf9a60065b 133 ns_timer_state |= NS_TIMER_RUNNING;
kadonotakashi 0:8fdf9a60065b 134 return 0;
kadonotakashi 0:8fdf9a60065b 135 }
kadonotakashi 0:8fdf9a60065b 136
kadonotakashi 0:8fdf9a60065b 137 int8_t ns_timer_sleep(void)
kadonotakashi 0:8fdf9a60065b 138 {
kadonotakashi 0:8fdf9a60065b 139 int8_t ret_val = -1;
kadonotakashi 0:8fdf9a60065b 140 if (ns_timer_state & NS_TIMER_RUNNING) {
kadonotakashi 0:8fdf9a60065b 141 /*Start HAL timer*/
kadonotakashi 0:8fdf9a60065b 142 platform_timer_disable();
kadonotakashi 0:8fdf9a60065b 143 /*Set HAL timer state to running*/
kadonotakashi 0:8fdf9a60065b 144 ns_timer_state &= ~NS_TIMER_RUNNING;
kadonotakashi 0:8fdf9a60065b 145 ret_val = 0;
kadonotakashi 0:8fdf9a60065b 146 }
kadonotakashi 0:8fdf9a60065b 147 return ret_val;
kadonotakashi 0:8fdf9a60065b 148 }
kadonotakashi 0:8fdf9a60065b 149
kadonotakashi 0:8fdf9a60065b 150 static int8_t ns_timer_get_next_running_to(void)
kadonotakashi 0:8fdf9a60065b 151 {
kadonotakashi 0:8fdf9a60065b 152 uint8_t hold_count = 0;
kadonotakashi 0:8fdf9a60065b 153 ns_timer_struct *first_timer = NULL;
kadonotakashi 0:8fdf9a60065b 154
kadonotakashi 0:8fdf9a60065b 155 /*Find hold-labelled timer with the least remaining slots*/
kadonotakashi 0:8fdf9a60065b 156 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 157 if (current_timer->timer_state == NS_TIMER_HOLD) {
kadonotakashi 0:8fdf9a60065b 158 if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) {
kadonotakashi 0:8fdf9a60065b 159 first_timer = current_timer;
kadonotakashi 0:8fdf9a60065b 160 }
kadonotakashi 0:8fdf9a60065b 161 /*For optimisation, count the found timers*/
kadonotakashi 0:8fdf9a60065b 162 hold_count++;
kadonotakashi 0:8fdf9a60065b 163 }
kadonotakashi 0:8fdf9a60065b 164 }
kadonotakashi 0:8fdf9a60065b 165
kadonotakashi 0:8fdf9a60065b 166 if (!first_timer) {
kadonotakashi 0:8fdf9a60065b 167 return 0;
kadonotakashi 0:8fdf9a60065b 168 }
kadonotakashi 0:8fdf9a60065b 169
kadonotakashi 0:8fdf9a60065b 170 /*If hold-labelled timer found, set it active and start the HAL driver*/
kadonotakashi 0:8fdf9a60065b 171 hold_count--;
kadonotakashi 0:8fdf9a60065b 172 first_timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 173 /*Compensate time spent in timer function*/
kadonotakashi 0:8fdf9a60065b 174 if (first_timer->remaining_slots > COMPENSATION) {
kadonotakashi 0:8fdf9a60065b 175 first_timer->remaining_slots -= COMPENSATION;
kadonotakashi 0:8fdf9a60065b 176 }
kadonotakashi 0:8fdf9a60065b 177 /*Start HAL timer*/
kadonotakashi 0:8fdf9a60065b 178 ns_timer_start_pl_timer(first_timer->remaining_slots);
kadonotakashi 0:8fdf9a60065b 179
kadonotakashi 0:8fdf9a60065b 180 /*Update other hold-labelled timers*/
kadonotakashi 0:8fdf9a60065b 181 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 182 if (hold_count == 0) { // early termination optimisation
kadonotakashi 0:8fdf9a60065b 183 break;
kadonotakashi 0:8fdf9a60065b 184 }
kadonotakashi 0:8fdf9a60065b 185 if (current_timer->timer_state == NS_TIMER_HOLD) {
kadonotakashi 0:8fdf9a60065b 186 if (current_timer->remaining_slots == first_timer->remaining_slots) {
kadonotakashi 0:8fdf9a60065b 187 current_timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 188 } else {
kadonotakashi 0:8fdf9a60065b 189 current_timer->remaining_slots -= first_timer->remaining_slots;
kadonotakashi 0:8fdf9a60065b 190 /*Compensate time spent in timer function*/
kadonotakashi 0:8fdf9a60065b 191 if (current_timer->remaining_slots > COMPENSATION) {
kadonotakashi 0:8fdf9a60065b 192 current_timer->remaining_slots -= COMPENSATION;
kadonotakashi 0:8fdf9a60065b 193 }
kadonotakashi 0:8fdf9a60065b 194 }
kadonotakashi 0:8fdf9a60065b 195 hold_count--;
kadonotakashi 0:8fdf9a60065b 196 }
kadonotakashi 0:8fdf9a60065b 197 }
kadonotakashi 0:8fdf9a60065b 198
kadonotakashi 0:8fdf9a60065b 199 return 0;
kadonotakashi 0:8fdf9a60065b 200 }
kadonotakashi 0:8fdf9a60065b 201
kadonotakashi 0:8fdf9a60065b 202
kadonotakashi 0:8fdf9a60065b 203 static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id)
kadonotakashi 0:8fdf9a60065b 204 {
kadonotakashi 0:8fdf9a60065b 205 /*Find timer with the given ID*/
kadonotakashi 0:8fdf9a60065b 206 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 207 if (current_timer->ns_timer_id == timer_id) {
kadonotakashi 0:8fdf9a60065b 208 return current_timer;
kadonotakashi 0:8fdf9a60065b 209 }
kadonotakashi 0:8fdf9a60065b 210 }
kadonotakashi 0:8fdf9a60065b 211 return NULL;
kadonotakashi 0:8fdf9a60065b 212 }
kadonotakashi 0:8fdf9a60065b 213
kadonotakashi 0:8fdf9a60065b 214 int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots)
kadonotakashi 0:8fdf9a60065b 215 {
kadonotakashi 0:8fdf9a60065b 216 int8_t ret_val = 0;
kadonotakashi 0:8fdf9a60065b 217 uint16_t pl_timer_remaining_slots;
kadonotakashi 0:8fdf9a60065b 218 ns_timer_struct *timer;
kadonotakashi 0:8fdf9a60065b 219 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 220
kadonotakashi 0:8fdf9a60065b 221 /*Find timer to be activated*/
kadonotakashi 0:8fdf9a60065b 222 timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
kadonotakashi 0:8fdf9a60065b 223 if (!timer) {
kadonotakashi 0:8fdf9a60065b 224 ret_val = -1;
kadonotakashi 0:8fdf9a60065b 225 goto exit;
kadonotakashi 0:8fdf9a60065b 226 }
kadonotakashi 0:8fdf9a60065b 227
kadonotakashi 0:8fdf9a60065b 228 // XXX this assumes the timer currently isn't running?
kadonotakashi 0:8fdf9a60065b 229 // Is event.c relying on this restarting HAL timer after ns_timer_sleep()?
kadonotakashi 0:8fdf9a60065b 230
kadonotakashi 0:8fdf9a60065b 231 /*If any timers are active*/
kadonotakashi 0:8fdf9a60065b 232 if (ns_timer_state & NS_TIMER_RUNNING) {
kadonotakashi 0:8fdf9a60065b 233 /*Get remaining slots of the currently activated timeout*/
kadonotakashi 0:8fdf9a60065b 234 pl_timer_remaining_slots = platform_timer_get_remaining_slots();
kadonotakashi 0:8fdf9a60065b 235
kadonotakashi 0:8fdf9a60065b 236 /*New timeout is shorter than currently enabled timeout*/
kadonotakashi 0:8fdf9a60065b 237 if (pl_timer_remaining_slots > slots) {
kadonotakashi 0:8fdf9a60065b 238 /*Start HAL timer*/
kadonotakashi 0:8fdf9a60065b 239 ns_timer_start_pl_timer(slots - 0);
kadonotakashi 0:8fdf9a60065b 240
kadonotakashi 0:8fdf9a60065b 241 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 242 /*Switch active timers to hold*/
kadonotakashi 0:8fdf9a60065b 243 if (current_timer->timer_state == NS_TIMER_ACTIVE) {
kadonotakashi 0:8fdf9a60065b 244 current_timer->timer_state = NS_TIMER_HOLD;
kadonotakashi 0:8fdf9a60065b 245 current_timer->remaining_slots = 0;
kadonotakashi 0:8fdf9a60065b 246 }
kadonotakashi 0:8fdf9a60065b 247 /*Update hold-labelled timers*/
kadonotakashi 0:8fdf9a60065b 248 if (current_timer->timer_state == NS_TIMER_HOLD) {
kadonotakashi 0:8fdf9a60065b 249 current_timer->remaining_slots += (pl_timer_remaining_slots - slots);
kadonotakashi 0:8fdf9a60065b 250 /*Compensate time spent in timer function*/
kadonotakashi 0:8fdf9a60065b 251 if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) {
kadonotakashi 0:8fdf9a60065b 252 current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE);
kadonotakashi 0:8fdf9a60065b 253 }
kadonotakashi 0:8fdf9a60065b 254 }
kadonotakashi 0:8fdf9a60065b 255 }
kadonotakashi 0:8fdf9a60065b 256 /*Mark active and start the timer*/
kadonotakashi 0:8fdf9a60065b 257 timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 258 timer->slots = slots;
kadonotakashi 0:8fdf9a60065b 259 timer->remaining_slots = slots;
kadonotakashi 0:8fdf9a60065b 260 }
kadonotakashi 0:8fdf9a60065b 261
kadonotakashi 0:8fdf9a60065b 262 /*New timeout is longer than currently enabled timeout*/
kadonotakashi 0:8fdf9a60065b 263 else if (pl_timer_remaining_slots < slots) {
kadonotakashi 0:8fdf9a60065b 264 /*Mark hold and update remaining slots*/
kadonotakashi 0:8fdf9a60065b 265 timer->timer_state = NS_TIMER_HOLD;
kadonotakashi 0:8fdf9a60065b 266 timer->slots = slots;
kadonotakashi 0:8fdf9a60065b 267 timer->remaining_slots = (slots - pl_timer_remaining_slots);
kadonotakashi 0:8fdf9a60065b 268 }
kadonotakashi 0:8fdf9a60065b 269 /*New timeout is equal to currently enabled timeout*/
kadonotakashi 0:8fdf9a60065b 270 else {
kadonotakashi 0:8fdf9a60065b 271 /*Mark it active and it will be handled in next interrupt*/
kadonotakashi 0:8fdf9a60065b 272 timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 273 timer->slots = slots;
kadonotakashi 0:8fdf9a60065b 274 timer->remaining_slots = slots;
kadonotakashi 0:8fdf9a60065b 275 }
kadonotakashi 0:8fdf9a60065b 276 } else {
kadonotakashi 0:8fdf9a60065b 277 /*No timers running*/
kadonotakashi 0:8fdf9a60065b 278 timer->timer_state = NS_TIMER_HOLD;
kadonotakashi 0:8fdf9a60065b 279 timer->slots = slots;
kadonotakashi 0:8fdf9a60065b 280 timer->remaining_slots = slots;
kadonotakashi 0:8fdf9a60065b 281 /*Start next timeout*/
kadonotakashi 0:8fdf9a60065b 282 ns_timer_get_next_running_to();
kadonotakashi 0:8fdf9a60065b 283 }
kadonotakashi 0:8fdf9a60065b 284 exit:
kadonotakashi 0:8fdf9a60065b 285 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 286 return ret_val;
kadonotakashi 0:8fdf9a60065b 287 }
kadonotakashi 0:8fdf9a60065b 288
kadonotakashi 0:8fdf9a60065b 289 static void ns_timer_interrupt_handler(void)
kadonotakashi 0:8fdf9a60065b 290 {
kadonotakashi 0:8fdf9a60065b 291 uint8_t i = 0;
kadonotakashi 0:8fdf9a60065b 292
kadonotakashi 0:8fdf9a60065b 293 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 294 /*Clear timer running state*/
kadonotakashi 0:8fdf9a60065b 295 ns_timer_state &= ~NS_TIMER_RUNNING;
kadonotakashi 0:8fdf9a60065b 296 /*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/
kadonotakashi 0:8fdf9a60065b 297 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 298 if (current_timer->timer_state == NS_TIMER_ACTIVE) {
kadonotakashi 0:8fdf9a60065b 299 current_timer->timer_state = NS_TIMER_RUN_INTERRUPT;
kadonotakashi 0:8fdf9a60065b 300 /*For optimisation, count the found timers*/
kadonotakashi 0:8fdf9a60065b 301 i++;
kadonotakashi 0:8fdf9a60065b 302 }
kadonotakashi 0:8fdf9a60065b 303 }
kadonotakashi 0:8fdf9a60065b 304
kadonotakashi 0:8fdf9a60065b 305 /*Start next timeout*/
kadonotakashi 0:8fdf9a60065b 306 ns_timer_get_next_running_to();
kadonotakashi 0:8fdf9a60065b 307
kadonotakashi 0:8fdf9a60065b 308 /*Call interrupt functions*/
kadonotakashi 0:8fdf9a60065b 309 ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 310 if (i == 0) {
kadonotakashi 0:8fdf9a60065b 311 break;
kadonotakashi 0:8fdf9a60065b 312 }
kadonotakashi 0:8fdf9a60065b 313 if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) {
kadonotakashi 0:8fdf9a60065b 314 current_timer->timer_state = NS_TIMER_STOP;
kadonotakashi 0:8fdf9a60065b 315 current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots);
kadonotakashi 0:8fdf9a60065b 316 i--;
kadonotakashi 0:8fdf9a60065b 317 }
kadonotakashi 0:8fdf9a60065b 318 }
kadonotakashi 0:8fdf9a60065b 319
kadonotakashi 0:8fdf9a60065b 320 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 321 }
kadonotakashi 0:8fdf9a60065b 322
kadonotakashi 0:8fdf9a60065b 323 int8_t eventOS_callback_timer_stop(int8_t ns_timer_id)
kadonotakashi 0:8fdf9a60065b 324 {
kadonotakashi 0:8fdf9a60065b 325 uint16_t pl_timer_remaining_slots;
kadonotakashi 0:8fdf9a60065b 326 bool active_timer_found = false;
kadonotakashi 0:8fdf9a60065b 327 ns_timer_struct *current_timer;
kadonotakashi 0:8fdf9a60065b 328 ns_timer_struct *first_timer = NULL;
kadonotakashi 0:8fdf9a60065b 329 int8_t retval = -1;
kadonotakashi 0:8fdf9a60065b 330
kadonotakashi 0:8fdf9a60065b 331 platform_enter_critical();
kadonotakashi 0:8fdf9a60065b 332 /*Find timer with given timer ID*/
kadonotakashi 0:8fdf9a60065b 333 current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
kadonotakashi 0:8fdf9a60065b 334 if (!current_timer) {
kadonotakashi 0:8fdf9a60065b 335 goto exit;
kadonotakashi 0:8fdf9a60065b 336 }
kadonotakashi 0:8fdf9a60065b 337
kadonotakashi 0:8fdf9a60065b 338 retval = 0;
kadonotakashi 0:8fdf9a60065b 339
kadonotakashi 0:8fdf9a60065b 340 /*Check if already stopped*/
kadonotakashi 0:8fdf9a60065b 341 if (current_timer->timer_state == NS_TIMER_STOP) {
kadonotakashi 0:8fdf9a60065b 342 goto exit;
kadonotakashi 0:8fdf9a60065b 343 }
kadonotakashi 0:8fdf9a60065b 344
kadonotakashi 0:8fdf9a60065b 345 current_timer->timer_state = NS_TIMER_STOP;
kadonotakashi 0:8fdf9a60065b 346 current_timer->remaining_slots = 0;
kadonotakashi 0:8fdf9a60065b 347
kadonotakashi 0:8fdf9a60065b 348 /*Check if some timer is already active*/
kadonotakashi 0:8fdf9a60065b 349 ns_list_foreach(ns_timer_struct, curr_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 350 if (curr_timer->timer_state == NS_TIMER_ACTIVE) {
kadonotakashi 0:8fdf9a60065b 351 active_timer_found = true;
kadonotakashi 0:8fdf9a60065b 352 break;
kadonotakashi 0:8fdf9a60065b 353 }
kadonotakashi 0:8fdf9a60065b 354 }
kadonotakashi 0:8fdf9a60065b 355 /*If no active timers found, start one*/
kadonotakashi 0:8fdf9a60065b 356 if (!active_timer_found) {
kadonotakashi 0:8fdf9a60065b 357 pl_timer_remaining_slots = platform_timer_get_remaining_slots();
kadonotakashi 0:8fdf9a60065b 358 /*Find hold-labelled timer with the least remaining slots*/
kadonotakashi 0:8fdf9a60065b 359 ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 360 if (cur_timer->timer_state == NS_TIMER_HOLD) {
kadonotakashi 0:8fdf9a60065b 361 cur_timer->remaining_slots += pl_timer_remaining_slots;
kadonotakashi 0:8fdf9a60065b 362
kadonotakashi 0:8fdf9a60065b 363 if (!first_timer || cur_timer->remaining_slots < first_timer->remaining_slots) {
kadonotakashi 0:8fdf9a60065b 364 first_timer = cur_timer;
kadonotakashi 0:8fdf9a60065b 365 }
kadonotakashi 0:8fdf9a60065b 366 }
kadonotakashi 0:8fdf9a60065b 367 }
kadonotakashi 0:8fdf9a60065b 368 /*If hold-labelled timer found, set it active and start the HAL driver*/
kadonotakashi 0:8fdf9a60065b 369 if (first_timer) {
kadonotakashi 0:8fdf9a60065b 370 first_timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 371 /*Start HAL timer*/
kadonotakashi 0:8fdf9a60065b 372 ns_timer_start_pl_timer(first_timer->remaining_slots);
kadonotakashi 0:8fdf9a60065b 373 /*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/
kadonotakashi 0:8fdf9a60065b 374 ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) {
kadonotakashi 0:8fdf9a60065b 375 if (cur_timer->timer_state == NS_TIMER_HOLD) {
kadonotakashi 0:8fdf9a60065b 376 if (cur_timer->remaining_slots == first_timer->remaining_slots) {
kadonotakashi 0:8fdf9a60065b 377 cur_timer->timer_state = NS_TIMER_ACTIVE;
kadonotakashi 0:8fdf9a60065b 378 } else {
kadonotakashi 0:8fdf9a60065b 379 cur_timer->remaining_slots -= first_timer->remaining_slots;
kadonotakashi 0:8fdf9a60065b 380 }
kadonotakashi 0:8fdf9a60065b 381 }
kadonotakashi 0:8fdf9a60065b 382 }
kadonotakashi 0:8fdf9a60065b 383 }
kadonotakashi 0:8fdf9a60065b 384 }
kadonotakashi 0:8fdf9a60065b 385
kadonotakashi 0:8fdf9a60065b 386 exit:
kadonotakashi 0:8fdf9a60065b 387 platform_exit_critical();
kadonotakashi 0:8fdf9a60065b 388
kadonotakashi 0:8fdf9a60065b 389 return retval;
kadonotakashi 0:8fdf9a60065b 390 }
kadonotakashi 0:8fdf9a60065b 391 #endif // NS_EXCLUDE_HIGHRES_TIMER