1 /******************************************************************************
2 *
3 * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4 * Analog Devices, Inc.),
5 * Copyright (C) 2023-2024 Analog Devices, Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************************/
20
21 /**
22 * @file mxc_sys.c
23 * @brief System layer driver.
24 * @details This driver is used to control the system layer of the device.
25 */
26
27 /* **** Includes **** */
28 #include <stddef.h>
29 #include <string.h>
30 #include "mxc_device.h"
31 #include "mxc_assert.h"
32 #include "mxc_sys.h"
33 #include "mxc_delay.h"
34 #include "lpgcr_regs.h"
35 #include "gcr_regs.h"
36 #include "fcr_regs.h"
37 #include "mcr_regs.h"
38 #include "pwrseq_regs.h"
39 #include "aes.h"
40 #include "flc.h"
41
42 /**
43 * @ingroup mxc_sys
44 * @{
45 */
46
47 /* **** Definitions **** */
48 #define MXC_SYS_CLOCK_TIMEOUT MSEC(1)
49
50 // DAP Lock macros
51 #define INFOBLOCK_DAP_LOCK_OFFSET 0x30
52 #define DAP_LOCK_SEQUENCE_01 0x5A5AA5A5
53 #define DAP_LOCK_SEQUENCE_23 0xFFFFFFFF
54
55 /* **** Globals **** */
56
57 /* Symbol defined when loading RISCV image */
58 extern uint32_t _binary_riscv_bin_start;
59
60 /* **** Functions **** */
61
62 /* ************************************************************************** */
MXC_SYS_GetUSN(uint8_t * usn,uint8_t * checksum)63 int MXC_SYS_GetUSN(uint8_t *usn, uint8_t *checksum)
64 {
65 int err = E_NO_ERROR;
66 uint32_t *infoblock = (uint32_t *)MXC_INFO0_MEM_BASE;
67
68 if (usn == NULL) {
69 return E_NULL_PTR;
70 }
71
72 /* Read the USN from the info block */
73 MXC_FLC_UnlockInfoBlock(MXC_INFO0_MEM_BASE);
74
75 memset(usn, 0, MXC_SYS_USN_CHECKSUM_LEN);
76
77 usn[0] = (infoblock[0] & 0x007F8000) >> 15;
78 usn[1] = (infoblock[0] & 0x7F800000) >> 23;
79 usn[2] = (infoblock[1] & 0x0000007F) << 1;
80 usn[2] |= (infoblock[0] & 0x80000000) >> 31;
81 usn[3] = (infoblock[1] & 0x00007F80) >> 7;
82 usn[4] = (infoblock[1] & 0x007F8000) >> 15;
83 usn[5] = (infoblock[1] & 0x7F800000) >> 23;
84 usn[6] = (infoblock[2] & 0x007F8000) >> 15;
85 usn[7] = (infoblock[2] & 0x7F800000) >> 23;
86 usn[8] = (infoblock[3] & 0x0000007F) << 1;
87 usn[8] |= (infoblock[2] & 0x80000000) >> 31;
88 usn[9] = (infoblock[3] & 0x00007F80) >> 7;
89 usn[10] = (infoblock[3] & 0x007F8000) >> 15;
90
91 /* If requested, verify and return the checksum */
92 if (checksum != NULL) {
93 uint8_t check_csum[MXC_SYS_USN_CHECKSUM_LEN];
94 uint8_t aes_key[MXC_SYS_USN_CHECKSUM_LEN] = { 0 }; // NULL Key (per checksum spec)
95
96 checksum[0] = ((infoblock[3] & 0x7F800000) >> 23);
97 checksum[1] = ((infoblock[4] & 0x007F8000) >> 15);
98
99 err = MXC_AES_Init();
100 if (err) {
101 MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
102 return err;
103 }
104
105 // Set NULL Key
106 MXC_AES_SetExtKey((const void *)aes_key, MXC_AES_128BITS);
107
108 // Compute Checksum
109 mxc_aes_req_t aes_req;
110 aes_req.length = MXC_SYS_USN_CHECKSUM_LEN / 4;
111 aes_req.inputData = (uint32_t *)usn;
112 aes_req.resultData = (uint32_t *)check_csum;
113 aes_req.keySize = MXC_AES_128BITS;
114 aes_req.encryption = MXC_AES_ENCRYPT_EXT_KEY;
115 aes_req.callback = NULL;
116
117 err = MXC_AES_Generic(&aes_req);
118 if (err) {
119 MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
120 return err;
121 }
122
123 MXC_AES_Shutdown();
124
125 // Verify Checksum
126 if (check_csum[0] != checksum[1] || check_csum[1] != checksum[0]) {
127 MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
128 return E_INVALID;
129 }
130 }
131
132 /* Add the info block checksum to the USN */
133 usn[11] = ((infoblock[3] & 0x7F800000) >> 23);
134 usn[12] = ((infoblock[4] & 0x007F8000) >> 15);
135
136 MXC_FLC_LockInfoBlock(MXC_INFO0_MEM_BASE);
137
138 return err;
139 }
140
141 /* ************************************************************************** */
MXC_SYS_GetRevision(void)142 int MXC_SYS_GetRevision(void)
143 {
144 return MXC_GCR->revision;
145 }
146
147 /* ************************************************************************** */
MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)148 int MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)
149 {
150 /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
151 if (clock > 63) {
152 clock -= 64;
153 return !(MXC_LPGCR->pclkdis & (0x1 << clock));
154 } else if (clock > 31) {
155 clock -= 32;
156 return !(MXC_GCR->pclkdis1 & (0x1 << clock));
157 } else {
158 return !(MXC_GCR->pclkdis0 & (0x1 << clock));
159 }
160 }
161
162 /* ************************************************************************** */
MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)163 void MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)
164 {
165 /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
166 if (clock > 63) {
167 clock -= 64;
168 MXC_LPGCR->pclkdis |= (0x1 << clock);
169 } else if (clock > 31) {
170 clock -= 32;
171 MXC_GCR->pclkdis1 |= (0x1 << clock);
172 } else {
173 MXC_GCR->pclkdis0 |= (0x1 << clock);
174 }
175 }
176
177 /* ************************************************************************** */
MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)178 void MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)
179 {
180 /* The mxc_sys_periph_clock_t enum uses enum values that are the offset by 32 and 64 for the perckcn1 register. */
181 if (clock > 63) {
182 clock -= 64;
183 MXC_LPGCR->pclkdis &= ~(0x1 << clock);
184 } else if (clock > 31) {
185 clock -= 32;
186 MXC_GCR->pclkdis1 &= ~(0x1 << clock);
187 } else {
188 MXC_GCR->pclkdis0 &= ~(0x1 << clock);
189 }
190 }
191 /* ************************************************************************** */
MXC_SYS_RTCClockEnable()192 void MXC_SYS_RTCClockEnable()
193 {
194 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
195 }
196
197 /* ************************************************************************** */
MXC_SYS_RTCClockDisable(void)198 int MXC_SYS_RTCClockDisable(void)
199 {
200 /* Check that the RTC is not the system clock source */
201 if ((MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL) != MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ERTCO) {
202 MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ERTCO_EN;
203 return E_NO_ERROR;
204 } else {
205 return E_BAD_STATE;
206 }
207 }
208
209 #if TARGET_NUM == 32655
210 /******************************************************************************/
MXC_SYS_RTCClockPowerDownEn(void)211 void MXC_SYS_RTCClockPowerDownEn(void)
212 {
213 MXC_MCR->ctrl |= MXC_F_MCR_CTRL_32KOSC_EN;
214 }
215
216 /******************************************************************************/
MXC_SYS_RTCClockPowerDownDis(void)217 void MXC_SYS_RTCClockPowerDownDis(void)
218 {
219 MXC_MCR->ctrl &= ~MXC_F_MCR_CTRL_32KOSC_EN;
220 }
221 #endif //TARGET_NUM == 32655
222
223 /******************************************************************************/
MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)224 int MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)
225 {
226 switch (clock) {
227 case MXC_SYS_CLOCK_IPO:
228 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IPO_EN;
229 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IPO_RDY);
230 break;
231
232 case MXC_SYS_CLOCK_IBRO:
233 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
234 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IBRO_RDY);
235 break;
236
237 case MXC_SYS_CLOCK_EXTCLK:
238 // No "RDY" bit to monitor, so just configure the GPIO
239 return MXC_GPIO_Config(&gpio_cfg_extclk);
240 break;
241
242 case MXC_SYS_CLOCK_INRO:
243 // The 80k clock is always enabled
244 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_INRO_RDY);
245 break;
246
247 case MXC_SYS_CLOCK_ERFO:
248 MXC_GCR->btleldoctrl |= MXC_F_GCR_BTLELDOCTRL_LDOTXEN | MXC_F_GCR_BTLELDOCTRL_LDORXEN;
249
250 /* Initialize kickstart circuit
251 Select Kick start circuit clock source- IPO/ISO
252 */
253 MXC_FCR->erfoks = ((MXC_S_FCR_ERFOKS_KSCLKSEL_ISO)
254 /* Set Drive strengh - 0x1,0x2,0x3 */
255 | ((0x1) << MXC_F_FCR_ERFOKS_KSERFODRIVER_POS)
256 /* Set kick count 1-127 */
257 | (0x8)
258 /* Set double pulse length On/Off*/
259 | (0 & MXC_F_FCR_ERFOKS_KSERFO2X)
260 /* Enable On/Off */
261 | (MXC_F_FCR_ERFOKS_KSERFO_EN));
262
263 /* Enable ERFO */
264 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERFO_EN;
265 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERFO_RDY);
266 break;
267
268 case MXC_SYS_CLOCK_ERTCO:
269 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
270 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERTCO_RDY);
271 break;
272
273 default:
274 return E_BAD_PARAM;
275 break;
276 }
277 }
278
279 /******************************************************************************/
MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)280 int MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)
281 {
282 uint32_t current_clock;
283
284 current_clock = MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL;
285
286 // Don't turn off the clock we're running on
287 if (clock == current_clock) {
288 return E_BAD_PARAM;
289 }
290
291 switch (clock) {
292 case MXC_SYS_CLOCK_IPO:
293 MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_IPO_EN;
294 break;
295
296 case MXC_SYS_CLOCK_IBRO:
297 MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_IBRO_EN;
298 break;
299
300 case MXC_SYS_CLOCK_EXTCLK:
301 /*
302 There's not a great way to disable the external clock.
303 Deinitializing the GPIO here may have unintended consequences
304 for application code.
305 Selecting a different system clock source is sufficient
306 to "disable" the EXT_CLK source.
307 */
308 break;
309
310 case MXC_SYS_CLOCK_INRO:
311 // The 80k clock is always enabled
312 break;
313
314 case MXC_SYS_CLOCK_ERFO:
315 MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ERFO_EN;
316 break;
317
318 case MXC_SYS_CLOCK_ERTCO:
319 MXC_GCR->clkctrl &= ~MXC_F_GCR_CLKCTRL_ERTCO_EN;
320 break;
321
322 default:
323 return E_BAD_PARAM;
324 }
325
326 return E_NO_ERROR;
327 }
328
329 /* ************************************************************************** */
MXC_SYS_Clock_Timeout(uint32_t ready)330 int MXC_SYS_Clock_Timeout(uint32_t ready)
331 {
332 #ifdef __riscv
333 // The current RISC-V implementation is to block until the clock is ready.
334 // We do not have access to a system tick in the RV core.
335 while (!(MXC_GCR->clkctrl & ready)) {}
336 return E_NO_ERROR;
337 #else
338 #ifndef BOARD_ME17_TESTER
339 // Start timeout, wait for ready
340 MXC_DelayAsync(MXC_SYS_CLOCK_TIMEOUT, NULL);
341
342 do {
343 if (MXC_GCR->clkctrl & ready) {
344 MXC_DelayAbort();
345 return E_NO_ERROR;
346 }
347 } while (MXC_DelayCheck() == E_BUSY);
348
349 return E_TIME_OUT;
350 #else
351
352 return E_NO_ERROR;
353 #endif
354
355 #endif // __riscv
356 }
357 /* ************************************************************************** */
MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)358 int MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)
359 {
360 uint32_t current_clock;
361 int err = E_NO_ERROR;
362
363 // Save the current system clock
364 current_clock = MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL;
365
366 switch (clock) {
367 case MXC_SYS_CLOCK_ISO:
368
369 // Enable ISO clock
370 if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ISO_EN)) {
371 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ISO_EN;
372
373 // Check if ISO clock is ready
374 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ISO_RDY) != E_NO_ERROR) {
375 return E_TIME_OUT;
376 }
377 }
378
379 // Set ISO clock as System Clock
380 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
381 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ISO);
382
383 break;
384 case MXC_SYS_CLOCK_IPO:
385
386 // Enable IPO clock
387 if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IPO_EN)) {
388 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IPO_EN;
389
390 // Check if IPO clock is ready
391 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IPO_RDY) != E_NO_ERROR) {
392 return E_TIME_OUT;
393 }
394 }
395
396 // Set IPO clock as System Clock
397 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
398 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_IPO);
399
400 break;
401
402 case MXC_SYS_CLOCK_IBRO:
403
404 // Enable IBRO clock
405 if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IBRO_EN)) {
406 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN;
407
408 // Check if IBRO clock is ready
409 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_IBRO_RDY) != E_NO_ERROR) {
410 return E_TIME_OUT;
411 }
412 }
413
414 // Set IBRO clock as System Clock
415 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
416 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_IBRO);
417
418 break;
419
420 case MXC_SYS_CLOCK_EXTCLK:
421 /*
422 There's not "EXT_CLK RDY" bit for the ME17, so we'll
423 blindly enable (configure GPIO) the external clock every time.
424 */
425 err = MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_EXTCLK);
426 if (err)
427 return err;
428
429 // Set EXT clock as System Clock
430 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
431 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_EXTCLK);
432
433 break;
434
435 case MXC_SYS_CLOCK_ERFO:
436
437 // Enable ERFO clock
438 if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ERFO_EN)) {
439 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERFO_EN;
440
441 // Check if ERFO clock is ready
442 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERFO_RDY) != E_NO_ERROR) {
443 return E_TIME_OUT;
444 }
445 }
446
447 // Set ERFO clock as System Clock
448 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
449 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ERFO);
450
451 break;
452
453 case MXC_SYS_CLOCK_INRO:
454 // Set INRO clock as System Clock
455 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
456 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_INRO);
457
458 break;
459
460 case MXC_SYS_CLOCK_ERTCO:
461
462 // Enable ERTCO clock
463 if (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ERTCO_EN)) {
464 MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN;
465
466 // Check if ERTCO clock is ready
467 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_ERTCO_RDY) != E_NO_ERROR) {
468 return E_TIME_OUT;
469 }
470 }
471
472 // Set ERTCO clock as System Clock
473 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL,
474 MXC_S_GCR_CLKCTRL_SYSCLK_SEL_ERTCO);
475
476 break;
477
478 default:
479 return E_BAD_PARAM;
480 }
481
482 // Wait for system clock to be ready
483 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLKCTRL_SYSCLK_RDY) != E_NO_ERROR) {
484 // Restore the old system clock if timeout
485 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_SEL, current_clock);
486
487 return E_TIME_OUT;
488 }
489
490 // Update the system core clock
491 SystemCoreClockUpdate();
492
493 return E_NO_ERROR;
494 }
495
496 /* ************************************************************************** */
MXC_SYS_SetClockDiv(mxc_sys_system_clock_div_t div)497 void MXC_SYS_SetClockDiv(mxc_sys_system_clock_div_t div)
498 {
499 /* Return if this setting is already current */
500 if (div == MXC_SYS_GetClockDiv()) {
501 return;
502 }
503
504 MXC_SETFIELD(MXC_GCR->clkctrl, MXC_F_GCR_CLKCTRL_SYSCLK_DIV, div);
505
506 SystemCoreClockUpdate();
507 }
508
509 /* ************************************************************************** */
MXC_SYS_GetClockDiv(void)510 mxc_sys_system_clock_div_t MXC_SYS_GetClockDiv(void)
511 {
512 return (MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_DIV);
513 }
514
515 /* ************************************************************************** */
MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)516 void MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)
517 {
518 /* The mxc_sys_reset_t enum uses enum values that are the offset by 32 and 64 for the rst register. */
519 if (reset > 63) {
520 reset -= 64;
521 MXC_LPGCR->rst = (0x1 << reset);
522 while (MXC_LPGCR->rst & (0x1 << reset)) {}
523 } else if (reset > 31) {
524 reset -= 32;
525 MXC_GCR->rst1 = (0x1 << reset);
526 while (MXC_GCR->rst1 & (0x1 << reset)) {}
527 } else {
528 MXC_GCR->rst0 = (0x1 << reset);
529 while (MXC_GCR->rst0 & (0x1 << reset)) {}
530 }
531 }
532
533 /* ************************************************************************** */
MXC_SYS_RISCVRun(void)534 void MXC_SYS_RISCVRun(void)
535 {
536 /* Disable the the RSCV */
537 MXC_GCR->pclkdis1 |= MXC_F_GCR_PCLKDIS1_CPU1;
538
539 /* Set the interrupt vector base address */
540 MXC_FCR->urvbootaddr = (uint32_t)&_binary_riscv_bin_start;
541
542 /* Power up the RSCV */
543 MXC_GCR->pclkdis1 &= ~(MXC_F_GCR_PCLKDIS1_CPU1);
544
545 /* CPU1 reset */
546 MXC_GCR->rst1 |= MXC_F_GCR_RST1_CPU1;
547 }
548
549 /* ************************************************************************** */
MXC_SYS_RISCVShutdown(void)550 void MXC_SYS_RISCVShutdown(void)
551 {
552 /* Disable the the RSCV */
553 MXC_GCR->pclkdis1 |= MXC_F_GCR_PCLKDIS1_CPU1;
554 }
555
556 /* ************************************************************************** */
MXC_SYS_RiscVClockRate(void)557 uint32_t MXC_SYS_RiscVClockRate(void)
558 {
559 // If in LPM mode and the PCLK is selected as the RV32 clock source,
560 if (((MXC_GCR->pm & MXC_F_GCR_PM_MODE) == MXC_S_GCR_PM_MODE_LPM) &&
561 (MXC_PWRSEQ->lpcn & MXC_F_PWRSEQ_LPCN_LPMCLKSEL)) {
562 return ISO_FREQ;
563 } else {
564 return PeripheralClock;
565 }
566 }
567
568 /* ************************************************************************** */
MXC_SYS_LockDAP_Permanent(void)569 int MXC_SYS_LockDAP_Permanent(void)
570 {
571 #ifdef DEBUG
572 // Locking the DAP is not supported while in DEBUG.
573 // To use this function, build for release ("make release")
574 // or set DEBUG = 0
575 // (see https://analogdevicesinc.github.io/msdk/USERGUIDE/#build-tables)
576 return E_NOT_SUPPORTED;
577 #else
578 int err;
579 uint32_t info_blk_addr;
580 uint32_t lock_sequence[4];
581
582 // Infoblock address to write lock sequence to
583 info_blk_addr = MXC_INFO_MEM_BASE + INFOBLOCK_DAP_LOCK_OFFSET;
584
585 // Set lock sequence
586 lock_sequence[0] = DAP_LOCK_SEQUENCE_01;
587 lock_sequence[1] = DAP_LOCK_SEQUENCE_01;
588 lock_sequence[2] = DAP_LOCK_SEQUENCE_23;
589 lock_sequence[3] = DAP_LOCK_SEQUENCE_23;
590
591 // Initialize FLC
592 MXC_FLC_Init();
593
594 // Unlock infoblock
595 MXC_FLC_UnlockInfoBlock(info_blk_addr);
596
597 // Write DAP lock sequence to infoblock
598 err = MXC_FLC_Write128(info_blk_addr, lock_sequence);
599
600 // Re-lock infoblock
601 MXC_FLC_LockInfoBlock(info_blk_addr);
602
603 return err;
604 #endif
605 }
606
607 /**@} end of mxc_sys */
608