From: Robin Krens Date: Tue, 30 Jul 2019 20:11:42 +0000 (+0800) Subject: HSE usage X-Git-Url: https://robinkrens.nl/gitweb/?p=cortex-from-scratch;a=commitdiff_plain;h=d98e5505c9433565ebb71fa6a843997ea0e0cda6 HSE usage High speed external clock set to 36 MHz, 72MHz speeds crashed on board. No changes to buspeeds. Adaptions to UART baud rates. --- diff --git a/Makefile b/Makefile index 3da9701..edff16a 100644 --- 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 --- 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 #include #include -#include -#include +#include +#include + +#include + +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 + } + diff --git a/drivers/tm1637.c b/drivers/tm1637.c index 517e0cf..a2889fd 100644 --- a/drivers/tm1637.c +++ b/drivers/tm1637.c @@ -28,7 +28,7 @@ #include -#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 diff --git a/drivers/uart.c b/drivers/uart.c index 4693c6f..b370294 100644 --- a/drivers/uart.c +++ b/drivers/uart.c @@ -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 +} diff --git a/include/lib/regfunc.h b/include/lib/regfunc.h index f194df0..b13c28f 100644 --- a/include/lib/regfunc.h +++ b/include/lib/regfunc.h @@ -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); diff --git a/include/sys/mmap.h b/include/sys/mmap.h index 4fd043d..71ecbd5 100644 --- a/include/sys/mmap.h +++ b/include/sys/mmap.h @@ -32,7 +32,10 @@ /* 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 @@ -46,10 +49,12 @@ /* 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) diff --git a/include/sys/robsys.h b/include/sys/robsys.h index e02eded..162dafc 100644 --- a/include/sys/robsys.h +++ b/include/sys/robsys.h @@ -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(); diff --git a/lib/regfunc.c b/lib/regfunc.c index b783901..9ea7d7b 100644 --- a/lib/regfunc.c +++ b/lib/regfunc.c @@ -8,6 +8,34 @@ #include + +// 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 --- a/main.c +++ b/main.c @@ -26,15 +26,35 @@ 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"); diff --git a/systick.c b/systick.c index 1d632ec..05f515f 100644 --- a/systick.c +++ b/systick.c @@ -5,7 +5,8 @@ #include #include -#include // TODO +#include +#include 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); + + }