Пример #1
0
/**
 * \brief Set the given value to the period.
 *
 * Sets the given value to the period.
 *
 * \note Only available in 16-bit mode.
 *
 * \param[in,out] module  Pointer to the software instance struct
 * \param[in] period_value  The value to set to the period
 *
 * \return Status of setting the period value.
 * \retval STATUS_OK                   If the period was set correctly
 * \retval STATUS_ERR_UNSUPPORTED_DEV  If module is not operated in 16-bit mode
 */
enum status_code rtc_count_set_period(
		struct rtc_module *const module,
		const uint16_t period_value)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Check that correct mode is set. */
	if (module->mode != RTC_COUNT_MODE_16BIT) {
		return STATUS_ERR_UNSUPPORTED_DEV;
	}

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Write value to register. */
	rtc_module->MODE1.PER.reg = period_value;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	return STATUS_OK;
}
Пример #2
0
/**
 * \brief Resets the RTC module.
 * Resets the RTC to hardware defaults.
 *
 * \param[in,out]  module  Pointer to the software instance struct
 */
void rtc_count_reset(struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Disable module before reset. */
	rtc_count_disable(module);

#if RTC_COUNT_ASYNC == true
	module->registered_callback = 0;
	module->enabled_callback    = 0;
#endif

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Initiate software reset. */
	rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_SWRST;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}
}
Пример #3
0
/**
 * \brief Set the compare value for the specified compare.
 *
 * Sets the value specified by the implementer to the requested compare.
 *
 * \note Compare 4 and 5 are only available in 16-bit mode.
 *
 * \param[in,out] module  Pointer to the software instance struct
 * \param[in] comp_value  The value to be written to the compare
 * \param[in] comp_index  Index of the compare to set
 *
 * \return Status indicating if compare was successfully set.
 * \retval STATUS_OK               If compare was successfully set
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
 * \retval STATUS_ERR_BAD_FORMAT   If the module was not initialized in a mode
 */
enum status_code rtc_count_set_compare(
		struct rtc_module *const module,
		const uint32_t comp_value,
		const enum rtc_count_compare comp_index)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Set compare values based on operation mode. */
	switch (module->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Check sanity of comp_index. */
			if ((uint32_t)comp_index > RTC_COMP32_NUM) {
				return STATUS_ERR_INVALID_ARG;
			}

			/* Set compare value for COMP. */
			rtc_module->MODE0.COMP[comp_index].reg = comp_value;

			break;

		case RTC_COUNT_MODE_16BIT:
			/* Check sanity of comp_index. */
			if ((uint32_t)comp_index > RTC_NUM_OF_COMP16) {
				return STATUS_ERR_INVALID_ARG;
			}

			/* Check that 16-bit value is provided. */
			if (comp_value > 0xffff) {
				Assert(false);
				return STATUS_ERR_INVALID_ARG;
			}

			/* Set compare value for COMP. */
			rtc_module->MODE1.COMP[comp_index].reg = comp_value & 0xffff;

			break;

		default:
			Assert(false);
			return STATUS_ERR_BAD_FORMAT;
	}

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Return status if everything is OK. */
	return STATUS_OK;
}
Пример #4
0
/**
 * \brief Get the current count value.
 *
 * \param[in,out] module  Pointer to the software instance struct
 *
 * Returns the current count value.
 *
 * \return The current counter value as a 32-bit unsigned integer.
 */
uint32_t rtc_count_get_count(struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Initialize return value. */
	uint32_t ret_val;

	/* Change of read method based on value of continuously_update value in
	 * the configuration structure. */
	if(!(module->continuously_update)) {
		/* Request read on count register. */
		rtc_module->MODE0.READREQ.reg = RTC_READREQ_RREQ;

		while (rtc_count_is_syncing(module)) {
			/* Wait for synchronization */
		}
	} else if (!(rtc_module->MODE0.READREQ.reg & RTC_READREQ_RCONT)){
		while (rtc_count_is_syncing(module)) { // a write synchronization may be running
			/* Wait for synchronization */
		}
		rtc_module->MODE0.READREQ.reg |= RTC_READREQ_RCONT | RTC_READREQ_RREQ;
		 /* wait that the first Read request finishes */
		while (rtc_count_is_syncing(module)) {
			/* Wait for synchronization */
		}
	}

	/* Read value based on mode. */
	switch (module->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Return count value in 32-bit mode. */
			ret_val = rtc_module->MODE0.COUNT.reg;

			break;

		case RTC_COUNT_MODE_16BIT:
			/* Return count value in 16-bit mode. */
			ret_val = (uint32_t)rtc_module->MODE1.COUNT.reg;

			break;

		default:
			Assert(false);
			/* Counter not initialized. Assume counter value 0.*/
			ret_val = 0;
			break;
	}

	return ret_val;
}
Пример #5
0
/**
 * \brief Calibrate for too-slow or too-fast oscillator.
 *
 * When used, the RTC will compensate for an inaccurate oscillator. The
 * RTC module will add or subtract cycles from the RTC prescaler to adjust the
 * frequency in approximately 1 PPM steps. The provided correction value should
 * be between 0 and 127, allowing for a maximum 127 PPM correction.
 *
 * If no correction is needed, set value to zero.
 *
 * \note Can only be used when the RTC is operated in 1Hz.
 *
 * \param[in,out] module  Pointer to the software instance struct
 * \param[in] value  Ranging from -127 to 127 used for the correction
 *
 * \return Status of the calibration procedure.
 * \retval STATUS_OK               If calibration was executed correctly
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
 */
