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.c Source File

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