コグノスケ


link 未来から過去へ表示  link 過去から未来へ表示(*)

link もっと前
2020年8月13日 >>> 2020年9月9日
link もっと後

2020年8月13日

CPAPの効果

SpO2(血中酸素飽和度)を測りながらCPAPを付けて寝たところ、途中で寝苦しくて起きてしまい、CPAPを外して二度寝しました。このときのSpO2の変化がなかなか面白いです。


CPAPあり〜外すまでの1時間


CPAPなしの最初の1時間


そのあとの1時間

CPAP外すとSpO2は明らかに悪化(2枚目)するかと思えば、CPAPない方がマシ(3枚目)な時間もあります。CPAPなしで寝た場合も何度か測っていますが、寝た直後はSpO2が悪化しますが、しばらく経つと悪化しなくなることが多いです。

睡眠のサイクルとか、寝ている姿勢とか、何かしら呼吸が止まる原因があるはずなんですが、寝ている自分には全くわからないし、突き止めるのが難しいですね……。

メモ: 技術系?の話はFacebookから転記しておくことにした。

編集者:すずき(2020/08/15 16:55)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月15日

サラウンドヘッドフォンシステム

先日(2020年8月3日の日記参照)購入したサラウンドヘッドフォンシステムSONY MDR-HW700DSですが、このような仕様みたいです。

  • スタンバイ(電源LEDがオレンジ):入力側のHDMIをパススルー
  • 電源OFF(電源LEDが消灯):入力側のHDMIをカット

今日の朝、何かの拍子に電源OFFになったらしく、ディスプレイ側に何も映らず真っ黒になりました。最初見たとき、えええ!?もう壊れた?早すぎない??と勘違いして、かなり焦りました。

ワイヤレスヘッドフォンゆえの不都合

ダイニングテーブル(普段の作業机がこれしかない)にあまり機械類を置けないので、SONY MDR-HW700DS本体の上に、USB-DACのONKYO SE-U33GXVIIを乗せて使っています。すると5秒に1回くらい、USB-DACの出力にジー…ビー…というノイズが乗ります。ワイヤレスヘッドフォンを探す電波を拾うのでしょうか?

USB-DACのボリュームをいじってもノイズの大きさが変わらないので、アナログ回路で電波拾ってるんですかね?オシロスコープでノイズを測ろうと思いましたが、オシロの測定限界以下らしく測れませんでした。無音でも何も見えません。

オシロで見えない程度のノイズゆえ、音量は極めて小さいです。しかし、私には聞こえる程度の音量はあるので、気が散って仕方ありません。機器を離して置こうにも、場所がないです。困りました。

周波数依存?

実はSONY MDR-HW700DSはワイヤレスヘッドフォンとの通信に使う帯域を2.4GHz帯と5GHz帯から選択可能です。ダメ元で切り替えてみたところ、2.4GHz帯にするとビー…というノイズが乗り、5GHz帯だとノイズが乗りませんでした。うおー!やった!これで回避できます。

2.4GHz, 5GHz自動選択機能を付けてくれたSONYの開発者には申し訳ないですが、5GHz固定で使うことにします……。

編集者:すずき(2020/08/15 19:25)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月16日

The Hunter: Call of the Wild

お盆休みの間、行くところも特にないのでThe Hunter: Call of the Wildばかりやっていました。気づいたらプレイ時間が100時間を超えていたので、そろそろ感想くらい書いても良かろうってことで書いてみます。

The Hunterはゲームというより「リアル指向」のスポーツハンティングシミュレータです。とても良くできていると思います。ただですね、最初に言っておきますが、私は「リアル指向」が強すぎるゲームは嫌いです。ゲームとして全く面白くないです……。

気に入ったところ

  • 画がめちゃくちゃ綺麗(貧弱なGPU(※)ではプレイできない)
  • マップが多彩、山あり、川あり、湖あり、ツンドラにもサバンナにも行ける
  • 鳥、うさぎ、シカ、クマなどなど獲物が多彩
  • ライフルや他の武器の再現度が高い(実物がモデルになっているようだ)
  • 鳴き声や足跡から獲物を追う、わくわく感

気に入らないところ

  • GPUの力が足りないときフレームスキップせず、スローモーションになりイライラ度がMAX
  • マップが広い割に移動が遅くてイライラする
  • 動物が少ない、特に初期3マップ(レイトン湖水地方、ヒルシュフェルデン保護区、メドヴェド=タイガ国立公園)は過疎地すぎる
  • リアルに寄せすぎてゲーム的な面白さがない
  • ごちゃごちゃうるさい(撃てばOKじゃなくて、狩猟基準のシステムがややこしい)
  • 「狩猟圧」というファンタジーシステムの存在

上に挙げた、良い点も悪い点も全て「リアル指向」であることに端を発しています。リアル指向である点が気に入らなければ、ほぼ全てが気に入らないと思います。逆に「リアル指向」が好きな人には最高の作品だと思います。

(※)私のノートPCに搭載されている、Radeon RX 550では歯が立たないです。画質設定を全て最低に落としたうえで、ウインドウモードにして、FullHDの1/4くらいのサイズにしないとまともに動きません。

The Hunter細かすぎて伝わらないルール: 狩猟基準

The Hunter: COTWでは、獲物を仕留め回収する際に点数が付きます。今はAnimal Scoring 2.0という基準だそうです。大まかには、下記を守ると点が高くなります。

  • 適切な弾丸を使用したか?
  • 2発以内に仕留めたか?
  • 致命傷を与えたか(心臓、肺など)?
  • トロフィー部位(たいていは頭蓋骨)は無事か?

