uart small ping pong receive, update of register functions
authorRobin Krens <robin@robinkrens.nl>
Thu, 18 Jul 2019 16:55:33 +0000 (00:55 +0800)
committerRobin Krens <robin@robinkrens.nl>
Thu, 18 Jul 2019 16:55:33 +0000 (00:55 +0800)
no priorities, so one handler might keep 霸占 the CPU

Makefile
include/mmap.h
include/stm32.h
ivt.c
lib.c
main.c
regf.c [new file with mode: 0644]
sysinfo.c
systick.c
uart.c

index 9eba3b4..c4803b9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,7 +19,8 @@ all:
        $(CC) $(CFLAGS) -c -I./include -ffreestanding -o sysinfo.o sysinfo.c 
        $(CC) $(CFLAGS) -c -I./include -ffreestanding -o lib.o lib.c 
        $(CC) $(CFLAGS) -c -I./include -ffreestanding -o mm.o mm.c 
-       $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o sysinfo.o lib.o mm.o
+       $(CC) $(CFLAGS) -c -I./include -ffreestanding -o regf.o regf.c 
+       $(LD) -nostartfiles -T link.ld -o start.out start.o main.o uart.o ivt.o systick.o sysinfo.o lib.o mm.o regf.o
        $(MKIMG) -Obinary -R .data start.out kernel.bin
 
 run:
index 6fa4adc..d0f9338 100644 (file)
@@ -6,12 +6,11 @@
  * 
  * */
 
-
 #define BSS_BASE ((volatile uint32_t *)(0x20000800)) //TODO: .data flexible siz
 #define TOTAL_MEM_SIZE 64000;
 
 /* SYSTEM INFO AND DEBUG */
-#define MCU_ID ((volatile uint32_t*)( 0xE0042000)) 
+#define MCU_ID ((volatile uint32_t*)( 0xE000ED00)) 
 #define FLASH_MEM ((volatile uint32_t*)( 0x1FFFF000)) 
 
 /* SYSTEM CONTROL BLOCK REGISTER */
@@ -19,6 +18,7 @@
 
 /* NESTED VECTOR INTERRUPT CONTROL REGISTER */
 #define NVIC_ISER0 ((volatile uint32_t*)( 0xE000E100)) // interrupt set enable register
+#define NVIC_ISER1 ((volatile uint32_t*)( 0xE000E104)) // interrupt set enable register
 
 /* SYSTICK REGISTER */
 #define STK_CTRL ((volatile uint32_t *)(0xE000E010))
@@ -30,7 +30,7 @@
 
 /* SYSTEM CONTROL REGISTER */
 #define SYSCTRL_RCC ((volatile unsigned long *)(0x40021000))
-#define RCC_APB2ENR ((volatile unsigned long *)(0x40021018)) // register to enable USART1
+#define RCC_APB2ENR ((volatile uint32_t *)(0x40021018)) // register to enable USART1
 
 #define SYSCTRL_RIS ((volatile unsigned long *)(0x400FE050))
 #define SYSCTRL_RCGC1 ((volatile unsigned long *)(0x400FE104))
 #define GPIOPA_AFSEL ((volatile unsigned long *)(0x40004420))
 
 #define GPIOA_CRH ((volatile unsigned long *)(0x40010804))
-#define AFIO_EVCR ((volatile unsigned long *)(0x40010000))
+
+#define AFIO_EVCR ((volatile uint32_t *)(0x40010000))
+//#define AFIO_EXTICR1 ((volatile uint32_t *)(AFIO_EVCR + 0x08))
+
+/* EXTERNAL INTERRUPTS */
+#define EXTI_IMR ((volatile uint32_t *)(0x40010400))
+#define EXTI_RTSR ((volatile uint32_t *)  (EXTI_IMR + 0x08))
+//#define EXTI_FTSR ((volatile uint32_t *)  (EXTI_IMR + 0x04))
 
 /* UART1 REGISTERS */
 #define USART1_BASE ((volatile uint32_t) (0x40013800))
index 4f52257..62ee93e 100644 (file)
@@ -34,4 +34,8 @@ extern void * mm_alloc(size_t);
 extern void free(void *);
 extern void test_memory(uint32_t *);
 
+/* REGF.C */ 
+extern void regw_u8(volatile uint32_t *, uint8_t, short, short);
+extern void regw_u32(volatile uint32_t *, uint32_t, short, short);
+
 #endif
