aboutsummaryrefslogtreecommitdiff
path: root/uart.c
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2020-01-03 04:53:01 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2020-01-03 04:53:01 +0100
commitffb2c4adfb8e65e355b39abd39d994eebc649c98 (patch)
tree760ef43f89b480ecd0be4bfd9312eb0d8c744d05 /uart.c
parent6bf5a3b8c6e8a5d1cb3fb4880a5d9688ab094c62 (diff)
downloadrpi-MMU-example-ffb2c4adfb8e65e355b39abd39d994eebc649c98.tar.gz
rpi-MMU-example-ffb2c4adfb8e65e355b39abd39d994eebc649c98.zip
add (not yet fully working - it can only send through uart now) interrupt-driven uart together with "scheduler"
Diffstat (limited to 'uart.c')
-rw-r--r--uart.c66
1 files changed, 49 insertions, 17 deletions
diff --git a/uart.c b/uart.c
index 2030538..c9fcd35 100644
--- a/uart.c
+++ b/uart.c
@@ -24,8 +24,8 @@ static inline void delay(int32_t count)
void uart_init()
{
- // Disable UART0.
- mmio_write(UART0_CR, 0x00000000);
+ // Disable PL011_UART.
+ mmio_write(PL011_UART_CR, 0x00000000);
// Setup the GPIO pin 14 && 15.
// Disable pull up/down for all GPIO pins & delay for 150 cycles.
@@ -40,7 +40,7 @@ void uart_init()
mmio_write(GPPUDCLK0, 0x00000000);
// Clear pending interrupts.
- mmio_write(UART0_ICR, 0x7FF);
+ mmio_write(PL011_UART_ICR, 0x7FF);
// Set integer & fractional part of baud rate.
// Divider = UART_CLOCK/(16 * Baud)
@@ -48,31 +48,63 @@ void uart_init()
// UART_CLOCK = 3000000; Baud = 115200.
// Divider = 3000000 / (16 * 115200) = 1.627 = ~1.
- mmio_write(UART0_IBRD, 1);
+ mmio_write(PL011_UART_IBRD, 1);
// Fractional part register = (.627 * 64) + 0.5 = 40.6 = ~40.
- mmio_write(UART0_FBRD, 40);
+ mmio_write(PL011_UART_FBRD, 40);
// Enable FIFO & 8 bit data transmission (1 stop bit, no parity).
- mmio_write(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
+ mmio_write(PL011_UART_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
- // Mask all interrupts.
- mmio_write(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) |
- (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10));
+ // set interrupt to come when transmit FIFO becomes ≤ 1/8 full
+ // or receive FIFO becomes ≥ 1/8 full
+ mmio_write(PL011_UART_IFLS, 0);
- // Enable UART0, receive & transfer part of UART.
- mmio_write(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
+ // Enable PL011_UART, receive & transfer part of UART.2
+ mmio_write(PL011_UART_CR, (1 << 0) | (1 << 8) | (1 << 9));
+
+ // At first, it's probably safer to disable interrupts :)
+ uart_irq_disable();
+}
+
+inline static _Bool can_transmit(void)
+{
+ return !(mmio_read(PL011_UART_FR) & (1 << 5));
+}
+
+inline static _Bool can_receive(void)
+{
+ return !(mmio_read(PL011_UART_FR) & (1 << 4));
}
void putchar(char c)
{
- // Wait for UART to become ready to transmit.
- while ( mmio_read(UART0_FR) & (1 << 5) ) { }
- mmio_write(UART0_DR, c);
+ while (!can_transmit());
+
+ mmio_write(PL011_UART_DR, c);
}
char getchar(void)
{
- // Wait for UART to have received something.
- while ( mmio_read(UART0_FR) & (1 << 4) ) { }
- return mmio_read(UART0_DR);
+ while (!can_receive());
+
+ return mmio_read(PL011_UART_DR);
+}
+
+_Bool putchar_non_blocking(char c)
+{
+ if (can_transmit())
+ {
+ mmio_write(PL011_UART_DR, c);
+ return 0;
+ }
+
+ return 1;
+}
+
+int getchar_non_blocking(void)
+{
+ if (can_receive())
+ return mmio_read(PL011_UART_DR);
+
+ return -1;
}