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