最初の「適切な弾丸か?」について捕捉すると、鳥やウサギ、キツネのような小物を、ヘラジカ用の大口径ライフルの弾丸でぶっ飛ばすと点が下がります。獲物と弾丸にはクラス分けがされているので、一致させればOKです。

真ん中の2つについては、致命傷を与えなければ何度も撃つ羽目になるので、たいていは一緒に達成するはずです。

最後の「トロフィー部位は無事か?」については、獲物をはく製にして飾ることが狩りの1つの目的なので、はく製にする部分に穴が開くような撃ち方(=ヘッドショットする)をすると点が下がります。

The Hunter細かすぎて伝わらないルール: 狩猟圧

リアル指向のThe Hunterにおいて、極めて不自然なファンタジーシステムです。

獲物を仕留めた場所に、マップ上で見ると紫色の血飛沫のようなマークがつき、その付近には再び動物が寄りつきにくくなります。時間経過では消えず、他の場所で獲物を仕留めると段々古い狩猟圧から消えるようです。

同じニードゾーンでずっと待ち伏せ狩りすることを阻止したかったのだと思いますが、かなり変なシステムです。全然リアルじゃないでしょう。私の中ではこのシステムがつまんなさに拍車をかけています……。

邪道ハンターのススメ

The Hunterはスコアシステムを考慮して、急所を狙いやすく、弱い弾丸でも威力が保てる至近距離に近づくべきです。が、50mくらいまで近寄ろうとすると、何かと最悪なことが多くて、本当にイライラします。

気づかれないように近づく移動方法として匍匐前進があります。しかし匍匐前進は、速度が遅く時間ばかり掛かってイライラします。いかに慎重に近づいても獲物に逃げられることがあってこれまたイライラします。匍匐前進だと藪で獲物が見えず近づいても撃てないことが多くて、さらにイライラ度が高まります。

真面目に接近しようとするほど、イライラして正直やってられませんので、邪道ハンターのススメ「走り回って、気づかれないほど遠くから、大口径ライフルでズドン」を紹介します。

  • 動物の密度が高いDLCマップを選ぶ(初期3マップ以外なら多分OK)
  • 鳴き声を聴くまで適当に走り回る(呼び笛に反応しない動物は無視)
  • 三脚を建てて登る
  • 呼び笛を鳴らしまくる(何も来なかったら三脚を畳み、また走り回る)
  • 近づいてくる獲物を双眼鏡で見つける
  • ライフルに持ち替えて、動物が立ち止まるまで待つ
  • 使用可能な最強の大口径ライフルで一撃必殺する(獲物のクラスは無視)

もしニードゾーンが使えそうなら、

  • 動物の密度が高いDLCマップを選ぶ(初期3マップ以外なら多分OK)
  • 時間に合ったニードゾーン(※2)に行く
  • 獲物を双眼鏡で見つける(見つからなかったら、気にせず他の場所を探す)
  • ウェイポイントを獲物を見つけた地点に置く
  • ウェイポイントの100m〜150mくらいまで近寄る(匍匐は不要、中腰でOK)
  • ライフルに持ち替える
  • 使用可能な最強の大口径ライフルで一撃必殺する(獲物のクラスは無視)

最重要ポイントは、動物への接近に時間を掛けないことです。手早く次にチャレンジできてダルさが激減しますし、動物に逃げられても惜しくありません。The Hunterは動物との遭遇率がかなり低いので、時間をかけて逃げられたときのガッカリ感が半端じゃないです。

次に重要なのは距離を開けることと、高威力のライフルです。距離を100mくらい空ければ、風向きを無視しても、動物が逃げる確率は低いです。大口径ライフルならば急所を外しても即死する確率が高まります。これらの合わせ技により、ハント成功率がかなり上がりました。

とにかく「走り回って、気づかれないほど遠くから、大口径ライフルでズドン」で、お気軽な快適ハンティングを楽しみましょう。

(※2)ニードゾーン=動物の食事、給水、休憩場所のことです。このゲームでは特定の時間帯に、特定の動物がニードゾーンに集まってくるようにできています。かなり強い引き寄せ力をもっているため、待ち伏せ狩りの場所として最適です。

細かいことは気にしない

狩猟基準は無視を推奨します。点を上げるには弱い弾1発で仕留める必要があり、そのためには近づく必要があります。近づけば逃げられる可能性が高まります。時間かかってイライラするだけです。健康に良くありません。別に0点だろうが10点だろうが、どうでも良いです。それよりもハントしたいだろ?なあ?

シナリオも無視を推奨します。真面目に追いかけると、シナリオの攻略対象の動物が見つからずイライラするだけで、全く面白くないです。それよりもあらゆる場所で目に付いた動物を乱獲すれば、いくつかは勝手に終わります。暇で仕方なくて、シナリオが気になる!くらいまで、無視して良いと思います。

編集者:すずき(2020/08/16 18:05)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月19日

Androidのメモリの使い方 - Khadas VIMシリーズ

目次: Android

久しぶりにAndroidが動作するボードを購入したので、メモリの使い方を見てみました。開発用ボードはsuが使えるので、情報が何でも取れて楽で良いですね。

最初はKhadas VIM2 Basicというボードです(Linux 3.14.29 aarch64, Android 7.1.2ベース)。Amlogic S912というSoCです。RAMは2GBです。RAMが3GBのProというボードもあります。

Khadas VIM2 Basicの /proc/meminfo
MemTotal:        1746388 kB
MemFree:          457292 kB
MemAvailable:    1170284 kB
Buffers:            7384 kB
Cached:           676612 kB
SwapCached:            0 kB
Active:           380856 kB
Inactive:         585248 kB
Active(anon):     282472 kB
Inactive(anon):      612 kB
Active(file):      98384 kB
Inactive(file):   584636 kB
Unevictable:         252 kB
Mlocked:             252 kB
SwapTotal:        511996 kB
SwapFree:         511996 kB
Dirty:                76 kB
Writeback:             0 kB
AnonPages:        282492 kB
Mapped:           264172 kB
Shmem:               976 kB
Slab:             150844 kB
SReclaimable:     115568 kB
SUnreclaim:        35276 kB
KernelStack:       15184 kB
PageTables:        20864 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1385188 kB
Committed_AS:   45821668 kB
VmallocTotal:    2097088 kB
VmallocUsed:      106876 kB
VmallocChunk:    1805380 kB
TotalCMA:         221184 kB
UsedCMA:            4172 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Khadas VIM2 Basicの /proc/pagetypeinfo
Page block order: 9
Pages per block:  512

Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10   total
Node    0, zone   Normal, type    Unmovable    103     43     23      8      1      0      0      0      1      0      0     617
Node    0, zone   Normal, type  Reclaimable      0      1      1      0      1      2      0      0      1      0      0     342
Node    0, zone   Normal, type      Movable      0      0     95     52     12      5      1      0      1      0    109  113084
Node    0, zone   Normal, type      Reserve      0      0      0      0      0      0      0      0      0      0      0       0
Node    0, zone   Normal, type          CMA      0      0      0      0      0      0      0      0      0      0      0       0
Node    0, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0       0


Number of blocks type     Unmovable  Reclaimable      Movable      Reserve          CMA      Isolate
Node 0, zone   Normal          144           14          690            2          108            0
Khadas VIM2 Basicの /proc/iomem
00000000-04ffffff : System RAM
  01080000-01f5b813 : Kernel code
  020ac000-025a0fff : Kernel data
05300000-072fffff : System RAM
07300000-07307fff : persistent_ram
07308000-0730ffff : persistent_ram
07310000-07317fff : persistent_ram
07318000-0731ffff : persistent_ram
07320000-07327fff : persistent_ram
07328000-0732ffff : persistent_ram
07330000-07337fff : persistent_ram
07338000-0733ffff : persistent_ram
07340000-07347fff : persistent_ram
07348000-0734ffff : persistent_ram
07350000-07357fff : persistent_ram
07358000-0735ffff : persistent_ram
07360000-07367fff : persistent_ram
07368000-0736ffff : persistent_ram
07370000-07377fff : persistent_ram
07378000-0737ffff : persistent_ram
07380000-07387fff : persistent_ram
07388000-0738ffff : persistent_ram
07390000-07397fff : persistent_ram
07398000-0739ffff : persistent_ram
073a0000-073a7fff : persistent_ram
073a8000-073affff : persistent_ram
073b0000-073b7fff : persistent_ram
073b8000-073bffff : persistent_ram
073c0000-073c7fff : persistent_ram
073c8000-073cffff : persistent_ram
073d0000-073d7fff : persistent_ram
073d8000-073dffff : persistent_ram
073e0000-073e7fff : persistent_ram
073e8000-073effff : persistent_ram
073f0000-073f7fff : persistent_ram
073f8000-073fbfff : persistent_ram
073fc000-073fcfff : persistent_ram
073fd000-073fdfff : persistent_ram
07400000-77ffffff : System RAM
c11084c0-c11084d7 : c11084c0.serial
c1108500-c110851f : /i2c@c1108500
c1108680-c11086af : c1108680.saradc
c11087c0-c11087df : /i2c@c11087c0
c1109880-c110988f : /pinmux
c8013000-c80137ff : /mhu@c883c400
c8100014-c810001b : mux
c8100024-c810002b : gpio
c810002c-c810002f : pull
c8100480-c810049f : /rc@c8100580
c81004c0-c81004d7 : c81004c0.serial
c81004e0-c81004f7 : c81004e0.serial
c8100580-c81005c3 : /rc@c8100580
c8832000-c8832013 : /t9015
c8834430-c883446f : gpio
c88344b0-c88344d7 : mux
c88344e8-c88344fb : pull
c8834500-c8834503 : /defendkey
c8834520-c8834533 : pull-enable
c8834540-c8834547 : /ethernet@0xc9410000
c8834558-c8834563 : /ethernet@0xc9410000
c8838000-c88383ff : c8838000.canvas
c883c3d8-c883c3df : c1108680.saradc
c883c400-c883c44b : /mhu@c883c400
c9000000-c9007fff : /dwc3@c9000000
  c9000000-c9007fff : xhci-hcd
c900c100-c90fffff : /dwc3@c9000000
c9410000-c941ffff : /ethernet@0xc9410000
d0078000-d007807f : /usb2phy@d0078000
d0078080-d007809f : /usb3phy@d0078080
d00c0000-d01bffff : d00c0000.t82x

2つ目はKhadas VIM3 Basicというボードです(Linux 4.9.113 armv7l, Android 9ベース)。Amlogic A311DというSoCで、S922XにNPUというAI処理用のIPを搭載した仕様です。S922Xとピンコンパチとのこと。RAMは2GBです。RAMが4GBのProというボードもあります。

