Hi there,
I’m slowly learning zig and embedded development on my spare time and my, long term, goal is to build a simple SDK for the Nintendo DS, based on libnds.
I already manage to get a very basic and hacky zig example (that you can found here) but it still use gcc arm and blocksds SDK (previously devkitpro) for linking.
My goal is to be able to run my code only with zig build system and package manager.
The first step is to be able to use zig for linking instead of gcc.
So I tried to tranform gcc
args into zig cc
ones, but not sure if I got it the right way.
Here is all the gcc args used for linking and the zig cc
equivalent I used :
arm-none-eabi-gcc -mthumb
=>zig cc -target thumb-freestanding-eabi
. Isfreestanding
the equivalent ofnone
?-mcpu=arm946e-s+nofp
=>-mcpu=arm946e_s
. I don’t know how to specifynofp
option, do you have any idea on how to do that ?-Wl,-Map,zig-nds-sample.map
=>-fmodule-map-file=zig-nds-sample.map
. Not sure about this one .- There was also some
.specs
file which specify astartfile
which is a.o
file that I added to the other.o
file to link. It’s my understanding of what is astartfile
but it may be something else, never worked with.specs
files before. - There was also
link
instruction in the spec files and I added them to the args, it was-T
options pointing to.mem
files.
After a lot of try and error and reading, I still got an error which I don’t fully understand :
ld.lld: error: ./libnds/ds_arm9.ld:7: memory region not defined: ewram
>>> __ewram_end = ORIGIN(ewram) + LENGTH(ewram);
>>>
I never occurred such errors in C, I assumed the EWRAM nds memory region must be somehow initialized. Is this related to the .map
file or the .mem
files ?
Here is the ds_arm9.specs
file :
%include <picolibc.specs>
%rename cc1plus blocksds_cc1plus
%rename cpp blocksds_cpp
%rename link blocksds_link
*cpp:
-D__NDS__ -D__BLOCKSDS__ -DARM9 %(blocksds_cpp)
*cc1_cpu:
-mcpu=arm946e-s+nofp
*cc1plus:
%(cpp) %(blocksds_cc1plus)
*link:
%(blocksds_link) -T %:getenv(BLOCKSDS /sys/crts/ds_arm9.mem) -T %:getenv(BLOCKSDS /sys/crts/ds_arm9.ld) --gc-sections --no-warn-rwx-segments --use-blx
*startfile:
%:getenv(BLOCKSDS /sys/crts/ds_arm9_crt0%O)
*lib:
%(libgcc)
And the picolibc.specs
(BLOCKSDS used picolibc
instead of newlibc
:
%rename link picolibc_link
%rename cc1 picolibc_cc1
%rename cc1plus picolibc_cc1plus
*cc1:
%{!ftls-model:-ftls-model=local-exec} %(picolibc_cc1)
*cc1plus:
%{!ftls-model:-ftls-model=local-exec} %(picolibc_cc1plus)
*link:
%{DPICOLIBC_DOUBLE_PRINTF_SCANF:--defsym=vfprintf=__d_vfprintf} %{DPICOLIBC_DOUBLE_PRINTF_SCANF:--defsym=vfscanf=__d_vfscanf} %{DPICOLIBC_FLOAT_PRINTF_SCANF:--defsym=vfprintf=__f_vfprintf} %{DPICOLIBC_FLOAT_PRINTF_SCANF:--defsym=vfscanf=__f_vfscanf} %{DPICOLIBC_LONG_LONG_PRINTF_SCANF:--defsym=vfprintf=__l_vfprintf} %{DPICOLIBC_LONG_LONG_PRINTF_SCANF:--defsym=vfscanf=__l_vfscanf} %{DPICOLIBC_INTEGER_PRINTF_SCANF:--defsym=vfprintf=__i_vfprintf} %{DPICOLIBC_INTEGER_PRINTF_SCANF:--defsym=vfscanf=__i_vfscanf} %{DPICOLIBC_MINIMAL_PRINTF_SCANF:--defsym=vfprintf=__m_vfprintf} %{DPICOLIBC_MINIMAL_PRINTF_SCANF:--defsym=vfscanf=__m_vfscanf} %(picolibc_link)
*lib:
--start-group %(libgcc) -lc --end-group
And the original command line from a blockds’s sample Makefile :
/opt/wonderful/toolchain/gcc-arm-none-eabi/bin/arm-none-eabi-gcc -o build/console_ansi.elf build/console_ansi/source/main.c.o -mthumb -mcpu=arm946e-s+nofp -L/opt/blocksds/core/libs/libnds/lib -Wl,-Map,build/console_ansi.map -Wl,--start-group -lnds9 -lc -Wl,--end-group -specs=/opt/blocksds/core/sys/crts/ds_arm9.specs
I know that I miss a lot of knowledge in embedded system to fully understand what I’m doing, but if someone can help me it would be awesome.
Thanks for reading me,
Andréas
P.S : Don’t be mad if I don’t answer, I’ll be on vacation in a couple of days.