enum status_code rtc_count_frequency_correction(
		struct rtc_module *const module,
		const int8_t value)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Check if valid argument. */
	if (abs(value) > 0x7F) {
		/* Value bigger than allowed, return invalid argument. */
		return STATUS_ERR_INVALID_ARG;
	}

	uint32_t new_correction_value;

	/* Load the new correction value as a positive value, sign added later */
	new_correction_value = abs(value);

	/* Convert to positive value and adjust register sign bit. */
	if (value < 0) {
		new_correction_value |= RTC_FREQCORR_SIGN;
	}

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Set value. */
	rtc_module->MODE0.FREQCORR.reg = new_correction_value;

	return STATUS_OK;
}
Пример #6
0
/**
 * \brief Set the current count value to desired value.
 *
 * Sets the value of the counter to the specified value.
 *
 * \param[in,out] module  Pointer to the software instance struct
 * \param[in] count_value  The value to be set in count register
 *
 * \return Status of setting the register.
 * \retval STATUS_OK               If everything was executed correctly
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
 */
enum status_code rtc_count_set_count(
		struct rtc_module *const module,
		const uint32_t count_value)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Set count according to mode */
	switch(module->mode){
		case RTC_COUNT_MODE_32BIT:
			/* Write value to register. */
			rtc_module->MODE0.COUNT.reg = count_value;
			break;
		case RTC_COUNT_MODE_16BIT:
			/* Check if 16-bit value is provided. */
			if(count_value > 0xffff){
				return STATUS_ERR_INVALID_ARG;
			}

			/* Write value to register. */
			rtc_module->MODE1.COUNT.reg = (uint32_t)count_value;

			break;

		default:
			Assert(false);
			return STATUS_ERR_INVALID_ARG;
	}

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}
	return STATUS_OK;
}
Пример #7
0
/**
 * \brief Enables the RTC module.
 *
 * Enables the RTC module once it has been configured, ready for use. Most
 * module configuration parameters cannot be altered while the module is enabled.
 *
 * \param[in,out]  module  RTC hardware module
 */
void rtc_count_enable(struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

#if RTC_COUNT_ASYNC == true
	system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_RTC);
#endif

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Enable RTC module. */
	rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_ENABLE;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}
}
Пример #8
0
/**
 * \brief Get the current compare value of specified compare.
 *
 * Retrieves the current value of the specified compare.
 *
 * \note Compare 4 and 5 are only available in 16-bit mode.
 *
 * \param[in,out] module  Pointer to the software instance struct
 * \param[out] comp_value  Pointer to 32-bit integer that will be populated with
 *                         the current compare value
 * \param[in]  comp_index  Index of compare to check
 *
 * \return Status of the reading procedure.
 * \retval STATUS_OK               If the value was read correctly
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were provided
 * \retval STATUS_ERR_BAD_FORMAT   If the module was not initialized in a mode
 */
enum status_code rtc_count_get_compare(
		struct rtc_module *const module,
		uint32_t *const comp_value,
		const enum rtc_count_compare comp_index)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	switch (module->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Check sanity of comp_index. */
			if ((uint32_t)comp_index > RTC_COMP32_NUM) {
				return STATUS_ERR_INVALID_ARG;
			}

			/* Get compare value for COMP. */
			*comp_value = rtc_module->MODE0.COMP[comp_index].reg;

			break;

		case RTC_COUNT_MODE_16BIT:
			/* Check sanity of comp_index. */
			if ((uint32_t)comp_index > RTC_NUM_OF_COMP16) {
				return STATUS_ERR_INVALID_ARG;
			}

			/* Get compare value for COMP. */
			*comp_value = (uint32_t)rtc_module->MODE1.COMP[comp_index].reg;

			break;

		default:
			Assert(false);
			return STATUS_ERR_BAD_FORMAT;
	}
	/* Return status showing everything is OK. */
	return STATUS_OK;
}
Пример #9
0
/**
 * \brief Get the current count value.
 *
 * \param[in,out] module  Pointer to the software instance struct
 *
 * Returns the current count value.
 *
 * \return The current counter value as a 32-bit unsigned integer.
 */
