From 6d0a60881c08b7bf76f7c0cb11af4ef0ebe6b7f8 Mon Sep 17 00:00:00 2001 From: Matte23 Date: Sun, 3 Nov 2024 12:04:40 +0100 Subject: [PATCH] Add example USART driver --- Makefile | 4 ++-- libc/library.c | 8 ++----- os/delay.c | 18 +++++++++++++++ os/delay.h | 2 ++ os/driver/usart.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ os/driver/usart.h | 12 ++++++++++ 6 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 os/delay.c create mode 100644 os/delay.h create mode 100644 os/driver/usart.c create mode 100644 os/driver/usart.h diff --git a/Makefile b/Makefile index c5e0352..4a9ef52 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CPU = -mcpu=cortex-m4 THUMB = -mthumb LDFLAGS = -T linker.ld -CFLAGS = $(CPU) $(THUMB) -I libc/ +CFLAGS = $(CPU) $(THUMB) -I libc/ -I ./ QEMU = qemu-system-arm BOARD = netduino2 @@ -13,7 +13,7 @@ BOARD = netduino2 # Output file TARGET = main.elf # Source files -SRCS = os/main.c os/process.c os/scheduler.c os/alloc.c libc/library.c tasks/tasks.c +SRCS = os/main.c os/process.c os/scheduler.c os/alloc.c os/delay.c os/driver/usart.c libc/library.c tasks/tasks.c # Object files OBJS = $(SRCS:.c=.o) diff --git a/libc/library.c b/libc/library.c index c37f1ee..650534a 100644 --- a/libc/library.c +++ b/libc/library.c @@ -1,10 +1,6 @@ #include "library.h" - -volatile unsigned int *const USART1_PTR = (unsigned int *)0x40011004; +#include "os/driver/usart.h" void puts(const char *s) { - while(*s != '\0') { /* Loop until end of string */ - *USART1_PTR= (unsigned int)(*s); /* Transmit char */ - s++; /* Next char */ - } + usart_tx_write_string(s); } diff --git a/os/delay.c b/os/delay.c new file mode 100644 index 0000000..b0a86a3 --- /dev/null +++ b/os/delay.c @@ -0,0 +1,18 @@ +#define CLOCK_FREQUENCY 120000 + +unsigned int ms_to_ticks(unsigned int ms) { + return ms * (CLOCK_FREQUENCY/3); +} + +void delay_routine(unsigned int delay_counter) { + asm("mov r1, %[input]\n" + "loop_2:\n" + "subs r1, #1\n" + "cmp r1, #0\n" + "bne loop_2\n" + : [input] "=r" (delay_counter)); +} + +void delay_ms(unsigned int seconds) { + delay_routine(ms_to_ticks(seconds)); +} diff --git a/os/delay.h b/os/delay.h new file mode 100644 index 0000000..f7d0b87 --- /dev/null +++ b/os/delay.h @@ -0,0 +1,2 @@ +void delay_routine(unsigned int delay_counter); +void delay_ms(unsigned int ms); diff --git a/os/driver/usart.c b/os/driver/usart.c new file mode 100644 index 0000000..4b6e662 --- /dev/null +++ b/os/driver/usart.c @@ -0,0 +1,57 @@ +#include "usart.h" +#include "os/delay.h" +#include +#include +#define USART_SR_TXE (1 << 7) + +typedef struct uart_s { + uint32_t USART_SR; + uint32_t USART_DR; + uint32_t USART_BRR; + uint32_t USART_CR1; + uint32_t USART_CR2; + uint32_t USART_CR3; + uint32_t USART_GTPR; +} uart_c; + +volatile uart_c *const USART1 = (uart_c *)0x40011000; + +static uint32_t usart_tx_ready(void) { + return (USART1->USART_SR & USART_SR_TXE) >> 7; +} + +uint32_t usart_tx_write(const uint8_t *data_bytes, uint32_t n_bytes) { + if (data_bytes == NULL) return USART_TX_ERROR; + + for (int i = 0; i < n_bytes; i++) { + unsigned int timeout = TIMEOUT; + while (!usart_tx_ready()) { + delay_ms(1); + timeout--; + if (timeout == 0) return USART_TX_BUSY; + } + + USART1->USART_DR = *data_bytes; + + data_bytes++; + } + return USART_TX_COMPLETE; +} + +uint32_t usart_tx_write_string(const uint8_t *data_bytes) { + if (data_bytes == NULL) return USART_TX_ERROR; + + while (*data_bytes != '\0') { + unsigned int timeout = TIMEOUT; + while (!usart_tx_ready()) { + delay_ms(1); + timeout--; + if (timeout == 0) return USART_TX_BUSY; + } + + USART1->USART_DR = *data_bytes; + + data_bytes++; + } + return USART_TX_COMPLETE; +} diff --git a/os/driver/usart.h b/os/driver/usart.h new file mode 100644 index 0000000..99cfbd5 --- /dev/null +++ b/os/driver/usart.h @@ -0,0 +1,12 @@ +#include +#define TIMEOUT 1000 + +enum UartErrorCode { + USART_TX_ERROR, + USART_TX_BUSY, + USART_TX_COMPLETE +}; + +static uint32_t usart_tx_ready(void); +uint32_t usart_tx_write(const uint8_t *data_bytes, uint32_t n_bytes); +uint32_t usart_tx_write_string(const uint8_t *data_bytes); \ No newline at end of file