4
0
mirror of https://github.com/RT-Thread/rt-thread.git synced 2025-02-13 21:29:18 +08:00
Wayne Lin 4fcb87a8aa Support M2354 platform.
1. Add NuMaker-M2354 BSP.
2. Fix SLCD library and modify its demo.
2021-02-05 18:52:13 +08:00

410 lines
13 KiB
C

/**************************************************************************//**
* @file dpm.c
* @version V3.00
* @brief Debug Protection Mechanism (DPM) driver source file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "NuMicro.h"
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup DPM_Driver DPM Driver
@{
*/
/** @addtogroup DPM_EXPORTED_FUNCTIONS DPM Exported Functions
@{
*/
/**
* @brief Set Debug Disable
* @param[in] u32dpm The pointer of the specified DPM module
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return None
* @details This macro sets Secure or Non-secure DPM debug disable.
* The debug disable function works after reset (chip reset or pin reset).
*/
void DPM_SetDebugDisable(uint32_t u32dpm)
{
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (DPM->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_DBGDIS_Msk);
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_DBGDIS_Msk);
}
}
/**
* @brief Set Debug Lock
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return None
* @details This macro sets Secure or Non-secure DPM debug lock.
* The debug lock function works after reset (chip reset or pin reset).
*/
void DPM_SetDebugLock(uint32_t u32dpm)
{
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_LOCK_Msk);
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_LOCK_Msk);
}
}
/**
* @brief Get Debug Disable
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @retval 0 Debug is not in disable status
* @retval 1 Debug is in disable status
* @details This macro gets Secure or Non-secure DPM debug disable status.
* If Secure debug is disabled, debugger cannot access Secure region and can access Non-secure region only.
* If Non-secure debug is disabled, debugger cannot access all Secure and Non-secure region.
*/
uint32_t DPM_GetDebugDisable(uint32_t u32dpm)
{
uint32_t u32RetVal = 0;
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
u32RetVal = (dpm->STS & DPM_STS_DBGDIS_Msk) >> DPM_STS_DBGDIS_Pos;
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
u32RetVal = (dpm->NSSTS & DPM_NSSTS_DBGDIS_Msk) >> DPM_NSSTS_DBGDIS_Pos;
}
return u32RetVal;
}
/**
* @brief Get Debug Lock
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @retval 0 Debug is not in lock status
* @retval 1 Debug is in lock status
* @details This macro gets Secure or Non-secure DPM debug disable status.
* If Secure debug is locked, debugger cannot access Secure region and can access Non-secure region only.
* If Non-secure debug is locked, debugger cannot access all Secure and Non-secure region.
*/
uint32_t DPM_GetDebugLock(uint32_t u32dpm)
{
uint32_t u32RetVal = 0;
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
u32RetVal = (dpm->STS & DPM_STS_LOCK_Msk) >> DPM_STS_LOCK_Pos;
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
u32RetVal = (dpm->NSSTS & DPM_NSSTS_LOCK_Msk) >> DPM_NSSTS_LOCK_Pos;
}
return u32RetVal;
}
/**
* @brief Update DPM Password
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @param[in] au32Password Password length is 256 bits.
* @retval 0 No password is updated. The password update count has reached the maximum value.
* @retval 1 Password update is successful.
* @details This macro updates Secure or Non-secure DPM password.
*/
uint32_t DPM_SetPasswordUpdate(uint32_t u32dpm, uint32_t au32Pwd[])
{
uint32_t u32i, u32RetVal = 0;
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
/* Set Secure DPM password */
for(u32i = 0; u32i < 4; u32i++)
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->SPW[u32i] = au32Pwd[u32i];
}
/* Set Secure DPM password update */
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_PWUPD_Msk);
/* Check Secure DPM password update flag */
while(dpm->STS & DPM_STS_BUSY_Msk);
u32RetVal = (dpm->STS & DPM_STS_PWUOK_Msk) >> DPM_STS_PWUOK_Pos;
/* Clear Secure DPM password update flag */
if(u32RetVal) dpm->STS = DPM_STS_PWUOK_Msk;
}
else /* Non-secure DPM */
{
/* Set Non-secure DPM password */
for(u32i = 0; u32i < 4; u32i++)
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSPW[u32i] = au32Pwd[u32i];
}
/* Set Non-secure DPM password update */
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_NSCTL_PWUPD_Msk);
/* Check Non-secure DPM password update flag */
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
u32RetVal = (dpm->NSSTS & DPM_NSSTS_PWUOK_Msk) >> DPM_NSSTS_PWUOK_Pos;
/* Clear Non-secure DPM password update flag */
if(u32RetVal) dpm->NSSTS = DPM_NSSTS_PWUOK_Msk;
}
return u32RetVal;
}
/**
* @brief Compare DPM Password
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @retval 0 The password comparison can be proccessed.
* @retval 1 No more password comparison can be proccessed. \n
* The password comparison fail times has reached the maximum value.
* @details This macro sets Secure or Non-secure DPM password comparison. \n
* The comparison result is checked by DPM_GetPasswordErrorFlag().
*/
uint32_t DPM_SetPasswordCompare(uint32_t u32dpm, uint32_t au32Pwd[])
{
uint32_t u32i, u32RetVal = 0;
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
/* Check Secure DPM password compare fail times maximum flag */
while(dpm->STS & DPM_STS_BUSY_Msk);
if(dpm->STS & DPM_STS_PWFMAX_Msk)
{
u32RetVal = 1;
}
else
{
/* Set Secure DPM password */
for(u32i = 0; u32i < 4; u32i++)
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->SPW[u32i] = au32Pwd[u32i];
}
/* Set Secure DPM password cpmpare */
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_PWCMP_Msk);
}
}
else /* Non-secure DPM */
{
/* Check Non-secure DPM password compare fail times maximum flag */
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
if(dpm->NSSTS & DPM_NSSTS_PWFMAX_Msk)
{
u32RetVal = 1;
}
else
{
/* Set Non-secure DPM password */
for(u32i = 0; u32i < 4; u32i++)
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSPW[u32i] = au32Pwd[u32i];
}
/* Set Non-secure DPM password compare */
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_PWCMP_Msk);
}
}
return u32RetVal;
}
/**
* @brief Get DPM Password Error Flag
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return Specified DPM module password compare error flag.
* @details This macro returns Secure or Non-secure DPM password compare error flag.
*/
uint32_t DPM_GetPasswordErrorFlag(uint32_t u32dpm)
{
uint32_t u32RetVal = 0;
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
/* Check Secure DPM password compare error flag */
while(dpm->STS & DPM_STS_BUSY_Msk);
u32RetVal = (dpm->STS & DPM_STS_PWCERR_Msk) >> DPM_STS_PWCERR_Pos;
}
else /* Non-secure DPM */
{
/* Check Non-secure DPM password compare error flag */
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
u32RetVal = (dpm->NSSTS & DPM_NSSTS_PWCERR_Msk) >> DPM_NSSTS_PWCERR_Pos;
}
return u32RetVal;
}
/**
* @brief Get DPM Interrupt Flag
* @param None
* @return Secure DPM interrupt flag.
* @details This macro returns Secure DPM interrupt flag.
* Secure DPM interrupt flag includes Secure and Non-secure DPM password compare error flag.
* This macro is for Secure DPM and Secure region only.
*/
uint32_t DPM_GetIntFlag(void)
{
while(DPM->STS & DPM_STS_BUSY_Msk);
return (DPM->STS & DPM_STS_INT_Msk) >> DPM_STS_INT_Pos;
}
/**
* @brief Clear DPM Password Error Flag
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return Specified DPM module interrupt flag.
* @details This macro clears Secure or Non-secure DPM password compare error flag.
*/
void DPM_ClearPasswordErrorFlag(uint32_t u32dpm)
{
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->STS = DPM_STS_PWCERR_Msk;
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSSTS = DPM_NSSTS_PWCERR_Msk;
}
}
/**
* @brief Enable Debugger Write Access
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return None.
* @details This macro enables external debugger to write Secure or Non-secure DPM registers.
*/
void DPM_EnableDebuggerWriteAccess(uint32_t u32dpm)
{
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (dpm->CTL & (~(DPM_CTL_RVCODE_Msk | DPM_CTL_DACCWDIS_Msk))) | DPM_CTL_WVCODE;
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~(DPM_NSCTL_RVCODE_Msk | DPM_NSCTL_DACCWDIS_Msk))) | DPM_NSCTL_WVCODE;
}
}
/**
* @brief Disable Debugger Write Access
* @param[in] u32dpm Select DPM module. Valid values are:
* - \ref SECURE_DPM
* - \ref NONSECURE_DPM
* @return None.
* @details This macro disables external debugger to write Secure or Non-secure DPM registers.
*/
void DPM_DisableDebuggerWriteAccess(uint32_t u32dpm)
{
DPM_T *dpm;
if(__PC()&NS_OFFSET) dpm = DPM_NS;
else dpm = DPM;
if(u32dpm == SECURE_DPM) /* Secure DPM */
{
while(dpm->STS & DPM_STS_BUSY_Msk);
dpm->CTL = (dpm->CTL & (~DPM_CTL_RVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_DACCWDIS_Msk);
}
else /* Non-secure DPM */
{
while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_RVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_DACCWDIS_Msk);
}
}
/**@}*/ /* end of group DPM_EXPORTED_FUNCTIONS */
/**@}*/ /* end of group DPM_Driver */
/**@}*/ /* end of group Standard_Driver */