~aleteoryx/muditaos

085bccb7a153b22296496e5a26442603b734909e — Borys Jelenski 5 years ago fa61bb3
[EGD-6355] Adjust MuditaOS to be used with Secure Boot

The start address of the OS image adjusted to comply with HAB
Secure Boot. Proper SNVS initialization performed at system startup.
SNVS drivers updated to most recent version. Image signing can be
performed as a part of build process. See doc/secure_boot.md for
more info.
M CMakeLists.txt => CMakeLists.txt +39 -8
@@ 80,8 80,6 @@ add_compile_definitions(FSL_RTOS_FREE_RTOS
                __STARTUP_INITIALIZE_NONCACHEDATA
                SDK_OS_FREE_RTOS
                XIP_EXTERNAL_FLASH=0
                XIP_BOOT_HEADER_ENABLE=1
                XIP_BOOT_HEADER_DCD_ENABLE=0
                CPU_MIMXRT1051DVL6B_cm7
                CPU_MIMXRT1051DVL6B
                SDK_DEBUGCONSOLE=0


@@ 108,6 106,17 @@ if (GENERATE_STACK_USAGE)
    add_compile_options (-fstack-usage)
endif ()

include(SecureBoot)

if (NOT ENABLE_SECURE_BOOT)
    # Only enable the build-time boot header in a non-secure configuration,
    # a header for Secure Boot is added post-build when signing the binary
    add_compile_definitions(
        XIP_BOOT_HEADER_ENABLE=1
        XIP_BOOT_HEADER_DCD_ENABLE=0
    )
endif ()

target_compile_features(${PROJECT_NAME} PUBLIC
        ${TARGET_COMPILE_FEATURES})



@@ 217,12 226,34 @@ if (${PROJECT_TARGET} STREQUAL "TARGET_RT1051")
    set(HEX_FILE ${CMAKE_PROJECT_NAME}.hex)
    set(BIN_FILE ${CMAKE_BINARY_DIR}/sys/current/boot.bin)

    add_custom_command(
        COMMENT "Generate boot.bin"
        OUTPUT ${BIN_FILE}
        DEPENDS ${CMAKE_PROJECT_NAME}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${BIN_FILE}
        )
    if (ENABLE_SECURE_BOOT)
        set (SREC_FILE ${CMAKE_PROJECT_NAME}.srec)
        # .srec file required by elftosb
        add_custom_command(
            COMMENT "Generate ${CMAKE_PROJECT_NAME}.srec"
            OUTPUT ${CMAKE_BINARY_DIR}/${SREC_FILE}
            DEPENDS ${CMAKE_PROJECT_NAME}
            COMMAND ${CMAKE_OBJCOPY} -Osrec $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${SREC_FILE}
            )

        add_custom_command(
            COMMENT "Generate signed boot.bin (Secure Boot)"
            OUTPUT ${BIN_FILE}
            DEPENDS ${CMAKE_BINARY_DIR}/${SREC_FILE}
            COMMAND ${CMAKE_SOURCE_DIR}/config/elftosb_wrapper.sh "${ELFTOSB_PATH}" "${CST_PATH}" -f imx -V
            -c ${CMAKE_BINARY_DIR}/imx_authenticated_hab.bd
            -o ${BIN_FILE}
            ${CMAKE_BINARY_DIR}/${SREC_FILE}
            VERBATIM
            )
    else ()
        add_custom_command(
            COMMENT "Generate boot.bin"
            OUTPUT ${BIN_FILE}
            DEPENDS ${CMAKE_PROJECT_NAME}
            COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${CMAKE_PROJECT_NAME}> ${BIN_FILE}
            )
    endif()

    add_custom_command(
        COMMENT "Generate ${CMAKE_PROJECT_NAME}.hex"

M board/rt1051/ldscripts/sections.ld => board/rt1051/ldscripts/sections.ld +1 -1
@@ 35,7 35,7 @@ SECTIONS
        . = 0x430 ;
        KEEP(*(.boot_hdr.dcd_data))
        __boot_hdr_end__ = ABSOLUTE(.) ;
        . = 0x2000 ;
        . = 0x1000 ;
    } > BOARD_SDRAM_TEXT

    /* Data sections descriptors for startup initialization */

A cmake/modules/SecureBoot.cmake => cmake/modules/SecureBoot.cmake +49 -0
@@ 0,0 1,49 @@
option (ENABLE_SECURE_BOOT "Build signed binary for Secure Boot" OFF)

if (ENABLE_SECURE_BOOT)
    message(STATUS "Secure boot enabled")
    # NXP CST utility
    set(CST_PATH "" CACHE PATH "NXP Code Signing Tool (CST) utility exec. path. PATH lookup if not specified.")
    if (NOT CST_PATH)
        message(STATUS "Using NXP CST utility from PATH")
    else ()
        message(STATUS "Using NXP CST utility path: ${CST_PATH}")
    endif ()
    # NXP elftosb utility
    set(ELFTOSB_PATH "" CACHE FILEPATH "NXP elftosb utility exec. path. PATH lookup if not specified.")
    if (NOT ELFTOSB_PATH)
        message(STATUS "Using NXP elftosb utility from PATH")
    else ()
        message(STATUS "Using NXP elftosb utility path: ${ELFTOSB_PATH}")
    endif ()
    # SRK table
    set(SRK_TABLE "" CACHE FILEPATH "Super Root Key (SRK) table in a binary form (generated by NXP srktool)")
    if (NOT SRK_TABLE)
        message(FATAL_ERROR "SRK_TABLE not specified (required for Secure Boot)")
    endif ()
    # SRK index
    set(SRK_INDEX "" CACHE STRING "SRK key index in the SRK table (0-3)")
    if (NOT SRK_INDEX)
        set(SRK_INDEX "0" CACHE STRING "" FORCE)
    endif ()
    # CSF key
    set(CSF_KEY "" CACHE FILEPATH "CSF key in PEM format for CSF authentication")
    if (NOT CSF_KEY)
        message(FATAL_ERROR "CSF_KEY not specified (required for Secure Boot)")
    endif ()
    # IMG key
    set(IMG_KEY "" CACHE FILEPATH "IMG key in PEM format for image authentication")
    if (NOT IMG_KEY)
        message(FATAL_ERROR "IMG_KEY not specified (required for Secure Boot)")
    endif ()

    message(STATUS "Using SRK table: ${SRK_TABLE}")
    message(STATUS "Using SRK index: ${SRK_INDEX}")
    message(STATUS "Using CSF key: ${CSF_KEY}")
    message(STATUS "Using IMG key: ${IMG_KEY}")

    configure_file(
        ${CMAKE_SOURCE_DIR}/config/imx_authenticated_hab.cmake_template
        ${CMAKE_BINARY_DIR}/imx_authenticated_hab.bd
        )
endif ()

A config/elftosb_wrapper.sh => config/elftosb_wrapper.sh +42 -0
@@ 0,0 1,42 @@
#! /bin/bash
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

# This wrapper script expects filepaths to elftosb and cst NXP utilities
# as the first and second pos. arg. respectively. It passes the rest of
# pos. args to elftosb. Its main purpose is to export the path to cst utility
# so it is visible to elftosb.

function print_help() {
    echo -e "This script is a wrapper around the elftosb NXP utility used for" 
    echo -e "signing program images. Its purpose is to export the path to"
    echo -e "the NXP Code Signing Utility (CST) which is looked up in PATH"
    echo -e "by elftosb.\n"
    echo -e "Usage: elftosb_wrapper <elftosb_path> <cst_path> [elftosb_args]"
}

set -euo pipefail

if [[ $# -lt 2 ]]; then
    print_help
    exit 1
fi

elftosb_path=$1
shift 1
cst_path=$1
shift 1

if [[ -n "$elftosb_path" ]]; then
    elftosb_exec="$elftosb_path/elftosb"
else
    elftosb_exec="elftosb"
fi

if [[ -n "$cst_path" ]]; then
    # Export CST path for elftosb (assume already in PATH if empty)
    export "PATH=$cst_path:$PATH"
fi

# Run elftosb passing the remaining args
"$elftosb_exec" $@

A config/imx_authenticated_hab.cmake_template => config/imx_authenticated_hab.cmake_template +90 -0
@@ 0,0 1,90 @@
# This is a template of the command file for the NXP elftosb utility. It is
# processed by CMake which substitutes placeholders wich CMake variable values
# (configure file).

options {
    flags = 0x08;
    startAddress = 0x80000000;
    ivtOffset = 0x400;
    initialLoadSize = 0x1000;
}

sources {
    elfFile = extern(0);
}

constants {
    SEC_CSF_HEADER              = 20;
    SEC_CSF_INSTALL_SRK         = 21;
    SEC_CSF_INSTALL_CSFK        = 22;
    SEC_CSF_INSTALL_NOCAK       = 23;
    SEC_CSF_AUTHENTICATE_CSF    = 24;
    SEC_CSF_INSTALL_KEY         = 25;
    SEC_CSF_AUTHENTICATE_DATA   = 26;
    SEC_CSF_INSTALL_SECRET_KEY  = 27;
    SEC_CSF_DECRYPT_DATA        = 28;
    SEC_NOP                     = 29;
    SEC_SET_MID                 = 30;
    SEC_SET_ENGINE              = 31;
    SEC_INIT                    = 32;
    SEC_UNLOCK                  = 33;
}

section (SEC_CSF_HEADER;
    Header_Version="4.2",
    Header_HashAlgorithm="sha256",
    Header_Engine="DCP",
    Header_EngineConfiguration=0,
    Header_CertificateFormat="x509",
    Header_SignatureFormat="CMS"
    )
{
}

section (SEC_CSF_INSTALL_SRK;
    InstallSRK_Table="${SRK_TABLE}",
    InstallSRK_SourceIndex=${SRK_INDEX}
    )
{
}

section (SEC_CSF_INSTALL_CSFK;
    InstallCSFK_File="${CSF_KEY}",
    InstallCSFK_CertificateFormat="x509"
    )
{
}

section (SEC_CSF_AUTHENTICATE_CSF)
{
}

section (SEC_CSF_INSTALL_KEY;
    InstallKey_File="${IMG_KEY}",
    InstallKey_VerificationIndex=0,
    InstallKey_TargetIndex=2)
{
}

section (SEC_CSF_AUTHENTICATE_DATA;
    AuthenticateData_VerificationIndex=2,
    AuthenticateData_Engine="DCP",
    AuthenticateData_EngineConfiguration=0)
{
}


section (SEC_SET_ENGINE;
    SetEngine_HashAlgorithm = "sha256",
    SetEngine_Engine = "DCP",
    SetEngine_EngineConfiguration = "0")
{
}

section (SEC_UNLOCK;
    Unlock_Engine = "SNVS",
    Unlock_features = "ZMK WRITE"
    )
{
}


A doc/secure_boot.md => doc/secure_boot.md +123 -0
@@ 0,0 1,123 @@
# Secure Boot

The RT1051 processor features a Secure Boot mechanism in which a signed binary
image of the program can be authenticated against a public key stored
in the One-Time-Programmable (OTP) memory of the device also referred to as *eFuses*.

Secure Boot is meant be used in production and as long as you don't use a special CMake
configuration, you don't need to concern yourself with it.

For more information regarding Secure Boot, please refer the our internal documents:

* *Secure boot on the RT1051 MCU for Mudita Pure. A technical overview*

and to the official NXP documentation:

* *Security Reference Manual for the iMX RT1050 Processor, Rev. 2* - not publically
available on NXP site. If you're one of Mudita employees, please ask on Slack
to share it with you.
* *AN12681. How to use HAB secure boot in iMX RT10xx*

## Requirements

In order to enable Secure Boot on the device, you need the following:

* A signed bootloader (ecoboot) in a version which supports Secure Boot flashed
into the device. See the documentation in the ecoboot repository.
* A set of keys in order to sign the program image and provision the device.
Refer to [Generating keys](#generating-keys).
* An SRK hash (public key hash) written into the OTP memory and the *Closed* security
configuration fuse (bit) burned. See [Device provisioning](#device-provisioning).
* A signed MuditaOS image loaded into the device.
See [Signing MuditaOS image](#signing-muditaos-image).

## Generating keys

> The steps presented here are for generating keys for testing purposes only.

The keys used for signing and verifying the program image follow a certain PKI structure:

* SRK key - the root key of other keys. It's used for verifying the authenticity
of its subordinate keys. Its hash (called *SRK hash*) is burned into OTP memory
of the device.
* CSF key - subordinate key of SRK. Used for authenticating the CSF commands
presents in the image.
* IMG key - subordinate key of SRK. Used for authenticating the actual software
part of the image.

Actually, the SRK hash may be computed over *SRK table* which contains multiple SRKs.
This feature allow for revocation of a particular SRK in case it gets compromised.

For details regarding the PKI and key generation, refer to the *Code-Signing Tool
User’s Guide, Rev. 3.1.0*. 

The keys required for Secure Boot can be generated using the *MCUXpresso Secure
Provisioning Tool*, an NXP utility with a graphical user interface. Alternatively,
there is a set of scripts for key generation provided with the *NXP Code-Signing
Tool (CST)*. These scripts utilize OpenSSL and offer more control when compared
to the aforementioned graphical tool.

MCUXpresso Secure Provisioning Tool use the CST scripts underneath and the CST
package can be find among its files (in the `/opt/nxp/MCUX_Provi_v2.1/bin/tools/cst`
directory on Linux). The CST utility is also available as a separate download
on the NXP site.

## Device provisioning

In this context, provisioning involves writing the SRK hash into OTP memory and
burning the Closed security configuration fuse. Without performing these,
the ecoboot bootloader supporting Secure Boot will skip the image authentication
and perform a straightforward boot. This policy has been implemented so that the
Secure Boot feature won't interfere with the development of MuditaOS.

According to the documentation, the OTP memory can be programmed using the
NXP Flashloader program. When loaded into RAM using Serial Downloader boot mode,
it receives commands from the SDPHost tool and performs appropriate writes. However,
during testing it failed to run properly when loaded using the Serial Downloader
boot mode. This behaviour was not thoroughly investigated so the Flashloader
may yet happen to a viable option for eFuse programming.

During testing, eventually a simple program based on the *D1_Flashloader* (can be found on 
Mudita's GitHub) was used. It burned appropriate fuses using hardcoded values
upon running it on the MCU.

> It's important that when burning the SRK hash into eFuses, each four bytes of the
> SRK hash must be reversed.

## Signing MuditaOS image

> Signing the program image to be used with Secure Boot actually involves more
> than appending a cryptographic signature to the binary. A secure bootable image
> consist of multiple components like IVT, boot data, CSF, certificates and signatures
> besides the program itself. Refer to *Security Reference Manual for the iMX RT1050
> Processor, Rev. 2* for more information.

Image signing is optionally performed by CMake as one of the last steps of the build
process. In order to perform signing, the following CMake cache variables must be set:
* `ENABLE_SECURE_BOOT` - CMake option which enables image signing, set it to `ON`
* `CST_PATH` (optional) - a path to the NXP CST utility. If not specified, it is
assumed that CST is available from PATH.
* `ELFTOSB_PATH` (optional) - a path to the NXP elftosb utility. If not specified,
it is assumend that elftosb is available from PATH.
* `SRK_TABLE` - a full path to the SRK table binary file
* `SRK_INDEX` - the index in the SRK table of the SRK to be used for authentication.
Zero by default.
* `CSF_KEY` - a full path to the CSF key in PEM format
* `IMG_KEY` - a full path to the IMG key in PEM format

As you can see, in order to prepare a binary for Secure Boot, two utilities are
required: the NXP elftosb and NXP Code-Signing Tool (CST). These are used by the
MCUXpresso Secure Provisioning Tool so they can be found in its installation
directory (`/opt/nxp/MCUX_Provi_v2.1/bin/tools/cst` on Linux).

You can set the required CMake variables when configuring the project using the
`configure.sh` script:
``` bash
./configure.sh rt1051 RelWithDebInfo \
-DENABLE_SECURE_BOOT=ON \
-DCST_PATH="/opt/nxp/MCUX_Provi_v2.1/bin/tools/cst/linux64/bin" \
-DELFTOSB_PATH="/opt/nxp/MCUX_Provi_v2.1/bin/tools/elftosb/linux/amd64" \
-DSRK_TABLE="/home/SRK_hash.bin" \
-DCSF_KEY="/home/CSF1_1_sha256_2048_65537_v3_usr_crt.pem" \
-DIMG_KEY="/home/IMG1_1_sha256_2048_65537_v3_usr_crt.pem"
```

M module-bsp/board/rt1051/bsp/rtc/rtc.cpp => module-bsp/board/rt1051/bsp/rtc/rtc.cpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

/*

M module-bsp/board/rt1051/common/board.cpp => module-bsp/board/rt1051/common/board.cpp +7 -0
@@ 5,6 5,8 @@ extern "C"
#include "fsl_common.h"
#include "fsl_clock.h"
#include "fsl_dcdc.h"
#include "fsl_snvs_hp.h"
#include "fsl_snvs_lp.h"
#include "pin_mux.h"
#if LOG_LUART_ENABLED
#include "fsl_lpuart.h"


@@ 191,6 193,11 @@ namespace bsp

        irq_gpio_Init();

        // SNVS init. is required for proper operation of the RTC when Secure Boot is used
        SNVS_LP_Init(SNVS);
        SNVS_HP_Init(SNVS);
        SNVS_HP_ChangeSSMState(SNVS);

        // Set internal DCDC to DCM mode. Switching between DCM and CCM mode will be done automatically.
        DCDC_BootIntoDCM(DCDC);


M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c +221 -87
@@ 1,35 1,9 @@
/*
 * The Clear BSD License
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright (c) 2017, NXP
 * Copyright 2017-2019, NXP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted (subject to the limitations in the disclaimer below) provided
 *  that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
 * 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 HOLDER 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.
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "fsl_snvs_hp.h"


@@ 50,9 24,6 @@
#define YEAR_RANGE_START    (1970U)
#define YEAR_RANGE_END      (2099U)

#if !(defined(SNVS_HPCOMR_SW_SV_MASK))
#define SNVS_HPCOMR_SW_SV_MASK (0x100U)
#endif
#if !(defined(SNVS_HPSR_PI_MASK))
#define SNVS_HPSR_PI_MASK (0x2U)
#endif


@@ 100,7 71,7 @@ static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datet
 */
static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base);

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) &&                       \
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
/*!
 * @brief Get the SNVS instance from peripheral base address.


@@ 115,10 86,10 @@ static uint32_t SNVS_HP_GetInstance(SNVS_Type *base);
/*******************************************************************************
 * Variables
 ******************************************************************************/
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) &&                       \
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
/*! @brief Pointer to snvs_hp clock. */
const clock_ip_name_t s_snvsHpClock[] = SNVS_HP_CLOCKS;
static const clock_ip_name_t s_snvsHpClock[] = SNVS_HP_CLOCKS;
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

/*******************************************************************************


@@ 126,7 97,7 @@ const clock_ip_name_t s_snvsHpClock[] = SNVS_HP_CLOCKS;
 ******************************************************************************/
static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    /* Table of days in a month for a non leap year. First entry in the table is not used,
     * valid months start from 1


@@ 135,18 106,21 @@ static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime)

    /* Check year, month, hour, minute, seconds */
    if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
        (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U)) {
        (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
    {
        /* If not correct then error*/
        return false;
    }

    /* Adjust the days in February for a leap year */
    if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0)) {
    if ((((datetime->year & 3U) == 0U) && (datetime->year % 100U != 0U)) || (datetime->year % 400U == 0U))
    {
        daysPerMonth[2] = 29U;
    }

    /* Check the validity of the day */
    if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U)) {
    if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
    {
        return false;
    }



@@ 155,7 129,7 @@ static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime)

static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    /* Number of days from begin of the non Leap-year*/
    /* Number of days from begin of the non Leap-year*/


@@ 163,16 137,17 @@ static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *d
    uint32_t seconds;

    /* Compute number of days from 1970 till given year*/
    seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
    seconds = (((uint32_t)datetime->year - 1970U) * DAYS_IN_A_YEAR);
    /* Add leap year days */
    seconds += ((datetime->year / 4) - (1970U / 4));
    seconds += (((uint32_t)datetime->year / 4U) - (1970U / 4U));
    /* Add number of days till given month*/
    seconds += monthDays[datetime->month];
    /* Add days in given month. We subtract the current day as it is
     * represented in the hours, minutes and seconds field*/
    seconds += (datetime->day - 1);
    seconds += ((uint32_t)datetime->day - 1U);
    /* For leap year if month less than or equal to Febraury, decrement day counter*/
    if ((!(datetime->year & 3U)) && (datetime->month <= 2U)) {
    if ((0U == (datetime->year & 3U)) && (datetime->month <= 2U))
    {
        seconds--;
    }



@@ 184,7 159,7 @@ static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *d

static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    uint32_t x;
    uint32_t secondsRemaining, days;


@@ 200,53 175,60 @@ static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datet
    /* Calcuate the number of days, we add 1 for the current day which is represented in the
     * hours and seconds field
     */
    days = secondsRemaining / SECONDS_IN_A_DAY + 1;
    days = secondsRemaining / SECONDS_IN_A_DAY + 1U;

    /* Update seconds left*/
    secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;

    /* Calculate the datetime hour, minute and second fields */
    datetime->hour   = secondsRemaining / SECONDS_IN_A_HOUR;
    datetime->hour   = (uint8_t)(secondsRemaining / SECONDS_IN_A_HOUR);
    secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
    datetime->minute = secondsRemaining / 60U;
    datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
    datetime->minute = (uint8_t)(secondsRemaining / 60U);
    datetime->second = (uint8_t)(secondsRemaining % SECONDS_IN_A_MINUTE);

    /* Calculate year */
    daysInYear     = DAYS_IN_A_YEAR;
    datetime->year = YEAR_RANGE_START;
    while (days > daysInYear) {
    while (days > daysInYear)
    {
        /* Decrease day count by a year and increment year by 1 */
        days -= daysInYear;
        datetime->year++;

        /* Adjust the number of days for a leap year */
        if (datetime->year & 3U) {
        if ((datetime->year & 3U) != 0U)
        {
            daysInYear = DAYS_IN_A_YEAR;
        }
        else {
            daysInYear = DAYS_IN_A_YEAR + 1;
        else
        {
            daysInYear = DAYS_IN_A_YEAR + 1U;
        }
    }

    /* Adjust the days in February for a leap year */
    if (!(datetime->year & 3U)) {
    if (0U == (datetime->year & 3U))
    {
        daysPerMonth[2] = 29U;
    }

    for (x = 1U; x <= 12U; x++) {
        if (days <= daysPerMonth[x]) {
            datetime->month = x;
    for (x = 1U; x <= 12U; x++)
    {
        if (days <= daysPerMonth[x])
        {
            datetime->month = (uint8_t)x;
            break;
        }
        else {
        else
        {
            days -= daysPerMonth[x];
        }
    }

    datetime->day = days;
    datetime->day = (uint8_t)days;
}

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) &&                       \
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
static uint32_t SNVS_HP_GetInstance(SNVS_Type *base)
{


@@ 254,40 236,98 @@ static uint32_t SNVS_HP_GetInstance(SNVS_Type *base)
}
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

/*!
 * brief Initialize the SNVS.
 *
 * note This API should be called at the beginning of the application using the SNVS driver.
 *
 * param base SNVS peripheral base address
 */
void SNVS_HP_Init(SNVS_Type *base)
{
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
    uint32_t instance = SNVS_HP_GetInstance(base);
    CLOCK_EnableClock(s_snvsHpClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

/*!
 * brief Deinitialize the SNVS.
 *
 * param base SNVS peripheral base address
 */
void SNVS_HP_Deinit(SNVS_Type *base)
{
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
    uint32_t instance = SNVS_HP_GetInstance(base);
    CLOCK_DisableClock(s_snvsHpClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

/*!
 * brief Ungates the SNVS clock and configures the peripheral for basic operation.
 *
 * note This API should be called at the beginning of the application using the SNVS driver.
 *
 * param base   SNVS peripheral base address
 * param config Pointer to the user's SNVS configuration structure.
 */
void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config)
{
    assert(config);
    assert(config != NULL);

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) &&                       \
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
    uint32_t instance = SNVS_HP_GetInstance(base);
    CLOCK_EnableClock(s_snvsHpClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */

    base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN_MASK | SNVS_HPCOMR_SW_SV_MASK;
    base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN_MASK;

    base->HPCR = SNVS_HPCR_PI_FREQ(config->periodicInterruptFreq);

    if (config->rtcCalEnable) {
        base->HPCR = SNVS_HPCR_HPCALB_VAL_MASK & (config->rtcCalValue << SNVS_HPCR_HPCALB_VAL_SHIFT);
    if (config->rtcCalEnable)
    {
        base->HPCR |= SNVS_HPCR_HPCALB_VAL_MASK & (config->rtcCalValue << SNVS_HPCR_HPCALB_VAL_SHIFT);
        base->HPCR |= SNVS_HPCR_HPCALB_EN_MASK;
    }
}

/*!
 * brief Stops the RTC and SRTC timers.
 *
 * param base SNVS peripheral base address
 */
void SNVS_HP_RTC_Deinit(SNVS_Type *base)
{
    base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK;

#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) &&                       \
#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
     defined(SNVS_HP_CLOCKS))
    uint32_t instance = SNVS_HP_GetInstance(base);
    CLOCK_DisableClock(s_snvsHpClock[instance]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
}

/*!
 * brief Fills in the SNVS config struct with the default settings.
 *
 * The default values are as follows.
 * code
 *    config->rtccalenable = false;
 *    config->rtccalvalue = 0U;
 *    config->PIFreq = 0U;
 * endcode
 * param config Pointer to the user's SNVS configuration structure.
 */
void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config)
{
    assert(config);
    assert(config != NULL);

    /* Initializes the configure structure to zero. */
    (void)memset(config, 0, sizeof(*config));

    config->rtcCalEnable          = false;
    config->rtcCalValue           = 0U;


@@ 300,17 340,28 @@ static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base)
    uint32_t tmp     = 0;

    /* Do consecutive reads until value is correct */
    do {
    do
    {
        seconds = tmp;
        tmp     = (base->HPRTCMR << 17U) | (base->HPRTCLR >> 15U);
        tmp     = (base->HPRTCMR << 17U);
        tmp |= (base->HPRTCLR >> 15U);
    } while (tmp != seconds);

    return seconds;
}

/*!
 * brief Sets the SNVS RTC date and time according to the given time structure.
 *
 * param base     SNVS peripheral base address
 * param datetime Pointer to the structure where the date and time details are stored.
 *
 * return kStatus_Success: Success in setting the time and starting the SNVS RTC
 *         kStatus_InvalidArgument: Error because the datetime format is incorrect
 */
status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    uint32_t seconds = 0U;
    uint32_t tmp     = base->HPCR;


@@ 319,7 370,8 @@ status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *
    SNVS_HP_RTC_StopTimer(base);

    /* Return error if the time provided is not valid */
    if (!(SNVS_HP_CheckDatetimeFormat(datetime))) {
    if (!(SNVS_HP_CheckDatetimeFormat(datetime)))
    {
        return kStatus_InvalidArgument;
    }



@@ 330,30 382,52 @@ status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *
    base->HPRTCLR = (uint32_t)(seconds << 15U);

    /* reenable RTC in case that it was enabled before */
    if (tmp & SNVS_HPCR_RTC_EN_MASK) {
    if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U)
    {
        SNVS_HP_RTC_StartTimer(base);
    }

    return kStatus_Success;
}

/*!
 * brief Gets the SNVS RTC time and stores it in the given time structure.
 *
 * param base     SNVS peripheral base address
 * param datetime Pointer to the structure where the date and time details are stored.
 */
void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    SNVS_HP_ConvertSecondsToDatetime(SNVS_HP_RTC_GetSeconds(base), datetime);
}

/*!
 * brief Sets the SNVS RTC alarm time.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time
 * is greater than the present time. If not, the function does not set the alarm
 * and returns an error.
 *
 * param base      SNVS peripheral base address
 * param alarmTime Pointer to the structure where the alarm time is stored.
 *
 * return kStatus_Success: success in setting the SNVS RTC alarm
 *         kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
 *         kStatus_Fail: Error because the alarm time has already passed
 */
status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime)
{
    assert(alarmTime);
    assert(alarmTime != NULL);

    uint32_t alarmSeconds = 0U;
    uint32_t currSeconds  = 0U;
    uint32_t tmp          = base->HPCR;

    /* Return error if the alarm time provided is not valid */
    if (!(SNVS_HP_CheckDatetimeFormat(alarmTime))) {
    if (!(SNVS_HP_CheckDatetimeFormat(alarmTime)))
    {
        return kStatus_InvalidArgument;
    }



@@ 361,13 435,16 @@ status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *ala
    currSeconds  = SNVS_HP_RTC_GetSeconds(base);

    /* Return error if the alarm time has passed */
    if (alarmSeconds < currSeconds) {
    if (alarmSeconds < currSeconds)
    {
        return kStatus_Fail;
    }

    /* disable RTC alarm interrupt */
    base->HPCR &= ~SNVS_HPCR_HPTA_EN_MASK;
    while (base->HPCR & SNVS_HPCR_HPTA_EN_MASK) {}
    while ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U)
    {
    }

    /* Set alarm in seconds*/
    base->HPTAMR = (uint32_t)(alarmSeconds >> 17U);


@@ 379,19 456,31 @@ status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *ala
    return kStatus_Success;
}

/*!
 * brief Returns the SNVS RTC alarm time.
 *
 * param base     SNVS peripheral base address
 * param datetime Pointer to the structure where the alarm date and time details are stored.
 */
void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
{
    assert(datetime);
    assert(datetime != NULL);

    uint32_t alarmSeconds = 0U;

    /* Get alarm in seconds  */
    alarmSeconds = (base->HPTAMR << 17U) | (base->HPTALR >> 15U);
    alarmSeconds = (base->HPTAMR << 17U);
    alarmSeconds |= (base->HPTALR >> 15U);

    SNVS_HP_ConvertSecondsToDatetime(alarmSeconds, datetime);
}

#if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0))
/*!
 * brief The function synchronizes RTC counter value with SRTC.
 *
 * param base SNVS peripheral base address
 */
void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base)
{
    uint32_t tmp = base->HPCR;


@@ 402,38 491,83 @@ void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base)
    base->HPCR |= SNVS_HPCR_HP_TS_MASK;

    /* reenable RTC in case that it was enabled before */
    if (tmp & SNVS_HPCR_RTC_EN_MASK) {
    if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U)
    {
        SNVS_HP_RTC_StartTimer(base);
    }
}
#endif /* FSL_FEATURE_SNVS_HAS_SRTC */

/*!
 * brief Gets the SNVS status flags.
 *
 * param base SNVS peripheral base address
 *
 * return The status flags. This is the logical OR of members of the
 *         enumeration ::snvs_status_flags_t
 */
uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base)
{
    uint32_t flags = 0U;

    if (base->HPSR & SNVS_HPSR_PI_MASK) {
        flags |= kSNVS_RTC_PeriodicInterruptFlag;
    if ((base->HPSR & SNVS_HPSR_PI_MASK) != 0U)
    {
        flags |= (uint32_t)kSNVS_RTC_PeriodicInterruptFlag;
    }

    if (base->HPSR & SNVS_HPSR_HPTA_MASK) {
        flags |= kSNVS_RTC_AlarmInterruptFlag;
    if ((base->HPSR & SNVS_HPSR_HPTA_MASK) != 0U)
    {
        flags |= (uint32_t)kSNVS_RTC_AlarmInterruptFlag;
    }

    return flags;
}

/*!
 * brief Gets the enabled SNVS interrupts.
 *
 * param base SNVS peripheral base address
 *
 * return The enabled interrupts. This is the logical OR of members of the
 *         enumeration ::snvs_interrupt_enable_t
 */
uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base)
{
    uint32_t val = 0U;

    if (base->HPCR & SNVS_HPCR_PI_EN_MASK) {
        val |= kSNVS_RTC_PeriodicInterrupt;
    if ((base->HPCR & SNVS_HPCR_PI_EN_MASK) != 0U)
    {
        val |= (uint32_t)kSNVS_RTC_PeriodicInterrupt;
    }

    if (base->HPCR & SNVS_HPCR_HPTA_EN_MASK) {
        val |= kSNVS_RTC_AlarmInterrupt;
    if ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U)
    {
        val |= (uint32_t)kSNVS_RTC_AlarmInterrupt;
    }

    return val;
}

#if defined(FSL_FEATURE_SNVS_HAS_SET_LOCK) && (FSL_FEATURE_SNVS_HAS_SET_LOCK > 0)
/*!
 * brief Set SNVS HP Set locks.
 *
 * param base SNVS peripheral base address
 *
 */
void SNVS_HP_SetLocks(SNVS_Type *base)
{
    uint32_t sec_config = ((OCOTP_CTRL->HW_OCOTP_OTFAD_CFG3 & OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_MASK) >>
                           OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_SHIFT);

    if (sec_config == SEC_CONFIG_OPEN)
    {
        /* Enable non-secure SW access */
        base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN(1);
    }

    /* Set LP Software Reset Disable lock and ZMK Write Soft Lock */
    base->HPCOMR |= SNVS_HPCOMR_LP_SWR_DIS(1);
    base->HPLR |= SNVS_HPLR_ZMK_WSL(1);
}
#endif /* FSL_FEATURE_SNVS_HAS_SET_LOCK */

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.h +525 -205
@@ 1,35 1,9 @@
/*
 * The Clear BSD License
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright (c) 2017, NXP
 * Copyright 2017-2020, NXP
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted (subject to the limitations in the disclaimer below) provided
 *  that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of the copyright holder nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
 * 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 HOLDER 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.
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef _FSL_SNVS_HP_H_


@@ 48,7 22,7 @@

/*! @name Driver version */
/*@{*/
#define FSL_SNVS_HP_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0 */
#define FSL_SNVS_HP_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*!< Version 2.2.0 */
/*@}*/

/*! @brief List of SNVS interrupts */


@@ 61,10 35,37 @@ typedef enum _snvs_hp_interrupts
/*! @brief List of SNVS flags */
typedef enum _snvs_hp_status_flags
{
    kSNVS_RTC_AlarmInterruptFlag    = SNVS_HPSR_HPTA_MASK, /*!< RTC time alarm flag */
    kSNVS_RTC_PeriodicInterruptFlag = SNVS_HPSR_PI_MASK,   /*!< RTC periodic interrupt flag */
    kSNVS_RTC_AlarmInterruptFlag    = SNVS_HPSR_HPTA_MASK,          /*!< RTC time alarm flag */
    kSNVS_RTC_PeriodicInterruptFlag = SNVS_HPSR_PI_MASK,            /*!< RTC periodic interrupt flag */
    kSNVS_ZMK_ZeroFlag              = (int)SNVS_HPSR_ZMK_ZERO_MASK, /*!< The ZMK is zero */
    kSNVS_OTPMK_ZeroFlag            = SNVS_HPSR_OTPMK_ZERO_MASK,    /*!< The OTPMK is zero */
} snvs_hp_status_flags_t;

/*! @brief List of SNVS security violation flags */
typedef enum _snvs_hp_sv_status_flags
{
    kSNVS_LP_ViolationFlag = SNVS_HPSVSR_SW_LPSV_MASK,           /*!< Low Power section Security Violation */
    kSNVS_ZMK_EccFailFlag  = SNVS_HPSVSR_ZMK_ECC_FAIL_MASK,      /*!< Zeroizable Master Key Error Correcting Code Check
                                                                   Failure */
    kSNVS_LP_SoftwareViolationFlag   = SNVS_HPSVSR_SW_LPSV_MASK, /*!< LP Software Security Violation */
    kSNVS_FatalSoftwareViolationFlag = SNVS_HPSVSR_SW_FSV_MASK,  /*!< Software Fatal Security Violation */
    kSNVS_SoftwareViolationFlag      = SNVS_HPSVSR_SW_SV_MASK,   /*!< Software Security Violation */
    kSNVS_Violation0Flag             = SNVS_HPSVSR_SV0_MASK,     /*!< Security Violation 0 */
    kSNVS_Violation1Flag             = SNVS_HPSVSR_SV1_MASK,     /*!< Security Violation 1 */
    kSNVS_Violation2Flag             = SNVS_HPSVSR_SV2_MASK,     /*!< Security Violation 2 */
    kSNVS_Violation3Flag             = SNVS_HPSVSR_SV3_MASK,     /*!< Security Violation 3 */
    kSNVS_Violation4Flag             = SNVS_HPSVSR_SV4_MASK,     /*!< Security Violation 4 */
    kSNVS_Violation5Flag             = SNVS_HPSVSR_SV5_MASK,     /*!< Security Violation 5 */
} snvs_hp_sv_status_flags_t;

/*!
 * @brief Macro to make security violation flag
 *
 * Macro help to make security violation flag kSNVS_Violation0Flag to kSNVS_Violation5Flag,
 * For example, SNVS_MAKE_HP_SV_FLAG(0) is kSNVS_Violation0Flag.
 */
#define SNVS_MAKE_HP_SV_FLAG(x) (1U << (SNVS_HPSVSR_SV0_SHIFT + (x)))

/*! @brief Structure is used to hold the date and time */
typedef struct _snvs_hp_rtc_datetime
{


@@ 95,207 96,526 @@ typedef struct _snvs_hp_rtc_config
                                         Range from 0 to 15 */
} snvs_hp_rtc_config_t;

/*! @brief List of SNVS Security State Machine State */
typedef enum _snvs_hp_ssm_state
{
    kSNVS_SSMInit      = 0x00, /*!< Init */
    kSNVS_SSMHardFail  = 0x01, /*!< Hard Fail */
    kSNVS_SSMSoftFail  = 0x03, /*!< Soft Fail */
    kSNVS_SSMInitInter = 0x08, /*!< Init Intermediate (transition state between Init and Check) */
    kSNVS_SSMCheck     = 0x09, /*!< Check */
    kSNVS_SSMNonSecure = 0x0B, /*!< Non-Secure */
    kSNVS_SSMTrusted   = 0x0D, /*!< Trusted */
    kSNVS_SSMSecure    = 0x0F, /*!< Secure */
} snvs_hp_ssm_state_t;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C"
{
extern "C" {
#endif

    /*!
     * @name Initialization and deinitialization
     * @{
     */

    /*!
     * @brief Ungates the SNVS clock and configures the peripheral for basic operation.
     *
     * @note This API should be called at the beginning of the application using the SNVS driver.
     *
     * @param base   SNVS peripheral base address
     * @param config Pointer to the user's SNVS configuration structure.
     */
    void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config);

    /*!
     * @brief Stops the RTC and SRTC timers.
     *
     * @param base SNVS peripheral base address
     */
    void SNVS_HP_RTC_Deinit(SNVS_Type *base);

    /*!
     * @brief Fills in the SNVS config struct with the default settings.
     *
     * The default values are as follows.
     * @code
     *    config->rtccalenable = false;
     *    config->rtccalvalue = 0U;
     *    config->PIFreq = 0U;
     * @endcode
     * @param config Pointer to the user's SNVS configuration structure.
     */
    void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config);

    /*! @}*/

    /*!
     * @name Non secure RTC current Time & Alarm
     * @{
     */

    /*!
     * @brief Sets the SNVS RTC date and time according to the given time structure.
     *
     * @param base     SNVS peripheral base address
     * @param datetime Pointer to the structure where the date and time details are stored.
     *
     * @return kStatus_Success: Success in setting the time and starting the SNVS RTC
     *         kStatus_InvalidArgument: Error because the datetime format is incorrect
     */
    status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime);

    /*!
     * @brief Gets the SNVS RTC time and stores it in the given time structure.
     *
     * @param base     SNVS peripheral base address
     * @param datetime Pointer to the structure where the date and time details are stored.
     */
    void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime);

    /*!
     * @brief Sets the SNVS RTC alarm time.
     *
     * The function sets the RTC alarm. It also checks whether the specified alarm time
     * is greater than the present time. If not, the function does not set the alarm
     * and returns an error.
     *
     * @param base      SNVS peripheral base address
     * @param alarmTime Pointer to the structure where the alarm time is stored.
     *
     * @return kStatus_Success: success in setting the SNVS RTC alarm
     *         kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
     *         kStatus_Fail: Error because the alarm time has already passed
     */
    status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime);

    /*!
     * @brief Returns the SNVS RTC alarm time.
     *
     * @param base     SNVS peripheral base address
     * @param datetime Pointer to the structure where the alarm date and time details are stored.
     */
    void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime);
/*!
 * @name Initialization and deinitialization
 * @{
 */

/*!
 * @brief Initialize the SNVS.
 *
 * @note This API should be called at the beginning of the application using the SNVS driver.
 *
 * @param base SNVS peripheral base address
 */
void SNVS_HP_Init(SNVS_Type *base);

/*!
 * @brief Deinitialize the SNVS.
 *
 * @param base SNVS peripheral base address
 */
void SNVS_HP_Deinit(SNVS_Type *base);

/*!
 * @brief Ungates the SNVS clock and configures the peripheral for basic operation.
 *
 * @note This API should be called at the beginning of the application using the SNVS driver.
 *
 * @param base   SNVS peripheral base address
 * @param config Pointer to the user's SNVS configuration structure.
 */
void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config);

/*!
 * @brief Stops the RTC and SRTC timers.
 *
 * @param base SNVS peripheral base address
 */
void SNVS_HP_RTC_Deinit(SNVS_Type *base);

/*!
 * @brief Fills in the SNVS config struct with the default settings.
 *
 * The default values are as follows.
 * @code
 *    config->rtccalenable = false;
 *    config->rtccalvalue = 0U;
 *    config->PIFreq = 0U;
 * @endcode
 * @param config Pointer to the user's SNVS configuration structure.
 */
void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config);

/*! @}*/

/*!
 * @name Non secure RTC current Time & Alarm
 * @{
 */

/*!
 * @brief Sets the SNVS RTC date and time according to the given time structure.
 *
 * @param base     SNVS peripheral base address
 * @param datetime Pointer to the structure where the date and time details are stored.
 *
 * @return kStatus_Success: Success in setting the time and starting the SNVS RTC
 *         kStatus_InvalidArgument: Error because the datetime format is incorrect
 */
status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime);

/*!
 * @brief Gets the SNVS RTC time and stores it in the given time structure.
 *
 * @param base     SNVS peripheral base address
 * @param datetime Pointer to the structure where the date and time details are stored.
 */
void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime);

/*!
 * @brief Sets the SNVS RTC alarm time.
 *
 * The function sets the RTC alarm. It also checks whether the specified alarm time
 * is greater than the present time. If not, the function does not set the alarm
 * and returns an error.
 *
 * @param base      SNVS peripheral base address
 * @param alarmTime Pointer to the structure where the alarm time is stored.
 *
 * @return kStatus_Success: success in setting the SNVS RTC alarm
 *         kStatus_InvalidArgument: Error because the alarm datetime format is incorrect
 *         kStatus_Fail: Error because the alarm time has already passed
 */
status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime);

