aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/ports/SAMA/SAMA5D2x
diff options
context:
space:
mode:
authoredolomb <none@example.com>2018-01-10 16:45:02 +0000
committeredolomb <none@example.com>2018-01-10 16:45:02 +0000
commitda0637d93d5935b1f6a398ecb420bd386d85d410 (patch)
treec44825c9e1292976ae42fc9357a5345653d8a793 /os/hal/ports/SAMA/SAMA5D2x
parenta8693baa481e1c4d91379af08bbc9f459b1b4d56 (diff)
downloadChibiOS-da0637d93d5935b1f6a398ecb420bd386d85d410.tar.gz
ChibiOS-da0637d93d5935b1f6a398ecb420bd386d85d410.tar.bz2
ChibiOS-da0637d93d5935b1f6a398ecb420bd386d85d410.zip
SECUMOD Driver
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11248 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/SAMA/SAMA5D2x')
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/sama_secumod.c568
-rw-r--r--os/hal/ports/SAMA/SAMA5D2x/sama_secumod.h554
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 */
+
+/** @} */