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