/*!
 * @brief Returns the SNVS RTC alarm time.
 *
 * @param base     SNVS peripheral base address
 * @param datetime Pointer to the structure where the alarm date and time details are stored.
 */
void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime);

#if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0))
    /*!
     * @brief The function synchronizes RTC counter value with SRTC.
     *
     * @param base SNVS peripheral base address
     */
    void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base);
/*!
 * @brief The function synchronizes RTC counter value with SRTC.
 *
 * @param base SNVS peripheral base address
 */
void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base);
#endif /* FSL_FEATURE_SNVS_HAS_SRTC */

    /*! @}*/

    /*!
     * @name Interrupt Interface
     * @{
     */

    /*!
     * @brief Enables the selected SNVS interrupts.
     *
     * @param base SNVS peripheral base address
     * @param mask The interrupts to enable. This is a logical OR of members of the
     *             enumeration ::snvs_interrupt_enable_t
     */
    static inline void SNVS_HP_RTC_EnableInterrupts(SNVS_Type *base, uint32_t mask)
/*! @}*/

/*!
 * @name Interrupt Interface
 * @{
 */

/*!
 * @brief Enables the selected SNVS interrupts.
 *
 * @param base SNVS peripheral base address
 * @param mask The interrupts to enable. This is a logical OR of members of the
 *             enumeration :: _snvs_hp_interrupts_t
 */
