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