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.
This commit is contained in:
Luigi Ghionda 2025-01-26 12:47:37 +01:00
parent da4e51e71d
commit dfd91b93a1
9 changed files with 113 additions and 3 deletions

View file

@ -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}")"

47
drivers/host_uart.c Normal file
View file

@ -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 <nwistoff@iis.ee.ethz.ch>
// Paul Scheffler <paulsc@iis.ee.ethz.ch>
#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);
}

View file

@ -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 <nwistoff@iis.ee.ethz.ch>
// Paul Scheffler <paulsc@iis.ee.ethz.ch>
#pragma once
#include <stdint.h>
// 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);

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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)

View file

@ -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