joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers system_timer.cpp Source File

system_timer.cpp

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 "ns_types.h"
00017 #include "ns_list.h"
00018 #include "timer_sys.h"
00019 #include "platform/arm_hal_interrupt.h"
00020 #include "ns_timer.h"
00021 #include "nsdynmemLIB.h"
00022 #include "eventOS_event.h"
00023 #include "eventOS_event_timer.h"
00024 #include "minar/minar.h"
00025 #include "mbed.h"
00026 #include "core-util/FunctionPointer.h"
00027 #include "core-util/Event.h"
00028 
00029 using minar::Scheduler;
00030 using minar::milliseconds;
00031 using minar::callback_handle_t;
00032 using namespace mbed::util;
00033 
00034 #ifndef ST_MAX
00035 #define ST_MAX 6
00036 #endif
00037 
00038 typedef struct sys_timer_struct_s {
00039     uint32_t timer_sys_launch_time;
00040     int8_t timer_sys_launch_receiver;
00041     uint8_t timer_sys_launch_message;
00042     uint8_t timer_event_type;
00043 
00044     ns_list_link_t link;
00045 } sys_timer_struct_s;
00046 
00047 #define TIMER_SYS_TICK_PERIOD       10 // milliseconds
00048 
00049 static uint32_t run_time_tick_ticks = 0;
00050 static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, link);
00051 static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, link);
00052 static callback_handle_t sys_timer_handle;
00053 
00054 
00055 static sys_timer_struct_s *sys_timer_dynamically_allocate(void);
00056 
00057 
00058 
00059 /*
00060  * Initializes timers and starts system timer
00061  */
00062 void timer_sys_init(void)
00063 {
00064     run_time_tick_ticks = 0;
00065 
00066     // Clear old timers
00067     ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_list) {
00068         ns_list_remove(&system_timer_list, temp);
00069         ns_dyn_mem_free(temp);
00070     }
00071     // Clear old free timer entrys
00072     ns_list_foreach_safe(sys_timer_struct_s, temp, &system_timer_free) {
00073         ns_list_remove(&system_timer_free, temp);
00074         ns_dyn_mem_free(temp);
00075     }
00076 
00077     for (uint8_t i = 0; i < ST_MAX; i++) {
00078         sys_timer_struct_s *temp = sys_timer_dynamically_allocate();
00079         if (temp) {
00080             ns_list_add_to_start(&system_timer_free, temp);
00081         }
00082     }
00083 
00084     Event e = FunctionPointer1<void, uint32_t>(system_timer_tick_update).bind(1);
00085     sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(TIMER_SYS_TICK_PERIOD)).getHandle();
00086 }
00087 
00088 
00089 
00090 /*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/
00091 void timer_sys_disable(void)
00092 {
00093     if (sys_timer_handle != NULL) {
00094         Scheduler::cancelCallback(sys_timer_handle);
00095         sys_timer_handle = NULL;
00096     }
00097 }
00098 
00099 /*
00100  * Starts ticking system timer interrupts every 10ms
00101  */
00102 int8_t timer_sys_wakeup(void)
00103 {
00104     // postCallback should never fail in MINAR
00105     // TODO: check if that's true
00106     if (NULL == sys_timer_handle) {
00107         Event e = FunctionPointer1<void, uint32_t>(system_timer_tick_update).bind(1);
00108         sys_timer_handle = Scheduler::postCallback(e).tolerance(minar::milliseconds(TIMER_SYS_TICK_PERIOD/10)).period(milliseconds(TIMER_SYS_TICK_PERIOD)).getHandle();
00109     }
00110     return 0;
00111 }
00112 
00113 
00114 /* * * * * * * * * */
00115 
00116 static sys_timer_struct_s *sys_timer_dynamically_allocate(void)
00117 {
00118     return (sys_timer_struct_s*)ns_dyn_mem_alloc(sizeof(sys_timer_struct_s));
00119 }
00120 
00121 static sys_timer_struct_s *timer_struct_get(void)
00122 {
00123     sys_timer_struct_s *timer;
00124     platform_enter_critical();
00125     timer = ns_list_get_first(&system_timer_free);
00126     if (timer) {
00127         ns_list_remove(&system_timer_free, timer);
00128     } else {
00129         timer = sys_timer_dynamically_allocate();
00130     }
00131     platform_exit_critical();
00132     return timer;
00133 }
00134 
00135 uint32_t timer_get_runtime_ticks(void)  // only used in dev_stats_internal.c
00136 {
00137     uint32_t ret_val;
00138     platform_enter_critical();
00139     ret_val = run_time_tick_ticks;
00140     platform_exit_critical();
00141     return ret_val;
00142 }
00143 
00144 
00145 
00146 int8_t eventOS_event_timer_request(uint8_t snmessage, uint8_t event_type, int8_t tasklet_id, uint32_t time)
00147 {
00148     int8_t res = -1;
00149     sys_timer_struct_s *timer = NULL;
00150 
00151     platform_enter_critical();
00152     // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks.
00153     // And why shouldn't they be able to get a 1-tick callback?
00154     if (time > 2 * TIMER_SYS_TICK_PERIOD) {
00155         time /= TIMER_SYS_TICK_PERIOD;
00156         // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe?
00157         time++;
00158     } else {
00159         time = 2;
00160     }
00161     timer = timer_struct_get();
00162     if (timer) {
00163         timer->timer_sys_launch_message = snmessage;
00164         timer->timer_sys_launch_receiver = tasklet_id;
00165         timer->timer_event_type = event_type;
00166         timer->timer_sys_launch_time = time;
00167         ns_list_add_to_start(&system_timer_list, timer);
00168         res = 0;
00169     }
00170     platform_exit_critical();
00171     return res;
00172 }
00173 
00174 int8_t eventOS_event_timer_cancel(uint8_t snmessage, int8_t tasklet_id)
00175 {
00176     int8_t res = -1;
00177     platform_enter_critical();
00178     ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) {
00179         if (cur->timer_sys_launch_receiver == tasklet_id && cur->timer_sys_launch_message == snmessage) {
00180             ns_list_remove(&system_timer_list, cur);
00181             ns_list_add_to_start(&system_timer_free, cur);
00182             res = 0;
00183             break;
00184         }
00185     }
00186 
00187     platform_exit_critical();
00188     return res;
00189 }
00190 
00191 
00192 uint32_t eventOS_event_timer_shortest_active_timer(void)
00193 {
00194     uint32_t ret_val = 0;
00195 
00196     platform_enter_critical();
00197     ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) {
00198         if (ret_val == 0 || cur->timer_sys_launch_time < ret_val) {
00199             ret_val = cur->timer_sys_launch_time;
00200         }
00201     }
00202 
00203     platform_exit_critical();
00204     //Convert ticks to ms
00205     ret_val *= TIMER_SYS_TICK_PERIOD;
00206     return ret_val;
00207 }
00208 
00209 void system_timer_tick_update(uint32_t ticks)
00210 {
00211     platform_enter_critical();
00212     //Keep runtime time
00213     run_time_tick_ticks += ticks;
00214     ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) {
00215         if (cur->timer_sys_launch_time <= ticks) {
00216             arm_event_s event;
00217             event.receiver = cur->timer_sys_launch_receiver;
00218             event.sender = 0; /**< Event sender Tasklet ID */
00219             event.data_ptr = NULL;
00220             event.event_type = cur->timer_event_type;
00221             event.event_id = cur->timer_sys_launch_message;
00222             event.event_data = 0;
00223             event.priority = ARM_LIB_MED_PRIORITY_EVENT;
00224             eventOS_event_send(&event);
00225             ns_list_remove(&system_timer_list, cur);
00226             ns_list_add_to_start(&system_timer_free, cur);
00227         } else {
00228             cur->timer_sys_launch_time -= ticks;
00229         }
00230     }
00231 
00232     platform_exit_critical();
00233 }
00234