commit 6533cdb8b7d9d742ad92e84d6d6aa556bd02e283
parent 77f964f5ce1fd8161aba0af654d67fe3844a71a5
Author: Matsuda Kenji <info@mtkn.jp>
Date: Sat, 22 Apr 2023 13:38:39 +0900
update
Diffstat:
3 files changed, 313 insertions(+), 17 deletions(-)
diff --git a/man/draft/rp2040_1.html b/man/draft/rp2040_1.html
@@ -348,7 +348,7 @@ fwrite32l(uint32_t d, FILE *f)
uint8_t b;
for (i = 0; i < 32; i += 8) {
b = (uint8_t) (d >> i & 0xff);
- fwrite(&b, 1, 1, f);
+ fwrite(&b, 1, 1, f);
if (ferror(f)) {
fprintf(stderr, "Fwrite32l: write error.\n");
return 0;
@@ -497,14 +497,19 @@ RP2040の内蔵ROMの<code>0x00000018</code>番地に関数を検索するため
今回欲しい関数はフラッシュROMをXIPに設定するもの\
(<code>_flash_enter_cmd_xip()</code>)なので、<code>'C', 'X'</code>を渡す。\
関数のポインタが返ってきたら、それを呼び出せばフラッシュROMとSSIはXIPモード\
-になる。
+になる:
</p>
<pre><code>\
- ldr r4, rom_base
+.cpu cortex-m0plus
+.thumb
+
+ .section .boot2
+setup_xip:
+ ldr r3, rom_base
- ldrh r0, [r4, #0x14] // rom_func_table
+ ldrh r0, [r3, #0x14] // rom_func_table
ldr r1, =('C' | 'X' << 8) // _flash_enter_cmd_xip()
- ldrh r2, [r4, #0x18] // rom_table_lookup
+ ldrh r2, [r3, #0x18] // rom_table_lookup
blx r2
blx r0
/* ... */
@@ -538,15 +543,15 @@ m0plus_vtor:
.word 0xe0000000 + 0xed08
</code></pre>
-<h2>メインのコード<h2>
+<h2>メインのコード(<code>main.s</code>)<h2>
<h3>ベクターテーブル</h3>
<p>
メインのコードの最初には上で説明したベクターテーブルを配置する。\
ここでは割り込みの処理は考えないので、初期スタックポインタと\
-エントリーポイントだけである。初期スタックポインタはSRAMの最後\
+エントリーポイントだけである。初期スタックポインタはSRAMの最後?\
(<code>0x20040000</code>)、エントリーポイントはエントリーポイントの\
ラベルを用いて設定した。ただしこのCPUはThumbモードなので、\
-ラベルに<code>0x1</code>を足している[要説明]:
+ラベルに<code>0x1</code>を足している[要説明?]:
</p>
<pre><code>\
.cpu cortex-m0plus
@@ -557,9 +562,157 @@ vectors:
.word 0x20040000 // initial SP
.word (reset+1)
</code></pre>
+
<h3>GPIOの設定</h3>
+<pre><code>\
+ .section .text
+reset:
+ // unreset gpio
+ mov r0, #1
+ lsl r0, r0, #5 // io_bank0
+ ldr r3, resets_base
+ ldr r1, atomic_clr
+ str r0, [r3, r1] // RESETS: RESET
+
+reset_chk:
+ ldr r1, [r3, #0x8] // RESETS: RESET_DONE
+ and r0, r0, r1
+ beq reset_chk
+
+ // set gpio functions
+ ldr r3, io_bank0_base
+ mov r0, #5 // sio
+ mov r1, #0xcc
+ str r0, [r3, r1] // IO_BANK0: GPIO25_CTRL
+
+ // enable gpio output
+ ldr r3, sio_base
+ mov r0, #1
+ lsl r0, r0, #25 // gpio25
+ str r0, [r3, #0x24] // SIO: GPIO_OE
+
+/* ... */
+
+atomic_clr:
+ .word 0x00003000
+resets_base:
+ .word 0x4000c000
+io_bank0_base:
+ .word 0x40014000
+sio_base:
+ .word 0xd0000000
+</code></pre>
+
+<h3>LEDの点滅</h3>
+<pre><code>\
+ // blink led on gpio25
+ ldr r4, sio_base
+ mov r5, r0
+loop:
+ str r5, [r4, #0x10] // SIO_GPIO_OUT_SET
+ bl delay
+ str r5, [r4, #0x18] // SIO_GPIO_OUT_CLR
+ bl delay
+ b loop
+
+delay:
+ mov r0, #1
+ lsl r0, r0, #20
+delay_loop:
+ sub r0, r0, #1
+ bne delay_loop
+ bx lr
+
+// literals
+ .align 2
+/* ... */
+sio_base:
+ .word 0xd0000000
+</code></pre>
+
+<h2>リンカスクリプト</h2>
+<p>
+以上のコードには<code>.boot2</code>、<code>.vectors</code>、<code>.text</code>\
+の3つのセクションが含まれる。<code>.boot2</code>はフラッシュの先頭から\
+256バイト(<code>0x100</code>)目まで、<code>.vectors</code>と<code>.text</code>\
+はその後ろに続くように配置する:
+<pre><code>\
+MEMORY
+{
+ FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
+}
+
+SECTIONS
+{
+ .boot2 : {
+ *(.boot2)
+ . = 0x100;
+ } > FLASH
+
+ .text : {
+ *(.vectors)
+ *(.text)
+ } > FLASH
+}
+</code></pre>
+
+<h2>Makefile</h2>
+ディレクトリ構造:
+<pre><code>\
+rp2040_baremetal
+├── ex1
+│ ├── Makefile
+│ ├── boot2.s
+│ ├── main.s
+│ └── memmap.ld
+└── tools
+ ├── Makefile
+ ├── bin2uf2.c
+ └── bincrc.c
+</code></pre>
<p>
+toolsディレクトリのMakefileは同じディレクトリのソースファイルを<code>cc</code>\
+でコンパイルするだけのものである(個人的な趣味で<code>tcc</code>を使っている)。\
+ex1ディレクトリのMakefileは以下の通り:
+</p>
+<pre><code>\
+AS = arm-none-eabi-as
+LD = arm-none-eabi-ld
+OBJCOPY = arm-none-eabi-objcopy
+BINCRC = ../tools/bincrc
+BIN2UF2 = ../tools/bin2uf2
+
+MCPU = -mcpu=cortex-m0plus
+ASFLAGS = $(MCPU)
+CFLAGS = $(MCPU) -ffreestanding -nostartfiles -O0 -fpic -mthumb -c
+LDFLAGS = --no-relax -nostdlib
+
+all: tools led.uf2
+
+clean:
+ rm -f *.o *.elf *.uf2 *.bin
+ cd ../tools && make clean
+
+.s.o:
+ $(AS) $(ASFLAGS) -o $@ $<
+led.elf: boot2.o main.o memmap.ld
+ $(LD) $(LDFLAGS) -o $@ -T memmap.ld boot2.o main.o
+
+led.bin: led.elf
+ $(OBJCOPY) -O binary led.elf $@
+
+led.uf2: led.bin
+ $(BINCRC) led.bin led_crc.bin
+ $(BIN2UF2) led_crc.bin $@
+
+flash: all
+ mount /dev/disk/by-label/RPI-RP2 /mnt
+ cp led.uf2 /mnt
+
+tools:
+ cd ../tools && make
+</code></pre>
<h2>参考</h2>
<ul>
diff --git a/pub/draft/rp2040_1.html b/pub/draft/rp2040_1.html
@@ -304,7 +304,7 @@ fwrite32l(uint32_t d, FILE *f)
uint8_t b;
for (i = 0; i < 32; i += 8) {
b = (uint8_t) (d >> i & 0xff);
- fwrite(&b, 1, 1, f);
+ fwrite(&b, 1, 1, f);
if (ferror(f)) {
fprintf(stderr, "Fwrite32l: write error.\n");
return 0;
@@ -417,13 +417,18 @@ RP2040に電源を投入し、CRC32のチェックが通った後、フラッシ
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モードになる。
+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
+<pre><code>.cpu cortex-m0plus
+.thumb
+
+ .section .boot2
+setup_xip:
+ ldr r3, rom_base
- ldrh r0, [r4, #0x14] // rom_func_table
+ ldrh r0, [r3, #0x14] // rom_func_table
ldr r1, =('C' | 'X' << 8) // _flash_enter_cmd_xip()
- ldrh r2, [r4, #0x18] // rom_table_lookup
+ ldrh r2, [r3, #0x18] // rom_table_lookup
blx r2
blx r0
/* ... */
@@ -449,10 +454,10 @@ m0plus_vtor:
.word 0xe0000000 + 0xed08
</code></pre>
-<h2>メインのコード<h2>
+<h2>メインのコード(<code>main.s</code>)<h2>
<h3>ベクターテーブル</h3>
<p>
-メインのコードの最初には上で説明したベクターテーブルを配置する。ここでは割り込みの処理は考えないので、初期スタックポインタとエントリーポイントだけである。初期スタックポインタはSRAMの最後(<code>0x20040000</code>)、エントリーポイントはエントリーポイントのラベルを用いて設定した。ただしこのCPUはThumbモードなので、ラベルに<code>0x1</code>を足している[要説明]:
+メインのコードの最初には上で説明したベクターテーブルを配置する。ここでは割り込みの処理は考えないので、初期スタックポインタとエントリーポイントだけである。初期スタックポインタはSRAMの最後?(<code>0x20040000</code>)、エントリーポイントはエントリーポイントのラベルを用いて設定した。ただしこのCPUはThumbモードなので、ラベルに<code>0x1</code>を足している[要説明?]:
</p>
<pre><code>.cpu cortex-m0plus
.thumb
@@ -462,9 +467,147 @@ vectors:
.word 0x20040000 // initial SP
.word (reset+1)
</code></pre>
+
<h3>GPIOの設定</h3>
+<pre><code> .section .text
+reset:
+ // unreset gpio
+ mov r0, #1
+ lsl r0, r0, #5 // io_bank0
+ ldr r3, resets_base
+ ldr r1, atomic_clr
+ str r0, [r3, r1] // RESETS: RESET
+
+reset_chk:
+ ldr r1, [r3, #0x8] // RESETS: RESET_DONE
+ and r0, r0, r1
+ beq reset_chk
+
+ // set gpio functions
+ ldr r3, io_bank0_base
+ mov r0, #5 // sio
+ mov r1, #0xcc
+ str r0, [r3, r1] // IO_BANK0: GPIO25_CTRL
+
+ // enable gpio output
+ ldr r3, sio_base
+ mov r0, #1
+ lsl r0, r0, #25 // gpio25
+ str r0, [r3, #0x24] // SIO: GPIO_OE
+
+/* ... */
+
+atomic_clr:
+ .word 0x00003000
+resets_base:
+ .word 0x4000c000
+io_bank0_base:
+ .word 0x40014000
+sio_base:
+ .word 0xd0000000
+</code></pre>
+
+<h3>LEDの点滅</h3>
+<pre><code> // blink led on gpio25
+ ldr r4, sio_base
+ mov r5, r0
+loop:
+ str r5, [r4, #0x10] // SIO_GPIO_OUT_SET
+ bl delay
+ str r5, [r4, #0x18] // SIO_GPIO_OUT_CLR
+ bl delay
+ b loop
+
+delay:
+ mov r0, #1
+ lsl r0, r0, #20
+delay_loop:
+ sub r0, r0, #1
+ bne delay_loop
+ bx lr
+
+// literals
+ .align 2
+/* ... */
+sio_base:
+ .word 0xd0000000
+</code></pre>
+
+<h2>リンカスクリプト</h2>
<p>
+以上のコードには<code>.boot2</code>、<code>.vectors</code>、<code>.text</code>の3つのセクションが含まれる。<code>.boot2</code>はフラッシュの先頭から256バイト(<code>0x100</code>)目まで、<code>.vectors</code>と<code>.text</code>はその後ろに続くように配置する:
+<pre><code>MEMORY
+{
+ FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k
+}
+SECTIONS
+{
+ .boot2 : {
+ *(.boot2)
+ . = 0x100;
+ } > FLASH
+
+ .text : {
+ *(.vectors)
+ *(.text)
+ } > FLASH
+}
+</code></pre>
+
+<h2>Makefile</h2>
+ディレクトリ構造:
+<pre><code>rp2040_baremetal
+├── ex1
+│ ├── Makefile
+│ ├── boot2.s
+│ ├── main.s
+│ └── memmap.ld
+└── tools
+ ├── Makefile
+ ├── bin2uf2.c
+ └── bincrc.c
+</code></pre>
+<p>
+toolsディレクトリのMakefileは同じディレクトリのソースファイルを<code>cc</code>でコンパイルするだけのものである(個人的な趣味で<code>tcc</code>を使っている)。ex1ディレクトリのMakefileは以下の通り:
+</p>
+<pre><code>AS = arm-none-eabi-as
+LD = arm-none-eabi-ld
+OBJCOPY = arm-none-eabi-objcopy
+BINCRC = ../tools/bincrc
+BIN2UF2 = ../tools/bin2uf2
+
+MCPU = -mcpu=cortex-m0plus
+ASFLAGS = $(MCPU)
+CFLAGS = $(MCPU) -ffreestanding -nostartfiles -O0 -fpic -mthumb -c
+LDFLAGS = --no-relax -nostdlib
+
+all: tools led.uf2
+
+clean:
+ rm -f *.o *.elf *.uf2 *.bin
+ cd ../tools && make clean
+
+.s.o:
+ $(AS) $(ASFLAGS) -o $@ $<
+
+led.elf: boot2.o main.o memmap.ld
+ $(LD) $(LDFLAGS) -o $@ -T memmap.ld boot2.o main.o
+
+led.bin: led.elf
+ $(OBJCOPY) -O binary led.elf $@
+
+led.uf2: led.bin
+ $(BINCRC) led.bin led_crc.bin
+ $(BIN2UF2) led_crc.bin $@
+
+flash: all
+ mount /dev/disk/by-label/RPI-RP2 /mnt
+ cp led.uf2 /mnt
+
+tools:
+ cd ../tools && make
+</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 19:15:50 +0900</lastBuildDate>
-<pubDate>Fri, 21 Apr 2023 19:15:50 +0900</pubDate>
+<lastBuildDate>Sat, 22 Apr 2023 13:38:27 +0900</lastBuildDate>
+<pubDate>Sat, 22 Apr 2023 13:38:27 +0900</pubDate>
<docs>https://www.rssboard.org/rss-specification</docs>
<item>
<title>Xlibで遊んでみる6</title>