mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Committer:
be_bryan
Date:
Mon Dec 11 17:54:04 2017 +0000
Revision:
0:b74591d5ab33
motor ++

Who changed what in which revision?

UserRevisionLine numberNew contents of line
be_bryan 0:b74591d5ab33 1 /* mbed Microcontroller Library
be_bryan 0:b74591d5ab33 2 * Copyright (c) 2006-2012 ARM Limited
be_bryan 0:b74591d5ab33 3 *
be_bryan 0:b74591d5ab33 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
be_bryan 0:b74591d5ab33 5 * of this software and associated documentation files (the "Software"), to deal
be_bryan 0:b74591d5ab33 6 * in the Software without restriction, including without limitation the rights
be_bryan 0:b74591d5ab33 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
be_bryan 0:b74591d5ab33 8 * copies of the Software, and to permit persons to whom the Software is
be_bryan 0:b74591d5ab33 9 * furnished to do so, subject to the following conditions:
be_bryan 0:b74591d5ab33 10 *
be_bryan 0:b74591d5ab33 11 * The above copyright notice and this permission notice shall be included in
be_bryan 0:b74591d5ab33 12 * all copies or substantial portions of the Software.
be_bryan 0:b74591d5ab33 13 *
be_bryan 0:b74591d5ab33 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
be_bryan 0:b74591d5ab33 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
be_bryan 0:b74591d5ab33 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
be_bryan 0:b74591d5ab33 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
be_bryan 0:b74591d5ab33 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
be_bryan 0:b74591d5ab33 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
be_bryan 0:b74591d5ab33 20 * SOFTWARE.
be_bryan 0:b74591d5ab33 21 */
be_bryan 0:b74591d5ab33 22
be_bryan 0:b74591d5ab33 23 #include "rtos/rtos_idle.h"
be_bryan 0:b74591d5ab33 24 #include "platform/mbed_sleep.h"
be_bryan 0:b74591d5ab33 25 #include "TimerEvent.h"
be_bryan 0:b74591d5ab33 26 #include "lp_ticker_api.h"
be_bryan 0:b74591d5ab33 27 #include "rtx_core_cm.h"
be_bryan 0:b74591d5ab33 28 #include "mbed_critical.h"
be_bryan 0:b74591d5ab33 29 #include "mbed_assert.h"
be_bryan 0:b74591d5ab33 30 #include <new>
be_bryan 0:b74591d5ab33 31 #include "rtx_os.h"
be_bryan 0:b74591d5ab33 32 extern "C" {
be_bryan 0:b74591d5ab33 33 #include "rtx_lib.h"
be_bryan 0:b74591d5ab33 34 }
be_bryan 0:b74591d5ab33 35
be_bryan 0:b74591d5ab33 36 using namespace mbed;
be_bryan 0:b74591d5ab33 37
be_bryan 0:b74591d5ab33 38 #ifdef MBED_TICKLESS
be_bryan 0:b74591d5ab33 39
be_bryan 0:b74591d5ab33 40 #if (defined(NO_SYSTICK))
be_bryan 0:b74591d5ab33 41 /**
be_bryan 0:b74591d5ab33 42 * Return an IRQ number that can be used in the absence of SysTick
be_bryan 0:b74591d5ab33 43 *
be_bryan 0:b74591d5ab33 44 * @return Free IRQ number that can be used
be_bryan 0:b74591d5ab33 45 */
be_bryan 0:b74591d5ab33 46 extern "C" IRQn_Type mbed_get_m0_tick_irqn(void);
be_bryan 0:b74591d5ab33 47 #endif
be_bryan 0:b74591d5ab33 48
be_bryan 0:b74591d5ab33 49 class RtosTimer : private TimerEvent {
be_bryan 0:b74591d5ab33 50 public:
be_bryan 0:b74591d5ab33 51 RtosTimer(): TimerEvent(get_lp_ticker_data()), _start_time(0), _tick(0) {
be_bryan 0:b74591d5ab33 52 _start_time = ticker_read_us(_ticker_data);
be_bryan 0:b74591d5ab33 53 #if (defined(NO_SYSTICK))
be_bryan 0:b74591d5ab33 54 NVIC_SetVector(mbed_get_m0_tick_irqn(), (uint32_t)SysTick_Handler);
be_bryan 0:b74591d5ab33 55 NVIC_SetPriority(mbed_get_m0_tick_irqn(), 0xFF); /* RTOS requires lowest priority */
be_bryan 0:b74591d5ab33 56 NVIC_EnableIRQ(mbed_get_m0_tick_irqn());
be_bryan 0:b74591d5ab33 57 #else
be_bryan 0:b74591d5ab33 58 // Ensure SysTick has the correct priority as it is still used
be_bryan 0:b74591d5ab33 59 // to trigger software interrupts on each tick. The period does
be_bryan 0:b74591d5ab33 60 // not matter since it will never start counting.
be_bryan 0:b74591d5ab33 61 OS_Tick_Setup(osRtxConfig.tick_freq, OS_TICK_HANDLER);
be_bryan 0:b74591d5ab33 62 #endif
be_bryan 0:b74591d5ab33 63 };
be_bryan 0:b74591d5ab33 64
be_bryan 0:b74591d5ab33 65 /**
be_bryan 0:b74591d5ab33 66 * Schedule an os tick to fire
be_bryan 0:b74591d5ab33 67 *
be_bryan 0:b74591d5ab33 68 * @param delta Tick to fire at relative to current tick
be_bryan 0:b74591d5ab33 69 */
be_bryan 0:b74591d5ab33 70 void schedule_tick(uint32_t delta=1) {
be_bryan 0:b74591d5ab33 71 insert_absolute(_start_time + (_tick + delta) * 1000000 / OS_TICK_FREQ);
be_bryan 0:b74591d5ab33 72 }
be_bryan 0:b74591d5ab33 73
be_bryan 0:b74591d5ab33 74
be_bryan 0:b74591d5ab33 75 /**
be_bryan 0:b74591d5ab33 76 * Prevent any scheduled ticks from triggering
be_bryan 0:b74591d5ab33 77 */
be_bryan 0:b74591d5ab33 78 void cancel_tick() {
be_bryan 0:b74591d5ab33 79 remove();
be_bryan 0:b74591d5ab33 80 }
be_bryan 0:b74591d5ab33 81
be_bryan 0:b74591d5ab33 82 /**
be_bryan 0:b74591d5ab33 83 * Get the current tick count
be_bryan 0:b74591d5ab33 84 *
be_bryan 0:b74591d5ab33 85 * @return The number of ticks since boot. This should match RTX's tick count
be_bryan 0:b74591d5ab33 86 */
be_bryan 0:b74591d5ab33 87 uint32_t get_tick() {
be_bryan 0:b74591d5ab33 88 return _tick & 0xFFFFFFFF;
be_bryan 0:b74591d5ab33 89 }
be_bryan 0:b74591d5ab33 90
be_bryan 0:b74591d5ab33 91 /**
be_bryan 0:b74591d5ab33 92 * Update the internal tick count
be_bryan 0:b74591d5ab33 93 *
be_bryan 0:b74591d5ab33 94 * @return The number of ticks incremented
be_bryan 0:b74591d5ab33 95 */
be_bryan 0:b74591d5ab33 96 uint32_t update_tick() {
be_bryan 0:b74591d5ab33 97 uint64_t new_tick = ticker_read_us(_ticker_data) * OS_TICK_FREQ / 1000000;
be_bryan 0:b74591d5ab33 98 if (new_tick > _tick) {
be_bryan 0:b74591d5ab33 99 // Don't update to the current tick. Instead, update to the
be_bryan 0:b74591d5ab33 100 // previous tick and let the SysTick handler increment it
be_bryan 0:b74591d5ab33 101 // to the current value. This allows scheduling restart
be_bryan 0:b74591d5ab33 102 // successfully after the OS is resumed.
be_bryan 0:b74591d5ab33 103 new_tick--;
be_bryan 0:b74591d5ab33 104 }
be_bryan 0:b74591d5ab33 105 uint32_t elapsed_ticks = new_tick - _tick;
be_bryan 0:b74591d5ab33 106 _tick = new_tick;
be_bryan 0:b74591d5ab33 107 return elapsed_ticks;
be_bryan 0:b74591d5ab33 108 }
be_bryan 0:b74591d5ab33 109
be_bryan 0:b74591d5ab33 110 /**
be_bryan 0:b74591d5ab33 111 * Get the time
be_bryan 0:b74591d5ab33 112 *
be_bryan 0:b74591d5ab33 113 * @return Current time in microseconds
be_bryan 0:b74591d5ab33 114 */
be_bryan 0:b74591d5ab33 115 us_timestamp_t get_time() {
be_bryan 0:b74591d5ab33 116 return ticker_read_us(_ticker_data);
be_bryan 0:b74591d5ab33 117 }
be_bryan 0:b74591d5ab33 118
be_bryan 0:b74591d5ab33 119 ~RtosTimer() {
be_bryan 0:b74591d5ab33 120
be_bryan 0:b74591d5ab33 121 };
be_bryan 0:b74591d5ab33 122
be_bryan 0:b74591d5ab33 123 protected:
be_bryan 0:b74591d5ab33 124
be_bryan 0:b74591d5ab33 125 void handler() {
be_bryan 0:b74591d5ab33 126 #if (defined(NO_SYSTICK))
be_bryan 0:b74591d5ab33 127 NVIC_SetPendingIRQ(mbed_get_m0_tick_irqn());
be_bryan 0:b74591d5ab33 128 #else
be_bryan 0:b74591d5ab33 129 SCB->ICSR = SCB_ICSR_PENDSTSET_Msk;
be_bryan 0:b74591d5ab33 130 #endif
be_bryan 0:b74591d5ab33 131 _tick++;
be_bryan 0:b74591d5ab33 132 }
be_bryan 0:b74591d5ab33 133
be_bryan 0:b74591d5ab33 134 us_timestamp_t _start_time;
be_bryan 0:b74591d5ab33 135 uint64_t _tick;
be_bryan 0:b74591d5ab33 136 };
be_bryan 0:b74591d5ab33 137
be_bryan 0:b74591d5ab33 138 static RtosTimer *os_timer;
be_bryan 0:b74591d5ab33 139 static uint64_t os_timer_data[sizeof(RtosTimer) / 8];
be_bryan 0:b74591d5ab33 140
be_bryan 0:b74591d5ab33 141 /// Enable System Timer.
be_bryan 0:b74591d5ab33 142 int32_t OS_Tick_Enable (void)
be_bryan 0:b74591d5ab33 143 {
be_bryan 0:b74591d5ab33 144 // Do not use SingletonPtr since this relies on the RTOS
be_bryan 0:b74591d5ab33 145 if (NULL == os_timer) {
be_bryan 0:b74591d5ab33 146 os_timer = new (os_timer_data) RtosTimer();
be_bryan 0:b74591d5ab33 147 }
be_bryan 0:b74591d5ab33 148
be_bryan 0:b74591d5ab33 149 // set to fire interrupt on next tick
be_bryan 0:b74591d5ab33 150 os_timer->schedule_tick();
be_bryan 0:b74591d5ab33 151
be_bryan 0:b74591d5ab33 152 return 0;
be_bryan 0:b74591d5ab33 153 }
be_bryan 0:b74591d5ab33 154
be_bryan 0:b74591d5ab33 155 /// Disable System Timer.
be_bryan 0:b74591d5ab33 156 int32_t OS_Tick_Disable (void)
be_bryan 0:b74591d5ab33 157 {
be_bryan 0:b74591d5ab33 158 os_timer->cancel_tick();
be_bryan 0:b74591d5ab33 159
be_bryan 0:b74591d5ab33 160 return 0;
be_bryan 0:b74591d5ab33 161 }
be_bryan 0:b74591d5ab33 162
be_bryan 0:b74591d5ab33 163 /// Acknowledge System Timer IRQ.
be_bryan 0:b74591d5ab33 164 int32_t OS_Tick_AcknowledgeIRQ (void)
be_bryan 0:b74591d5ab33 165 {
be_bryan 0:b74591d5ab33 166 os_timer->schedule_tick();
be_bryan 0:b74591d5ab33 167
be_bryan 0:b74591d5ab33 168 return 0;
be_bryan 0:b74591d5ab33 169 }
be_bryan 0:b74591d5ab33 170
be_bryan 0:b74591d5ab33 171 /// Get System Timer count.
be_bryan 0:b74591d5ab33 172 uint32_t OS_Tick_GetCount (void)
be_bryan 0:b74591d5ab33 173 {
be_bryan 0:b74591d5ab33 174 return os_timer->get_time() & 0xFFFFFFFF;
be_bryan 0:b74591d5ab33 175 }
be_bryan 0:b74591d5ab33 176
be_bryan 0:b74591d5ab33 177 // Get OS Tick IRQ number.
be_bryan 0:b74591d5ab33 178 int32_t OS_Tick_GetIRQn (void) {
be_bryan 0:b74591d5ab33 179 return -1;
be_bryan 0:b74591d5ab33 180 }
be_bryan 0:b74591d5ab33 181
be_bryan 0:b74591d5ab33 182 // Get OS Tick overflow status.
be_bryan 0:b74591d5ab33 183 uint32_t OS_Tick_GetOverflow (void) {
be_bryan 0:b74591d5ab33 184 return 0;
be_bryan 0:b74591d5ab33 185 }
be_bryan 0:b74591d5ab33 186
be_bryan 0:b74591d5ab33 187 // Get OS Tick interval.
be_bryan 0:b74591d5ab33 188 uint32_t OS_Tick_GetInterval (void) {
be_bryan 0:b74591d5ab33 189 return 1000;
be_bryan 0:b74591d5ab33 190 }
be_bryan 0:b74591d5ab33 191
be_bryan 0:b74591d5ab33 192 static void default_idle_hook(void)
be_bryan 0:b74591d5ab33 193 {
be_bryan 0:b74591d5ab33 194 uint32_t elapsed_ticks = 0;
be_bryan 0:b74591d5ab33 195
be_bryan 0:b74591d5ab33 196 core_util_critical_section_enter();
be_bryan 0:b74591d5ab33 197 uint32_t ticks_to_sleep = svcRtxKernelSuspend();
be_bryan 0:b74591d5ab33 198 MBED_ASSERT(os_timer->get_tick() == svcRtxKernelGetTickCount());
be_bryan 0:b74591d5ab33 199 if (ticks_to_sleep) {
be_bryan 0:b74591d5ab33 200 os_timer->schedule_tick(ticks_to_sleep);
be_bryan 0:b74591d5ab33 201
be_bryan 0:b74591d5ab33 202 sleep_manager_lock_deep_sleep();
be_bryan 0:b74591d5ab33 203 sleep();
be_bryan 0:b74591d5ab33 204 sleep_manager_unlock_deep_sleep();
be_bryan 0:b74591d5ab33 205
be_bryan 0:b74591d5ab33 206 os_timer->cancel_tick();
be_bryan 0:b74591d5ab33 207 // calculate how long we slept
be_bryan 0:b74591d5ab33 208 elapsed_ticks = os_timer->update_tick();
be_bryan 0:b74591d5ab33 209 }
be_bryan 0:b74591d5ab33 210 svcRtxKernelResume(elapsed_ticks);
be_bryan 0:b74591d5ab33 211 core_util_critical_section_exit();
be_bryan 0:b74591d5ab33 212 }
be_bryan 0:b74591d5ab33 213
be_bryan 0:b74591d5ab33 214 #elif defined(FEATURE_UVISOR)
be_bryan 0:b74591d5ab33 215
be_bryan 0:b74591d5ab33 216 static void default_idle_hook(void)
be_bryan 0:b74591d5ab33 217 {
be_bryan 0:b74591d5ab33 218 /* uVisor can't sleep. See <https://github.com/ARMmbed/uvisor/issues/420>
be_bryan 0:b74591d5ab33 219 * for details. */
be_bryan 0:b74591d5ab33 220 }
be_bryan 0:b74591d5ab33 221
be_bryan 0:b74591d5ab33 222 #else
be_bryan 0:b74591d5ab33 223
be_bryan 0:b74591d5ab33 224 static void default_idle_hook(void)
be_bryan 0:b74591d5ab33 225 {
be_bryan 0:b74591d5ab33 226 // critical section to complete sleep with locked deepsleep
be_bryan 0:b74591d5ab33 227 core_util_critical_section_enter();
be_bryan 0:b74591d5ab33 228 sleep_manager_lock_deep_sleep();
be_bryan 0:b74591d5ab33 229 sleep();
be_bryan 0:b74591d5ab33 230 sleep_manager_unlock_deep_sleep();
be_bryan 0:b74591d5ab33 231 core_util_critical_section_exit();
be_bryan 0:b74591d5ab33 232 }
be_bryan 0:b74591d5ab33 233
be_bryan 0:b74591d5ab33 234 #endif // MBED_TICKLESS
be_bryan 0:b74591d5ab33 235
be_bryan 0:b74591d5ab33 236 static void (*idle_hook_fptr)(void) = &default_idle_hook;
be_bryan 0:b74591d5ab33 237
be_bryan 0:b74591d5ab33 238 void rtos_attach_idle_hook(void (*fptr)(void))
be_bryan 0:b74591d5ab33 239 {
be_bryan 0:b74591d5ab33 240 //Attach the specified idle hook, or the default idle hook in case of a NULL pointer
be_bryan 0:b74591d5ab33 241 if (fptr != NULL) {
be_bryan 0:b74591d5ab33 242 idle_hook_fptr = fptr;
be_bryan 0:b74591d5ab33 243 } else {
be_bryan 0:b74591d5ab33 244 idle_hook_fptr = default_idle_hook;
be_bryan 0:b74591d5ab33 245 }
be_bryan 0:b74591d5ab33 246 }
be_bryan 0:b74591d5ab33 247
be_bryan 0:b74591d5ab33 248 extern "C" void rtos_idle_loop(void)
be_bryan 0:b74591d5ab33 249 {
be_bryan 0:b74591d5ab33 250 //Continuously call the idle hook function pointer
be_bryan 0:b74591d5ab33 251 while (1) {
be_bryan 0:b74591d5ab33 252 idle_hook_fptr();
be_bryan 0:b74591d5ab33 253 }
be_bryan 0:b74591d5ab33 254 }