uint32_t rtc_count_get_count(struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Initialize return value. */
	uint32_t ret_val;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Read value based on mode. */
	switch (module->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Return count value in 32-bit mode. */
			ret_val = rtc_module->MODE0.COUNT.reg;

			break;

		case RTC_COUNT_MODE_16BIT:
			/* Return count value in 16-bit mode. */
			ret_val = (uint32_t)rtc_module->MODE1.COUNT.reg;

			break;

		default:
			Assert(false);
			/* Counter not initialized. Assume counter value 0.*/
			ret_val = 0;
			break;
	}

	return ret_val;
}
Пример #10
0
/**
 * \brief Disables the RTC module.
 *
 * Disables the RTC module.
 *
 * \param[in,out]  module  RTC hardware module
 */
void rtc_count_disable(struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

#if RTC_COUNT_ASYNC == true
	system_interrupt_disable(SYSTEM_INTERRUPT_MODULE_RTC);
#endif

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Disbale interrupt */
	rtc_module->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_MASK;
	/* Clear interrupt flag */
	rtc_module->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_MASK;

	/* Disable RTC module. */
	rtc_module->MODE0.CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE;
}
Пример #11
0
/**
 * \brief Get the tamper stamp value.
 *
 * \param[in,out] module  Pointer to the software instance struct
 *
 * \return The current tamper stamp value as a 32-bit unsigned integer.
 */
uint32_t rtc_tamper_get_stamp (struct rtc_module *const module)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	/* Initialize return value. */
	uint32_t tamper_stamp = 0;

	while (rtc_count_is_syncing(module)) {
		/* Wait for synchronization */
	}

	/* Read value based on mode. */
	switch (module->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Return stamp value in 32-bit mode. */
			tamper_stamp = rtc_module->MODE0.TIMESTAMP.reg;

			break;

		case RTC_COUNT_MODE_16BIT:
			/* Return stamp value in 16-bit mode. */
			tamper_stamp = (uint32_t)rtc_module->MODE1.TIMESTAMP.reg;

			break;

		default:
			Assert(false);
			break;
	}

	return tamper_stamp;
}
Пример #12
0
/**
 * \internal Applies the given configuration.
 *
 * Sets the configurations given from the configuration structure to the
 * hardware module.
 *
 * \param[in,out]  module  Pointer to the software instance struct
 * \param[in] config  Pointer to the configuration structure.
 *
 * \return Status of the configuration procedure.
 * \retval STATUS_OK               RTC configurations was set successfully.
 * \retval STATUS_ERR_INVALID_ARG  If invalid argument(s) were given.
 */
static enum status_code _rtc_count_set_config(
		struct rtc_module *const module,
		const struct rtc_count_config *const config)
{
	/* Sanity check arguments */
	Assert(module);
	Assert(module->hw);

	Rtc *const rtc_module = module->hw;

	rtc_module->MODE0.CTRL.reg = RTC_MODE0_CTRL_MODE(0) | config->prescaler;

	/* Set mode and clear on match if applicable. */
	switch (config->mode) {
		case RTC_COUNT_MODE_32BIT:
			/* Set 32bit mode and clear on match if applicable. */
			rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_MODE(0);

			/* Check if clear on compare match should be set. */
			if (config->clear_on_match) {
				/* Set clear on match. */
				rtc_module->MODE0.CTRL.reg |= RTC_MODE0_CTRL_MATCHCLR;
			}
			/* Set compare values. */
			for (uint8_t i = 0; i < RTC_NUM_OF_COMP32; i++) {
				while (rtc_count_is_syncing(module)) {
					/* Wait for synchronization */
				}

				rtc_count_set_compare(module, config->compare_values[i],
						(enum rtc_count_compare)i);
			}
			break;

		case RTC_COUNT_MODE_16BIT:
			/* Set 16bit mode. */
			rtc_module->MODE1.CTRL.reg |= RTC_MODE1_CTRL_MODE(1);

			/* Check if match on clear is set, and return invalid
			 * argument if set. */
			if (config->clear_on_match) {
				Assert(false);
				return STATUS_ERR_INVALID_ARG;
			}
			/* Set compare values. */
			for (uint8_t i = 0; i < RTC_NUM_OF_COMP16; i++) {
				while (rtc_count_is_syncing(module)) {
					/* Wait for synchronization */
				}

				rtc_count_set_compare(module, config->compare_values[i],
						(enum rtc_count_compare)i);
			}
			break;
		default:
			Assert(false);
			return STATUS_ERR_INVALID_ARG;
	}

	/* Check to set continuously clock read update mode. */
	if (config->continuously_update) {
		/* Set continuously mode. */
		rtc_module->MODE0.READREQ.reg |= RTC_READREQ_RCONT;
	}

	/* Return status OK if everything was configured. */
	return STATUS_OK;
}