Open mMerlin opened 8 years ago
Hey Phil,
just a quick note, how fast do you want the pins to toggle? I think I once read somewhere that 300kHz is pretty much the max, though take that with a big grain of salt ;)
On 17-10-15 03:41, Phil Duby wrote:
Can someone help me out please! I am out of my previous areas here, and do not know the right question to ask, or the right place to ask it. What I currently want, is to create a program that will run standalone (no OS) on a A20-OLinuXino-Micro-4GB https://www.olimex.com/Products/OLinuXino/A20/A20-OLinuXino-MICRO-4GB/ board, that needs to use (at least) some standard math libraries. Eventually, I will want to load it into NAND, and run it on powerup, but for now I am trying to manually load it (loady) from the U-Boot https://github.com/linux-sunxi/u-boot-sunxi/wiki serial 'console', after booting from an SD card. Standalone is needed, because the linux distro level access to the hardware GPIO ports seems not very flexible, when working with more than one bit at a time, and quite slow. Too slow for the target application, and I did not really want to try modifying / adding a kernal module just to see if that would be fast enough.
I have been able to create bootable U-Boot images on SD cards from the repo, either building directly from the linux-sunxi http://linux-sunxi.org/Main_Page distro that was supplied with the board, or by cross-compiling from a Fedora 21 machine. Same for the standalone hello_world program that came in the examples for U-boot, which can be loaded and run from the U-Boot console. My current testing does not use any math library. Just stdio and printf, to try to get the build process right.
Starting from, and simplifying, the hello_world standalone example and Makefile provided with the U-Boot sources, I created a minimal program, and a script to use fairly minimal build options, that still runs successfully when loaded from U-Boot.
I created a standard hello_world program, plus a script to use as similar as possible options to the the U-Boot standalone example, while still being able to execute it normally from a linux shell.
I then tried to adjusted the build options to replicate the result from the initial standalone example program. That is, being able to load and run it from the U-Boot 'console'. So far without success. With the latest test, executing the program from the console fails with:
software interrupt pc : [<48000008>] lr : [<48000008>] sp : 7fb66da8 ip : 00000000 fp : 00000000 r10: 00000002 r9 : 7fb66f0c r8 : 7fb67778 r7 : 7ffbbaf8 r6 : 00000001 r5 : 7fb6777c r4 : 48000000 r3 : 00000000 r2 : 7fb6777c r1 : 7fb6777c r0 : 00000001 Flags: nZCv IRQs off FIQs off Mode SVC_32 Resetting CPU ... Since the start point is (supposed to be) 0x48000000, that is right at the beginning.
For all cases, the procedure in the U-Boot console is:
loady go 0x48000000 One of the current differences in the build paths, is the U-Boot environment is built with soft floating point. Changing to hard there fails because the needed libstubs.o is currently built with soft. Trying to build the standard program with soft in the linux environment complains about mismatch as well. Something to look at later.
Am I missing something obvious that is typically needed to build freestanding programs that are to run without and OS? Is it something that is specific to the ARM processor or board being used? Do I need to include something extra in the program to reference (again) something from the U-Boot code tree?
standalone hello_world.c for U-Boot environment
/*
- Simple hello_world program to check creation of freestanding program to be run
- standalone (without OS) from u-boot *
- variant to check how the u-boot standalone programs are built */
include
int main (void) { printf ("Hello World\n"); return (0); }
freestanding hello_world.c for sunxi environment
/*
- Simple hello_world program to check creation of freestanding program to be run
- standalone (without OS) from u-boot */
include
int main (void) { printf ("Hello World\n"); return (0); }
build script for U-Boot environment
! /bin/bash
HW="hello_world"
clean
rm -f$HW $HW.o$HW.d$HW.s$HW.i$HW.su$HW.bin
FLOATA="soft" INCLS="-I/home/olimex/u-boot-sunxi/include\ -I/home/olimex/u-boot-sunxi/arch/arm/include" OBJS="$HW.o\ /home/olimex/u-boot-sunxi/examples/standalone/libstubs.o" EGRP= LPATHS= LIBS=
LNKOPTS="-Ttext 0x48000000" WARNINGS= MACH="-marm -mfloat-abi=$FLOATA" DIAG= EMBD="-ffreestanding" DEFS="-DKERNEL" CMPOPTS=
set -x
compile
gcc -c$CMPOPTS $MACH $EMBD $DIAG $WARNINGS $DEFS $INCLS \ $HW.c -o$HW.o echo
link
ld.bfd -static$LNKOPTS $OBJS $LPATHS -o$HW $LIBS $EGRP echo
loadable binary
objcopy -O binary$HW $HW.bin
base build script for sunxi environment
! /bin/bash
HW="hello_world"
clean
rm -f$HW $HW.o$HW.d$HW.s$HW.i$HW.su$HW.bin
FLOATA="hard" INCLS= OBJS="/usr/lib/arm-linux-gnueabihf/crt1.o\ /usr/lib/arm-linux-gnueabihf/crti.o\ /usr/lib/gcc/arm-linux-gnueabihf/4.6/crtbeginT.o\ $HW.o" EGRP="--end-group\ /usr/lib/gcc/arm-linux-gnueabihf/4.6/crtend.o\ /usr/lib/arm-linux-gnueabihf/crtn.o" LPATHS="-L/usr/lib/gcc/arm-linux-gnueabihf/4.6\ -L/usr/lib/arm-linux-gnueabihf\ -L/usr/lib\ -L/lib/arm-linux-gnueabihf\ -L/usr/lib/arm-linux-gnueabihf" LIBS="--start-group -lgcc -lgcc_eh -lc"
LNKOPTS="-Ttext 0x48000000" WARNINGS= MACH="-marm -mfloat-abi=$FLOATA" DIAG= EMBD="-ffreestanding" DEFS="-DKERNEL" CMPOPTS=
set -x
compile
gcc -c$CMPOPTS $MACH $EMBD $DIAG $WARNINGS $DEFS $INCLS \ $HW.c -o$HW.o echo
link
ld.bfd -static$LNKOPTS $OBJS $LPATHS -o$HW $LIBS $EGRP echo
loadable binary
objcopy -O binary$HW $HW.bin
current modified build script for sunxi, to run from U-Boot console
! /bin/bash
HW="hello_world"
clean
rm -f$HW $HW.o$HW.d$HW.s$HW.i$HW.su$HW.bin
FLOATA="hard" INCLS= OBJS="$HW.o" EGRP= LPATHS="-L/usr/lib/gcc/arm-linux-gnueabihf/4.6\ -L/usr/lib/arm-linux-gnueabihf\ -L/usr/lib\ -L/lib/arm-linux-gnueabihf\ -L/usr/lib/arm-linux-gnueabihf" LIBS="--start-group -lgcc -lgcc_eh -lc"
LNKOPTS="-Ttext 0x48000000" WARNINGS= MACH="-marm -mfloat-abi=$FLOATA" DIAG= EMBD="-ffreestanding" DEFS="-DKERNEL" CMPOPTS=
set -x
compile
gcc -c$CMPOPTS $MACH $EMBD $DIAG $WARNINGS $DEFS $INCLS \ $HW.c -o$HW.o echo
link
ld.bfd -static$LNKOPTS $OBJS $LPATHS -o$HW $LIBS $EGRP echo
loadable binary
objcopy -O binary$HW $HW.bin
output from script for the U-Boot environment
|+ gcc -c -marm -mfloat-abi=soft -ffreestanding -DKERNEL -I/home/olimex/u-boot-sunxi/include -I/home/olimex/u-boot-sunxi/arch/arm/include hello_world.c -o hello_world.o
- echo
- ld.bfd -static -Ttext 0x48000000 hello_world.o /home/olimex/u-boot-sunxi/examples/standalone/libstubs.o -o hello_world ld.bfd: warning: cannot find entry symbol _start; defaulting to 48000000
- echo
objcopy -O binary hello_world hello_world.bin |
output from base script for the U-Boot environment
|+ gcc -c -marm -mfloat-abi=hard -ffreestanding -DKERNEL hello_world.c -o hello_world.o
- echo
- ld.bfd -static -Ttext 0x48000000 /usr/lib/arm-linux-gnueabihf/crt1.o /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/gcc/arm-linux-gnueabihf/4.6/crtbeginT.o hello_world.o -L/usr/lib/gcc/arm-linux-gnueabihf/4.6 -L/usr/lib/arm-linux-gnueabihf -L/usr/lib -L/lib/arm-linux-gnueabihf -L/usr/lib/arm-linux-gnueabihf -o hello_world --start-group -lgcc -lgcc_eh -lc --end-group /usr/lib/gcc/arm-linux-gnueabihf/4.6/crtend.o /usr/lib/arm-linux-gnueabihf/crtn.o
- echo
objcopy -O binary hello_world hello_world.bin |
output from modified script for the U-Boot environment
|+ gcc -c -marm -mfloat-abi=hard -ffreestanding -DKERNEL hello_world.c -o hello_world.o
- echo
- ld.bfd -static -Ttext 0x48000000 hello_world.o -L/usr/lib/gcc/arm-linux-gnueabihf/4.6 -L/usr/lib/arm-linux-gnueabihf -L/usr/lib -L/lib/arm-linux-gnueabihf -L/usr/lib/arm-linux-gnueabihf -o hello_world --start-group -lgcc -lgcc_eh -lc ld.bfd: warning: cannot find entry symbol _start; defaulting to 48000000
- echo
objcopy -O binary hello_world hello_world.bin |
the compiler defaults: gcc -v
Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.6/lto-wrapper Target: arm-linux-gnueabihf Configured with: ../src/configure -v --with-pkgversion='Debian 4.6.3-14' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --enable-checking=release --build=arm-linux-gnueabihf --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf Thread model: posix gcc version 4.6.3 (Debian 4.6.3-14) — Reply to this email directly or view it on GitHub https://github.com/linux-sunxi/u-boot-sunxi/issues/87.
Met vriendelijke groeten, Kind regards, 与亲切的问候
Olliver Schinagl Software Engineer Research & Development Ultimaker B.V.
I think that speed is talking to the ports through the linux interface. I found another reference that said you could get 4 MHz through bare metal. In my testing, I actually got double that. I expect that is because the context was for toggling a single pin (port in a port group), which requires a read, mask, write sequence. For my case, I can write every pin in the group in a single operation. Since it appears that (at the raw hardware level, every read/write memory access to the I/O port location requires (eyeballing on the scope) 62.5 ns, that extra read cuts the maximum toggle rate by half.
For my application, I need to get the overall cycle time in the 100KHz range, which includes control of pins on multiple ports, plus some reasonably intensive math. I've got the hardware pin control setup, actually limited by the access speed of an attached ADC. Now I need to get the math part to work along with that.
For the original query, I am slowly learning more. I found the hidden .{xxxx}.cmd files in …/examples/standalone, so I can recreate libstubs with different options (hardware floating point), but I do not understand what libstubs is doing to facilitate a minimal hello world building to (depending on optimization flags) a 316 byte .bin, while a normal hello world, compile/linked as freestanding and static is over 400K. I have to assume that libstubs is providing accessing to internals of U-Boot, but I have not seen how that works. continuing forward (and sideways).
Can someone help me out please! I am out of my previous areas here, and do not know the right question to ask, or the right place to ask it. What I currently want, is to create a program that will run standalone (no OS) on a A20-OLinuXino-Micro-4GB board, that needs to use (at least) some standard math libraries. Eventually, I will want to load it into NAND, and run it on powerup, but for now I am trying to manually load it (loady) from the U-Boot serial 'console', after booting from an SD card. Standalone is needed, because the linux distro level access to the hardware GPIO ports seems not very flexible, when working with more than one bit at a time, and quite slow. Too slow for the target application, and I did not really want to try modifying / adding a kernal module just to see if that would be fast enough.
I have been able to create bootable U-Boot images on SD cards from the repo, either building directly from the linux-sunxi distro that was supplied with the board, or by cross-compiling from a Fedora 21 machine. Same for the standalone hello_world program that came in the examples for U-boot, which can be loaded and run from the U-Boot console. My current testing does not use any math library. Just stdio and printf, to try to get the build process right.
Starting from, and simplifying, the hello_world standalone example and Makefile provided with the U-Boot sources, I created a minimal program, and a script to use fairly minimal build options, that still runs successfully when loaded from U-Boot.
I created a standard hello_world program, plus a script to use as similar as possible options to the the U-Boot standalone example, while still being able to execute it normally from a linux shell.
I then tried to adjusted the build options to replicate the result from the initial standalone example program. That is, being able to load and run it from the U-Boot 'console'. So far without success. With the latest test, executing the program from the console fails with:
Since the start point is (supposed to be) 0x48000000, that is right at the beginning.
For all cases, the procedure in the U-Boot console is:
One of the current differences in the build paths, is the U-Boot environment is built with soft floating point. Changing to hard there fails because the needed libstubs.o is currently built with soft. Trying to build the standard program with soft in the linux environment complains about mismatch as well. Something to look at later.
Am I missing something obvious that is typically needed to build freestanding programs that are to run without and OS? Is it something that is specific to the ARM processor or board being used? Do I need to include something extra in the program to reference (again) something from the U-Boot code tree?
standalone hello_world.c for U-Boot environment
freestanding hello_world.c for sunxi environment
build script for U-Boot environment
base build script for sunxi environment
current modified build script for sunxi, to run from U-Boot console
output from script for the U-Boot environment
output from base script for the U-Boot environment
output from modified script for the U-Boot environment
the compiler defaults: gcc -v