1 /**************************************************************************//**
2  * @file     dpm.c
3  * @version  V3.00
4  * @brief    Debug Protection Mechanism (DPM) driver source file
5  *
6  * @copyright SPDX-License-Identifier: Apache-2.0
7  * @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
8  *****************************************************************************/
9 #include "NuMicro.h"
10 
11 
12 /** @addtogroup Standard_Driver Standard Driver
13   @{
14 */
15 
16 /** @addtogroup DPM_Driver DPM Driver
17   @{
18 */
19 
20 /** @addtogroup DPM_EXPORTED_FUNCTIONS DPM Exported Functions
21   @{
22 */
23 
24 /**
25   * @brief      Set Debug Disable
26   * @param[in]  u32dpm  The pointer of the specified DPM module
27   *                     - \ref SECURE_DPM
28   *                     - \ref NONSECURE_DPM
29   * @return     None
30   * @details    This macro sets Secure or Non-secure DPM debug disable.
31   *             The debug disable function works after reset (chip reset or pin reset).
32   */
DPM_SetDebugDisable(uint32_t u32dpm)33 void DPM_SetDebugDisable(uint32_t u32dpm)
34 {
35     DPM_T *dpm;
36 
37     if(__PC()&NS_OFFSET) dpm = DPM_NS;
38     else dpm = DPM;
39 
40     if(u32dpm == SECURE_DPM) /* Secure DPM */
41     {
42         while(dpm->STS & DPM_STS_BUSY_Msk);
43         dpm->CTL = (DPM->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_DBGDIS_Msk);
44     }
45     else    /* Non-secure DPM */
46     {
47         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
48         dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_DBGDIS_Msk);
49     }
50 }
51 
52 /**
53   * @brief      Set Debug Lock
54   * @param[in]  u32dpm  Select DPM module. Valid values are:
55   *                     - \ref SECURE_DPM
56   *                     - \ref NONSECURE_DPM
57   * @return     None
58   * @details    This macro sets Secure or Non-secure DPM debug lock.
59   *             The debug lock function works after reset (chip reset or pin reset).
60   */
DPM_SetDebugLock(uint32_t u32dpm)61 void DPM_SetDebugLock(uint32_t u32dpm)
62 {
63     DPM_T *dpm;
64 
65     if(__PC()&NS_OFFSET) dpm = DPM_NS;
66     else dpm = DPM;
67 
68     if(u32dpm == SECURE_DPM) /* Secure DPM */
69     {
70         while(dpm->STS & DPM_STS_BUSY_Msk);
71         dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_LOCK_Msk);
72     }
73     else    /* Non-secure DPM */
74     {
75         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
76         dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_LOCK_Msk);
77     }
78 }
79 
80 /**
81   * @brief      Get Debug Disable
82   * @param[in]  u32dpm  Select DPM module. Valid values are:
83   *                     - \ref SECURE_DPM
84   *                     - \ref NONSECURE_DPM
85   * @retval     0   Debug is not in disable status
86   * @retval     1   Debug is in disable status
87   * @details    This macro gets Secure or Non-secure DPM debug disable status.
88   *             If Secure debug is disabled, debugger cannot access Secure region and can access Non-secure region only.
89   *             If Non-secure debug is disabled, debugger cannot access all Secure and Non-secure region.
90   */
DPM_GetDebugDisable(uint32_t u32dpm)91 uint32_t DPM_GetDebugDisable(uint32_t u32dpm)
92 {
93     uint32_t u32RetVal = 0;
94     DPM_T *dpm;
95 
96     if(__PC()&NS_OFFSET) dpm = DPM_NS;
97     else dpm = DPM;
98 
99     if(u32dpm == SECURE_DPM) /* Secure DPM */
100     {
101         while(dpm->STS & DPM_STS_BUSY_Msk);
102         u32RetVal = (dpm->STS & DPM_STS_DBGDIS_Msk) >> DPM_STS_DBGDIS_Pos;
103     }
104     else    /* Non-secure DPM */
105     {
106         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
107         u32RetVal = (dpm->NSSTS & DPM_NSSTS_DBGDIS_Msk) >> DPM_NSSTS_DBGDIS_Pos;
108     }
109 
110     return u32RetVal;
111 }
112 
113 /**
114   * @brief      Get Debug Lock
115   * @param[in]  u32dpm  Select DPM module. Valid values are:
116   *                     - \ref SECURE_DPM
117   *                     - \ref NONSECURE_DPM
118   * @retval     0   Debug is not in lock status
119   * @retval     1   Debug is in lock status
120   * @details    This macro gets Secure or Non-secure DPM debug disable status.
121   *             If Secure debug is locked, debugger cannot access Secure region and can access Non-secure region only.
122   *             If Non-secure debug is locked, debugger cannot access all Secure and Non-secure region.
123   */
DPM_GetDebugLock(uint32_t u32dpm)124 uint32_t DPM_GetDebugLock(uint32_t u32dpm)
125 {
126     uint32_t u32RetVal = 0;
127     DPM_T *dpm;
128 
129     if(__PC()&NS_OFFSET) dpm = DPM_NS;
130     else dpm = DPM;
131 
132     if(u32dpm == SECURE_DPM) /* Secure DPM */
133     {
134         while(dpm->STS & DPM_STS_BUSY_Msk);
135         u32RetVal = (dpm->STS & DPM_STS_LOCK_Msk) >> DPM_STS_LOCK_Pos;
136     }
137     else                    /* Non-secure DPM */
138     {
139         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
140         u32RetVal = (dpm->NSSTS & DPM_NSSTS_LOCK_Msk) >> DPM_NSSTS_LOCK_Pos;
141     }
142 
143     return u32RetVal;
144 }
145 
146 /**
147   * @brief      Update DPM Password
148   * @param[in]  u32dpm        Select DPM module. Valid values are:
149   *                           - \ref SECURE_DPM
150   *                           - \ref NONSECURE_DPM
151   * @param[in]  au32Password  Password length is 256 bits.
152   * @retval     0   No password is updated. The password update count has reached the maximum value.
153   * @retval     1   Password update is successful.
154   * @details    This macro updates Secure or Non-secure DPM password.
155   */
DPM_SetPasswordUpdate(uint32_t u32dpm,uint32_t au32Pwd[])156 uint32_t DPM_SetPasswordUpdate(uint32_t u32dpm, uint32_t au32Pwd[])
157 {
158     uint32_t u32i, u32RetVal = 0;
159     DPM_T *dpm;
160 
161     if(__PC()&NS_OFFSET) dpm = DPM_NS;
162     else dpm = DPM;
163 
164     if(u32dpm == SECURE_DPM) /* Secure DPM */
165     {
166         /* Set Secure DPM password */
167         for(u32i = 0; u32i < 4; u32i++)
168         {
169             while(dpm->STS & DPM_STS_BUSY_Msk);
170             dpm->SPW[u32i] = au32Pwd[u32i];
171         }
172 
173         /* Set Secure DPM password update */
174         while(dpm->STS & DPM_STS_BUSY_Msk);
175         dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_PWUPD_Msk);
176 
177         /* Check Secure DPM password update flag */
178         while(dpm->STS & DPM_STS_BUSY_Msk);
179         u32RetVal = (dpm->STS & DPM_STS_PWUOK_Msk) >> DPM_STS_PWUOK_Pos;
180 
181         /* Clear Secure DPM password update flag */
182         if(u32RetVal) dpm->STS = DPM_STS_PWUOK_Msk;
183     }
184     else    /* Non-secure DPM */
185     {
186         /* Set Non-secure DPM password */
187         for(u32i = 0; u32i < 4; u32i++)
188         {
189             while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
190             dpm->NSPW[u32i] = au32Pwd[u32i];
191         }
192 
193         /* Set Non-secure DPM password update */
194         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
195         dpm->NSCTL = (dpm->NSCTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_NSCTL_PWUPD_Msk);
196 
197         /* Check Non-secure DPM password update flag */
198         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
199         u32RetVal = (dpm->NSSTS & DPM_NSSTS_PWUOK_Msk) >> DPM_NSSTS_PWUOK_Pos;
200 
201         /* Clear Non-secure DPM password update flag */
202         if(u32RetVal) dpm->NSSTS = DPM_NSSTS_PWUOK_Msk;
203     }
204 
205     return u32RetVal;
206 }
207 
208 /**
209   * @brief      Compare DPM Password
210   * @param[in]  u32dpm  Select DPM module. Valid values are:
211   *                     - \ref SECURE_DPM
212   *                     - \ref NONSECURE_DPM
213   * @retval     0   The password comparison can be proccessed.
214   * @retval     1   No more password comparison can be proccessed. \n
215   *                 The password comparison fail times has reached the maximum value.
216   * @details    This macro sets Secure or Non-secure DPM password comparison. \n
217   *             The comparison result is checked by DPM_GetPasswordErrorFlag().
218   */
DPM_SetPasswordCompare(uint32_t u32dpm,uint32_t au32Pwd[])219 uint32_t DPM_SetPasswordCompare(uint32_t u32dpm, uint32_t au32Pwd[])
220 {
221     uint32_t u32i, u32RetVal = 0;
222     DPM_T *dpm;
223 
224     if(__PC()&NS_OFFSET) dpm = DPM_NS;
225     else dpm = DPM;
226 
227     if(u32dpm == SECURE_DPM) /* Secure DPM */
228     {
229         /* Check Secure DPM password compare fail times maximum flag */
230         while(dpm->STS & DPM_STS_BUSY_Msk);
231         if(dpm->STS & DPM_STS_PWFMAX_Msk)
232         {
233             u32RetVal = 1;
234         }
235         else
236         {
237             /* Set Secure DPM password */
238             for(u32i = 0; u32i < 4; u32i++)
239             {
240                 while(dpm->STS & DPM_STS_BUSY_Msk);
241                 dpm->SPW[u32i] = au32Pwd[u32i];
242             }
243 
244             /* Set Secure DPM password cpmpare */
245             while(dpm->STS & DPM_STS_BUSY_Msk);
246             dpm->CTL = (dpm->CTL & (~DPM_CTL_WVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_PWCMP_Msk);
247         }
248     }
249     else    /* Non-secure DPM */
250     {
251         /* Check Non-secure DPM password compare fail times maximum flag */
252         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
253         if(dpm->NSSTS & DPM_NSSTS_PWFMAX_Msk)
254         {
255             u32RetVal = 1;
256         }
257         else
258         {
259             /* Set Non-secure DPM password */
260             for(u32i = 0; u32i < 4; u32i++)
261             {
262                 while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
263                 dpm->NSPW[u32i] = au32Pwd[u32i];
264             }
265 
266             /* Set Non-secure DPM password compare */
267             while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
268             dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_WVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_PWCMP_Msk);
269         }
270     }
271 
272     return u32RetVal;
273 }
274 
275 /**
276   * @brief      Get DPM Password Error Flag
277   * @param[in]  u32dpm        Select DPM module. Valid values are:
278   *                           - \ref SECURE_DPM
279   *                           - \ref NONSECURE_DPM
280   * @return     Specified DPM module password compare error flag.
281   * @details    This macro returns Secure or Non-secure DPM password compare error flag.
282   */
DPM_GetPasswordErrorFlag(uint32_t u32dpm)283 uint32_t DPM_GetPasswordErrorFlag(uint32_t u32dpm)
284 {
285     uint32_t u32RetVal = 0;
286     DPM_T *dpm;
287 
288     if(__PC()&NS_OFFSET) dpm = DPM_NS;
289     else dpm = DPM;
290 
291     if(u32dpm == SECURE_DPM) /* Secure DPM */
292     {
293         /* Check Secure DPM password compare error flag */
294         while(dpm->STS & DPM_STS_BUSY_Msk);
295         u32RetVal = (dpm->STS & DPM_STS_PWCERR_Msk) >> DPM_STS_PWCERR_Pos;
296     }
297     else    /* Non-secure DPM */
298     {
299         /* Check Non-secure DPM password compare error flag */
300         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
301         u32RetVal = (dpm->NSSTS & DPM_NSSTS_PWCERR_Msk) >> DPM_NSSTS_PWCERR_Pos;
302     }
303 
304     return u32RetVal;
305 }
306 
307 /**
308   * @brief      Get DPM Interrupt Flag
309   * @param      None
310   * @return     Secure DPM interrupt flag.
311   * @details    This macro returns Secure DPM interrupt flag.
312   *             Secure DPM interrupt flag includes Secure and Non-secure DPM password compare error flag.
313   *             This macro is for Secure DPM and Secure region only.
314   */
DPM_GetIntFlag(void)315 uint32_t DPM_GetIntFlag(void)
316 {
317     while(DPM->STS & DPM_STS_BUSY_Msk);
318     return (DPM->STS & DPM_STS_INT_Msk) >> DPM_STS_INT_Pos;
319 }
320 
321 
322 /**
323   * @brief      Clear DPM Password Error Flag
324   * @param[in]  u32dpm        Select DPM module. Valid values are:
325   *                           - \ref SECURE_DPM
326   *                           - \ref NONSECURE_DPM
327   * @return     Specified DPM module interrupt flag.
328   * @details    This macro clears Secure or Non-secure DPM password compare error flag.
329   */
DPM_ClearPasswordErrorFlag(uint32_t u32dpm)330 void DPM_ClearPasswordErrorFlag(uint32_t u32dpm)
331 {
332     DPM_T *dpm;
333 
334     if(__PC()&NS_OFFSET) dpm = DPM_NS;
335     else dpm = DPM;
336 
337     if(u32dpm == SECURE_DPM) /* Secure DPM */
338     {
339         while(dpm->STS & DPM_STS_BUSY_Msk);
340         dpm->STS = DPM_STS_PWCERR_Msk;
341     }
342     else    /* Non-secure DPM */
343     {
344         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
345         dpm->NSSTS = DPM_NSSTS_PWCERR_Msk;
346     }
347 }
348 
349 /**
350   * @brief      Enable Debugger Write Access
351   * @param[in]  u32dpm        Select DPM module. Valid values are:
352   *                           - \ref SECURE_DPM
353   *                           - \ref NONSECURE_DPM
354   * @return     None.
355   * @details    This macro enables external debugger to write Secure or Non-secure DPM registers.
356   */
DPM_EnableDebuggerWriteAccess(uint32_t u32dpm)357 void DPM_EnableDebuggerWriteAccess(uint32_t u32dpm)
358 {
359     DPM_T *dpm;
360 
361     if(__PC()&NS_OFFSET) dpm = DPM_NS;
362     else dpm = DPM;
363 
364     if(u32dpm == SECURE_DPM) /* Secure DPM */
365     {
366         while(dpm->STS & DPM_STS_BUSY_Msk);
367         dpm->CTL = (dpm->CTL & (~(DPM_CTL_RVCODE_Msk | DPM_CTL_DACCWDIS_Msk))) | DPM_CTL_WVCODE;
368     }
369     else    /* Non-secure DPM */
370     {
371         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
372         dpm->NSCTL = (dpm->NSCTL & (~(DPM_NSCTL_RVCODE_Msk | DPM_NSCTL_DACCWDIS_Msk))) | DPM_NSCTL_WVCODE;
373     }
374 }
375 
376 /**
377   * @brief      Disable Debugger Write Access
378   * @param[in]  u32dpm        Select DPM module. Valid values are:
379   *                           - \ref SECURE_DPM
380   *                           - \ref NONSECURE_DPM
381   * @return     None.
382   * @details    This macro disables external debugger to write Secure or Non-secure DPM registers.
383   */
DPM_DisableDebuggerWriteAccess(uint32_t u32dpm)384 void DPM_DisableDebuggerWriteAccess(uint32_t u32dpm)
385 {
386     DPM_T *dpm;
387 
388     if(__PC()&NS_OFFSET) dpm = DPM_NS;
389     else dpm = DPM;
390 
391     if(u32dpm == SECURE_DPM) /* Secure DPM */
392     {
393         while(dpm->STS & DPM_STS_BUSY_Msk);
394         dpm->CTL = (dpm->CTL & (~DPM_CTL_RVCODE_Msk)) | (DPM_CTL_WVCODE | DPM_CTL_DACCWDIS_Msk);
395     }
396     else    /* Non-secure DPM */
397     {
398         while(dpm->NSSTS & DPM_NSSTS_BUSY_Msk);
399         dpm->NSCTL = (dpm->NSCTL & (~DPM_NSCTL_RVCODE_Msk)) | (DPM_NSCTL_WVCODE | DPM_NSCTL_DACCWDIS_Msk);
400     }
401 }
402 
403 
404 /**@}*/ /* end of group DPM_EXPORTED_FUNCTIONS */
405 
406 /**@}*/ /* end of group DPM_Driver */
407 
408 /**@}*/ /* end of group Standard_Driver */
409