www.mtkn.jp

Manuscripts for my personal webpage.
git clone https://git.mtkn.jp/www.mtkn.jp
Log | Files | Refs | README

commit 39ee3e691c1fb6d849c0f9ca6a7b3a5a1c2f2c95
parent 46e08a7fceb7b64373fe34e5fe25fab6deb653a1
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Fri, 21 Apr 2023 19:12:08 +0900

update

Diffstat:
Mman/draft/rp2040_1.html | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mpub/draft/rp2040_1.html | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mpub/rss.xml | 4++--
3 files changed, 171 insertions(+), 6 deletions(-)

diff --git a/man/draft/rp2040_1.html b/man/draft/rp2040_1.html @@ -43,8 +43,8 @@ RP2040は電源を入れるといくつかの段階(ここでは関係ないの に変換することが必要である。 </p> <pre>\ -source code ---------> object ------> elf ------> crc32 ----> uf2 - compile link crc32 uf2 +source code ---------> object ------> elf -------->----->---> uf2 + compile link objcopy crc32 uf2 </pre> <h2>CRC32(巡回冗長検査)</h2> @@ -451,6 +451,112 @@ defer: 下位バイトから順に書き込む関数である。バイトオーダーとかややこしそうなので\ 作っておいたけど必要なのかな?あと名前が気に入らない。\ </p> +<p> +CRC32のチェックサムが書き込まれたバイナリファイルを、このプログラムでUF2に\ +変換し、生成されたファイルをUSBストレージとして接続したRP2040にコピーすれば\ +フラッシュROMに書き込まれる。 +</p> + +<h2>Flash Second Stage</h2> +<p> +RP2040に電源を投入し、CRC32のチェックが通った後、フラッシュROMからコピー\ +されたプログラムの先頭から実行が開始される。このコピーされた部分で\ +その後の動作に必要な各種の設定を行うことになる。\ +RP2040のデータシートには、この部分でフラッシュROMとSSIコントローラのXIP\ +を設定するようにと書かれている。\ +XIPはExecute in Placeの略で、フラッシュROMの内容をCPUから\ +直接実行するものである。SSIはSynchronous Serial Interfaceの略で、\ +周辺機器と情報のやりとりをする通信方式である。\ +RP2040はチップに内蔵されたこのSSIコントローラを通して、\ +外部のフラッシュROMと通信しているのだが、このコントローラを適切に設定すれば\ +フラッシュROMの内容がCPUから直接アクセスできる<code>0x10000000</code>番地以降\ +にマップされる。これによりフラッシュROMから内部のSRAMにデータをコピーする\ +ことなく命令を実行できるので、速くて便利だという。 +</p> +<p> +しかしこのSSIコントローラはSynopsysという会社のDW_apb_ssiというIPを\ +使っているようで、データシートのSSIコントローラの章は多分Synopsysの\ +人が書いている。その他の章はRaspberry Pi財団の書いたブリティッシュイングリッシュ\ +だが、この部分だけ多分中国人の書いたいい加減な英語である。誤植も多い。\ +何日かかけて理解しようとしたが、あまりにも必要な情報が書かれていないので\ +よく分からん。不毛なので一旦諦めた。\ +</p> +<p> +RP2040には内部にもROMがあり、中にはバージョン情報や、電源を投入した時の動作、\ +その他便利な関数が書き込まれている。この関数のなかに外部のフラッシュROMと\ +SSIコントローラを設定するものも含まれているので今回はこれを利用した。\ +ただしこの方法だとフラッシュROMとの通信方式がStandard SPIのままなので少し\ +遅い。詳しくはデータシート<sup>[3]</sup>の2.3.8. 「Bootrom Contents」を参照。 +</p> +<p> +RP2040の内蔵ROMの<code>0x00000018</code>番地に関数を検索するための関数がある。\ +この関数に<code>0x00000014</code>番地の<code>rom_func_table</code>と、\ +各関数に割り当てられた二文字の文字列を渡せば、欲しい関数へのポインタが\ +返ってくる。なお、二文字の文字列はそれぞれASCIIコードで現し、二文字目を\ +8ビットシフトしたものと1文字目のORを取ったものを渡すことになっている。\ +今回欲しい関数はフラッシュROMをXIPに設定するもの\ +(<code>_flash_enter_cmd_xip()</code>)なので、<code>'C', 'X'</code>を渡す。\ +関数のポインタが返ってきたら、それを呼び出せばフラッシュROMとSSIはXIPモード\ +になる。 +</p> +<pre><code>\ + ldr r4, rom_base + + ldrh r0, [r4, #0x14] // rom_func_table + ldr r1, =('C' | 'X' << 8) // _flash_enter_cmd_xip() + ldrh r2, [r4, #0x18] // rom_table_lookup + blx r2 + blx r0 +/* ... */ +rom_base: + .word 0x00000000 +</code></pre> + +<p> +XIPの設定が完了すれば、次はメインのプログラムを実行するための準備である。\ +エントリーポイントの指定、スタックポインタの初期値の設定、ベクターテーブル\ +の設定である。初期スタックポインタとエントリーポイントはベクターテーブルの\ +<code>0x0</code>バイト目と<code>0x4</code>バイト目に書くことになっている[要出展]。\ +また、ベクターテーブルはメインのプログラムの先頭に擱くおとにする。\ +メインのプログラムはFlash Second Stageが占有する256バイトの直後、\ +フラッシュROMの257バイト目から配置することにする。 +RP2040のベクターテーブルは<code>M0PLUS: VTOR(0xe0000000 + 0xed08)</code>という\ +レジスタに書き込むことで設定する。以上をまとめると以下のコードになる: +</p> +<pre><code>\ + ldr r0, flash_main + ldr r1, m0plus_vtor + str r0, [r1, #0] // vector table + ldr r1, [r0, #4] // entry point + ldr r0, [r0, #0] // stack pointer + mov sp, r0 + bx r1 +/* ... */ +flash_main: + .word 0x10000000 + 0x100 +m0plus_vtor: + .word 0xe0000000 + 0xed08 +</code></pre> + +<h2>メインのコード<h2> +<p> +メインのコードの最初には上で説明したベクターテーブルを配置する。\ +ここでは割り込みの処理は考えないので、初期スタックポインタと\ +エントリーポイントだけである。初期スタックポインタはSRAMの最後\ +(<code>0x20040000</code>)、エントリーポイントはエントリーポイントの\ +ラベルを用いて設定した。ただしこのCPUはThumbモードなので、\ +ラベルに<code>0x1</code>を足している[要説明]: +</p> +<pre><code>\ +.cpu cortex-m0plus +.thumb + + .section .vectors +vectors: + .word 0x20040000 // initial SP + .word (reset+1) +</code></pre> + <h2>参考</h2> <ul> diff --git a/pub/draft/rp2040_1.html b/pub/draft/rp2040_1.html @@ -41,8 +41,8 @@ RP2040は電源を入れるといくつかの段階(ここでは関係ないの <p> 以上のことから、プログラムを実行するためにはCRC32を計算し、UF2という形式に変換することが必要である。 </p> -<pre>source code ---------> object ------> elf ------> crc32 ----> uf2 - compile link crc32 uf2 +<pre>source code ---------> object ------> elf -------->----->---> uf2 + compile link objcopy crc32 uf2 </pre> <h2>CRC32(巡回冗長検査)</h2> @@ -403,6 +403,65 @@ defer: } </code></pre> <p><code>fwrite32l()</code>関数は指定されたファイルに32ビットの整数を下位バイトから順に書き込む関数である。バイトオーダーとかややこしそうなので作っておいたけど必要なのかな?あと名前が気に入らない。</p> +<p> +CRC32のチェックサムが書き込まれたバイナリファイルを、このプログラムでUF2に変換し、生成されたファイルをUSBストレージとして接続したRP2040にコピーすればフラッシュROMに書き込まれる。 +</p> + +<h2>Flash Second Stage</h2> +<p> +RP2040に電源を投入し、CRC32のチェックが通った後、フラッシュROMからコピーされたプログラムの先頭から実行が開始される。このコピーされた部分でその後の動作に必要な各種の設定を行うことになる。RP2040のデータシートには、この部分でフラッシュROMとSSIコントローラのXIPを設定するようにと書かれている。XIPはExecute in Placeの略で、フラッシュROMの内容をCPUから直接実行するものである。SSIはSynchronous Serial Interfaceの略で、周辺機器と情報のやりとりをする通信方式である。RP2040はチップに内蔵されたこのSSIコントローラを通して、外部のフラッシュROMと通信しているのだが、このコントローラを適切に設定すればフラッシュROMの内容がCPUから直接アクセスできる<code>0x10000000</code>番地以降にマップされる。これによりフラッシュROMから内部のSRAMにデータをコピーすることなく命令を実行できるので、速くて便利だという。 +</p> +<p> +しかしこのSSIコントローラはSynopsysという会社のDW_apb_ssiというIPを使っているようで、データシートのSSIコントローラの章は多分Synopsysの人が書いている。その他の章はRaspberry Pi財団の書いたブリティッシュイングリッシュだが、この部分だけ多分中国人の書いたいい加減な英語である。誤植も多い。何日かかけて理解しようとしたが、あまりにも必要な情報が書かれていないのでよく分からん。不毛なので一旦諦めた。</p> +<p> +RP2040には内部にもROMがあり、中にはバージョン情報や、電源を投入した時の動作、その他便利な関数が書き込まれている。この関数のなかに外部のフラッシュROMとSSIコントローラを設定するものも含まれているので今回はこれを利用した。ただしこの方法だとフラッシュROMとの通信方式がStandard SPIのままなので少し遅い。詳しくはデータシート<sup>[3]</sup>の2.3.8. 「Bootrom Contents」を参照。 +</p> +<p> +RP2040の内蔵ROMの<code>0x00000018</code>番地に関数を検索するための関数がある。この関数に<code>0x00000014</code>番地の<code>rom_func_table</code>と、各関数に割り当てられた二文字の文字列を渡せば、欲しい関数へのポインタが返ってくる。なお、二文字の文字列はそれぞれASCIIコードで現し、二文字目を8ビットシフトしたものと1文字目のORを取ったものを渡すことになっている。今回欲しい関数はフラッシュROMをXIPに設定するもの(<code>_flash_enter_cmd_xip()</code>)なので、<code>'C', 'X'</code>を渡す。関数のポインタが返ってきたら、それを呼び出せばフラッシュROMとSSIはXIPモードになる。 +</p> +<pre><code> ldr r4, rom_base + + ldrh r0, [r4, #0x14] // rom_func_table + ldr r1, =('C' | 'X' << 8) // _flash_enter_cmd_xip() + ldrh r2, [r4, #0x18] // rom_table_lookup + blx r2 + blx r0 +/* ... */ +rom_base: + .word 0x00000000 +</code></pre> + +<p> +XIPの設定が完了すれば、次はメインのプログラムを実行するための準備である。エントリーポイントの指定、スタックポインタの初期値の設定、ベクターテーブルの設定である。初期スタックポインタとエントリーポイントはベクターテーブルの<code>0x0</code>バイト目と<code>0x4</code>バイト目に書くことになっている[要出展]。また、ベクターテーブルはメインのプログラムの先頭に擱くおとにする。メインのプログラムはFlash Second Stageが占有する256バイトの直後、フラッシュROMの257バイト目から配置することにする。 +RP2040のベクターテーブルは<code>M0PLUS: VTOR(0xe0000000 + 0xed08)</code>というレジスタに書き込むことで設定する。以上をまとめると以下のコードになる: +</p> +<pre><code> ldr r0, flash_main + ldr r1, m0plus_vtor + str r0, [r1, #0] // vector table + ldr r1, [r0, #4] // entry point + ldr r0, [r0, #0] // stack pointer + mov sp, r0 + bx r1 +/* ... */ +flash_main: + .word 0x10000000 + 0x100 +m0plus_vtor: + .word 0xe0000000 + 0xed08 +</code></pre> + +<h2>メインのコード<h2> +<p> +メインのコードの最初には上で説明したベクターテーブルを配置する。ここでは割り込みの処理は考えないので、初期スタックポインタとエントリーポイントだけである。初期スタックポインタはSRAMの最後(<code>0x20040000</code>)、エントリーポイントはエントリーポイントのラベルを用いて設定した。ただしこのCPUはThumbモードなので、ラベルに<code>0x1</code>を足している[要説明]: +</p> +<pre><code>.cpu cortex-m0plus +.thumb + + .section .vectors +vectors: + .word 0x20040000 // initial SP + .word (reset+1) +</code></pre> + <h2>参考</h2> <ul> diff --git a/pub/rss.xml b/pub/rss.xml @@ -5,8 +5,8 @@ <description>ウェブページの更新履歴</description> <language>ja-jp</language> <link>https://www.mtkn.jp</link> -<lastBuildDate>Fri, 21 Apr 2023 14:55:46 +0900</lastBuildDate> -<pubDate>Fri, 21 Apr 2023 14:55:46 +0900</pubDate> +<lastBuildDate>Fri, 21 Apr 2023 19:11:58 +0900</lastBuildDate> +<pubDate>Fri, 21 Apr 2023 19:11:58 +0900</pubDate> <docs>https://www.rssboard.org/rss-specification</docs> <item> <title>Xlibで遊んでみる6</title>