Khadas VIM3 Basicの /proc/meminfo
MemTotal:        1925088 kB
MemFree:          643640 kB
MemAvailable:    1091900 kB
Buffers:            9696 kB
Cached:           563448 kB
SwapCached:            0 kB
Active:           405012 kB
Inactive:         434112 kB
Active(anon):     268152 kB
Inactive(anon):      788 kB
Active(file):     136860 kB
Inactive(file):   433324 kB
Unevictable:        2372 kB
Mlocked:            2372 kB
HighTotal:       1179648 kB
HighFree:          36428 kB
LowTotal:         745440 kB
LowFree:          607212 kB
SwapTotal:        262140 kB
SwapFree:         262140 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:        268356 kB
Mapped:           389444 kB
Shmem:              1084 kB
Slab:              58456 kB
SReclaimable:      24384 kB
SUnreclaim:        34072 kB
KernelStack:        8856 kB
PageTables:        22616 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1224684 kB
Committed_AS:   29512728 kB
VmallocTotal:     245760 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
CmaTotal:         778240 kB
CmaFree:           10972 kB
VmapStack:          4440 kB
Khadas VIM3 Basicの /proc/pagetypeinfo
Page block order: 10
Pages per block:  1024

Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
Node    0, zone   Normal, type    Unmovable     39     46     15      4      3      1      1      0      1      1      0
Node    0, zone   Normal, type      Movable    418     81     32      8     11      8      2      1      1      1    144
Node    0, zone   Normal, type  Reclaimable      0      1      1      4      0      1      0      1      1      1      0
Node    0, zone   Normal, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type          CMA      6      0      0      1      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone  HighMem, type    Unmovable    150     76     76     34     17      3     40     10      0      0      0
Node    0, zone  HighMem, type      Movable     90    186     62     26     10      4      1      0      0      0      0
Node    0, zone  HighMem, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone  HighMem, type   HighAtomic      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone  HighMem, type          CMA    864    430    120     63     26      7      0      0      0      0      0
Node    0, zone  HighMem, type      Isolate      0      0      0      0      0      0      0      0      0      0      0

Number of blocks type     Unmovable      Movable  Reclaimable   HighAtomic          CMA      Isolate
Node 0, zone   Normal           17          167            7            0            1            0
Node 0, zone  HighMem           73           26            0            0          189            0
Khadas VIM3 Basicの /proc/iomem
00000000-77ffffff : System RAM
  00108000-015fffff : Kernel code
  01700000-0198cbc3 : Kernel data
ff100000-ff1007ff : galcore register region
ff3f0000-ff3fffff : eth_base
ff500000-ff507fff : /dwc3@ff500000
  ff500000-ff507fff : /dwc3@ff500000
ff50c100-ff5fffff : /dwc3@ff500000
ff630218-ff63021b : /rng
ff632000-ff633fff : /t9015
ff634440-ff63448b : gpio
ff6344e8-ff6344ff : pull
ff634520-ff634537 : pull-enable
ff634540-ff634547 : eth_cfg
ff6346c0-ff6346ff : mux
ff634740-ff63475b : drive-strength
ff638000-ff639fff : ff638000.canvas
ff63c400-ff63c44b : /mhu@c883c400
ff642000-ff643fff : /soc/audiobus@0xff642000
ff64c000-ff64c09f : eth_pll
ff800014-ff80001b : mux
ff80001c-ff800023 : drive-strength
ff800024-ff800037 : gpio
ff802000-ff80201f : /soc/aobus@ff800000/pwm@2000
ff803000-ff803017 : ff803000.serial
ff805000-ff80501f : /soc/aobus@ff800000/i2c@5000
ff808000-ff80801f : /rc@0xff808040
ff808040-ff808083 : /rc@0xff808040
ff809000-ff809047 : /saradc
ffd01008-ffd0100b : eth_reset
ffd19000-ffd1901f : /soc/cbus@ffd00000/pwm@19000
ffd1b000-ffd1b01f : /soc/cbus@ffd00000/pwm@1b000
ffd1c000-ffd1c01f : /soc/cbus@ffd00000/i2c@1c000
ffd22000-ffd22017 : ffd22000.serial
ffd24000-ffd24017 : ffd24000.serial
ffe03000-ffe037ff : /sdio@ffe03000
ffe05000-ffe057ff : /sd@ffe05000
ffe07000-ffe077ff : /emmc@ffe07000
ffe09000-ffe0907f : /usb2phy@ffe09000
ffe09080-ffe0909f : /usb3phy@ffe09080
ffe40000-ffe43fff : ffe40000.bifrost
fffe7000-fffe77ff : /mhu@c883c400
編集者:すずき(2023/09/24 08:50)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月20日

Android - まとめリンク

目次: Android

一覧が欲しくなったので作りました。

編集者:すずき(2023/09/24 08:49)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月24日

ALSAループバックデバイスで簡易リモート再生

目次: ALSA

デスクトップPCにはスピーカーを繋いでいませんが、たまに音声再生を確認したいことがあります。スピーカーを繋ぎ変えても良いですが、ALSAのループバックデバイスを使うと簡単に音声を転送したり、ファイルに記録したりできます。

ループバックデバイスとは再生した音声がそのまま戻ってきて(ループバック)録音できるデバイスのことです。ヘッドフォンの出力端子を、マイクロフォンの入力端子に繋いでループさせた状態を想像してもらうとわかりやすいと思います。

ALSAのループバックデバイス(aloop)は、ALSAの標準的な機能です。普通の環境だとロードされていないはずなので、modprobeでロードします。

ループバックデバイスのインストール
# modprobe snd-aloop

$ cat /proc/asound/pcm

00-03: HDMI 0 : HDMI 0 : playback 1
00-07: HDMI 1 : HDMI 1 : playback 1
00-08: HDMI 2 : HDMI 2 : playback 1
00-09: HDMI 3 : HDMI 3 : playback 1
00-10: HDMI 4 : HDMI 4 : playback 1
01-00: ALC1220 Analog : ALC1220 Analog : playback 1 : capture 1
01-01: ALC1220 Digital : ALC1220 Digital : playback 1
01-02: ALC1220 Alt Analog : ALC1220 Alt Analog : capture 1
02-00: Loopback PCM : Loopback PCM : playback 8 : capture 8    ★このデバイスhw:2を使用する
02-01: Loopback PCM : Loopback PCM : playback 8 : capture 8