static inline void SNVS_HP_RTC_EnableInterrupts(SNVS_Type *base, uint32_t mask)
{
    base->HPCR |= mask;
}

/*!
 * @brief Disables the selected SNVS interrupts.
 *
 * @param base SNVS peripheral base address
 * @param mask The interrupts to disable. This is a logical OR of members of the
 *             enumeration :: _snvs_hp_interrupts_t
 */
static inline void SNVS_HP_RTC_DisableInterrupts(SNVS_Type *base, uint32_t mask)
{
    base->HPCR &= ~mask;
}

/*!
 * @brief Gets the enabled SNVS interrupts.
 *
 * @param base SNVS peripheral base address
 *
 * @return The enabled interrupts. This is the logical OR of members of the
 *         enumeration :: _snvs_hp_interrupts_t
 */
uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base);

/*! @}*/

/*!
 * @name Status Interface
 * @{
 */

/*!
 * @brief Gets the SNVS status flags.
 *
 * @param base SNVS peripheral base address
 *
 * @return The status flags. This is the logical OR of members of the
 *         enumeration :: _snvs_hp_status_flags_t
 */
uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base);

/*!
 * @brief  Clears the SNVS status flags.
 *
 * @param base SNVS peripheral base address
 * @param mask The status flags to clear. This is a logical OR of members of the
 *             enumeration :: _snvs_hp_status_flags_t
 */
