mirror of https://github.com/rusefi/ChibiOS.git
SECUMOD Driver
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11248 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
a8693baa48
commit
da0637d93d
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue