uint32_t us_ticker_read()
{
    if (!us_ticker_inited)
        us_ticker_init();

    return tc_get_count_value(&us_ticker_module);
}
unsigned long millis(void)
{
	system_interrupt_disable_global();
	uint32_t tc_count = tc_get_count_value(&tc6_instance);
	system_interrupt_enable_global();
	return (((tc6_overflows<<16)+tc_count)*(1/8000.0));
}
Beispiel #3
0
/**
 * \internal
 * \brief Test for event system in asynchronous mode.
 *
 * This test waits for event channel and user to be ready and then
 * starts the RTC to generate overflow event. It waits until the timer
 * is started. If the timer starts running then it can be assumed that
 * the event has been propagated properly.
 *
 * \param test Current test case.
 */
static void run_asynchronous_event_test(const struct test_case *test)
{
	uint32_t timeout_cycles;

	/* Skip test if initialization failed */
	test_assert_true(test, init_success,
			"Skipping test due to failed initialization");

	/* Event action test */
	rtc_count_enable(&rtc_inst);
	rtc_count_set_period(&rtc_inst, 100);
	timeout_cycles = 10000;

	do {

		timeout_cycles--;
		if (tc_get_count_value(&tc_inst)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Error: Timeout in event reception/action");
}
Beispiel #4
0
/**
 * \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;
}
Beispiel #5
0
/**
 * \internal
 * \brief Test for event system in resynchronous mode.
 *
 * This test waits for event channel and user to be ready and then
 * starts the RTC to generate overflow event. It waits until the timer
 * is started. If the timer starts running then it can be assumed that
 * the event has been propagated properly.
 *
 * \param test Current test case.
 */
static void run_resynchronous_event_test(const struct test_case *test)
{
	uint32_t timeout_cycles = 1000;

	/* Skip test if initialization failed */
	test_assert_true(test, init_success,
			"Skipping test due to failed initialization");

	/* Check whether event user is ready */
	do {
		timeout_cycles--;
		if (events_is_users_ready(&events)) {
			break;
		}
	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event user not ready");

	/* Check whether event channel is ready */
	timeout_cycles = 1000;
	do {
		timeout_cycles--;
		if (!events_is_busy(&events)) {
			break;
		}
	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event channel not ready");

	/* Event action test */
	rtc_count_enable(&rtc_inst);
	rtc_count_set_period(&rtc_inst, 100);
	timeout_cycles = 10000;

	do {
		timeout_cycles--;
		if (tc_get_count_value(&tc_inst)) {
			break;
		}
	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Error: Timeout in event reception/action");
}
Beispiel #6
0
/**
 * \brief Initialize the TC3 & RTC for unit test
 *
 * Initializes the RTC module and TC3 module which are used as
 * event generator and event user respectively.
 */
static void test_event_gen_user_init(void)
{
	enum status_code status;
	init_success = true;

	/* Timer configuration (Event User) */
	struct tc_config config_tc;

	tc_get_config_defaults(&config_tc);
	config_tc.counter_16_bit.compare_capture_channel[0]
		= (0xFFFF / 4);

	/* Initialize the TC3 */
	status = tc_init(&tc_inst, TC3, &config_tc);
	if (status != STATUS_OK) {
		init_success = false;
	}

	struct tc_events events_tc;

	events_tc.on_event_perform_action = true;
	events_tc.event_action = TC_EVENT_ACTION_START;

	tc_enable_events(&tc_inst, &events_tc);

	/* Enable the TC3 */
	tc_enable(&tc_inst);

	/* RTC configuration (Event Generator) */
	struct rtc_count_config config_rtc_count;
	struct rtc_count_events config_rtc_event
		= { .generate_event_on_overflow = true };

	/* Initialize the RTC module */
	rtc_count_get_config_defaults(&config_rtc_count);
	config_rtc_count.prescaler           = RTC_COUNT_PRESCALER_DIV_1;
	config_rtc_count.mode                = RTC_COUNT_MODE_16BIT;
#ifdef FEATURE_RTC_CONTINUOUSLY_UPDATED
	config_rtc_count.continuously_update = true;
#endif
	config_rtc_count.compare_values[0]   = 50;
	status = rtc_count_init(&rtc_inst, RTC, &config_rtc_count);

	if (status != STATUS_OK) {
		init_success = false;
	}

	/* Enable RTC events */
	config_rtc_event.generate_event_on_overflow = true;
	rtc_count_enable_events(&rtc_inst, &config_rtc_event);
}

/**
 * \internal
 * \brief Setup Function: Synchronous event propagation.
 *
 * This function initializes the event system channel 0 and the RTC
 * module (event generator) to be in the same clock domain for
 * synchronous event propagation.
 *
 * \param test Current test case.
 */
static void setup_synchronous_event_test(const struct test_case *test)
{
	struct events_config   events_conf;

	/* Get default event channel configuration */
	events_get_config_defaults(&events_conf);

	events_conf.clock_source   = GCLK_GENERATOR_2;
	events_conf.edge_detect    = EVENTS_EDGE_DETECT_RISING;
	events_conf.path           = EVENTS_PATH_SYNCHRONOUS;
	events_conf.generator      = TEST_EVENT_GEN;

	events_allocate(&events, &events_conf);
	events_attach_user(&events, TEST_EVENT_USER);
}

/**
 * \internal
 * \brief Test for event system in synchronous mode.
 *
 * This test waits for event channel and user to be ready and then
 * starts the RTC to generate overflow event. It waits until the timer
 * is started. If the timer starts running then it can be assumed that
 * the event has been propagated properly.
 *
 * \param test Current test case.
 */
static void run_synchronous_event_test(const struct test_case *test)
{
	uint32_t timeout_cycles = 1000;

	/* Skip test if initialization failed */
	test_assert_true(test, init_success,
			"Skipping test due to failed initialization");

	/* Check whether event user is ready */
	do {

		timeout_cycles--;
		if (events_is_users_ready(&events)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event user not ready");

	/* Check whether event channel is ready */
	timeout_cycles = 1000;
	do {

		timeout_cycles--;
		if (!events_is_busy(&events)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Timeout error: Event channel not ready");

	/* Event action test */
	rtc_count_enable(&rtc_inst);
	rtc_count_set_period(&rtc_inst, 100);
	timeout_cycles = 10000;

	do {

		timeout_cycles--;
		if (tc_get_count_value(&tc_inst)) {
			break;
		}

	} while (timeout_cycles > 0);

	test_assert_true(test, timeout_cycles > 0,
			"Error: Timeout in event reception/action");
}
Beispiel #7
0
/*! \brief  read the actual timer count from register
 */
uint16_t tmr_read_count(void)
{
	return ((uint16_t)tc_get_count_value(&module_inst));
}
/*
 * \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);
		}
	}