max4146x_comp

Dependencies:   MAX14690

Committer:
sdivarci
Date:
Sun Oct 25 20:10:02 2020 +0000
Revision:
0:0061165683ee
sdivarci

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sdivarci 0:0061165683ee 1 /***************************************************************************//**
sdivarci 0:0061165683ee 2 * @file em_usbtimer.c
sdivarci 0:0061165683ee 3 * @brief USB protocol stack library, timer API.
sdivarci 0:0061165683ee 4 * @version 3.20.14
sdivarci 0:0061165683ee 5 *******************************************************************************
sdivarci 0:0061165683ee 6 * @section License
sdivarci 0:0061165683ee 7 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
sdivarci 0:0061165683ee 8 *******************************************************************************
sdivarci 0:0061165683ee 9 * Licensed under the Apache License, Version 2.0 (the "License");
sdivarci 0:0061165683ee 10 * you may not use this file except in compliance with the License.
sdivarci 0:0061165683ee 11 * You may obtain a copy of the License at
sdivarci 0:0061165683ee 12 *
sdivarci 0:0061165683ee 13 * http://www.apache.org/licenses/LICENSE-2.0
sdivarci 0:0061165683ee 14 *
sdivarci 0:0061165683ee 15 * Unless required by applicable law or agreed to in writing, software
sdivarci 0:0061165683ee 16 * distributed under the License is distributed on an "AS IS" BASIS,
sdivarci 0:0061165683ee 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sdivarci 0:0061165683ee 18 * See the License for the specific language governing permissions and
sdivarci 0:0061165683ee 19 * limitations under the License.
sdivarci 0:0061165683ee 20 *
sdivarci 0:0061165683ee 21 ******************************************************************************/
sdivarci 0:0061165683ee 22
sdivarci 0:0061165683ee 23 #include "em_device.h"
sdivarci 0:0061165683ee 24 #if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
sdivarci 0:0061165683ee 25 #include "em_usb.h"
sdivarci 0:0061165683ee 26 #if defined( USB_DEVICE ) || defined( USB_HOST )
sdivarci 0:0061165683ee 27 #include "em_cmu.h"
sdivarci 0:0061165683ee 28 #include "em_timer.h"
sdivarci 0:0061165683ee 29 #include "em_usbtypes.h"
sdivarci 0:0061165683ee 30 #include "em_usbhal.h"
sdivarci 0:0061165683ee 31
sdivarci 0:0061165683ee 32 #include "device_peripherals.h"
sdivarci 0:0061165683ee 33
sdivarci 0:0061165683ee 34 /*
sdivarci 0:0061165683ee 35 * Use one HW timer to serve n software milisecond timers.
sdivarci 0:0061165683ee 36 * A timer is, when running, in a linked list of timers.
sdivarci 0:0061165683ee 37 * A given timers timeout period is the acculmulated timeout
sdivarci 0:0061165683ee 38 * of all timers preceeding it in the queue.
sdivarci 0:0061165683ee 39 * This makes timer start (linked list insertion) computing intensive,
sdivarci 0:0061165683ee 40 * but the checking of the queue at each tick very effective.
sdivarci 0:0061165683ee 41 * ______ ______ ______
sdivarci 0:0061165683ee 42 * | | --->| | --->| |
sdivarci 0:0061165683ee 43 * head --> | | | | | | | |
sdivarci 0:0061165683ee 44 * |______|--- |______|--- |______|---/ NULL
sdivarci 0:0061165683ee 45 */
sdivarci 0:0061165683ee 46
sdivarci 0:0061165683ee 47 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
sdivarci 0:0061165683ee 48
sdivarci 0:0061165683ee 49 #ifndef USB_TIMER
sdivarci 0:0061165683ee 50 #error HW platform must define the timer to use for USB
sdivarci 0:0061165683ee 51 #endif
sdivarci 0:0061165683ee 52
sdivarci 0:0061165683ee 53 #if ( USB_TIMER == USB_TIMER0 ) && ( TIMER_COUNT >= 1 )
sdivarci 0:0061165683ee 54 #define TIMER TIMER0
sdivarci 0:0061165683ee 55 #define TIMER_CLK cmuClock_TIMER0
sdivarci 0:0061165683ee 56 #define TIMER_IRQ TIMER0_IRQn
sdivarci 0:0061165683ee 57 #define TIMER_IRQHandler TIMER0_IRQHandler
sdivarci 0:0061165683ee 58
sdivarci 0:0061165683ee 59 #elif ( USB_TIMER == USB_TIMER1 ) && ( TIMER_COUNT >= 2 )
sdivarci 0:0061165683ee 60 #define TIMER TIMER1
sdivarci 0:0061165683ee 61 #define TIMER_CLK cmuClock_TIMER1
sdivarci 0:0061165683ee 62 #define TIMER_IRQ TIMER1_IRQn
sdivarci 0:0061165683ee 63 #define TIMER_IRQHandler TIMER1_IRQHandler
sdivarci 0:0061165683ee 64
sdivarci 0:0061165683ee 65 #elif ( USB_TIMER == USB_TIMER2 ) && ( TIMER_COUNT >= 3 )
sdivarci 0:0061165683ee 66 #define TIMER TIMER2
sdivarci 0:0061165683ee 67 #define TIMER_CLK cmuClock_TIMER2
sdivarci 0:0061165683ee 68 #define TIMER_IRQ TIMER2_IRQn
sdivarci 0:0061165683ee 69 #define TIMER_IRQHandler TIMER2_IRQHandler
sdivarci 0:0061165683ee 70
sdivarci 0:0061165683ee 71 #elif ( USB_TIMER == USB_TIMER3 ) && ( TIMER_COUNT == 4 )
sdivarci 0:0061165683ee 72 #define TIMER TIMER3
sdivarci 0:0061165683ee 73 #define TIMER_CLK cmuClock_TIMER3
sdivarci 0:0061165683ee 74 #define TIMER_IRQ TIMER3_IRQn
sdivarci 0:0061165683ee 75 #define TIMER_IRQHandler TIMER3_IRQHandler
sdivarci 0:0061165683ee 76
sdivarci 0:0061165683ee 77 #else
sdivarci 0:0061165683ee 78 #error "Illegal USB TIMER definition"
sdivarci 0:0061165683ee 79 #endif
sdivarci 0:0061165683ee 80
sdivarci 0:0061165683ee 81 typedef struct _timer
sdivarci 0:0061165683ee 82 {
sdivarci 0:0061165683ee 83 uint32_t timeout; /* Delta value relative to prev. timer */
sdivarci 0:0061165683ee 84 struct _timer *next;
sdivarci 0:0061165683ee 85 USBTIMER_Callback_TypeDef callback;
sdivarci 0:0061165683ee 86 bool running;
sdivarci 0:0061165683ee 87 } USBTIMER_Timer_TypeDef;
sdivarci 0:0061165683ee 88
sdivarci 0:0061165683ee 89 #if ( NUM_QTIMERS > 0 )
sdivarci 0:0061165683ee 90 static USBTIMER_Timer_TypeDef timers[ NUM_QTIMERS ];
sdivarci 0:0061165683ee 91 static USBTIMER_Timer_TypeDef *head = NULL;
sdivarci 0:0061165683ee 92 #endif
sdivarci 0:0061165683ee 93
sdivarci 0:0061165683ee 94 static uint32_t ticksPrMs, ticksPr1us, ticksPr10us, ticksPr100us;
sdivarci 0:0061165683ee 95
sdivarci 0:0061165683ee 96 #if ( NUM_QTIMERS > 0 )
sdivarci 0:0061165683ee 97
sdivarci 0:0061165683ee 98 static void TimerTick( void );
sdivarci 0:0061165683ee 99
sdivarci 0:0061165683ee 100 void TIMER_IRQHandler( void )
sdivarci 0:0061165683ee 101 {
sdivarci 0:0061165683ee 102 uint32_t flags;
sdivarci 0:0061165683ee 103
sdivarci 0:0061165683ee 104 flags = TIMER_IntGet( TIMER );
sdivarci 0:0061165683ee 105
sdivarci 0:0061165683ee 106 if ( flags & TIMER_IF_CC0 )
sdivarci 0:0061165683ee 107 {
sdivarci 0:0061165683ee 108 TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
sdivarci 0:0061165683ee 109 TIMER_CompareSet( TIMER, 0, TIMER_CaptureGet( TIMER, 0 ) + ticksPrMs );
sdivarci 0:0061165683ee 110 TimerTick();
sdivarci 0:0061165683ee 111 }
sdivarci 0:0061165683ee 112 }
sdivarci 0:0061165683ee 113 #endif /* ( NUM_QTIMERS > 0 ) */
sdivarci 0:0061165683ee 114
sdivarci 0:0061165683ee 115 static void DelayTicks( uint16_t ticks )
sdivarci 0:0061165683ee 116 {
sdivarci 0:0061165683ee 117 uint16_t startTime;
sdivarci 0:0061165683ee 118 volatile uint16_t now;
sdivarci 0:0061165683ee 119
sdivarci 0:0061165683ee 120 if ( ticks )
sdivarci 0:0061165683ee 121 {
sdivarci 0:0061165683ee 122 startTime = TIMER_CounterGet( TIMER );
sdivarci 0:0061165683ee 123 do
sdivarci 0:0061165683ee 124 {
sdivarci 0:0061165683ee 125 now = TIMER_CounterGet(TIMER);
sdivarci 0:0061165683ee 126 } while ( (uint16_t)( now - startTime ) < ticks );
sdivarci 0:0061165683ee 127 }
sdivarci 0:0061165683ee 128 }
sdivarci 0:0061165683ee 129
sdivarci 0:0061165683ee 130 /** @endcond */
sdivarci 0:0061165683ee 131
sdivarci 0:0061165683ee 132 /** @addtogroup USB_COMMON
sdivarci 0:0061165683ee 133 * @{*/
sdivarci 0:0061165683ee 134
sdivarci 0:0061165683ee 135 /***************************************************************************//**
sdivarci 0:0061165683ee 136 * @brief
sdivarci 0:0061165683ee 137 * Active wait millisecond delay function. Can also be used inside
sdivarci 0:0061165683ee 138 * interrupt handlers.
sdivarci 0:0061165683ee 139 *
sdivarci 0:0061165683ee 140 * @param[in] msec
sdivarci 0:0061165683ee 141 * Number of milliseconds to wait.
sdivarci 0:0061165683ee 142 ******************************************************************************/
sdivarci 0:0061165683ee 143 void USBTIMER_DelayMs( uint32_t msec )
sdivarci 0:0061165683ee 144 {
sdivarci 0:0061165683ee 145 uint64_t totalTicks;
sdivarci 0:0061165683ee 146
sdivarci 0:0061165683ee 147 totalTicks = (uint64_t)ticksPrMs * msec;
sdivarci 0:0061165683ee 148 while ( totalTicks > 20000 )
sdivarci 0:0061165683ee 149 {
sdivarci 0:0061165683ee 150 DelayTicks( 20000 );
sdivarci 0:0061165683ee 151 totalTicks -= 20000;
sdivarci 0:0061165683ee 152 }
sdivarci 0:0061165683ee 153 DelayTicks( (uint16_t)totalTicks );
sdivarci 0:0061165683ee 154 }
sdivarci 0:0061165683ee 155
sdivarci 0:0061165683ee 156 /***************************************************************************//**
sdivarci 0:0061165683ee 157 * @brief
sdivarci 0:0061165683ee 158 * Active wait microsecond delay function. Can also be used inside
sdivarci 0:0061165683ee 159 * interrupt handlers.
sdivarci 0:0061165683ee 160 *
sdivarci 0:0061165683ee 161 * @param[in] usec
sdivarci 0:0061165683ee 162 * Number of microseconds to wait.
sdivarci 0:0061165683ee 163 ******************************************************************************/
sdivarci 0:0061165683ee 164 void USBTIMER_DelayUs( uint32_t usec )
sdivarci 0:0061165683ee 165 {
sdivarci 0:0061165683ee 166 uint64_t totalTicks;
sdivarci 0:0061165683ee 167
sdivarci 0:0061165683ee 168 totalTicks = (uint64_t)ticksPr1us * usec;
sdivarci 0:0061165683ee 169 if ( totalTicks == 0 )
sdivarci 0:0061165683ee 170 {
sdivarci 0:0061165683ee 171 usec /= 10;
sdivarci 0:0061165683ee 172 totalTicks = (uint64_t)ticksPr10us * usec;
sdivarci 0:0061165683ee 173
sdivarci 0:0061165683ee 174 if ( totalTicks == 0 )
sdivarci 0:0061165683ee 175 {
sdivarci 0:0061165683ee 176 usec /= 10;
sdivarci 0:0061165683ee 177 totalTicks = (uint64_t)ticksPr100us * usec;
sdivarci 0:0061165683ee 178 }
sdivarci 0:0061165683ee 179 }
sdivarci 0:0061165683ee 180
sdivarci 0:0061165683ee 181 while ( totalTicks > 60000 )
sdivarci 0:0061165683ee 182 {
sdivarci 0:0061165683ee 183 DelayTicks( 60000 );
sdivarci 0:0061165683ee 184 totalTicks -= 60000;
sdivarci 0:0061165683ee 185 }
sdivarci 0:0061165683ee 186 DelayTicks( (uint16_t)totalTicks );
sdivarci 0:0061165683ee 187 }
sdivarci 0:0061165683ee 188
sdivarci 0:0061165683ee 189 /***************************************************************************//**
sdivarci 0:0061165683ee 190 * @brief
sdivarci 0:0061165683ee 191 * Activate the hardware timer used to pace the 1 millisecond timer system.
sdivarci 0:0061165683ee 192 *
sdivarci 0:0061165683ee 193 * @details
sdivarci 0:0061165683ee 194 * Call this function whenever the HFPERCLK frequency is changed.
sdivarci 0:0061165683ee 195 * This function is initially called by HOST and DEVICE stack xxxx_Init()
sdivarci 0:0061165683ee 196 * functions.
sdivarci 0:0061165683ee 197 ******************************************************************************/
sdivarci 0:0061165683ee 198 void USBTIMER_Init( void )
sdivarci 0:0061165683ee 199 {
sdivarci 0:0061165683ee 200 uint32_t freq;
sdivarci 0:0061165683ee 201 TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
sdivarci 0:0061165683ee 202 TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
sdivarci 0:0061165683ee 203
sdivarci 0:0061165683ee 204 freq = CMU_ClockFreqGet( cmuClock_HFPER );
sdivarci 0:0061165683ee 205 ticksPrMs = ( freq + 500 ) / 1000;
sdivarci 0:0061165683ee 206 ticksPr1us = ( freq + 500000 ) / 1000000;
sdivarci 0:0061165683ee 207 ticksPr10us = ( freq + 50000 ) / 100000;
sdivarci 0:0061165683ee 208 ticksPr100us = ( freq + 5000 ) / 10000;
sdivarci 0:0061165683ee 209
sdivarci 0:0061165683ee 210 timerCCInit.mode = timerCCModeCompare;
sdivarci 0:0061165683ee 211 CMU_ClockEnable( TIMER_CLK, true );
sdivarci 0:0061165683ee 212 TIMER_TopSet( TIMER, 0xFFFF );
sdivarci 0:0061165683ee 213 TIMER_InitCC( TIMER, 0, &timerCCInit );
sdivarci 0:0061165683ee 214 TIMER_Init( TIMER, &timerInit );
sdivarci 0:0061165683ee 215
sdivarci 0:0061165683ee 216 #if ( NUM_QTIMERS > 0 )
sdivarci 0:0061165683ee 217 TIMER_IntClear( TIMER, 0xFFFFFFFF );
sdivarci 0:0061165683ee 218 TIMER_IntEnable( TIMER, TIMER_IEN_CC0 );
sdivarci 0:0061165683ee 219 TIMER_CompareSet( TIMER, 0, TIMER_CounterGet( TIMER ) + ticksPrMs );
sdivarci 0:0061165683ee 220 NVIC_ClearPendingIRQ( TIMER_IRQ );
sdivarci 0:0061165683ee 221 NVIC_EnableIRQ( TIMER_IRQ );
sdivarci 0:0061165683ee 222 #endif /* ( NUM_QTIMERS > 0 ) */
sdivarci 0:0061165683ee 223 }
sdivarci 0:0061165683ee 224
sdivarci 0:0061165683ee 225 #if ( NUM_QTIMERS > 0 ) || defined( DOXY_DOC_ONLY )
sdivarci 0:0061165683ee 226 /***************************************************************************//**
sdivarci 0:0061165683ee 227 * @brief
sdivarci 0:0061165683ee 228 * Start a timer.
sdivarci 0:0061165683ee 229 *
sdivarci 0:0061165683ee 230 * @details
sdivarci 0:0061165683ee 231 * If the timer is already running, it will be restarted with new timeout.
sdivarci 0:0061165683ee 232 *
sdivarci 0:0061165683ee 233 * @param[in] id
sdivarci 0:0061165683ee 234 * Timer id (0..).
sdivarci 0:0061165683ee 235 *
sdivarci 0:0061165683ee 236 * @param[in] timeout
sdivarci 0:0061165683ee 237 * Number of milliseconds before timer will elapse.
sdivarci 0:0061165683ee 238 *
sdivarci 0:0061165683ee 239 * @param[in] callback
sdivarci 0:0061165683ee 240 * Function to be called on timer elapse, ref. @ref USBTIMER_Callback_TypeDef.
sdivarci 0:0061165683ee 241 ******************************************************************************/
sdivarci 0:0061165683ee 242 void USBTIMER_Start( uint32_t id, uint32_t timeout,
sdivarci 0:0061165683ee 243 USBTIMER_Callback_TypeDef callback )
sdivarci 0:0061165683ee 244 {
sdivarci 0:0061165683ee 245 uint32_t accumulated;
sdivarci 0:0061165683ee 246 USBTIMER_Timer_TypeDef *this, **last;
sdivarci 0:0061165683ee 247
sdivarci 0:0061165683ee 248 INT_Disable();
sdivarci 0:0061165683ee 249
sdivarci 0:0061165683ee 250 if ( timers[ id ].running )
sdivarci 0:0061165683ee 251 {
sdivarci 0:0061165683ee 252 USBTIMER_Stop( id );
sdivarci 0:0061165683ee 253 }
sdivarci 0:0061165683ee 254
sdivarci 0:0061165683ee 255 if ( timeout == 0 )
sdivarci 0:0061165683ee 256 {
sdivarci 0:0061165683ee 257 callback();
sdivarci 0:0061165683ee 258 INT_Enable();
sdivarci 0:0061165683ee 259 return;
sdivarci 0:0061165683ee 260 }
sdivarci 0:0061165683ee 261
sdivarci 0:0061165683ee 262 timers[ id ].running = true;
sdivarci 0:0061165683ee 263 timers[ id ].callback = callback;
sdivarci 0:0061165683ee 264 timers[ id ].next = NULL;
sdivarci 0:0061165683ee 265
sdivarci 0:0061165683ee 266 if ( !head ) /* Queue empty ? */
sdivarci 0:0061165683ee 267 {
sdivarci 0:0061165683ee 268 timers[ id ].timeout = timeout;
sdivarci 0:0061165683ee 269 head = &timers[ id ];
sdivarci 0:0061165683ee 270 }
sdivarci 0:0061165683ee 271 else
sdivarci 0:0061165683ee 272 {
sdivarci 0:0061165683ee 273 this = head;
sdivarci 0:0061165683ee 274 last = &head;
sdivarci 0:0061165683ee 275 accumulated = 0;
sdivarci 0:0061165683ee 276
sdivarci 0:0061165683ee 277 /* Do a sorted insert */
sdivarci 0:0061165683ee 278 while ( this )
sdivarci 0:0061165683ee 279 {
sdivarci 0:0061165683ee 280 if ( timeout < accumulated + this->timeout ) /* Insert before "this" ? */
sdivarci 0:0061165683ee 281 {
sdivarci 0:0061165683ee 282 timers[ id ].timeout = timeout - accumulated;
sdivarci 0:0061165683ee 283 timers[ id ].next = this;
sdivarci 0:0061165683ee 284 *last = &timers[ id ];
sdivarci 0:0061165683ee 285 this->timeout -= timers[ id ].timeout; /* Adjust timeout */
sdivarci 0:0061165683ee 286 break;
sdivarci 0:0061165683ee 287 }
sdivarci 0:0061165683ee 288 else if ( this->next == NULL ) /* At end of queue ? */
sdivarci 0:0061165683ee 289 {
sdivarci 0:0061165683ee 290 timers[ id ].timeout = timeout - accumulated - this->timeout;
sdivarci 0:0061165683ee 291 this->next = &timers[ id ];
sdivarci 0:0061165683ee 292 break;
sdivarci 0:0061165683ee 293 }
sdivarci 0:0061165683ee 294 accumulated += this->timeout;
sdivarci 0:0061165683ee 295 last = &this->next;
sdivarci 0:0061165683ee 296 this = this->next;
sdivarci 0:0061165683ee 297 }
sdivarci 0:0061165683ee 298 }
sdivarci 0:0061165683ee 299
sdivarci 0:0061165683ee 300 INT_Enable();
sdivarci 0:0061165683ee 301 }
sdivarci 0:0061165683ee 302
sdivarci 0:0061165683ee 303 /***************************************************************************//**
sdivarci 0:0061165683ee 304 * @brief
sdivarci 0:0061165683ee 305 * Stop a timer.
sdivarci 0:0061165683ee 306 *
sdivarci 0:0061165683ee 307 * @param[in] id
sdivarci 0:0061165683ee 308 * Timer id (0..).
sdivarci 0:0061165683ee 309 ******************************************************************************/
sdivarci 0:0061165683ee 310 void USBTIMER_Stop( uint32_t id )
sdivarci 0:0061165683ee 311 {
sdivarci 0:0061165683ee 312 USBTIMER_Timer_TypeDef *this, **last;
sdivarci 0:0061165683ee 313
sdivarci 0:0061165683ee 314 INT_Disable();
sdivarci 0:0061165683ee 315
sdivarci 0:0061165683ee 316 if ( head ) /* Queue empty ? */
sdivarci 0:0061165683ee 317 {
sdivarci 0:0061165683ee 318 this = head;
sdivarci 0:0061165683ee 319 last = &head;
sdivarci 0:0061165683ee 320 timers[ id ].running = false;
sdivarci 0:0061165683ee 321
sdivarci 0:0061165683ee 322 while ( this )
sdivarci 0:0061165683ee 323 {
sdivarci 0:0061165683ee 324 if ( this == &timers[ id ] ) /* Correct timer ? */
sdivarci 0:0061165683ee 325 {
sdivarci 0:0061165683ee 326 if ( this->next )
sdivarci 0:0061165683ee 327 {
sdivarci 0:0061165683ee 328 this->next->timeout += timers[ id ].timeout; /* Adjust timeout */
sdivarci 0:0061165683ee 329 }
sdivarci 0:0061165683ee 330 *last = this->next;
sdivarci 0:0061165683ee 331 break;
sdivarci 0:0061165683ee 332 }
sdivarci 0:0061165683ee 333 last = &this->next;
sdivarci 0:0061165683ee 334 this = this->next;
sdivarci 0:0061165683ee 335 }
sdivarci 0:0061165683ee 336 }
sdivarci 0:0061165683ee 337
sdivarci 0:0061165683ee 338 INT_Enable();
sdivarci 0:0061165683ee 339 }
sdivarci 0:0061165683ee 340 #endif /* ( NUM_QTIMERS > 0 ) */
sdivarci 0:0061165683ee 341
sdivarci 0:0061165683ee 342 /** @} (end addtogroup USB_COMMON) */
sdivarci 0:0061165683ee 343
sdivarci 0:0061165683ee 344 #if ( NUM_QTIMERS > 0 )
sdivarci 0:0061165683ee 345 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
sdivarci 0:0061165683ee 346
sdivarci 0:0061165683ee 347 static void TimerTick( void )
sdivarci 0:0061165683ee 348 {
sdivarci 0:0061165683ee 349 USBTIMER_Callback_TypeDef cb;
sdivarci 0:0061165683ee 350
sdivarci 0:0061165683ee 351 INT_Disable();
sdivarci 0:0061165683ee 352
sdivarci 0:0061165683ee 353 if ( head )
sdivarci 0:0061165683ee 354 {
sdivarci 0:0061165683ee 355 head->timeout--;
sdivarci 0:0061165683ee 356
sdivarci 0:0061165683ee 357 while ( head )
sdivarci 0:0061165683ee 358 {
sdivarci 0:0061165683ee 359 if ( head->timeout == 0 )
sdivarci 0:0061165683ee 360 {
sdivarci 0:0061165683ee 361 cb = head->callback;
sdivarci 0:0061165683ee 362 head->running = false;
sdivarci 0:0061165683ee 363 head = head->next;
sdivarci 0:0061165683ee 364 /* The callback may place new items in the queue !!! */
sdivarci 0:0061165683ee 365 if ( cb )
sdivarci 0:0061165683ee 366 {
sdivarci 0:0061165683ee 367 (cb)();
sdivarci 0:0061165683ee 368 }
sdivarci 0:0061165683ee 369 continue; /* There might be more than one timeout pr. tick */
sdivarci 0:0061165683ee 370 }
sdivarci 0:0061165683ee 371 break;
sdivarci 0:0061165683ee 372 }
sdivarci 0:0061165683ee 373 }
sdivarci 0:0061165683ee 374
sdivarci 0:0061165683ee 375 INT_Enable();
sdivarci 0:0061165683ee 376 }
sdivarci 0:0061165683ee 377 /** @endcond */
sdivarci 0:0061165683ee 378 #endif /* ( NUM_QTIMERS > 0 ) */
sdivarci 0:0061165683ee 379
sdivarci 0:0061165683ee 380 #endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
sdivarci 0:0061165683ee 381 #endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */