/*! \brief to initialize hw timer */ uint8_t tmr_init(void) { uint8_t timer_multiplier; tc_get_config_defaults(&timer_config); #ifdef ENABLE_SLEEP if(sys_sleep == true) { timer_config.clock_source = GCLK_GENERATOR_1; timer_config.clock_prescaler = TC_CLOCK_PRESCALER_DIV2; timer_config.run_in_standby=true; } #endif timer_config.counter_16_bit.compare_capture_channel[0] = TIMER_PERIOD; tc_init(&module_inst, TIMER, &timer_config); tc_register_callback(&module_inst, tc_ovf_callback, TC_CALLBACK_OVERFLOW); tc_register_callback(&module_inst, tc_cca_callback, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&module_inst, TC_CALLBACK_OVERFLOW); tc_enable_callback(&module_inst, TC_CALLBACK_CC_CHANNEL0); tc_enable(&module_inst); /* calculate how faster the timer with current clk freq compared to timer with 1Mhz */ #ifdef ENABLE_SLEEP if(sys_sleep ==true) { timer_multiplier = system_gclk_gen_get_hz(1) / 2000000; } else { timer_multiplier = system_gclk_gen_get_hz(0) / DEF_1MHZ; } #else timer_multiplier = system_gclk_gen_get_hz(0) / DEF_1MHZ; #endif return timer_multiplier; }
/*---------------------------------------------------------------------------*/ void clock_init(void) { #define TIMER_PERIOD UINT16_MAX #define TIMER TC3 struct tc_config cfg; tc_get_config_defaults(&cfg); cfg.clock_source = GCLK_GENERATOR_5; cfg.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; cfg.run_in_standby = false; cfg.counter_16_bit.compare_capture_channel[0] = TIMER_PERIOD; tc_init(&tc_instance, TIMER, &cfg); /* tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_OVERFLOW);*/ tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_CC_CHANNEL0); /* tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_CC_CHANNEL1); tc_register_callback(&tc_instance, clock_irq_callback, TC_CALLBACK_ERROR);*/ /* tc_enable_callback(&tc_instance, TC_CALLBACK_OVERFLOW);*/ tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0); /* tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL1); tc_enable_callback(&tc_instance, TC_CALLBACK_ERROR);*/ tc_enable(&tc_instance); }
void *platform_configure_timer(platform_hw_timer_callback_t bus_tc_cb_ptr) { struct tc_config timer_config; system_interrupt_enter_critical_section(); if (hw_timers[0].timer_usage == 0) { hw_timers[0].timer_usage = 1; platform_cc1_cb = bus_tc_cb_ptr; tc_get_config_defaults(&timer_config); timer_config.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; timer_config.oneshot = true; timer_config.counter_size = TC_COUNTER_SIZE_32BIT; timer_config.count_direction = TC_COUNT_DIRECTION_UP; tc_init(&bus_tc_instance, CONF_BUS_TC_MODULE, &timer_config); timer_count_per_ms = ((system_gclk_gen_get_hz(timer_config.clock_source)) /1000); tc_set_count_value(&bus_tc_instance, 0); tc_enable(&bus_tc_instance); tc_stop_counter(&bus_tc_instance); tc_register_callback(&bus_tc_instance, tc_cc1_cb, TC_CALLBACK_OVERFLOW); tc_enable_callback(&bus_tc_instance, TC_CALLBACK_OVERFLOW); hw_timers[0].timer_frequency = (system_gclk_gen_get_hz(timer_config.clock_source)); hw_timers[0].timer_instance = bus_tc_instance; system_interrupt_leave_critical_section(); return (&hw_timers[0]); } system_interrupt_leave_critical_section(); return NULL; }
void configure_tc_callbacks(void) { tc_register_callback(&tc_instance, tc_callback_overflow, TC_CALLBACK_OVERFLOW); tc_enable_callback(&tc_instance, TC_CALLBACK_OVERFLOW); }
/** Registers TC callback function with the driver. */ static void configure_tc_callbacks(void) { tc_register_callback( &tc_instance, tc_callback_to_counter, TC_CALLBACK_OVERFLOW); tc_enable_callback(&tc_instance, TC_CALLBACK_OVERFLOW); }
void Adafruit_ZeroTimer::setCallback(boolean enable, tc_callback cb_type, tc_callback_t callback_func) { if (enable) { tc_register_callback(&tc_instance, callback_func, cb_type); tc_enable_callback(&tc_instance, cb_type); } else { tc_disable_callback(&tc_instance, cb_type); } }
/** * \internal * \brief Test the callback API * * This test tests the callback API for the TC. The TC uses one-shot mode. * * \param test Current test case. */ static void run_callback_test(const struct test_case *test) { test_assert_true(test, tc_init_success == true, "TC initialization failed, skipping test"); test_assert_true(test, basic_functionality_test_passed == true, "Basic functionality test failed, skipping test"); /* Setup TC0 */ tc_reset(&tc_test0_module); tc_get_config_defaults(&tc_test0_config); tc_test0_config.wave_generation = TC_WAVE_GENERATION_MATCH_PWM; tc_test0_config.counter_16_bit.compare_capture_channel\ [TC_COMPARE_CAPTURE_CHANNEL_0] = 0x03FF; tc_test0_config.counter_16_bit.compare_capture_channel\ [TC_COMPARE_CAPTURE_CHANNEL_1] = 0x03FA; tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config); /* Setup callbacks */ tc_register_callback(&tc_test0_module, tc_callback_function, TC_CALLBACK_CC_CHANNEL1); tc_enable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL1); tc_enable(&tc_test0_module); while ((tc_get_status(&tc_test0_module) & TC_STATUS_COUNT_OVERFLOW) == 0) { /* Wait for overflow of TC1*/ } tc_disable(&tc_test0_module); tc_clear_status(&tc_test0_module, TC_STATUS_COUNT_OVERFLOW); test_assert_true(test, callback_function_entered == 1, "The callback has failed callback_function_entered = %d", (int)callback_function_entered); /* Test disable callback function */ tc_disable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL1); tc_set_count_value(&tc_test0_module, 0x00000000); tc_enable(&tc_test0_module); while ((tc_get_status(&tc_test0_module) & TC_STATUS_COUNT_OVERFLOW) == 0) { /* Wait for overflow of TC1*/ } /* Test tc_disable() */ tc_disable(&tc_test0_module); test_assert_true(test, callback_function_entered == 1, "Disabling the callback has failed"); }
static void configure_tc3_callbacks(void) { //! [setup_register_callback] tc_register_callback(&tc3_instance,(tc_callback_t)_TC3_Handler,TC_CALLBACK_CC_CHANNEL0); //! [setup_register_callback] //! [setup_enable_callback] tc_enable_callback(&tc3_instance, TC_CALLBACK_CC_CHANNEL0); //! [setup_enable_callback] }
/** Callback run when a XOSC32K crystal failure is detected. * * \param[in] instance Timer instance that triggered the failure * (\ref CONF_TC_OSC32K) */ static void xosc32k_fail_callback( struct tc_module *instance) { /* Turn on the oscillator OK callback, turn off the fail callback */ tc_enable_callback(&tc_xosc32k, TC_CALLBACK_CC_CHANNEL0); tc_disable_callback(&tc_osc32k, TC_CALLBACK_CC_CHANNEL0); /* Crystal failed - switch DFLL to OSC32K */ init_dfll((enum system_clock_source)GCLK_GENERATOR_OSC32K); port_pin_set_output_level(LED_0_PIN, LED_0_INACTIVE); }
void configure_tc_callbacks(void) { //! [setup_register_callback] tc_register_callback( &tc_instance, tc_callback_to_change_duty_cycle, TC_CALLBACK_CC_CHANNEL0); //! [setup_register_callback] //! [setup_enable_callback] tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0); //! [setup_enable_callback] }
void sys_init_timing(void) { struct tc_config config_tc; tc_get_config_defaults(&config_tc); config_tc.counter_size = TC_COUNTER_SIZE_16BIT; config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ; config_tc.counter_16_bit.compare_capture_channel[0] = 0x5DC0; config_tc.clock_source = GCLK_GENERATOR_0; config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV2; tc_init(&tc_instance, TIMER, &config_tc); tc_enable(&tc_instance); tc_register_callback(&tc_instance, tc_callback, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0); /* Enable system interrupts. */ system_interrupt_enable_global(); }
void us_ticker_set_interrupt(timestamp_t timestamp) { uint32_t cur_time; int32_t delta; cur_time = us_ticker_read(); delta = (int32_t)((uint32_t)timestamp - cur_time); if (delta < 0) { /* Event already occurred in past */ us_ticker_irq_handler(); return; } NVIC_DisableIRQ(TICKER_COUNTER_IRQn); NVIC_SetVector(TICKER_COUNTER_IRQn, (uint32_t)TICKER_COUNTER_Handlr); /* Enable the callback */ tc_enable_callback(&us_ticker_module, TC_CALLBACK_CC_CHANNEL0); tc_set_compare_value(&us_ticker_module, TC_COMPARE_CAPTURE_CHANNEL_0, (uint32_t)timestamp); NVIC_EnableIRQ(TICKER_COUNTER_IRQn); }
/* * \brief Initialize and start timer for tick * * Function that sets up a timer to use for os tick. The same timer is also * used as the sleep timer. * The timer runs at 48MHz, i.e. with no prescaler on GCLK0. Wavegen function * Match Frequency is chosen to reload the count register on every CC0 match. * 8 bit counter mode must not be chosen. * The function is weakly defined in freeRTOS, and redefined here. */ void vPortSetupTimerInterrupt(void) { // Struct for configuring TC struct tc_config tcconf; // Set up configuration values tc_get_config_defaults(&tcconf); tcconf.counter_size = TC_COUNTER_SIZE_32BIT; tcconf.run_in_standby = true; tcconf.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; tcconf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ; // Initialize the TC tc_init(&tc, TICK_TC, &tcconf); // Register and enable callback for freeRTOS tick handler tc_register_callback(&tc, (tc_callback_t) xPortSysTickHandler, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); // Set top value equal to one os tick tc_set_top_value(&tc, TIMER_RELOAD_VALUE_ONE_TICK); // Enable the timer tc_enable(&tc); }
/** Initializes the XOSC32K crystal failure detector, and starts it. * * \param[in] ok_callback Callback function to run upon XOSC32K operational * \param[in] fail_callback Callback function to run upon XOSC32K failure */ static void init_xosc32k_fail_detector( const tc_callback_t ok_callback, const tc_callback_t fail_callback) { /* TC pairs share the same clock, ensure reference and crystal timers use * different clocks */ Assert(Abs(_tc_get_inst_index(CONF_TC_OSC32K) - _tc_get_inst_index(CONF_TC_XOSC32K)) >= 2); /* The crystal detection cycle count must be less than the reference cycle * count, so that the reference timer is periodically reset before expiry */ Assert(CRYSTAL_RESET_CYCLES < CRYSTAL_FAIL_CYCLES); /* Must use different clock generators for the crystal and reference, must * not be CPU generator 0 */ Assert(GCLK_GENERATOR_XOSC32K != GCLK_GENERATOR_OSC32K); Assert(GCLK_GENERATOR_XOSC32K != GCLK_GENERATOR_0); Assert(GCLK_GENERATOR_OSC32K != GCLK_GENERATOR_0); /* Configure and enable the XOSC32K GCLK generator */ struct system_gclk_gen_config xosc32k_gen_conf; system_gclk_gen_get_config_defaults(&xosc32k_gen_conf); xosc32k_gen_conf.source_clock = SYSTEM_CLOCK_SOURCE_XOSC32K; system_gclk_gen_set_config(GCLK_GENERATOR_XOSC32K, &xosc32k_gen_conf); system_gclk_gen_enable(GCLK_GENERATOR_XOSC32K); /* Configure and enable the reference clock GCLK generator */ struct system_gclk_gen_config ref_gen_conf; system_gclk_gen_get_config_defaults(&ref_gen_conf); ref_gen_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC32K; system_gclk_gen_set_config(GCLK_GENERATOR_OSC32K, &ref_gen_conf); system_gclk_gen_enable(GCLK_GENERATOR_OSC32K); /* Set up crystal counter - when target count elapses, trigger event */ struct tc_config tc_xosc32k_conf; tc_get_config_defaults(&tc_xosc32k_conf); tc_xosc32k_conf.clock_source = GCLK_GENERATOR_XOSC32K; tc_xosc32k_conf.counter_16_bit.compare_capture_channel[0] = CRYSTAL_RESET_CYCLES; tc_xosc32k_conf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ; tc_init(&tc_xosc32k, CONF_TC_XOSC32K, &tc_xosc32k_conf); /* Set up reference counter - when event received, restart */ struct tc_config tc_osc32k_conf; tc_get_config_defaults(&tc_osc32k_conf); tc_osc32k_conf.clock_source = GCLK_GENERATOR_OSC32K; tc_osc32k_conf.counter_16_bit.compare_capture_channel[0] = CRYSTAL_FAIL_CYCLES; tc_osc32k_conf.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ; tc_init(&tc_osc32k, CONF_TC_OSC32K, &tc_osc32k_conf); /* Configure event channel and link it to the xosc32k counter */ struct events_config config; struct events_resource event; events_get_config_defaults(&config); config.edge_detect = EVENTS_EDGE_DETECT_NONE; config.generator = CONF_EVENT_GENERATOR_ID; config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event, &config); /* Configure event user and link it to the osc32k counter */ events_attach_user(&event, CONF_EVENT_USED_ID); /* Enable event generation for crystal counter */ struct tc_events tc_xosc32k_events = { .generate_event_on_overflow = true }; tc_enable_events(&tc_xosc32k, &tc_xosc32k_events); /* Enable event reception for reference counter */ struct tc_events tc_osc32k_events = { .on_event_perform_action = true }; tc_osc32k_events.event_action = TC_EVENT_ACTION_RETRIGGER; tc_enable_events(&tc_osc32k, &tc_osc32k_events); /* Enable overflow callback for the crystal counter - if crystal count * has been reached, crystal is operational */ tc_register_callback(&tc_xosc32k, ok_callback, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc_xosc32k, TC_CALLBACK_CC_CHANNEL0); /* Enable compare callback for the reference counter - if reference count * has been reached, crystal has failed */ tc_register_callback(&tc_osc32k, fail_callback, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc_osc32k, TC_CALLBACK_CC_CHANNEL0); /* Start both crystal and reference counters */ tc_enable(&tc_xosc32k); tc_enable(&tc_osc32k); } /** Main application entry point. */ int main(void) { system_init(); system_flash_set_waitstates(2); init_osc32k(); init_xosc32k(); init_xosc32k_fail_detector( xosc32k_ok_callback, xosc32k_fail_callback); #if ENABLE_CPU_CLOCK_OUT == true /* Configure a GPIO pin as the CPU clock output */ struct system_pinmux_config clk_out_pin; system_pinmux_get_config_defaults(&clk_out_pin); clk_out_pin.direction = SYSTEM_PINMUX_PIN_DIR_OUTPUT; clk_out_pin.mux_position = CONF_CLOCK_PIN_MUX; system_pinmux_pin_set_config(CONF_CLOCK_PIN_OUT, &clk_out_pin); #endif for (;;) { static bool old_run_osc = true; bool new_run_osc = (port_pin_get_input_level(BUTTON_0_PIN) == BUTTON_0_INACTIVE); /* Check if the XOSC32K needs to be started or stopped when the board * button is pressed or released */ if (new_run_osc != old_run_osc) { if (new_run_osc) { system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K); while(!system_clock_source_is_ready( SYSTEM_CLOCK_SOURCE_XOSC32K)); } else { system_clock_source_disable(SYSTEM_CLOCK_SOURCE_XOSC32K); } old_run_osc = new_run_osc; } } }
/*! * @brief Configures TC6 callback register * * @param[in] NULL * * @param[out] NULL * * @return NULL * */ void tc6_configure_callbacks(void) { tc_register_callback(&tc6_instance, tc6_callback, TC_CALLBACK_OVERFLOW); //tc6_callback_flag = false; tc_enable_callback(&tc6_instance, TC_CALLBACK_OVERFLOW); }
/** * \internal * \brief Test capture and compare * * This test uses TC module 0 as a PWM generator (compare function). * TC module 1 will be set to capture the signal from TC module 0 to test the capture * functionality. * * \param test Current test case. */ static void run_16bit_capture_and_compare_test(const struct test_case *test) { test_assert_true(test, tc_init_success == true, "TC initialization failed, skipping test"); test_assert_true(test, callback_function_entered == 1, "The callback test has failed, skipping test"); /* Configure 16-bit TC module for PWM generation */ tc_reset(&tc_test0_module); tc_get_config_defaults(&tc_test0_config); tc_test0_config.wave_generation = TC_WAVE_GENERATION_MATCH_PWM; tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0] = 0x03FF; tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1] = 0x01FF; /* Calculate the theoretical PWM frequency & duty */ uint32_t frequency_output, duty_output; frequency_output = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ (0x03FF+1); /* This value is depend on the WaveGeneration Mode */ duty_output = (uint32_t)(tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_1]) * 100 \ / tc_test0_config.counter_16_bit.compare_capture_channel[TC_COMPARE_CAPTURE_CHANNEL_0]; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].enabled = true; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_out = CONF_TEST_PIN_OUT; tc_test0_config.pwm_channel[TC_COMPARE_CAPTURE_CHANNEL_1].pin_mux = CONF_TEST_PIN_MUX; tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config); tc_register_callback(&tc_test0_module, tc_callback_function, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc_test0_module, TC_CALLBACK_CC_CHANNEL0); /* Configure 16-bit TC module for capture */ tc_reset(&tc_test1_module); tc_get_config_defaults(&tc_test1_config); tc_test1_config.clock_prescaler = TC_CLOCK_PRESCALER_DIV1; tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_0] = true; tc_test1_config.enable_capture_on_channel[CONF_CAPTURE_CHAN_1] = true; tc_init(&tc_test1_module, CONF_TEST_TC1, &tc_test1_config); struct tc_events tc_events = { .on_event_perform_action = true, .event_action = TC_EVENT_ACTION_PPW,}; tc_enable_events(&tc_test1_module, &tc_events); /* Configure external interrupt controller */ struct extint_chan_conf extint_chan_config; extint_chan_config.gpio_pin = CONF_EIC_PIN; extint_chan_config.gpio_pin_mux = CONF_EIC_MUX; extint_chan_config.gpio_pin_pull = EXTINT_PULL_UP; extint_chan_config.wake_if_sleeping = false; extint_chan_config.filter_input_signal = false; extint_chan_config.detection_criteria = EXTINT_DETECT_HIGH; extint_chan_set_config(0, &extint_chan_config); /* Configure external interrupt module to be event generator */ struct extint_events extint_event_conf; extint_event_conf.generate_event_on_detect[0] = true; extint_enable_events(&extint_event_conf); /* Configure event system */ struct events_resource event_res; /* Configure channel */ struct events_config config; events_get_config_defaults(&config); config.generator = CONF_EVENT_GENERATOR_ID; config.edge_detect = EVENTS_EDGE_DETECT_NONE; config.path = EVENTS_PATH_ASYNCHRONOUS; events_allocate(&event_res, &config); /* Configure user */ events_attach_user(&event_res, CONF_EVENT_USED_ID); /* Enable TC modules */ tc_enable(&tc_test1_module); tc_enable(&tc_test0_module); uint16_t period_after_capture = 0; uint16_t pulse_width_after_capture = 0; uint32_t capture_frequency = 0; uint32_t capture_duty = 0; while (callback_function_entered < 4) { period_after_capture = tc_get_capture_value(&tc_test1_module, TC_COMPARE_CAPTURE_CHANNEL_0); pulse_width_after_capture = tc_get_capture_value(&tc_test1_module, TC_COMPARE_CAPTURE_CHANNEL_1); } if(period_after_capture != 0) { capture_frequency = system_clock_source_get_hz(SYSTEM_CLOCK_SOURCE_OSC8M)/ period_after_capture; capture_duty = (uint32_t)(pulse_width_after_capture) * 100 / period_after_capture; } test_assert_true(test, (capture_frequency <= (frequency_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_frequency >= (frequency_output * (100 - CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty <= (duty_output * (100 + CONF_TEST_TOLERANCE) / 100)) && \ (capture_duty >= (duty_output * (100 - CONF_TEST_TOLERANCE) / 100)) \ ,"The result of Capture is wrong, captured frequency: %ldHz, captured duty: %ld%%", capture_frequency, capture_duty ); } /** * \brief Initialize the USART for unit test * * Initializes the SERCOM USART used for sending the unit test status to the * computer via the EDBG CDC gateway. */ static void cdc_uart_init(void) { struct usart_config usart_conf; /* Configure USART for unit test output */ usart_get_config_defaults(&usart_conf); usart_conf.mux_setting = CONF_STDIO_MUX_SETTING; usart_conf.pinmux_pad0 = CONF_STDIO_PINMUX_PAD0; usart_conf.pinmux_pad1 = CONF_STDIO_PINMUX_PAD1; usart_conf.pinmux_pad2 = CONF_STDIO_PINMUX_PAD2; usart_conf.pinmux_pad3 = CONF_STDIO_PINMUX_PAD3; usart_conf.baudrate = CONF_STDIO_BAUDRATE; stdio_serial_init(&cdc_uart_module, CONF_STDIO_USART, &usart_conf); usart_enable(&cdc_uart_module); } /** * \brief Run TC unit tests * * Initializes the system and serial output, then sets up the TC unit test * suite and runs it. */ int main(void) { system_init(); cdc_uart_init(); /* Define Test Cases */ DEFINE_TEST_CASE(init_test, NULL, run_init_test, NULL, "Initialize tc_xmodules"); DEFINE_TEST_CASE(basic_functionality_test, NULL, run_basic_functionality_test, NULL, "test start stop and getters and setters"); DEFINE_TEST_CASE(callback_test, NULL, run_callback_test, NULL, "test callback API"); DEFINE_TEST_CASE(reset_32bit_master_test, NULL, run_reset_32bit_master_test, NULL, "Setup, reset and reinitialize TC modules of a 32-bit TC"); DEFINE_TEST_CASE(capture_and_compare_test, NULL, run_16bit_capture_and_compare_test, NULL, "Test capture and compare"); /* Put test case addresses in an array */ DEFINE_TEST_ARRAY(tc_tests) = { &init_test, &basic_functionality_test, &callback_test, &reset_32bit_master_test, &capture_and_compare_test, }; /* Define the test suite */ DEFINE_TEST_SUITE(tc_suite, tc_tests, "SAM TC driver test suite"); /* Run all tests in the suite*/ test_suite_run(&tc_suite); tc_reset(&tc_test0_module); tc_reset(&tc_test1_module); while (true) { /* Intentionally left empty */ } }
/*! \brief to enable compare interrupt */ void tmr_enable_cc_interrupt(void) { tc_enable_callback(&module_inst, TC_CALLBACK_CC_CHANNEL0); }
/*! \brief to disable overflow interrupt */ void tmr_enable_ovf_interrupt(void) { tc_enable_callback(&module_inst, TC_CALLBACK_OVERFLOW); }
/*! * @brief Configures TC4 callback register * * @param[in] NULL * * @param[out] NULL * * @return NULL * */ void tc4_configure_callbacks (void) { tc_register_callback(&tc4_instance, tc4_callback, TC_CALLBACK_CC_CHANNEL0); tc4_callback_flag = false; tc_enable_callback(&tc4_instance, TC_CALLBACK_CC_CHANNEL0); }
void hw_timer_start(uint32_t timer_val) { timeout_count = timer_val; tc_set_count_value(&tc_instance, 0); tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0); }
/* * \brief Configure sleep timer and sleep * * Function to configure timer for sleep, and calculate time slept. */ void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) { // Are we running tickless now? if (!tickless_enable) return; // Reconfigure the timer to act as sleep timer tc_disable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_unregister_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_register_callback(&tc, empty_callback, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); // Check that the offset is not greater than the range of the timer if (xExpectedIdleTime > TIMER_MAX_POSSIBLE_SUPPRESSED_TICKS) { xExpectedIdleTime = TIMER_MAX_POSSIBLE_SUPPRESSED_TICKS; } // Set sleep time, -1 because we want to wake up before the last tick tc_set_top_value(&tc, (xExpectedIdleTime - 1) * TIMER_RELOAD_VALUE_ONE_TICK); // Clear overflow interrupt flag tc.hw->COUNT32.INTFLAG.bit.OVF = 1; // Check if we still should sleep if (eTaskConfirmSleepModeStatus() == eAbortSleep) { // Reset the timer to act as SysTick tc_disable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_unregister_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_register_callback(&tc, (tc_callback_t) xPortSysTickHandler, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_set_top_value(&tc, TIMER_RELOAD_VALUE_ONE_TICK); } else { if (xExpectedIdleTime > 0) { // Data sync barrier before sleep __asm volatile ("dsb"); // Go to sleep __asm volatile ("wfi"); // If OVF interrupt flag is set, we know the timer has wrapped if (tc.hw->COUNT32.INTFLAG.bit.OVF) { vTaskStepTick(xExpectedIdleTime - 1); } // We do not know how long we've slept else { // Calculate from Counter how long we've slept // Reset counter to less than one os tick // This might result in a tiny drift in time. uint32_t count_val = tc_get_count_value(&tc); vTaskStepTick(count_val / TIMER_RELOAD_VALUE_ONE_TICK); tc_set_count_value(&tc, count_val % TIMER_RELOAD_VALUE_ONE_TICK); } } // Reset the timer to act as SysTick tc_disable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_unregister_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_register_callback(&tc, (tc_callback_t) xPortSysTickHandler, TC_CALLBACK_CC_CHANNEL0); tc_enable_callback(&tc, TC_CALLBACK_CC_CHANNEL0); tc_set_top_value(&tc, TIMER_RELOAD_VALUE_ONE_TICK); // Make sure that the counter hasn't passed the CC before callback was registered if ( tc_get_count_value(&tc) > TIMER_RELOAD_VALUE_ONE_TICK ) { // If so, reload count value, and step one tick */ tc_set_count_value(&tc, tc_get_count_value(&tc) % TIMER_RELOAD_VALUE_ONE_TICK); vTaskStepTick(1); } }