Exemple #1
0
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;
}
Exemple #4
0
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;
}
Exemple #6
0
int Tmr::setoc(const tmr_reqattr_t * req){
	return hwpl_tmr_setoc(port_, (void*)req);
}