目次: Windows
今に始まったことではないのですが、Windows 10が突然高負荷に陥ってしまうことがあります。大抵Windows Updateが裏で動いているだけのことが多いですが、今日は様子が違ったのでメモしておきます。
いつもと違う点、その1は、Systemプロセスが高負荷に陥っていることです。Windows Updateが裏で実行されている場合、マウスを動かしたりキーボードに触ったりすると負荷が下がります。今回はマウスを触っても負荷が下がりません。
Process Explorerで見るとPsReturnProcessNonPagedPoolQuota() という関数がめちゃくちゃ頑張っていました。なんでしょうね?これ?
この記事にコメントする
NVIDIAがArm全株式買収、ソフトバンクGから最大400億ドルで - ケータイWatch を読んで。
NVIDIAがArm買収です。買収額の2/3は株式交換で、ソフトバンクはNVIDIAの大株主になります。買収が成立すれば、ソフトバンクは1兆円超の利益を得ます。
ArmがNVIDIA配下となれば、NVIDIAと思い切り食い合う、Ethos(エッジAIプロセッサ)とMali(モバイル向けGPU)はゴミ箱行きですかね?ディスコンにしなくても、まともに開発しなくなりそうです。
さらにNVIDIAはNVIDIA GPUをライセンスするメリットがない(自分で作れる)ので、組み込み業界はImagination PowerVRとArm Maliという2大モバイルGPU IPを揃って失ってしまう悲しい未来になりそうです。
他陣営(RISC-Vとか)はまともなGPU IPがありませんし、Armがどんな地獄になろうとも、グラフィック必須のスマホ系SoCベンダーに逃げ場はなく、Armで作り続けるしかありません。
Armの築いたエコシステムがArmごとひっくり返されるとは思いませんでしたね。耐震構造のビルを建てていたら、いきなり一面の海になるような……バグったゲームみたいですが、現実なんですよね。
中国はImaginationごとPowerVRを買ってるので、ArmもしくはRISC-V用にPowerVRを売り出す可能性はあります(もう売ってる?)けど、PowerVRって性能的に今の時代のGPUに追いついているんでしょうか??
メモ: 技術系?の話はFacebookから転記しておくことにした。
この記事にコメントする
目次: FreeRTOS
FreeRTOSにRISC-V QEMU virtpcのパッチをぶん投げてみました。やり方はGitHubでプルリクエストを送れば良いみたいです(説明へのリンク(FreeRTOS/CONTRIBUTING.md))。
FreeRTOSには既にQMEUのプロジェクトはある(SiFive HiFive1エミュレーション環境向けのEclipseプロジェクトがある)から要らないよ!?と言われることが目に浮かびますが、それならそれで良し。今後なにかの役に立つでしょう。
FreeRTOSはインデントやコード記法が非常に特徴的で、とても書きにくかったです。
void vFunc( int aaa )
{
int xBbb;
if( aaa )
{
/* do something */
xBbb = 0;
}
}
クセが強すぎる。何でこんな記法にしたのやら……??
メモ: 技術系?の話はFacebookから転記しておくことにした。色々と加筆。
この記事にコメントする
自動車業界(だけじゃないですが)で重宝されているMATLABを家で使えることになったので、インストールしてみました。
ダウンロードは Mathworksのサイトからできますが、たぶん会社や学校からもらえるアカウント、アクティベーション番号が必要です。MATLABは個人でも買えますがメチャクチャ値段が高く、私は買う気は起きません……。
MATLABはDebian 9, Debian 10には対応しています(System Requirements for MATLAB R2020a - MATLAB & Simulink)が、Debian Testingには対応していません。インストーラを起動した瞬間にクラッシュします。
$ cd matlab_archive $ unzip matlab_R2020a_glnxa64.zip $ ./install terminate called after throwing an instance of 'std::runtime_error' what(): Unable to launch the MATLABWindow application Aborted
ありがたいことに、Linux向けのMATLABインストーラは通常版とlegacy版が同梱されています。
$ cd matlab_archive $ unzip matlab_R2020a_glnxa64.zip $ bin/glnxa64/install_unix_legacy
推奨された使い方ではないと思いますがlegacy版ならばインストーラが動きます。質問にはハイハイ答えておけば、そんなに問題ないはずです。
MATLABを起動するときに変なエラーが出ます。
$ matlab MATLAB is selecting SOFTWARE OPENGL rendering. matlab_install_dir/bin/glnxa64/jcef_helper: symbol lookup error: /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0: undefined symbol: g_ptr_array_copy
このエラーはMATLABの動的ライブラリの構成がおかしいことが原因です。libglib-2.0.soをMATLAB内部に抱えているのですが、libpango-1.0.soはシステム側を使うため、バージョンの非互換が発生します。libpango-1.0.soも内部に抱えれば良いのに??何だか中途半端な作りですね。
$ ldd bin/glnxa64/jcef_helper | grep glib libglib-2.0.so.0 => matlab_install_dir/bin/glnxa64/../../cefclient/sys/os/glnxa64/libglib-2.0.so.0 (0x00007f43ac828000) ★MATLAB内部に抱えているライブラリをダイナミックリンクする $ cd matlab_install_dir/cefclient/sys/os/glnxa64 $ mv libglib-2.0.so _libglib-2.0.so $ mv libglib-2.0.so.0 _libglib-2.0.so.0 $ mv libglib-2.0.so.0.5600.1 _libglib-2.0.so.0.5600.1 $ ldd bin/glnxa64/jcef_helper | grep glib libglib-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f10b2e6d000) ★システム側のライブラリをダイナミックリンクする
MATLABの内部で抱えているlibglib-2.0.soを無視して、システム側のlibglib-2.0.soをダイナミックリンクすればエラーは出ません。これも推奨された使い方ではないと思いますが、とりあえず動いたのでめでたしめでたし。
この記事にコメントする
目次: FreeRTOS
目次: 一覧の一覧
この記事にコメントする
目次: FreeRTOS
前回UARTドライバとmain() 関数を実装しました。今回はmain() に至るまでのブート部分を実装します。ざっくり言うとアセンブラで書いたスタートコードと、リンカスクリプトが必要です。
RISC-V QEMU virtマシンのメモリマップは下記のようになっています。使わないハードウェアは載せていません。
今回はRAMの一部をROMの代わりとして使います。0x80000000は本来RAMですがROMの代わりとして扱います。0x80080000以降をRAMとして扱います。本当はSPI Flash ROMを使ったほうが良いですが、手抜き実装です。リンカスクリプトは下記のようにしました。
OUTPUT_ARCH( "riscv" )
ENTRY( _start )
MEMORY
{
rom (rxa) : ORIGIN = 0x80000000, LENGTH = 512K
ram (wxa) : ORIGIN = 0x80080000, LENGTH = 512K
}
SECTIONS
{
.init :
{
_text = .;
KEEP (*(SORT_NONE(.init)))
} >rom AT>rom
.text :
{
*(.text.unlikely .text.unlikely.*)
*(.text.startup .text.startup.*)
*(.text .text.*)
*(.gnu.linkonce.t.*)
} >rom AT>rom
.fini :
{
KEEP (*(SORT_NONE(.fini)))
_etext = .;
} >rom AT>rom
.rodata.align :
{
. = ALIGN(4);
_rodata = .;
} >rom AT>rom
.rodata.start :
{
_rodata_lma = LOADADDR(.rodata.start);
} >rom AT>rom
.rodata :
{
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_erodata = .;
} >rom AT>rom
.data.align :
{
. = ALIGN(4);
_data = .;
} >ram AT>rom
.data.start :
{
_data_lma = LOADADDR(.data.start);
} >ram AT>rom
.data :
{
*(.data .data.*)
*(.gnu.linkonce.d.*)
. = ALIGN(8);
PROVIDE( __global_pointer$ = . + 0x800 );
*(.sdata .sdata.*)
*(.sdata2 .sdata2.*)
*(.gnu.linkonce.s.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
. = ALIGN(4);
_edata = .;
} >ram AT>rom
.bss.align :
{
. = ALIGN(4);
_bss = .;
} >ram AT>rom
.bss.start :
{
_bss_lma = LOADADDR(.bss.start);
} >ram AT>rom
.bss :
{
*(.sbss*)
*(.gnu.linkonce.sb.*)
*(.bss .bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram AT>rom
. = ALIGN(8);
_end = .;
.stack :
{
. = ALIGN(16);
_stack0_bottom = .;
. += __stack_size;
_stack0_top = .;
} >ram AT>ram
}
ビルドしたバイナリをnmやreadelfで見るときわかりやすくするために、あえて変なセクション(.*.align, .*.start)をいくつか作っています。このように見えます。
$ riscv64-unknown-elf-nm -n a.out | less ★.bss.alignにALIGN(4) と書いたとき 80002ea8 R __clz_tab 80002fa8 A _data_lma 80002fa8 R _erodata ★.rodataの終わり(ROM領域を0x80000000としている) 80002fb8 A _bss_lma 80080000 D _data ★.dataの始まり(RAM領域を0x80080000としている) 80080000 D pullNextTime 80080008 D uxTimerIncrementsForOneTick 8008000c D xISRStackTop 80080010 B _bss ★.bssの始まり ★4bytes alignになっている(.dataの終わりと連続している) 80080010 D _edata ★.dataの終わり 80080010 b xQueue ... ★.data.alignにALIGN(2048) と書いたとき 80002ca8 R __clz_tab 80002da8 A _data_lma 80002da8 R _erodata ★.rodataの終わり(ROM領域を0x80000000としている) 80002db8 A _bss_lma 80080000 D _data ★.dataの始まり(RAM領域を0x80080000としている) 80080000 D pullNextTime 80080008 D uxTimerIncrementsForOneTick 8008000c D xISRStackTop 80080010 D _edata ★.dataの終わり 80080800 D __global_pointer$ 80080800 B _bss ★.bssの始まり ★2KB alignになっている(.dataの終わりと連続して「いない」) 80080800 b xQueue ... $ riscv64-unknown-elf-readelf -a a.out | less ★.bss.alignにALIGN(4) と書いたとき Section Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .init PROGBITS 80000000 001000 00006c 00 AX 0 0 1 [ 2] .text PROGBITS 80000100 001100 002d2c 00 AX 0 0 256 [ 3] .rodata.align PROGBITS 80002e2c 004010 000000 00 WA 0 0 1 [ 4] .rodata PROGBITS 80002e2c 003e2c 00017c 00 A 0 0 4 [ 5] .data.align PROGBITS 80080000 004010 000000 00 WA 0 0 1 [ 6] .data PROGBITS 80080000 004000 000010 00 WA 0 0 4 [ 7] .bss.align NOBITS 80080010 000000 000000 00 WA 0 0 1 [ 8] .bss NOBITS 80080010 004010 0040c0 00 WA 0 0 16 ★4bytes alignになっている [ 9] .stack NOBITS 800840d0 0040d0 00012c 00 WA 0 0 1 ★.data.alignにALIGN(2048) と書いたとき ection Headers: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .init PROGBITS 80000000 001000 000068 00 AX 0 0 1 [ 2] .text PROGBITS 80000100 001100 002b2c 00 AX 0 0 256 [ 3] .rodata.align PROGBITS 80002c2c 004010 000000 00 WA 0 0 1 [ 4] .rodata PROGBITS 80002c2c 003c2c 00017c 00 A 0 0 4 [ 5] .data.align PROGBITS 80080000 004010 000000 00 WA 0 0 1 [ 6] .data PROGBITS 80080000 004000 000010 00 WA 0 0 4 [ 7] .bss.align NOBITS 80080010 004010 0007f0 00 WA 0 0 1 [ 8] .bss NOBITS 80080800 004800 0040c0 00 WA 0 0 16 ★2KB alignになっている [ 9] .stack NOBITS 800848c0 0048c0 00012c 00 WA 0 0 1
ALIGN(4) をALIGN(2048) など、大きめの値に変えたときの様子を載せました。変なセクション .*.alignがアドレスのアラインメントをしている様子が nmでもreadelfでもわかりやすいですよね?だめ?上記は .bssの例ですが、他のセクションでも同様です。
ブートコードはアセンブラで書く必要があります。
// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/start.S
#include "riscv-reg.h"
#if __riscv_xlen == 32
#define REGSIZE 4
#define LOAD lw
#define STOR sw
#elif __riscv_xlen == 64
#define REGSIZE 8
#define LOAD ld
#define STOR sd
#endif /* __riscv_xlen */
.section .init
.globl _start
.type _start,@function
_start:
.cfi_startproc
.cfi_undefined ra
.option push
.option norelax
la gp, __global_pointer$
.option pop
la sp, _stack0_top
# Load data section
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
LOAD t0, (a0)
STOR t0, (a1)
addi a0, a0, REGSIZE
addi a1, a1, REGSIZE
bltu a1, a2, 1b
2:
# Clear bss section
la a0, _bss
la a1, _ebss
bgeu a0, a1, 2f
1:
STOR zero, (a0)
addi a0, a0, REGSIZE
bltu a0, a1, 1b
2:
/* argc, argv, envp is 0 */
li a0, 0
li a1, 0
li a2, 0
j main
.cfi_endproc
実装は非常に単純です。.dataをROM領域からRAM領域にコピーし、.bssを0クリアしてmain() に飛ぶだけです。
以上の実装でビルドして(makeするだけ)、動かします。
$ qemu-system-riscv32 -nographic -machine virt -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -bios none -kernel a.out Hello FreeRTOS! Blink Blink Blink ...
動きましたね。良かった良かった。 改行が余計に入っちゃってるのが気になる場合はmain.cの "Blink\r\n" を "Blink\n" にすると治ります。
この記事にコメントする
目次: FreeRTOS
前回は既にあるデモアプリのビルドシステムを組み替えてRISC-V QEMU sifive_eマシン(SiFive HiFive1相当)上でFreeRTOSを動かしました。今回はRISC-V QEMU virtマシン上でFreeRTOSを動かします。
マシンの違いですが、まずUARTが違います。HiFive1はSiFive UART、virtは16550です。UARTを動かすための簡易的なドライバを書きます。
// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/ns16550.c
#include <stdint.h>
#include "ns16550.h"
/* register definitions */
#define REG_RBR 0x00 /* Receiver buffer reg. */
#define REG_THR 0x00 /* Transmitter holding reg. */
#define REG_IER 0x01 /* Interrupt enable reg. */
#define REG_IIR 0x02 /* Interrupt ID reg. */
#define REG_FCR 0x02 /* FIFO control reg. */
#define REG_LCR 0x03 /* Line control reg. */
#define REG_MCR 0x04 /* Modem control reg. */
#define REG_LSR 0x05 /* Line status reg. */
#define REG_MSR 0x06 /* Modem status reg. */
#define REG_SCR 0x07 /* Scratch reg. */
#define REG_BRDL 0x00 /* Divisor latch (LSB) */
#define REG_BRDH 0x01 /* Divisor latch (MSB) */
/* Line status */
#define LSR_DR 0x01 /* Data ready */
#define LSR_OE 0x02 /* Overrun error */
#define LSR_PE 0x04 /* Parity error */
#define LSR_FE 0x08 /* Framing error */
#define LSR_BI 0x10 /* Break interrupt */
#define LSR_THRE 0x20 /* Transmitter holding register empty */
#define LSR_TEMT 0x40 /* Transmitter empty */
#define LSR_EIRF 0x80 /* Error in RCVR FIFO */
uint8_t readb( uintptr_t addr )
{
return *((uint8_t *) addr );
}
void writeb( uint8_t b, uintptr_t addr )
{
*((uint8_t *) addr ) = b;
}
void ns16550_out( struct device *dev, unsigned char c )
{
uintptr_t addr = dev->addr;
while ( (readb( addr + REG_LSR ) & LSR_THRE) == 0 ) {
/* busy wait */
}
writeb( c, addr + REG_THR );
}
このドライバは初期化も設定も何もせず、いきなり出力だけ行う手抜き実装です。QEMUでは動きますが、おそらく実機では動かないでしょう。
元のコードはmain.cにSiFive UART用のシリアルの出力コードが入っているので、これを削ります。またmain.cとmain_blinky.c, main_full.cに別れていますが、あまり複雑なデモは要りません。main_full.cの方は削って、main.cに統合します。
// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/main.c
static void prvQueueSendTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const unsigned long ulValueToSend = 100UL;
BaseType_t xReturned;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
/* Initialise xNextWakeTime - this only needs to be done once. */
xNextWakeTime = xTaskGetTickCount();
for( ;; )
{
/* Place this task in the blocked state until it is time to run again. */
vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS );
/* Send to the queue - causing the queue receive task to unblock and
toggle the LED. 0 is used as the block time so the sending operation
will not block - it shouldn't need to block as the queue should always
be empty at this point in the code. */
xReturned = xQueueSend( xQueue, &ulValueToSend, 0U );
configASSERT( xReturned == pdPASS );
}
}
/*-----------------------------------------------------------*/
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
const char * const pcPassMessage = "Blink\r\n";
const char * const pcFailMessage = "Unexpected value received\r\n";
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{
/* Wait until something arrives in the queue - this task will block
indefinitely provided INCLUDE_vTaskSuspend is set to 1 in
FreeRTOSConfig.h. */
xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY );
/* To get here something must have been received from the queue, but
is it the expected value? If it is, toggle the LED. */
if( ulReceivedValue == ulExpectedValue )
{
puts( pcPassMessage );
ulReceivedValue = 0U;
}
else
{
puts( pcFailMessage );
}
}
}
/*-----------------------------------------------------------*/
int main( void )
{
puts( "Hello FreeRTOS!" );
/* Create the queue. */
xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
if( xQueue != NULL )
{
/* Start the two tasks as described in the comments at the top of this
file. */
xTaskCreate( prvQueueReceiveTask, "Rx", configMINIMAL_STACK_SIZE * 2U, NULL,
mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE * 2U, NULL,
mainQUEUE_SEND_TASK_PRIORITY, NULL );
}
vTaskStartScheduler();
return 0;
}
// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/riscv-virt.c
int puts( const char *s )
{
struct device dev;
size_t i;
dev.addr = NS16550_ADDR;
for (i = 0; i < strlen(s); i++)
{
ns16550_out( &dev, s[i] );
}
ns16550_out( &dev, '\n' );
return 0;
}
別にPOSIX信者というわけでもないんですが、ついでにputs() もどきを実装しておきました。
続きはまた今度。
この記事にコメントする
目次: FreeRTOS
以前RTOS界の新星Zephyrを調べて、新たなRISC-Vボードの定義を作りました。今回はRTOSの老舗FreeRTOSを調べます。FreeRTOSはGPLv2で開発されていましたが、Amazonが買収した後はMITライセンスになっています。IoT分野での企業ユーザー(大抵コード公開を嫌がる)を重視したんでしょう。
$ git clone https://github.com/FreeRTOS/FreeRTOS freertos Cloning into 'freertos'... remote: Enumerating objects: 149823, done. Receiving objects: 0% (1/149823) remote: Total 149823 (delta 0), reused 0 (delta 0), pack-reused 149823 Receiving objects: 100% (149823/149823), 115.38 MiB | 8.29 MiB/s, done. Resolving deltas: 100% (107018/107018), done. Updating files: 100% (12962/12962), done. $ git submodule update --init --recursive
FreeRTOSのカーネルはFreeRTOS/Sourceに配置されており、リポジトリはhttps://github.com/FreeRTOS/FreeRTOS-Kernelです。
FreeRTOS上で動く何かを作成する場合はfreertos/FreeRTOS/Demoの下に作るルールになっているようです。たくさんのアーキテクチャ、ボード向けのコードが格納されています。統一感がなくて、どれを見たら良いのか良くわからないのが難点です。
RISC-V 32ビット用でしたら、以前Zephyr用に作成したツールチェーン(2020年1月31日の日記参照)が流用できます。ARMやそれ以外の環境でもCrosstool-NGを使えばたいてい作成できるはずです。
Demoディレクトリの下にはRISC-V QEMU向けのプロジェクト(正確にはSiFive HiFive1エミュレーション環境向け)が既に1つあります。FreeRTOS/Demo/RISC-V-Qemu-sifive_e-Eclipse-GCCです。このデモはEclipse向けになっているので、Makefile向けに作り直します。Eclipse関連のファイルを削除してMakefileを作成するだけです。
CROSS=riscv64-unknown-elf-
CC=$(CROSS)gcc
OBJCOPY=$(CROSS)objcopy
ARCH=$(CROSS)ar
RTOS_SOURCE_DIR=../../Source
DEMO_SOURCE_DIR=../Common/Minimal
LIBWRAP_SOURCE_DIR=./freedom-e-sdk/libwrap
CPPFLAGS = -g -O2 -Wall -march=rv32ima -mabi=ilp32 -mcmodel=medlow \
-fmessage-length=0 \
-ffunction-sections \
-fdata-sections \
-fno-builtin-printf \
-DportasmHANDLE_INTERRUPT=handle_trap \
-I . -I ../Common/include \
-I $(RTOS_SOURCE_DIR)/include \
-I $(RTOS_SOURCE_DIR)/portable/GCC/RISC-V \
-I $(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/chip_specific_extensions/RV32I_CLINT_no_extensions \
\
-I freedom-e-sdk/include \
-I freedom-e-sdk/env \
-I freedom-e-sdk/env/freedom-e300-hifive1
CFLAGS =
ASFLAGS =
LDFLAGS = \
-march=rv32ima -mabi=ilp32 -mcmodel=medlow \
-Tfreedom-e-sdk/env/freedom-e300-hifive1/flash.lds \
-Xlinker --gc-sections \
-Xlinker --defsym=__stack_size=300
SRCS = \
main.c \
blinky_demo/main_blinky.c \
$(DEMO_SOURCE_DIR)/EventGroupsDemo.c \
$(DEMO_SOURCE_DIR)/TaskNotify.c \
$(DEMO_SOURCE_DIR)/TimerDemo.c \
$(DEMO_SOURCE_DIR)/blocktim.c \
$(DEMO_SOURCE_DIR)/dynamic.c \
$(DEMO_SOURCE_DIR)/recmutex.c \
$(RTOS_SOURCE_DIR)/event_groups.c \
$(RTOS_SOURCE_DIR)/list.c \
$(RTOS_SOURCE_DIR)/queue.c \
$(RTOS_SOURCE_DIR)/stream_buffer.c \
$(RTOS_SOURCE_DIR)/tasks.c \
$(RTOS_SOURCE_DIR)/timers.c \
$(RTOS_SOURCE_DIR)/portable/MemMang/heap_4.c \
$(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/port.c
ASMS = \
$(RTOS_SOURCE_DIR)/portable/GCC/RISC-V/portASM.S \
\
freedom-e-sdk/env/start.S \
freedom-e-sdk/env/entry.S
OBJS = $(SRCS:.c=.o) $(ASMS:.S=.o)
a.out: $(OBJS) $(CRT0) Makefile
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -nostartfiles $(CRT0) $(LINKER_FLAGS) -o $@
clean:
rm -rf $(OBJS)
元のコードでは --defsym=__stack_size=350なんですが、そのまま使うとなぜか下記のリンクエラーが出るので、少しだけ減らしています。
x-tools/riscv64-unknown-elf/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/bin/ld: section .stack VMA [0000000080003e00,0000000080003fff] overlaps section .bss VMA [0000000080000440,0000000080003ebb] collect2: error: ld returned 1 exit status make: *** [Makefile:105: rtosdemo.elf] Error 1
リンカースクリプトを見る限りHiFive1はRAMが16KBしかないようで、あまり大きな領域を取ろうとするとすぐに溢れてしまいます。
// freertos/FreeRTOS/Demo/RISC-V-Qemu-virt_GCC/freedom-e-sdk/env/freedom-e300-hifive1/flash.lds
MEMORY
{
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 512M
ram (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
Makefileを作ったらmakeし、動作確認します。
$ qemu-system-riscv32 -nographic -machine sifive_e -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -bios none -kernel a.out StartingBlink Blink Blink Blink Blink ...
動作しました。QEMUを止めるまでBlinkという文字が延々と出続けます。最初のStartingに改行が入っていないのは元々です。理由は良くわかりません、作った人がミスっただけかな?
この記事にコメントする
目次: Zephyr
以前、RISC-V QEMUの -machine virtで、シリアルドライバ16550を使う設定を作りましたが、Zephyr 2.3.0で動かなくなってしまいました。悲しい。
変更点はレジスタアドレスシフト量の設定方法です。DT_NS16550_REG_SHIFTで設定する方式でしたが、デバイスツリーから設定するように変更されました。
commit 70a0063b69b06812c5726077646cffae3b8e199c
Author: Kumar Gala <kumar.gala@linaro.org>
Date: Fri Mar 27 06:03:59 2020 -0500
drivers: serial: uart_ns16550: Convert to new DT_INST macros
Convert older DT_INST_ macro use the new include/devicetree.h
DT_INST macro APIs.
Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
// zephyr/drivers/serial/uart_ns16550.c
-#ifdef DT_INST_0_NS16550_REG_SHIFT
-#define UART_REG_ADDR_INTERVAL (1<<DT_INST_0_NS16550_REG_SHIFT)
+#if DT_INST_NODE_HAS_PROP(0, reg_shift)
+#define UART_REG_ADDR_INTERVAL (1<<DT_INST_PROP(0, reg_shift))
#endif
デバイスツリーに何を書けば良いのかは、デバイスツリーのドキュメント(ns16550.yaml)を見ましょう。プロパティ名と説明が書いてあります。
// zephyr/dts/bindings/serial/ns16550.yaml
properties:
reg:
required: true
reg-shift:
type: int
required: false
description: quantity to shift the register offsets by
// zephyr/dts/riscv/riscv32-virt.dtsi
...
uart0: serial@10000000 {
compatible = "ns16550";
reg = <0x10000000 0x100>;
clock-frequency = <3686400>;
label = "uart_0";
current-speed = <115200>;
reg-shift = <0>; /* ★これを追加★ */
};
// zephyr/soc/riscv/riscv-privilege/rv32-virt/soc.h
...
/* ★★下記定義は全て不要★★ */
#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_INST_0_NS16550_BASE_ADDRESS
#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_INST_0_NS16550_CURRENT_SPEED
#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_INST_0_NS16550_CLOCK_FREQUENCY
#define DT_UART_NS16550_PORT_0_NAME DT_INST_0_NS16550_LABEL
#define DT_NS16550_REG_SHIFT 0
以上の修正を入れて動かします。
$ qemu-system-riscv32 -nographic -machine virt -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf -bios none
*** Booting Zephyr OS build zephyr-v2.3.0-2350-g2f294fcc2da8 ***
Hello World! QEMU RV32 virt board
動きました。良かった良かった。
この記事にコメントする
| < | 2020 | > | ||||
| << | < | 09 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 | - | - | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: