From a6eadeb4fb20495e1d9cad415a0ff5f76bd8df28 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Sep 2019 17:21:55 -0700 Subject: [PATCH 1/2] gloss: Include in sys_getcwd.c This provides a definition of size_t Signed-off-by: Keith Packard --- gloss/sys_getcwd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gloss/sys_getcwd.c b/gloss/sys_getcwd.c index e80ff4ad..d8e73de6 100644 --- a/gloss/sys_getcwd.c +++ b/gloss/sys_getcwd.c @@ -1,4 +1,5 @@ #include +#include char *_getcwd(char *buf, size_t size) { errno = -ENOSYS; From 567f1280f43b8fe58c3d7d1eeb70841a5fe37af3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Aug 2019 21:55:36 -0700 Subject: [PATCH 2/2] Add metal-pico library [v4] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This library hooks picolibc to libmetal, offering a small number of APIs. Signed-off-by: Keith Packard --- v2: Initialize TLS base register from __tls_base and __tdata_size The RISC-V ABI sets the tp register between tls initialized data and tls uninitialized data areas. The linker sets __tls_base to the start of tls data and __tdata_size to the size of the initialized data area, so the correct tp value is the sum of these two symbols. libriscv__pico__metal.a → libmetal-pico.a Use the name that freedom-e-sdk wants Use gloss/crt0.S and gloss/sys_exit.c for libmetal-pico.a Share source code, especially the startup code, between the two C library users to avoid duplicating work between them. Expose sbrk/brk instead of _sbrk/_brk when compiled against picolibc This changes the names of these two functions when using picolibc instead of newlib. Otherwise, the implementation is the same. Use gloss/sys_sbrk.c with picolibc Instead of a separate copy with minor edits. v3: Use correct TLS initialization value. Risc-V places TP at the base of TLS storage, not between data and BSS values. v4: Fix spelling error in Makefile.am (libmetail-pico → libmetal-pico) Found-by: Nathaniel Graff --- Makefile.am | 14 +++++++++++ Makefile.in | 62 ++++++++++++++++++++++++++++++++++++++++++++---- gloss/crt0.S | 4 ++++ gloss/sys_sbrk.c | 17 ++++++++----- pico/iob.c | 44 ++++++++++++++++++++++++++++++++++ pico/sysconf.c | 16 +++++++++++++ pico/times.c | 17 +++++++++++++ 7 files changed, 163 insertions(+), 11 deletions(-) create mode 100644 pico/iob.c create mode 100644 pico/sysconf.c create mode 100644 pico/times.c diff --git a/Makefile.am b/Makefile.am index acb944a4..39fcd440 100644 --- a/Makefile.am +++ b/Makefile.am @@ -156,6 +156,20 @@ libmetal_a_SOURCES = \ src/vector.S \ src/watchdog.c +######################################################## +# libmetal-pico +######################################################## + +lib_LIBRARIES += libmetal-pico.a + +libmetal_pico_a_SOURCES = \ + gloss/crt0.S \ + pico/iob.c \ + gloss/sys_exit.c \ + pico/times.c \ + gloss/sys_sbrk.c \ + pico/sysconf.c + ######################################################## # libgloss ######################################################## diff --git a/Makefile.in b/Makefile.in index 4e38c146..7c0d628a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -243,6 +243,13 @@ am_libmetal_a_OBJECTS = src/drivers/fixed-clock.$(OBJEXT) \ src/time.$(OBJEXT) src/trap.$(OBJEXT) src/tty.$(OBJEXT) \ src/uart.$(OBJEXT) src/vector.$(OBJEXT) src/watchdog.$(OBJEXT) libmetal_a_OBJECTS = $(am_libmetal_a_OBJECTS) +libmetal_pico_a_AR = $(AR) $(ARFLAGS) +libmetal_pico_a_LIBADD = +am_libmetal_pico_a_OBJECTS = gloss/crt0.$(OBJEXT) \ + pico/iob.$(OBJEXT) gloss/sys_exit.$(OBJEXT) pico/times.$(OBJEXT) \ + gloss/sys_sbrk.$(OBJEXT) pico/sysconf.$(OBJEXT) +libmetal_pico_a_OBJECTS = \ + $(am_libmetal_pico_a_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -277,9 +284,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(libmetal_gloss_a_SOURCES) $(libmetal_a_SOURCES) +SOURCES = $(libmetal_gloss_a_SOURCES) $(libmetal_a_SOURCES) \ + $(libmetal_pico_a_SOURCES) DIST_SOURCES = $(am__libmetal_gloss_a_SOURCES_DIST) \ - $(libmetal_a_SOURCES) + $(libmetal_a_SOURCES) $(libmetal_pico_a_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -473,7 +481,11 @@ BUILT_SOURCES = \ ######################################################## # libmetal ######################################################## -lib_LIBRARIES = libmetal.a $(am__append_1) + +######################################################## +# libmetal-pico +######################################################## +lib_LIBRARIES = libmetal.a libmetal-pico.a $(am__append_1) libmetal_a_SOURCES = \ src/drivers/fixed-clock.c \ src/drivers/fixed-factor-clock.c \ @@ -534,6 +546,14 @@ libmetal_a_SOURCES = \ src/vector.S \ src/watchdog.c +libmetal_pico_a_SOURCES = \ + gloss/crt0.S \ + pico/iob.c \ + gloss/sys_exit.c \ + pico/times.c \ + gloss/sys_sbrk.c \ + pico/sysconf.c + @WITH_BUILTIN_LIBGLOSS_TRUE@libmetal_gloss_a_SOURCES = \ @WITH_BUILTIN_LIBGLOSS_TRUE@ gloss/crt0.S \ @WITH_BUILTIN_LIBGLOSS_TRUE@ gloss/nanosleep.c \ @@ -838,10 +858,34 @@ libmetal.a: $(libmetal_a_OBJECTS) $(libmetal_a_DEPENDENCIES) $(EXTRA_libmetal_a_ $(AM_V_at)-rm -f libmetal.a $(AM_V_AR)$(libmetal_a_AR) libmetal.a $(libmetal_a_OBJECTS) $(libmetal_a_LIBADD) $(AM_V_at)$(RANLIB) libmetal.a +pico/$(am__dirstamp): + @$(MKDIR_P) pico + @: > pico/$(am__dirstamp) +pico/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) pico/$(DEPDIR) + @: > pico/$(DEPDIR)/$(am__dirstamp) +gloss/crt0.$(OBJEXT): gloss/$(am__dirstamp) \ + gloss/$(DEPDIR)/$(am__dirstamp) +pico/iob.$(OBJEXT): pico/$(am__dirstamp) \ + pico/$(DEPDIR)/$(am__dirstamp) +gloss/sys_exit.$(OBJEXT): gloss/$(am__dirstamp) \ + gloss/$(DEPDIR)/$(am__dirstamp) +pico/times.$(OBJEXT): pico/$(am__dirstamp) \ + pico/$(DEPDIR)/$(am__dirstamp) +gloss/sys_sbrk.$(OBJEXT): gloss/$(am__dirstamp) \ + gloss/$(DEPDIR)/$(am__dirstamp) +pico/sysconf.$(OBJEXT): pico/$(am__dirstamp) \ + pico/$(DEPDIR)/$(am__dirstamp) + +libmetal-pico.a: $(libmetal_pico_a_OBJECTS) $(libmetal_pico_a_DEPENDENCIES) $(EXTRA_libmetal_pico_a_DEPENDENCIES) + $(AM_V_at)-rm -f libmetal-pico.a + $(AM_V_AR)$(libmetal_pico_a_AR) libmetal-pico.a $(libmetal_pico_a_OBJECTS) $(libmetal_pico_a_LIBADD) + $(AM_V_at)$(RANLIB) libmetal-pico.a mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f gloss/*.$(OBJEXT) + -rm -f pico/*.$(OBJEXT) -rm -f src/*.$(OBJEXT) -rm -f src/drivers/*.$(OBJEXT) @@ -881,6 +925,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@gloss/$(DEPDIR)/sys_utime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gloss/$(DEPDIR)/sys_wait.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gloss/$(DEPDIR)/sys_write.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/crt0.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/exit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/iob.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/sbrk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/sysconf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@pico/$(DEPDIR)/times.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/atomic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/button.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cache.Po@am__quote@ @@ -1254,6 +1304,8 @@ distclean-generic: -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f gloss/$(DEPDIR)/$(am__dirstamp) -rm -f gloss/$(am__dirstamp) + -rm -f pico/$(DEPDIR)/$(am__dirstamp) + -rm -f pico/$(am__dirstamp) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) -rm -f src/drivers/$(DEPDIR)/$(am__dirstamp) @@ -1269,7 +1321,7 @@ clean-am: clean-generic clean-libLIBRARIES clean-local mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf gloss/$(DEPDIR) src/$(DEPDIR) src/drivers/$(DEPDIR) + -rm -rf gloss/$(DEPDIR) pico/$(DEPDIR) src/$(DEPDIR) src/drivers/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -1317,7 +1369,7 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf gloss/$(DEPDIR) src/$(DEPDIR) src/drivers/$(DEPDIR) + -rm -rf gloss/$(DEPDIR) pico/$(DEPDIR) src/$(DEPDIR) src/drivers/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/gloss/crt0.S b/gloss/crt0.S index e68b736a..4d81e253 100644 --- a/gloss/crt0.S +++ b/gloss/crt0.S @@ -126,6 +126,10 @@ _start: #endif 2: + /* Set TLS pointer */ + .weak __tls_base + la tp, __tls_base + /* At this point we're in an environment that can execute C code. The first * thing to do is to make the callback to the parent environment if it's been * requested to do so. */ diff --git a/gloss/sys_sbrk.c b/gloss/sys_sbrk.c index 5deb1371..a1b14b21 100644 --- a/gloss/sys_sbrk.c +++ b/gloss/sys_sbrk.c @@ -8,15 +8,20 @@ * that's been allocated. */ extern char metal_segment_heap_target_start; extern char metal_segment_heap_target_end; -static char *brk = &metal_segment_heap_target_start; +static char *__brk = &metal_segment_heap_target_start; + +#ifdef _PICOLIBC__ +#define _brk brk +#define _sbrk sbrk +#endif int _brk(void *addr) { - brk = addr; + __brk = addr; return 0; } char *_sbrk(ptrdiff_t incr) { - char *old = brk; + char *old = __brk; /* If __heap_size == 0, we can't allocate memory on the heap */ if (&metal_segment_heap_target_start == &metal_segment_heap_target_end) { @@ -24,10 +29,10 @@ char *_sbrk(ptrdiff_t incr) { } /* Don't move the break past the end of the heap */ - if ((brk + incr) < &metal_segment_heap_target_end) { - brk += incr; + if ((__brk + incr) < &metal_segment_heap_target_end) { + __brk += incr; } else { - brk = &metal_segment_heap_target_end; + __brk = &metal_segment_heap_target_end; return (void *)-1; } diff --git a/pico/iob.c b/pico/iob.c new file mode 100644 index 00000000..481c014f --- /dev/null +++ b/pico/iob.c @@ -0,0 +1,44 @@ +/* + * Copyright © 2019 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include + +static int metal_putc(char c, FILE *file) { + (void)file; + metal_tty_putc(c); + return c; +} + +static int metal_getc(FILE *file) { + int c; + (void)file; + metal_tty_getc(&c); + return c; +} + +static int metal_flush(FILE *file) { return 0; } + +static FILE __stdio = + FDEV_SETUP_STREAM(metal_putc, metal_getc, metal_flush, _FDEV_SETUP_RW); + +FILE *const __iob[3] = {&__stdio, &__stdio, &__stdio}; diff --git a/pico/sysconf.c b/pico/sysconf.c new file mode 100644 index 00000000..63f4ce90 --- /dev/null +++ b/pico/sysconf.c @@ -0,0 +1,16 @@ +#include +#include + +/* Get configurable system variables. */ + +long sysconf(int name) { + unsigned long long timebase; + + switch (name) { + case _SC_CLK_TCK: + metal_timer_get_timebase_frequency(0, &timebase); + return (long)timebase; + } + + return -1; +} diff --git a/pico/times.c b/pico/times.c new file mode 100644 index 00000000..a6a19192 --- /dev/null +++ b/pico/times.c @@ -0,0 +1,17 @@ +#include +#include +#include + +/* + * Simple enough to return the tick count by + * just getting it from the hardware. + */ + +clock_t times(struct tms *buf) { + unsigned long long mcc; + metal_timer_get_cyclecount(0, &mcc); + buf->tms_stime = 0; + buf->tms_cutime = 0; + buf->tms_cstime = 0; + return buf->tms_utime = mcc; +}