Пример #1
0
void TC0_Handler( void )
{
static uint32_t ulISRCount = 0;

	/* Clear the interrupt. */
	if( tc_get_status( TC0, 0 ) != 0 )
	{
		/* As noted in the comments above, manually pend the TC1 interrupt from
		the TC0 interrupt handler.  This is not done on each occurrence of the
		TC0 interrupt though, to make sure interrupts don't nest in every single
		case. */
		ulISRCount++;
		if( ( ulISRCount & 0x07 ) != 0x07 )
		{
			/* Pend an interrupt that will nest with this interrupt. */
			NVIC_SetPendingIRQ( TC1_IRQn );
		}

		/* Call the IntQ test function for this channel. */
		portYIELD_FROM_ISR( xFirstTimerHandler() );
	}
}
Пример #2
0
/**
 *  Interrupt handler for TC0 interrupt. 
 */
void TC0_Handler(void)
{
	volatile uint32_t ul_dummy;

	/* Clear status bit to acknowledge interrupt */
	ul_dummy = tc_get_status(TC0,0);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);
	
	/** Muda o estado do LED */
		
	if(pio_get_output_data_status(PORT_LED_BLUE , MASK_LED_BLUE) == 0)
	{
		pio_set(PORT_LED_BLUE, (1 << PIN_LED_BLUE));
	}
	else
	{
		pio_clear(PORT_LED_BLUE, (1 << PIN_LED_BLUE));
	}
	
}
Пример #3
0
void TC0_Handler(void)
{
	volatile uint32_t ul_dummy, TC_value;
	
	/* Get the current timer counter value from a 32-bit register*/
	TC_value = tc_read_tc(TC0,0);
	
	/* Clear status bit to acknowledge interrupt */
	ul_dummy = tc_get_status(TC0, 0);
	
	if ((ul_dummy & TC_SR_CPCS) == TC_SR_CPCS) {
		
		#if DEBUG
		printf("%08x OV \n",TC_value);
		#endif
		
		time_msb++;
		
		rtimer_clock_t now =  ((rtimer_clock_t)time_msb << 32)|tc_read_tc(TC0,0);
		
		rtimer_clock_t clock_to_wait = next_rtimer_time - now;
		
		if(clock_to_wait <= 0x100000000 && clock_to_wait > 0)
		{ 
			// We must set now the Timer Compare Register.
			
			// Set the auxiliary timer (TC0,1) at the write time interrupt
			tc_write_rc(TC0,1,(uint32_t)clock_to_wait);
			// Set and enable interrupt on RC compare
			tc_enable_interrupt(TC0,1,TC_IER_CPCS);
			// Start the auxiliary timer
			tc_start(TC0,1);
		}
	}
	
	else {
		printf("ERROR: TC: Unknown interrupt.\n");
	}
}
Пример #4
0
/**
 * \brief Interrupt handler for TC00. Record the number of bytes received,
 * and then restart a read transfer on the USART if the transfer was stopped.
 */
void TC00_Handler(void)
{
	static int32_t input_data = 0;
	static int32_t cnt = 0;

	/* Read TC0 Status. */
	tc_get_status(TC0, 0);

	/* Toggel I/O pin to simulate the PCCK */
	ioport_toggle_pin_level(PIN_PCCK_INPUT);

	/* PCDATA changes every two PCCK level change*/
	cnt++;
	if (cnt == 1) {
		/* Simulate PCD data */
		place_data_to_port(input_data++);
		if (input_data == BUFFER_SIZE ) {
			input_data = 0;
		}
	} else if (cnt == 2) {
		cnt =0;
	}
}
Пример #5
0
/**
 *  Interrupt handler for TC0 interrupt. 
 */
