GCC toolchain

1,439 views
Skip to first unread message

Liviu Ionescu

unread,
Aug 24, 2017, 6:54:51 PM8/24/17
to RISC-V SW Dev
Please note that following some discussions with the maintainers of the RISC-V GCC toolchain, it was confirmed that the riscv64-unknown-elf-gcc version is intended to generate applications that run in linux environments, and not in bare metal environments (it intentionally mandates the inclusion of libgloss, the library that implements the system calls via ecalls, the kernel traps).

The problem was identified when I had major difficulties to build the same kind of retargeted applications that I already use for other platforms (applications that reimplement the standard system calls in bare metal environment).


The initial release of GNU MCU RISC-V GCC toolchain, being a replica of the official SiFive toolchain, is also linux dedicated, but I already managed to build a bare metal configured toolchain, with the same configuration as the ARM toolchain, which no longer mandates the presence of libgloss and allows to build retargeted applications (plus that it also includes the size optimised newlib-nano).


Since it looks like the linux toolchain is heavily used for some testing purposes, and will continue to be needed, it is not clear if/how the bare metal needs will be addressed (a second toolchain will be provided, or a common solution will be accepted).

Anyway, the GNU MCU Eclipse project is committed to support bare metal applications, so it'll probably provide a bare metal toolchain anyway; if it'll be different from the SiFive toolchain, probably we'll have to rename it to the more appropriate name riscv-none-gcc, to avoid confusion.


Regards,

Liviu



Richard Herveille

unread,
Aug 25, 2017, 8:23:30 AM8/25/17
to Liviu Ionescu, Richard Herveille, RISC-V SW Dev

riscv64-unknown-elf-gcc uses newlib, which relies on libgloss, which in turn uses BSP (board support package) to implement the syscalls.

You would need to create a BSP for each board/environment.

From your findings, it seems the current BSP targets linux (not my 1st choice for a bare-metal environment).

Can we define a common environment and add a BSP for real bare-metal systems?

 

Richard

 

 

Richard Herveille

Managing Director

Phone +31 (45) 405 5681

Cell +31 (6) 5207 2230

richard....@roalogic.com

 

--

You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.

To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.

To post to this group, send email to sw-...@groups.riscv.org.

 

John Leidel

unread,
Aug 25, 2017, 8:34:08 AM8/25/17
to Richard Herveille, Liviu Ionescu, RISC-V SW Dev
Richard, defining a base level BSP for bare-metal systems would be very useful.  We've deployed RISC-V builds on a number of FPGA platforms that aren't supported by SiFive, Microsemi or others.  As a result, we've been forced to build (and rebuild) all sorts of tools for each orthogonal BSP.  

To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.

To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Liviu Ionescu

unread,
Aug 25, 2017, 8:47:56 AM8/25/17
to Richard Herveille, RISC-V SW Dev

> On 25 Aug 2017, at 15:23, Richard Herveille <richard....@roalogic.com> wrote:
>
> riscv64-unknown-elf-gcc uses newlib, which relies on libgloss, which in turn uses BSP (board support package) to implement the syscalls.
> You would need to create a BSP for each board/environment.
> From your findings, it seems the current BSP targets linux (not my 1st choice for a bare-metal environment).

why do you say libgloss uses BSP?

libgloss is a small library in the newlib package, architecture specific. for risc-v, the current implementation issues `scall` traps to the kernel:

https://github.com/riscv/riscv-newlib/tree/riscv-newlib-2.5.0/libgloss/riscv

> Can we define a common environment and add a BSP for real bare-metal systems?

there is no need for this. or at least not for the toolchain usage.

a bare-metal toolchain should simply not force the inclusion of libgloss, and the application can/should redefine all underscore specific functions (like `_write()`) to its needs.

because the current toolchain is intended for linux tests, it forces libgloss to be always linked to the application.

as such, if you build a bare-metal application and try to issue a `puts()`, you end up calling `_write()`, which calls SYS_write via a `scall`; in my tests, this resulted in a hanged core.

the usual solution is to redefine `_write()`, but in this case it is not possible, since the library does not define it as weak, and you get an error.

(if you want to test, please note that the current toolchain release has another problem, it does not use the underscore functions, but the standard non-underscore functions, i.e. write() instead of _write(), which creates additional problems; fortunately this was already solved in the newlib 2.5.0 repository and will probably be included in the next toolchain release)


to overcome the redefinition error, the current SDK uses libwrap, accompanied by lots of --wrap linker command line options, to wrap each linux call with a custom call.

this approach is functional, but it is way too complicated for regular bare-metal usage.


the natural bare-metal solution is to not include libgloss. when you build an application that tries to write something via `puts()` (or any other standard IO function), the linker complains that `_write()` and a few more are not defined, and the application should provide them.


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 9:06:14 AM8/25/17
to RISC-V SW Dev, richard....@roalogic.com
I'm a bit confused...

If riscv64-unknown-elf-gcc  is targeting Linux then why are there different instructions for building the newlib riscv64-unknown-elf-gcc tool chain (which I always assumed was for bare metal) here:


and the linux riscv64-unknown-linux-gnu-gcc here:


Has something changed to render this info out of date?

Also I don't really see how the use of libgloss relates to linux since it's a newlib thing.
Isn't the fundamental problem here the lack of weak linkage on the relevant system calls (stubs) in libgloss?

Regards
Tommy

Liviu Ionescu

unread,
Aug 25, 2017, 9:16:42 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 16:06, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> I'm a bit confused...
>
> If riscv64-unknown-elf-gcc is targeting Linux then why are there different instructions for building the newlib riscv64-unknown-elf-gcc tool chain (which I always assumed was for bare metal) here:
>
> https://github.com/riscv/riscv-tools#newlibman
>
> and the linux riscv64-unknown-linux-gnu-gcc here:
>
> https://github.com/riscv/riscv-tools#linuxman
>
> Has something changed to render this info out of date?

if I got it right, `riscv64-unknown-linux-gnu-gcc` is intended to run natively on linux, while `riscv64-unknown-elf-gcc` is intended to run as a cross compiler.

newlib in itself is not necessarily a bare-metal library, it is intended as a light version of libc; it can be configured in many ways, including as newlib-nano, which is usually for bare-metal applications.

> Also I don't really see how the use of libgloss relates to linux since it's a newlib thing.

as mentioned before, for risc-v, the current implementation of libgloss issues `scall` traps to the kernel:

https://github.com/riscv/riscv-newlib/tree/riscv-newlib-2.5.0/libgloss/riscv

> Isn't the fundamental problem here the lack of weak linkage on the relevant system calls (stubs) in libgloss?

no, the fundamental problem here is that in a bare-metal application there should be no functions that issue `scall` traps to the kernel.


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 9:28:37 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
> if I got it right, `riscv64-unknown-linux-gnu-gcc` is intended to run natively on linux, while `riscv64-unknown-elf-gcc` is intended to run as a cross compiler. 

I'm skeptical about this.
My understanding is that they are both cross compilers targeting physical or simulated RISC-V hardware.
And that the difference between the two is that riscv64-unknown-elf-gcc targets bare metal and uses the "raw" RISC-V ABI while riscv64-linux-gnu-gcc targets RISC-V running linux and, for example, uses the System-V (rather than raw RISC-V) ABI.
Maybe somebody more knowledgeable than me can clarify?