diff --git a/ivt.c b/ivt.c
index 1b4cb9b..6df1e8b 100644 (file)
--- a/ivt.c
+++ b/ivt.c
@@ -5,15 +5,63 @@
 #include <mmap.h>
 
 /* 
+ * These values are pushed on the stack just before
+ * entering the ISR. Normally, this would require
+ * assembly or inline assembly code. I use a so-called
+ * 'naked function' __attribute__ ((interrupt)) which
+ * gives me a little bit more control over the caller
+ *
+ * The following register are pushed to the stack
+ * in reverse order
+ *
+ * */
+struct interrupt_frame {
+
+       uint32_t r0; // N-32
+       uint32_t r1;
+       uint32_t r2;
+       uint32_t r3;
+       uint32_t r12;
+       uint32_t lr;
+       uint32_t pc;
+       uint32_t psr; // N-4
+};
+
+/* 
  * Vector table, each entry contains an interrupt
- * service routine:  
+ * service routine:  
  *
  * interrupt vector 1-15: processor exceptions
- * interrupt vector 16-32: irq0 - irq ..
+ * interrupt vector 16-64: irq0 - irq ..
  * */
 
-uint32_t ivt[32];
+uint32_t ivt[64];
 
+/* 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)*/
+unsigned char *exception_messages[] =
+{
+    "--",
+    "RESET",
+    "NMI",
+    "HARD FAULT",
+    "MEMMANAGE FAULT",
+    "BUS FAULT",
+    "USAGE FAULT",
+    "RESERVED",
+    "SVC",
+    "DEBUG MONITOR",
+    "RESERVED",
+    "PENDSV",
+    "SYSTICK",
+    "IRQ1",
+    "IRQ2",
+    "IRQ3",
+    "IRQ4",
+    // add more if needed
+};
 
 void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 
