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 /* **** Includes **** */
22 #include <stddef.h>
23 #include "mxc_errors.h"
24 #include "mxc_assert.h"
25 #include "mxc_sys.h"
26 #include "gpio.h"
27 #include "mxc_pins.h"
28 #include "gcr_regs.h"
29 #include "tmr_regs.h"
30 #include "flc_regs.h"
31 #include "icc_regs.h"
32 #include "nbbfc_regs.h"
33 #include "mxc_delay.h"
34 #include "sdhc_regs.h"
35 #include "usbhs_regs.h"
36 #include "bbfc_regs.h"
37 #include "hpb_regs.h"
38 #include "rtc.h"
39 #include "flc.h"
40 #include "pwrseq_regs.h"
41
42 /* **** Definitions **** */
43 #define SYS_CLOCK_TIMEOUT MXC_DELAY_MSEC(1)
44
45 #define SYS_RTC_CLK 32768UL
46
47 // DAP Lock macros
48 #define INFOBLOCK_DAP_LOCK_OFFSET 0x30
49 #define DAP_LOCK_SEQUENCE_01 0x5A5AA5A5
50 #define DAP_LOCK_SEQUENCE_23 0xFFFFFFFF
51
52 /* **** Globals **** */
53
54 /* **** Functions **** */
55
56 /* ************************************************************************** */
MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)57 int MXC_SYS_IsClockEnabled(mxc_sys_periph_clock_t clock)
58 {
59 /* The sys_periph_clock_t enum uses enum values that are the offset by 32 for the perckcn1 register. */
60 if (clock > 31) {
61 clock -= 32;
62 return !(MXC_GCR->pclk_dis1 & (0x1 << clock));
63 } else {
64 return !(MXC_GCR->pclk_dis0 & (0x1 << clock));
65 }
66 }
67
68 /* ************************************************************************** */
MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)69 int MXC_SYS_ClockDisable(mxc_sys_periph_clock_t clock)
70 {
71 /* The sys_periph_clock_t enum uses enum values that are the offset by 32 for the perckcn1 register. */
72 if (clock > 31) {
73 clock -= 32;
74 MXC_GCR->pclk_dis1 |= (0x1 << clock);
75 } else {
76 MXC_GCR->pclk_dis0 |= (0x1 << clock);
77 }
78
79 return E_NO_ERROR;
80 }
81
82 /* ************************************************************************** */
MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)83 int MXC_SYS_ClockEnable(mxc_sys_periph_clock_t clock)
84 {
85 /* The sys_periph_clock_t enum uses enum values that are the offset by 32 for the perckcn1 register. */
86 if (clock > 31) {
87 clock -= 32;
88 MXC_GCR->pclk_dis1 &= ~(0x1 << clock);
89 } else {
90 MXC_GCR->pclk_dis0 &= ~(0x1 << clock);
91 }
92
93 return E_NO_ERROR;
94 }
95
96 /* ************************************************************************** */
MXC_SYS_RTCClockEnable(void)97 int MXC_SYS_RTCClockEnable(void)
98 {
99 // Enable 32k Oscillator
100 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_X32K_EN;
101
102 // Check if 32k clock is ready
103 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_X32K_RDY) != E_NO_ERROR) {
104 return E_TIME_OUT;
105 }
106
107 return E_NO_ERROR;
108 }
109
110 /* ************************************************************************** */
MXC_SYS_RTCClockDisable(void)111 int MXC_SYS_RTCClockDisable(void)
112 {
113 // Enable 32k Oscillator
114 MXC_GCR->clk_ctrl &= (~MXC_F_GCR_CLK_CTRL_X32K_EN);
115 return E_NO_ERROR;
116 }
117
118 /**
119 * @brief Disable System Clock Source
120 * @param clock The clock to disable
121 * @return E_NO_ERROR if everything is successful
122 */
MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)123 int MXC_SYS_ClockSourceDisable(mxc_sys_system_clock_t clock)
124 {
125 uint32_t current_clock;
126
127 current_clock = MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_SYSOSC_SEL;
128
129 // Don't turn off the clock we're running on
130 if (clock == current_clock) {
131 return E_BAD_PARAM;
132 }
133
134 switch (clock) {
135 case MXC_SYS_CLOCK_CRYPTO:
136 MXC_GCR->clk_ctrl &= ~MXC_F_GCR_CLK_CTRL_CRYPTO_EN;
137 break;
138 case MXC_SYS_CLOCK_NANORING: //Always enabled
139 break;
140 case MXC_SYS_CLOCK_HIRC96:
141 MXC_GCR->clk_ctrl &= ~MXC_F_GCR_CLK_CTRL_HIRC96_EN;
142 break;
143 case MXC_SYS_CLOCK_HIRC8:
144 MXC_GCR->clk_ctrl &= ~MXC_F_GCR_CLK_CTRL_HIRC8_EN;
145 break;
146 case MXC_SYS_CLOCK_X32K:
147 MXC_GCR->clk_ctrl &= ~MXC_F_GCR_CLK_CTRL_X32K_EN;
148 break;
149 default:
150 return E_BAD_PARAM;
151 }
152
153 return E_NO_ERROR;
154 }
155
156 /**
157 * @brief Enable System Clock Source without switching to it
158 * @param clock The clock to enable
159 * @return E_NO_ERROR if everything is successful
160 */
MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)161 int MXC_SYS_ClockSourceEnable(mxc_sys_system_clock_t clock)
162 {
163 switch (clock) {
164 case MXC_SYS_CLOCK_CRYPTO:
165 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_CRYPTO_EN;
166 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_CRYPTO_RDY);
167 case MXC_SYS_CLOCK_NANORING: //Always enabled
168 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_NANORING_RDY);
169 case MXC_SYS_CLOCK_HIRC96:
170 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC96_EN;
171 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC96_RDY);
172 case MXC_SYS_CLOCK_HIRC8:
173 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC8_EN;
174 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC8_RDY);
175 case MXC_SYS_CLOCK_X32K:
176 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_X32K_EN;
177 return MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_X32K_RDY);
178 default:
179 return E_BAD_PARAM;
180 }
181
182 return E_NO_ERROR;
183 }
184
185 /* ************************************************************************** */
MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)186 int MXC_SYS_Clock_Select(mxc_sys_system_clock_t clock)
187 {
188 uint32_t current_clock;
189
190 // Save the current system clock
191 current_clock = MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_SYSOSC_SEL;
192
193 switch (clock) {
194 case MXC_SYS_CLOCK_CRYPTO:
195 // Enable CRYPTO clock
196 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_CRYPTO_EN;
197
198 // Check if CRYPTO clock is ready
199 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_CRYPTO_RDY) != E_NO_ERROR) {
200 return E_TIME_OUT;
201 }
202
203 // Set CRYPTO clock as System Clock
204 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL,
205 MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_CRYPTO);
206
207 break;
208 case MXC_SYS_CLOCK_NANORING:
209 // Check if NANORING clock is ready
210 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_NANORING_RDY) != E_NO_ERROR) {
211 return E_TIME_OUT;
212 }
213
214 // Set NANORING clock as System Clock
215 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL,
216 MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_NANORING);
217
218 break;
219 case MXC_SYS_CLOCK_HIRC96:
220 // Enable HIRC96 clock
221 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC96_EN;
222
223 // Check if HIRC96 clock is ready
224 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC96_RDY) != E_NO_ERROR) {
225 return E_TIME_OUT;
226 }
227
228 // Set HIRC96 clock as System Clock
229 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL,
230 MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_HIRC96);
231
232 break;
233 case MXC_SYS_CLOCK_HIRC8:
234 // Enable HIRC8 clock
235 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC8_EN;
236
237 // Check if HIRC8 clock is ready
238 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC8_RDY) != E_NO_ERROR) {
239 return E_TIME_OUT;
240 }
241
242 // Set HIRC8 clock as System Clock
243 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL,
244 MXC_S_GCR_CLK_CTRL_SYSOSC_SEL_HIRC8);
245
246 break;
247 case MXC_SYS_CLOCK_HFXIN:
248 case MXC_SYS_CLOCK_X32K:
249 // Enable 32k Oscillator
250 MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_X32K_EN;
251
252 // Check if 32k clock is ready
253 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_X32K_RDY) != E_NO_ERROR) {
254 return E_TIME_OUT;
255 }
256
257 // Set 32k clock as System Clock
258 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL, MXC_F_GCR_CLK_CTRL_X32K_RDY);
259
260 break;
261 default:
262 return E_BAD_PARAM;
263 }
264
265 // Wait for system clock to be ready
266 if (MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_SYSOSC_RDY) != E_NO_ERROR) {
267 // Restore the old system clock if timeout
268 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSOSC_SEL, current_clock);
269
270 return E_TIME_OUT;
271 }
272
273 // Disable other clocks
274 switch (clock) {
275 case MXC_SYS_CLOCK_CRYPTO:
276 MXC_GCR->clk_ctrl &= ~(MXC_F_GCR_CLK_CTRL_X32K_EN | MXC_F_GCR_CLK_CTRL_HIRC96_EN |
277 MXC_F_GCR_CLK_CTRL_HIRC8_EN);
278 break;
279
280 case MXC_SYS_CLOCK_NANORING:
281 MXC_GCR->clk_ctrl &= ~(MXC_F_GCR_CLK_CTRL_X32K_EN | MXC_F_GCR_CLK_CTRL_CRYPTO_EN |
282 MXC_F_GCR_CLK_CTRL_HIRC96_EN | MXC_F_GCR_CLK_CTRL_HIRC8_EN);
283 break;
284
285 case MXC_SYS_CLOCK_HIRC96:
286 MXC_GCR->clk_ctrl &= ~(MXC_F_GCR_CLK_CTRL_X32K_EN | MXC_F_GCR_CLK_CTRL_CRYPTO_EN |
287 MXC_F_GCR_CLK_CTRL_HIRC8_EN);
288 break;
289
290 case MXC_SYS_CLOCK_HIRC8:
291 MXC_GCR->clk_ctrl &= ~(MXC_F_GCR_CLK_CTRL_X32K_EN | MXC_F_GCR_CLK_CTRL_CRYPTO_EN |
292 MXC_F_GCR_CLK_CTRL_HIRC96_EN);
293 break;
294
295 case MXC_SYS_CLOCK_HFXIN:
296 case MXC_SYS_CLOCK_X32K:
297 MXC_GCR->clk_ctrl &= ~(MXC_F_GCR_CLK_CTRL_CRYPTO_EN | MXC_F_GCR_CLK_CTRL_HIRC96_EN |
298 MXC_F_GCR_CLK_CTRL_HIRC8_EN);
299 break;
300 }
301
302 // Update the system core clock
303 SystemCoreClockUpdate();
304
305 return E_NO_ERROR;
306 }
307
308 /**
309 * @brief Select the system clock divider.
310 * @param clock Enumeration for desired system clock divider.
311 */
MXC_SYS_Clock_Div(mxc_sys_system_div_t div)312 void MXC_SYS_Clock_Div(mxc_sys_system_div_t div)
313 {
314 MXC_SETFIELD(MXC_GCR->clk_ctrl, MXC_F_GCR_CLK_CTRL_SYSCLK_PRESCALE, div);
315
316 // Update the system core clock
317 SystemCoreClockUpdate();
318 }
319
320 /* ************************************************************************** */
MXC_SYS_Clock_Timeout(uint32_t ready)321 int MXC_SYS_Clock_Timeout(uint32_t ready)
322 {
323 // Start timeout, wait for ready
324 MXC_DelayAsync(SYS_CLOCK_TIMEOUT, NULL);
325 do {
326 if (MXC_GCR->clk_ctrl & ready) {
327 MXC_DelayAbort();
328 return E_NO_ERROR;
329 }
330 } while (MXC_DelayCheck() == E_BUSY);
331
332 return E_TIME_OUT;
333 }
334
335 /* ************************************************************************** */
MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)336 int MXC_SYS_Reset_Periph(mxc_sys_reset_t reset)
337 {
338 if (reset > 31) {
339 reset -= 32;
340 MXC_GCR->rst1 = (1 << reset);
341 while (MXC_GCR->rst1 != 0x0) {}
342 } else {
343 MXC_GCR->rst0 = (1 << reset);
344 while (MXC_GCR->rst0 != 0x0) {}
345 }
346
347 return E_NO_ERROR;
348 }
349
350 /* ************************************************************************** */
MXC_SYS_GetRev(void)351 uint8_t MXC_SYS_GetRev(void)
352 {
353 uint8_t serialNumber[MXC_SYS_USN_LEN];
354 MXC_SYS_GetUSN(serialNumber, MXC_SYS_USN_LEN);
355
356 if ((serialNumber[0] < 0x9F) | ((serialNumber[0] & 0x0F) > 0x09)) {
357 // Fail back to the hardware register
358 return MXC_GCR->rev & 0xFF;
359 }
360 return serialNumber[0];
361 }
362
363 /* ************************************************************************** */
MXC_SYS_GetUSN(uint8_t * serialNumber,int len)364 int MXC_SYS_GetUSN(uint8_t *serialNumber, int len)
365 {
366 if (len != MXC_SYS_USN_LEN) {
367 return E_BAD_PARAM;
368 } else if (serialNumber == NULL) {
369 return E_NULL_PTR;
370 }
371
372 uint32_t infoblock[6];
373
374 MXC_FLC_UnlockInfoBlock(MXC_INFO_MEM_BASE);
375 infoblock[0] = *(uint32_t *)0x10800000;
376 infoblock[1] = *(uint32_t *)0x10800004;
377 infoblock[2] = *(uint32_t *)0x10800008;
378 infoblock[3] = *(uint32_t *)0x1080000C;
379 infoblock[4] = *(uint32_t *)0x10800010;
380 infoblock[5] = *(uint32_t *)0x10800014;
381 MXC_FLC_LockInfoBlock(MXC_INFO_MEM_BASE);
382
383 serialNumber[0] = (infoblock[0] & 0x007F8000) >> 15;
384 serialNumber[1] = (infoblock[0] & 0x7F800000) >> 23;
385 serialNumber[2] = (infoblock[0] & 0x80000000) >> 31;
386 serialNumber[2] |= (infoblock[1] & 0x0000007F) << 1;
387 serialNumber[3] = (infoblock[1] & 0x00007F80) >> 7;
388 serialNumber[4] = (infoblock[1] & 0x007F8000) >> 15;
389 serialNumber[5] = (infoblock[1] & 0x7F800000) >> 23;
390 serialNumber[6] = (infoblock[2] & 0x007F8000) >> 15;
391 serialNumber[7] = (infoblock[2] & 0x7F800000) >> 23;
392 serialNumber[8] = (infoblock[2] & 0x80000000) >> 31;
393 serialNumber[8] |= (infoblock[3] & 0x0000007F) << 1;
394 serialNumber[9] = (infoblock[3] & 0x00007F80) >> 7;
395 serialNumber[10] = (infoblock[3] & 0x007F8000) >> 15;
396 serialNumber[11] = (infoblock[3] & 0x7F800000) >> 23;
397 serialNumber[12] = (infoblock[4] & 0x007F8000) >> 15;
398
399 return E_NO_ERROR;
400 }
401
402 /* ************************************************************************** */
MXC_SYS_SCACHE_Init(const mxc_sys_cfg_scache_t * sys_cfg)403 int MXC_SYS_SCACHE_Init(const mxc_sys_cfg_scache_t *sys_cfg)
404 {
405 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_SCACHE);
406
407 return E_NO_ERROR;
408 }
409
410 /* ************************************************************************** */
MXC_SYS_SCACHE_Shutdown(void)411 int MXC_SYS_SCACHE_Shutdown(void)
412 {
413 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_SCACHE);
414
415 return E_NO_ERROR;
416 }
417
418 /* ************************************************************************** */
MXC_SYS_USBHS_Init(const mxc_sys_cfg_usbhs_t * sys_cfg)419 int MXC_SYS_USBHS_Init(const mxc_sys_cfg_usbhs_t *sys_cfg)
420 {
421 MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB);
422
423 return E_NO_ERROR;
424 }
425
426 /* ************************************************************************** */
MXC_SYS_USBHS_Shutdown(void)427 int MXC_SYS_USBHS_Shutdown(void)
428 {
429 MXC_SYS_ClockDisable(MXC_SYS_PERIPH_CLOCK_USB);
430
431 return E_NO_ERROR;
432 }
433
434 /* ************************************************************************** */
MXC_SYS_SysTick_Config(uint32_t ticks,int clk_src,mxc_tmr_regs_t * tmr)435 int MXC_SYS_SysTick_Config(uint32_t ticks, int clk_src, mxc_tmr_regs_t *tmr)
436 {
437 if (ticks == 0)
438 return E_BAD_PARAM;
439
440 /* If SystemClock, call default CMSIS config and return */
441 if (clk_src) {
442 return SysTick_Config(ticks);
443 } else { /* External clock source requested. Enable RTC clock in run mode*/
444 MXC_RTC_Init(0, 0);
445 MXC_RTC_Start();
446
447 /* Disable SysTick Timer */
448 SysTick->CTRL = 0;
449 /* Check reload value for valid */
450 if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) {
451 /* Reload value impossible */
452 return E_BAD_PARAM;
453 }
454 /* set reload register */
455 SysTick->LOAD = ticks - 1;
456
457 /* set Priority for Systick Interrupt */
458 NVIC_SetPriority(SysTick_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
459
460 /* Load the SysTick Counter Value */
461 SysTick->VAL = 0;
462
463 /* Enable SysTick IRQ and SysTick Timer leaving clock source as external */
464 SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
465
466 /* Function successful */
467 return E_NO_ERROR;
468 }
469 }
470
471 /* ************************************************************************** */
MXC_SYS_SysTick_Disable(void)472 int MXC_SYS_SysTick_Disable(void)
473 {
474 SysTick->CTRL = 0;
475
476 return E_NO_ERROR;
477 }
478
479 /* ************************************************************************** */
MXC_SYS_SysTick_Delay(uint32_t ticks)480 int MXC_SYS_SysTick_Delay(uint32_t ticks)
481 {
482 uint32_t cur_ticks, num_full, num_remain, previous_ticks, num_subtract, i;
483 uint32_t reload, value, ctrl; /* save/restore variables */
484
485 if (ticks == 0)
486 return E_BAD_PARAM;
487
488 /* If SysTick is not enabled we can take it for our delay */
489 if (!(SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)) {
490 /* Save current state in case it's disabled but already configured, restore at return.*/
491 reload = SysTick->LOAD;
492 value = SysTick->VAL;
493 ctrl = SysTick->CTRL;
494
495 /* get the number of ticks less than max RELOAD. */
496 num_remain = ticks % SysTick_LOAD_RELOAD_Msk;
497
498 /* if ticks is < Max SysTick Reload num_full will be 0, otherwise it will
499 give us the number of max SysTicks cycles required */
500 num_full = (ticks - 1) / SysTick_LOAD_RELOAD_Msk;
501
502 /* Do the required full systick countdowns */
503 if (num_full) {
504 /* load the max count value into systick */
505 SysTick->LOAD = SysTick_LOAD_RELOAD_Msk;
506 /* load the starting value */
507 SysTick->VAL = 0;
508 /*enable SysTick counter with SystemClock source internal, immediately forces LOAD register into VAL register */
509 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
510 /* CountFlag will get set when VAL reaches zero */
511 for (i = num_full; i > 0; i--) {
512 do {
513 cur_ticks = SysTick->CTRL;
514 } while (!(cur_ticks & SysTick_CTRL_COUNTFLAG_Msk));
515 }
516 /* Disable systick */
517 SysTick->CTRL = 0;
518 }
519 /* Now handle the remainder of ticks */
520 if (num_remain) {
521 SysTick->LOAD = num_remain;
522 SysTick->VAL = 0;
523 SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
524 /* wait for countflag to get set */
525 do {
526 cur_ticks = SysTick->CTRL;
527 } while (!(cur_ticks & SysTick_CTRL_COUNTFLAG_Msk));
528 /* Disable systick */
529 SysTick->CTRL = 0;
530 }
531
532 /* restore original state of SysTick and return */
533 SysTick->LOAD = reload;
534 SysTick->VAL = value;
535 SysTick->CTRL = ctrl;
536
537 return E_NO_ERROR;
538
539 } else {
540 /* SysTick is enabled
541 When SysTick is enabled count flag can not be used
542 and the reload can not be changed.
543 Do not read the CTRL register -> clears count flag */
544
545 /* Get the reload value for wrap/reload case */
546 reload = SysTick->LOAD;
547
548 /* Read the starting systick value */
549 previous_ticks = SysTick->VAL;
550
551 do {
552 /* get current SysTick value */
553 cur_ticks = SysTick->VAL;
554 /* Check for wrap/reload of timer countval */
555 if (cur_ticks > previous_ticks) {
556 /* subtract count to 0 (previous_ticks) and wrap (reload value - cur_ticks) */
557 num_subtract = (previous_ticks + (reload - cur_ticks));
558 } else {
559 /* standard case (no wrap) - subtract off the number of ticks since last pass */
560 num_subtract = (previous_ticks - cur_ticks);
561 }
562 /* check to see if we are done. */
563 if (num_subtract >= ticks)
564 return E_NO_ERROR;
565 else
566 ticks -= num_subtract;
567 /* cur_ticks becomes previous_ticks for next timer read. */
568 previous_ticks = cur_ticks;
569 } while (ticks > 0);
570 /* Should not ever be reached */
571 return E_NO_ERROR;
572 }
573 }
574
575 /* ************************************************************************** */
MXC_SYS_SysTick_GetFreq(void)576 uint32_t MXC_SYS_SysTick_GetFreq(void)
577 {
578 /* Determine is using internal (SystemCoreClock) or external (32768) clock */
579 if ((SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk) ||
580 !(SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)) {
581 return SystemCoreClock;
582 } else {
583 return SYS_RTC_CLK;
584 }
585 }
586
587 /* ************************************************************************** */
MXC_SYS_SysTick_DelayUs(uint32_t us)588 int MXC_SYS_SysTick_DelayUs(uint32_t us)
589 {
590 MXC_SYS_SysTick_Delay((uint32_t)(((uint64_t)MXC_SYS_SysTick_GetFreq() * us) / 1000000));
591
592 return E_NO_ERROR;
593 }
594
595 /* ************************************************************************** */
MXC_SYS_LockDAP_Permanent(void)596 int MXC_SYS_LockDAP_Permanent(void)
597 {
598 #ifdef DEBUG
599 // Locking the DAP is not supported while in DEBUG.
600 // To use this function, build for release ("make release")
601 // or set DEBUG = 0
602 // (see https://analogdevicesinc.github.io/msdk/USERGUIDE/#build-tables)
603 return E_NOT_SUPPORTED;
604 #else
605 int err;
606 uint32_t info_blk_addr;
607 uint32_t lock_sequence[4];
608
609 // Infoblock address to write lock sequence to
610 info_blk_addr = MXC_INFO_MEM_BASE + INFOBLOCK_DAP_LOCK_OFFSET;
611
612 // Set lock sequence
613 lock_sequence[0] = DAP_LOCK_SEQUENCE_01;
614 lock_sequence[1] = DAP_LOCK_SEQUENCE_01;
615 lock_sequence[2] = DAP_LOCK_SEQUENCE_23;
616 lock_sequence[3] = DAP_LOCK_SEQUENCE_23;
617
618 // Initialize FLC
619 MXC_FLC_Init();
620
621 // Unlock infoblock
622 MXC_FLC_UnlockInfoBlock(info_blk_addr);
623
624 // Write DAP lock sequence to infoblock
625 err = MXC_FLC_Write128(info_blk_addr, lock_sequence);
626
627 // Re-lock infoblock
628 MXC_FLC_LockInfoBlock(info_blk_addr);
629
630 return err;
631 #endif
632 }
633