static inline void SNVS_HP_RTC_ClearStatusFlags(SNVS_Type *base, uint32_t mask)
{
    base->HPSR |= mask;
}

/*! @}*/

/*!
 * @name Timer Start and Stop
 * @{
 */

/*!
 * @brief Starts the SNVS RTC time counter.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_RTC_StartTimer(SNVS_Type *base)
{
    base->HPCR |= SNVS_HPCR_RTC_EN_MASK;
    while (0U == (base->HPCR & SNVS_HPCR_RTC_EN_MASK))
    {
        base->HPCR |= mask;
    }
}

    /*!
     * @brief Disables the selected SNVS interrupts.
     *
     * @param base SNVS peripheral base address
     * @param mask The interrupts to enable. This is a logical OR of members of the
     *             enumeration ::snvs_interrupt_enable_t
     */
    static inline void SNVS_HP_RTC_DisableInterrupts(SNVS_Type *base, uint32_t mask)
/*!
 * @brief Stops the SNVS RTC time counter.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_RTC_StopTimer(SNVS_Type *base)
{
    base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK;
    while ((base->HPCR & SNVS_HPCR_RTC_EN_MASK) != 0U)
    {
        base->HPCR &= ~mask;
    }
}

/*! @}*/

    /*!
     * @brief Gets the enabled SNVS interrupts.
     *
     * @param base SNVS peripheral base address
     *
     * @return The enabled interrupts. This is the logical OR of members of the
     *         enumeration ::snvs_interrupt_enable_t
     */
    uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base);

    /*! @}*/

    /*!
     * @name Status Interface
     * @{
     */

    /*!
     * @brief Gets the SNVS status flags.
     *
     * @param base SNVS peripheral base address
     *
     * @return The status flags. This is the logical OR of members of the
     *         enumeration ::snvs_status_flags_t
     */
    uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base);

    /*!
     * @brief  Clears the SNVS status flags.
     *
     * @param base SNVS peripheral base address
     * @param mask The status flags to clear. This is a logical OR of members of the
     *             enumeration ::snvs_status_flags_t
     */
    static inline void SNVS_HP_RTC_ClearStatusFlags(SNVS_Type *base, uint32_t mask)