void TC0_Handler(void)
{
	volatile uint32_t ul_dummy;

    /****************************************************************
	* Devemos indicar ao TC que a interrupção foi satisfeita.
    ******************************************************************/
	ul_dummy = tc_get_status(TC0, 0);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);

	/** Muda o estado do LED */
	
	if (PORT_LED_BLUE->PIO_ODSR & MASK_LED_BLUE) {
		/* Value to be driven on the I/O line: 0. */
		pio_clear(PORT_LED_BLUE, MASK_LED_BLUE);
		} else {
		/* Value to be driven on the I/O line: 1. */
		pio_set(PORT_LED_BLUE, MASK_LED_BLUE);
	}
	
}
Пример #6
0
 */
void TC3_Handler(void) {

	volatile uint32_t ul_dummy;

    /****************************************************************
	* Devemos indicar ao TC que a interrupção foi satisfeita.
    ******************************************************************/
	ul_dummy = tc_get_status(TC1, CHANNEL0);

	/* Avoid compiler warning */
	UNUSED(ul_dummy);


	/** Muda o estado do LED */
	
	
	switch (flagLED){
		
		case 0:
			pio_clear(PIN_LED_BLUE_PIO, PIN_LED_BLUE_MASK);
			break;
			
		case 1:
			pio_set(PIN_LED_BLUE_PIO, PIN_LED_BLUE_MASK);
			break;
			
		case 2:
			if(PIN_LED_BLUE_PIO->PIO_ODSR & PIN_LED_BLUE_MASK){
				pio_clear(PIN_LED_BLUE_PIO, PIN_LED_BLUE_MASK);
				} else{
				pio_set(PIN_LED_BLUE_PIO, PIN_LED_BLUE_MASK);
			}
			break;
				
	}
Пример #7
0
/**
 * \brief TC0,1 overflow interrupt
 */
void TC1_Handler(void)
{
	tc_get_status(TC0, 1);
	led_activity_routine();
}
Пример #8
0
void TC_DUTY_HANDLER(void){
	if ((tc_get_status(TC1, TC_CHANNEL_CAP_DUTY) & TC_SR_LDRBS) == TC_SR_LDRBS) {
		capture_ra_duty = tc_read_ra(TC1, TC_CHANNEL_CAP_DUTY);
		capture_rb_duty = tc_read_rb(TC1, TC_CHANNEL_CAP_DUTY);
	}
}
Пример #9
0
/**
 * \brief Interrupt handler. Record the number of bytes received,
 * and then restart a read transfer on the USART if the transfer was stopped.
 */
void TC_USART_Handler(void)
{
	uint32_t ul_status;
#if defined(CONF_BOARD_USART0_RXD) || defined(CONF_BOARD_USART1_RXD)
	uint32_t ul_byte_total = 0;
#endif

	/* Read TC_USART Status. */
	ul_status = tc_get_status(TC_USART, TC_USART_CHN);

	/* RC compare. */
	if ((ul_status & TC_SR_CPCS) == TC_SR_CPCS) {
#ifdef CONF_BOARD_USART0_RXD
		if (busart_chn_open[0]) {
			/* Flush PDC buffer. */
			ul_byte_total = USART_BUFFER_SIZE - pdc_read_rx_counter(g_p_usart_pdc0);
			if (ul_byte_total > 0) {
				if (ul_byte_total == num_bytes_rx_usart0) {
					/* Disable timer. */
					tc_stop(TC_USART, TC_USART_CHN);

					/* Log current size */
					gs_ul_size_usart_buf0 = ul_byte_total;

					/* Stop DMA USART_RX -> force Uart Handler*/
					g_st_usart_rx_packet0.ul_size = 0;
					pdc_rx_init(g_p_usart_pdc0, &g_st_usart_rx_packet0, NULL);
				} else {
					num_bytes_rx_usart0 = ul_byte_total;
				}
			} else {
				num_bytes_rx_usart0 = 0;
			}
		}
#endif

#ifdef CONF_BOARD_USART1_RXD
		if (busart_chn_open[1]) {
			/* Flush PDC buffer. */
			ul_byte_total = USART_BUFFER_SIZE - pdc_read_rx_counter(g_p_usart_pdc1);
			if (ul_byte_total > 0) {
				if (ul_byte_total == num_bytes_rx_usart1) {
					/* Disable timer. */
					tc_stop(TC_USART, TC_USART_CHN);

					/* Log current size */
					gs_ul_size_usart_buf1 = ul_byte_total;

					/* Stop DMA USART_RX -> force Uart Handler*/
					g_st_usart_rx_packet1.ul_size = 0;
					pdc_rx_init(g_p_usart_pdc1, &g_st_usart_rx_packet1, NULL);
				} else {
					num_bytes_rx_usart1 = ul_byte_total;
				}
			} else {
				num_bytes_rx_usart1 = 0;
			}
		}
#endif
	}
}
Пример #10
0
/** Set up the measurement and comparison timer events.
 *   - Configure the reference timer to generate an event upon comparison
 *     match with channel 0.
 *   - Configure the measurement timer to trigger a capture when an event is
 *     received.
 */
static void setup_tc_events(void)
{
	/* Enable incoming events on on measurement timer */
	struct tc_events events_calib = { .on_event_perform_action = true };
	tc_enable_events(&tc_calib, &events_calib);

	/* Generate events from the reference timer on channel 0 compare match */
	struct tc_events events_comp = { .generate_event_on_compare_channel[0] = true };
	tc_enable_events(&tc_comp, &events_comp);

	tc_enable(&tc_calib);
	tc_enable(&tc_comp);
}

/** Set up the event system, linking the measurement and comparison timers so
 *  that events generated from the reference timer are linked to the measurement
 *  timer.
 */
static void setup_events(struct events_resource *event)
{
	struct events_config config;

	events_get_config_defaults(&config);

	/* The event channel detects rising edges of the reference timer output
	 * event */
	config.edge_detect    = EVENTS_EDGE_DETECT_RISING;
	config.path           = EVENTS_PATH_SYNCHRONOUS;
	config.generator      = CONF_EVENT_GENERATOR_ID;

	events_allocate(event, &config);
	events_attach_user(event, CONF_EVENT_USED_ID);

}

/** Set up the USART for transmit-only communication at a fixed baud rate. */
static void setup_usart_channel(void)
{
	struct usart_config cdc_uart_config;
	usart_get_config_defaults(&cdc_uart_config);

	/* Configure the USART settings and initialize the standard I/O library */
	cdc_uart_config.mux_setting = EDBG_CDC_SERCOM_MUX_SETTING;
	cdc_uart_config.pinmux_pad0 = EDBG_CDC_SERCOM_PINMUX_PAD0;
	cdc_uart_config.pinmux_pad1 = EDBG_CDC_SERCOM_PINMUX_PAD1;
	cdc_uart_config.pinmux_pad2 = EDBG_CDC_SERCOM_PINMUX_PAD2;
	cdc_uart_config.pinmux_pad3 = EDBG_CDC_SERCOM_PINMUX_PAD3;
	cdc_uart_config.baudrate    = 115200;
	stdio_serial_init(&usart_edbg, EDBG_CDC_MODULE, &cdc_uart_config);

	usart_enable(&usart_edbg);
}

/** Set up the clock output pin so that the current system clock frequency can
 *  be monitored via an external frequency counter or oscilloscope. */
static void setup_clock_out_pin(void)
{
	struct system_pinmux_config pin_mux;
	system_pinmux_get_config_defaults(&pin_mux);

	/* MUX out the system clock to a I/O pin of the device */
	pin_mux.mux_position = CONF_CLOCK_PIN_MUX;
	system_pinmux_pin_set_config(CONF_CLOCK_PIN_OUT, &pin_mux);
}

/** Retrieves the current system clock frequency, computed from the reference
 *  clock.
 *
 * \return Current system clock frequency in Hz.
 */
static uint32_t get_osc_frequency(void)
{
	/* Clear any existing match status on the measurement timer */
	tc_clear_status(&tc_comp, TC_STATUS_CHANNEL_0_MATCH);

	/* Restart both measurement and reference timers */
	tc_start_counter(&tc_calib);
	tc_start_counter(&tc_comp);

	/* Wait for the measurement timer to signal a compare match */
	while (!(tc_get_status(&tc_comp) & TC_STATUS_CHANNEL_0_MATCH)) {
		/* Wait for channel 0 match */
	}

	/* Compute the real clock frequency from the measurement timer count and
	 * reference count */
	uint64_t tmp = tc_get_capture_value(&tc_calib, TC_COMPARE_CAPTURE_CHANNEL_0);
	return ((tmp * REFERENCE_CLOCK_HZ) >> CALIBRATION_RESOLUTION);
}

int main(void)
{
	struct events_resource event;

	/* System initialization */
	system_init();
	delay_init();

	/* Module initialization */
	setup_tc_channels();
	setup_tc_events();
	setup_events(&event);
	setup_clock_out_pin();

	/* Init the variables with default calibration settings */
	uint8_t frange_cal = SYSCTRL->OSC8M.bit.FRANGE;
	uint8_t temp_cal = SYSCTRL->OSC8M.bit.CALIB >> TEMP_CAL_OFFSET;
	uint8_t comm_cal = SYSCTRL->OSC8M.bit.CALIB & COMM_CAL_MAX;
	/* Set the calibration test range */
	uint8_t frange_cal_min = max((frange_cal - CONF_FRANGE_CAL), FRANGE_CAL_MIN);
	uint8_t frange_cal_max = min((frange_cal + CONF_FRANGE_CAL), FRANGE_CAL_MAX);
	uint8_t temp_cal_min = max((temp_cal - CONF_TEMP_CAL), TEMP_CAL_MIN);
	uint8_t temp_cal_max = min((temp_cal + CONF_TEMP_CAL), TEMP_CAL_MAX);

	/* Variables to track the previous and best calibration settings */
	uint16_t comm_best   = 0;
	uint8_t  frange_best = 0;
	uint32_t freq_best   = 0;
	uint32_t freq_before = get_osc_frequency();

	/* Run calibration loop */
	for (frange_cal = frange_cal_min; frange_cal <= frange_cal_max; frange_cal++) {
		for (temp_cal = temp_cal_min; temp_cal <= temp_cal_max; temp_cal++) {
			for (comm_cal = COMM_CAL_MIN; comm_cal <= COMM_CAL_MAX; comm_cal++) {
				/* Set the test calibration values */
				system_clock_source_write_calibration(
						SYSTEM_CLOCK_SOURCE_OSC8M, (temp_cal << 7) | comm_cal, frange_cal);

				/* Wait for stabilization */
				delay_cycles(1000);

				/* Compute the deltas of the current and best system clock
				 * frequencies, save current settings if they are closer to the
				 * ideal frequency than the previous best values
				 */
				uint32_t freq_current = get_osc_frequency();
				if (abs(freq_current - TARGET_FREQUENCY) < abs(freq_best - TARGET_FREQUENCY)) {
					freq_best   = freq_current;
					comm_best   = comm_cal;
					frange_best = frange_cal;

					port_pin_set_output_level(LED_0_PIN, LED_0_ACTIVE);
				} else {
					port_pin_set_output_level(LED_0_PIN, !LED_0_ACTIVE);
				}
			}
		}
	}

	/* Set the found best calibration values */
	system_clock_source_write_calibration(
			SYSTEM_CLOCK_SOURCE_OSC8M, (temp_cal << 7) | comm_best, frange_best);

	/* Setup USART module to output results */
	setup_usart_channel();

	/* Write previous and current frequency and new calibration settings to the
	 * USART
	 */
	printf("Freq Before: %lu\r\n", freq_before);
	printf("Freq Best: %lu\r\n", freq_best);

	printf("Freq Range: %u\r\n", frange_best);
	printf("Calib Value: 0x%x\r\n", (temp_cal << 7) | comm_best);

	/* Rapidly flash the board LED to signal the calibration completion */
	while (1) {
		port_pin_toggle_output_level(LED_0_PIN);
		delay_ms(200);
	}
}