/** * \file * * \brief SAM RTC Driver (Count Mode) * * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * * Subject to your compliance with these terms, you may use Microchip * software and any derivatives exclusively with Microchip products. * It is your responsibility to comply with third party license terms applicable * to your use of third party software (including open source software) that * may accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /* * Support and FAQ: visit Microchip Support */ #include "rtc_count.h" #include #include #include "conf_rtc.h" #if !defined(__DOXYGEN__) struct rtc_module *_rtc_instance[RTC_INST_NUM]; #endif #if !defined(RTC_CLOCK_SOURCE) # warning RTC_CLOCK_SOURCE is not defined, assuming RTC_CLOCK_SELECTION_ULP1K. # define RTC_CLOCK_SOURCE RTC_CLOCK_SELECTION_ULP1K #endif /** * \brief Determines if the hardware module(s) are currently synchronizing to the bus. * * Checks to see if the underlying hardware peripheral module(s) are currently * synchronizing across multiple clock domains to the hardware bus, This * function can be used to delay further operations on a module until such time * that it is ready, to prevent blocking delays for synchronization in the * user application. * * \param[in] module RTC hardware module * * \return Synchronization status of the underlying hardware module(s). * * \retval true if the module synchronization is ongoing * \retval false if the module has completed synchronization */ static bool rtc_count_is_syncing(struct rtc_module *const module) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Rtc *const rtc_module = module->hw; if (rtc_module->MODE0.SYNCBUSY.reg) { return true; } return false; } /** * \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 */ } } /** * \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.CTRLA.reg &= ~RTC_MODE0_CTRLA_ENABLE; while (rtc_count_is_syncing(module)) { /* Wait for synchronization */ } } /** * \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 */ } } /** * \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; #if SAML21 || SAMR30 || (SAMR34) || (SAMR35) rtc_module->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE(0) #if (SAML21XXXB) || (SAMR30) || (SAMR34) || (SAMR35) | (config->enable_read_sync << RTC_MODE0_CTRLA_COUNTSYNC_Pos) #endif | config->prescaler; #endif #if (SAMC20) || (SAMC21) || (SAML22) rtc_module->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE(0) | config->prescaler | (config->enable_read_sync << RTC_MODE0_CTRLA_COUNTSYNC_Pos); #endif /* Set mode and clear on match if applicable. */ switch (config->mode) { case RTC_COUNT_MODE_32BIT: /* Set 32-bit mode and clear on match if applicable. */ rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_MODE(0); /* Check if clear on compare match should be set. */ if (config->clear_on_match) { /* Set clear on match. */ rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_MATCHCLR; } /* Set compare values. */ for (uint8_t i = 0; i < RTC_COMP32_NUM; i++) { 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.CTRLA.reg |= RTC_MODE1_CTRLA_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++) { rtc_count_set_compare(module, config->compare_values[i], (enum rtc_count_compare)i); } break; default: Assert(false); return STATUS_ERR_INVALID_ARG; } /* Return status OK if everything was configured. */ return STATUS_OK; } /** * \brief Initializes the RTC module with given configurations. * * Initializes the module, setting up all given configurations to provide * the desired functionality of the RTC. * * \param[out] module Pointer to the software instance struct * \param[in] hw Pointer to hardware instance * \param[in] config Pointer to the configuration structure * * \return Status of the initialization procedure. * \retval STATUS_OK If the initialization was run stressfully * \retval STATUS_ERR_INVALID_ARG If invalid argument(s) were given */ enum status_code rtc_count_init( struct rtc_module *const module, Rtc *const hw, const struct rtc_count_config *const config) { /* Sanity check arguments */ Assert(module); Assert(hw); Assert(config); /* Initialize device instance */ module->hw = hw; /* Turn on the digital interface clock */ system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, MCLK_APBAMASK_RTC); /* Select RTC clock */ OSC32KCTRL->RTCCTRL.reg = RTC_CLOCK_SOURCE; /* Reset module to hardware defaults. */ rtc_count_reset(module); /* Save conf_struct internally for continued use. */ module->mode = config->mode; # if (RTC_INST_NUM == 1) _rtc_instance[0] = module; # else /* Register this instance for callbacks*/ _rtc_instance[_rtc_get_inst_index(hw)] = module; # endif /* Set config and return status. */ return _rtc_count_set_config(module, config); } /** * \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; } /** * \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; } /** * \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; } /** * \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; } /** * \brief Retrieves the value of period. * * Retrieves the value of the period for the 16-bit mode counter. * * \note Only available in 16-bit mode. * * \param[in,out] module Pointer to the software instance struct * \param[out] period_value Pointer to value for return argument * * \return Status of getting the period value. * \retval STATUS_OK If the period value was read correctly * \retval STATUS_ERR_UNSUPPORTED_DEV If incorrect mode was set */ enum status_code rtc_count_get_period( struct rtc_module *const module, uint16_t *const period_value) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Rtc *const rtc_module = module->hw; while (rtc_count_is_syncing(module)) { /* Wait for synchronization */ } /* Check that correct mode is set. */ if (module->mode != RTC_COUNT_MODE_16BIT) { return STATUS_ERR_UNSUPPORTED_DEV; } /* Returns the value. */ *period_value = rtc_module->MODE1.PER.reg; return STATUS_OK; } /** * \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; } /** * \brief Check if RTC compare match has occurred. * * Checks the compare flag to see if a match has occurred. The compare flag is * set when there is a compare match between counter and the 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_index Index of compare to check current flag */ bool rtc_count_is_compare_match( struct rtc_module *const module, const enum rtc_count_compare comp_index) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Rtc *const rtc_module = module->hw; /* Check sanity. */ switch (module->mode) { case RTC_COUNT_MODE_32BIT: /* Check sanity for 32-bit mode. */ if (comp_index > RTC_COMP32_NUM) { return false; } break; case RTC_COUNT_MODE_16BIT: /* Check sanity for 16-bit mode. */ if (comp_index > RTC_NUM_OF_COMP16) { return false; } break; default: Assert(false); return false; } /* Set status of INTFLAG as return argument. */ return (rtc_module->MODE0.INTFLAG.reg & RTC_MODE1_INTFLAG_CMP(1 << comp_index)) ? true : false; } /** * \brief Clears RTC compare match flag. * * Clears the compare flag. The compare flag is set when there is a compare * match between the counter and the 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_index Index of compare to check current flag * * \return Status indicating if flag was successfully cleared. * \retval STATUS_OK If flag was successfully cleared * \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_clear_compare_match( struct rtc_module *const module, const enum rtc_count_compare comp_index) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Rtc *const rtc_module = module->hw; /* Check sanity. */ switch (module->mode){ case RTC_COUNT_MODE_32BIT: /* Check sanity for 32-bit mode. */ if (comp_index > RTC_COMP32_NUM) { return STATUS_ERR_INVALID_ARG; } break; case RTC_COUNT_MODE_16BIT: /* Check sanity for 16-bit mode. */ if (comp_index > RTC_NUM_OF_COMP16) { return STATUS_ERR_INVALID_ARG; } break; default: Assert(false); return STATUS_ERR_BAD_FORMAT; } /* Clear INTFLAG. */ rtc_module->MODE0.INTFLAG.reg = RTC_MODE1_INTFLAG_CMP(1 << comp_index); return STATUS_OK; } /** * \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; while (rtc_count_is_syncing(module)) { /* Wait for synchronization */ } return STATUS_OK; } #ifdef FEATURE_RTC_TAMPER_DETECTION /** * \brief Applies the given configuration. * * Sets the configurations given from the configuration structure to the * RTC tamper and it should be called before RTC module enable. * * \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 * \note If tamper input configured as active layer protection, RTC prescaler * output automatically enabled in the function. */ enum status_code rtc_tamper_set_config ( struct rtc_module *const module, struct rtc_tamper_config *const tamper_cfg) { /* Sanity check arguments */ Assert(module); Assert(module->hw); Assert(tamper_cfg); Rtc *const rtc_module = module->hw; uint16_t ctrl_b = 0; /* Configure enable backup and GP register reset on tamper or not. */ if(tamper_cfg->bkup_reset_on_tamper) { rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_BKTRST; } else { rtc_module->MODE0.CTRLA.reg &= ~RTC_MODE0_CTRLA_BKTRST; } if (tamper_cfg->gp_reset_on_tamper) { rtc_module->MODE0.CTRLA.reg |= RTC_MODE0_CTRLA_GPTRST; } else { rtc_module->MODE0.CTRLA.reg &= ~RTC_MODE0_CTRLA_GPTRST; } /* Configure tamper detection of frequency and debounce setting. */ ctrl_b = tamper_cfg->actl_freq_div | tamper_cfg->deb_freq_div; if(tamper_cfg->deb_seq == RTC_TAMPER_DEBOUNCE_ASYNC) { ctrl_b |= RTC_MODE0_CTRLB_DEBASYNC; } else if (tamper_cfg->deb_seq == RTC_TAMPER_DEBOUNCE_MAJORITY) { ctrl_b |= RTC_MODE0_CTRLB_DEBMAJ; } if(tamper_cfg->dma_tamper_enable) { ctrl_b |= RTC_MODE0_CTRLB_DMAEN; } if (tamper_cfg->gp0_enable) { ctrl_b |= RTC_MODE0_CTRLB_GP0EN; } /* Configure tamper input. */ volatile RTC_TAMPCTRL_Type *tamper_ctrl = &(rtc_module->MODE0.TAMPCTRL); struct rtc_tamper_input_config in_cfg; for (uint8_t tamper_id = 0; tamper_id < RTC_TAMPER_NUM; tamper_id++) { in_cfg = tamper_cfg->in_cfg[tamper_id]; if(in_cfg.action == RTC_TAMPER_INPUT_ACTION_ACTL) { ctrl_b |= RTC_MODE0_CTRLB_RTCOUT; } switch(tamper_id) { case 0: tamper_ctrl->bit.IN0ACT = in_cfg.action; tamper_ctrl->bit.TAMLVL0 = in_cfg.level; tamper_ctrl->bit.DEBNC0 = in_cfg.debounce_enable; break; case 1: tamper_ctrl->bit.IN1ACT = in_cfg.action; tamper_ctrl->bit.TAMLVL1 = in_cfg.level; tamper_ctrl->bit.DEBNC1 = in_cfg.debounce_enable; break; case 2: tamper_ctrl->bit.IN2ACT = in_cfg.action; tamper_ctrl->bit.TAMLVL2 = in_cfg.level; tamper_ctrl->bit.DEBNC2 = in_cfg.debounce_enable; break; case 3: tamper_ctrl->bit.IN3ACT = in_cfg.action; tamper_ctrl->bit.TAMLVL3 = in_cfg.level; tamper_ctrl->bit.DEBNC3 = in_cfg.debounce_enable; break; case 4: tamper_ctrl->bit.IN4ACT = in_cfg.action; tamper_ctrl->bit.TAMLVL4 = in_cfg.level; tamper_ctrl->bit.DEBNC4 = in_cfg.debounce_enable; break; default: Assert(false); break; } } rtc_module->MODE0.CTRLB.reg = ctrl_b; /* Return status OK if everything was configured. */ return STATUS_OK; } /** * \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; } #endif