ロードし終わるとPCMデバイスが1つ増えます。上記の場合は02-xx(02-00と02-01)が増えています。

ALSAループバックデバイスの使い方

ループバックデバイスはサブデバイス0が再生用、サブデバイス1が録音用となっています。先ほどの例でいうと、再生時はhw:2,0を使い、録音時はhw:2,1を使います。

音声を再生する側
$ aplay test.wav -D hw:2,0

Playing WAVE 'test.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
ループバック音声を録音する側
#### ファイルに記録する場合

$ arecord -D hw:2,1 -r 48000 -f S16_LE -c 2 test2.wav

Recording WAVE 'test2.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo


#### ネットワーク経由で送る場合

$ arecord -D hw:2,1 -r 48000 -f S16_LE -c 2 | nc 192.168.1.10 5555

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo

私の家のスピーカーは、今のところROCK64に繋がっています。ROCK64にネットワーク経由で送って、下記のように受け取れば「ほぼ」リアルタイムでデスクトップPCの音声が確認できます。

ネットワーク経由で別端末で受け取る場合
$ nc -l 5555 | aplay -D hw:0

Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo

受け取る方は先頭のWAVヘッダでサンプリング周波数やチャネル数を知ることができるため、-rや -cを指定する必要はありません。指定しても構いませんが無視されるはずです。

「ほぼ」リアルタイムと書いた理由は、上記の方法だと人間が余裕でわかるくらいの遅延が発生してしまうからです。ちゃんと測っていませんが、0.5秒くらい遅れてるかも?これでも簡易的な音声確認としては十分ですし、気にしなくでも良いでしょう。

編集者:すずき(2023/01/23 14:13)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月27日

サーバ向けプロセッサでは最強のIntel

目次: ROCK64/ROCKPro64

TwitterでCavium Thunder X3はサーバ向け汎用ARM SoCではなくなるかもしれない、という話を見かけました。Cavium(今はMarvellに買収されました)は独自ARM CPUコアを作って頑張ってたメーカーです。

ARM自体はまだまだめげることなく、サーバ向けに売りたい(Armのサーバ向け戦略十年の計は実を結ぶか、新プロセッサ「Neoverse」 - MONOist)ようですが、肝心のARM系SoCメーカーやサーバベンダーがARM系サーバで成功している様子がないです。

以前Qualcomm Centriqも鳴り物入りでサーバ向けARM SoCに参入しましたが、2018年にあっさり撤退Arm SoCの開発部門を秘かに閉鎖していたQualcomm - EE Times Japan)しています。モバイルの王者Qualcommをもってしても困難な道のようです。

サーバ向けプロセッサはIntelが9割取っているらしいので、崩すのはなかなか容易ではありませんね……。

ARMメニーコア系SoC

サーバ向けとして発表されているARMメニーコア系SoCを列挙してみました。年代はチップがローンチされたおおよその時期です。間違ってたらごめんなさい。

  • Ampere Altra(2020, ARM Neoverse N1, 80コア, 7nm)
  • Amazon Graviton 2(2020, ARM Neoverse N1, 64コア, 7nm)
  • Huawei Kunpeng 920(2019, Hisilicon TSV110, 64コア, 7nm)
  • Cavium Thunder X2(2018, Broadcom Vulkan, 32コア, 14nm)
  • Amazon Graviton(2018, ARM Cortex-A72, 16コア, 16nm)
  • Qualcomm Centriq(2017, Qualcomm Folker, 48コア, 10nm)
  • Socionext SC2A11(2017, Cortex-A53, 24コア)
  • Cavium Thunder X1(2014, Cavium独自, 48コア)

こんな感じですかね?SC2A11はホームページでサーバ向けと謳っていたので、リストに入れてます。でもCA53コアなので、性能的にはThunder X2辺りと並べるのはちょっと厳しい……かな?

編集者:すずき(2023/09/24 12:54)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月29日

ROCK64をRaspberry Pi 3のケースに無理やり格納

目次: ROCK64/ROCKPro64

先日KADHAS VIM2, VIM3を購入したため、ARMボードがさらに増え置き場がなくなりました。既存のボードをコンパクトに収納できないかと画策し、目を付けたのがROCK64です。現在ROCK64は純正ケースに入れて使っていますが、ギリシャの神殿を思わせる立派な柱と、無駄にでかいアクリル板のせいで、すっっごい邪魔です。


ROCK64の純正ケース

ROCK64はRaspberry Pi 3とほぼ同じ大きさですから、Raspberry Pi 3のケースを流用できるはずです。

ケース選び

改造のベースになるケースは、TinkerBoardやRaspberry Pi 3の格納で活躍しているPhysical Computing Labの3ple Decker Raspberry Piケース(公式サイトへのリンク)です。

Rasberry Pi 3は電源がUSB micro Bですが、ROCK64はACアダプタなので、全く形が合いません。アクリルケースの穴を削って広げる必要があります。もう一か所、ROCK64の個体差か(or単に設計の問題か?)ヘッドホンジャックがケースとズレていて、プラグが刺さらないため、これも直さないといけません。


電源コネクタ周辺(削る予定の部分を黒く塗っている)


ヘッドホンジャック周辺(削る予定の部分を黒く塗っている)

削り方はリューターにプラスチック用のビットを付けてゴリゴリ削るだけです。厚さも面積も大したことないので、力業でどうにでもなると思います。アクリルを削ると変なにおいがしますね。焦げてるのかな……?


