commit ab5f5c418fd4e8c41910ed38de0b9c57f8d9433d
parent 567d892277c90238da36880db707143253a0e0f6
Author: Dimitris Papastamos <dimitris.papastamos@arm.com>
Date: Mon, 15 Oct 2018 13:54:52 +0100
[drivers] Change uart driver implementation from assembly to C
Change-Id: I65701a91e2d669454be313916bfd3d22ecf72340
Signed-off-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Diffstat:
8 files changed, 135 insertions(+), 77 deletions(-)
diff --git a/Makefile b/Makefile
@@ -13,7 +13,7 @@ src: lib bin
bin lib:
mkdir $@
-src arch/$(ARCH): FORCE
+drivers src arch/$(ARCH): FORCE
+@cd $@ && $(MAKE)
gen: FORCE
@@ -22,5 +22,6 @@ gen: FORCE
clean:
+@cd src && $(MAKE) clean
+@cd arch && $(MAKE) clean
+ +@cd drivers && $(MAKE) clean
+@cd test && $(MAKE) clean
rm -rf lib bin
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
@@ -1,8 +1,18 @@
PROJECTDIR = ../..
include $(PROJECTDIR)/scripts/rules.mk
-ROMOBJS = rom-crt-$(SYS).o rom-$(SYS).o panic.o arch.o $(SRCDIR)/romfw/builtin.o
-RAMOBJS = ram-crt-$(SYS).o ram-$(SYS).o panic.o arch.o $(SRCDIR)/ramfw/builtin.o
+ROMOBJS = rom-crt-$(SYS).o \
+ rom-$(SYS).o panic.o \
+ arch.o \
+ $(DRVDIR)/uart.o \
+ $(SRCDIR)/romfw/builtin.o \
+
+RAMOBJS = ram-crt-$(SYS).o \
+ ram-$(SYS).o \
+ panic.o \
+ arch.o \
+ $(DRVDIR)/uart.o \
+ $(SRCDIR)/ramfw/builtin.o \
TARGET = $(BINDIR)/romfw.bin $(BINDIR)/ramfw.bin
LIBS = -lhdl -lrmu -lc
diff --git a/arch/arm64/rom-none.c b/arch/arm64/rom-none.c
@@ -1,6 +1,7 @@
#include <string.h>
#include <rcode.h>
+#include <uart.h>
/*
* We allocate space for 3 nested exceptions, covering
@@ -21,7 +22,7 @@ main(void *text, void *ram, size_t ramsiz)
fp = (struct trapframe *) (bp + bsssiz);
fp += NR_NESTED - 1;
wr_sp_r(fp);
- _uart_init();
+ uartinit(115200);
enaabt();
isb();
diff --git a/drivers/Makefile b/drivers/Makefile
@@ -0,0 +1,9 @@
+PROJECTDIR=..
+include $(PROJECTDIR)/scripts/rules.mk
+
+OBJS = uart.o
+
+all: $(OBJS)
+
+clean:
+ rm -f $(OBJS)
diff --git a/drivers/uart.c b/drivers/uart.c
@@ -0,0 +1,98 @@
+#include <uart.h>
+#include <rcode.h>
+
+#define BASE 0x1c090000
+#define CLK 24000000
+
+#define CR 0x30
+#define FBRD 0x28
+#define IBRD 0x24
+#define LCRH 0x2c
+#define FR 0x18
+#define RSR_ECR 0x4
+#define DR 0x0
+
+#define CR_RTS (1 << 11)
+#define CR_RXE (1 << 9)
+#define CR_TXE (1 << 8)
+#define CR_EN (1 << 0)
+
+#define LCRH_FEN (1 << 4)
+#define LCRH_WLEN_8 (3 << 5)
+
+#define FR_TXFE (1 << 6)
+#define FR_TXFF (1 << 5)
+#define FR_RXFE (1 << 4)
+
+static void
+setbaudrate(int baudrate)
+{
+ char *base = (char *)BASE;
+ unsigned int div;
+
+ div = (CLK * 4) / baudrate;
+ outm32(div >> 6, base + IBRD);
+ outm32(div & 0x3f, base + FBRD);
+}
+
+static void
+flush(void)
+{
+ char *base = (char *)BASE;
+
+ while ((inm32(base + CR) & CR_EN) &&
+ (inm32(base + FR) & FR_TXFE))
+ ;
+}
+
+static void
+ansism(void)
+{
+ static const char buf[5] = { 0x1b, '[', '2', '0', 'h' };
+ uartwrite(buf, sizeof(buf));
+}
+
+void
+uartinit(int baudrate)
+{
+ char *base = (char *)BASE;
+
+ outm32(0, base + RSR_ECR);
+ outm32(0, base + CR);
+ setbaudrate(baudrate);
+ outm32(LCRH_WLEN_8 | LCRH_FEN, base + LCRH);
+ outm32(CR_EN | CR_TXE | CR_RXE, base + CR);
+ ansism();
+ return;
+}
+
+int
+uartgetc(void)
+{
+ char *base = (char *)BASE;
+
+ while (inm32(base + FR) & FR_RXFE)
+ ;
+ return inm8(base + DR);
+}
+
+int
+uartputc(int c)
+{
+ char *base = (char *)BASE;
+
+ while (inm32(base + FR) & FR_TXFF)
+ ;
+ outm8(c, base + DR);
+ return c;
+}
+
+void
+uartwrite(const char *buf, size_t siz)
+{
+ size_t i;
+
+ for (i = 0; i < siz; i++)
+ uartputc(buf[i]);
+ flush();
+}
diff --git a/include/uart.h b/include/uart.h
@@ -0,0 +1,6 @@
+#include <stddef.h>
+
+extern void uartinit(int baudrate);
+extern int uartgetc(void);
+extern int uartputc(int c);
+extern void uartwrite(const char *buf, size_t siz);
diff --git a/scripts/rules.mk b/scripts/rules.mk
@@ -5,6 +5,7 @@ INCDIR = $(PROJECTDIR)/include
LIBDIR = $(PROJECTDIR)/lib
BINDIR = $(PROJECTDIR)/bin
ARCHDIR = $(PROJECTDIR)/arch/$(ARCH)
+DRVDIR = $(PROJECTDIR)/drivers
SRCDIR = $(PROJECTDIR)/src
SCRIPTDIR= $(PROJECTDIR)/scripts
INCLUDES = -I$(INCDIR) -I$(INCDIR)/bits/$(ARCH)/ -I$(INCDIR)/bits/$(SYS)
diff --git a/src/libc/arch/arm64/_write-none.s b/src/libc/arch/arm64/_write-none.s
@@ -1,81 +1,13 @@
.file "_write-none.s"
-BASE = 0x1c090000
-CLK = 24000000
-BAUD = 115200
-
-CR = 0x30
-LCR_H = 0x2c
-FBRD = 0x28
-IBRD = 0x24
-FR = 0x18
-ECR = 0x04
-DR = 0x0
-
-CR_RXE = (1<<9)
-CR_TXE = (1<<8)
-CR_EN = (1<<0)
-
-LCR_H_FEN = (1<<4)
-LCR_H_WLEN_8 = (3<<5)
-
-FR_TXFF_BIT = 5
-FR_BUSY_BIT = 3
-
.text
- .globl _uart_init,_write
-
-_uart_init:
- ldr x0,=BASE
- ldr x1,=CLK
- ldr x2,=BAUD
-
- ldr w3,[x0,CR]
- mov w4,CR_EN
- bic w3, w3, w4
- str w3,[x0,CR]
- lsl w1,w1,2
- udiv w2,w1,w2
- lsr w1,w2,6
- str w1,[x0,IBRD]
- and w1,w2,0x3f
- str w1,[x0,FBRD]
- mov w1,LCR_H_FEN|LCR_H_WLEN_8
- str w1,[x0,LCR_H]
- str wzr,[x0,ECR]
- mov w1,CR_RXE|CR_TXE|CR_EN
- str w1,[x0,CR]
-
- adr x1,ansism
- mov x2,5
- b _write
-
+ .globl _write
/*
* x0 = fd (unused)
* x1 = buf
* x2 = cnt
*/
-_write: ldr x3,=BASE
-
-noready:
- ldr w4,[x3,FR]
- tbnz w4,FR_TXFF_BIT,noready
-
- ldrb w4,[x1],#1
- str w4,[x3,DR]
- subs x2,x2,#1
- cbnz x2,noready
-
- mov w5,'\n'
- cmp w4,w0
- b.eq busy
- ret
-
-busy:
- ldr w2,[x3,FR]
- tbnz w2,FR_BUSY_BIT,busy
- ret
-
- .section .rodata
-ansism: .byte 0x1b
- .ascii "[20h"
+_write:
+ mov x0,x1
+ mov x1,x2
+ b uartwrite