/*!
 * @brief Enable or disable master key selection.
 *
 * @param base SNVS peripheral base address
 * @param enable Pass true to enable, false to disable.
 */
static inline void SNVS_HP_EnableMasterKeySelection(SNVS_Type *base, bool enable)
{
    if (enable)
    {
        base->HPSR |= mask;
        base->HPCOMR |= SNVS_HPCOMR_MKS_EN_MASK;
    }
    else
    {
        base->HPCOMR &= (~SNVS_HPCOMR_MKS_EN_MASK);
    }
}

/*!
 * @brief Trigger to program Zeroizable Master Key.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_ProgramZeroizableMasterKey(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_PROG_ZMK_MASK;
}

/*!
 * @brief Trigger SSM State Transition
 *
 * Trigger state transition of the system security monitor (SSM). It results only
 * the following transitions of the SSM:
 *   - Check State -> Non-Secure (when Non-Secure Boot and not in Fab Configuration)
 *   - Check State --> Trusted (when Secure Boot or in Fab Configuration )
 *   - Trusted State --> Secure
 *   - Secure State --> Trusted
 *   - Soft Fail --> Non-Secure
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_ChangeSSMState(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_SSM_ST_MASK;
}

/*!
 * @brief Trigger Software Fatal Security Violation
 *
 * The result SSM state transition is:
 *  - Check State -> Soft Fail
 *  - Non-Secure State -> Soft Fail
 *  - Trusted State -> Soft Fail
 *  - Secure State -> Soft Fail
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_SetSoftwareFatalSecurityViolation(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_SW_FSV_MASK;
}

/*!
 * @brief Trigger Software Security Violation
 *
 * The result SSM state transition is:
 *  - Check -> Non-Secure
 *  - Trusted -> Soft Fail
 *  - Secure -> Soft Fail
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_SetSoftwareSecurityViolation(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_SW_SV_MASK;
}

/*!
 * @brief Get current SSM State
 *
 * @param base SNVS peripheral base address
 * @return Current SSM state
 */
