Seuls les membres ayant 30 points peuvent parler sur le chat.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Complete C standard library
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Complete C standard library

Posté le 19/08/2018 19:31

Motivation
Until now there was no complete C standard library (aka libc) available for the Casio calculators. Although some parts of this library have been provided by fxlib and gint, there was no libc implementation complying with the standard and compatible with the sh3eb architecture ready to use.

To change that, I decided to port newlib to the Casio CPU. Newlib is an alternative libc implementation intended for use on embedded systems.


Alpha
Follow this link and click the download button in the top right corner:

>>> v1.1 <<<


Instructions on how to install newlib alongside with gcc (big shout-out to Lephé):

Compiler sous Linux avec GCC


Features for Casio fx9860g calculators:
* C standard library libc
printf implementation to print text to the display
→ Dynamic allocation of memory using malloc and free
→ Memory manipulation using memcpy, memcmp, memset etc.
→ String manipulation using strcpy, strcmp, strstr, strtok
→ ...
* Math library libm
→ Floating point arithmetics
→ ...
* Automatic library and include path recognition after installation
* Basic Casio features:
→ implementation of GetKey, Bdisp_AllClr_DDVRAM, Bdisp_PutDisp_DD, Print and locate without fxlib (but you can use it if you want)


Code
To contribute or get all those bleeding edge features, see the code including all further information:

libc (my GitLab repository)


The project you find in my repository is a fork of the official newlib repository. To make it easier for everyone to follow, I try to keep a clean git history. That means that all my changes are located on a dedicated branch with meaningful commits.

I also try to keep the changes to the upstream library minimal. That increases maintainability a lot.


Contributing
If you have a ideas, feature request, found a bug or simply want to contribute, just send me a message and you're in! You can also create Issues and Merge Requests directly in the repository. As in every OpenSource project: merge requests welcome!


Pages : 1, 2, 3, 4, 5, 6, ... 10Suivante
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 19/08/2018 19:57 | #


Since many use gint, I also look forward to collaborate with Lephe. I think for now, the libc is conflicting with gint in several aspects. On a later stage, the incomplete libc implementation might even be replaced with newlib.
Stop starting~ Start finishing~
LephenixnoirHors ligneAdministrateurPoints: 16397 Défis: 140 Message

Citer : Posté le 19/08/2018 20:06 | #


Good news! My current compilers (sh3eb-elf and sh4eb-nofpu-elf) need to be recompiled before I can try out this port, I'll do it asap.

Let's see about the issues you pointed out with gint.

As expected it conflicts with gint.
* internals/stdio.h has to be renamed
* the includes of gprint.c and dprint.c have to be changed accordingly
* key_t in keyboard.h has to be renamed

I probably need to strip everything libc-related from gint's sources to avoid conflicts. Out of curiosity, where is key_t used newlib's sources?

One particular error I encountered is
newlib/libc/sys/sh/syscalls.c:56: undefined reference to 'end'
In syscalls.c I found
extern char end; /* Defined by the linker */
Tbh, I have no experience whatsoever with linker scripts, maybe you have an idea what to do here.

When using gint I roll my linker scripts so I understand what's going on here. Basically this symbol is calculated and exported by the linker and will typically correspond to the end of some region, maybe code/text/data. It looks like newlib's sbrk() implementation uses it as a region limit for the heap.

Also, by looking at this sbrk(), I can tell that a certain memory layout is assumed, which may not really work on our calculators. Besides, there is no sbrk() in the system, nor any kind of read() or write(). You can tell from the file newlib/libc/sys/sh/sys/syscall.h that a certain kind of syscall procedure is assumed. On Linux, from syscall(2), I know that the syscall instruction is trapa #0x17, here it seems to be trapa #34.

I expect all of this to be configurable and I think we should try to cut off too-low-level code for now. We could, for instance, use a dummy implementation of write() that does nothing and go with sprintf() for a start. We don't have syscalls, we don't have file I/O and we don't have an Unix-like API so we can only get something minimalist.

-

I'm currently in the process of rewriting gint from the ground up for the purpose of porting it to fx-cg50. Your libc may be of use here, as well. All of this is happening on the compat branch of gint's repo, which I invite you to build with although it's not production-ready.

I will create a repo for my gint test/control application, which does nothing special now (a lot of tests that are commented out in a single file) but will expand into a full test add-in when I get the screen drawing back, hopefully in the incoming weeks.

