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; }
/** * \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"); }
/** TC Callback function. */ static void tc_callback_to_counter( struct tc_module *const module_inst) { static uint32_t count = 0; count ++; if(count%800 == 0){ printf("The output is triggered by TC counter\r\n"); } tc_set_count_value(module_inst,TC_COUNT_VALUE); }
void tc_cc0_cb(struct tc_module *const module_inst) { static uint16_t tc_count; tc_set_count_value(&tc_instance, 0); tc_count += 1; if (tc_count >= timeout_count) { tc_count = 0; if (timer_callback != NULL) { timer_callback(); } } }
/** * \internal * \brief Test basic functionality. * * This test tests the basic functionality for the TC. It tests the following functions: * - tc_get_count_value() * - tc_stop_counter() * - tc_set_count_value() * - tc_start_counter() * * \param test Current test case. */ static void run_basic_functionality_test(const struct test_case *test) { test_assert_true(test, tc_init_success == true, "TC initialization failed, skipping test"); /* Setup TC0 */ tc_reset(&tc_test0_module); tc_get_config_defaults(&tc_test0_config); tc_init(&tc_test0_module, CONF_TEST_TC0, &tc_test0_config); tc_enable(&tc_test0_module); /* Test tc_get_count_value() */ uint32_t test_val0 = tc_get_count_value(&tc_test0_module); test_assert_true(test, test_val0 > 0, "The tc_get_count_value() returned 0 expected larger value"); /* Test tc_stop_counter() */ tc_stop_counter(&tc_test0_module); uint32_t test_val1 = tc_get_count_value(&tc_test0_module); uint32_t test_val2 = tc_get_count_value(&tc_test0_module); test_assert_true(test, test_val1 == test_val2, "The counter failed to stop"); /* Test tc_set_count_value() */ tc_set_count_value(&tc_test0_module, 0x00FF); test_assert_true(test, tc_get_count_value(&tc_test0_module) == 0x00FF, "tc_set_count_value() have failed"); /* Test tc_start_counter() */ tc_start_counter(&tc_test0_module); test_assert_true(test, tc_get_count_value(&tc_test0_module) > 0x00FF, "tc_get_count_value() have failed"); basic_functionality_test_passed = true; }
void platform_start_bus_timer(void *timer_handle, uint32_t ms) { tc_set_count_value(&bus_tc_instance, (0xFFFFFFFF - (timer_count_per_ms * ms))); tc_start_counter(&bus_tc_instance); }
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); } }
/*! * @brief Starts TC6 counter * * @param[in] NULL * * @param[out] NULL * * @return NULL * */ void tc6_start_counter (void) { tc_set_count_value(&tc6_instance, TC6_COUNT_VALUE); tc_start_counter(&tc6_instance); }