05f040663132100228fcbe383d137915c9eef7b8
[cortex-from-scratch] / drivers / uart.c
1 #include <stdbool.h>
2 #include <stddef.h>
3 #include <stdint.h>
4
5 #include <sys/mmap.h>
6 #include <sys/robsys.h>
7
8 #include <lib/regfunc.h>
9 #include <lib/string.h>
10
11 #include <drivers/uart.h>
12
13 #define UARTBUF 256
14 #define ECHO 1
15
16 static struct {
17          uint8_t buf[UARTBUF];
18          uint32_t rpos;
19          uint32_t wpos;
20 } linefeed;
21
22 void set_baudrate();
23
24 void * uart_handler() {
25
26         while (rchkbit(USART1_SR, 5)) {
27                 char echochar = *USART1_DR;
28                 linefeed.buf[linefeed.wpos++] = echochar;
29                  if (linefeed.wpos == UARTBUF)
30                          linefeed.wpos = 0;
31         }
32                 
33 }
34
35 void uart_init() {
36
37         linefeed.rpos = 0; 
38         linefeed.wpos = 0;
39
40         //memset(&linefeed, 0, (sizeof(struct linefeed) ));
41         //regw_u32(RCC_APB2ENR, 0x4005, 0, SETBIT);// enable clock to UART1, AFIO and GPIOA
42         rsetbitsfrom(RCC_APB2ENR, 0, 0x4005);
43         
44         /* (after enable GPIOA), on PA9&PA10 and set mode
45          *  to alternative output */
46         //regw_u32(GPIOA_CRH, 0x444444D4, 0, OWRITE);
47         rwrite(GPIOA_CRH, 0x444444D4);
48         //regw_u8(AFIO_EVCR, 0x89, 0, OWRITE);// set event control register, output on PA, Pin 9 TODO: check
49         rsetbitsfrom(AFIO_EVCR, 0, 0x89);
50
51         //disable temporarily to set values
52         //regw_u8(USART1_CR1, 0x0, 13, SETBIT);
53         rclrbit(USART1_CR1, 13);
54
55         set_baudrate();
56
57         //regw_u32(USART1_CR2, 0x0000, 0, OWRITE); //set stop bit, default is 1 stop bit 0x00
58         rwrite(USART1_CR2, 0x0000);
59         
60         /* parity = 8 bit, UART1 enabled,
61          * TX and RX enabled, interrupts enabled */
62         //regw_u32(USART1_CR1, 0x0000302C, 0, OWRITE);
63         rwrite(USART1_CR1, 0x0000302C);
64
65         ivt_set_gate(53, uart_handler, 0);
66         
67         rsetbit(NVIC_ISER1, 5);
68 }
69
70 void uart_putc(unsigned char ch) {
71         
72         if (ch == '\n') {
73                 while(!rchkbit(USART1_SR, 6));
74                 regw_u8(USART1_DR, 0x0D, 0, OWRITE); // return line
75         }
76                 while(!rchkbit(USART1_SR, 6));
77                 regw_u8(USART1_DR, ch, 0, OWRITE);
78 }
79
80 char uart_getc(void) {
81          char c;
82
83          if (linefeed.rpos != linefeed.wpos) {
84                  c = linefeed.buf[linefeed.rpos++];
85                  if (linefeed.rpos == UARTBUF)
86                          linefeed.rpos = 0;
87                  return c;
88          }
89          return 0;
90  }
91
92 /* Calculate baud rate. Example how this is done
93  * to set this register on a stm32
94  * Desired baudrate: 115200,  CLK: 8 MHz
95  * Desired Baudrate = CLK / (16 * USARTDIV)
96  * USARTDIV = 4.34
97  * FRACTION: 16 x 0.34 = 0d5.44 0d5 -> 0x5
98  * MANTISSA: 0d4.34 0d4 -> 0x4 
99  * USART_BRR = 0x45*/
100         
101 void set_baudrate() {
102
103 //      rwrite(USART1_BRR, 0x000001A1); 48 MHZ
104 //      rwrite(USART1_BRR, 0x0000022B); 64 MHz
105 //      rwrite(USART1_BRR, 0x00000138); 36 MHz
106 //      rwrite(USART1_BRR, 0x00000271); 72 MHz
107 #ifdef ENABLE_HSE
108         rwrite(USART1_BRR, 0x00000138);
109 #else
110         rwrite(USART1_BRR, 0x00000045);
111 #endif
112 }