The compat branch is quite minimalist now and has absolutely nothing of a libc except for src/core/memory.c which exports a memcpy() and a memset() functions. Both will eventually be renamed. They are the only dependency from gint to the libc so I plan on keeping the implemented in gint to leverage the dependency (otherwise we'd have a dependency cycle since the libc will certainly depend on gint for timer, date and time, things like this).
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 19/08/2018 20:31 | #


Lephenixnoir a écrit :
Out of curiosity, where is key_t is newlib's sources?


I don't really know what it is used for, but it is defined here:
sh3eb-elf/include/sys/types.h:195:
typedef    __key_t        key_t;        /* IPC key */


Lephenixnoir a écrit :
It looks like newlib's sbrk() implementation uses it as a region limit for the heap


I tried to add a symbol at the end of what I expected to be heap in the linker script. Even if it's the wrong address, the linker error persists.
PROVIDE (end = .);

As I mentioned, until now I did not change a single line of code and mapped sh3eb to the existing sh. The most important code is provided there: the implementation for setjmp. I think the rest of the interface to the underlying platform (the Board Support Package, BSP) which contains the syscalls is not as important. We need functions like memalloc etc. and the rest will be stubs for now.

Lephenixnoir a écrit :
libc will certainly depend on gint for timer, date and time, things like this


To be honest I would like to avoid having libc depend on gint (or any library infact). I'd prefer moving the code over to the libc (I'd give you the credit ofc) and have gint depend on libc which feels much more natural to me. Frankly, I do not anyone expect to use libc without gint, but it just seems cleaner to me that way... What do you think?

However, it's a long way before we need to discuss this

PS.: How do I write inline code o.O?
@Breizh_craft works like a charm, thanks!

Stop starting~ Start finishing~
Breizh_craftHors ligneModérateurPoints: 1001 Défis: 7 Message

Citer : Posté le 19/08/2018 20:35 | #


