basic led gpio driver
authorRobin Krens <robin@robinkrens.nl>
Thu, 25 Jul 2019 14:33:25 +0000 (22:33 +0800)
committerRobin Krens <robin@robinkrens.nl>
Thu, 25 Jul 2019 14:33:25 +0000 (22:33 +0800)
Makefile
drivers/led.c [new file with mode: 0644]
drivers/tm1637.c [new file with mode: 0644]
drivers/uart.c
include/drivers/led.h [new file with mode: 0644]
include/drivers/tm1637.h [new file with mode: 0644]
include/sys/mmap.h
ivt.c
main.c
start.asm
sysinfo.c

index 520f0f1..3da9701 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ _OBJ = ivt.o systick.o sysinfo.o term.o main.o
 OBJ = $(patsubst %, $(ODIR)/%,$(_OBJ))
 
 DDIR = obj/drivers
-_DRIVERS = uart.o
+_DRIVERS = uart.o tm1637.o led.o
 DRIVERS = $(patsubst %, $(DDIR)/%,$(_DRIVERS))
 
 LDIR = obj/lib
diff --git a/drivers/led.c b/drivers/led.c
new file mode 100644 (file)
index 0000000..0cdda5a
--- /dev/null
@@ -0,0 +1,47 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/25 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Hardly a driver, but a driver nonetheless. Enables clock on 
+ * a GPIOx range and sets the GPIOx pin in push-pull output mode. 
+ * Basic on - off function (writing a 1 or zero 0) 
+ * 
+ * $USAGE$
+ * In the code below we enable GPIOC and use PC0 as output. But 
+ * basically any GPIO range or pin could be used. Note that the 
+ * output register is only word accessible.
+ *
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+
+#include <drivers/led.h>
+
+
+void led_init() {
+
+       regw_u8(RCC_APB2ENR, 0x1, 4, SETBIT); // enable GPIOC
+       regw_u32(GPIOC_CRL, 0x44444442, 0, OWRITE); // set PC0 pin to output mode
+       *GPIOC_ODR = 0xFFFF; // only writable in word mode
+
+}
+
+void led_on() {
+       *GPIOC_ODR = 0x0001;
+}
+
+void led_off() {
+       *GPIOC_ODR = 0x0000;
+}
+
diff --git a/drivers/tm1637.c b/drivers/tm1637.c
new file mode 100644 (file)
index 0000000..a4e3842
--- /dev/null
@@ -0,0 +1,44 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/25 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ * Basic driver for the TM1637. The TM1637 is 7 segment
+ * ledclock peripheral. Communication is over I2C.
+ *
+ * */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/mmap.h>
+#include <sys/robsys.h>
+
+#include <lib/regfunc.h>
+#include <lib/string.h>
+
+#include <drivers/tm1637.h>
+
+
+void tm1637_init() {
+
+ /* Program the peripheral input clock in I2C_CR2 Register in order to generate correct timings
+ Configure the clock control registers
+ Configure the rise time register
+ Program the I2C_CR1 register to enable the peripheral
+ Set the START bit in the I2C_CR1 register to generate a Start condition 
+
+ ENABLE GPIOB6 and B7*/
+
+ //regw_u8(RCC_APB1ENR, 0x1, 21, SETBIT);
+ //regw_u32(RCC_APB2ENR, 0x1, 3, SETBIT);
+ // //regw_u8(AFIO_EVCR, 0x89, 0, SETBIT);// set event control register, output on ?
+ // regw_u32(GPIOB_CRL, 0xEE444444, 0, OWRITE);
+
+}
+
index 6fc940b..a107548 100644 (file)
@@ -47,7 +47,7 @@ void uart_init() {
        /* (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
+       regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9 TODO: check
 
        //disable temporarily to set values
        regw_u8(USART1_CR1, 0x0, 13, SETBIT);
diff --git a/include/drivers/led.h b/include/drivers/led.h
new file mode 100644 (file)
index 0000000..8e090d8
--- /dev/null
@@ -0,0 +1,4 @@
+extern void led_init();
+extern void led_on();
+extern void led_off();
+
diff --git a/include/drivers/tm1637.h b/include/drivers/tm1637.h
new file mode 100644 (file)
index 0000000..319d5c5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __TM1637_H
+#define __TM1637_H
+
+extern void tm1637_init();
+
+#endif
index a5921d2..c3c91a1 100644 (file)
 #define SETBIT 0x02
 #define CLRBIT 0x03
 
+/* 64kB SRAM located at SRAM_OFFSET */
+#define SRAM_SIZE      0x00010000 
+#define SRAM_OFFSET    0x20000000
+
 /* Safety macro's to get the address or value */
 #define MEM_VALUE(addr) *((volatile uint32_t(*) (addr))
 #define MEM_ADDR(addr) ((volatile uint32_t *) (addr))
@@ -49,6 +53,7 @@
 
 /* SYSTEM CONTROL REGISTER */
 #define SYSCTRL_RCC MEM_ADDR(0x40021000)
+#define RCC_APB1ENR MEM_ADDR(0x4002101C) // register to enable I2C
 #define RCC_APB2ENR MEM_ADDR(0x40021018) // register to enable USART1
 
 #define SYSCTRL_RIS MEM_ADDR(0x400FE050)
 #define SYSCTRL_RCGC2 MEM_ADDR(0x400FE108)
 #define GPIOPA_AFSEL MEM_ADDR(0x40004420)
 
-#define GPIOA_CRH MEM_ADDR(0x40010804)
+#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 AFIO_EVCR MEM_ADDR(0x40010000)
 
diff --git a/ivt.c b/ivt.c
index a6761d0..9f8e643 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -56,50 +56,42 @@ struct interrupt_frame {
 
 /* 
  * Vector table, each entry contains an interrupt
- * service routine:  
- *
+ * service routine: 
  * interrupt vector 1-15: processor exceptions
  * interrupt vector 16-92: irq0 - irq ..
- *
  * Vector table needs to be aligned in memory.
  * */
-
 uint32_t __attribute__((aligned(0x100))) ivt[92];
 
-/* each message corresponds to each and every exception. 
- * We get the correct message by accessing
- *  exception_message[interrupt_number] 
- *  exception_message[0] is not used (=MSP)*/
-
+/* Each message corresponds to each and every exception. */
 char * exception_message(uint8_t intnr) {
 
-       char * messages[] = {
-           "--",
-           "RESET",
-           "NMI",
-           "HARD FAULT",
-           "MEMMANAGE FAULT",
-           "BUS FAULT",
-           "USAGE FAULT",
-           "RESERVED",
-           "SVC",
-           "DEBUG MONITOR",
-           "RESERVED",
-           "RESERVED",
-           "RESERVED",
-           "RESERVED",
-           "PENDSV",
-           "SYSTICK",
-           "IRQ1",
-           "IRQ2",
-           "IRQ3",
-           "IRQ4",
-           // add more if needed
-       };
-
-       if (intnr < 20) // TODO: strlen
-               return messages[intnr];
+char * messages[] = {
+    "--",
+    "RESET",
+    "NMI",
+    "HARD FAULT",
+    "MEMMANAGE FAULT",
+    "BUS FAULT",
+    "USAGE FAULT",
+    "RESERVED",
+    "SVC",
+    "DEBUG MONITOR",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "RESERVED",
+    "PENDSV",
+    "SYSTICK",
+    "IRQ1",
+    "IRQ2",
+    "IRQ3",
+    "IRQ4",
+    // add more if needed
+};
 
+if (intnr < 20) // TODO: strlen
+       return messages[intnr];
        return NULL;
 }
 
@@ -107,11 +99,11 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 
        ivt[num] = (uint32_t) isr;
        *NVIC_ISER0 = (1 << ((uint32_t)(num) & 0x1F));
-       /* Priorities */
+       /* TODO: Priorities */
 }
 
 
-/* Dummy interrupt: comment out the comment to use a naked f
+/* Dummy interrupt: comment out the comment to use a naked
  * function */
 
 // __attribute__ ((interrupt)) 
@@ -129,13 +121,16 @@ void * dummy_isr(/* struct interrupt_frame * frame */) {
 /* Initialize interrupt vector  */
 void ivt_init() {
 
-       /* clear entire IVT, in SRAM location for SRAM + .data (in .bss section) */
+       /* clear entire IVT location in memory  */
        memset(&ivt, 0, (sizeof(uint32_t) * 92));
 
-       // stack top is loaded from the first entry table on boot/reset
-       // don't need to relocate or init this here
+       /* The reset, NMI and hardfault handlers are originally
+        * defined in the assembly start up and can be 
+        * reused or overwritten. 
+       *  */
        extern void * reset,  * nmi, * hardfault;
 
+       // set dummy handlers 
        for (int i = 1; i <= 64 ; i++) {
                ivt_set_gate(i, dummy_isr, 0);
        }
diff --git a/main.c b/main.c
index 35b718e..c5ee202 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,6 +5,8 @@
  * Initial version 
  * 
  * $DESCRIPTION$
+ * Main intialize basic components of the boards
+ * and jumps to a terminal
  *
  * */
 
 #include <sys/mmap.h>
 
 #include <drivers/uart.h>
+#include <drivers/led.h>
+#include <drivers/tm1637.h>
 
 void main()
 {
        ivt_init();
+       
        uart_init();
-
        systick_init();
+
+       led_init();
        
        sysinfo();
 
-       extern void stub();
+       //extern void stub();
        //stub();
        //__asm__ __volatile__ ("ldc p1, cr1, r0");
 
-       terminal();
+       while(1) {
+               int r;
+               for (int i = 0; i < 50000; i++) {
+                       r = 0;  
+               }
+               led_on();
+               for (int i = 0; i < 50000; i++) {
+                       r = 0;  
+               }
+               led_off();
+       }
+       // terminal();
 
        for(;;) {
 
index 54d2b91..180f9a4 100644 (file)
--- a/start.asm
+++ b/start.asm
@@ -1,4 +1,13 @@
-       .equ STACK_TOP, 0x20010000 /* placed at 32kB, TODO: could place at top of SRAM? */
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * $DESCRIPTION$
+ *
+ * */
+       .equ STACK_TOP, 0x20010000 /* placed at 64kB, top of SRAM */
        .text
        .global _start
        .global reset, nmi, hardfault
index e9b2429..ba639a6 100644 (file)
--- a/sysinfo.c
+++ b/sysinfo.c
@@ -1,3 +1,11 @@
+/* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
+ * 
+ * $LOG$
+ * 2019/7/20 - ROBIN KRENS     
+ * Initial version 
+ * 
+ * */
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -8,8 +16,6 @@
 #include <lib/stdio.h>
 #include <lib/regfunc.h>
 
-#define MEM_SIZE       0x00010000 
-#define MEM_OFFSET     0x20000000
 
 uint32_t get_msp(void);
 
@@ -44,12 +50,12 @@ void sysinfo() {
        extern char _endofbss;
        
        uint32_t current_stack = get_msp();
-       uint32_t stack_usage = (MEM_OFFSET + MEM_SIZE) - current_stack;
-       uint32_t data_bss = &_endofbss - MEM_OFFSET;
-       uint32_t mem_free = MEM_SIZE - stack_usage - data_bss;
+       uint32_t stack_usage = (SRAM_OFFSET + SRAM_SIZE) - current_stack;
+       uint32_t data_bss = &_endofbss - SRAM_OFFSET;
+       uint32_t mem_free = SRAM_SIZE - stack_usage - data_bss;
 
        cputs("# TOTAL MEMORY: ");
-       cputs(regtohex(MEM_SIZE));
+       cputs(regtohex(SRAM_SIZE));
        cputchar('\n');
        cputs("# FREE MEMORY: ");
        cputs(regtohex(mem_free));