takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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