@@ -24,9 +72,25 @@ void ivt_set_gate(unsigned char num, void * isr(), short pri) {
 
 
 /* Dummy interrupt */
-void * dummy_isr() {
+__attribute__ ((interrupt)) 
+void * dummy_isr(struct interrupt_frame * frame) {
+
+
+       uint32_t * p = (volatile uint32_t *) 0x21000000;
 
+       addrtohex(frame->r0);
+       addrtohex(frame->r1);
+       addrtohex(frame->r2);
+       addrtohex(frame->r3);
+       addrtohex(frame->r12);
+       addrtohex(frame->lr);
+       addrtohex(frame->pc);
+       addrtohex(frame->psr);
+       
+       //__asm__ __volatile__ ("MRS r0, IPSR");
+       //addrtohex(frame->r0);
        uart_puts("EXCEPTION X: SYSTEM HALTED\n");
+       
        for(;;);
 }
 
@@ -40,18 +104,16 @@ void ivt_init() {
        // don't need to relocate or init this here
        extern void * reset,  * nmi, * hardfault;
 
-       ivt_set_gate(1, dummy_isr, 0);
-       ivt_set_gate(2, dummy_isr, 0);
-       ivt_set_gate(3, dummy_isr, 0);
-       ivt_set_gate(4, dummy_isr, 0);
-       ivt_set_gate(5, dummy_isr, 0);
-       ivt_set_gate(6, dummy_isr, 0);
+       for (int i = 1; i < 7; i++) {
+               ivt_set_gate(i, dummy_isr, 0);
+       }
 
        /* the vector table starts at 0x0. Since the address 0x0 point to 
         * bootcode, it is on ROM or FLASH. The vector table can be
         * relocated to other memory locations. We can do this by setting 
         * a register in the NVIC called the vector table offset register */
 
-       *SCB_VTOR = (volatile uint32_t) &ivt; 
+       //*SCB_VTOR = (volatile uint32_t) &ivt; 
+       regw_u32(SCB_VTOR, (uint32_t) &ivt, 0, 0x01);
 
 }
diff --git a/lib.c b/lib.c
index 69bb12d..bc5bc8c 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -7,7 +7,7 @@
 /* Temporary libc functions, which can later be 
  * replaced by a *real* library */
 
-char hexbuf[8] = {'0', '0','0', '0','0', '0','0', '0'};
+char hexbuf[8];
 
 void addrtohex(uint32_t addr) {
        char tmpbuf[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
@@ -33,3 +33,5 @@ void addrtohex(uint32_t addr) {
        uart_putc('\n');
 }
 
+
+
diff --git a/main.c b/main.c
index 84496d5..4134c95 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
-#include <stm32.h> // <-- your own header file located located in ./include
+#include <stm32.h> // <-- my own header file located located in ./include
 #include <mmap.h>
 
 
@@ -46,19 +46,23 @@ void main()
        ivt_init();
 //     clock_init();
        uart_init();
-       systick_init();
+//     systick_init();
        uart_puts("LOADING SYSTEM 0.1 ...\n");
        sysinfo();
        mm_init();
 
-       int * p2 = mm_alloc(200);
-       *p2 = 0x12345678;
+       //int * p2 = mm_alloc(512);
+       //memset(p2, 'a', 512);
 
-       test_memory(p2);
+       //addrtohex(p2);
+       //addrtohex(*p2);
 
-       addrtohex(p2);
-       addrtohex(*p2);
+       //uint32_t * p = (volatile unsigned)  0x21000000;
+       //regw_u32(p, 0x0CCCCCCCC, 4, 0x01);
 
+       //regw_u8(p, 0xFF, 0, 0x02);
+       
+       //addrtohex(*p);
 
        //addrtohex((volatile uint32_t) 0x12345678 );
        //addrtohex((volatile uint32_t) SCB_VTOR );
diff --git a/regf.c b/regf.c
new file mode 100644 (file)
index 0000000..257a417
--- /dev/null
+++ b/regf.c
@@ -0,0 +1,43 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stm32.h>
+
+#define O_WRITE 0x01
+#define SET 0x02
+#define CLEAR 0x03
+
+/* write value (uint8_t) to register */
+void regw_u8(volatile uint32_t * reg, uint8_t val, short shift, short flag) {
+
+       switch(flag) {
+               case O_WRITE:
+                       (*(volatile uint32_t *) (reg)) = (val << shift);
+                       break;
+               case SET:
+                       (*(volatile uint32_t *) (reg)) = 
+                       ((*(volatile uint32_t *) (reg)) | (val << shift));
+                       break;
+               case CLEAR:
+                       (*(volatile uint32_t *) (reg)) = (val << shift);
+                       break;
+       }
+}
+
+/* write value (uint32_t) to register */
+void regw_u32(volatile uint32_t * reg, uint32_t val, short shift, short flag) {
+
+       switch(flag) {
+               case O_WRITE:
+                       (*(volatile uint32_t *) (reg)) = (val << shift);
+                       break;
+               case SET:
+                       (*(volatile uint32_t *) (reg)) = 
+                       ((*(volatile uint32_t *) (reg)) | (val << shift));
+               case CLEAR:
+                       //
+                       break;
+       }
+}
+
+
index fb19c9b..3971d3b 100644 (file)
--- a/sysinfo.c
+++ b/sysinfo.c
@@ -21,6 +21,7 @@ void sysinfo() {
 
        tmp = (tmp >> 16);
        uart_puts("# REVISION: ");
+//     addrtohex(tmp);
        switch  (tmp) {
                case 0x1000:
                      uart_puts("REVISION A\n");
index 777d04d..48065ef 100644 (file)
--- a/systick.c
+++ b/systick.c
@@ -4,13 +4,34 @@
 #include <stm32.h>
 #include <mmap.h>
 
+struct interrupt_frame {
 
-void * systick_handler() {
+        uint32_t r0; // N-32
+        uint32_t r1;
+        uint32_t r2;
+        uint32_t r3;
+        uint32_t r12;
+        uint32_t lr;
+        uint32_t pc;
+        uint32_t psr; // N-4
+};
+
+
+/* void * systick_handler() {
 
 //     *RANDOM_ADDR = (volatile uint32_t) 0x10101010 ;
 //     uart_puts("TEST");
+} */
+
+__attribute__ ((interrupt))
+void * systick_handler(struct interrupt_frame * frame) {
+
+       uart_puts("TICKING\n");
+//     addrtohex((uint32_t) 0x12345678);
+       //      for(;;);
 }
 
+
 void systick_init() {
 
        /* Enable the counter and enable the interrupt
diff --git a/uart.c b/uart.c
index a3905c4..4751645 100644 (file)
--- a/uart.c
+++ b/uart.c
@@ -4,14 +4,39 @@
 #include <stm32.h>
 #include <mmap.h>
 
+#define RXNE ((*USART1_SR >> 5) & 0x1)
+
+#define O_WRITE 0x01
+#define SET 0x02
+#define CLEAR 0x03
+
+void * uart_handler() {
+
+       uart_puts("\n echo: ");
+       while (RXNE) {
+               char echochar = *USART1_DR;
+       //      regw_u8(USART1_DR, echochar, 0, O_WRITE);
+       uart_putc(echochar);
+       }  
+//for(;;);
+
+}
 void uart_init() {
 
+       // global interrupt setup
+//     regw_u32(EXTI_IMR, 0x000FFFFF, 0, O_WRITE);
+//     regw_u32(EXTI_RTSR, 0x000FFFFF, 0, O_WRITE);
+
+               
+       regw_u32(RCC_APB2ENR, 0x4005, 0, SET);// enable clock to UART1, AFIO and GPIOA
        
-       *RCC_APB2ENR = 0x4005; // enable clock to UART1, AFIO and GPIOA
-       *GPIOA_CRH = 0x444444D4; // (after enable GPIOA), on PA9&PA10 and set mode to alternative output
-       *AFIO_EVCR = 0x89; // (after enable) set event control register, output on PA, Pin 9
+       /* (after enable GPIOA), on PA9&PA10 and set mode
+        *  to alternative output */
+       regw_u32(GPIOA_CRH, 0x444444D4, 0, O_WRITE);
+       regw_u8(AFIO_EVCR, 0x89, 0, O_WRITE);// set event control register, output on PA, Pin 9
 
-       *USART1_CR1 = (0 << 13); // disable temporarily to set values
+       //disable temporarily to set values
+       regw_u8(USART1_CR1, 0x0, 13, SET);
 
        /* baud rate 115200,  8MHz / (16 * USARTDIV)
         * USARTDIV = 4.34
@@ -19,28 +44,17 @@ void uart_init() {
         * MANTISSA: 0d4.34 0d4 -> 0x4 
         * USART_BRR = 0x45*/
 
-       /* baud rate 2400 
-        * 
-        * 16 * 0.33 -> 0x5
-        * 208 -> 0x34 */
-
-       *USART1_BRR = (volatile uint32_t) 0x00000045;
+       regw_u32(USART1_BRR, 0x00000045, 0, O_WRITE);
+       regw_u32(USART1_CR2, 0x0000, 0, O_WRITE); //set stop bit, default is 1 stop bit 0x00
        
-       *USART1_CR2 = (volatile uint32_t) 0x0000; // set stop bit, default is 1 stop bit 0x00
-       // enable DMA 
-       // *USART1_CR3 = 0x0C0; 
        /* parity = 8 bit, UART1 enabled,
         * TX and RX enabled, interrupts enabled */
-       *USART1_CR1 = (volatile uint32_t) 0x000030AC; 
-
-/* 
- * Configure UART0:
-       1. Disable the UART by clearing the UARTEN bit in the UARTCTL register.
-       2. Write the integer portion of the BRD to the UARTIBRD register.
-       3. Write the fractional portion of the BRD to the UARTFBRD register.
-       4. Write the desired serial parameters to the UARTLCRH register
-       5. Enable the UART by setting the UARTEN bit in the UARTCTL register.
-*/
+       //regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
+       regw_u32(USART1_CR1, 0x0000302C, 0, O_WRITE);
+
+       ivt_set_gate(53, uart_handler, 0);
+       
+       *NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
 }
 
 void wait() {
@@ -51,34 +65,33 @@ extern void uart_putc(unsigned char ch) {
        
        if (ch == '\n') {
                while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
-               *USART1_DR = 0x0D; // return line
+               regw_u8(USART1_DR, 0x0D, 0, O_WRITE); // return line
        }
 
-
        while (*USART1_SR & 0x0C) {} 
-               *USART1_DR = ch;
+               regw_u8(USART1_DR, ch, 0, O_WRITE);
 
-
-       
        wait();
 }
 
-extern void uart_puts(unsigned char *str)
-{
-
+extern void uart_puts(unsigned char *str) {
     int i;
-
-    for (i = 0; i < strlen(str); i++)
-    {
+    for (i = 0; i < strlen(str); i++)     {
         uart_putc(str[i]);
     }
 }
 
 
 
-char * uart_read() {
+char uart_read() { 
 
-       return NULL;
+       /* while (buffer not empty)
+        *      read()
+        *      uart_putc(ch) // echo
+        *              if ch = enter
+        *              process inquiry.
+        */
+       
 }