High speed external clock set to 36 MHz, 72MHz speeds crashed on board.
No changes to buspeeds. Adaptions to UART baud rates.
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
+/* (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
+
}
+
#include <drivers/tm1637.h>
-#define TIMEOUT 1000
+#define TIMEOUT 5000
#define DATASET 0x40
#define CONTROL 0x80
int ack_recv() {
int cnt = 0;
- while(!(*I2C_SR1 & 0x1)) {
+ while(!(*I2C_SR1 & 0x2)) {
cnt++;
if (cnt > TIMEOUT)
return 0;
}
+int buf_empty() {
+ int cnt = 0;
+ while(!(*I2C_SR1 & 0x80)) {
+ cnt++;
+ if (cnt > TIMEOUT)
+ return 0;
+ }
+
+ return 1;
+}
+
int delay() {
int a = 0;
//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
uint32_t wpos;
} linefeed;
+void set_baudrate();
void * uart_handler() {
//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,
}
static void wait() {
- for (int i = 0; i < 100; i++);
+ for (int i = 0; i < 400; i++);
}
void uart_putc(unsigned char ch) {
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
+}
/* 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);
/* 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)
#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();
/* 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();
#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) {
*reg = *reg | (val << shift);
break;
case CLRBIT:
- *reg = (val << shift);
+ *reg = *reg & ~(val << shift);
break;
}
}
*reg = *reg | (val << shift);
break;
case CLRBIT:
+ *reg = *reg & ~(val << shift);
break;
}
}
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");
#include <sys/robsys.h>
#include <sys/mmap.h>
-#include <lib/regfunc.h> // TODO
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
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);
+
+
}