Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers arm_hal_timer.cpp Source File

arm_hal_timer.cpp

00001 /*
00002  * Copyright (c) 2016 ARM Limited, All Rights Reserved
00003  */
00004 
00005 // Include before mbed.h to properly get UINT*_C()
00006 #include "ns_types.h"
00007 
00008 #include "mbed.h"
00009 #include "platform/SingletonPtr.h"
00010 #include "platform/arm_hal_timer.h"
00011 #include "platform/arm_hal_interrupt.h"
00012 #include <mbed_assert.h>
00013 
00014 static SingletonPtr<Timer> timer;
00015 static SingletonPtr<Timeout> timeout;
00016 
00017 // If critical sections are implemented using mutexes, timers must be called in thread context, and
00018 // we use the high-priority event queue for this.
00019 // If critical sections disable interrupts, we can call timers directly from interrupt. Avoiding the
00020 // event queue can save ~1600B of RAM if the rest of the system is not using the event queue either.
00021 // Caveats of this tunable are listed on arm_hal_interrupt.c.
00022 #if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00023 static EventQueue *equeue;
00024 #endif
00025 
00026 static uint32_t due;
00027 static void (*arm_hal_callback)(void);
00028 
00029 // Called once at boot
00030 void platform_timer_enable(void)
00031 {
00032 #if !MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00033     equeue = mbed_highprio_event_queue();
00034     MBED_ASSERT(equeue != NULL);
00035 #endif
00036     // Prime the SingletonPtrs - can't construct from IRQ/critical section
00037     timer.get();
00038     timeout.get();
00039 }
00040 
00041 // Actually cancels a timer, not the opposite of enable
00042 void platform_timer_disable(void)
00043 {
00044     timeout->detach();
00045 }
00046 
00047 // Not called while running, fortunately
00048 void platform_timer_set_cb(void (*new_fp)(void))
00049 {
00050     arm_hal_callback = new_fp;
00051 }
00052 
00053 static void timer_callback(void)
00054 {
00055     due = 0;
00056 
00057 #if MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT
00058     // Callback is interrupt safe so it can be called directly without
00059     // bouncing via event queue thread.
00060     arm_hal_callback();
00061 #else
00062     equeue->call(arm_hal_callback);
00063 #endif
00064 }
00065 
00066 // This is called from inside platform_enter_critical - IRQs can't happen
00067 void platform_timer_start(uint16_t slots)
00068 {
00069     timer->reset();
00070     due = slots * UINT32_C(50);
00071     timeout->attach_us(timer_callback, due);
00072 }
00073 
00074 // This is called from inside platform_enter_critical - IRQs can't happen
00075 uint16_t platform_timer_get_remaining_slots(void)
00076 {
00077     uint32_t elapsed = timer->read_us();
00078     if (elapsed < due) {
00079         return (uint16_t) ((due - elapsed) / 50);
00080     } else {
00081         return 0;
00082     }
00083 }
00084