The best way to learn WrmOS is to use it. So, this article provide step-by-step manual how to build and run your own project Hello World. At first we will build Hello project from WrmOS examples. Then we will create new external project.
Contents 1. Hello World example 2. Create new external project
1. Hello World example [up]
Step 1.1. Get cross-platform toolchain
See the article How to get toolchain for detail.
Step 1.2. Get WrmOS sources
Clone repository from github:
git clone https://github.com/wrmlab/wrmos.git
or download zip archive.
Step 1.3. Build example project Hello
Run building of example project Hello for architecture ARM and platform Versatile Express Cortex-A9:
cd wrmos make build P=cfg/prj/hello-qemu-veca9.prj B=../build/hello-qemu-veca9 -j
As result we will get bootloader image with RAMFS containing hello.elf:
ls ../build/hello-qemu-veca9/ldr/bootloader.elf
Step 1.4. Run WrmOS on QEMU virtual machine
qemu-system-arm -M vexpress-a9 -display none -serial stdio \ -kernel ../build/hello-qemu-veca9/ldr/bootloader.elf
As result we will see output:
[ldr] _ _ ___ __ __ ___ ___ [ldr] | | | | _ \ \/ | / _ \/ __| [ldr] | |/\| | / |\/| || (_) \__ \ [ldr] |__/\__|_|_\_| |_(_)___/|___/ [ldr] From Russia with love! [ldr] [ldr] cpu #0/1 ready, sp=0x60341a78. [ldr] [ldr] hello: 13:39:09 Jun 5 2018. [ldr] gccver: 7.3.0. [ldr] hware: arm, cortex_a9, vexpress_a9, qemu_vexpress_a9. [ldr] ram: [0x60000000 - 0x60800000) 8 MB. [ldr] ramfs: [0x6028d000 - 0x60338000) 684 KB. [ldr] ## name data size content [ldr] 1 kernel.elf 0x6028e000 443148 'ELF ...' [ldr] 2 sigma0.elf 0x602fa30c 41120 'ELF ...' [ldr] 3 roottask.elf 0x603043ac 144704 'ELF ...' [ldr] 4 config.alph 0x603278ec 516 '# config ...' [ldr] 5 hello.elf 0x60328000 64204 'ELF ...' [ldr] [ldr] elf: foreach: elf=0x6028e000, sz=0x6c30c. [ldr] app=kernel, va=0x60000000, pa=0x60000000, sz=0x00014000, load=1. [ldr] app=kernel, va=0xf0020000, pa=0x60020000, sz=0x001f9000, load=1. [ldr] app=kernel, va=0x00000000, pa=0x00000000, sz=0x00000000, load=0. [ldr] elf: foreach: elf=0x602fa30c, sz=0xa0a0. [ldr] app=sigma0, addr=0x00000000, sz=0x00000000, acc=0, progbits=0, name=. [ldr] app=sigma0, addr=0x60219000, sz=0x00005000, acc=5, progbits=1, name=.text. [ldr] app=sigma0, addr=0x6021e000, sz=0x00001000, acc=4, progbits=1, name=.rodata. [ldr] app=sigma0, addr=0x6021f000, sz=0x00001000, acc=6, progbits=1, name=.data. [ldr] app=sigma0, addr=0x60220000, sz=0x00004000, acc=6, progbits=1, name=.bss. [ldr] app=sigma0, addr=0x00000000, sz=0x00000039, acc=0, progbits=0, name=.ARM.attributes. [ldr] app=sigma0, addr=0x00000000, sz=0x00001240, acc=0, progbits=0, name=.symtab. [ldr] app=sigma0, addr=0x00000000, sz=0x00000c76, acc=0, progbits=0, name=.strtab. [ldr] app=sigma0, addr=0x00000000, sz=0x00000044, acc=0, progbits=0, name=.shstrtab. [ldr] app=sigma0, va=0x60219000, pa=0x60219000, sz=0x0000b000, load=1. [ldr] elf: foreach: elf=0x603043ac, sz=0x23540. [ldr] app=roottask, addr=0x00000000, sz=0x00000000, acc=0, progbits=0, name=. [ldr] app=roottask, addr=0x60224000, sz=0x00018000, acc=5, progbits=1, name=.text. [ldr] app=roottask, addr=0x6023c000, sz=0x00004000, acc=4, progbits=1, name=.rodata. [ldr] app=roottask, addr=0x60240000, sz=0x00001000, acc=6, progbits=1, name=.data. [ldr] app=roottask, addr=0x60241000, sz=0x0004c000, acc=6, progbits=1, name=.bss. [ldr] app=roottask, addr=0x00000000, sz=0x00000039, acc=0, progbits=0, name=.ARM.attributes. [ldr] app=roottask, addr=0x00000000, sz=0x00002600, acc=0, progbits=0, name=.symtab. [ldr] app=roottask, addr=0x00000000, sz=0x00002d58, acc=0, progbits=0, name=.strtab. [ldr] app=roottask, addr=0x00000000, sz=0x00000044, acc=0, progbits=0, name=.shstrtab. [ldr] app=roottask, va=0x60224000, pa=0x60224000, sz=0x00069000, load=1. [ldr] memory regions: [ldr] [60000000 - 60014000) sz=0x00014000, kernel. [ldr] [60020000 - 60219000) sz=0x001f9000, kernel. [ldr] [60219000 - 60224000) sz=0x0000b000, sigma0. [ldr] [60224000 - 6028d000) sz=0x00069000, roottask. [ldr] [60338000 - 60342000) sz=0x0000a000, bootloader. [ldr] [60342000 - 60800000) sz=0x004be000, free. [ldr] elf: foreach: elf=0x6028e000, sz=0x6c30c. [ldr] load: loc=0x60292000, pa=0x60000000, sz=0x00014000, load=1. [ldr] load: loc=0x602a6000, pa=0x60020000, sz=0x001f9000, load=1. [ldr] load: loc=0x6028e000, pa=0x00000000, sz=0x00000000, load=0. [ldr] elf: foreach: elf=0x602fa30c, sz=0xa0a0. [ldr] load: loc=0x602fb30c, pa=0x60219000, sz=0x0000b000, load=1. [ldr] elf: foreach: elf=0x603043ac, sz=0x23540. [ldr] load: loc=0x603053ac, pa=0x60224000, sz=0x00069000, load=1. [ldr] KIP found at 0x60020000. [ldr] Go to kernel. [----:0.000000] kernel: cpu #0 hello, sp=0xf0065f88. [sgm0:0.007522] inf: hello. [sgm0:0.009770] inf: free memory = 0x4c8000. [alph:0.064399] inf: hello. [alph:0.068992] inf: get memory from sigma0. [alph:0.089952] inf: got memory: 0x4c8000 bytes. [alph:0.093330] inf: Project config: [alph:0.093521] inf: Board config: [alph:0.093698] inf: ## device paddr size irq [alph:0.093953] inf: Memory config: [alph:0.094143] inf: ## name size cached contig [alph:0.094370] inf: Apps config: [alph:0.094616] inf: [0] [alph:0.094787] inf: name: hello [alph:0.094999] inf: short_name: hell [alph:0.095207] inf: file: ramfs:/hello.elf [alph:0.095448] inf: stack_sz: 0x1000 [alph:0.095670] inf: heap_sz: 0x0 [alph:0.095898] inf: max_aspaces: 1 [alph:0.096101] inf: max_threads: 3 [alph:0.096304] inf: max_prio: 100 [alph:0.096512] inf: fpu: 0 [alph:0.096725] inf: malloc_strategy: on_startup [alph:0.096942] inf: devices: [alph:0.097149] inf: memory: [alph:0.097351] inf: args: arg1=123, arg2=345 [alph:0.097614] inf: get iospace from sigma0. [alph:0.097827] inf: got iospace from sigma0. [alph:0.098519] inf: prepare named memory regions for apps. [alph:0.098777] inf: prepared named memory regions for apps. [alph:0.099028] inf: create app=hello. hello. argc=0x3, argv=0xff2000. arg[0] = hello. arg[1] = arg1=123. arg[2] = arg2=345. hello: I'm alive. hello: I'm alive. hello: I'm alive. hello: I'm alive. hello: I'm alive. hello: bye-bye.
2. Create new external project [up]
The usual use case of WrmOS is work with external projects. It allows to do not modifying original WrmOS sources.
Step 2.1. Get cross-platform toolchain
See the article How to get toolchain for detail.
Step 2.2. Get WrmOS sources
Clone repository from github:
git clone https://github.com/wrmlab/wrmos.git
or download zip archive.
Step 2.3. Create external project directory
mkdir my_project
Step 2.4. Create application directory
mkdir -p my_project/app/my_hello
Step 2.5. Create application source file my_project/app/my_hello/main.cpp
#include <stdio.h> #include <unistd.h> int main(int argc, const char* argv[]) { printf("hello.\n"); printf("argc=0x%x, argv=0x%p.\n", argc, argv); for (int i=0; i<argc; i++) { printf("arg[%d] = %s.\n", i, argv[i]); } const char* app_name = argv[0]; for (int i=0; i<5; ++i) { printf("%s: I'm alive.\n", app_name); sleep(1); } printf("%s: bye-bye.\n", app_name); return 0; }
Step 2.6. Create application make file my_project/app/my_hello/Makefile
objs := main.o incflags := -I$(cfgdir) baseflags := -O2 -Wall -Werror cxxflags := -std=c++11 -fno-rtti -fno-exceptions ldflags := libs := $(rtblddir)/lib/l4/libl4.a libs += $(rtblddir)/lib/wrmos/libwrmos.a libs += $(rtblddir)/lib/wlibc/libwlibc.a libs += $(rtblddir)/lib/wstdc++/libwstdc++.a ifeq ($(dbg),1) baseflags += -DDEBUG else baseflags += -DNDEBUG endif include $(wrmdir)/mk/base.mk
Step 2.7. Create project configuration directory
mkdir -p my_project/cfg/prj
Step 2.8. Create project configuration file my_project/cfg/prj/hello.prj
# platform parameters plt_file = $(wrmdir)/cfg/plt/arm-qemu-veca9.plt # toolchain gccprefix = arm-linux- # debug flags usr_lib_dbg = 1 usr_krn_dbg = 1 usr_krn_log = 1 usr_app_dbg = 1 usr_ldr_dbg = 0 # files to put in the ramfs usr_ramfs = config.alph:$(extdir)/cfg/alph/hello.alph usr_ramfs += hello.elf:$(blddir)/app/hello/hello.elf # base file to set all project params include $(wrmdir)/cfg/base.cfg
Step 2.9. Create Alpha configuration directory
mkdir -p my_project/cfg/alph
Step 2.10. Create Alpha's run-time configuration file my_project/cfg/alph/hello.alph
APPLICATIONS { name: myhello short_name: myhl file_path: ramfs:/hello.elf stack_size: 0x1000 heap_size: 0x0 aspaces_max: 1 threads_max: 3 prio_max: 100 fpu: off malloc_strategy: on_startup devices: memory: args: arg1=xxx, arg2=yyy }
Step 2.11. Build external project
cd my_project make -C ../wrmos build P=$(pwd)/cfg/prj/hello.prj E=$(pwd) B=$(pwd)/../build/my_hello -j
Step 2.12. Run project on QEMU virtual machine
qemu-system-arm -M vexpress-a9 -display none -serial stdio \ -kernel ../build/my_hello/ldr/bootloader.elf
As result we will see output:
[ldr] _ _ ___ __ __ ___ ___ [ldr] | | | | _ \ \/ | / _ \/ __| [ldr] | |/\| | / |\/| || (_) \__ \ [ldr] |__/\__|_|_\_| |_(_)___/|___/ [ldr] From Russia with love! [ldr] [ldr] cpu #0/1 ready, sp=0x60340518. [ldr] [ldr] hello: 13:46:59 Jun 5 2018. [ldr] gccver: 7.3.0. [ldr] hware: arm, cortex_a9, vexpress_a9, qemu_vexpress_a9. [ldr] ram: [0x60000000 - 0x60800000) 8 MB. [ldr] ramfs: [0x6028d000 - 0x60338000) 684 KB. [ldr] ## name data size content [ldr] 1 kernel.elf 0x6028e000 443140 'ELF ...' [ldr] 2 sigma0.elf 0x602fa304 41112 'ELF ...' [ldr] 3 roottask.elf 0x6030439c 144696 'ELF ...' [ldr] 4 config.alph 0x603278d4 343 'APPLICAT ...' [ldr] 5 hello.elf 0x60328000 64204 'ELF ...' [ldr] [ldr] KIP found at 0x60020000. [ldr] Go to kernel. [----:0.000000] kernel: cpu #0 hello, sp=0xf0065f88. [sgm0:0.007362] inf: hello. [sgm0:0.009624] inf: free memory = 0x4c8000. [alph:0.064424] inf: hello. [alph:0.069014] inf: get memory from sigma0. [alph:0.089183] inf: got memory: 0x4c8000 bytes. [alph:0.092560] inf: Project config: [alph:0.092771] inf: Board config: [alph:0.092962] inf: ## device paddr size irq [alph:0.093224] inf: Memory config: [alph:0.093421] inf: ## name size cached contig [alph:0.093684] inf: Apps config: [alph:0.093936] inf: [0] [alph:0.094115] inf: name: myhello [alph:0.094352] inf: short_name: myhl [alph:0.094570] inf: file: ramfs:/hello.elf [alph:0.094812] inf: stack_sz: 0x1000 [alph:0.095046] inf: heap_sz: 0x0 [alph:0.095255] inf: max_aspaces: 1 [alph:0.095450] inf: max_threads: 3 [alph:0.095647] inf: max_prio: 100 [alph:0.095846] inf: fpu: 0 [alph:0.096047] inf: malloc_strategy: on_startup [alph:0.096255] inf: devices: [alph:0.096452] inf: memory: [alph:0.096640] inf: args: arg1=xxx, arg2=yyy [alph:0.096895] inf: get iospace from sigma0. [alph:0.097101] inf: got iospace from sigma0. [alph:0.097748] inf: prepare named memory regions for apps. [alph:0.097992] inf: prepared named memory regions for apps. [alph:0.098221] inf: create app=myhello. hello. argc=0x3, argv=0xff2000. arg[0] = myhello. arg[1] = arg1=xxx. arg[2] = arg2=yyy. myhello: I'm alive. myhello: I'm alive. myhello: I'm alive. myhello: I'm alive. myhello: I'm alive. myhello: bye-bye.