diff --git a/Makefile.am b/Makefile.am index a5966569..8b475e70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,6 +75,7 @@ nobase_include_HEADERS = \ metal/drivers/sifive_rtc0.h \ metal/drivers/sifive_spi0.h \ metal/drivers/sifive_test0.h \ + metal/drivers/sifive_trace.h \ metal/drivers/sifive_uart0.h \ metal/drivers/sifive_wdog0.h \ metal/machine/inline.h \ @@ -179,6 +180,7 @@ libriscv__mmachine__@MACHINE_NAME@_a_SOURCES = \ src/drivers/sifive_rtc0.c \ src/drivers/sifive_spi0.c \ src/drivers/sifive_test0.c \ + src/drivers/sifive_trace.c \ src/drivers/sifive_uart0.c \ src/drivers/sifive_wdog0.c \ src/button.c \ diff --git a/Makefile.in b/Makefile.in index 710b41d4..270f24a8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -221,6 +221,7 @@ am_libriscv__mmachine__@MACHINE_NAME@_a_OBJECTS = src/drivers/libriscv__mmachine src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_rtc0.$(OBJEXT) \ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_spi0.$(OBJEXT) \ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_test0.$(OBJEXT) \ + src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.$(OBJEXT) \ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.$(OBJEXT) \ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_wdog0.$(OBJEXT) \ src/libriscv__mmachine__@MACHINE_NAME@_a-button.$(OBJEXT) \ @@ -498,6 +499,7 @@ nobase_include_HEADERS = \ metal/drivers/sifive_rtc0.h \ metal/drivers/sifive_spi0.h \ metal/drivers/sifive_test0.h \ + metal/drivers/sifive_trace.h \ metal/drivers/sifive_uart0.h \ metal/drivers/sifive_wdog0.h \ metal/machine/inline.h \ @@ -569,6 +571,7 @@ libriscv__mmachine__@MACHINE_NAME@_a_SOURCES = \ src/drivers/sifive_rtc0.c \ src/drivers/sifive_spi0.c \ src/drivers/sifive_test0.c \ + src/drivers/sifive_trace.c \ src/drivers/sifive_uart0.c \ src/drivers/sifive_wdog0.c \ src/button.c \ @@ -859,6 +862,9 @@ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_spi0.$(OBJEXT): \ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_test0.$(OBJEXT): \ src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) +src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.$(OBJEXT): \ + src/drivers/$(am__dirstamp) \ + src/drivers/$(DEPDIR)/$(am__dirstamp) src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.$(OBJEXT): \ src/drivers/$(am__dirstamp) \ src/drivers/$(DEPDIR)/$(am__dirstamp) @@ -1041,6 +1047,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_rtc0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_spi0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_test0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_wdog0.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/hello-hello.Po@am__quote@ @@ -1415,6 +1422,20 @@ src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_test0.obj: src/drivers/s @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_test0.obj `if test -f 'src/drivers/sifive_test0.c'; then $(CYGPATH_W) 'src/drivers/sifive_test0.c'; else $(CYGPATH_W) '$(srcdir)/src/drivers/sifive_test0.c'; fi` +src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.o: src/drivers/sifive_trace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -MT src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.o -MD -MP -MF src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Tpo -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.o `test -f 'src/drivers/sifive_trace.c' || echo '$(srcdir)/'`src/drivers/sifive_trace.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Tpo src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/drivers/sifive_trace.c' object='src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.o `test -f 'src/drivers/sifive_trace.c' || echo '$(srcdir)/'`src/drivers/sifive_trace.c + +src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.obj: src/drivers/sifive_trace.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -MT src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.obj -MD -MP -MF src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Tpo -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.obj `if test -f 'src/drivers/sifive_trace.c'; then $(CYGPATH_W) 'src/drivers/sifive_trace.c'; else $(CYGPATH_W) '$(srcdir)/src/drivers/sifive_trace.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Tpo src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/drivers/sifive_trace.c' object='src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_trace.obj `if test -f 'src/drivers/sifive_trace.c'; then $(CYGPATH_W) 'src/drivers/sifive_trace.c'; else $(CYGPATH_W) '$(srcdir)/src/drivers/sifive_trace.c'; fi` + src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.o: src/drivers/sifive_uart0.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libriscv__mmachine__@MACHINE_NAME@_a_CFLAGS) $(CFLAGS) -MT src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.o -MD -MP -MF src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.Tpo -c -o src/drivers/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.o `test -f 'src/drivers/sifive_uart0.c' || echo '$(srcdir)/'`src/drivers/sifive_uart0.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.Tpo src/drivers/$(DEPDIR)/libriscv__mmachine__@MACHINE_NAME@_a-sifive_uart0.Po diff --git a/metal/drivers/sifive_trace.h b/metal/drivers/sifive_trace.h new file mode 100644 index 00000000..3c67522f --- /dev/null +++ b/metal/drivers/sifive_trace.h @@ -0,0 +1,23 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#ifndef METAL__DRIVERS__SIFIVE_TRACE_H +#define METAL__DRIVERS__SIFIVE_TRACE_H + +#include +#include +#include + +struct __metal_driver_vtable_sifive_trace { + const struct metal_uart_vtable uart; +}; + +struct __metal_driver_sifive_trace; + +__METAL_DECLARE_VTABLE(__metal_driver_vtable_sifive_trace) + +struct __metal_driver_sifive_trace { + struct metal_uart uart; +}; + +#endif /* METAL__DRIVERS__SIFIVE_TRACE_H */ diff --git a/src/drivers/sifive_trace.c b/src/drivers/sifive_trace.c new file mode 100644 index 00000000..8b63fbd2 --- /dev/null +++ b/src/drivers/sifive_trace.c @@ -0,0 +1,95 @@ +/* Copyright 2019 SiFive, Inc */ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include + +#ifdef METAL_SIFIVE_TRACE + +#include +#include + +#define TRACE_REG(offset) (((unsigned long)base + (offset))) +#define TRACE_REG8(offset) \ + (__METAL_ACCESS_ONCE((__metal_io_u8 *)TRACE_REG(offset))) +#define TRACE_REG16(offset) \ + (__METAL_ACCESS_ONCE((__metal_io_u16 *)TRACE_REG(offset))) +#define TRACE_REG32(offset) \ + (__METAL_ACCESS_ONCE((__metal_io_u32 *)TRACE_REG(offset))) + +static void write_itc_uint32(struct metal_uart *trace, uint32_t data) { + long base = __metal_driver_sifive_trace_base(trace); + + TRACE_REG32(METAL_SIFIVE_TRACE_ITCSTIMULUS) = data; +} + +static void write_itc_uint16(struct metal_uart *trace, uint16_t data) { + long base = __metal_driver_sifive_trace_base(trace); + + TRACE_REG16(METAL_SIFIVE_TRACE_ITCSTIMULUS + 2) = data; +} + +static void write_itc_uint8(struct metal_uart *trace, uint8_t data) { + long base = __metal_driver_sifive_trace_base(trace); + + TRACE_REG8(METAL_SIFIVE_TRACE_ITCSTIMULUS + 3) = data; +} + +int __metal_driver_sifive_trace_putc(struct metal_uart *trace, + unsigned char c) { + static uint32_t buffer = 0; + static int bytes_in_buffer = 0; + + buffer |= (((uint32_t)c) << (bytes_in_buffer * 8)); + + bytes_in_buffer += 1; + + if (bytes_in_buffer >= 4) { + write_itc_uint32(trace, buffer); + + buffer = 0; + bytes_in_buffer = 0; + } else if ((c == '\n') || (c == '\r')) { // partial write + switch (bytes_in_buffer) { + case 3: // do a full word write + write_itc_uint16(trace, (uint16_t)(buffer)); + write_itc_uint8(trace, (uint8_t)(buffer >> 16)); + break; + case 2: // do a 16 bit write + write_itc_uint16(trace, (uint16_t)buffer); + break; + case 1: // do a 1 byte write + write_itc_uint8(trace, (uint8_t)buffer); + break; + } + + buffer = 0; + bytes_in_buffer = 0; + } + + return (int)c; +} + +void __metal_driver_sifive_trace_init(struct metal_uart *trace, int baud_rate) { + // The only init we do here is to make sure ITC 0 is enabled. It is up to + // Freedom Studio or other mechanisms to make sure tracing is enabled. If we + // try to enable tracing here, it will likely conflict with Freedom Studio, + // and they will just fight with each other. + + long base = __metal_driver_sifive_trace_base(trace); + + TRACE_REG32(METAL_SIFIVE_TRACE_ITCTRACEENABLE) |= 0x00000001; +} + +__METAL_DEFINE_VTABLE(__metal_driver_vtable_sifive_trace) = { + .uart.init = __metal_driver_sifive_trace_init, + .uart.putc = __metal_driver_sifive_trace_putc, + .uart.getc = NULL, + + .uart.get_baud_rate = NULL, + .uart.set_baud_rate = NULL, + + .uart.controller_interrupt = NULL, + .uart.get_interrupt_id = NULL, +}; + +#endif /* METAL_SIFIVE_TRACE */