static inline snvs_hp_ssm_state_t SNVS_HP_GetSSMState(SNVS_Type *base)
{
    return (snvs_hp_ssm_state_t)((uint32_t)((base->HPSR & SNVS_HPSR_SSM_STATE_MASK) >> SNVS_HPSR_SSM_STATE_SHIFT));
}

    /*! @}*/
/*!
 * @brief Reset the SNVS LP section.
 *
 * Reset the LP section except SRTC and Time alarm.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_ResetLP(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_LP_SWR_MASK;
}

    /*!
     * @name Timer Start and Stop
     * @{
     */
/*!
 * @name High Assurance Counter (HAC)
 * @{
 */

    /*!
     * @brief Starts the SNVS RTC time counter.
     *
     * @param base SNVS peripheral base address
     */
    static inline void SNVS_HP_RTC_StartTimer(SNVS_Type *base)
/*!
 * @brief Enable or disable the High Assurance Counter (HAC)
 *
 * @param base SNVS peripheral base address
 * @param enable Pass true to enable, false to disable.
 */
static inline void SNVS_HP_EnableHighAssuranceCounter(SNVS_Type *base, bool enable)
{
    if (enable)
    {
        base->HPCOMR |= SNVS_HPCOMR_HAC_EN_MASK;
    }
    else
    {
        base->HPCR |= SNVS_HPCR_RTC_EN_MASK;
        while (!(base->HPCR & SNVS_HPCR_RTC_EN_MASK)) {}
        base->HPCOMR &= (~SNVS_HPCOMR_HAC_EN_MASK);
    }
}

    /*!
     * @brief Stops the SNVS RTC time counter.
     *
     * @param base SNVS peripheral base address
     */
    static inline void SNVS_HP_RTC_StopTimer(SNVS_Type *base)
/*!
 * @brief Start or stop the High Assurance Counter (HAC)
 *
 * @param base SNVS peripheral base address
 * @param start Pass true to start, false to stop.
 */
static inline void SNVS_HP_StartHighAssuranceCounter(SNVS_Type *base, bool start)
{
    if (start)
    {
        base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK;
        while (base->HPCR & SNVS_HPCR_RTC_EN_MASK) {}
        base->HPCOMR &= (~SNVS_HPCOMR_HAC_STOP_MASK);
    }
    else
    {
        base->HPCOMR |= SNVS_HPCOMR_HAC_STOP_MASK;
    }
}

/*!
 * @brief Set the High Assurance Counter (HAC) initialize value.
 *
 * @param base SNVS peripheral base address
 * @param value The initial value to set.
 */
static inline void SNVS_HP_SetHighAssuranceCounterInitialValue(SNVS_Type *base, uint32_t value)
{
    base->HPHACIVR = value;
}

/*!
 * @brief Load the High Assurance Counter (HAC)
 *
 * This function loads the HAC initialize value to counter register.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_LoadHighAssuranceCounter(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_HAC_LOAD_MASK;
}

/*!
 * @brief Get the current High Assurance Counter (HAC) value
 *
 * @param base SNVS peripheral base address
 * @return HAC currnet value.
 */
static inline uint32_t SNVS_HP_GetHighAssuranceCounter(SNVS_Type *base)
{
    return base->HPHACR;
}

/*!
 * @brief Clear the High Assurance Counter (HAC)
 *
 * This function can be called in a functional or soft fail state. When the HAC
 * is enabled:
 *   - If the HAC is cleared in the soft fail state, the SSM transitions to the
 * hard fail state immediately;
 *   - If the HAC is cleared in functional state, the SSM will transition to
 * hard fail immediately after transitioning to soft fail.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_ClearHighAssuranceCounter(SNVS_Type *base)
{
    base->HPCOMR |= SNVS_HPCOMR_HAC_CLEAR_MASK;
}

/*!
 * @brief Lock the High Assurance Counter (HAC)
 *
 * Once locked, the HAC initialize value could not be changed, the HAC enable
 * status could not be changed. This could only be unlocked by system reset.
 *
 * @param base SNVS peripheral base address
 */
static inline void SNVS_HP_LockHighAssuranceCounter(SNVS_Type *base)
{
    base->HPLR |= SNVS_HPLR_HAC_L_MASK;
}

/*! @}*/

/*!
 * @brief Get the SNVS HP status flags.
 *
 * The flags are returned as the OR'ed value f the
 *             enumeration :: _snvs_hp_status_flags_t.
 *
 * @param base SNVS peripheral base address
 * @return The OR'ed value of status flags.
 */
static inline uint32_t SNVS_HP_GetStatusFlags(SNVS_Type *base)
{
    return base->HPSR;
}

/*!
 * @brief Clear the SNVS HP status flags.
 *
 * The flags to clear are passed in as the OR'ed value of the
 *             enumeration :: _snvs_hp_status_flags_t.
 * Only these flags could be cleared using this API.
 *  - @ref kSNVS_RTC_PeriodicInterruptFlag
 *  - @ref kSNVS_RTC_AlarmInterruptFlag
 *
 * @param base SNVS peripheral base address
 * @param mask OR'ed value of the flags to clear.
 */
static inline void SNVS_HP_ClearStatusFlags(SNVS_Type *base, uint32_t mask)
{
    base->HPSR = mask;
}

/*!
 * @brief Get the SNVS HP security violation status flags.
 *
 * The flags are returned as the OR'ed value of the
 *             enumeration :: _snvs_hp_sv_status_flags_t.
 *
 * @param base SNVS peripheral base address
 * @return The OR'ed value of security violation status flags.
 */
static inline uint32_t SNVS_HP_GetSecurityViolationStatusFlags(SNVS_Type *base)
{
    return base->HPSVSR;
}

/*!
 * @brief Clear the SNVS HP security violation status flags.
 *
 * The flags to clear are passed in as the OR'ed value of the
 *             enumeration :: _snvs_hp_sv_status_flags_t.
 * Only these flags could be cleared using this API.
 *
 *  - @ref kSNVS_ZMK_EccFailFlag
 *  - @ref kSNVS_Violation0Flag
 *  - @ref kSNVS_Violation1Flag
 *  - @ref kSNVS_Violation2Flag
 *  - @ref kSNVS_Violation3Flag
 *  - @ref kSNVS_Violation4Flag
 *  - @ref kSNVS_Violation5Flag
 *
 * @param base SNVS peripheral base address
 * @param mask OR'ed value of the flags to clear.
 */
static inline void SNVS_HP_ClearSecurityViolationStatusFlags(SNVS_Type *base, uint32_t mask)
{
    base->HPSVSR = mask;
}

#if defined(FSL_FEATURE_SNVS_HAS_SET_LOCK) && (FSL_FEATURE_SNVS_HAS_SET_LOCK > 0)
/*!
 * brief Set SNVS HP Set locks.
 *
 * param base SNVS peripheral base address
 *
 */
void SNVS_HP_SetLocks(SNVS_Type *base);
#endif /* FSL_FEATURE_SNVS_HAS_SET_LOCK */

#if defined(__cplusplus)
}

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.c +48 -5
@@ 17,12 17,12 @@
#define FSL_COMPONENT_ID "platform.drivers.snvs_lp"
#endif

#define SECONDS_IN_A_DAY (86400U)
#define SECONDS_IN_A_HOUR (3600U)
#define SECONDS_IN_A_DAY    (86400U)
#define SECONDS_IN_A_HOUR   (3600U)
#define SECONDS_IN_A_MINUTE (60U)
#define DAYS_IN_A_YEAR (365U)
#define YEAR_RANGE_START (1970U)
#define YEAR_RANGE_END (2099U)
#define DAYS_IN_A_YEAR      (365U)
#define YEAR_RANGE_START    (1970U)
#define YEAR_RANGE_END      (2099U)

#define SNVS_DEFAULT_PGD_VALUE (0x41736166U)



@@ 764,3 764,46 @@ void SNVS_LP_WriteZeroizableMasterKey(SNVS_Type *base, uint32_t ZMKey[SNVS_ZMK_R
        base->LPZMKR[i] = ZMKey[i];
    }
}

#if defined(FSL_FEATURE_SNVS_HAS_STATE_TRANSITION) && (FSL_FEATURE_SNVS_HAS_STATE_TRANSITION > 0)
/*!
 * brief Transition SNVS SSM state to Trusted/Non-secure from Check state
 *
 * param base SNVS peripheral base address
 *
 * return kStatus_Success: Success in transitioning SSM State
 *        kStatus_Fail: SSM State transition failed
 */
status_t SNVS_LP_SSM_State_Transition(SNVS_Type *base)
{
    uint32_t curr_ssm_state = ((base->HPSR & SNVS_HPSR_SSM_STATE_MASK) >> SNVS_HPSR_SSM_STATE_SHIFT);
    uint32_t sec_config     = ((OCOTP_CTRL->HW_OCOTP_OTFAD_CFG3 & OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_MASK) >>
                           OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_SHIFT);

    /* Check if SSM State is Check state */
    if (curr_ssm_state == SNVS_SSM_STATE_CHECK)
    {
        if (sec_config == SEC_CONFIG_OPEN)
        {
            /* Transition to Non-secure state */
            base->HPCOMR |= SNVS_HPCOMR_SW_SV(1);
        }
        else
        {
            /* Transition to Trusted state */
            base->HPCOMR |= SNVS_HPCOMR_SSM_ST(1);
        }
    }

    uint32_t new_ssm_state = ((base->HPSR & SNVS_HPSR_SSM_STATE_MASK) >> SNVS_HPSR_SSM_STATE_SHIFT);

    if (new_ssm_state != SNVS_SSM_STATE_CHECK)
    {
        return kStatus_Success;
    }
    else
    {
        return kStatus_Fail;
    }
}
#endif /* FSL_FEATURE_SNVS_HAS_STATE_TRANSITION */

M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_lp.h +22 -9
@@ 1,6 1,6 @@
/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2017-2019, NXP
 * Copyright 2017-2020, NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause


@@ 22,9 22,10 @@

/*! @name Driver version */
/*@{*/
#define FSL_SNVS_LP_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*!< Version 2.1.2 */
#define FSL_SNVS_LP_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*!< Version 2.2.0 */
/*@}*/

/*! @brief Define of SNVS_LP Zeroizable Master Key registers */
#define SNVS_ZMK_REG_COUNT 8U /* 8 Zeroizable Master Key registers. */

/*! @brief List of SNVS_LP interrupts */


@@ 57,6 58,7 @@ typedef enum _snvs_lp_external_tamper
} snvs_lp_external_tamper_t;

/* define max possible tamper present */
/*! @brief Define of SNVS_LP Max possible tamper */
#if defined(FSL_FEATURE_SNVS_HAS_MULTIPLE_TAMPER) && (FSL_FEATURE_SNVS_HAS_MULTIPLE_TAMPER > 1)
#define SNVS_LP_MAX_TAMPER kSNVS_ExternalTamper10
#else


@@ 143,7 145,6 @@ extern "C" {
 * @note This API should be called at the beginning of the application using the SNVS driver.
 *
 * @param base   SNVS peripheral base address
 * @param config Pointer to the user's SNVS configuration structure.
 */
void SNVS_LP_Init(SNVS_Type *base);



@@ 249,7 250,7 @@ void SNVS_LP_SRTC_GetAlarm(SNVS_Type *base, snvs_lp_srtc_datetime_t *datetime);
 *
 * @param base SNVS peripheral base address
 * @param mask The interrupts to enable. This is a logical OR of members of the
 *             enumeration ::snvs_interrupt_enable_t
 *             enumeration :: _snvs_lp_srtc_interrupts
 */
static inline void SNVS_LP_SRTC_EnableInterrupts(SNVS_Type *base, uint32_t mask)
{


@@ 261,7 262,7 @@ static inline void SNVS_LP_SRTC_EnableInterrupts(SNVS_Type *base, uint32_t mask)
 *
 * @param base SNVS peripheral base address
 * @param mask The interrupts to enable. This is a logical OR of members of the
 *             enumeration ::snvs_interrupt_enable_t
 *             enumeration :: _snvs_lp_srtc_interrupts
 */
static inline void SNVS_LP_SRTC_DisableInterrupts(SNVS_Type *base, uint32_t mask)
{


@@ 274,7 275,7 @@ static inline void SNVS_LP_SRTC_DisableInterrupts(SNVS_Type *base, uint32_t mask
 * @param base SNVS peripheral base address
 *
 * @return The enabled interrupts. This is the logical OR of members of the
 *         enumeration ::snvs_interrupt_enable_t
 *         enumeration :: _snvs_lp_srtc_interrupts
 */
uint32_t SNVS_LP_SRTC_GetEnabledInterrupts(SNVS_Type *base);



@@ 291,7 292,7 @@ uint32_t SNVS_LP_SRTC_GetEnabledInterrupts(SNVS_Type *base);
 * @param base SNVS peripheral base address
 *
 * @return The status flags. This is the logical OR of members of the
 *         enumeration ::snvs_status_flags_t
 *         enumeration :: _snvs_lp_srtc_status_flags
 */
uint32_t SNVS_LP_SRTC_GetStatusFlags(SNVS_Type *base);



@@ 300,7 301,7 @@ uint32_t SNVS_LP_SRTC_GetStatusFlags(SNVS_Type *base);
 *
 * @param base SNVS peripheral base address
 * @param mask The status flags to clear. This is a logical OR of members of the
 *             enumeration ::snvs_status_flags_t
 *             enumeration :: _snvs_lp_srtc_status_flags
 */
static inline void SNVS_LP_SRTC_ClearStatusFlags(SNVS_Type *base, uint32_t mask)
{


@@ 372,7 373,7 @@ void SNVS_LP_DisableExternalTamper(SNVS_Type *base, snvs_lp_external_tamper_t pi
 * @param base SNVS peripheral base address
 * @param pin SNVS external tamper pin
 *
 * @return The status flag. This is the enumeration ::snvs_external_tamper_status_t
 * @return The status flag. This is the enumeration :: _snvs_lp_external_tamper_status
 */
snvs_lp_external_tamper_status_t SNVS_LP_GetExternalTamperStatus(SNVS_Type *base, snvs_lp_external_tamper_t pin);



@@ 531,6 532,18 @@ static inline void SNVS_LP_SetMasterKeyMode(SNVS_Type *base, snvs_lp_master_key_
    base->LPMKCR    = lpmkcr;
}

#if defined(FSL_FEATURE_SNVS_HAS_STATE_TRANSITION) && (FSL_FEATURE_SNVS_HAS_STATE_TRANSITION > 0)
/*!
 * brief Transition SNVS SSM state to Trusted/Non-secure from Check state
 *
 * param base SNVS peripheral base address
 *
 * return kStatus_Success: Success in transitioning SSM State
 *        kStatus_Fail: SSM State transition failed
 */
status_t SNVS_LP_SSM_State_Transition(SNVS_Type *base);
#endif /* FSL_FEATURE_SNVS_HAS_STATE_TRANSITION */

/*! @}*/

#if defined(__cplusplus)