Liviu Ionescu

unread,
Aug 25, 2017, 9:42:23 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
one more good example why the bare-metal cross compiler should be called `riscv-none-gcc` and not `riscv64-unknown-elf-gcc` **plus** `riscv32-unknown-elf-gcc`:

https://gnu-mcu-eclipse.github.io/toolchain/riscv/#riscv64-unknown-elf-gcc-vs-riscv32-unknown-elf-gcc


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 9:50:22 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
Yes - I just read that link now.
But since, for example, the ARM GCC bare metal toolchain is arm-none-eabi-gcc doesn't this imply that the RISC-V bare metal toolchain might best be called riscv-none-<someabi>-gcc?
I'm not sure what <someabi> should be since RISC-V supports different ABIs - e.g. ilp32, ilp32d etc.

Whatever about that I still believe that both riscv[xx]-unknown-elf-gcc and riscv[xx]-linux-gnu-gcc toolchains are cross compilers with the former targeting bare metal/raw RISC-V ABI[s] and the latter targeting linux/System-V ABI etc.
Who was it who said that riscv[xx]-unknown-elf targets linux?

Richard Herveille

unread,
Aug 25, 2017, 10:06:01 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, Richard Herveille

That was my understanding as well …

 

Richard

 

 

 

 

Richard Herveille

Managing Director

Phone +31 (45) 405 5681

Cell +31 (6) 5207 2230

richard....@roalogic.com

 

 

 

From: Tommy Murphy <tommy_...@hotmail.com>


Date: Friday 25 August 2017 at 15:06
To: RISC-V SW Dev <sw-...@groups.riscv.org>

--

You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Richard Herveille

unread,
Aug 25, 2017, 10:09:19 AM8/25/17
to Liviu Ionescu, RISC-V SW Dev, Richard Herveille

 

On 25 Aug 2017, at 15:23, Richard Herveille <richard....@roalogic.com> wrote:

riscv64-unknown-elf-gcc uses newlib, which relies on libgloss, which in turn uses BSP (board support package) to implement the syscalls.

You would need to create a BSP for each board/environment.

From your findings, it seems the current BSP targets linux (not my 1st choice for a bare-metal environment).

 

why do you say libgloss uses BSP?

[rih] Because that’s how libgloss works …

 

 

 

libgloss is a small library in the newlib package, architecture specific. for risc-v, the current implementation issues `scall` traps to the kernel:

https://github.com/riscv/riscv-newlib/tree/riscv-newlib-2.5.0/libgloss/riscv

[rih] Yes, and it should be BSP that does the actual syscalls.

 

 

 

Can we define a common environment and add a BSP for real bare-metal systems?

 

there is no need for this. or at least not for the toolchain usage.

 

a bare-metal toolchain should simply not force the inclusion of libgloss, and the application can/should redefine all underscore specific functions (like `_write()`) to its needs.

 

because the current toolchain is intended for linux tests, it forces libgloss to be always linked to the application.

 

as such, if you build a bare-metal application and try to issue a `puts()`, you end up calling `_write()`, which calls SYS_write via a `scall`; in my tests, this resulted in a hanged core.

[rih] If written well, then you can overrule the default implementation. By default it calls _write(). But if you define write() it should call that function and not the one in the library.

 

 

Richard

 

 

 

 

Liviu Ionescu

unread,
Aug 25, 2017, 10:20:35 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 16:50, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> Who was it who said that riscv[xx]-unknown-elf targets linux?

since it creates applications that use scall kernel traps, I would hardly call it a bare-metal toolchain.


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 10:41:00 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
Only because the existing newlib implementation insists on pulling in libgloss routines that use scall kernel traps and which are not weakly linked allowing them to be overridden?
I.e. I think that the problem here is with the newlib that gets built when building the bare metal riscv[xx]-unknown-elf-gcc toolchain and not with the toolchain itself?
At the very least the libgloss routines should be weakly linked and maybe the default implementations should be different (i.e. not use scall kernel traps)?

Liviu Ionescu

unread,
Aug 25, 2017, 10:42:57 AM8/25/17
to Richard Herveille, RISC-V SW Dev

> On 25 Aug 2017, at 17:09, Richard Herveille <richard....@roalogic.com> wrote:
>
>
> On 25 Aug 2017, at 15:23, Richard Herveille <richard....@roalogic.com> wrote:
> riscv64-unknown-elf-gcc uses newlib, which relies on libgloss, which in turn uses BSP (board support package) to implement the syscalls.
> You would need to create a BSP for each board/environment.
> From your findings, it seems the current BSP targets linux (not my 1st choice for a bare-metal environment).
>
> why do you say libgloss uses BSP?
> [rih] Because that’s how libgloss works …
> libgloss is a small library in the newlib package, architecture specific. for risc-v, the current implementation issues `scall` traps to the kernel:
> https://github.com/riscv/riscv-newlib/tree/riscv-newlib-2.5.0/libgloss/riscv
> [rih] Yes, and it should be BSP that does the actual syscalls.

I'm not sure I understand you.

indeed libgloss implements several posix system calls by redirecting them to the host, either a kernel or a debugger (with ARM semihosting probably a good example of such an implementation), but this is not a common use case for bare metal scenarios.

practically, what you say, is that in a bare-metal application, if you want to use the standard IO functions, you must use libgloss and a small kernel that processes the ecall traps?

isn't it quite heavy?

the alternative is to **not** include libgloss and provide direct implementations for _write() & co, without having to go via traps and exception handlers at all. I think this is more common for embedded applications.


regards,

Liviu

Liviu Ionescu

unread,
Aug 25, 2017, 10:57:23 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 17:41, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> Only because the existing newlib implementation insists on pulling in libgloss routines that use scall kernel traps and which are not weakly linked allowing them to be overridden?
> I.e. I think that the problem here is with the newlib that gets built when building the bare metal riscv[xx]-unknown-elf-gcc toolchain and not with the toolchain itself?

the libgloss is pulled due to a line in the specs file, configured in the GCC source tree, not in the NEWLIB source tree.

> At the very least the libgloss routines should be weakly linked and maybe the default implementations should be different (i.e. not use scall kernel traps)?

this is debatable.

apart from this current RISC-V toolchain, the normal use case is that, by default, libgloss is **not** linked, and the application should define all needed functions (like _write()).

if an application is targeted to a test environment (debugger/simulator/etc), then the linker must be informed (with a -lgloss) and in this case **all** system calls should be forwarded to the host, and **all** means **all**, otherwise the application might not behave consistently).

in your scenario, if libgloss is linked, and all symbols are weak, you can overwrite some of the functions with your local implementations, but if you forget, you unwillingly get a default function that issues a scall and hangs your application.

personally I prefer the linker to complain about missing functions instead of defaulting to scall kernel traps. (this is also the behaviour of the ARM toolchain).


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 11:06:25 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
OK - but it still seems to me that the intention is that the riscv[xx]-unknown-elf-gcc toolchain is a bare metal toolchain (+ newlib) but a mistake (?) in building it means that libgloss gets pulled in.
I still don't believe that the riscv[xx]-unknown-elf-gcc cross compiler toolchain is intended to target linux.
For that one would use the riscv[xx]-linux-gnu-gcc cross compiler toolchain.
So the key question to me seems to be how can the issue with newlib/libgloss in the de facto bare metal toolchain be tackled/fixed?
If my analysis is incorrect then perhaps somebody can explain clearly why?
Regards
Tommy

