1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ZephyrのLLEXTをFlashメモリからロードする

1
Posted at

概要

をヒントに、
Flashに置いたhello_world.llextから関数を動的ロードして実行する実験を行う。

ボード

こちらを使う
https://docs.zephyrproject.org/latest/boards/nxp/frdm_mcxn947/doc/index.html

コーディング

フラッシュからの読み出しということで、NXPのFMUというペリフェラルを使えばよいとのことなので、
それでもって、読み出し部分のAPIを実装した。

struct flash_loader_wrapper {
	struct llext_loader		loader;		// Must be top
	uintptr_t				base;
	size_t					pos;
	const struct device*	dev;
};

static const struct device *flash_ctl_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));

static int _read(struct llext_loader *ldr, void *dest, size_t len)
{
	struct flash_loader_wrapper *flw = CONTAINER_OF(ldr, struct flash_loader_wrapper, loader);
	int rc = flash_read(flw->dev, flw->base + flw->pos, dest, len);
	if (rc == 0) {
		LOG_INF("loaded addr :%p size:%d\n", (void*)(flw->base + flw->pos), len);
		flw->pos += len;
	}
	return rc;
}

static int _seek(struct llext_loader *ldr, size_t pos)
{
	struct flash_loader_wrapper *flw = CONTAINER_OF(ldr, struct flash_loader_wrapper, loader);
	flw->pos = pos;
	LOG_INF("seeked pos:%d\n", flw->pos);
	return 0;
}

static void init_flash_loader_wrapper(struct flash_loader_wrapper *flw, const struct device *dev, uintptr_t flash_base)
{
	flw->dev = dev;
	flw->pos = 0;
	flw->base = flash_base;
	flw->loader.read = _read;
	flw->loader.seek = _seek;
}

そして、以下のようにしてローダを今回実装したものに指定する。

int main(void)
{
	LOG_INF("Calling hello world as a module");

#ifdef LOAD_FROM_FLASH_ADDR
	struct flash_loader_wrapper flw = {0};
	init_flash_loader_wrapper(&flw, flash_ctl_dev, LOAD_FROM_FLASH_ADDR);
	struct llext_loader *ldr = &flw.loader;
#else
	size_t llext_buf_len = ARRAY_SIZE(llext_buf);
	struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(llext_buf, llext_buf_len);
	struct llext_loader *ldr = &buf_loader.loader;
#endif
...
..

ソースコードは以下にコミットしておいた。
https://github.com/zephyrproject-rtos/zephyr/commit/1105af8d04c28eeafad92c9c5b08bf7dba597206

ビルド

CONFIG_ARM_MPUの無効化が必要とのことなので、CMakeのオプションを直接指定してビルドする

$ west build -p -b frdm_mcxn947/mcxn947/cpu0 -T sample.llext.modules.module_build samples/subsys/llext/modules/ -- -DCONFIG_ARM_MPU=n

.llextのFlash

LinkServerのフラッシュツールは、.llext拡張子のファイルはサポート外のようなエラーが出たので、
llext拡張子をbinにしたバイナリを事前に用意しておこう。

cp ~/zephyrproject/zephyr/build/llext/hello_world.llext /tmp/hello.bin

そして、適当な位置に焼き込む。

/usr/local/LinkServer_26.3.123/LinkServer flash MCXN947:FRDM-MCXN947 load /tmp/hello.bin:0x100000

念の為Dumpして、焼けたことを確認しておこう...

$ /usr/local/LinkServer_26.3.123/LinkServer flash MCXN947:FRDM-MCXN947 dump 0x100000 16 ./dumped_0x100000
$ hexdump -c ./dumped_0x100000
0000000 177   E   L   F 001 001 001  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000010

ちゃんとELFヘッダがあるな:ok_hand:

動作確認

$ west flash

起動ログを見てみよう

*** Booting Zephyr OS build v4.4.0-539-g1105af8d04c2 ***
[00:00:00.014,000] <inf> app: Calling hello world as a module
[00:00:00.020,000] <dbg> llext: do_llext_load: Loading ELF data...
[00:00:00.026,000] <inf> app: seeked pos:0

[00:00:00.031,000] <inf> app: loaded addr :0x100000 size:52

[00:00:00.037,000] <dbg> llext: llext_load_elf_data: Loading relocatable ELF
[00:00:00.044,000] <inf> app: seeked pos:504

[00:00:00.049,000] <inf> app: loaded addr :0x1001f8 size:520

[00:00:00.055,000] <dbg> llext: do_llext_load: Finding ELF tables...
[00:00:00.062,000] <dbg> llext: llext_find_tables: section 0 at 0: name 0, type 0, flags 0, addr 0, align 0, size 0, link 0, info 0
[00:00:00.074,000] <dbg> llext: llext_find_tables: section 1 at 0x34: name 31, type 1, flags 0x6, addr 0, align 0x4, size 24, link 0, info 0

省略...

[00:00:01.076,000] <inf> app: loaded addr :0x100148 size:16

[00:00:01.082,000] <dbg> elf: arch_elf_relocate: 2 300025f8 300025a5 hello_world
[00:00:01.090,000] <dbg> llext: llext_export_symbols: sym 0x300025a5 name hello_world
[00:00:01.098,000] <dbg> llext: do_llext_load: Loaded llext: 337 bytes in heap, .text at 0x300025a4, .rodata at 0x300025c4
[00:00:01.110,000] <inf> llext: Loaded extension ext
Hello, world, from an llext!
[00:00:01.118,000] <dbg> llext: llext_free_regions: freeing memory region 0
[00:00:01.125,000] <dbg> llext: llext_free_regions: freeing memory region 2
[00:00:01.132,000] <dbg> llext: llext_free_regions: freeing memory region 4
[00:00:01.140,000] <dbg> llext: llext_free_regions: freeing memory region 5
[00:00:01.147,000] <dbg> llext: llext_free_regions: freeing memory region 6
[00:00:01.155,000] <dbg> llext: llext_free_regions: freeing memory region 7

素晴らしい:heart_eyes:
seekやloadも動いてそうだ。

感想

Zephyrが公式にこういったサブシステムを実装してくれているのは助かる。

.llext自体はelfとはいえ軽量そうだし、
ネットワーク経由などで、外部からAppをFlashに引き込んでおき、動的ロードなんてこともできそう:v:

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?