Простейший проект Hello World

Опубликовано Sergey Worm - вт, 06/05/2018 - 16:39

Наилучший способ изучить WrmOS — использовать его. Поэтому эта статья предоставляет пошаговое руководство как собрать и запустить свой собственный проект Hello World. Сперва мы соберём проект Hello из примеров WrmOS. Затем мы создадим новый внешний (external) проект.

Содержание
1. Ознакомительный проект Hello
2. Создание нового внешнего (external) проекта

1. Ознакомительный проект Hello [наверх]


Шаг 1.1. Получить кроссплатформенный тулчейн

Подробную информацию смотрите в статье Как получить тулчейн.

Шаг 1.2. Получить исходники WrmOS

Клонировать репозиторий из github:

git clone https://github.com/wrmlab/wrmos.git

или загрузить zip архив.

Шаг 1.3. Собрать ознакомительный проект Hello

Запустим сборку ознакомительного проекта Hello для архитектуры ARM и платформы Versatile Express Cortex-A9:

cd wrmos
make build P=cfg/prj/hello-qemu-veca9.prj B=../build/hello-qemu-veca9 -j

В результате мы получим образ загрузчика с файловой системой, содержащей исполняемый файл приложения hello.elf:

ls ../build/hello-qemu-veca9/ldr/bootloader.elf

Шаг 1.4. Запустить WrmOS на виртуальной машине QEMU

qemu-system-arm -M vexpress-a9 -display none -serial stdio \
                -kernel ../build/hello-qemu-veca9/ldr/bootloader.elf

В результате мы увидим следующий вывод:

[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. Создание нового внешнего (external) проекта [наверх]


Типовым вариантом использоавния WrmOS является внешний (external) проект. Это позволяет не вносить изменений в оригинальные исходники WrmOS.

Шаг 2.1. Получить кроссплатформенный тулчейн

Подробную информацию смотрите в статье Как получить тулчейн.

Шаг 2.2. Получить исходники WrmOS

Клонировать репозиторий из github:

git clone https://github.com/wrmlab/wrmos.git

или загрузить zip архив.

Шаг 2.3. Создать директорию для внешнего (external) проекта

mkdir my_project

Шаг 2.4. Создать директорию для приложения

mkdir -p my_project/app/my_hello

Шаг 2.5. Создать исходный файл приложения 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;
}

Шаг 2.6. Создать мэйкфайл приложения 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

Шаг 2.7. Создать конфигурационную директорию проекта

mkdir -p my_project/cfg/prj

Шаг 2.8. Создать конфигурационный файл проекта 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

Шаг 2.9. Создать конфигурационную директорию корневого приложения Alpha

mkdir -p my_project/cfg/alph

Шаг 2.10. Создать конфигурационный файл времени выполения для корневого приложения Alpha 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
	}

Шаг 2.11. Собрать внешний (external) проект

cd my_project
make -C ../wrmos build P=$(pwd)/cfg/prj/hello.prj E=$(pwd) B=$(pwd)/../build/my_hello -j

Шаг 2.12. Запустить собранный проект на виртуальной машине QEMU

qemu-system-arm -M vexpress-a9 -display none -serial stdio \
                -kernel ../build/my_hello/ldr/bootloader.elf

В результате мы увидим следующий вывод:

[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.