/* * Copyright (c) 2020, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*!**************************************************************************** * @file dl_trng.h * @brief True Random Number Generator (TRNG) Driver Library * @defgroup TRNG True Random Number Generator (TRNG) * * @anchor ti_dl_dl_m0p_trng_Overview * # Overview * * The True Random Number Generator Driver Library allows full configuration of * the MSPM0 TRNG module. * The true random number generator (TRNG) block is an entropy source which * can be used to generate random bit sequences. * *
****************************************************************************** */ /** @addtogroup TRNG * @{ */ #ifndef ti_dl_dl_trng__include #define ti_dl_dl_trng__include #include #include #include #include #ifdef __MSPM0_HAS_TRNG__ #ifdef __cplusplus extern "C" { #endif /* clang-format off */ /** @addtogroup DL_TRNG_INTERRUPT * @{ */ /*! * @brief TRNG interrupt definition for health test failed */ #define DL_TRNG_INTERRUPT_HEALTH_FAIL_EVENT (TRNG_IMASK_IRQ_HEALTH_FAIL_MASK) /*! * @brief TRNG interrupt definition for commafnd done */ #define DL_TRNG_INTERRUPT_CMD_DONE_EVENT (TRNG_IMASK_IRQ_CMD_DONE_MASK) /*! * @brief TRNG interrupt definition for command fail */ #define DL_TRNG_INTERRUPT_CMD_FAIL_EVENT (TRNG_IMASK_IRQ_CMD_FAIL_MASK) /*! * @brief TRNG interrupt definition for capture ready */ #define DL_TRNG_INTERRUPT_CAPTURE_RDY_EVENT (TRNG_IMASK_IRQ_CAPTURED_RDY_MASK) /** @}*/ /** @addtogroup DL_TRNG_HEALTH_TEST_SUCCESS * @{ */ /*! * @brief TRNG Digital health test success value */ #define DL_TRNG_DIGITAL_HEALTH_TEST_SUCCESS (0xFF) /*! * @brief TRNG Analog health test success value */ #define DL_TRNG_ANALOG_HEALTH_TEST_SUCCESS (0x1) /** @}*/ /* clang-format on */ /*! @enum DL_TRNG_IIDX */ typedef enum { /*! TRNG interrupt index for health fail */ DL_TRNG_IIDX_HEALTH_FAIL = TRNG_IIDX_STAT_IRQ_HEALTH_FAIL, /*! TRNG interrupt index for command done */ DL_TRNG_IIDX_CMD_DONE = TRNG_IIDX_STAT_IRQ_CMD_DONE, /*! TRNG interrupt index for command fail */ DL_TRNG_IIDX_CMD_FAIL = TRNG_IIDX_STAT_IRQ_CMD_FAIL, /*! TRNG interrupt index indicating the capture buffer is ready */ DL_TRNG_IIDX_CAPTURED_READY = TRNG_IIDX_STAT_IRQ_CAPTURED_RDY, } DL_TRNG_IIDX; /*! @enum DL_TRNG_DECIMATION_RATE */ typedef enum { /*! Decimation by 1 (no decimation) */ DL_TRNG_DECIMATION_RATE_1 = 0x0, /*! Decimation rate 2 -- take every other sample */ DL_TRNG_DECIMATION_RATE_2 = 0x1, /*! Decimation rate 3 -- take every third sample */ DL_TRNG_DECIMATION_RATE_3 = 0x2, /*! Decimation rate 4 -- take every fourth sample */ DL_TRNG_DECIMATION_RATE_4 = 0x3, /*! Decimation rate 5 -- take every fifth sample */ DL_TRNG_DECIMATION_RATE_5 = 0x4, /*! Decimation rate 6 -- take every sixth sample */ DL_TRNG_DECIMATION_RATE_6 = 0x5, /*! Decimation rate 7 -- take every seventh sample */ DL_TRNG_DECIMATION_RATE_7 = 0x6, /*! Decimation rate 8 -- take every eighth sample */ DL_TRNG_DECIMATION_RATE_8 = 0x7, } DL_TRNG_DECIMATION_RATE; /*! @enum DL_TRNG_CMD */ typedef enum { /*! TRNG command to power off analog blocks and digital blocks are gated */ DL_TRNG_CMD_PWROFF = TRNG_CTL_CMD_PWR_OFF, /*! TRNG command to execute digital power-on self-tests */ DL_TRNG_CMD_TEST_DIG = TRNG_CTL_CMD_PWRUP_DIG, /*! TRNG command to execute digital power-on self-tests */ DL_TRNG_CMD_TEST_ANA = TRNG_CTL_CMD_PWRUP_ANA, /*! TRNG command to go into normal operating mode */ DL_TRNG_CMD_NORM_FUNC = TRNG_CTL_CMD_NORM_FUNC, } DL_TRNG_CMD; /*! @enum DL_TRNG_CLOCK_DIVIDE */ typedef enum { /*! Clock divide by 1 */ DL_TRNG_CLOCK_DIVIDE_1 = TRNG_CLKDIVIDE_RATIO_DIV_BY_1, /*! Clock divide by 2 */ DL_TRNG_CLOCK_DIVIDE_2 = TRNG_CLKDIVIDE_RATIO_DIV_BY_2, /*! Clock divide by 4 */ DL_TRNG_CLOCK_DIVIDE_4 = TRNG_CLKDIVIDE_RATIO_DIV_BY_4, /*! Clock divide by 6 */ DL_TRNG_CLOCK_DIVIDE_6 = TRNG_CLKDIVIDE_RATIO_DIV_BY_6, /*! Clock divide by 8 */ DL_TRNG_CLOCK_DIVIDE_8 = TRNG_CLKDIVIDE_RATIO_DIV_BY_8, } DL_TRNG_CLOCK_DIVIDE; /*! @enum DL_TRNG_STATE */ typedef enum { /*! Current state of the TRNG is OFF */ DL_TRNG_STATE_OFF = 0x0, /*! Current state of the TRNG is PWRUP_ES */ DL_TRNG_STATE_PWRUP_ES = 0x1, /*! Current state of the TRNG is NORM_FUNC */ DL_TRNG_STATE_NORM_FUNC = 0x3, /*! Current state of the TRNG is TEST_DIG */ DL_TRNG_STATE_TEST_DIG = 0x7, /*! Current state of the TRNG is TEST_ANA */ DL_TRNG_STATE_TEST_ANA = 0xB, /*! Current state of the TRNG is ERROR */ DL_TRNG_STATE_ERROR = 0xA, /*! Current state of the TRNG is PWRDOWN_ES */ DL_TRNG_STATE_PWRDOWN = 0x2, } DL_TRNG_STATE; /** * @brief Configuration structure to backup TRNG peripheral state before * going to STOP/STANDBY mode. Used by @ref DL_TRNG_saveConfiguration */ typedef struct { /*! TRNG control word. Combination of @ref DL_TRNG_DECIMATION_RATE and * @ref DL_TRNG_CMD */ uint32_t controlWord; /*! TRNG clock divider. Must be one of @ref DL_TRNG_CLOCK_DIVIDE */ uint32_t clockDivider; /*! TRNG interrupt status. Must be one of @ref DL_TRNG_IIDX */ uint32_t interruptMask; /*! Boolean flag indicating whether or not a valid configuration structure exists. Should not be modified by the user. */ bool backupRdy; } DL_TRNG_backupConfig; /** * @brief Enables the Peripheral Write Enable (PWREN) register for the TRNG * * Before any peripheral registers can be configured by software, the * peripheral itself must be enabled by writing the ENABLE bit together with * the appropriate KEY value to the peripheral's PWREN register. * * @param trng Pointer to the register overlay for the peripheral */ __STATIC_INLINE void DL_TRNG_enablePower(TRNG_Regs *trng) { trng->GPRCM.PWREN = TRNG_PWREN_KEY_UNLOCK_W | TRNG_PWREN_ENABLE_ENABLE; } /** * @brief Disables the Peripheral Write Enable (PWREN) register for the TRNG * * When the PWREN.ENABLE bit is cleared, the peripheral's registers are not * accessible for read/write operations. * * @note This API does not provide large power savings. * * @param trng Pointer to the register overlay for the peripheral */ __STATIC_INLINE void DL_TRNG_disablePower(TRNG_Regs *trng) { trng->GPRCM.PWREN = TRNG_PWREN_KEY_UNLOCK_W | TRNG_PWREN_ENABLE_DISABLE; } /** * @brief Returns if the Peripheral Write Enable (PWREN) register for the TRNG * is enabled * * Before any peripheral registers can be configured by software, the * peripheral itself must be enabled by writing the ENABLE bit together with * the appropriate KEY value to the peripheral's PWREN register. * * When the PWREN.ENABLE bit is cleared, the peripheral's registers are not * accessible for read/write operations. * * @param trng Pointer to the register overlay for the peripheral * * @return true if peripheral register access is enabled * @return false if peripheral register access is disabled */ __STATIC_INLINE bool DL_TRNG_isPowerEnabled(TRNG_Regs *trng) { return ((TRNG->GPRCM.PWREN & TRNG_PWREN_ENABLE_MASK) == TRNG_PWREN_ENABLE_ENABLE); } /** * @brief Get the clock divider on the TRNG module * * @param trng Pointer to the register overlay for the peripheral * * @return Clock divider value for the TRNG module */ __STATIC_INLINE DL_TRNG_CLOCK_DIVIDE DL_TRNG_getClockDivider( const TRNG_Regs *trng) { return (DL_TRNG_CLOCK_DIVIDE) trng->CLKDIVIDE; } /** * @brief Set the clock divider on the TRNG module * * @param trng Pointer to the register overlay for the peripheral * * @param clockDivider Clock divider value for the TRNG module. * One of @ref DL_TRNG_CLOCK_DIVIDE */ __STATIC_INLINE void DL_TRNG_setClockDivider( TRNG_Regs *trng, DL_TRNG_CLOCK_DIVIDE clockDivider) { trng->CLKDIVIDE = (uint32_t) clockDivider; } /** * @brief Resets the TRNG module * * @param trng Pointer to the register overlay for the peripheral */ __STATIC_INLINE void DL_TRNG_reset(TRNG_Regs *trng) { trng->GPRCM.RSTCTL = TRNG_RSTCTL_RESETASSERT_ASSERT | TRNG_RSTCTL_KEY_UNLOCK_W; } /** * @brief Returns if TRNG peripheral was reset * * @param trng Pointer to the register overlay for the peripheral * * @return true if peripheral was reset * @return false if peripheral wasn't reset */ __STATIC_INLINE bool DL_TRNG_isReset(const TRNG_Regs *trng) { return (trng->GPRCM.STAT & TRNG_GPRCM_STAT_RESETSTKY_MASK) == TRNG_GPRCM_STAT_RESETSTKY_RESET; } /** * @brief Returns if the data capture is ready * * @param trng Pointer to the register overlay for the peripheral * * @return true if the data capture is ready * @return false if the data capture is not ready */ __STATIC_INLINE bool DL_TRNG_isCaptureReady(const TRNG_Regs *trng) { return ((trng->CPU_INT.RIS & TRNG_RIS_IRQ_CAPTURED_RDY_MASK)) == TRNG_RIS_IRQ_CAPTURED_RDY_SET; } /** * @brief Returns if the issued TRNG command is done * * @param trng Pointer to the register overlay for the peripheral * * @return true if the issued command is done * @return false if the issued command is not done */ __STATIC_INLINE bool DL_TRNG_isCommandDone(const TRNG_Regs *trng) { return ((trng->CPU_INT.RIS & TRNG_RIS_IRQ_CMD_DONE_MASK)) == TRNG_RIS_IRQ_CMD_DONE_SET; } /** * @brief Returns if the issued TRNG command failed * * @param trng Pointer to the register overlay for the peripheral * * @return true if the issued command failed * @return false if the issued command failed */ __STATIC_INLINE bool DL_TRNG_isCommandFail(const TRNG_Regs *trng) { return ((trng->CPU_INT.RIS & TRNG_RIS_IRQ_CMD_FAIL_MASK)) == TRNG_RIS_IRQ_CMD_FAIL_SET; } /** * @brief Returns if a health test failed * * @param trng Pointer to the register overlay for the peripheral * * @return true if a health test is failed * @return false if a health test did not fail */ __STATIC_INLINE bool DL_TRNG_isHealthTestFail(const TRNG_Regs *trng) { return ((trng->CPU_INT.RIS & TRNG_RIS_IRQ_HEALTH_FAIL_MASK)) == TRNG_RIS_IRQ_HEALTH_FAIL_SET; } /** * @brief Set the decimation rate * * @param trng Pointer to the register overlay for the peripheral * * @param decimationRate Decimation rate to set. * One of @ref DL_TRNG_DECIMATION_RATE */ __STATIC_INLINE void DL_TRNG_setDecimationRate( TRNG_Regs *trng, DL_TRNG_DECIMATION_RATE decimationRate) { DL_Common_updateReg(&trng->CTL, ((uint32_t) decimationRate << TRNG_CTL_DECIM_RATE_OFS), TRNG_CTL_DECIM_RATE_MASK); } /** * @brief Get the decimation rate * * @param[in] trng Pointer to the register overlay for the peripheral * * @return The decimation rate of the TRNG module * * @retval One of @ref DL_TRNG_DECIMATION_RATE */ __STATIC_INLINE DL_TRNG_DECIMATION_RATE DL_TRNG_getDecimationRate( const TRNG_Regs *trng) { uint32_t decimationRate = ((trng->CTL & TRNG_CTL_DECIM_RATE_MASK) >> TRNG_CTL_DECIM_RATE_OFS); return (DL_TRNG_DECIMATION_RATE)(decimationRate); } /** * @brief Get the digital health test results * * The test sequence includes eight tests, and each test reports its status in * an individual result bit. As each test passes, the corresponding bit is set. * * @param trng Pointer to the register overlay for the peripheral * * @return The results of the digital health tests * * @retval DL_TRNG_DIGITAL_HEALTH_TEST_SUCCESS if all tests passed, * otherwise a bitmask of which tests passed */ __STATIC_INLINE uint8_t DL_TRNG_getDigitalHealthTestResults( const TRNG_Regs *trng) { return (uint8_t)(trng->TEST_RESULTS & TRNG_TEST_RESULTS_DIG_TEST_MASK); } /** * @brief Get the analog health test results * * @param trng Pointer to the register overlay for the peripheral * * @return The results of the analog health test * * @retval DL_TRNG_ANALOG_HEALTH_TEST_SUCCESS if success * @retval 0 if test failed */ __STATIC_INLINE uint8_t DL_TRNG_getAnalogHealthTestResults( const TRNG_Regs *trng) { return (uint8_t)((trng->TEST_RESULTS & TRNG_TEST_RESULTS_ANA_TEST_MASK) >> TRNG_TEST_RESULTS_ANA_TEST_OFS); } /** * @brief Get the current state of the TRNG front end FSM * * This API should be called twice since two reads of the state are required as * there is a chance of metastability when reading this register. * * @param trng Pointer to the register overlay for the peripheral * * @return The current state of the TRNG * * @retval One of @ref DL_TRNG_STATE */ __STATIC_INLINE uint32_t DL_TRNG_getCurrentState(const TRNG_Regs *trng) { return ((trng->STAT & TRNG_STAT_FSM_STATE_MASK)) >> TRNG_STAT_FSM_STATE_OFS; } /** * @brief Get the last accepted command that was issued to the TRNG * * @param trng Pointer to the register overlay for the peripheral * * @return The last issued accepted command * * @retval One of @ref DL_TRNG_CMD */ __STATIC_INLINE uint32_t DL_TRNG_getIssuedCommand(const TRNG_Regs *trng) { return ((trng->STAT & TRNG_STAT_ISSUED_CMD_MASK)) >> TRNG_STAT_ISSUED_CMD_OFS; } /** * @brief Indicates if the repetition counter test caused the most recent * failure * * @param trng Pointer to the register overlay for the peripheral * * @return The status of the repetition test * * @retval true if the repetition test failed * @retval false if the repetition test did not fail */ __STATIC_INLINE bool DL_TRNG_isRepetitionTestFail(const TRNG_Regs *trng) { return ((trng->STAT & TRNG_STAT_REP_FAIL_MASK)) == TRNG_STAT_REP_FAIL_MASK; } /** * @brief Indicates if the Adaptive Proportion Test (1,2,3, or 4-bit counters) * caused the most recent failure * * @param trng Pointer to the register overlay for the peripheral * * @return The status of the Adaptive Proportion Test * * @retval true if the repetition test failed * @retval false if the repetition test did not fail */ __STATIC_INLINE bool DL_TRNG_isAdaptiveTestFail(const TRNG_Regs *trng) { return ((trng->STAT & TRNG_STAT_ADAP_FAIL_MASK)) == TRNG_STAT_ADAP_FAIL_MASK; } /** * @brief Enable TRNG interrupt * * @param[in] trng Pointer to the register overlay for the peripheral * * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_INTERRUPT. */ __STATIC_INLINE void DL_TRNG_enableInterrupt( TRNG_Regs *trng, uint32_t interruptMask) { trng->CPU_INT.IMASK |= interruptMask; } /** * @brief Disable TRNG interrupt * * @param[in] trng Pointer to the register overlay for the peripheral * * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_INTERRUPT. */ __STATIC_INLINE void DL_TRNG_disableInterrupt( TRNG_Regs *trng, uint32_t interruptMask) { trng->CPU_INT.IMASK &= ~interruptMask; } /** * @brief Check which TRNG interrupts are enabled * * @param[in] trng Pointer to the register overlay for the * peripheral * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_IIDX. * * @return Which of the requested TRNG interrupts are enabled * * @retval Bitwise OR of @ref DL_TRNG_INTERRUPT values */ __STATIC_INLINE uint32_t DL_TRNG_getEnabledInterrupts( const TRNG_Regs *trng, uint32_t interruptMask) { return trng->CPU_INT.IMASK & interruptMask; } /** * @brief Check interrupt flag of enabled TRNG interrupt * * Checks if the TRNG interrupt that was previously enabled is pending. * * @param[in] trng Pointer to the register overlay for the * peripheral * * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_INTERRUPT. * * @return If the enabled TRNG interrupt is pending * * @sa DL_TRNG_enableInterrupt */ __STATIC_INLINE uint32_t DL_TRNG_getEnabledInterruptStatus( const TRNG_Regs *trng, uint32_t interruptMask) { return (trng->CPU_INT.MIS & interruptMask); } /** * @brief Check interrupt flag of any TRNG interrupt * * Checks if the TRNG interrupt is pending. Interrupt does not have to * be previously enabled. * * @param[in] trng Pointer to the register overlay for the * peripheral * * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_INTERRUPT. * * @return If the trng interrupt is pending */ __STATIC_INLINE uint32_t DL_TRNG_getRawInterruptStatus( const TRNG_Regs *trng, uint32_t interruptMask) { return trng->CPU_INT.RIS & interruptMask; } /** * @brief Get highest priority pending TRNG interrupt * * Checks if any of the TRNG interrupts are pending. Interrupts do not have to * be previously enabled. * * @param[in] trng Pointer to the register overlay for the peripheral * * @return The highest priority pending TRNG interrupt * * @retval One of @ref DL_TRNG_IIDX */ __STATIC_INLINE DL_TRNG_IIDX DL_TRNG_getPendingInterrupt(const TRNG_Regs *trng) { return (DL_TRNG_IIDX) trng->CPU_INT.IIDX; } /** * @brief Clear pending TRNG interrupt * * @param[in] trng Pointer to the register overlay for the * peripheral * * @param[in] interruptMask Bit mask of interrupts to check. Bitwise OR of * @ref DL_TRNG_INTERRUPT. */ __STATIC_INLINE void DL_TRNG_clearInterruptStatus( TRNG_Regs *trng, uint32_t interruptMask) { trng->CPU_INT.ICLR = interruptMask; } /** * @brief Update control register's command bits to send a TRNG command * * @param[in] trng Pointer to the register overlay for the peripheral * * @param[in] cmd Command to update the control register with */ __STATIC_INLINE void DL_TRNG_sendCommand(TRNG_Regs *trng, DL_TRNG_CMD cmd) { DL_Common_updateReg(&trng->CTL, (uint32_t) cmd, TRNG_CTL_CMD_MASK); } /** * @brief Get word capture from TRNG * * Gets the captured data from the decimation block. * * @param[in] trng Pointer to the register overlay for the peripheral * * @retval TRNG capture value * * @pre The IRQ_CAPTURED_RDY IRQ should be asserted first, indicating that * random bits are available for read-out. * * @sa DL_TRNG_isCaptureReady */ __STATIC_INLINE uint32_t DL_TRNG_getCapture(const TRNG_Regs *trng) { return trng->DATA_CAPTURE; } /** * @brief Save TRNG configuration before entering a power loss state. * * @param[in] trng Pointer to the register overlay for the peripheral * * @param[in] ptr Configuration backup setup structure. See * @ref DL_TRNG_backupConfig. * * @retval FALSE if a configuration already exists in ptr (will not be * overwritten). TRUE if a configuration was successfully saved */ bool DL_TRNG_saveConfiguration( const TRNG_Regs *trng, DL_TRNG_backupConfig *ptr); /** * @brief Restore TRNG configuration after leaving a power loss state. * Upon restoration, if the TRNG was not originally in OFF state, * then the TRNG will be set to the normal operating mode. * * @param[in] trng Pointer to the register overlay for the peripheral * * @param[in] ptr Configuration backup setup structure. See * @ref DL_TRNG_backupConfig. * * @retval FALSE if a configuration does not exist in ptr (will not be * loaded). TRUE if a configuration successfully loaded */ bool DL_TRNG_restoreConfiguration(TRNG_Regs *trng, DL_TRNG_backupConfig *ptr); #ifdef __cplusplus } #endif #endif /* __MSPM0_HAS_TRNG__ */ #endif /* ti_dl_dl_trng__include */ /** @}*/