9dbc01cc6de9d2fd9e6d3563e41020df7d6a2938
[cortex-from-scratch] / uart.c
1 #include <stdbool.h>
2 #include <stddef.h>
3 #include <stdint.h>
4 #include <stm32.h>
5 #include <mmap.h>
6 #include <drivers.h>
7
8 #define RXNE ((*USART1_SR >> 5) & 0x1)
9 #define UARTBUF 256
10 #define ECHO 1
11
12 static struct {
13          uint8_t buf[UARTBUF] ;
14          uint32_t rpos;
15          uint32_t wpos;
16 } linefeed;
17
18
19 void * uart_handler() {
20
21         //uart_puts("echo: ");
22         while (RXNE) {
23                 char echochar = *USART1_DR;
24                 //uart_putc(echochar);
25                 linefeed.buf[linefeed.wpos++] = echochar;
26                  if (linefeed.wpos == UARTBUF)
27                          linefeed.wpos = 0;
28                 //regw_u32(USART1_DR, echochar, 0, O_WRITE);
29         }
30         //uart_putc('\n');
31                 
32 }
33
34 void uart_init() {
35
36         regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
37         
38         /* (after enable GPIOA), on PA9&PA10 and set mode
39          *  to alternative output */
40         regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
41         regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9
42
43         //disable temporarily to set values
44         regw_u8(USART1_CR1, 0x0, 13, SETBIT);
45
46         /* baud rate 115200,  8MHz / (16 * USARTDIV)
47          * USARTDIV = 4.34
48          * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
49          * MANTISSA: 0d4.34 0d4 -> 0x4 
50          * USART_BRR = 0x45*/
51
52         regw_u32(USART1_BRR, 0x00000045, 0, OWRITE);
53         regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
54         
55         /* parity = 8 bit, UART1 enabled,
56          * TX and RX enabled, interrupts enabled */
57         //regw_u32(USART1_CR1, 0x000030AC, 0, O_WRITE);
58         regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
59
60         ivt_set_gate(53, uart_handler, 0);
61         
62         *NVIC_ISER1 = (1 << 5); // Enable UART interrupt at NVIC
63 }
64
65 static void wait() {
66         for (int i = 0; i < 100; i++);
67 }
68
69 extern void uart_putc(unsigned char ch) {
70         
71         if (ch == '\n') {
72                 while (*USART1_SR & 0x0C) { } // transmit data register empty and complete
73                 regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
74         }
75
76         while (*USART1_SR & 0x0C) {} 
77                 regw_u8(USART1_DR, ch, 0, OWRITE);
78
79         wait();
80 }
81
82 char uart_getc(void) {
83          char c;
84
85          if (linefeed.rpos != linefeed.wpos) {
86                  c = linefeed.buf[linefeed.rpos++];
87                  if (linefeed.rpos == UARTBUF)
88                          linefeed.rpos = 0;
89                  return c;
90          }
91          return 0;
92  }
93
94
95 // move to library 
96 extern void uart_puts(unsigned char *str) {
97     int i;
98     for (i = 0; i < strlen(str); i++)     {
99         uart_putc(str[i]);
100     }
101 }
102