2bcca11b98d72e5a96b9ee86b5e6bf6f1ca2b144
[cortex-from-scratch] / clock.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/7/30 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * 1. Routines to setup the high speed external (HSE) clock. 
9  * Initially a (less accurate) high speed internal (HSI) 
10  * clock is used. PPL is enabled; HSE is input for PPL.
11  * PPL is multiplied to get the desired clock speed. 
12  *
13  * Some buses might not support the maximum speed and
14  * should be prescaled (i.e. low speed APB)
15  * 
16  * 2. Routines to setup a real time clock (RTC). A external 
17  * low speed oscillator (LSE) is used. 
18  *
19  * $USAGE
20  * Check external crystals on board and maximum speed
21  * for buses. In this example, a 8 Mhz external crystal
22  * is used. CPU speed is 36 Mhz. No prescaling is done.
23  * 
24  * */
25
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdint.h>
29
30 #include <sys/robsys.h>
31 #include <sys/mmap.h>
32
33 #include <lib/regfunc.h>
34
35 static void setup_hse() {
36
37         rsetbit(RCC_CR, 16); /* HSE enable */
38         rsetbit(RCC_CFGR, 17); /* HSE divider for PLL entry */
39         
40         while(!rchkbit(RCC_CR, 17)); /* Wait for HSE to come up */
41         
42         rsetbitsfrom(RCC_CFGR, 18, 0x7); /* PLL Multiplayer (x9) */
43         rsetbit(RCC_CFGR, 16); /* HSE as PPL clock source */
44         rsetbit(RCC_CR, 24); /* PLL enable */
45         //rsetbitsfrom(RCC_CFGR, 8, 0x4); /* APB low speed prescraler */
46         rsetbitsfrom(RCC_CFGR, 0, 0x2); /* use PPL as system clock */
47
48         while(!rchkbit(RCC_CFGR, 3)); /* Wait for the clock switch to complete */
49 }
50
51 static void setup_rtc() {
52
53 // TODO: long time to get stable?
54 //      /* Enable PWREN and BKPEN */
55 //      rsetbit(RCC_APB1ENR, 28);
56 //      rsetbit(RCC_APB1ENR, 27);
57 //
58 //      /* Enable access to backup registers and RTC */
59 //      rsetbit(PWR_CR, 8);
60 //
61 //      rsetbit(RCC_BDCR, 0); /* LSE enable */
62 //      while(!rchkbit(RCC_BDCR, 1)); /* wait for LSE to come up */
63 //      
64 //      rsetbitsfrom(RCC_BDCR, 8, 0x1); /* use LSE as RTC source */
65 //      rsetbit(RCC_BDCR, 15); /* enable RTC */
66 //      
67
68 }
69
70 void clock_init() {
71
72 #ifdef ENABLE_HSE
73 setup_hse();
74 #endif
75
76 #ifdef ENABLE_RTC
77 setup_rtc();
78 #endif
79       
80 }
81