HSE usage
authorRobin Krens <robin@robinkrens.nl>
Tue, 30 Jul 2019 20:11:42 +0000 (04:11 +0800)
committerRobin Krens <robin@robinkrens.nl>
Tue, 30 Jul 2019 20:11:42 +0000 (04:11 +0800)
High speed external clock set to 36 MHz, 72MHz speeds crashed on board.
No changes to buspeeds. Adaptions to UART baud rates.

Makefile
clock.c
drivers/tm1637.c
drivers/uart.c
include/lib/regfunc.h
include/sys/mmap.h
include/sys/robsys.h
lib/regfunc.c
main.c
systick.c

index 3da9701..edff16a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ INCLUDE+= -Iinclude
 BIN = bin
 
 ODIR = obj
-_OBJ = ivt.o systick.o sysinfo.o term.o main.o 
+_OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o 
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
 DDIR = obj/drivers
diff --git a/clock.c b/clock.c
index 7d5dc19..2bcca11 100644 (file)
--- a/clock.c
+++ b/clock.c
@@ -1,15 +1,81 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/30 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * 1. Routines to setup the high speed external (HSE) clock. 
+ * Initially a (less accurate) high speed internal (HSI) 
+ * clock is used. PPL is enabled; HSE is input for PPL.
+ * PPL is multiplied to get the desired clock speed. 
+ *
+ * Some buses might not support the maximum speed and
+ * should be prescaled (i.e. low speed APB)
+ * 
+ * 2. Routines to setup a real time clock (RTC). A external 
+ * low speed oscillator (LSE) is used. 
+ *
+ * $USAGE
+ * Check external crystals on board and maximum speed
+ * for buses. In this example, a 8 Mhz external crystal
+ * is used. CPU speed is 36 Mhz. No prescaling is done.
+ * 
+ * */
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h>
-#include <mmap.h>
 
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/regfunc.h>
+
+static void setup_hse() {
+
+       rsetbit(RCC_CR, 16); /* HSE enable */
+       rsetbit(RCC_CFGR, 17); /* HSE divider for PLL entry */
+       
+       while(!rchkbit(RCC_CR, 17)); /* Wait for HSE to come up */
+       
+       rsetbitsfrom(RCC_CFGR, 18, 0x7); /* PLL Multiplayer (x9) */
+       rsetbit(RCC_CFGR, 16); /* HSE as PPL clock source */
+       rsetbit(RCC_CR, 24); /* PLL enable */
+       //rsetbitsfrom(RCC_CFGR, 8, 0x4); /* APB low speed prescraler */
+       rsetbitsfrom(RCC_CFGR, 0, 0x2); /* use PPL as system clock */
+
+       while(!rchkbit(RCC_CFGR, 3)); /* Wait for the clock switch to complete */
+}
+
+static void setup_rtc() {
+
+// TODO: long time to get stable?
+//     /* Enable PWREN and BKPEN */
+//     rsetbit(RCC_APB1ENR, 28);
+//     rsetbit(RCC_APB1ENR, 27);
+//
+//     /* Enable access to backup registers and RTC */
+//     rsetbit(PWR_CR, 8);
+//
+//     rsetbit(RCC_BDCR, 0); /* LSE enable */
+//     while(!rchkbit(RCC_BDCR, 1)); /* wait for LSE to come up */
+//     
+//     rsetbitsfrom(RCC_BDCR, 8, 0x1); /* use LSE as RTC source */
+//     rsetbit(RCC_BDCR, 15); /* enable RTC */
+//     
+
+}
 
 void clock_init() {
 
+#ifdef ENABLE_HSE
+setup_hse();
+#endif
 
-      *RCC_CR = *RCC_CR | 0x00010000;
-      for (int i = 0; i < 200; i++) {
-      }
-      *RCC_CFGR = *RCC_CFGR | 0x05000001;
+#ifdef ENABLE_RTC
+setup_rtc();
+#endif
+      
 }
+
index 517e0cf..a2889fd 100644 (file)
@@ -28,7 +28,7 @@
 
 #include <drivers/tm1637.h>
 
-#define TIMEOUT 1000
+#define TIMEOUT 5000
 
 #define DATASET        0x40
 #define CONTROL        0x80
