tick_t getTime() { #if YOTTA_CFG_MINAR_TEST_CLOCK_OVERFLOW #warning "testing clock overflow" return lp_ticker_read() & Time_Mask; #else return lp_ticker_read(); #endif }
void sleepFromUntil(tick_t now, tick_t until){ #if YOTTA_CFG_MINAR_TEST_CLOCK_OVERFLOW /* only lower bits of the timer is passed to this function * in order to set the correct sleeping time in the underlying timer, * the full time (with the top bits) have to be reconstructed here.*/ tick_t timer_top_bits = lp_ticker_read() & ~Time_Mask; now += timer_top_bits; until += timer_top_bits; if (until < now) { until += Time_Mask; } const tick_t real_now = timer_top_bits + getTime(); uint32_t *buf = test::get_sleep_until_buf(); uint32_t tail = test::get_sleep_until_buf_tail(); buf[tail] = until; test::inc_sleep_until_buf_tail(); #else // use real-now for front-most end of do-not-sleep range check const tick_t real_now = getTime(); #endif if(timeIsInPeriod(now, until, real_now + Minimum_Sleep)){ // in this case too soon to go to sleep, just return return; } else { const uint32_t next_int = lp_ticker_get_compare_match(); #if YOTTA_CFG_MINAR_STATS // update stats tick_t now = lp_ticker_read(); total_active += now - last_wakeup; total_sleep += last_wakeup - last_gotosleep; last_gotosleep = now; #endif if(timeIsInPeriod(now, until, next_int)){ lp_ticker_sleep_until(now, until); } else { // existing compare match is sooner, go to sleep sleep(); } #if YOTTA_CFG_MINAR_STATS // update stats last_wakeup = lp_ticker_read(); #endif } }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t now = lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); /** * FIXME: Scheduled alarm may go off incorrectly due to wrap around. * Conditions in which delta is negative: * 1. Wrap around * 2. Newly scheduled alarm is behind now */ //int delta = (timestamp > now) ? (timestamp - now) : (uint32_t) ((uint64_t) timestamp + 0xFFFFFFFFu - now); int delta = (int) (timestamp - now); if (delta > 0) { cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; lp_ticker_arm_cd(); } else { cd_major_minor_clks = cd_minor_clks = 0; /** * This event was in the past. Set the interrupt as pending, but don't process it here. * This prevents a recurive loop under heavy load which can lead to a stack overflow. */ NVIC_SetPendingIRQ(timer3_modinit.irq_n); } }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t cur_time; uint32_t delta; cur_time = lp_ticker_read(); delta = timestamp - cur_time; uint16_t interruptat=0; if(delta > OVERFLOW_16bit_VALUE) { lp_ticker_interrupt_counter= (delta/OVERFLOW_16bit_VALUE) -1; lp_ticker_interrupt_offset=delta%OVERFLOW_16bit_VALUE; interruptat=OVERFLOW_16bit_VALUE; } else { lp_ticker_interrupt_counter=0; lp_ticker_interrupt_offset=0; interruptat=delta; } NVIC_DisableIRQ(TICKER_COUNTER_IRQn2); tc_write_rc(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, (uint32_t)interruptat); NVIC_ClearPendingIRQ(TICKER_COUNTER_IRQn2); NVIC_SetPriority(TICKER_COUNTER_IRQn2, 0); NVIC_EnableIRQ(TICKER_COUNTER_IRQn2); tc_enable_interrupt(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2, TC_IDR_CPCS ); tc_start(TICKER_COUNTER_lp, TICKER_COUNTER_CHANNEL2); }
void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t delta = timestamp - lp_ticker_read(); wakeup_tick = timestamp; TIMER_Stop((TIMER_T *) NU_MODBASE(timer3_modinit.modname)); cd_major_minor_clks = (uint64_t) delta * US_PER_TICK * TMR3_CLK_PER_SEC / US_PER_SEC; lp_ticker_arm_cd(); }
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size) { (void)(obj); /* Return value defaults to error. */ uint32_t result = NRF_ERROR_BUSY; /* Convert size to words. */ uint32_t words = size / sizeof(uint32_t); if (NRF_HAL_SD_IS_ENABLED()) { /* Setup stop watch for timeout. */ uint32_t start_us = lp_ticker_read(); uint32_t now_us = start_us; /* Retry if flash is busy until timeout is reached. */ while (((now_us - start_us) < (words * WORD_WRITE_TIMEOUT_US)) && (result == NRF_ERROR_BUSY)) { result = sd_flash_write((uint32_t *) address, (const uint32_t *) data, words); /* Read timeout timer. */ now_us = lp_ticker_read(); } } else { /* We will use *_words function to speed up flashing code. Word means 32bit -> 4B * or sizeof(uint32_t). */ nrf_nvmc_write_words(address, (const uint32_t *) data, words); result = NRF_SUCCESS; } /* Convert Nordic error code to mbed HAL error code. */ return (result == NRF_SUCCESS) ? 0 : -1; }
void lp_ticker_init(void) { if (lp_ticker_inited) { return; } lp_ticker_inited = 1; counter_major = 0; cd_major_minor_ms = 0; cd_minor_ms = 0; wakeup_tick = TMR_CMP_MAX * MS_PER_TMR2_CLK / MS_PER_TICK; // Reset module SYS_ResetModule(timer2_modinit.rsetidx); SYS_ResetModule(timer3_modinit.rsetidx); // Select IP clock source CLK_SetModuleClock(timer2_modinit.clkidx, timer2_modinit.clksrc, timer2_modinit.clkdiv); CLK_SetModuleClock(timer3_modinit.clkidx, timer3_modinit.clksrc, timer3_modinit.clkdiv); // Enable IP clock CLK_EnableModuleClock(timer2_modinit.clkidx); CLK_EnableModuleClock(timer3_modinit.clkidx); // Configure clock uint32_t clk_timer2 = TIMER_GetModuleClock((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); uint32_t prescale_timer2 = clk_timer2 / TMR2_CLK_FREQ - 1; MBED_ASSERT((prescale_timer2 != (uint32_t) -1) && prescale_timer2 <= 127); uint32_t cmp_timer2 = MS_PER_TMR2_INT / MS_PER_TMR2_CLK; MBED_ASSERT(cmp_timer2 >= TMR_CMP_MIN && cmp_timer2 <= TMR_CMP_MAX); // Continuous mode ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CTL = TIMER_PERIODIC_MODE | prescale_timer2 | TIMER_CTL_CNTDATEN_Msk; ((TIMER_T *) NU_MODBASE(timer2_modinit.modname))->CMP = cmp_timer2; // Set vector NVIC_SetVector(timer2_modinit.irq_n, (uint32_t) timer2_modinit.var); NVIC_SetVector(timer3_modinit.irq_n, (uint32_t) timer3_modinit.var); NVIC_EnableIRQ(timer2_modinit.irq_n); NVIC_EnableIRQ(timer3_modinit.irq_n); TIMER_EnableInt((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); TIMER_EnableWakeup((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); // Schedule wakeup to match semantics of lp_ticker_get_compare_match() lp_ticker_set_interrupt(lp_ticker_read(), wakeup_tick); // Start timer TIMER_Start((TIMER_T *) NU_MODBASE(timer2_modinit.modname)); }
int32_t flash_erase_sector(flash_t *obj, uint32_t address) { (void)(obj); /* Return value defaults to error. */ uint32_t result = NRF_ERROR_BUSY; if (NRF_HAL_SD_IS_ENABLED()) { /* Convert address to page number. */ uint32_t page_number = address / NRF_FICR->CODEPAGESIZE; /* Setup stop watch for timeout. */ uint32_t start_us = lp_ticker_read(); uint32_t now_us = start_us; /* Retry if flash is busy until timeout is reached. */ while (((now_us - start_us) < PAGE_ERASE_TIMEOUT_US) && (result == NRF_ERROR_BUSY)) { result = sd_flash_page_erase(page_number); /* Read timeout timer. */ now_us = lp_ticker_read(); } } else { /* Raw API doesn't return error code, assume success. */ nrf_nvmc_page_erase(address); result = NRF_SUCCESS; } /* Convert Nordic error code to mbed HAL error code. */ return (result == NRF_SUCCESS) ? 0 : -1; }
/** * Set interrupt for specified timestamp * timestamp: The time in microseconds to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { int32_t delta = 0; /* Verify if lp_ticker has been not Initialized */ if (lp_ticker_initialized == 0) lp_ticker_init(); /* Calculate the delta */ delta = (int32_t)(timestamp - lp_ticker_read()); /* Check if the event was in the past */ if (delta <= 0) { /* This event was in the past */ DualTimer_SetInterrupt_1(DUALTIMER0, 0, DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); return; } /* Enable interrupt on SingleTimer1 */ DualTimer_SetInterrupt_1(DUALTIMER0, delta, DUALTIMER_COUNT_32 | DUALTIMER_ONESHOT); }
/** Set interrupt for specified timestamp * * @param timestamp The time in microseconds to be set */ void lp_ticker_set_interrupt(timestamp_t timestamp) { uint32_t now_us, delta_us, delta_ticks; if (!lp_ticker_inited) { lp_ticker_init(); } lptmr_schedule = 0; now_us = lp_ticker_read(); delta_us = timestamp > now_us ? timestamp - now_us : (uint32_t)((uint64_t)timestamp + 0xFFFFFFFF - now_us); /* Checking if LPTRM can handle this sleep */ delta_ticks = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); if (delta_ticks > MAX_LPTMR_SLEEP) { /* Using RTC if wait time is over 16b (2s @32kHz) */ uint32_t delta_sec; delta_us += COUNT_TO_USEC(RTC->TPR, CLOCK_GetFreq(kCLOCK_Er32kClk)); /* Accounting for started second */ delta_sec = delta_us / SEC_IN_USEC; delta_us -= delta_sec * SEC_IN_USEC; RTC->TAR = RTC->TSR + delta_sec - 1; RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable); /* Set aditional, subsecond, sleep time */ if (delta_us) { lptmr_schedule = USEC_TO_COUNT(delta_us, CLOCK_GetFreq(kCLOCK_Er32kClk)); } } else { /* Below RTC resolution using LPTMR */ LPTMR_SetTimerPeriod(LPTMR0, delta_ticks); LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable); LPTMR_StartTimer(LPTMR0); } }