rtc implementation
authorRobin Krens <robin@robinkrens.nl>
Thu, 1 Aug 2019 15:32:49 +0000 (23:32 +0800)
committerRobin Krens <robin@robinkrens.nl>
Thu, 1 Aug 2019 15:32:49 +0000 (23:32 +0800)
Basic rtc implementation. LSE oscillator is used as clock source
(32kHz). Second (periodic) interrupt is enabled to trigger a interrupt
every second. RTC is not calibrated with tamper pin (so could be off
with a few second each month). Added small uptime cmd.

Makefile
clock.c
drivers/uart.c
include/sys/mmap.h
include/sys/robsys.h
main.c
rtc.c [new file with mode: 0644]
term.c

index edff16a..5cc5791 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 clock.o 
+_OBJ = ivt.o systick.o sysinfo.o term.o main.o clock.o rtc.o 
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
 DDIR = obj/drivers
diff --git a/clock.c b/clock.c
index 2bcca11..02a26ab 100644 (file)
--- a/clock.c
+++ b/clock.c
@@ -13,9 +13,6 @@
  * 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
@@ -48,34 +45,11 @@ static void setup_hse() {
        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
 
-#ifdef ENABLE_RTC
-setup_rtc();
-#endif
-      
 }
 
index b370294..05f0406 100644 (file)
@@ -10,7 +10,6 @@
 
 #include <drivers/uart.h>
 
-#define RXNE ((*USART1_SR >> 5) & 0x1)
 #define UARTBUF 256
 #define ECHO 1
 