You can use backticks (`) or [inlinecode]code[/inlinecode] to write inline code ^^.
Informagicien professionnel, prestidigitateur système. Tout est possible.
LephenixnoirHors ligneAdministrateurPoints: 16397 Défis: 140 Message

Citer : Posté le 19/08/2018 20:54 | #


Memallox a écrit :
I tried to add a symbol at the end of what I expected to be heap in the linker script. Even if it's the wrong address, the linker error persists.
PROVIDE (end = .);

You almost got it right. On SuperH all C names correspond to symbols with a leading underscore. Certainly PROVIDE (_end = .); would be better.

I think the rest of the interface to the underlying platform (the Board Support Package, BSP) which contains the syscalls is not as important. We need functions like memalloc etc. and the rest will be stubs for now.

I have not yet looked at the documentation for now, but the page you linked will definitely be useful!

To be honest I would like to avoid having libc depend on gint (or any library infact). I'd prefer moving the code over to the libc (I'd give you the credit ofc) and have gint depend on libc which feels much more natural to me. Frankly, I do not anyone expect to use libc without gint, but it just seems cleaner to me that way... What do you think?

This is a difficult question indeed. So far I see gint as a kernel, which is why I suggested that the libc depends on gint. But it would prevent the library from being used anywhere else... which we'd like to avoid, if possible!

We could let gint depend on the libc, but "there's no need" since gint does really not use the libc functions at all. I've ported around half of it and it still needs just memcpy(), the rest of the core memory functions being required by gcc to build in the first place.

However, it's a long way before we need to discuss this

Yes, and we can always add a configure switch to build versions that actually depend on each other.

Something else I probably ought to mention is that gint provides its linker script and C runtime. This may, again, clash with the standard library. A possible solution would be to edit gint's linker script to allow linking with newlib if newlib require any linking facility, and requiring that the user of your libc provides its own C runtime, leaving the choice to use gint or a more traditional, fxlib-based environment with a crt0.s that we've been using for ages.
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 19/08/2018 22:25 | #


L a écrit :
Certainly PROVIDE (_end = .); would be better.


You're absolutely right, should have known that xD.

Lephenixnoir a écrit :
So far I see gint as a kernel, which is why I suggested that the libc depends on gint. But it would prevent the library from being used anywhere else... which we'd like to avoid, if possible!


That makes perfectly sense to me. From that perspective newlib should indeed depend on gint. The configure switch is what I would have suggested as well, good call!

Lephenixnoir a écrit :
Something else I probably ought to mention is that gint provides its linker script and C runtime


I don't know what you mean by C runtime, but later on, libc should not require a specific linker script (I think it's only used by _sbrk anyway). I intend to have newlib compatible for both fxlib (basic feature set) and gint (enhanced feature set).
Stop starting~ Start finishing~
LephenixnoirHors ligneAdministrateurPoints: 16397 Défis: 140 Message

Citer : Posté le 19/08/2018 22:34 | #


I don't know what you mean by C runtime, but later on, libc should not require a specific linker script (I think it's only used by _sbrk anyway). I intend to have newlib compatible for both fxlib (basic feature set) and gint (enhanced feature set).

Basically the C runtime is the small program that loads the add-in into memory. In embedded systems such as our calculators, a typical task for it is to initialize the RAM sections by copying the contents from the add-in file which is mapped in ROM.

When running fxlib under the SDK the INIT_ADDIN_APPLICATION() function is assigned to that task. You can see that the default places it in the pretext section which is a very strong hint.

When using fxlib with GCC, it is common to use a small assembler script called crt0.s (stands for C runtime), for which the source is on the path of being lost. I think Kristaba's behind this. (Kristaba is a formerly-active member of the community who worked on a POSIX-compliant kernel going with the name of FiXOS. He and the people helping him could not finish the kernel but they did a lot of interesting stuff.)

When using gint, the C runtime resembles a kernel's initialization phase. The program is loaded to memory, then gint does a bit of hardware detection and starts initializing its drivers.

Cakeisalie5 would argue that in a modern, well-written system the C runtime would be provided by the libc. Honestly I don't know how we could pull this out and I suggest that we leave the C runtime to the library user
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 19/08/2018 22:57 | #


Oh thanks for the insight! Newlib indeed contains newlib/libc/sys/sh/crt0.S which I did not have a look into yet. I guess we could replace that with our own implementation. I have to think about all this... (*-* )

About your compat branch: I could build it, but I have to have a deeper look into it another day.
Stop starting~ Start finishing~
Dark stormHors ligneMembre d'honneurPoints: 10853 Défis: 176 Message

Citer : Posté le 19/08/2018 23:15 | #


About FiXOS, I remember that Kristaba has made his own libc. Sources can be found here. I don't know if it's relevant, but it can help. FiXOS sources are on the same GitLab instance.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
LephenixnoirHors ligneAdministrateurPoints: 16397 Défis: 140 Message

Citer : Posté le 19/08/2018 23:23 | #


Looking at lines 66..119 which correspond to SH4 and lower, this is pretty much the same thing as our usual assembly file.

    70        mov.l    stack_k,r15

Looks like newlib loads its own stack pointer (symbol _stack). Normally this is not necessary for us as the system that launches the add-in sets one for us.

Since we don't have an FPU, the rest of the script just clears the BSS section, calls main and exits, which every of our C runtimes do. I think we can safely use our own initialization instead of this one.

Also note that the _end symbol is referenced here as the end of the BSS section. Symbol _stack is probably from the linker script as well.

There doesn't seem to be any linker script in the newlib directory, but there clearly are in libgloss, which -I didn't expect it- turns out to be part of newlib as well:

Newlib is now divided into two parts. The main newlib directory contains the bulk of the code for the two main libraries, libc and libm, together with any architecture specific code for particular targets.

The libgloss directory contains code specific to particular platforms on which the library will be used, generally referred to as the Board Support Package (BSP). Any particular target architecture may have multiple BSPs, for example for different hardware platforms, for a simulator etc.

libgloss/sh contains in fact just linker scripts - 4 of them. Looking at what they contain, I think gint's linker scripts can usually provide all the functionality; the usual gcc + fxlib environment can as well. With a bit of tweaking I expect this part to actually work.

So, to sum it up, I suggest that:
- We drop most of their crt0.S and include the little remaining functionality in our init scripts
- Same for the linker scripts (mainly some section names to add in the right places)

Gonna blow up everything
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 20/08/2018 18:20 | #


Wow this is getting fun xD

Lephenixnoir a écrit :
So, to sum it up, I suggest that:
- We drop most of their crt0.S and include the little remaining functionality in our init scripts
- Same for the linker scripts (mainly some section names to add in the right places)


To be honest I try to keep the changes to the library at a necessary minimum. I'll be glad later on when I need to maintain the library and rebase the upstream project from time to time to keep it up-to-date. That means that I try to use the existing crt0.S and linker script and change (delete) the parts that need to be changed (deleted) (at least that's my plan).

As for the gint support: I think it would be best to get the std lib up and running first (basic feature set) and then we will see what will depend on what and how
Stop starting~ Start finishing~
LephenixnoirHors ligneAdministrateurPoints: 16397 Défis: 140 Message

Citer : Posté le 20/08/2018 18:43 | #


To be honest I try to keep the changes to the library at a necessary minimum. I'll be glad later on when I need to maintain the library and rebase the upstream project from time to time to keep it up-to-date.

I was wondering about that. If you plan to maintain it seriously then you're right, we need to change a minimum of code!

For the C runtime and linker scripts, we actually don't need to change the sources. I understand that we have settled on leaving the C runtime out of the libc, is it right? In this case we need only alter the existing runtimes (fxlib/gcc or gint or whatever!) to support the "features" required by newlib. Basically this is specially-provided symbols or specific section names. Then we "ignore" newlib's runtime; we just don't compile or link with it.

Memallox a écrit :
As for the gint support: I think it would be best to get the std lib up and running first (basic feature set) and then we will see what will depend on what and how

You're right, but you will need a runtime to test out the basic feature set of the library in an add-in! I strongly suggest starting with fxlib/gcc because it's stable and easy to roll with.
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 20/08/2018 19:33 | #


Unrelated question: is there a simulator for the fx9860GII like the one shipped with the Casio SDK available for linux? If not, do you know any other way to debug my programs?
Stop starting~ Start finishing~
ZezombyeHors ligneRédacteurPoints: 1640 Défis: 13 Message

Citer : Posté le 20/08/2018 19:35 | #


Yes :
- There is a free emulator, however it is on OS 1.00: https://www.planet-casio.com/Fr/logiciels/voir_un_logiciel_casio.php?showid=19
- Casio provides the Manager PLUS emulator, with a trial period of 90 days. Drak has done a tutorial on how to set up a VM to have infinite trial period: https://www.planet-casio.com/Fr/forums/topic15178-1-%C3%89mulez-gratuitement-une-Casio-Graph-75+-sur-votre-ordinateur.html
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 20/08/2018 19:56 | #


Thanks Zezombye! I fear that the first tool is for "Graph 75, 85, 95 seulement" and second one is for Windows in a VM which is a very suboptimal solution for me since I develop on Linux. Additionally I don't know if "Casio Graph 75+" covers my Casio fx9860GII. To be honest, I doubt so.
Stop starting~ Start finishing~
ZezombyeHors ligneRédacteurPoints: 1640 Défis: 13 Message

Citer : Posté le 20/08/2018 20:03 | #


fx-9860GII is just the international name of the Graph 35 (or graph 75, I don't remember). Either way it's a monochrome calc, so it should be compatible with the emulators.

If you develop on linux, then all the emulators are on windows either way. I think you could run them on wine though, the VM is just to bypass the trial period.
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 20/08/2018 20:21 | #


Oh I didn't know that, thank you!

Zezombye a écrit :
all the emulators are on windows either way

What a pity!

Ajouté le 20/08/2018 à 20:24 :
I ran first tests (commit 4a6c165f):

Using the fxlib.h I get a nasty linker errors (section overlap) which I don't know how to resolve.

Using gint I can get malloc, strcpy and free to work. I did use Lephé's (modified) linker script.

For both tests I used the linker scripts and/or crt0.s files of gint/fxlib.
Stop starting~ Start finishing~
Dark stormHors ligneMembre d'honneurPoints: 10853 Défis: 176 Message

Citer : Posté le 20/08/2018 20:26 | #


What a pity!

You're right. Kristaba also started a long time ago a port of QEmu for the fx9860 Series, but it was stopped before the first visible results has been produced…
Here is the code
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
ZezombyeHors ligneRédacteurPoints: 1640 Défis: 13 Message

Citer : Posté le 20/08/2018 20:26 | #


What errors exactly are you having?
Divers jeux : Puissance 4 - Chariot Wars - Sokoban
Ecrivez vos programmes basic sur PC avec BIDE
MemalloxHors ligneMembrePoints: 161 Défis: 0 Message

Citer : Posté le 20/08/2018 20:32 | #


sh3eb-elf-g++ -c src/cryptfx.cpp -o build/cryptfx.cpp.o -m3 -mb -ffreestanding -Iinclude -O2 -std=c++11

sh3eb-elf-gcc -o build/cryptfx.elf build/cryptfx.cpp.o -m3 -mb -ffreestanding -Iinclude -O2 -std=c11 -T ld/cryptfx.ld -Llib  -lc-lgcc -lfx

.../ld: section .eh_frame LMA [0000000000301dd4,0000000000301e27] overlaps section .data LMA [0000000000301dd4,000000000030260f]
.../ld: warning: section`.bss' type changed to PROGBITS

Stop starting~ Start finishing~
Pages : 1, 2, 3, 4, 5, 6, ... 10Suivante

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2019 | Il y a 37 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd