diff options
Diffstat (limited to 'os')
-rw-r--r-- | os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c | 568 | ||||
-rw-r--r-- | os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h | 554 |
2 files changed, 1122 insertions, 0 deletions
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c new file mode 100644 index 000000000..3652e6b65 --- /dev/null +++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c @@ -0,0 +1,568 @@ +/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file SAMA5D2x/sama_secumod.c
+ * @brief SAMA SECUMOD support code.
+ *
+ * @addtogroup SAMA5D2x_SECUMOD
+ * @{
+ */
+
+#include "hal.h"
+
+#if HAL_USE_SECUMOD || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Driver local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported variables. */
+/*===========================================================================*/
+/**
+ * @brief SEC driver identifier.
+ */
+SECDriver SECD0;
+
+/*===========================================================================*/
+/* Driver local types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver constant */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver interrupt handlers. */
+/*===========================================================================*/
+
+/**
+ * @brief SECURAM interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_SECURAM_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uint32_t ramaccsr, sr, sysr;
+ uint32_t rwx;
+ uint32_t i;
+
+ ramaccsr = SECUMOD->SECUMOD_RAMACCSR;
+ sr = SECUMOD->SECUMOD_SR;
+
+ for (i = 0; i < SECUMOD_RAM_REGIONS; i++) {
+ rwx = (ramaccsr >> (2 * i)) & 3;
+ if (rwx != RAMACCSR_NO_VIOLATION && SECD0.config->securam_callback != NULL)
+ SECD0.config->securam_callback(&SECD0);
+ }
+
+ /* process the end of erase signalling */
+ do {
+ sysr = SECUMOD->SECUMOD_SYSR;
+ } while (sysr & SECUMOD_SYSR_ERASE_ON);
+
+ if (SECUMOD_SYSR_ERASE_DONE == (sysr & SECUMOD_SYSR_ERASE_DONE)) {
+ /* Clear the flag ERASE_DONE */
+ SECUMOD->SECUMOD_SYSR = SECUMOD_SYSR_ERASE_DONE;
+ if (SECD0.config->erased_callback != NULL)
+ SECD0.config->erased_callback(&SECD0);
+ }
+
+ /* wait at least one slow clock */
+ chSysPolledDelayX(SAMA_PCK / SAMA_SLOW_CLK);
+
+ /* Clear RAM access violation flags */
+ SECUMOD->SECUMOD_RAMACCSR = ramaccsr;
+ /* Clear corresponding alarm flag bit */
+ SECUMOD->SECUMOD_SCR = sr;
+
+ aicAckInt();
+ OSAL_IRQ_EPILOGUE();
+}
+
+/**
+ * @brief SECUMOD interrupt handler.
+ *
+ * @isr
+ */
+OSAL_IRQ_HANDLER(SAMA_SECUMOD_HANDLER) {
+
+ OSAL_IRQ_PROLOGUE();
+
+ uint32_t sr, nimpr;
+
+ /* Read alarm status */
+ sr = SECUMOD->SECUMOD_SR;
+
+ if ((sr & SECUMOD_SR_SHLDM) && (nimpr & SECUMOD_NIMPR_SHLDM)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_SHLDM);
+ }
+ else if ((sr & SECUMOD_SR_DBLFM) && (nimpr & SECUMOD_NIMPR_DBLFM)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_DBLFM);
+ }
+ else if ((sr & SECUMOD_SR_TST) && (nimpr & SECUMOD_NIMPR_TST)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_TST);
+ }
+ else if ((sr & SECUMOD_SR_JTAG) && (nimpr & SECUMOD_NIMPR_JTAG)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_JTAG);
+ }
+ else if ((sr & SECUMOD_SR_MCKM) && (nimpr & SECUMOD_NIMPR_MCKM)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_MCKM);
+ }
+ else if ((sr & SECUMOD_SR_TPML) && (nimpr & SECUMOD_NIMPR_TPML)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_TPML);
+ }
+ else if ((sr & SECUMOD_SR_TPMH) && (nimpr & SECUMOD_NIMPR_TPMH)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_TPMH);
+ }
+ else if ((sr & SECUMOD_SR_VDDBUL) && (nimpr & SECUMOD_NIMPR_VDDBUL)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDBUL);
+ }
+ else if ((sr & SECUMOD_SR_VDDBUH) && (nimpr & SECUMOD_NIMPR_VDDBUH)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDBUH);
+ }
+ else if ((sr & SECUMOD_SR_VDDCOREL) && (nimpr & SECUMOD_NIMPR_VDDCOREL)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDCOREL);
+ }
+ else if ((sr & SECUMOD_SR_VDDCOREH) && (nimpr & SECUMOD_NIMPR_VDDCOREH)) {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_VDDCOREH);
+ }
+ else {
+ SECD0.secumod_callback(&SECD0, SEC_EVENT_PIOBU);
+ }
+
+ /* wait at least one slow clock */
+ chSysPolledDelayX(SAMA_PCK / SAMA_SLOW_CLK);
+
+ /* Clear corresponding alarm flag bit */
+ SECUMOD->SECUMOD_SCR = sr;
+
+ aicAckInt();
+ OSAL_IRQ_EPILOGUE();
+}
+
+/*===========================================================================*/
+/* Driver local functions. */
+/*===========================================================================*/
+/**
+ * @brief Configures PIOBU pads according to configuration struct.
+ *
+ * @param[in] listp pointer to a PIOBUConfig array
+ * @param[in] length length of array
+ *
+ * @notapi
+ */
+void piobu_config(PIOBUConfig *listp, size_t length) {
+ uint8_t i;
+ uint32_t cfg;
+ uint32_t index;
+ PIOBUConfig *piobup;
+
+ for (i = 0; i < length; i++) {
+ index = listp[i].pinIndex;
+ piobup = &listp[i];
+
+ /* AFV and RFV fields must be set to 0 when dynamic intrusion is selected. */
+ if (piobup->dynamic) {
+ cfg = 0;
+ } else {
+ cfg = (piobup->afv << SECUMOD_PIOBU_AFV_Pos ) | (piobup->rfv << SECUMOD_PIOBU_RFV_Pos);
+ }
+
+ if (piobup->mode) {
+ cfg |= SECUMOD_PIOBU_OUTPUT;
+ if (piobup->outputLevel)
+ cfg |= SECUMOD_PIOBU_PIO_SOD;
+ }
+
+ cfg |= piobup->pullUpState << SECUMOD_PIOBU_PULLUP_Pos;
+
+ if (piobup->scheduled)
+ cfg |= SECUMOD_PIOBU_SCHEDULE;
+
+ if (piobup->inputDefaultLevel)
+ cfg |= SECUMOD_PIOBU_SWITCH;
+
+ /* FILTER3_5 and DYNSTAT fields exist only for even PIOBUs */
+ if (0 == (index & 0x01)) {
+ if (piobup->dynamic)
+ cfg |= SECUMOD_PIOBU_DYNSTAT;
+
+ if (piobup->filter3_5)
+ cfg |= SECUMOD_PIOBU_FILTER3_5;
+ }
+ SECUMOD->SECUMOD_PIOBU[index] = cfg;
+ }
+}
+
+/**
+ * @brief Low level SEC driver initialization.
+ *
+ * @notapi
+ */
+void sec_lld_init(void) {
+
+ /* Driver initialization.*/
+ secObjectInit(&SECD0);
+ SECD0.sec = SECUMOD;
+}
+
+/**
+ * @brief Configures and activates the SEC peripheral.
+ *
+ * @param[in] secp pointer to the @p SECDriver object
+ *
+ * @notapi
+ */
+void sec_lld_start(SECDriver *secp) {
+
+ uint8_t i;
+
+ if (secp->state == SEC_STOP) {
+ /* Clock activation. */
+ pmcEnableSEC();
+
+ /* Register Reset */
+ secp->sec->SECUMOD_NIDPR = SECUMOD_NIDPR_ALL;
+ secumodSetNormalModeProtections(~SECUMOD_NMPR_ALL);
+
+ /*
+ * Configure interrupts
+ */
+ aicSetSourcePriority(ID_SECUMOD, SAMA_SECUMOD_IRQ_PRIORITY);
+ aicSetSourceHandler(ID_SECUMOD, SAMA_SECUMOD_HANDLER);
+
+ aicSetSourcePriority(ID_SECURAM, SAMA_SECURAM_IRQ_PRIORITY);
+ aicSetSourceHandler(ID_SECURAM, SAMA_SECURAM_HANDLER);
+
+ /* Enabling interrupt. */
+ aicEnableInt(ID_SECUMOD);
+ aicEnableInt(ID_SECURAM);
+ }
+
+ uint32_t ramacc_cfg = 0;
+
+ /* Select mode normal or backup*/
+ secp->sec->SECUMOD_CR = secp->config->cr;
+
+ /* Configure JTAGCR */
+ secp->sec->SECUMOD_JTAGCR = secp->config->jtagcr;
+
+ /* Configure region rights. */
+ for (i = 0; i < SECUMOD_RAM_REGIONS; i++) {
+ ramacc_cfg |= (secp->config->region[i].mode & 0x3u) << (i * 2);
+ }
+ secp->sec->SECUMOD_RAMACC = ramacc_cfg;
+
+ /* Configure PIOBU pads. */
+ piobu_config(secp->config->list, secp->config->length);
+}
+
+/**
+ * @brief Deactivates the SEC peripheral.
+ *
+ * @param[in] secp pointer to the @p SECDriver object
+ *
+ * @notapi
+ */
+void sec_lld_stop(SECDriver *secp) {
+
+ secp->sec->SECUMOD_NMPR &= ~(0xFF << 16);
+ secp->sec->SECUMOD_NIDPR |= (0xFF << 16);
+
+ aicDisableInt(ID_SECURAM);
+ aicDisableInt(ID_SECUMOD);
+
+ pmcDisableSEC();
+}
+
+/*===========================================================================*/
+/* Driver exported functions. */
+/*===========================================================================*/
+/**
+ * @brief SEC Driver initialization.
+ *
+ * @init
+ */
+void secInit(void) {
+
+ sec_lld_init();
+}
+
+/**
+ * @brief Initializes the standard part of a @p SECDriver structure.
+ *
+ * @param[out] secp pointer to a @p SECDriver object
+ *
+ * @init
+ */
+void secObjectInit(SECDriver *secp) {
+
+ secp->state = SEC_STOP;
+ secp->config = NULL;
+}
+
+/**
+ * @brief Configures and activates the SEC peripheral.
+ *
+ * @param[in] secp pointer to a @p SECDriver object
+ * @param[in] config pointer to a @p SECConfig object
+ *
+ * @api
+ */
+void secStart(SECDriver *secp, const SECConfig *config) {
+
+ osalDbgCheck((secp != NULL) && (config != NULL));
+
+ osalSysLock();
+ osalDbgAssert((secp->state == SEC_STOP), "invalid state");
+ secp->config = config;
+ sec_lld_start(secp);
+ secp->state = SEC_ACTIVE;
+ osalSysUnlock();
+}
+
+/**
+ * @brief Deactivates the SEC peripheral.
+ *
+ * @param[in] secp pointer to a @p SECDriver object
+ *
+ * @api
+ */
+void secStop(SECDriver *secp) {
+
+ osalDbgCheck(secp != NULL);
+
+ osalSysLock();
+
+ osalDbgAssert((secp->state == SEC_STOP) || (secp->state == SEC_ACTIVE),
+ "invalid state");
+
+ sec_lld_stop(secp);
+ secp->config = NULL;
+ secp->state = SEC_STOP;
+
+ osalSysUnlock();
+}
+
+/**
+ * @brief Enables or disables SECUMOD callbacks.
+ * @details This function enables or disables callbacks, use a @p NULL pointer
+ * in order to disable a callback.
+ * @note The function can be called from any context.
+ *
+ * @param[in] secp pointer to SECUMOD driver structure
+ * @param[in] sources Bitwise OR of protections.
+ * @param[in] callback callback function pointer or @p NULL
+ *
+ * @api
+ */
+void secSetCallback(SECDriver *secp, uint32_t sources, secumod_callback_t callback) {
+
+ osalDbgCheck(secp != NULL);
+
+ syssts_t sts;
+
+ /* Entering a reentrant critical zone.*/
+ sts = osalSysGetStatusAndLockX();
+
+ if (callback != NULL) {
+
+ /* IRQ sources enabled only after setting up the callback.*/
+ secp->secumod_callback = callback;
+ secp->sec->SECUMOD_NIEPR = sources;
+ if (SECUMOD->SECUMOD_NMPR != sources) {
+ secumodToggleProtectionReg();
+ secp->sec->SECUMOD_NIEPR = sources;
+ }
+ }
+ else {
+ secp->sec->SECUMOD_NIDPR = sources;
+
+ /* Callback set to NULL only after disabling the IRQ sources.*/
+ secp->secumod_callback = NULL;
+ }
+
+ /* Leaving a reentrant critical zone.*/
+ osalSysRestoreStatusX(sts);
+}
+
+/**
+ * @brief Set JTAG protection options of SECUMOD.
+ *
+ * @param[in] reset Whether preventing debug state and BSD (Boundary Scan Diagnostics) to work.
+ * @param[in] permissions Debug permissions.
+ * @param[in] ack Whether monitor the DBGACK signal.
+ *
+ * @api
+ */
+void secumodSetJtagProtection(bool reset, uint8_t permissions,
+ bool ack) {
+
+ uint32_t jtagcr;
+ jtagcr = permissions << SECUMOD_JTAGCR_CA5_DEBUG_MODE_Pos;
+
+ if (reset)
+ jtagcr |= SECUMOD_JTAGCR_FNTRST;
+
+ if (ack)
+ jtagcr |= SECUMOD_JTAGCR_CA5_DEBUG_MON;
+
+ SECUMOD->SECUMOD_JTAGCR = jtagcr;
+}
+
+/**
+ * @brief Tuning dynamic signatures by period and threshold.
+ *
+ * @param[in] period Signature Clock Period.
+ * @param[in] detection_thr Error Detection Threshold.
+ * @param[in] reset_thr Error Counter Reset Threshold.
+ *
+ * @api
+ */
+void secumodDynamicSignaturesTuning(uint16_t period,
+ uint8_t detectionThr, uint8_t resetThr) {
+
+ uint32_t dystune;
+
+ dystune = SECUMOD->SECUMOD_DYSTUNE & SECUMOD_DYSTUNE_NOPA;
+ dystune |= SECUMOD_DYSTUNE_PERIOD(period);
+ dystune |= SECUMOD_DYSTUNE_RX_ERROR_THRESHOLD(detectionThr);
+ dystune |= SECUMOD_DYSTUNE_RX_OK_CORREL_NUMBER(resetThr);
+ SECUMOD->SECUMOD_DYSTUNE = dystune;
+}
+
+/**
+ * @brief Enable/Disable alarm regenerated periodically while intrusion is maintained.
+ *
+ * @param[in] enable periodic alarm while intrusion is maintained,
+ * true: disable, false: enable.
+ * @api
+ */
+void secumodPeriodicAlarm(bool enable) {
+
+ uint32_t tmp;
+
+ tmp = SECUMOD->SECUMOD_DYSTUNE & ~SECUMOD_DYSTUNE_NOPA;
+ if (!enable)
+ tmp |= SECUMOD_DYSTUNE_NOPA;
+ SECUMOD->SECUMOD_DYSTUNE = tmp;
+}
+
+/**
+ * @brief Set access rights for secure RAM in SECUMOD.
+ *
+ * @param[in] region RAM region N,
+ * for N = 0 ~ 5: RAM range (N)Kbyte ~ (N+1)Kbyte;
+ * for N = 5: register bank 256bit.
+ * @param rights 0: No access allowed;
+ * 1: Only write access allowed;
+ * 2: Only read access allowed;
+ * 3: Read and write access allowed.
+ * @api
+ */
+void secumodSetRamAccessRights(uint32_t region, uint8_t rights) {
+
+ uint32_t tmp;
+
+ tmp = SECUMOD->SECUMOD_RAMACC & ~SECUMOD_RAMACC_RWx_Msk(region);
+ SECUMOD->SECUMOD_RAMACC = tmp | (rights << SECUMOD_RAMACC_RWx_Pos(region));
+}
+
+/**
+ * @brief Read the SECUMOD internal memory from the specified address
+ *
+ * @param[in] data Point to where the data read is stored
+ * @param[in] addr memory address
+ * @param[in] size The number of bytes to be read
+ *
+ * @return Bytes read
+ *
+ * @api
+ */
+uint32_t secumodReadInternalMemory(uint8_t *data, uint32_t addr, uint32_t size) {
+
+ uint32_t i;
+ uint32_t region;
+ uint32_t count;
+
+ if (addr >= ((uint32_t)SECURAM))
+ addr -= ((uint32_t)SECURAM);
+
+ for (i = 0; i < size; i += count) {
+ region = (addr + i) >> 10;
+ if ((SECUMOD_RAMACC_RWx_NO_ACCESS(region) ==
+ (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region))) ||
+ (SECUMOD_RAMACC_RWx_WR_ACCESS(region) ==
+ (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region)))) {
+ break;
+ }
+ count = size;
+ if (((region + 1) << 10 ) <= (addr + i + size)) {
+ size = ((region + 1) << 10) - (addr + i);
+ }
+ memcpy(data + i, (uint8_t *)(((uint32_t)SECURAM) + addr + i), count);
+ }
+ return i;
+}
+
+/**
+ * @brief Write data to the SECUMOD internal memory from the specified address
+ *
+ * @param[in] data Pointer to the data to be written
+ * @param[in] addr memory address
+ * @param[in] size The number of bytes to be be written
+ *
+ * @return Bytes written
+ *
+ * @api
+ */
+uint32_t secumodWriteInternalMemory(uint8_t *data, uint32_t addr, uint32_t size) {
+
+ uint32_t i;
+ uint32_t region;
+ uint32_t count;
+
+ if (addr >= ((uint32_t)SECURAM))
+ addr -= ((uint32_t)SECURAM);
+
+ for (i = 0; i < size; i += count) {
+ region = (addr + i) >> 10;
+ if ((SECUMOD_RAMACC_RWx_NO_ACCESS(region) ==
+ (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region))) ||
+ (SECUMOD_RAMACC_RWx_RD_ACCESS(region) ==
+ (SECUMOD->SECUMOD_RAMACC & SECUMOD_RAMACC_RWx_Msk(region)))) {
+ break;
+ }
+ count = size;
+ if (((region + 1) << 10 ) <= (addr + i + size)) {
+ size = ((region + 1) << 10) - (addr + i);
+ }
+ memcpy((uint8_t *)(((uint32_t)SECURAM) + addr + i), data + i, count);
+ }
+ return i;
+}
+
+#endif /* HAL_USE_SECUMOD */
+
+/** @} */
diff --git a/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h new file mode 100644 index 000000000..54c7a3207 --- /dev/null +++ b/os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h @@ -0,0 +1,554 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SAMA5D2x/sama_secumod.h + * @brief SAMA SECUMOD support macros and structures. + * + * @addtogroup SAMA5D2x_SECUMOD + * @{ + */ + +#ifndef SAMA_SECUMOD_LLD_H +#define SAMA_SECUMOD_LLD_H + +#if HAL_USE_SECUMOD || defined(__DOXYGEN__) + +#include <string.h> +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +/** + * @name RAM ACCESS mode macros + * @{ + */ +/** + * @brief No access allowed. + */ +#define RAMACC_NO_ACCESS 0x0U + +/** + * @brief Only write access allowed. + */ +#define RAMACC_WR_ACCESS 0x1U + +/** + * @brief Only read access allowed. + */ +#define RAMACC_RD_ACCESS 0x2U + +/** + * @brief Read and Write access allowed. + */ +#define RAMACC_WR_RD_ACCESS 0x3U +/** @} */ + +/** + * @name SOURCE INTERRUPT macros + * @{ + */ +/* + * @brief Shield Monitor Protection Interrupt Source. + */ +#define SECUMOD_SHLDM (0x1u << 0) + +/* + * @brief Double Frequency Monitor Protection Interrupt Source. + */ +#define SECUMOD_DBLFM (0x1u << 1) + +/* + * @brief Test Pin Protection Interrupt Source. + */ +#define SECUMOD_TST (0x1u << 2) + +/* + * @brief JTAG Pins Protection Interrupt Source. + */ +#define SECUMOD_JTAG (0x1u << 3) + +/* + * @brief Master Clock Monitor Protection Interrupt Source. + */ +#define SECUMOD_MCKM (0x1u << 5) + +/* + * @brief Low Temperature Monitor Protection Interrupt Source. + */ +#define SECUMOD_TPML (0x1u << 6) + +/* + * @brief High Temperature Monitor Protection Interrupt Source. + */ +#define SECUMOD_TPMH (0x1u << 7) + +/* + * @brief Low VDDBU Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDBUL (0x1u << 10) + +/* + * @brief High VDDBU Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDBUH (0x1u << 11) + +/* + * @brief Low VDDCORE Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDCOREL (0x1u << 12) + +/* + * @brief High VDDCORE Voltage Monitor Protection Interrupt Source. + */ +#define SECUMOD_VDDCOREH (0x1u << 13) + +/* + * @brief PIOBUx Intrusion Detector Protection Interrupt Source. + */ +#define SECUMOD_DET0 (0x1u << 16) +#define SECUMOD_DET1 (0x1u << 17) +#define SECUMOD_DET2 (0x1u << 18) +#define SECUMOD_DET3 (0x1u << 19) +#define SECUMOD_DET4 (0x1u << 20) +#define SECUMOD_DET5 (0x1u << 21) +#define SECUMOD_DET6 (0x1u << 22) +#define SECUMOD_DET7 (0x1u << 23) +/** @} */ + +/** + * @name RAM STATUS mode macros + * @{ + */ +/** + * @brief No access violation occurred. + */ +#define RAMACCSR_NO_VIOLATION 0x0U + +/** + * @brief Write access violation occurred. + */ +#define RAMACCSR_WR_VIOLATION 0x1U + +/** + * @brief Read access violation occurred. + */ +#define RAMACCSR_RD_VIOLATION 0x2U + +/** + * @brief Read and Write access violation occurred. + */ +#define RAMACCSR_WR_RD_VIOLATION 0x3U +/** @} */ + +/** + * @name SCRAMB mode macros + * @{ + */ +/** + * @brief SCRAMB ENABLE. + */ +#define SCRAMB_ENABLE 0x1U + +/** + * @brief SCRAMB DISABLE. + */ +#define SCRAMB_DISABLE 0x2U +/** @} */ + +/* + * @brief RAM regions of SECUMOD + */ +#define SECUMOD_RAM_REGIONS 6 + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ +/** + * @name Configuration options + * @{ + */ +/** + * @brief SECUMOD interrupt priority level setting. + */ +#if !defined(SAMA_SECUMOD_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SAMA_SECUMOD_IRQ_PRIORITY 7 +#endif + +/** + * @brief SECURAM interrupt priority level setting. + */ +#if !defined(SAMA_SECURAM_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SAMA_SECURAM_IRQ_PRIORITY 7 +#endif + +/** @} */ +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SEC_UNINIT = 0, /**< Not initialized. */ + SEC_STOP = 1, /**< Stopped. */ + SEC_ACTIVE = 2 /**< Active. */ +} secstate_t; + +/** + * @brief Type of an SECUMOD event. + */ +typedef enum { + SEC_EVENT_SHLDM = 0, /* Triggered on Shield Monitor. */ + SEC_EVENT_DBLFM = 1, /* Triggered on Double Frequency Monitor. */ + SEC_EVENT_TST = 2, /* Triggered on Test Pin Monitor. */ + SEC_EVENT_JTAG = 3, /* Triggered on JTAG Pins Monitor. */ + SEC_EVENT_MCKM = 4, /* Triggered on Master Clock Monitor. */ + SEC_EVENT_TPML = 5, /* Triggered on Low Temperature Monitor. */ + SEC_EVENT_TPMH = 6, /* Triggered on High Temperature Monitor. */ + SEC_EVENT_VDDBUL = 7, /* Triggered on Low VDDBU Voltage Monitor. */ + SEC_EVENT_VDDBUH = 8, /* Triggered on High VDDBU Voltage Monitor. */ + SEC_EVENT_VDDCOREL = 9, /* Triggered on Low VDDCORE Voltage Monitor. */ + SEC_EVENT_VDDCOREH = 10, /* Triggered on High VDDCORE Voltage Monitor. */ + SEC_EVENT_PIOBU = 11 /* Triggered on PIOBU intrusion. */ +} secevent_t; + +/** + * @brief Type of a structure representing an SEC driver. + */ +typedef struct SECDriver SECDriver; + +/** + * @brief SECURAM notification callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*securam_callback_t)(SECDriver *secp); + +/** + * @brief SECUMOD notification callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*secumod_callback_t)(SECDriver *secp, secevent_t event); + +/** + * @brief SECUMOD erase callback type. + * + * @param[in] secp pointer to a @p SECDriver object + */ +typedef void (*erased_callback_t)(SECDriver *secp); + +/** + * @brief Type of RAM access mode. + */ +typedef uint32_t ram_access_mode_t; + +/** + * @brief PIOBU configuration structure. + */ +typedef struct { + /* + * @brief PIOBU pin's index + */ + uint32_t pinIndex:3; + /* + * @brief alarm filter value + */ + uint32_t afv:4; + /* + * @brief reset filter value + */ + uint32_t rfv:4; + /* + * @brief I/O line mode + * @note 0: pure input, 1: enabled in output + */ + uint32_t mode:1; + /* + * @brief Configure the I/O line in output mode + * @note 0: clear, 1: set + */ + uint32_t outputLevel:1; + /* + * @brief programmable pull-up state + * @note 0: none, 1: pull-up; 2: pull-down; 3: reserved + */ + uint32_t pullUpState:2; + /* + * @brief Pull-up/Down Scheduled: + * @note 0: no; 1: yes + */ + uint32_t scheduled:1; + /* + * @brief switch input default state + */ + uint32_t inputDefaultLevel:1; + /* + * @brief Mode of detection intrusion. + * @note 0: static, 1: dynamic + */ + uint32_t dynamic:1; + /* + * @brief filter for dynamic signatures input + * @note 0: 3 stages majority vote, 1: 5 stages + */ + uint32_t filter3_5:1; +} PIOBUConfig; + +typedef struct { + /** + * @brief RAM Access Right + */ + ram_access_mode_t mode; + /* End of the mandatory fields.*/ +} RAMAccessConfig; + +/** + * @brief Driver configuration structure. + * @note It could be empty on some architectures. + */ +typedef struct { + /** + * @brief Callback for memory violation + */ + securam_callback_t securam_callback; + /** + * @brief Callback after memory erasing + */ + erased_callback_t erased_callback; + /** + * @brief lenght of PIOBUConfig array + * @note Number of pads to configure + */ + size_t length; + /** + * @brief pointer to PIOBUConfig array + */ + PIOBUConfig *list; + /** + * @brief RAM Access Rights + */ + RAMAccessConfig region[SECUMOD_RAM_REGIONS]; + /** + * @brief SECUMOD CR register initialization data. + */ + uint32_t cr; + /** + * @brief SECUMOD JTAGCR register initialization data. + */ + uint32_t jtagcr; +} SECConfig; + +/** + * @brief Structure representing a SEC driver. + */ +struct SECDriver { + /** + * @brief Driver state. + */ + secstate_t state; + /** + * @brief Current configuration data. + */ + const SECConfig *config; + /* End of the mandatory fields.*/ + /** + * @brief Pointer to the SECUMOD registers block. + */ + Secumod *sec; + /** + * @brief Callback pointer. + */ + secumod_callback_t secumod_callback; +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ +/** + * @brief Switch to Backup Mode. + * + * @api + */ +#define secumodSwitch2BackupMode() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_BACKUP; \ +} + +/** + * @brief Switch to Normal Mode. + * + * @api + */ +#define secumodSwitch2NormalMode() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_NORMAL; \ +} + +/** + * @brief Start clear content of SECUMOD internal RAM 4Kbyte and 256bits. + * + * @api + */ +#define secumodSoftwareProtection() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SWPROT; \ +} + +/** + * @brief Enable/Disable Auto-Backup. + * + * @param[in] enable Enable auto-backup if true, disable otherwise. + * + * @api + */ +#define secumodSetAutoBackup(enable) { \ + if (enable) { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_AUTOBKP_AUTO_SWITCH; \ + } \ + else { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_AUTOBKP_SW_SWITCH; \ + } \ +} + +/** + * @brief Enable/Disable Memory Scrambling. + * + * @param[in] enable Enable memory scrambling if true, disable otherwise. + * + * @api + */ +#define secumodSetScrambling(enable) { \ + if (enable) { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SCRAMB_ENABLE; \ + } \ + else { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_SCRAMB_DISABLE; \ + } \ +} + +/** + * @brief Toggle normal or backup protection registers appear and disappear. + * + * @api + */ +#define secumodToggleProtectionReg() { \ + SECUMOD->SECUMOD_CR = SECUMOD_CR_KEY_TOGGLE; \ +} + +/** + * @brief Set scrambling key for secure RAM in SECUMOD. + * + * @param[in] key Scrambling key. + * + * @api + */ +#define secumodSetScramblingKey(key) { \ + SECUMOD->SECUMOD_SCRKEY = key; \ +} + +/** + * @brief Get scrambling key for secure RAM in SECUMOD. + * + * @return Scrambling key. + * + * @api + */ +#define secumodGetScramblingKey() { \ + SECUMOD->SECUMOD_SCRKEY; \ +} + +/** + * @brief Set protections enabled in backup mode. + * + * @note Make sure registers appears before call this function, to toggle the + * appearance of the registers using secumodToggleProtectionReg(). + * + * @param[in] sources Bitwise OR of protections. + * + * @api + */ +#define secumodSetBackupModeProtections(sources) { \ + SECUMOD->SECUMOD_BMPR = sources; \ +} + +/** + * @brief Set protections enabled in normal mode. + * + * @note Make sure registers appears before call this function, to toggle the + * appearance of the registers using secumodToggleProtectionReg(). + * + * @param[in] sources Bitwise OR of protections. + * + * @api + */ +#define secumodSetNormalModeProtections(sources) { \ + SECUMOD->SECUMOD_NMPR = sources; \ + if (SECUMOD->SECUMOD_NMPR != sources) { \ + secumodToggleProtectionReg(); \ + SECUMOD->SECUMOD_NMPR = sources; \ + } \ +} + +/** + * @brief Set protection sources which can cause wake up signal generated. + * + * @param[in] sources Bitwise OR of protection sources. + * + * @api + */ +#define secumodSetWakeupProtections(sources) { \ + SECUMOD->SECUMOD_WKPR = sources; \ +} + +/** + * @brief Wait availability status of memory. + * + * @api + */ +#define secumodMemReady() { \ + while (!(SECUMOD->SECUMOD_RAMRDY & SECUMOD_RAMRDY_READY)); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ +extern SECDriver SECD0; + +#ifdef __cplusplus +extern "C" { +#endif + void secInit(void); + void secObjectInit(SECDriver *secp); + void secStart(SECDriver *secp, const SECConfig *config); + void secStop(SECDriver *secp); + void secSetCallback(SECDriver *secp, uint32_t sources, secumod_callback_t callback); + void secumodSetJtagProtection(bool reset, uint8_t permissions, bool ack); + void secumodDynamicSignaturesTuning(uint16_t period, uint8_t detectionThr, uint8_t resetThr); + void secumodPeriodicAlarm(bool enable); + void secumodSetRamAccessRights(uint32_t region, uint8_t rights); + uint32_t secumodReadInternalMemory(uint8_t *data, uint32_t addr, uint32_t size); + uint32_t secumodWriteInternalMemory(uint8_t *data, uint32_t addr, uint32_t size); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SECUMOD */ + +#endif /* SAMA_SECUMOD_LLD_H */ + +/** @} */ |