1 /**
2  * @file    mxc_sys.c
3  * @brief   System level setup help
4  */
5 
6 /*******************************************************************************
7  * Copyright (C) 2015 Maxim Integrated Products, Inc., All Rights Reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
23  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  * Except as contained in this notice, the name of Maxim Integrated
28  * Products, Inc. shall not be used except as stated in the Maxim Integrated
29  * Products, Inc. Branding Policy.
30  *
31  * The mere transfer of this software does not imply any licenses
32  * of trade secrets, proprietary technology, copyrights, patents,
33  * trademarks, maskwork rights, or any other form of intellectual
34  * property whatsoever. Maxim Integrated Products, Inc. retains all
35  * ownership rights.
36  *
37  * $Date: 2020-01-17 08:38:51 -0600 (Fri, 17 Jan 2020) $
38  * $Revision: 50772 $
39  *
40  ******************************************************************************/
41 
42 #include <stddef.h>
43 #include "mxc_config.h"
44 #include "mxc_assert.h"
45 #include "mxc_sys.h"
46 #include "gpio.h"
47 #include "mxc_pins.h"
48 #include "gcr_regs.h"
49 #include "tmr_regs.h"
50 #include "pwrseq_regs.h"
51 #include "spi17y_regs.h"
52 #include "spimss_regs.h"
53 #include "mxc_delay.h"
54 #include "rtc.h"
55 
56 /**
57  * @ingroup MXC_sys
58  * @{
59  */
60 
61 /***** Definitions *****/
62 #define SYS_CLOCK_TIMEOUT       MXC_DELAY_MSEC(1)
63 
64 #define SYS_RTC_CLK 32768UL
65 
66 /***** Functions ******/
SYS_Clock_Timeout(uint32_t ready)67 static int SYS_Clock_Timeout(uint32_t ready)
68 {
69     // Start timeout, wait for ready
70     mxc_delay_start(SYS_CLOCK_TIMEOUT);
71     do {
72         if (MXC_GCR->clkcn & ready) {
73             mxc_delay_stop();
74             return E_NO_ERROR;
75         }
76     } while (mxc_delay_check() == E_BUSY);
77 
78     return E_TIME_OUT;
79 }
80 
81 /* ************************************************************************ */
SYS_Clock_Select(sys_system_clock_t clock,mxc_tmr_regs_t * tmr)82 int SYS_Clock_Select(sys_system_clock_t clock, mxc_tmr_regs_t* tmr)
83 {
84     uint32_t current_clock,ovr, div;
85 
86     // Save the current system clock
87     current_clock = MXC_GCR->clkcn & MXC_F_GCR_CLKCN_CLKSEL;
88     // Set FWS higher than what the minimum for the fastest clock is
89     MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x5UL << MXC_F_GCR_MEMCKCN_FWS_POS);
90     switch(clock) {
91         case SYS_CLOCK_NANORING:
92             // Set NANORING clock as System Clock
93             MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_NANORING);
94 
95         break;
96         case SYS_CLOCK_HFXIN:
97             // Enable 32k Oscillator
98             MXC_GCR->clkcn |=MXC_F_GCR_CLKCN_X32K_EN;
99 
100             // Check if 32k clock is ready
101             if (SYS_Clock_Timeout(MXC_F_GCR_CLKCN_X32K_RDY) != E_NO_ERROR) {
102                 return E_TIME_OUT;
103             }
104             MXC_RTC->ctrl |= MXC_F_RTC_CTRL_WE;      // Allow writing to registers
105 
106             // Set 32k clock as System Clock
107             MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_HFXIN);
108 
109         break;
110 
111         case SYS_CLOCK_HFXIN_DIGITAL:
112             // Enable 32k Oscillator
113             MXC_GCR->clkcn |=MXC_F_GCR_CLKCN_X32K_EN;
114 
115             // Check if 32k clock is ready
116             if (SYS_Clock_Timeout(MXC_F_GCR_CLKCN_X32K_RDY) != E_NO_ERROR) {
117                 return E_TIME_OUT;
118             }
119             MXC_RTC->ctrl |= MXC_F_RTC_CTRL_WE;      // Allow writing to registers
120             MXC_RTC->oscctrl |= MXC_F_RTC_OSCCTRL_BYPASS;  // To allow square wave driven on 32KIN
121             // Set 32k clock as System Clock
122             MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_HFXIN);
123 
124         break;
125         case SYS_CLOCK_HIRC:
126             // Enable 96MHz Clock
127             MXC_GCR->clkcn |=MXC_F_GCR_CLKCN_HIRC_EN;
128 
129             // Check if 96MHz clock is ready
130             if (SYS_Clock_Timeout(MXC_F_GCR_CLKCN_HIRC_RDY) != E_NO_ERROR) {
131                 return E_TIME_OUT;
132             }
133 
134             // Set 96MHz clock as System Clock
135             MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, MXC_S_GCR_CLKCN_CLKSEL_HIRC);
136 
137         break;
138         default:
139         return E_BAD_PARAM;
140     }
141 
142     // Wait for system clock to be ready
143     if (SYS_Clock_Timeout(MXC_F_GCR_CLKCN_CKRDY) != E_NO_ERROR) {
144 
145         // Restore the old system clock if timeout
146         MXC_SETFIELD(MXC_GCR->clkcn, MXC_F_GCR_CLKCN_CLKSEL, current_clock);
147 
148         return E_TIME_OUT;
149     }
150 
151     // Disable other clocks
152     switch(clock) {
153         case SYS_CLOCK_NANORING:
154             MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC_EN);
155         break;
156 
157         case SYS_CLOCK_HFXIN:
158             MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC_EN);
159         break;
160 
161         case SYS_CLOCK_HFXIN_DIGITAL:
162             MXC_GCR->clkcn &= ~(MXC_F_GCR_CLKCN_HIRC_EN);
163         break;
164 
165         case SYS_CLOCK_HIRC:
166             //Don't disable 32KHz clock
167         break;
168     }
169 
170     // Update the system core clock
171     SystemCoreClockUpdate();
172 
173     // Get the clock divider
174     div = (MXC_GCR->clkcn & MXC_F_GCR_CLKCN_PSC) >> MXC_F_GCR_CLKCN_PSC_POS;
175 
176     //get ovr setting
177     ovr = (MXC_PWRSEQ->lp_ctrl & MXC_F_PWRSEQ_LP_CTRL_OVR);
178 
179     //Set flash wait settings
180     if(ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_0_9V){
181 
182         if(div == 0){
183             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
184 
185         } else{
186             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
187 
188         }
189 
190     } else if( ovr == MXC_S_PWRSEQ_LP_CTRL_OVR_1_0V){
191         if(div == 0){
192             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
193 
194         } else{
195             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
196 
197         }
198 
199     } else {
200 
201         if(div == 0){
202             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x4UL << MXC_F_GCR_MEMCKCN_FWS_POS);
203 
204         } else if(div == 1){
205             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x2UL << MXC_F_GCR_MEMCKCN_FWS_POS);
206 
207         } else{
208             MXC_GCR->memckcn = (MXC_GCR->memckcn & ~(MXC_F_GCR_MEMCKCN_FWS)) | (0x1UL << MXC_F_GCR_MEMCKCN_FWS_POS);
209 
210         }
211     }
212 
213     return E_NO_ERROR;
214 }
215 
216 /* ************************************************************************ */
SYS_ClockEnable_X32K(sys_cfg_rtc_t * sys_cfg)217 int SYS_ClockEnable_X32K(sys_cfg_rtc_t *sys_cfg)
218 {
219     // Enable 32k Oscillator
220     MXC_GCR->clkcn |=MXC_F_GCR_CLKCN_X32K_EN;
221 
222     return E_NO_ERROR;
223 }
224 
225 /* ************************************************************************ */
SYS_ClockDisable_X32K()226 int SYS_ClockDisable_X32K()
227 {
228     // Disable 32k Oscillator
229     MXC_GCR->clkcn &= (~MXC_F_GCR_CLKCN_X32K_EN);
230     return E_NO_ERROR;
231 }
232 
233 /* ************************************************************************ */
SYS_UART_Init(mxc_uart_regs_t * uart,const sys_cfg_uart_t * sys_cfg)234 int SYS_UART_Init(mxc_uart_regs_t *uart, const sys_cfg_uart_t* sys_cfg)
235 {
236         // Configure GPIO for UART
237     if (uart == MXC_UART0) {
238         SYS_ClockEnable(SYS_PERIPH_CLOCK_UART0);
239         if(sys_cfg->map == MAP_A){
240             GPIO_Config(&gpio_cfg_uart0a);
241         }
242         else{
243             return E_BAD_PARAM;
244         }
245         if(sys_cfg->flow_flag == UART_FLOW_ENABLE){
246             GPIO_Config(&gpio_cfg_uart0rtscts);
247         }
248     }
249     if (uart == MXC_UART1) {
250         SYS_ClockEnable(SYS_PERIPH_CLOCK_UART1);
251         if(sys_cfg->map == MAP_A){
252             GPIO_Config(&gpio_cfg_uart1a);
253         }
254         else if(sys_cfg->map == MAP_B){
255             GPIO_Config(&gpio_cfg_uart1b);
256         }
257         else if(sys_cfg->map == MAP_C){
258             GPIO_Config(&gpio_cfg_uart1c);
259         }
260         else{
261             return E_BAD_PARAM;
262         }
263         if(sys_cfg->flow_flag == UART_FLOW_ENABLE){
264             GPIO_Config(&gpio_cfg_uart1rtscts);
265         }
266     }
267     return E_NO_ERROR;
268 }
269 
270 /* ************************************************************************ */
SYS_UART_Shutdown(mxc_uart_regs_t * uart)271 int SYS_UART_Shutdown(mxc_uart_regs_t *uart)
272 {
273     if (uart == MXC_UART0) {
274         SYS_ClockDisable(SYS_PERIPH_CLOCK_UART0);
275     }
276     else if (uart == MXC_UART1) {
277         SYS_ClockDisable(SYS_PERIPH_CLOCK_UART1);
278     }
279     return E_NO_ERROR;
280 }
281 
282 /* ************************************************************************ */
SYS_I2C_Init(mxc_i2c_regs_t * i2c,const sys_cfg_i2c_t * sys_cfg)283 int SYS_I2C_Init(mxc_i2c_regs_t *i2c,  const sys_cfg_i2c_t* sys_cfg)
284 {
285 
286     // Configure GPIO for I2C
287     if (i2c == MXC_I2C0) {
288         SYS_ClockEnable(SYS_PERIPH_CLOCK_I2C0);
289         GPIO_Config(&gpio_cfg_i2c0);
290 
291     } else if (i2c == MXC_I2C1) {
292         SYS_ClockEnable(SYS_PERIPH_CLOCK_I2C1);
293         GPIO_Config(&gpio_cfg_i2c1);
294     } else {
295         return E_NO_DEVICE;
296     }
297 
298     return E_NO_ERROR;
299 }
300 
301 /* ************************************************************************ */
SYS_I2C_Shutdown(mxc_i2c_regs_t * i2c)302 int SYS_I2C_Shutdown(mxc_i2c_regs_t *i2c)
303 {
304     if (i2c == MXC_I2C0) {
305         gpio_cfg_t cfg = { gpio_cfg_i2c0.port, gpio_cfg_i2c0.mask, GPIO_FUNC_IN, GPIO_PAD_NONE };
306         SYS_ClockDisable(SYS_PERIPH_CLOCK_I2C0);
307         GPIO_Config(&cfg);
308     } else if (i2c == MXC_I2C1) {
309         gpio_cfg_t cfg = { gpio_cfg_i2c1.port, gpio_cfg_i2c1.mask, GPIO_FUNC_IN, GPIO_PAD_NONE };
310         SYS_ClockDisable(SYS_PERIPH_CLOCK_I2C1);
311         GPIO_Config(&cfg);
312     } else {
313         return E_NO_DEVICE;
314     }
315     // Clear registers
316     i2c->ctrl = 0;
317 
318     return E_NO_ERROR;
319 }
320 
321 /* ************************************************************************ */
SYS_DMA_Init(void)322 int SYS_DMA_Init(void)
323 {
324     SYS_ClockEnable(SYS_PERIPH_CLOCK_DMA);
325     return E_NO_ERROR;
326 }
327 
328 /* ************************************************************************ */
SYS_DMA_Shutdown(void)329 int SYS_DMA_Shutdown(void)
330 {
331     SYS_ClockDisable(SYS_PERIPH_CLOCK_DMA);
332     return E_NO_ERROR;
333 }
334 
335 /* ************************************************************************ */
SYS_I2C_GetFreq(mxc_i2c_regs_t * i2c)336 unsigned SYS_I2C_GetFreq(mxc_i2c_regs_t *i2c)
337 {
338     return PeripheralClock;
339 }
340 
341 /* ************************************************************************ */
SYS_TMR_GetFreq(mxc_tmr_regs_t * tmr)342 unsigned SYS_TMR_GetFreq(mxc_tmr_regs_t *tmr)
343 {
344     return PeripheralClock;
345 }
346 
347 /* ************************************************************************ */
SYS_Reset0(sys_reset0_t reset)348 void SYS_Reset0(sys_reset0_t reset)
349 {
350     MXC_GCR->rstr0 = reset;
351     while(MXC_GCR->rstr0 != 0x0) {}
352 }
353 
354 /* ************************************************************************ */
SYS_Reset1(sys_reset1_t reset)355 void SYS_Reset1(sys_reset1_t reset)
356 {
357     MXC_GCR->rstr1 = reset;
358     while(MXC_GCR->rstr0 != 0x0) {}
359 }
360 
361 /* ************************************************************************ */
SYS_ClockDisable(sys_periph_clock_t clock)362 void SYS_ClockDisable(sys_periph_clock_t clock)
363 {
364     /* The sys_periph_clock_t enum uses bit 27 (an unused bit in both perkcn registers)
365        to determine which of the two perckcn registers to write to. */
366     if (clock & (1<<27)) {
367         clock &= ~(1<<27);
368         MXC_GCR->perckcn1 |= clock;
369     } else {
370         MXC_GCR->perckcn0 |= clock;
371     }
372 }
373 
374 /* ************************************************************************ */
SYS_ClockEnable(sys_periph_clock_t clock)375 void SYS_ClockEnable(sys_periph_clock_t clock)
376 {
377     /* The sys_periph_clock_t enum uses bit 27 (an unused bit in both perkcn registers)
378        to determine which of the two perckcn registers to write to. */
379     if (clock & (1<<27)) {
380         clock &= ~(1<<27);
381         MXC_GCR->perckcn1 &= ~(clock);
382     } else {
383         MXC_GCR->perckcn0 &= ~(clock);
384     }
385 }
386 
387 /* ************************************************************************ */
388 #if defined (__ICCARM__)
389 #pragma optimize=none           /* Turn off optimizations for next function */
390 #elif defined ( __CC_ARM )
391 /* Keil MDK - Turn off optimizations after saving current state */
392 #pragma push                    /* Save current optimization level */
393 #pragma O0                      /* Optimization level 0 */
394 #elif ( __GNUC__ )
395 /* GCC - Turn off optimizations after saving current state */
396 #pragma GCC push_options        /* Save current optimization level */
397 #pragma GCC optimize ("O0")     /* Set optimization level to none for this function */
398 #endif
SYS_Flash_Operation(void)399 void SYS_Flash_Operation(void)
400 {
401     volatile uint32_t *line_addr;
402     volatile uint32_t __attribute__ ((unused)) line;
403 
404     // Clear the cache
405     MXC_ICC->cache_ctrl ^= MXC_F_ICC_CACHE_CTRL_CACHE_EN;
406     MXC_ICC->cache_ctrl ^= MXC_F_ICC_CACHE_CTRL_CACHE_EN;
407 
408     // Clear the line fill buffer
409     line_addr = (uint32_t*)(MXC_FLASH_MEM_BASE);
410     line = *line_addr;
411 
412     line_addr = (uint32_t*)(MXC_FLASH_MEM_BASE + MXC_FLASH_PAGE_SIZE);
413     line = *line_addr;
414 }
415 /* Set optimizations to the previous level. For IAR, the optimize none applies
416    only to the next function. Keil MDK and GNUC need state restored. */
417 #if defined ( __CC_ARM )
418 #pragma pop                     /* Restore Kiel MDK optimizations to saved level */
419 #elif defined ( __GNUC__ )
420 #pragma GCC pop_options         /* Restore GCC optimization level */
421 #endif
422 
423 /* ************************************************************************ */
SYS_TMR_Init(mxc_tmr_regs_t * tmr,const sys_cfg_tmr_t * sys_cfg)424 int SYS_TMR_Init(mxc_tmr_regs_t *tmr, const sys_cfg_tmr_t* sys_cfg)
425 {
426     if(sys_cfg) {
427         if(sys_cfg->out_en) {
428 
429             if (tmr == MXC_TMR0) {
430                 GPIO_Config(&gpio_cfg_tmr0);
431             }
432         }
433     }
434 
435     if (tmr == MXC_TMR0) {
436         SYS_ClockEnable(SYS_PERIPH_CLOCK_T0);
437     }
438     else if (tmr == MXC_TMR1) {
439         SYS_ClockEnable(SYS_PERIPH_CLOCK_T1);
440     }
441     else if (tmr == MXC_TMR2) {
442         SYS_ClockEnable(SYS_PERIPH_CLOCK_T2);
443     }
444 
445     return E_NO_ERROR;
446 }
447 
448 /* ************************************************************************ */
SYS_FLC_Init(const sys_cfg_flc_t * sys_cfg)449 int SYS_FLC_Init(const sys_cfg_flc_t* sys_cfg)
450 {
451     return E_NO_ERROR;
452 }
453 
454 /* ************************************************************************ */
SYS_FLC_Shutdown(void)455 int SYS_FLC_Shutdown(void)
456 {
457     return E_NO_ERROR;
458 }
459 
460 /* ************************************************************************ */
SYS_SPI17Y_Init(mxc_spi17y_regs_t * spi,const sys_cfg_spi17y_t * sys_cfg)461 int SYS_SPI17Y_Init(mxc_spi17y_regs_t *spi, const sys_cfg_spi17y_t* sys_cfg)
462 {
463     // Configure GPIO for spi17y
464     if (spi == MXC_SPI17Y) {
465         SYS_ClockEnable(SYS_PERIPH_CLOCK_SPI17Y);
466         if(sys_cfg->map == MAP_A){
467             GPIO_Config(&gpio_cfg_spi17y);
468              MXC_GPIO0->ds |= 0x0003BF0;
469         }else{
470             return E_BAD_PARAM;
471         }
472     } else {
473         return E_NO_DEVICE;
474     }
475     return E_NO_ERROR;
476 }
477 
478 /* ************************************************************************ */
SYS_SPI17Y_Shutdown(mxc_spi17y_regs_t * spi)479 int SYS_SPI17Y_Shutdown(mxc_spi17y_regs_t *spi)
480 {
481     if (spi == MXC_SPI17Y) {
482         SYS_ClockDisable(SYS_PERIPH_CLOCK_SPI17Y);
483     }
484     return E_NO_ERROR;
485 }
486 
487 /* ************************************************************************ */
SYS_SPIMSS_Init(mxc_spimss_regs_t * spi,const sys_cfg_spimss_t * sys_cfg)488 int SYS_SPIMSS_Init(mxc_spimss_regs_t *spi, const sys_cfg_spimss_t* sys_cfg)
489 {
490     // Configure GPIO for spimss
491     if (spi == MXC_SPIMSS) {
492         SYS_ClockEnable(SYS_PERIPH_CLOCK_SPIMSS);
493         if(sys_cfg->map == MAP_A){
494             GPIO_Config(&gpio_cfg_spimss1a);  // SPI1A chosen
495         }else if(sys_cfg->map == MAP_B){
496             GPIO_Config(&gpio_cfg_spimss1b);  // SPI1B chosen
497         }else{
498             return E_BAD_PARAM;
499         }
500     } else {
501         return E_NO_DEVICE;
502     }
503     return E_NO_ERROR;
504 }
505 
506 /* ************************************************************************ */
SYS_SPIMSS_Shutdown(mxc_spimss_regs_t * spi)507 int SYS_SPIMSS_Shutdown(mxc_spimss_regs_t *spi)
508 {
509     if(spi == MXC_SPIMSS) {
510         SYS_ClockDisable(SYS_PERIPH_CLOCK_SPIMSS);
511     }
512     return E_NO_ERROR;
513 }
514 
SYS_TMR_Shutdown(mxc_tmr_regs_t * tmr)515 int SYS_TMR_Shutdown(mxc_tmr_regs_t *tmr)
516 {
517     return E_NO_ERROR;
518 }
519 
520 /* ************************************************************************ */
SYS_I2S_Init(const sys_cfg_i2s_t * sys_cfg)521 int SYS_I2S_Init(const sys_cfg_i2s_t* sys_cfg)
522 {
523     if(sys_cfg->map == MAP_A) {
524         GPIO_Config(&gpio_cfg_i2s1a);
525     }
526     else if(sys_cfg->map == MAP_B) {
527         GPIO_Config(&gpio_cfg_i2s1b);
528     }
529     else {
530         return E_BAD_PARAM;
531     }
532         SYS_ClockEnable(SYS_PERIPH_CLOCK_SPIMSS);
533 
534     return E_NO_ERROR;
535 }
536 
537 /* ************************************************************************ */
SYS_I2S_Shutdown(void)538 int SYS_I2S_Shutdown(void)
539 {
540         SYS_ClockDisable(SYS_PERIPH_CLOCK_SPIMSS);
541 
542     return E_NO_ERROR;
543 }
544 
545 /* ************************************************************************ */
SYS_I2S_GetFreq(mxc_spimss_regs_t * spimss)546 int SYS_I2S_GetFreq(mxc_spimss_regs_t *spimss)
547 {
548     return PeripheralClock;
549 }
550 
551 /* ************************************************************************ */
SYS_RTC_SqwavInit(const sys_cfg_rtc_t * sys_cfg)552 int SYS_RTC_SqwavInit(const sys_cfg_rtc_t* sys_cfg)
553 {
554     GPIO_Config(&gpio_cfg_rtc);
555     return E_NO_ERROR;
556 }
557 
558 /* ************************************************************************ */
SYS_SysTick_GetFreq(void)559 uint32_t SYS_SysTick_GetFreq(void)
560 {
561     // Determine is using internal (SystemCoreClock) or external (32768) clock
562     if ( (SysTick->CTRL & SysTick_CTRL_CLKSOURCE_Msk) || !(SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)) {
563         return SystemCoreClock;
564     } else {
565         return SYS_RTC_CLK;
566     }
567 }
568 
569 /* ************************************************************************ */
SYS_SysTick_Config(uint32_t ticks,int clk_src,mxc_tmr_regs_t * tmr)570 int SYS_SysTick_Config(uint32_t ticks, int clk_src, mxc_tmr_regs_t* tmr)
571 {
572 
573     if(ticks == 0)
574         return E_BAD_PARAM;
575 
576     // If SystemClock, call default CMSIS config and return
577     if (clk_src) {
578         return SysTick_Config(ticks);
579     } else { /* External clock source requested
580                 enable RTC clock in run mode*/
581         RTC_Init(MXC_RTC, 0, 0, NULL);
582         RTC_EnableRTCE(MXC_RTC);
583 
584         // Disable SysTick Timer
585         SysTick->CTRL = 0;
586         // Check reload value for valid
587         if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) {
588             // Reload value impossible
589             return E_BAD_PARAM;
590         }
591         // set reload register
592         SysTick->LOAD  = ticks - 1;
593 
594         // set Priority for Systick Interrupt
595         NVIC_SetPriority(SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
596 
597         // Load the SysTick Counter Value
598         SysTick->VAL   = 0;
599 
600         // Enable SysTick IRQ and SysTick Timer leaving clock source as external
601         SysTick->CTRL  = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
602 
603         // Function successful
604         return E_NO_ERROR;
605     }
606 }
607 
608 /* ************************************************************************ */
SYS_SysTick_Disable(void)609 void SYS_SysTick_Disable(void)
610 {
611     SysTick->CTRL = 0;
612 }
613 
614 /* ************************************************************************ */
SYS_SysTick_Delay(uint32_t ticks)615 int SYS_SysTick_Delay(uint32_t ticks)
616 {
617     uint32_t cur_ticks, num_full, num_remain, previous_ticks, num_subtract, i;
618     uint32_t reload, value, ctrl;  // save/restore variables
619 
620     if(ticks == 0)
621         return E_BAD_PARAM;
622 
623     // If SysTick is not enabled we can take it for our delay
624     if (!(SysTick->CTRL & SysTick_CTRL_ENABLE_Msk)) {
625 
626         // Save current state in case it's disabled but already configured, restore at return.
627         reload = SysTick->LOAD;
628         value = SysTick->VAL;
629         ctrl = SysTick->CTRL;
630 
631         // get the number of ticks less than max RELOAD.
632         num_remain = ticks % SysTick_LOAD_RELOAD_Msk;
633 
634         /* if ticks is < Max SysTick Reload num_full will be 0, otherwise it will
635            give us the number of max SysTicks cycles required */
636         num_full = (ticks - 1) / SysTick_LOAD_RELOAD_Msk;
637 
638         // Do the required full systick countdowns
639         if (num_full) {
640             // load the max count value into systick
641             SysTick->LOAD = SysTick_LOAD_RELOAD_Msk;
642             // load the starting value
643             SysTick->VAL = 0;
644             // enable SysTick counter with SystemClock source internal, immediately forces LOAD register into VAL register
645             SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
646             // CountFlag will get set when VAL reaches zero
647             for (i = num_full; i > 0; i--) {
648                 do {
649                     cur_ticks = SysTick->CTRL;
650                 } while (!(cur_ticks & SysTick_CTRL_COUNTFLAG_Msk));
651             }
652             // Disable systick
653             SysTick->CTRL = 0;
654         }
655         // Now handle the remainder of ticks
656         if (num_remain) {
657             SysTick->LOAD = num_remain;
658             SysTick->VAL = 0;
659             SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
660             // wait for countflag to get set
661             do {
662                 cur_ticks = SysTick->CTRL;
663             } while (!(cur_ticks & SysTick_CTRL_COUNTFLAG_Msk));
664             // Disable systick
665             SysTick->CTRL = 0;
666         }
667 
668         // restore original state of SysTick and return
669         SysTick->LOAD = reload;
670         SysTick->VAL =  value;
671         SysTick->CTRL = ctrl;
672 
673         return E_NO_ERROR;
674 
675     } else { /* SysTick is enabled
676            When SysTick is enabled count flag can not be used
677            and the reload can not be changed.
678            Do not read the CTRL register -> clears count flag */
679 
680         // Get the reload value for wrap/reload case
681         reload = SysTick->LOAD;
682 
683         // Read the starting systick value
684         previous_ticks = SysTick->VAL;
685 
686         do {
687             // get current SysTick value
688             cur_ticks = SysTick->VAL;
689             // Check for wrap/reload of timer countval
690             if (cur_ticks > previous_ticks) {
691                 // subtract count to 0 (previous_ticks) and wrap (reload value - cur_ticks)
692                 num_subtract = (previous_ticks + (reload - cur_ticks));
693             } else { /* standard case (no wrap)
694                         subtract off the number of ticks since last pass */
695                 num_subtract = (previous_ticks - cur_ticks);
696             }
697             // check to see if we are done.
698             if (num_subtract >= ticks)
699                 return E_NO_ERROR;
700             else
701                 ticks -= num_subtract;
702             // cur_ticks becomes previous_ticks for next timer read.
703             previous_ticks = cur_ticks;
704         } while (ticks > 0);
705         // Should not ever be reached
706         return E_NO_ERROR;
707     }
708 }
709 
710 /* ************************************************************************ */
SYS_SysTick_DelayUs(uint32_t us)711 void SYS_SysTick_DelayUs(uint32_t us)
712 {
713     SYS_SysTick_Delay((uint32_t)(((uint64_t)SYS_SysTick_GetFreq() * us) / 1000000));
714 }
715 
716 /* ************************************************************************ */
SYS_WDT_Init(mxc_wdt_regs_t * wdt,const sys_cfg_wdt_t * sys_cfg)717 int SYS_WDT_Init(mxc_wdt_regs_t* wdt, const sys_cfg_wdt_t* sys_cfg)
718 {
719     return E_NO_ERROR;
720 }
721 /**@} end of ingroup MXC_sys*/
722