Skip to content

Commit b064243

Browse files
committed
Update UART code to work with Raspi4
1 parent 2ee2f1c commit b064243

File tree

5 files changed

+71
-53
lines changed

5 files changed

+71
-53
lines changed

src/common/stdio.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#include "stdlib.h"
44

55
char getc() {
6-
return uart_getc();
6+
return uart_recv();
77
}
88

99
void putc(char c) {
10-
uart_putc(c);
10+
uart_send(c);
1111
}
1212

1313
void puts(const char * str) {

src/common/utils.S

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22
get_core_id:
33
mrs x0, mpidr_el1
44
and x0, x0, #0xFF
5+
6+
.globl put32
7+
put32:
8+
str w1,[x0]
9+
ret
10+
11+
.globl get32
12+
get32:
13+
ldr w0,[x0]
514
ret
615

716
.globl delay

src/common/utils.h

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef __ASSEMBLER__
66

77
extern unsigned int get_core_id ( void );
8+
extern void put32 ( unsigned long, unsigned int);
9+
extern unsigned int get32 ( unsigned long );
810
extern void delay ( unsigned long );
911

1012
#endif

src/peripherals/uart.c

+42-32
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,55 @@
11
#include "uart.h"
22
#include "../common/utils.h"
33

4-
void uart_init()
4+
void uart_init (void)
55
{
6-
mmio_write(UART0_CR, 0x00000000);
7-
8-
mmio_write(GPPUD, 0x00000000);
9-
delay(150);
10-
11-
mmio_write(GPPUDCLK0, (1 << 14) | (1 << 15));
12-
delay(150);
13-
14-
mmio_write(GPPUDCLK0, 0x00000000);
15-
16-
mmio_write(UART0_ICR, 0x7FF);
17-
18-
mmio_write(UART0_IBRD, 1);
19-
mmio_write(UART0_FBRD, 40);
20-
21-
mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
22-
23-
mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) |
24-
(1 << 7) | (1 << 8) | (1 << 9) | (1 << 10));
25-
26-
mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
6+
unsigned int selector;
7+
selector = get32(GPFSEL1);
8+
selector &= ~(7<<12); // clean gpio14
9+
selector |= 4<<12; // set alt0 for gpio14
10+
selector &= ~(7<<15); // clean gpio15
11+
selector |= 4<<15; // set alt0 for gpio 15
12+
put32(GPFSEL1, selector);
13+
14+
put32(GPPUD, 0);
15+
delay(150);
16+
put32(GPPUDCLK0, (1<<14) | (1<<15));
17+
delay(150);
18+
put32(GPPUDCLK0, 0);
19+
20+
put32(UART0_CR, 0); // disable UART until configuration is done
21+
/* baud divisor = UARTCLK / (16 * baud_rate) = 48 * 10^6 / (16 * 115200) = 26.0416666667
22+
* integer part = 26
23+
* fractional part = (int) ((0.0416666667 * 64) + 0.5) = 3
24+
* generated baud rate divisor = 26 + (3 / 64) = 26.046875
25+
* generated baud rate = (48 * 10^6) / (16 * 26.046875) = 115177
26+
* error = |(115177 - 115200) / 115200 * 100| = 0.02%
27+
*/
28+
put32(UART0_IBRD, 26); // baud rate divisor, integer part
29+
put32(UART0_FBRD, 3); // baud rate divisor, fractional part
30+
put32(UART0_LCRH, (1<<4) | (3<<5)); // enable FIFOs and 8 bits frames
31+
put32(UART0_IMSC, 0); // mask interupts
32+
put32(UART0_CR, 1 | (1<<8) | (1<<9)); // enable UART, receive and transmit
2733
}
2834

29-
void uart_putc(unsigned char c)
35+
void uart_send (char c)
3036
{
31-
while ( mmio_read(UART0_FR) & (1 << 5) ) { }
32-
mmio_write(UART0_DR, c);
37+
// wait for transmit FIFO to have an available slot
38+
while(get32(UART0_FR) & (1<<5)) { }
39+
put32(UART0_DR, c);
3340
}
3441

35-
unsigned char uart_getc()
42+
char uart_recv ()
3643
{
37-
while ( mmio_read(UART0_FR) & (1 << 4) ) { }
38-
return mmio_read(UART0_DR);
44+
// wait for receive FIFO to have data to read
45+
while(get32(UART0_FR) & (1<<4)) { }
46+
return(get32(UART0_DR) & 0xFF);
3947
}
4048

41-
void uart_puts(const char* str)
49+
void uart_send_string(char* str)
4250
{
43-
for (size_t i = 0; str[i] != '\0'; i ++)
44-
uart_putc((unsigned char)str[i]);
45-
}
51+
for (int i = 0; str[i] != '\0'; i ++) {
52+
uart_send((char) str[i]);
53+
}
54+
}
55+

src/peripherals/uart.h

+16-19
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@
44
#include <stdint.h>
55

66
enum {
7-
// The GPIO registers base address.
8-
GPIO_BASE = 0x3F200000, // for raspi2 & 3, 0x20200000 for raspi1
9-
10-
GPPUD = (GPIO_BASE + 0x94),
11-
GPPUDCLK0 = (GPIO_BASE + 0x98),
12-
13-
// The base address for UART.
14-
UART0_BASE = 0x3F201000, // for raspi2 & 3, 0x20201000 for raspi1
15-
16-
UART0_DR = (UART0_BASE + 0x00),
7+
// The GPIO registers base address.
8+
//GPIO_BASE = 0x20200000 // raspi1
9+
//GPIO_BASE = 0x3f200000 // raspi2 & 3
10+
GPIO_BASE = 0xFE200000, // raspi4
11+
12+
// GPIO
13+
GPFSEL1 = (GPIO_BASE + 0x04),
14+
GPSET0 = (GPIO_BASE + 0x1C),
15+
GPCLR0 = (GPIO_BASE + 0x28),
16+
GPPUD = (GPIO_BASE + 0x94),
17+
GPPUDCLK0 = (GPIO_BASE + 0x98),
18+
19+
// The base address for UART.
20+
UART0_BASE = (GPIO_BASE + 0x1000),
21+
UART0_DR = (UART0_BASE + 0x00),
1722
UART0_RSRECR = (UART0_BASE + 0x04),
1823
UART0_FR = (UART0_BASE + 0x18),
1924
UART0_ILPR = (UART0_BASE + 0x20),
@@ -33,19 +38,11 @@ enum {
3338
UART0_TDR = (UART0_BASE + 0x8C),
3439
};
3540

36-
static inline void mmio_write(uint64_t reg, uint64_t data) {
37-
*(volatile uint64_t*)reg = data;
38-
}
39-
40-
static inline uint64_t mmio_read(uint64_t reg) {
41-
return *(volatile uint64_t*)reg;
42-
}
43-
4441
void uart_init();
4542

4643
void uart_putc(unsigned char c);
4744
unsigned char uart_getc();
4845

4946
void uart_puts(const char* str);
5047

51-
#endif /*_UAART_H */
48+
#endif /*_UART_H */

0 commit comments

Comments
 (0)