Richard Herveille

unread,
Aug 25, 2017, 11:10:14 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, Richard Herveille

That’s exactly my understanding as well.

Maybe someone from the GCC developers should step in here.

Maybe the solution is as easy as, by default, not linking libgloss?!

 

Richard

 

 

 

Richard Herveille

Managing Director

Phone +31 (45) 405 5681

Cell +31 (6) 5207 2230

richard....@roalogic.com

 

 

 

From: Tommy Murphy <tommy_...@hotmail.com>


Date: Friday 25 August 2017 at 17:06
To: RISC-V SW Dev <sw-...@groups.riscv.org>

Cc: "tommy_...@hotmail.com" <tommy_...@hotmail.com>, Richard Herveille <richard....@roalogic.com>
Subject: Re: [sw-dev] GCC toolchain

 

OK - but it still seems to me that the intention is that the riscv[xx]-unknown-elf-gcc toolchain is a bare metal toolchain (+ newlib) but a mistake (?) in building it means that libgloss gets pulled in.

--

You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Jay Aurabind

unread,
Aug 25, 2017, 11:38:47 AM8/25/17
to Richard Herveille, Tommy Murphy, RISC-V SW Dev
On 25 August 2017 at 20:40, Richard Herveille
<richard....@roalogic.com> wrote:
> That’s exactly my understanding as well.
>
> Maybe someone from the GCC developers should step in here.
>
> Maybe the solution is as easy as, by default, not linking libgloss?!

Sorry if its noobish, but I have two questions here.

In the first message in the thread, Liviu mentions that
"riscv64-unknown-elf-gcc version is intended to generate applications
that run in linux environments, and not in bare metal environments"
because it mandates the inclusion of libgloss. My questions are:

* Is the handling of a few _functions() the only difference between a
bare metal and an os-api toolchain ? I searched for the differences,
and getting only high level difference which I understand, but I cant
seem to find them in terms of their implementation.

* If no, is the inclusion of libgloss the **only** thing mandated by
riscv[xx]-unknown-elf-gcc in its current configuration?

** What about the changes required for the linker configuration? In
the riscv[xx]-unknown-elf-gcc configuration, is it linked like to be
used in linux environment or a bare metal env?

** It was mentioned that riscv[xx]-unknown-elf-gcc is being used
extensively for testing. I'm assuming, these tests [with binaries
generated by riscv[xx]-unknown-elf-gcc] would be running on a linux
emulator?

As per my understanding, if the riscv[xx]-unknown-elf-gcc is linked
for linux env, and it is mandating libgloss, then the only difference
between riscv[xx]-linux-gnu-gcc and riscv[xx]-unknown-elf-gcc is just
renaming ?

>
>
>
> Richard
> https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/9DC3EF20-F855-4AAA-8E57-B3FF6329387E%40roalogic.com.



--

Thanks and Regards,
Aurabindo J

Liviu Ionescu

unread,
Aug 25, 2017, 11:41:47 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 18:06, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> OK - but it still seems to me that the intention is that the riscv[xx]-unknown-elf-gcc toolchain is a bare metal toolchain (+ newlib) but a mistake (?) in building it means that libgloss gets pulled in.

