static void update_count(void){ tmr_reqattr_t chan_req; uint32_t now; chan_req.channel = LCD_USECOND_OC; hwpl_tmr_off(LCD_USECOND_TMR, 0); now = hwpl_tmr_get(LCD_USECOND_TMR, 0); chan_req.value = now + LCD_USECOND_COUNTS; if( chan_req.value > CAOS_USECOND_PERIOD ){ chan_req.value -= CAOS_USECOND_PERIOD; } hwpl_tmr_setoc(LCD_USECOND_TMR, &chan_req); hwpl_tmr_on(LCD_USECOND_TMR, 0); }
void sched_priv_timedblock(void * block_object, struct sched_timeval * abs_time){ #if SINGLE_TASK == 0 int id; tmr_reqattr_t chan_req; uint32_t now; bool time_sleep; //Initialization id = task_get_current(); sched_table[id].block_object = block_object; time_sleep = false; if (abs_time->tv_sec >= sched_usecond_counter){ sched_table[id].wake.tv_sec = abs_time->tv_sec; sched_table[id].wake.tv_usec = abs_time->tv_usec; if(abs_time->tv_sec == sched_usecond_counter){ hwpl_tmr_off(clk_usecond_tmr, NULL); //stop the timer //Read the current OC value to see if it needs to be updated chan_req.channel = CAOSLIB_USECOND_TMR_SLEEP_OC; hwpl_tmr_getoc(clk_usecond_tmr, &chan_req); if ( abs_time->tv_usec < chan_req.value ){ chan_req.value = abs_time->tv_usec; } //See if abs_time is in the past now = (uint32_t)hwpl_tmr_get(clk_usecond_tmr, NULL); if( abs_time->tv_usec > (now+40) ){ //needs to be enough in the future to allow the OC to be set before the timer passes it hwpl_tmr_setoc(clk_usecond_tmr, &chan_req); time_sleep = true; } hwpl_tmr_on(clk_usecond_tmr, NULL); //start the timer } else { time_sleep = true; } } if ( (block_object == NULL) && (time_sleep == false) ){ //Do not sleep return; } sched_priv_update_on_sleep(); #endif }
int priv_usecond_match_event(void * context, const void * data){ #if SINGLE_TASK == 0 int i; uint32_t next; uint32_t tmp; int new_priority; tmr_reqattr_t chan_req; static const uint32_t overflow = (CAOS_USECOND_PERIOD); uint32_t current_match; //Initialize variables chan_req.channel = CAOSLIB_USECOND_TMR_SLEEP_OC; chan_req.value = CAOS_USECOND_PERIOD + 1; new_priority = SCHED_LOWEST_PRIORITY - 1; next = overflow; hwpl_tmr_off(clk_usecond_tmr, NULL); //stop the timer current_match = hwpl_tmr_get(clk_usecond_tmr, NULL); for(i=1; i < task_get_total(); i++){ if ( task_enabled(i) && !sched_active_asserted(i) ){ //enabled and inactive tasks only tmp = sched_table[i].wake.tv_usec; //compare the current clock to the wake time if ( (sched_table[i].wake.tv_sec < sched_usecond_counter) || ( (sched_table[i].wake.tv_sec == sched_usecond_counter) && (tmp <= current_match) ) ){ //wake this task sched_table[i].wake.tv_sec = SCHED_TIMEVAL_SEC_INVALID; sched_priv_assert_active(i, SCHED_UNBLOCK_SLEEP); if ( sched_get_priority(i) > new_priority ){ new_priority = sched_get_priority(i); } } else if ( (sched_table[i].wake.tv_sec == sched_usecond_counter) && (tmp < next) ) { //see if this is the next event to wake up next = tmp; } } } if ( next < overflow ){ chan_req.value = next; } hwpl_tmr_setoc(clk_usecond_tmr, &chan_req); sched_priv_update_on_wake(new_priority); hwpl_tmr_on(clk_usecond_tmr, NULL); #endif return 1; }
void Timer::wait_usec(uint32_t timeout){ Tmr tmr(port); tmr_reqattr_t chan_req; //enable the interrupt hwpl_tmr_off(port, 0); chan_req.channel = TMR_ACTION_CHANNEL_OC0; chan_req.value = hwpl_tmr_get(port, 0) + timeout; hwpl_tmr_setoc(port, &chan_req); tmr_is_expired = false; hwpl_tmr_on(port, 0); while( !tmr_is_expired ){ _hwpl_core_sleep(CORE_SLEEP); } }
int open_usecond_tmr(void){ int err; tmr_attr_t cfg; tmr_action_t action; tmr_reqattr_t chan_req; device_periph_t tmr; tmr.port = clk_usecond_tmr; //Open the microsecond timer err = hwpl_tmr_open((device_cfg_t*)&tmr); if (err){ return err; } memset(&cfg, 0, sizeof(tmr_attr_t)); cfg.freq = 1000000; cfg.clksrc = TMR_CLKSRC_CPU; err = hwpl_tmr_setattr(tmr.port, &cfg); if ( err ){ return err; } //Initialize the value of the timer to zero err = hwpl_tmr_set(tmr.port, (void*)0); if (err){ return err; } //Set the reset output compare value to reset the clock every 32 seconds chan_req.channel = CAOSLIB_USECOND_TMR_RESET_OC; chan_req.value = CAOS_USECOND_PERIOD; //overflow every SCHED_TIMEVAL_SECONDS seconds err = hwpl_tmr_setoc(tmr.port, &chan_req); if (err){ return -1; } action.channel = CAOSLIB_USECOND_TMR_RESET_OC; action.event = TMR_ACTION_EVENT_RESET|TMR_ACTION_EVENT_INTERRUPT; action.callback = usecond_overflow_event; err = hwpl_tmr_setaction(tmr.port, &action); if (err){ return -1; } //Turn the timer on err = hwpl_tmr_on(tmr.port, NULL); if (err){ return -1; } //This sets up the output compare unit used with the usleep() function chan_req.channel = CAOSLIB_USECOND_TMR_SLEEP_OC; chan_req.value = CAOS_USECOND_PERIOD + 1; err = hwpl_tmr_setoc(tmr.port, &chan_req); if ( err ){ return -1; } action.channel = CAOSLIB_USECOND_TMR_SLEEP_OC; action.event = TMR_ACTION_EVENT_INTERRUPT; action.callback = priv_usecond_match_event; err = hwpl_tmr_setaction(tmr.port, &action); if ( err ){ return -1; } return 0; }
int Tmr::setoc(const tmr_reqattr_t * req){ return hwpl_tmr_setoc(port_, (void*)req); }