From dfd91b93a1653328ed701e649a441a002e1f14f6 Mon Sep 17 00:00:00 2001 From: Luigi Ghionda Date: Sun, 26 Jan 2025 12:47:37 +0100 Subject: [PATCH] Add UART drivers in case this is a host peripheral to differentiate them from those that make use of udma This mod is tailored for Astral and its host, Cheshire, whose basic funcitons are reused. This enables printing from the cluster. --- configs/astral-cluster.sh | 1 + drivers/host_uart.c | 47 +++++++++++++++++++ drivers/include/host_uart.h | 40 ++++++++++++++++ drivers/{uart.c => udma_uart.c} | 0 .../archi/chips/astral-cluster/memory_map.h | 1 + include/pulp.h | 4 +- lib/libc/minimal/io.c | 9 ++++ rules/pulpos/default_rules.mk | 4 ++ rules/pulpos/src.mk | 10 +++- 9 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 drivers/host_uart.c create mode 100644 drivers/include/host_uart.h rename drivers/{uart.c => udma_uart.c} (100%) diff --git a/configs/astral-cluster.sh b/configs/astral-cluster.sh index fda44fd..fc79117 100644 --- a/configs/astral-cluster.sh +++ b/configs/astral-cluster.sh @@ -4,6 +4,7 @@ export PULPRT_TARGET=astral-cluster export PULPRUN_TARGET=astral-cluster export CONFIG_NO_FC=1 export ARCHI_HMR=1 +export ARCHI_HOST_UART=1 if [ -n "${ZSH_VERSION:-}" ]; then DIR="$(readlink -f -- "${(%):-%x}")" diff --git a/drivers/host_uart.c b/drivers/host_uart.c new file mode 100644 index 0000000..eaace7d --- /dev/null +++ b/drivers/host_uart.c @@ -0,0 +1,47 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Nils Wistoff +// Paul Scheffler + +#include "host_uart.h" + +static inline volatile uint8_t *reg8(void *base, int offs) { + return (volatile uint8_t *)(base + offs); +} + +static inline void fence() { + asm volatile("fence" ::: "memory"); +} + +int uart_read_ready(void *uart_base) { + return *reg8(uart_base, UART_LINE_STATUS_REG_OFFSET) & (1 << UART_LINE_STATUS_DATA_READY_BIT); +} + +static inline int __uart_write_ready(void *uart_base) { + return *reg8(uart_base, UART_LINE_STATUS_REG_OFFSET) & (1 << UART_LINE_STATUS_THR_EMPTY_BIT); +} + +static inline int __uart_write_idle(void *uart_base) { + return __uart_write_ready(uart_base) && + *reg8(uart_base, UART_LINE_STATUS_REG_OFFSET) & (1 << UART_LINE_STATUS_TMIT_EMPTY_BIT); +} + +void uart_write(void *uart_base, uint8_t byte) { + while (!__uart_write_ready(uart_base)) + ; + *reg8(uart_base, UART_THR_REG_OFFSET) = byte; +} + +void uart_write_flush(void *uart_base) { + fence(); + while (!__uart_write_idle(uart_base)) + ; +} + +uint8_t uart_read(void *uart_base) { + while (!uart_read_ready(uart_base)) + ; + return *reg8(uart_base, UART_RBR_REG_OFFSET); +} diff --git a/drivers/include/host_uart.h b/drivers/include/host_uart.h new file mode 100644 index 0000000..915fc2c --- /dev/null +++ b/drivers/include/host_uart.h @@ -0,0 +1,40 @@ +// Copyright 2022 ETH Zurich and University of Bologna. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Nils Wistoff +// Paul Scheffler + +#pragma once + +#include + +// Register offsets +#define UART_RBR_REG_OFFSET 0 +#define UART_THR_REG_OFFSET 0 +#define UART_INTR_ENABLE_REG_OFFSET 4 +#define UART_INTR_IDENT_REG_OFFSET 8 +#define UART_FIFO_CONTROL_REG_OFFSET 8 +#define UART_LINE_CONTROL_REG_OFFSET 12 +#define UART_MODEM_CONTROL_REG_OFFSET 16 +#define UART_LINE_STATUS_REG_OFFSET 20 +#define UART_MODEM_STATUS_REG_OFFSET 24 +#define UART_DLAB_LSB_REG_OFFSET 0 +#define UART_DLAB_MSB_REG_OFFSET 4 + +// Register fields +#define UART_LINE_STATUS_DATA_READY_BIT 0 +#define UART_LINE_STATUS_THR_EMPTY_BIT 5 +#define UART_LINE_STATUS_TMIT_EMPTY_BIT 6 + +int uart_read_ready(void *uart_base); + +void uart_write(void *uart_base, uint8_t byte); + +void uart_write_str(void *uart_base, void *src, uint64_t len); + +void uart_write_flush(void *uart_base); + +uint8_t uart_read(void *uart_base); + +void uart_read_str(void *uart_base, void *dst, uint64_t len); diff --git a/drivers/uart.c b/drivers/udma_uart.c similarity index 100% rename from drivers/uart.c rename to drivers/udma_uart.c diff --git a/include/archi/chips/astral-cluster/memory_map.h b/include/archi/chips/astral-cluster/memory_map.h index 10db2bb..d4d1bd0 100644 --- a/include/archi/chips/astral-cluster/memory_map.h +++ b/include/archi/chips/astral-cluster/memory_map.h @@ -60,6 +60,7 @@ #define ARCHI_FC_ITC_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_ITC_OFFSET ) #define ARCHI_FC_TIMER_ADDR ( ARCHI_SOC_PERIPHERALS_ADDR + ARCHI_FC_TIMER_OFFSET ) #define ARCHI_STDOUT_ADDR 0x03002000 +#define ARCHI_HOST_UART_ADDR 0x03002000 #define ARCHI_FLL_AREA_SIZE 0x00000010 diff --git a/include/pulp.h b/include/pulp.h index f7870e0..635f412 100755 --- a/include/pulp.h +++ b/include/pulp.h @@ -93,12 +93,12 @@ void _start(); #ifdef ARCHI_CLUSTER_NB_PE static inline int get_core_num() { return ARCHI_CLUSTER_NB_PE; } #endif - - +#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 int uart_open(int uart_id, int baudrate); void uart_close(int uart_id); int uart_write(int uart_id, void *buffer, uint32_t size); int uart_read(int uart_id, void *buffer, uint32_t size); +#endif void synch_barrier(); diff --git a/lib/libc/minimal/io.c b/lib/libc/minimal/io.c index 3a0857a..3510ec4 100644 --- a/lib/libc/minimal/io.c +++ b/lib/libc/minimal/io.c @@ -239,12 +239,21 @@ static void pos_libc_putc_uart(char c) } #endif +#if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 2 +static void pos_libc_putc_host_uart(char c) +{ + uart_write(ARCHI_HOST_UART_ADDR, c); + uart_write_flush(ARCHI_HOST_UART_ADDR); +} +#endif static void pos_putc(char c) { #if defined(CONFIG_IO_UART) && CONFIG_IO_UART == 1 pos_libc_putc_uart(c); +#elif defined(CONFIG_IO_UART) && CONFIG_IO_UART == 2 + pos_libc_putc_host_uart(c); #else pos_libc_putc_stdout(c); #endif diff --git a/rules/pulpos/default_rules.mk b/rules/pulpos/default_rules.mk index 9ea3c2b..0621820 100644 --- a/rules/pulpos/default_rules.mk +++ b/rules/pulpos/default_rules.mk @@ -36,6 +36,10 @@ ifdef io ifeq '$(io)' 'uart' CONFIG_IO_UART=1 endif +ifeq '$(io)' 'host_uart' +CONFIG_IO_UART=2 +PULP_APP_CFLAGS += -I$(PULPRT_HOME)/drivers/include +endif endif VPATH = $(PULPRT_HOME) diff --git a/rules/pulpos/src.mk b/rules/pulpos/src.mk index 22152d0..50ae84c 100644 --- a/rules/pulpos/src.mk +++ b/rules/pulpos/src.mk @@ -6,7 +6,15 @@ ifeq '$(CONFIG_LIBC_MINIMAL)' '1' PULP_SRCS += lib/libc/minimal/io.c lib/libc/minimal/fprintf.c lib/libc/minimal/prf.c lib/libc/minimal/sprintf.c endif -PULP_SRCS += kernel/init.c kernel/kernel.c kernel/alloc.c kernel/alloc_pool.c kernel/irq.c kernel/soc_event.c kernel/bench.c drivers/uart.c +ifeq '$(CONFIG_IO_UART)' '1' +PULP_SRCS += drivers/udma_uart.c +endif + +ifeq '$(CONFIG_IO_UART)' '2' +PULP_SRCS += drivers/host_uart.c +endif + +PULP_SRCS += kernel/init.c kernel/kernel.c kernel/alloc.c kernel/alloc_pool.c kernel/irq.c kernel/soc_event.c kernel/bench.c PULP_ASM_SRCS += kernel/irq_asm.S