the reason I started this thread was that it was confirmed that it was **not** a mistake, but an intended behaviour, which makes me think if bare-metal configurations, as we understand them, were even considered... :-(


regards,

Liviu






Tommy Murphy

unread,
Aug 25, 2017, 11:46:53 AM8/25/17
to RISC-V SW Dev, richard....@roalogic.com, tommy_...@hotmail.com

On Friday, 25 August 2017 16:38:47 UTC+1, jay.aurabind wrote:
 
In the first message in the thread, Liviu mentions that
"riscv64-unknown-elf-gcc version is intended to generate applications
that run in linux environments, and not in bare metal environments"
because it mandates the inclusion of libgloss. My questions are:

As I have said I remain skeptical about this.
As far as I can see the riscv[xx]-unknown-elf-gcc toolchain IS designed for bare metal but there seems to be a problem with the newlib/libgloss bundled whereby it uses scall kernel traps.
 
* Is the handling of a few _functions() the only difference between a
bare metal and an os-api toolchain ? I searched for the differences,
and getting only high level difference which I understand, but I cant
seem to find them in terms of their implementation. 

I believe that at least one other difference is that the riscv[xx]-unknown-elf-gcc toolchain uses the relevant bare metal ABI (e.g. ilp32, ilp64 etc.) whereas the riscv[xx]-linux-gnu-gcc toolchain most likely uses the System-V ABI used by most or all linux/unix OSs.
Note that compiling with riscv[xx]-unknown-elf-gcc versus riscv[xx]-linux-gnu-gcc and -ffreestanding results in significantly different ELF contents.


As per my understanding, if the riscv[xx]-unknown-elf-gcc is linked
for linux env, and it is mandating libgloss, then the only difference
between riscv[xx]-linux-gnu-gcc and riscv[xx]-unknown-elf-gcc is just
renaming ?

As I have said I don't believe that this is the case.

Khem Raj

unread,
Aug 25, 2017, 11:49:52 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
On 8/25/17 6:06 AM, Tommy Murphy wrote:
> I'm a bit confused...
>
> If riscv64-unknown-elf-gcc  is targeting Linux then why are there
> different instructions for building the newlib riscv64-unknown-elf-gcc
> tool chain (which I always assumed was for bare metal) here:
>

Generally speaking triplets specify the OS as the third part which when
contains linux means that this is a cross toolchain which will generate
code that will run on a linux (hosted) environment. Then there are C
libraries e.g. linux-musl linux-gnu linux-uclibc to confuse a bit more
there are ABIs also reflected there e.g. linux-gnueabi

'elf' for OS means toolchain is targeting baremetal or standalone
applications using ELF object format. Newlib could be one option to use
as C library for standalone toolchains.

Tommy Murphy

unread,
Aug 25, 2017, 11:50:03 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
But who exactly confirmed this?
Maybe they can contribute to this thread since there's so much confusion?
To start with maybe they can explain why there are instructions for building separate riscv[xx]-unknown-elf-gcc + newlib (aka bare metal?) and riscv[xx]-linux-gnu-gcc toolchains if both target linux?

Liviu Ionescu

unread,
Aug 25, 2017, 11:52:14 AM8/25/17
to Jay Aurabind, Richard Herveille, Tommy Murphy, RISC-V SW Dev

> On 25 Aug 2017, at 18:38, Jay Aurabind <jay.au...@gmail.com> wrote:
>
> ... then the only difference
> between riscv[xx]-linux-gnu-gcc and riscv[xx]-unknown-elf-gcc is just
> renaming ?

nope, `riscv[xx]-linux-gnu-gcc` is built with glibc instead of newlib.

that's the reason I assumed it is intended to run on linux, but probably this is not correct, I guess it can be built on other platforms than linux.


regards,

Liviu





Richard Herveille

unread,
Aug 25, 2017, 11:52:44 AM8/25/17
to Liviu Ionescu, Tommy Murphy, RISC-V SW Dev, Richard Herveille

 

 

On 25 Aug 2017, at 18:06, Tommy Murphy <tommy_...@hotmail.com> wrote:

OK - but it still seems to me that the intention is that the riscv[xx]-unknown-elf-gcc toolchain is a bare metal toolchain (+ newlib) but a mistake (?) in building it means that libgloss gets pulled in.

 

the reason I started this thread was that it was confirmed that it was **not** a mistake, but an intended behaviour, which makes me think if bare-metal configurations, as we understand them, were even considered... :-(

 

[rih]

Well that just @*$&#^!$ then … So that means so far me and my customers have been lucky??

You can’t call a toolchain bare-metal (=without relying on an underlying OS) and then state it requires Linux. That’s just plain wrong.

This can’t be right. It might well be that test environments rely on newlib->libglogss->linux syscalls, but then those environments should explicitly link libgloss.

 

So far we had no issues using riscv64-unknown-elf-gcc for bare-metal environments, so it can be used.  We’ve used puts() but added an ‘undef puts’ before defining our own and that seemed to work. Which already hints at that puts() was predefined.

 

I still don’t believe we need another toolchain; riscv64-unknown-elf-gcc is perfectly fine. It just needs to be built WITHOUT relying on libgloss.

 

Richard

 

 

 

 

 

 

 

 

Khem Raj

unread,
Aug 25, 2017, 11:54:36 AM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
On 8/25/17 6:50 AM, Tommy Murphy wrote:
> Yes - I just read that link now.
> But since, for example, the ARM GCC bare metal toolchain is
> arm-none-eabi-gcc doesn't this imply that the RISC-V bare metal
> toolchain might best be called riscv-none-<someabi>-gcc?
> I'm not sure what <someabi> should be since RISC-V supports different
> ABIs - e.g. ilp32, ilp32d etc.

ARM had old ABI which was using arm-none-elf then once EABI became
standard, it needed another way to differentiate and hence eabi creeped
into triplet. Its not a good example to follow for risc-v. Hopefully
RISC-V wont have to redefine its ABI completely down the lane, but for
now rscv-*-elf can mean a ELF based baremetal toolchain for risv
processors to keep it simple.

>
> Whatever about that I still believe that both riscv[xx]-unknown-elf-gcc
> and riscv[xx]-linux-gnu-gcc toolchains are cross compilers with the
> former targeting bare metal/raw RISC-V ABI[s] and the latter targeting
> linux/System-V ABI etc.
> Who was it who said that riscv[xx]-unknown-elf targets linux?
>
>
> On Friday, 25 August 2017 14:42:23 UTC+1, Liviu Ionescu wrote:
>
>
> > On 25 Aug 2017, at 16:28, Tommy Murphy <tommy_...@hotmail.com
> <javascript:>> wrote:
> >
> > > if I got it right, `riscv64-unknown-linux-gnu-gcc` is intended
> to run natively on linux, while `riscv64-unknown-elf-gcc` is
> intended to run as a cross compiler.
> >
> > I'm skeptical about this.
> > My understanding is that they are both cross compilers targeting
> physical or simulated RISC-V hardware.
> > And that the difference between the two is that
> riscv64-unknown-elf-gcc targets bare metal and uses the "raw" RISC-V
> ABI while riscv64-linux-gnu-gcc targets RISC-V running linux and,
> for example, uses the System-V (rather than raw RISC-V) ABI.
>
> one more good example why the bare-metal cross compiler should be
> called `riscv-none-gcc` and not `riscv64-unknown-elf-gcc` **plus**
> `riscv32-unknown-elf-gcc`:
>
>         https://gnu-mcu-eclipse.github.io/toolchain/riscv/#riscv64-unknown-elf-gcc-vs-riscv32-unknown-elf-gcc
> <https://gnu-mcu-eclipse.github.io/toolchain/riscv/#riscv64-unknown-elf-gcc-vs-riscv32-unknown-elf-gcc>
>
>
>
> regards,
>
> Liviu
>
> --
> You received this message because you are subscribed to the Google
> Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sw-dev+un...@groups.riscv.org
> <mailto:sw-dev+un...@groups.riscv.org>.
> To post to this group, send email to sw-...@groups.riscv.org
> <mailto:sw-...@groups.riscv.org>.
> Visit this group at
> https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit
> https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/b8cb2dd7-0704-4889-9191-0dc38d126a02%40groups.riscv.org
> <https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/b8cb2dd7-0704-4889-9191-0dc38d126a02%40groups.riscv.org?utm_medium=email&utm_source=footer>.

Tommy Murphy

unread,
Aug 25, 2017, 11:55:43 AM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
Yes - although the vendor field can also be omitted in which case the OS is the second, not third, field.
E.g.:


Also this seems to back up my view that riscv[xx]-unknown-elf-gcc is for embedded (bare metal?) not linux and riscv[xx]-linux-gnu-gcc is for Linux:


I really wonder who claimed that riscv[xx]-unknown-elf-gcc was for linux...?

Tommy Murphy

unread,
Aug 25, 2017, 11:58:30 AM8/25/17
to RISC-V SW Dev, i...@livius.net, tommy_...@hotmail.com, richard....@roalogic.com
I'm 100% in agreement with Richard here.
And we too have had no problems using riscv64-unknown-elf-gcc for bare metal.
Admittedly we do provide our own "syscall" stubs (write() etc.) so maybe libgloss never gets a look in?
I can't believe that it has simple been luck that allowed things to work...

Liviu Ionescu

unread,
Aug 25, 2017, 12:00:47 PM8/25/17
to Khem Raj, Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 18:54, Khem Raj <raj....@gmail.com> wrote:
>
> but for
> now rscv-*-elf can mean a ELF based baremetal toolchain for risv
> processors to keep it simple.

then riscv-none-elf is probably less confusing then the pair riscv64-unknown-elf and riscv32-unknown-elf.

I'm not a linguist, but to me 'none' means clearly 'no OS', while 'unknown' gives a feeling of uncertainty.


regards,

Liviu


Tommy Murphy

unread,
Aug 25, 2017, 12:01:23 PM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
Well it has multiple ABIs (ilp32, ilp64 etc.) but I suppose that these are communicated via -march and -mabi so the  toolchain name doesn't need to reflect them?
Also - you seem to agree (with me, Richard) that riscv-*-elf means bare metal which contradicts what Liviu's source seems to be claiming (i.e. that riscv[xx]-uknknown-elf-gcc) targets linux?

Tommy Murphy

unread,
Aug 25, 2017, 12:03:56 PM8/25/17
to RISC-V SW Dev, raj....@gmail.com, tommy_...@hotmail.com, richard....@roalogic.com
I don't know what the general approach is here but doesn't "unknown" allow for bare metal or, say, FreeRTOS or mynewt other "lightweight" OSs that use the bare metal ABIs and don't introduce their own as linux does (System V ABI)?

Bruce Hoult

unread,
Aug 25, 2017, 12:03:58 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, Richard Herveille
On Fri, Aug 25, 2017 at 6:55 PM, Tommy Murphy <tommy_...@hotmail.com> wrote:
Yes - although the vendor field can also be omitted in which case the OS is the second, not third, field.
E.g.:


Also this seems to back up my view that riscv[xx]-unknown-elf-gcc is for embedded (bare metal?) not linux and riscv[xx]-linux-gnu-gcc is for Linux:

Of course it is.

However, people do like to be able to use libc functions such as puts or printf in their code, for debugging if nothing else. Those have to call *something* low level and it's convenient for them to call something compatible with POSIX style write(2) rather than something ad-hoc or whatever abomination MSDOS or Windows or VMS used. 
 
> I really wonder who claimed that riscv[xx]-unknown-elf-gcc was for linux...?

I suspect Liviu misunderstood someone.

Khem Raj

unread,
Aug 25, 2017, 12:07:42 PM8/25/17
to Liviu Ionescu, Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
Hi Liviu
second element in triplet denotes vendor not OS, so I could also call it

riscv-<mycompany>-elf

OS field here effectively is 'elf' which means baremetal.

>
> regards,
>
> Liviu
>
>

Liviu Ionescu

unread,
Aug 25, 2017, 12:08:20 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 18:58, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> Admittedly we do provide our own "syscall" stubs (write() etc.) so maybe libgloss never gets a look in?
> I can't believe that it has simple been luck that allowed things to work...

if you provide your own syscalls, it can't be luck.

but create a very basic project, with the Eclipse RISC-V hello world example (or simply use a 'main() { puts("Hello Worls"); }' and try to run it on your bare-metal environment without your stubs; it'll crash in the scall.

I did not try it, but running it in a linux test environment might work.


regards,

Liviu

Khem Raj

unread,
Aug 25, 2017, 12:09:26 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
On 8/25/17 9:03 AM, Tommy Murphy wrote:
> I don't know what the general approach is here but doesn't "unknown"
> allow for bare metal or, say, FreeRTOS or mynewt other "lightweight" OSs
> that use the bare metal ABIs and don't introduce their own as linux does
> (System V ABI)?

general approach could be. all baremetal targets are riscv-*-elf
and hosted environments like linux, freebsd etc are riscv-*-<hosted>

Liviu Ionescu

unread,
Aug 25, 2017, 12:11:32 PM8/25/17
to Khem Raj, Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 19:07, Khem Raj <raj....@gmail.com> wrote:
>
> ... second element in triplet denotes vendor not OS

actually it is not a triplet, but a tuple:

<arch>-<vendor>-<os>-<libc/abi>-


regards,

Liviu

Khem Raj

unread,
Aug 25, 2017, 12:17:21 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
On 8/25/17 9:01 AM, Tommy Murphy wrote:
> Well it has multiple ABIs (ilp32, ilp64 etc.) but I suppose that these
> are communicated via -march and -mabi so the  toolchain name doesn't
> need to reflect them?

There are triplets like *-*-linux-gnux32 which indicate intel x32 ABI (
ipl32), and similarily for mips, in my personal opinion its better to
leave them to commandline and let compiler do the right thing. This way
you can have multilibbed toolchain targetting mutliple ABIs, its
convenient for SDKs but end users may find it complex since they usually
ship 1 ABI or may be 2. Having a dedicated naming in triplet lets you
hack autotooled packages based on it. see why gcc introduced
linux-gnueabihf for ARM ( to indicate ARM EAVI with harf-float FP
calling convention), desktop distros ( debian, fedora) use the triplet
quite a bit.

> Also - you seem to agree (with me, Richard) that riscv-*-elf means bare
> metal which contradicts what Liviu's source seems to be claiming (i.e.
> that riscv[xx]-uknknown-elf-gcc) targets linux?
>
> On Friday, 25 August 2017 16:54:36 UTC+1, Khem Raj wrote:
>
> Hopefully
> RISC-V wont have to redefine its ABI completely down the lane, but for
> now rscv-*-elf can mean a ELF based baremetal toolchain for risv
> processors to keep it simple.
>
> --
> You received this message because you are subscribed to the Google
> Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sw-dev+un...@groups.riscv.org
> <mailto:sw-dev+un...@groups.riscv.org>.
> To post to this group, send email to sw-...@groups.riscv.org
> <mailto:sw-...@groups.riscv.org>.
> Visit this group at
> https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit
> https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/83256eb0-ef04-41cc-95e2-339e5665b955%40groups.riscv.org
> <https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/83256eb0-ef04-41cc-95e2-339e5665b955%40groups.riscv.org?utm_medium=email&utm_source=footer>.

Liviu Ionescu

unread,
Aug 25, 2017, 12:21:55 PM8/25/17
to Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille

> On 25 Aug 2017, at 19:03, Bruce Hoult <br...@hoult.org> wrote:
>
> > I really wonder who claimed that riscv[xx]-unknown-elf-gcc was for linux...?
>
> I suspect Liviu misunderstood someone.

please note that in my initial message I stated:

"... the riscv64-unknown-elf-gcc version is intended to generate applications that run in linux environments, and not in bare metal environments (it intentionally mandates the inclusion of libgloss, the library that implements the system calls via ecalls, the kernel traps)."

if you think that implementing system calls via kernel traps is perfectly acceptable in bare-metal embedded applications, then yes, I misunderstood it.


regards,

Liviu

Tommy Murphy

unread,
Aug 25, 2017, 2:08:02 PM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
OK - but what did you expect the default implementations of write() etc. to do when you linked with them without providing your own implementations for your bare metal target platform?

Khem Raj

unread,
Aug 25, 2017, 2:19:09 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com
On Fri, Aug 25, 2017 at 11:08 AM, Tommy Murphy <tommy_...@hotmail.com> wrote:
> OK - but what did you expect the default implementations of write() etc. to
> do when you linked with them without providing your own implementations for
> your bare metal target platform?

right. libgloss is the part that needs to implement the semi hosting APIs
one common target is gdb simulator to test the baremetal apps if gdb-sim
is ported to the given architecture.

>
> On Friday, 25 August 2017 17:08:20 UTC+1, Liviu Ionescu wrote:
>>
>>
>> > On 25 Aug 2017, at 18:58, Tommy Murphy <tommy_...@hotmail.com> wrote:
>> >
>> > Admittedly we do provide our own "syscall" stubs (write() etc.) so maybe
>> > libgloss never gets a look in?
>> > I can't believe that it has simple been luck that allowed things to
>> > work...
>>
>> if you provide your own syscalls, it can't be luck.
>>
>> but create a very basic project, with the Eclipse RISC-V hello world
>> example (or simply use a 'main() { puts("Hello Worls"); }' and try to run it
>> on your bare-metal environment without your stubs; it'll crash in the scall.
>>
>> I did not try it, but running it in a linux test environment might work.
>>
>>
>> regards,
>>
>> Liviu
>>
> --
> You received this message because you are subscribed to the Google Groups
> "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at
> https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit
> https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/a32d1985-3f97-44da-b3f9-2d3f5bf895d5%40groups.riscv.org.

Liviu Ionescu

unread,
Aug 25, 2017, 2:35:20 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 21:08, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> OK - but what did you expect the default implementations of write() etc. to do when you linked with them without providing your own implementations for your bare metal target platform?

fail the link with "missing _write()", to explicitly tell you what to do (i.e. implement this function).

once you know this, but explicitly do not want yet to bother with the implementation, you can add a `c-syscalls-empty.c` file to the project; it includes weak empty implementations, that just return ENOSYS, for all underscore functions. then you can use a small file called `newlib-syscall.c` located in the application part, where customised versions of the syscalls are defined (for example to route STDOUT to the UART, like in libwrap).

I know there is also the possibility to use -spec=nosys (I already added it as an option to the Eclipse RISC-V build plug-in), but I still think that using the `c-syscalls-empty.c` file increases the project readability. and provides an easy path for further retargeting customisation, you only have to copy/paste a function from this file to the application `newlib-syscall.c` and add the desired functionality.

BTW, this strategy is already used in the new projects generated by the RISC-V project wizard, available soon.


regards,

Liviu

Samuel Falvo II

unread,
Aug 25, 2017, 2:35:53 PM8/25/17
to Richard Herveille, Liviu Ionescu, RISC-V SW Dev
On Fri, Aug 25, 2017 at 5:23 AM, Richard Herveille <richard....@roalogic.com> wrote:

riscv64-unknown-elf-gcc uses newlib, which relies on libgloss, which in turn uses BSP (board support package) to implement the syscalls.

You would need to create a BSP for each board/environment.

From your findings, it seems the current BSP targets linux (not my 1st choice for a bare-metal environment).

Can we define a common environment and add a BSP for real bare-metal systems?


Just so I am totally clear and keeping up in the conversation, what things would a BSP offer support for?  Things like missing instructions?  Or, are we looking at something closer in scope to a PC BIOS ROM?

--
Samuel A. Falvo II

Tommy Murphy

unread,
Aug 25, 2017, 2:41:39 PM8/25/17
to RISC-V SW Dev, tommy_...@hotmail.com, richard....@roalogic.com
Thanks - that makes sense to me alright.
So the problem boils down to the fact that the riscv[xx]-unknown-elf-gcc bare metal toolchain builds newlib/libgloss such that it provides system calls inappropriate to a bare metal embedded target?
Not that the riscv[xx]-unknown-elf-gcc toolchain targets linux per se?

BTW - I asked elsewhere but never got anything useful so ... does anybody know what the difference is between compiling with the bare metal rscv[xx]-unknown-elf-gcc toolchain and compiling with the linux riscv[xx]-linux-gnu-gcc toolhain but passing -ffreestanding?
I.e. is there actually a need for separate bare metal and linux toolchains or would the latter suffice for both?

Liviu Ionescu

unread,
Aug 25, 2017, 2:57:16 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 21:41, Tommy Murphy <tommy_...@hotmail.com> wrote:
>
> what the difference is between compiling with the bare metal rscv[xx]-unknown-elf-gcc toolchain and compiling with the linux riscv[xx]-linux-gnu-gcc toolhain but passing -ffreestanding?

`riscv[xx]-linux-gnu-gcc` is built with glibc instead of newlib.

at minimum, `-ffreestanding` adds __STDC_HOSTED__ and you can conditionally compile out some of the code in the libraries, if you have them in source code.

I don't know if `-ffreestanding` does something more in the RISC-V toolchain.

> I.e. is there actually a need for separate bare metal and linux toolchains or would the latter suffice for both?

I would say it is. the linux toolchain should use libc and implement all syscalls via kernel traps. the bare-metal toolchain should use newlib/newlib-nano and by all means do not implement anything via kernel traps.


regards,

Liviu


Liviu Ionescu

unread,
Aug 25, 2017, 3:32:53 PM8/25/17
to Tommy Murphy, RISC-V SW Dev, richard....@roalogic.com

> On 25 Aug 2017, at 21:57, Liviu Ionescu <i...@livius.net> wrote:
>
> `-ffreestanding` adds __STDC_HOSTED__

one small addition:

- `-ffreestanding` adds __STDC_HOSTED__ = 0
- `-fhosted` adds __STDC_HOSTED__ = 1

regards,

Liviu

Liviu Ionescu

unread,
Aug 25, 2017, 3:40:18 PM8/25/17
to Samuel Falvo II, Richard Herveille, RISC-V SW Dev

> On 25 Aug 2017, at 21:35, Samuel Falvo II <sam....@gmail.com> wrote:
>
> ... what things would a BSP offer support for? Things like missing instructions? Or, are we looking at something closer in scope to a PC BIOS ROM?

I think there must be a misunderstanding somewhere.

the most common bare-metal embedded device is a Cortex-M. (at least this is what I'm talking about). what BIOS do you expect to encounter on a Cortex-M device?


regards,

Liviu

Samuel Falvo II

unread,
Aug 25, 2017, 3:48:49 PM8/25/17
to Liviu Ionescu, Richard Herveille, RISC-V SW Dev
On Fri, Aug 25, 2017 at 12:40 PM, Liviu Ionescu <i...@livius.net> wrote:
> I think there must be a misunderstanding somewhere.

Yes; you're responding to me instead of the person who brought up BSPs
in the first place. :)

Palmer Dabbelt

unread,
Aug 25, 2017, 5:18:42 PM8/25/17
to Liviu Ionescu, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille
Sorry this is confusing, but we're really just trying to follow existing tuple conventions here.  Here's what's going on with the existing toolchains we provide:

* riscv64-unknown-linux-gnu-gcc is the full-featured toolchain, which uses glibc as a C library and targets the Linux operating system.  As glibc is not designed for embedded systems, 
* riscv64-unknown-elf-gcc is the embedded toolchain, which uses newlib as a C library and targets no particular operating system.  Since newlib is designed for embedded use, it factors out its implementation of system calls into libgloss.  As we see no reason to have two different system call ABIs we just use the Linux one here.  Note that this isn't a Linux toolchain, as it doesn't have the Linux headers or any of the Linux-specific syscalls, it just follows the same ABI for the system calls it does implement.  The result is that you can run binaries generated by riscv64-unknown-elf-gcc on a Linux system, but we consider that a feature not a bug :).

While I understand you want a toolchain that works with your current compilation flow, I don't think you actually want what you're asking for.  For example, you probably want to use your own implementation of "_start" and your own linker scripts.  For example, newlib's "_start"


assumes that something else has setup the stack, provided "argc" and "argv", etc.  This doesn't make a whole lot of sense in a bare-metal environment.  What you probably want (and what we usually do), is to build with "-nostdlib".  That will provide you with a black canvas so you only get what you ask for.  Note that you can still link against libc by passing "-nostdlib -lc", so things like "printf" will work -- as long as you provide your own implementation of things like "write".  There's examples of how to do this in our SDK


though we use a slightly different mechanism here (we pass --wrap to the linker), so the names of the symbols are a bit different.  We should probably convert

I've gone ahead and created an experimental "riscv64-unknown-none" toolchain.  This toolchain links "libnosys" instead of "libgloss" for system calls, which means that you'll get implementations of system calls that return an error instead of making an "ecall".  You still get newlib's crt0.o here, which as far as I can tell is what happens on other platforms.


There's some other options for what to do in "riscv*-*-none" toolchains:

* Link "-lc" and "crt0.o".  This would get linker errors when calling system calls, but you'll still get "_start" from the C runtime.  It seems odd to provide exactly one useless definition of a standard symbol, so I don't really like this.
* Link "-lc" (and avoid "crt0.o").  I don't really see the point here, as this would just be exactly "-nostdlib -lc".
* Link "crt0.o" (and avoid libc).  That doesn't seem useful.

It'd be great if someone could figure out what other popular ISAs are doing here so we can just match them.

Just to be clear: I don't recommend you use "riscv*-*-none" toolchains at all.  Like I said above: if you're writing bare metal code then you probably want to know exactly what is linked in, so you probably want to just go with "-nostdlib -lc".  At that point "riscv*-*-elf" and "riscv*-*-none" will be exactly the same, so there's no point bothering with the new tuple.

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+unsubscribe@groups.riscv.org.

To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Liviu Ionescu

unread,
Aug 25, 2017, 6:01:29 PM8/25/17
to Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille

> On 26 Aug 2017, at 00:18, Palmer Dabbelt <pal...@dabbelt.com> wrote:
>
> ... you probably want to use your own implementation of "_start" and your own linker scripts. For example, newlib's "_start"
>
> https://github.com/riscv/riscv-newlib/blob/riscv-newlib-2.5.0/libgloss/riscv/crt0.S
>
> assumes that something else has setup the stack, provided "argc" and "argv", etc. This doesn't make a whole lot of sense in a bare-metal environment. What you probably want (and what we usually do), is to build with "-nostdlib". That will provide you with a black canvas so you only get what you ask for. Note that you can still link against libc by passing "-nostdlib -lc", so things like "printf" will work -- as long as you provide your own implementation of things like "write". There's examples of how to do this in our SDK
>
> https://github.com/sifive/freedom-e-sdk/tree/master/bsp/libwrap
>
> though we use a slightly different mechanism here (we pass --wrap to the linker),

I'm afraid your assumptions are only partly true.

- '_start': yes, I do use my own implementation for _start(), together my own linker scripts; on C friendly architectures, like Cortex-M, the Reset_Handler is actually the _start() routine, written in C (or even C++), since the stack was already set by hardware; for RISC-V I use a minimal reset-entry.S, with a small assembly function that loads GP, loads SP and jumps to _start().

- 'linker scripts': real applications rarely can use the default linker scripts; real devices have custom memory maps that need to be defined in the linker scripts

- '-nostdlib': yes & no; in most applications I use only -nostartfiles, together with some workarounds (a few files that reimplement the problematic behaviour); otherwise the default libs are mostly usable; but for super special applications it might be necessary to disable the libs too.

- 'libwrap and the --wrap mechanism': although functional, I think this is way too complicated and labour intensive for regular use, and I cannot recommend it.

- '-lnosys': although I give the user the choice to use it via an optional `--specs=nosys.specs`, I do not recommend it; I prefer an explicit `c-syscalls-empty.c` file in the system part of the application (I already explained the advantages in a previous message)

- 'riscv64-unknown-none': I think not only the name is unfortunate, but mandating 'libnosys' is not necessarily a feature.

> ... It'd be great if someone could figure out what other popular ISAs are doing here so we can just match them.

things are very simple, the most widely used embedded toolchain (arm-none-eabi) simply does... nothing; it does not mandate neither libgloss nor libnosys, the user has the freedom to explicitly choose the one it is needed.

by default, it you use `puts()` in your application, the linker will complain that _write() is not defined, and you know you have to add it.

and, by no means, it does not generate applications that by default use semihosting or kernel traps (which is, in fact, the problem that I wanted the community to be aware of).


regards,

Liviu

Jeremy Herbert

unread,
Aug 26, 2017, 1:49:13 AM8/26/17
to Liviu Ionescu, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille
I mostly follow the RISCV project out of interest of using it someday as a soft core, and I thought I would just chime in. I would agree here with Liviu; at least coming from a bare metal ARM background, if the linker has a known _start (or _write, etc) without me supplying one myself, I wouldn't consider it a bare metal toolchain; I expect a linker error. If I include a big library which calls puts() somewhere, I want the linker to tell me about it. I'm not necessarily saying that this is the best way for it to be in general, but it's still what I personally would expect and want in a bare metal environment. Throwing a linker error is the way it behaves in the ARM world.

I'm not so sure I would go as far as saying that this existing toolchain is designed for Linux, just that it is designed for a system a little more abstracted than a conventional bare metal one. In this case "unknown" is probably appropriate given that it targets an unknown kernel. But I think there should definitely be a "none" toolchain; in fact, it is the one I am most interested in.

Also as a sort of side perspective, I do some teaching of undergraduates. I can totally see that some of them calling puts(), have it compile and link without error, and then be confused when it doesn't actually show up on the serial port or something on the real hardware. I'd much prefer them being confused over a linker error instead ;)

Thanks,
Jeremy
--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.

To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Liviu Ionescu

unread,
Aug 26, 2017, 2:07:44 AM8/26/17
to Jeremy Herbert, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille

> On 26 Aug 2017, at 08:49, Jeremy Herbert <jerem...@gmail.com> wrote:
>
> ... some of them calling puts(), have it compile and link without error, and then be confused when it doesn't actually show up on the serial port or something on the real hardware.

in my test environment things were even worse, the application crashed on the very first line when calling puts(); it took me some good efforts to step through the assembly code to finally discover that the execution ended in a `ecall`. at first I was quite puzzled and I could not believe it, I though I did something wrong while building the toolchain. then I studied the build configurations and discovered the issues with libgloss. I informed the maintainers about my findings and possible solutions, but, to my surprise, I was told that this was the expected behaviour :-(

> I'd much prefer them being confused over a linker error instead ;)

absolutely.

regards,

Liviu

Angelo Bulfone

unread,
Aug 26, 2017, 2:31:21 AM8/26/17
to Liviu Ionescu, Jeremy Herbert, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille
I've been following this discussion for a while. Coming from the other side of things: OS Development rather than embedded development, I'd rather have clear documentation of the SBI than a presupplied implementation of puts. Maybe I have a RISC-V CPU hooked up to a graphics card and I want to render the text on a display. On x86, I have 2 choices for output with minimal setup and a third for not much more work. That's a 33% change that some builtin function will give the right response. Add in the possibilities of printing to multiple outputs at once and you're down to a 11% chance. Alternatively, the compiler can politely ask me what I want.
In a way, this debate feels like static vs dynamic typing or manual vs managed memory but on the hardware level. Writing for the bare hardware is not a domain where you want everything done for you. If they are, then you're not writing a supervisor anymore.
For the record, the domain I'm coming from doesn't even provide memcpy for you. If copying blocks of memory from one address to another is too high level, then printing to something called a "display" certainly is. Oh wait, you say it's a "serial port" and not a "display"? What if I wanted to write to a "display"? In that case I'd have to do it myself anyway and throw out the provided implementation.

\rant
Long story short: a toolchain for supervisors should not use the ABI. The ABI is provided *by* the supervisor, not *for* the supervisor.

--
You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
To post to this group, send email to sw-...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.

Michael Clark

unread,
Aug 26, 2017, 3:03:41 AM8/26/17
to Angelo Bulfone, Liviu Ionescu, Jeremy Herbert, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille

> On 26 Aug 2017, at 6:31 PM, Angelo Bulfone <mbul...@gmail.com> wrote:
>
> I've been following this discussion for a while. Coming from the other side of things: OS Development rather than embedded development, I'd rather have clear documentation of the SBI than a presupplied implementation of puts. Maybe I have a RISC-V CPU hooked up to a graphics card and I want to render the text on a display. On x86, I have 2 choices for output with minimal setup and a third for not much more work. That's a 33% change that some builtin function will give the right response. Add in the possibilities of printing to multiple outputs at once and you're down to a 11% chance. Alternatively, the compiler can politely ask me what I want.
> In a way, this debate feels like static vs dynamic typing or manual vs managed memory but on the hardware level. Writing for the bare hardware is not a domain where you want everything done for you. If they are, then you're not writing a supervisor anymore.
> For the record, the domain I'm coming from doesn't even provide memcpy for you. If copying blocks of memory from one address to another is too high level, then printing to something called a "display" certainly is. Oh wait, you say it's a "serial port" and not a "display"? What if I wanted to write to a "display"? In that case I'd have to do it myself anyway and throw out the provided implementation.
>
> \rant
> Long story short: a toolchain for supervisors should not use the ABI. The ABI is provided *by* the supervisor, not *for* the supervisor.

Agree. libc is at a high level of abstraction compared to bare metal, given it assumes a filesystem.

linux, bbl and the proxy kernel are all bare metal apps and they all compile using riscv-unknown-elf. Indeed linux kernel can use the full linux host compiler but uses -nostdinc and invokes the linker directly with a custom linker script so start files or libc stubs are not an issue. These bare metal projects all include their own memory copy and string functions and don’t rely on libc at all. Expecting stdio in a baremetal environment is not a typical requirement. Linux uses printk, which buffers until an output device has been initialised. What is one supposed to do for fopen? If one is implementing a filesystem in a baremetal app then providing the libc ABI is the least of ones worries.

In fact, if riscv-pk was split into riscv-pk and riscv-bbl (the commit history infers that such a split could happen), then the machine and util directories which are shared between the proxy kernel and bbl could be factored into a riscv-baremetal repo that provides RISC-V specific functions for machine initialisation from processor reset and trap handling, fp emulation, misaligned accesses and what not. A riscv-baremetal repo factored out from riscv-pk would be more useful than a new toolchain, given it is possible to get what one needs simply with compiler flags. A RISC-V bare metal app is of course most likely going to be a bbl payload after all, or be derived from riscv-pk/bbl:

- https://github.com/riscv/riscv-pk/tree/master/machine
- https://github.com/riscv/riscv-pk/tree/master/util

> On Fri, Aug 25, 2017 at 11:07 PM Liviu Ionescu <i...@livius.net> wrote:
>
> > On 26 Aug 2017, at 08:49, Jeremy Herbert <jerem...@gmail.com> wrote:
> >
> > ... some of them calling puts(), have it compile and link without error, and then be confused when it doesn't actually show up on the serial port or something on the real hardware.
>
> in my test environment things were even worse, the application crashed on the very first line when calling puts(); it took me some good efforts to step through the assembly code to finally discover that the execution ended in a `ecall`. at first I was quite puzzled and I could not believe it, I though I did something wrong while building the toolchain. then I studied the build configurations and discovered the issues with libgloss. I informed the maintainers about my findings and possible solutions, but, to my surprise, I was told that this was the expected behaviour :-(
>
> > I'd much prefer them being confused over a linker error instead ;)
>
> absolutely.
>
> regards,
>
> Liviu
>
> --
> You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/436AB35A-DB1E-4F09-AF1A-E8D0FC0B4A49%40livius.net.
>
> --
> You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/CAGP_OL5GQke_GLVeOSnmHj6kBFhLS-xVhCFeP7fAN9FM0fRsvQ%40mail.gmail.com.

Richard Herveille

unread,
Aug 26, 2017, 3:31:46 AM8/26/17
to Jeremy Herbert, Liviu Ionescu, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev, Richard Herveille

I don’t think anyone is arguing against what you’re saying here.

We do provide a custom _start() and _write(), etc.

I do agree with Liviu that the toolchain should probably not include libgloss. Or if it does, make weak versions of the 18 or so calls it implements.

What we don’t agree on is that riscv[xx]-unkown-elf-gcc is not suitable for bare-metal projects. We use it all the time and it does the job just fine.

If the toolchain builds without libgloss, then it’s what we all want, right?

 

Richard

 

 

 

 

Richard Herveille

Managing Director

Phone +31 (45) 405 5681

Cell +31 (6) 5207 2230

richard....@roalogic.com

 

Angelo Bulfone

unread,
Aug 26, 2017, 3:55:11 AM8/26/17
to Richard Herveille, Jeremy Herbert, Liviu Ionescu, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev
I can use x86_64-unknown-linux-gnu with -nostdlib on baremetal and it works just fine. But you're not supposed to because there's no safety net if you type something wrong and accidentally use something you shouldn't. That's why the OSDev wiki has an entire page on *not using* *-*-linux-gnu: http://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F.

Liviu Ionescu

unread,
Aug 26, 2017, 4:09:19 AM8/26/17
to Richard Herveille, Jeremy Herbert, Palmer Dabbelt, Bruce Hoult, Tommy Murphy, RISC-V SW Dev

> On 26 Aug 2017, at 10:31, Richard Herveille <richard....@roalogic.com> wrote:
>
> If the toolchain builds without libgloss, then it’s what we all want, right?

I already removed the reference to libgloss in GNU MCU RISC-V GCC, so the next release will be fine anyway.

as soon as SiFive tags the new version, I'll run my build scripts and publish the binaries, for anyone who needs them.


regards,

Liviu




Tommy Murphy

unread,
Aug 26, 2017, 5:27:03 AM8/26/17
to RISC-V SW Dev
That seems like a non sequitur.
Richard is talking about riscv[xx]-unknown-elf but you're talking about an x86 Linux toolchain.
I don't get your point.

Surely riscv[xx]-unknown-elf-gcc IS a bare metal toolchain if we (a) provide our own specific startup, linker script, write() etc and (b) ignore any libgloss issues for now (even if there may be an argument to change or fix(?) these)?

Certainly lots of people are using it in practice as such right now.
It can't simply be luck that it works?

Some of the discussion here seems to me like esoteric hair splitting that skirts/avoids the issue of simply declaring clearly whether or not it is a bare metal toolchain or at least suitable for use as such.

I think it is - not least of all because I'm using it successfully as such (admittedly with our own HAL providing startup code, ld scripts etc).
Does anybody (still?) think that it's not and, if so, why?

Regards
Tommy

Jeremy Herbert

unread,
Aug 26, 2017, 6:10:48 AM8/26/17
to Liviu Ionescu, Palmer Dabbelt, Richard Herveille, Bruce Hoult, RISC-V SW Dev, Tommy Murphy
Yeah, wasn't trying to argue as much as give another perspective :)

All I would want is a tool chain which complains if I don't define _start (and others) myself without adding flags to enable this behavior; it should be the default with flags to turn it off i.e. -lnosys like ARM. That makes it bare metal for me. The name is unimportant :)

Thanks,
Jeremy
Reply all
Reply to author
Forward
0 new messages