@@ -79,7 +79,7 @@ static void stop_condition() {
 int ack_recv() {
 
        int cnt = 0;
-       while(!(*I2C_SR1 & 0x1)) {
+       while(!(*I2C_SR1 & 0x2)) {
                cnt++;
                if (cnt > TIMEOUT)
                        return 0;
@@ -89,6 +89,17 @@ int ack_recv() {
 
 }
 
+int buf_empty() {
+       int cnt = 0;
+       while(!(*I2C_SR1 & 0x80)) {
+               cnt++;
+               if (cnt > TIMEOUT)
+                       return 0;
+       }
+
+       return 1;
+}
+
 int delay() {
 
        int a = 0;
@@ -127,18 +138,18 @@ void tm1637_start() {
        //statusr = *I2C_SR1;
        //statusr = *I2C_SR2;
        regw_u32(I2C_DR, 0x7D, 0, OWRITE);
-       if(!ack_recv())
+       if(!buf_empty())
                cputs("TIMEOUT3!");
        stop_condition();
 
-       delay();
+/*     delay();
 
        start_condition();
        statusr = *I2C_SR1;
        regw_u32(I2C_DR, DISPLAY_ON, 0, OWRITE);
        if(!ack_recv())
                cputs("TIMEOUT4!");
-       stop_condition();
+       stop_condition(); */
 
 
        /* regw_u32(I2C_CR1, 0x1, 8, SETBIT); //start
index 4693c6f..b370294 100644 (file)
@@ -20,6 +20,7 @@ static struct {
                 uint32_t wpos;
 } linefeed;
 
+void set_baudrate();
 
 void * uart_handler() {
 
@@ -52,13 +53,8 @@ void uart_init() {
        //disable temporarily to set values
        regw_u8(USART1_CR1, 0x0, 13, SETBIT);
 
-       /* baud rate 115200,  8MHz / (16 * USARTDIV)
-        * USARTDIV = 4.34
-        * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
-        * MANTISSA: 0d4.34 0d4 -> 0x4 
-        * USART_BRR = 0x45*/
+       set_baudrate();
 
-       regw_u32(USART1_BRR, 0x00000045, 0, OWRITE);
        regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
        
        /* parity = 8 bit, UART1 enabled,
@@ -72,7 +68,7 @@ void uart_init() {
 }
 
 static void wait() {
-       for (int i = 0; i < 100; i++);
+       for (int i = 0; i < 400; i++);
 }
 
 void uart_putc(unsigned char ch) {
@@ -100,12 +96,24 @@ char uart_getc(void) {
          return 0;
  }
 
-
-// move to library 
-/* extern void uart_puts(unsigned char *str) {
-    int i;
-    for (i = 0; i < strlen(str); i++)     {
-        uart_putc(str[i]);
-    }
-} */
-
+/* Calculate baud rate. Example how this is done
+ * to set this register on a stm32
+ * Desired baudrate: 115200,  CLK: 8 MHz
+ * Desired Baudrate = CLK / (16 * USARTDIV)
+ * USARTDIV = 4.34
+ * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
+ * MANTISSA: 0d4.34 0d4 -> 0x4 
+ * USART_BRR = 0x45*/
+       
+void set_baudrate() {
+
+//     rwrite(USART1_BRR, 0x000001A1); 48 MHZ
+//     rwrite(USART1_BRR, 0x0000022B); 64 MHz
+//     rwrite(USART1_BRR, 0x00000138); 36 MHz
+//     rwrite(USART1_BRR, 0x00000271); 72 MHz
+#ifdef ENABLE_HSE
+       rwrite(USART1_BRR, 0x00000138);
+#else
+       rwrite(USART1_BRR, 0x00000045);
+#endif
+}
index f194df0..b13c28f 100644 (file)
@@ -1,5 +1,10 @@
 /* regfunc.h */
 extern char * regtohex(uint32_t );
 extern uint32_t hextoreg(char *);
+extern void rsetbit(volatile uint32_t *, short);
+extern void rclrbit(volatile uint32_t *, short);
+extern void rsetbitsfrom(volatile uint32_t *, short, int);
+extern int rchkbit(volatile uint32_t *, short);
+extern void rwrite(volatile uint32_t *, uint32_t);
 extern void regw_u8(volatile uint32_t *, uint8_t, short, short);
 extern void regw_u32(volatile uint32_t *, uint32_t, short, short);
index 4fd043d..71ecbd5 100644 (file)
 
 /* SYSTEM INFO AND DEBUG */
 #define MCU_ID MEM_ADDR(0xE000ED00) 
-#define FLASH_MEM MEM_ADDR(0x1FFFF000) 
+#define FLASH_MEM MEM_ADDR(0x1FFFF000)
+
+/* POWER CONTROL REGISTERS */
+#define PWR_CR MEM_ADDR(0x40007000)
 
 /* SYSTEM CONTROL BLOCK REGISTER */
 #define SCB_VTOR MEM_ADDR(0xE000ED08) // VECTOR TABLE
 /* SYSTICK REGISTER */
 #define STK_CTRL MEM_ADDR(0xE000E010)
 #define STK_RELOAD MEM_ADDR(0xE000E014)
+#define STK_CALIB MEM_ADDR(0xE000E01C)
 
 /* CLOCK REGISTER */
 #define RCC_CR MEM_ADDR(0x40021000)
 #define RCC_CFGR MEM_ADDR(0x40021004)
+#define RCC_BDCR MEM_ADDR(0x40021020)
 
 /* SYSTEM CONTROL REGISTER */
 #define SYSCTRL_RCC MEM_ADDR(0x40021000)
index e02eded..162dafc 100644 (file)
@@ -1,8 +1,20 @@
 #ifndef __SYSTEM_H
 #define __SYSTEM_H
 
-/* CLOCK.C */
+
+/* CLOCK.C 
+ * Board specific clock settings. These boards often come with two 
+ * external oscillators: one high speed (8MHz) and one low speed (~30kHz).
+ * These values are used throughout the code to calculator desired baud
+ * rates etc.
+ */
+#define ENABLE_HSE     
+#define ENABLE_RTC     
+//efine CRYSTAL_MHZ    8
+//efine CLKSPEED_MHZ   72
 extern void clock_init();
+extern int clock_test();
+// extern void clock_reset();
 
 /* IVT.C */
 extern void ivt_init();
@@ -14,12 +26,6 @@ extern void systick_init();
 /* SYSINFO.C */
 extern void sysinfo();
 
-/* MM.C DELETE TODO */
-//extern void mm_init();
-//extern void * malloc(size_t);
-//extern void free(void *);
-//extern void test_memory(uint32_t *);
-
 /* POOL.c */
 extern void pool_init(size_t, unsigned int, uint32_t *);
 extern void * alloc();
index b783901..9ea7d7b 100644 (file)
@@ -8,6 +8,34 @@
 
 #include <sys/mmap.h>
 
+
+// register set bit at position
+void rsetbit(volatile uint32_t * reg, short pos) {
+       *reg = *reg | (0x1 << pos);
+}
+
+// register set bits from certain pos
+void rsetbitsfrom(volatile uint32_t * reg, short pos, int val) {
+       *reg = *reg | (val << pos);
+}
+
+// register clear bit at position
+void rclrbit(volatile uint32_t * reg, short pos) {
+       *reg = *reg & ~(0x1 << pos);
+}
+
+int rchkbit(volatile uint32_t * reg, short pos) {
+       if ((*reg >> pos) & 0x1)
+               return 1;
+       return 0;
+}
+
+// register (over)write
+void rwrite(volatile uint32_t * reg, uint32_t val) {
+       *reg = val;
+}
+
+
 /* write value (uint8_t) to register */
 void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
 
@@ -19,7 +47,7 @@ void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
                        *reg = *reg | (val << shift);
                        break;
                case CLRBIT:
-                       *reg = (val << shift);
+                       *reg = *reg & ~(val << shift);
                        break;
        }
 }
@@ -35,6 +63,7 @@ void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
                        *reg = *reg | (val << shift);
                        break;
                case CLRBIT:
+                       *reg = *reg & ~(val << shift);
                        break;
        }
 }
diff --git a/main.c b/main.c
index 342059e..4240f0c 100644 (file)
--- a/main.c
+++ b/main.c
 
 void main()
 {
+       clock_init();
        ivt_init();
        uart_init();
 //     cputs("ROBSYS LOADING...\n");
        systick_init();
        led_init();
+
+       // SPEED_TEST
+/*     cputs("START TEST (8MHz) \n");
+       int a;
+       for (int i = 0; i < 20000000; i++) {
+               a + 2;  
+       }
+       a = 0;
+       cputs("END TEST\n");
+       
+       //! 
+       clock_init();
+
+       cputs("START TEST (??MHz) \n");
+       for (int i = 0; i < 20000000; i++) {
+               a + 2;  
+       }
+       cputs("END TEST\n"); */
+
        sysinfo();
 
-       tm1637_init();
-       tm1637_start();
+//     tm1637_init();
+//     tm1637_start();
 
        //uint32_t test = hextoreg("12345678");
                
index 1d632ec..05f515f 100644 (file)
--- a/systick.c
+++ b/systick.c
@@ -5,7 +5,8 @@
 #include <sys/robsys.h>
 #include <sys/mmap.h>
 
-#include <lib/regfunc.h> // TODO
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
 
 struct interrupt_frame {
 
@@ -22,25 +23,31 @@ struct interrupt_frame {
 //__attribute__ ((interrupt))
 void * systick_handler(/* struct interrupt_frame * frame */) {
 
-//     uint32_t volatile status;
-       //uart_puts("TICKING\n");
+//     cputs("TICKING\n");
 //     for(;;);
 }
 
 
 void systick_init() {
 
-       /* Enable the counter and enable the interrupt
-        * associated with it */
-       *STK_CTRL = (volatile uint32_t) 0x00000003;
-
-       /* The counter reload register here holds 
-        * 0x1000 -- that's 4096 clock cycles -- if 
-        * it is down to zero it is restores the value */
-       *STK_RELOAD = (volatile uint32_t) 0x00400000; 
-
        /* Every time the counter counts down to zero
         * a systick exception is asserted. Systick has
         * exception number 15. in the vector table  */
        ivt_set_gate(15, systick_handler, 0); 
+
+       /* Get calibration and set this to 1 sec
+        * !Most boards have a 1 ms or 10 ms 
+        * calibration value */
+       int calib = (*STK_CALIB << 0) * 500;
+
+       /* The counter reload registers counts down to zero
+        * and then it is restores the value */
+       rwrite(STK_RELOAD, calib);
+       
+       /* Enable the counter and enable the interrupt
+        * associated with it */
+       rsetbit(STK_CTRL, 0);
+       rsetbit(STK_CTRL, 1);
+
+
 }