加工後のケース

ケースを削り終わりました。ROCK64の端子がちゃんと外から見えています。

細かい不都合

元よりROCK64用のケースではないので、様々な不都合が発生します。

  • ROCK64の22pinのピンヘッダ(Pi P5+ Bus)がケースで隠れて配線できない
  • ROCK64のPWR, RESETボタンが押せない
  • ボードの固定が甘くなる

Pi P5+ Busが使用不能になる点は諦めました。Rasberry Pi 3にはないピンヘッダなので致し方無しです。このピンヘッダから引き出していたS/PDIFが利用不可能になりました。さよならS/PDIFさん。

PWR, RESETボタンはケースを開ければ押せますが、面倒です。今後はPWRボタンに頼らない運用を考えるべきでしょう。

ボードが固定できない問題はどうにもなりませんでした。microSDの上部を抑えるケース側のツメがうまくハマりません。


ボードを固定するケース側のツメ

もう少しきちんと調べてみると、ROCK64はRasberry Pi 3よりmicroSDスロットに厚みがあるせいで、microSDの上部を抑えるケース側のツメがうまくハマらないようです。


Raspberry Pi 3の場合


ROCK64の場合

スロットの厚さはどうしようもないので、泣く泣くケース側のツメを折りました。

ツメがないので、microSDカードがケースに引っ掛かってギリギリケースに固定されている状態です。ROCK64の40pinのピンヘッダ(Pi-2 Bus)にジャンパケーブルを抜き差しすると、microSDにかなり力が掛かります。これは良くないですね……。

Pi-2 Busへのケーブル抜き差しは結構固いため、そのうちmicroSDスロットが変形するか、microSDが折れて壊れると思います。幸いなことに、今は頻繁にピンヘッダのケーブル抜き差しはしませんから、しばらくこの状態でも使えるでしょう。

編集者:すずき(2020/10/30 01:22)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月30日

自宅駐車場でのもらい事故

目次:

先週、突然知らない番号から電話が掛かってきました。何だか焦った様子でした。要約すると「アパートの駐車場で隣に駐車している者です、駐車しようとして、あなたの車にぶつけてしまいました」とのことでした。車の様子を確認したところ、見事にバンパーの右前が取れていました。ああー……。


レガシィのバンパーが取れた

後日、保険屋さんと修理屋さん(スーパーオートバックス)から電話があり、車を引き取りに来る日時等を決めました。そして今日、レガシィさんはフロントバンパー修理のため旅立っていきました。

修理屋さん曰く「右ライトもAssy交換で新品になるだろう」とのこと。新品交換後の右ライトに対し、古ぼけた左ライトの明るさがアンバランスになるのはうまくないので、左ライトの研磨もお願いしました。残念ながら左ライトの研磨は保険が効かず自費になりそうですが、曇っていたライトが明るくなるから良しとしましょう。

代車

代車はホンダのフィットでした。


代車のフィット、外観


代車のフィット、インパネ

総じて良い車だと思います。レガシィとの違いとしては、

  • フロントがかなり斜めってる、真上の日差しがダッシュボードを照らし前が見えない
  • アクセルがフニャフニャ、踏んでもあまり速度が変わらない(遊びが大きい??)
  • ブレーキがある点から急激に効いて怖い

昔のフィットに乗ったときアクセルオフ時のエンブレが急すぎて車酔いしたので、正直好きな車ではなかったのですが、今のフィットは素敵な車です。新しい車って確実に良くなってますね。

ADAS(前車の車間検知、車線逸脱の警告)も搭載されていて面白いです。たまに誤検知?するのか、何もないところで突然ピー!と警告音が鳴ったり、車線逸脱の警告とともにハンドルがンゴゴー!って言い出すのはご愛敬です。

