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