@@ -24,16 +23,12 @@ void set_baudrate();
 
 void * uart_handler() {
 
-       //uart_puts("echo: ");
-       while (RXNE) {
+       while (rchkbit(USART1_SR, 5)) {
                char echochar = *USART1_DR;
-//             uart_putc(echochar);
                 linefeed.buf[linefeed.wpos++] = echochar;
                  if (linefeed.wpos == UARTBUF)
                          linefeed.wpos = 0;
-               //regw_u32(USART1_DR, echochar, 0, O_WRITE);
        }
-       //uart_putc('\n');
                
 }
 
@@ -43,45 +38,43 @@ void uart_init() {
        linefeed.wpos = 0;
 
        //memset(&linefeed, 0, (sizeof(struct linefeed) ));
-       regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
+       //regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
+       rsetbitsfrom(RCC_APB2ENR, 0, 0x4005);
        
        /* (after enable GPIOA), on PA9&PA10 and set mode
         *  to alternative output */
-       regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
-       regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9 TODO: check
+       //regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
+       rwrite(GPIOA_CRH, 0x444444D4);
+       //regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9 TODO: check
+       rsetbitsfrom(AFIO_EVCR, 0, 0x89);
 
        //disable temporarily to set values
-       regw_u8(USART1_CR1, 0x0, 13, SETBIT);
+       //regw_u8(USART1_CR1, 0x0, 13, SETBIT);
+       rclrbit(USART1_CR1, 13);
 
        set_baudrate();
 
-       regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
+       //regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
+       rwrite(USART1_CR2, 0x0000);
        
        /* parity = 8 bit, UART1 enabled,
         * TX and RX enabled, interrupts enabled */
-       //regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
-       regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
+       //regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
+       rwrite(USART1_CR1, 0x0000302C);
 
        ivt_set_gate(53, uart_handler, 0);
        
-       *NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
-}
-
-static void wait() {
-       for (int i = 0; i < 400; i++);
+       rsetbit(NVIC_ISER1, 5);
 }
 
 void uart_putc(unsigned char ch) {
        
        if (ch == '\n') {
-               while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
+               while(!rchkbit(USART1_SR, 6));
                regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
        }
-
-       while (*USART1_SR & 0x0C) {} 
+               while(!rchkbit(USART1_SR, 6));
                regw_u8(USART1_DR, ch, 0, OWRITE);
-
-       wait();
 }
 
 char uart_getc(void) {
index 71ecbd5..6dda221 100644 (file)
@@ -51,7 +51,7 @@
 #define STK_RELOAD MEM_ADDR(0xE000E014)
 #define STK_CALIB MEM_ADDR(0xE000E01C)
 
-/* CLOCK REGISTER */
+/* RESET AND CLOCK REGISTER */
 #define RCC_CR MEM_ADDR(0x40021000)
 #define RCC_CFGR MEM_ADDR(0x40021004)
 #define RCC_BDCR MEM_ADDR(0x40021020)
 
 #define GPIOA_CRH MEM_ADDR(0x40010804) // for USART1
 #define GPIOB_CRL MEM_ADDR(0x40010C00) // low register (!) for I2C1
-#define GPIOC_CRL MEM_ADDR(0x40011000) // for led
-#define GPIOC_ODR MEM_ADDR(0x4001100C) //
+#define GPIOC_CRL MEM_ADDR(0x40011000) // led
+#define GPIOC_ODR MEM_ADDR(0x4001100C)
+
+//#define GPIOD_CRL MEM_ADDR(0x40011400)
+//#define GPIOD_ODR MEM_ADDR(0x4001140C)
 
 #define AFIO_EVCR MEM_ADDR(0x40010000)
 
 #define USART1_CR1 MEM_ADDR(0x4001380C)
 #define USART1_CR2 MEM_ADDR(0x40013810)
 #define USART1_CR3 MEM_ADDR(0x40013814)
+
+/* REAL TIME CLOCK REGISTERS */
+#define RTC_CRH MEM_ADDR(0x40002800) // interrupts
+#define RTC_CRL MEM_ADDR(0x40002804)
+#define RTC_PRLL MEM_ADDR(0x4000280C)
+#define RTC_CNTH MEM_ADDR(0x40002818)
+#define RTC_CNTL MEM_ADDR(0x4000281C)
+
+/* BACKUP (CALIBR) REGISTERS */
+#define BKP_RTCCR MEM_ADDR(0x40006C2C) // RTC Calibration 
index 162dafc..78aedef 100644 (file)
@@ -9,13 +9,16 @@
  * 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 int clock_test();
 // extern void clock_reset();
 
+/* RTC.C */
+#define ENABLE_RTC     
+extern void rtc_init();
+
 /* IVT.C */
 extern void ivt_init();
 extern void ivt_set_gate(unsigned char, void *(), short);
diff --git a/main.c b/main.c
index 4240f0c..ccf6015 100644 (file)
--- a/main.c
+++ b/main.c
 #include <drivers/led.h>
 #include <drivers/tm1637.h>
 
+//void sleep() {
+//
+//     __asm__ __volatile__("wfe");
+//
+//}
+
 void main()
 {
        clock_init();
@@ -32,6 +38,7 @@ void main()
 //     cputs("ROBSYS LOADING...\n");
        systick_init();
        led_init();
+       rtc_init();
 
        // SPEED_TEST
 /*     cputs("START TEST (8MHz) \n");
@@ -50,9 +57,9 @@ void main()
                a + 2;  
        }
        cputs("END TEST\n"); */
-
        sysinfo();
 
+
 //     tm1637_init();
 //     tm1637_start();
 
diff --git a/rtc.c b/rtc.c
new file mode 100644 (file)
index 0000000..9ffffc7
--- /dev/null
+++ b/rtc.c
@@ -0,0 +1,85 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/30 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * 
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/robsys.h>
+#include <sys/mmap.h>
+
+#include <lib/regfunc.h>
+#include <lib/stdio.h>
+
+
+static void periodic_intr() {
+
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(RTC_CRL, 4);
+       
+       rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
+       
+       while(!rchkbit(RTC_CRL, 5)); 
+
+       rwrite(RTC_PRLL, 0x7FFF); // 1 second
+       rclrbit(RTC_CRL, 4);
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+}
+
+static void calibrate_rtc() {
+
+
+//     rsetbit(BKP_RTCCR, 7); // enable CC0, 
+//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+//     rsetbit(RTC_CRL, 4);
+
+       // Set up and check tamper pin
+       
+//     rclrbit(RTC_CRL, 4);
+//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+}
+
+void * rtc_handler() {
+
+       //cputs("TICKING IN REAL TIME\n");
+       rclrbit(RTC_CRL, 0);
+}
+
+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 */
+       
+       ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */
+
+//     calibrate_rtc(); TODO: TAMPER PIN?
+       
+       periodic_intr();// setup periodic interrupt
+
+}
+
+void rtc_init() {
+
+#ifdef ENABLE_RTC
+       setup_rtc();
+#endif
+
+}
diff --git a/term.c b/term.c
index 51eb9cf..dba355b 100644 (file)
--- a/term.c
+++ b/term.c
 #define BUFSIZE 200
 #define MAXARGS 5
 #define WHITESPACE "\t\r\n "
-#define BUILTINCMDS 3
+#define BUILTINCMDS 4
 
 int help(int, char**);
 
 /* 
  * Built in commands
  *     info -- shows basic info of system
- *     reset -- software reset
+ *     uptime -- uptime; read from the RTC register
+ *     reset -- software reset TODO
  *     show [ADDRESS-ADDRESS] -- shows SRAM range
  *     switchmode -- switch to unprivileged mode
  * */
@@ -37,11 +38,17 @@ struct cmd {
 
 struct cmd builtincmds[4];
 
-int help(int argc, char ** argsv) {
+int info(int argc, char ** argsv) {
        sysinfo();
        return 0;
 }
 
+int uptime(int arg, char ** argsv) {
+       cputs("CURRENT UPTIME: ");
+       cputs(regtohex(*RTC_CNTL));
+       cputchar('\n');
+}
+
 int led(int argc, char ** argsv) {
 
 
@@ -116,8 +123,8 @@ int exec_cmd(char * buf) {
 
 void terminal() {
 
-               builtincmds[0].name = "help";
-       builtincmds[0].function = help;
+               builtincmds[0].name = "info";
+       builtincmds[0].function = info;
 
        builtincmds[1].name = "led";
        builtincmds[1].function = led;
@@ -125,6 +132,10 @@ void terminal() {
        builtincmds[2].name = "show";
        builtincmds[2].function = show;
 
+       builtincmds[3].name = "uptime";
+       builtincmds[3].function = uptime;
+
+
        char *buf;
         cputs("WELCOME TO ROBSYS!\n");