編集者:すずき(2023/09/30 14:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年8月31日

Zephyr OSで遊ぼう その10 - QEMUの変化に対応する

目次: Zephyr

最近のRISC-V向けQEMUでspike, virtを起動すると、下記のようなエラーで怒られてしまいます。

QEMU RISC-Vの起動時に出るエラー
$ qemu-system-riscv32 -nographic -machine spike -net none -chardev stdio,id=con,mux=on -serial chardev:con -mon chardev=con,mode=readline -kernel zephyr/zephyr.elf

qemu-system-riscv32: Unable to load the RISC-V firmware "opensbi-riscv32-spike-fw_jump.elf"

このエラーの原因はQEMU RISC-V向けの仕様変更によるものです。machineがspike, virtのときに、自由にBIOSを選べるように変わりました。ですがZephyrを起動する際には、特にBIOSは必要ないため、noneを指定すればOKです。

QEMU RISC-VをBIOSなしで起動する
$ qemu-system-riscv32 -nographic -machine spike -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 v2.2.0-rc1-123-gcaca3f60b012  ***
Hello World! hoge

ZephyrだけでなくQEMUも日々進化しているのですね。

編集者:すずき(2023/09/24 12:06)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年9月1日

Zephyr OSで遊ぼう その11 - Zephyr 2.3.0に対応する

目次: Zephyr

Zephyr 2.3.0にバージョンアップしたところ、またHogeボードのビルドが通らなくなりました。

一点目はUARTドライバのCMakeListsです。zephyr_library_sources_if_kconfig() がなくなったため、書き方が変わりました。

CMakeListsの書き方が変わったZephyr本家のコミット
commit 244f826e3c7333bb92fb53a65c50ee5cbd8a2ea0
Author: Carles Cufi <carles.cufi@nordicsemi.no>
Date:   Fri Jul 31 13:52:40 2020 +0200

    cmake: remove _if_kconfig() functions

    This set of functions seem to be there just because of historical
    reasons, stemming from Kbuild. They are non-obvious and prone to errors,
    so remove them in favor of the `_ifdef()` ones with an explicit
    `CONFIG_` condition.

    Script used:

    git grep -l _if_kconfig | xargs sed -E -i
    "s/_if_kconfig\(\s*(\w*)/_ifdef(CONFIG_\U\1\E \1/g"

    Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
CMakeListsの書き方を変更

# drivers/serial/CMakeLists.txt

zephyr_library_sources_if_kconfig(uart_spike.c)

下記に変更

zephyr_library_sources_ifdef(CONFIG_UART_SPIKE uart_spike.c)

二点目は整数型です。Zephyrはu8_t, u16_t, u32_tのような独自の整数型を持っていましたが、C99の型に置き換えられました。drivers/serial/uart_spike.cの実装を書き換える必要があります。

C99の型に置き換えたZephyr本家のコミット
commit a1b77fd589dbe7284c17b029f251426a724abd47
Author: Kumar Gala <kumar.gala@linaro.org>
Date:   Wed May 27 11:26:57 2020 -0500

    zephyr: replace zephyr integer types with C99 types

            git grep -l 'u\(8\|16\|32\|64\)_t' | \
                    xargs sed -i "s/u\(8\|16\|32\|64\)_t/uint\1_t/g"
            git grep -l 's\(8\|16\|32\|64\)_t' | \
                    xargs sed -i "s/s\(8\|16\|32\|64\)_t/int\1_t/g"

    Signed-off-by: Kumar Gala <kumar.gala@linaro.org>

三点目はDT_INST_0_SPIKE_UART_SPIKE_LABELマクロです。こいつは元々、訳のわからない名前で直しようがないので、SiFiveのシリアルドライバの履歴を参考に直します。履歴を見ると2回ほど変わっています。

マクロ名のルールはDT_INST_<INSTANCE>_<COMPAT>_<PROP> だったみたいです。今初めて知りました。やっぱりこの書き方は意味不明と思ったのか、DT_INST_PROP(0, label) という形式になりました。さらに今はDT_INST_LABEL(0) という形式に落ち着いています。

マクロ名の変更を行ったZephyr本家のコミット
★★DT_INST_PROP(0, label) になったコミット

commit 8f84520130a346957ac2e2bdff1d6a51bca13af0
Author: Kumar Gala <kumar.gala@linaro.org>
Date:   Tue Mar 10 17:24:43 2020 -0500

    drivers: serial: uart_sifive: convert to new DT API

    Use the new devicetree.h API instead of the legacy macros.

    Signed-off-by: Kumar Gala <kumar.gala@linaro.org>


★★DT_INST_LABEL(0) になったコミット

commit 74d459fb66b10a5a0614a582fb0375d8b4a78c9e
Author: Kumar Gala <kumar.gala@linaro.org>
Date:   Thu Apr 2 13:13:47 2020 -0500

    drivers: serial: sifive: use DT_INST_LABEL macro

    Replace a few cases that should have been DT_INST_LABEL instead.

    Signed-off-by: Kumar Gala <kumar.gala@linaro.org>

このマクロの罠はそれだけに留まらず、ソースコードの先頭に下記マクロを定義する必要があります。依然として訳がわかりません。ZephyrはDviceTree周りの仕様が不安定です。

ソースコードの先頭に必要なマクロ定義

// zephyr/drivers/serial/uart_spike.c

#define DT_DRV_COMPAT spike_uart_spike

最後はリンカーです。これは元々のコードのコンフィグが間違っていたことに起因します。ROM領域がないのにCONFIG_XIPが有効になっていました。

リンクエラー
$ ninja

...

x-tools/riscv64-zephyr-elf/lib/gcc/riscv64-zephyr-elf/8.3.0/../../../../riscv64-zephyr-elf/bin/ld: invalid origin for memory region ROM
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

エラーメッセージからは何が原因か読み取れないですね。こういうときはビルドディレクトリのリンカースクリプト(zephyr/linker.cmd)をうまく行く場合と、うまく行かない場合で見比べます。

リンクエラーが起きないとき(qemu_riscv32)のリンカースクリプト

/* zephyr/build/zephyr/linker.cmd */

 OUTPUT_ARCH("riscv")
 OUTPUT_FORMAT("elf32-littleriscv")
MEMORY
{
    ROM (rx) : ORIGIN = 541065216, LENGTH = 12582912
    RAM (rwx) : ORIGIN = 0x80000000, LENGTH = ((16) << 10)
    IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}
リンクエラーが起きるとき(Hogeボード)のリンカースクリプト

/* zephyr/build/zephyr/linker.cmd */

 OUTPUT_ARCH("riscv")
 OUTPUT_FORMAT("elf32-littleriscv")
MEMORY
{
    ROM (rx) : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE    /* ★★ここがおかしい★★ */
    RAM (rwx) : ORIGIN = 0x80000000, LENGTH = ((32) << 10)
    IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}

このスクリプトは下記のファイルから生成されているようです。HogeボードはROM領域を使う前提ではないので、領域そのものが要りません。ROM領域を葬るにはCONFIG_XIPをnにすれば良さそうです。ファイルはboards/riscv/hoge/hoge_defconfigです。

RISC-Vのリンカースクリプト

// include/arch/riscv/common/linker.ld

MEMORY
{
#ifdef CONFIG_XIP
#if DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), soc_nv_flash, okay)
#define ROM_BASE DT_REG_ADDR(DT_CHOSEN(zephyr_flash))
#define ROM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_flash))
#elif DT_NODE_HAS_COMPAT_STATUS(DT_CHOSEN(zephyr_flash), jedec_spi_nor, okay)
/* For jedec,spi-nor we expect the spi controller to memory map the flash
 * and for that mapping to be the second register property of the spi
 * controller.
 */
#define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash))
#define ROM_BASE DT_REG_ADDR_BY_IDX(SPI_CTRL, 1)
#define ROM_SIZE DT_REG_SIZE_BY_IDX(SPI_CTRL, 1)
#endif
    ROM (rx)  : ORIGIN = ROM_BASE, LENGTH = ROM_SIZE    /* ★★CONFIG_XIPが無効ならこの行ごと消える★★ */
#endif
    RAM (rwx) : ORIGIN = CONFIG_SRAM_BASE_ADDRESS, LENGTH = KB(CONFIG_SRAM_SIZE)
    /* Used by and documented in include/linker/intlist.ld */
    IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
}

以上の修正を入れて動かします。

動作確認
$ qemu-system-riscv32 -nographic -machine spike -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-2349-g0769bb760b2a  ***
Hello World! hoge

やっと動きました。良かった良かった。

編集者:すずき(2023/09/24 12:06)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年9月2日

Zephyrの16550シリアルドライバ その2

目次: Zephyr

以前、RISC-V QEMUの -machine virtで、シリアルドライバ16550を使う設定を作りましたが、Zephyr 2.3.0で動かなくなってしまいました。悲しい。

変更点はレジスタアドレスシフト量の設定方法です。DT_NS16550_REG_SHIFTで設定する方式でしたが、デバイスツリーから設定するように変更されました。

NS16550のコードを変えているZephyr本家のコミット
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>
NS16550のコードの変更内容

// 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

動きました。良かった良かった。

編集者:すずき(2023/09/24 12:07)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年9月3日

FreeRTOSで遊ぼう その1 - FreeRTOS入門

目次: FreeRTOS

以前RTOS界の新星Zephyrを調べて、新たなRISC-Vボードの定義を作りました。今回はRTOSの老舗FreeRTOSを調べます。FreeRTOSはGPLv2で開発されていましたが、Amazonが買収した後はMITライセンスになっています。IoT分野での企業ユーザー(大抵コード公開を嫌がる)を重視したんでしょう。

FreeRTOSのコード取得
$ 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を作成するだけです。

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なんですが、そのまま使うとなぜか下記のリンクエラーが出るので、少しだけ減らしています。

__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に改行が入っていないのは元々です。理由は良くわかりません、作った人がミスっただけかな?

編集者:すずき(2023/09/24 08:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年9月4日

FreeRTOSで遊ぼう その2 - FreeRTOSをvirtに移植(ドライバ準備編)

目次: FreeRTOS

前回は既にあるデモアプリのビルドシステムを組み替えてRISC-V QEMU sifive_eマシン(SiFive HiFive1相当)上でFreeRTOSを動かしました。今回はRISC-V QEMU virtマシン上でFreeRTOSを動かします。

マシンの違いですが、まずUARTが違います。HiFive1はSiFive UART、virtは16550です。UARTを動かすための簡易的なドライバを書きます。

16550の出力だけするドライバ

// 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を書き換える

元のコードはmain.cにSiFive UART用のシリアルの出力コードが入っているので、これを削ります。またmain.cとmain_blinky.c, main_full.cに別れていますが、あまり複雑なデモは要りません。main_full.cの方は削って、main.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() もどきを実装しておきました。

続きはまた今度。

編集者:すずき(2023/09/24 08:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



2020年9月5日

FreeRTOSで遊ぼう その3 - FreeRTOSをvirtに移植(ブート編)

目次: FreeRTOS

前回UARTドライバとmain() 関数を実装しました。今回はmain() に至るまでのブート部分を実装します。ざっくり言うとアセンブラで書いたスタートコードと、リンカスクリプトが必要です。

メモリマップ

RISC-V QEMU virtマシンのメモリマップは下記のようになっています。使わないハードウェアは載せていません。

  • 0x02000000: CLINT
  • 0x10000000: 16550 UART
  • 0x80000000: RAM

今回は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)をいくつか作っています。このように見えます。

nmやreadelfで見たとき
$ 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" にすると治ります。

編集者:すずき(2023/09/24 08:51)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする




link もっと前
2020年8月13日 >>> 2020年9月9日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<08>>>
------1
2345678
9101112131415
16171819202122
23242526272829
3031-----

最近のコメント5件

  • link 24年6月17日
    すずきさん (06/23 00:12)
    「ありがとうございます。バルコニーではない...」
  • link 24年6月17日
    hdkさん (06/22 22:08)
    「GPSの最初の同期を取る時は見晴らしのい...」
  • link 24年5月16日
    すずきさん (05/21 11:41)
    「あー、確かにdpkg-reconfigu...」
  • link 24年5月16日
    hdkさん (05/21 08:55)
    「システム全体のlocale設定はDebi...」
  • link 24年5月17日
    すずきさん (05/20 13:16)
    「そうですねえ、普通はStandardなの...」

最近の記事3件

  • link 24年6月27日
    すずき (06/30 15:39)
    「[何もない組み込み環境でDOOMを動かす - その4 - 自作OSの組み込み環境へ移植] 目次: RISC-V目次: 独自OS...」
  • link 22年12月13日
    すずき (06/30 15:38)
    「[独自OS - まとめリンク] 目次: 独自OS一覧が欲しくなったので作りました。自作OSの紹介その1 - 概要自作OSの紹介...」
  • link 21年6月18日
    すずき (06/29 22:28)
    「[RISC-V - まとめリンク] 目次: RISC-VSiFive社ボードの話、CoreMarkの話のまとめ。RISC-V ...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 06/30 15:39