SNSへはこちら

Longan NanoでRISC-Vチャレンジ(3) - ライブラリの導入

本格的に開発環境の導入です。以前確か「既存のライブラリは使わず自力で実装します」と言ったのですが、やはり無理でした。その理由は

  • 自分があまりにも RISC-V について知らなすぎる
  • Longna Nano のコアマニュアルがぐっちゃぐちゃで読めたものではない
  • コアマニュアル自体にも不備があり、必要な情報が一切掲載されていない

というものでした。これではおいおい使う割り込みだとか、モード切り替えだとかができないので、泣く泣く公式ファームウェアを導入するということです。

でも

相変わらず、極力既存の初期化関数を用いずにレジスタ手打ちをしていきたいと思っています。
ですので方針は変わらず、これまでどおり楽しんでいきたいと思いますので、これからもよろしくお願いします。

※注意:
ただ、何故かプログラムが動くときと動かないときがあります。具体的には、生成したオブジェクトファイルを最後にまとめてリンクする時、引数として渡す順番によって動く場合と動かない場合があります。これは RISC-V Toolchains として配布されている riscv-none-embed-gcc を用いたときも同様です。どうしたことか...
しかも、こちらの Lチカリポジトリでビルド→書き込みを行ったときも同じ状況。。。

取り敢えず、現状動く状態のコードを提供します。この謎も今後取り組んでいく所存です。

→→ 次回の記事で解決しています。結論から言うと書き込みツールの問題でした。

ファームウェアの導入

ARM でいう CMSIS を導入しましょう。前提として、riscv-unknown-elf という target 設定でコンパイラをビルドしてあるということにします。

まず、公式の GitHub リポジトリからファームウェアを持ってきます。

$ cd ~
$ git clone https://github.com/riscv-mcu/GD32VF103_Firmware_Library

そこから、Firmware ディレクトリを持ってきます。プロジェクトのルートディレクトリは ~/Registers としましょう。
さらに、

$ mkdir -p ~/Registers/inc ~/Registers/src ~/Registers/obj # ビルドに必要なディレクトリを作っておく
$ cp -r ~/GD32VF103_Firmware_Library/Firmware ~/Registers

この Firmware から必要なファイルを持ってきます。

$ cd ~/Registers
$ cp Firmware/RISCV/env_Eclipse/GD32VF103xB.lds linker.ld
$ cp Firmware/RISCV/env_Eclipse/entry.S src/entrty.s
$ cp Firmware/RISCV/env_Eclipse/start.S src/start.s
$ cp Firmware/RISCV/env_Eclipse/init.c src

つづいて、先程の GD32VF103_Firmware_Library から Template ディレクトリの一部を持ってきます。

$ cd 
$ cp ~/GD32VF103_Firmware_Library/Template/handlers.c src
$ cp ~/GD32VF103_Firmware_Library/Template/systick.c src
$ cp ~/GD32VF103_Firmware_Library/Template/systick.h inc
$ cp ~/GD32VF103_Firmware_Library/Template/gd32vf103_libopt.h inc

続いて、Makefile です。以下のような構成にしました。

最後に main.c です。

#include <gd32vf103.h>

int main(void){
    rcu_periph_clock_enable(RCU_GPIOC);
    gpio_init(GPIOC, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_ALL);
    while(1) {
        for(volatile long long i=0; i<100000; i++) asm volatile("nop");
        GPIO_OCTL(GPIOC) ^= GPIO_PIN_13;
    }
    return 0;
}

最終的にこんな構成になっていればOKです。

.
├── Firmware
│   ├── GD32VF103_standard_peripheral
│   ├── GD32VF103_usbfs_driver
│   └── RISCV
│       ├── drivers
│       ├── env_Eclipse
│       └── stubs
├── Makefile
├── inc
│   ├── gd32vf103_libopt.h
│   └── systick.h
├── linker.ld
├── obj
└── src
    ├── entrty.s
    ├── handlers.c
    ├── init.c
    ├── main.c
    ├── start.s
    └── systick.c

最後の最後ですが、src/start.s の 235 行目から3行をコメントアウトします。これがあると何故か動きません。
次回の記事参照:。

    //la a0, __libc_fini_array
    //call atexit
    //call __libc_init_array

あとは make && make flash で書き込むことができます。リセット後はボード上の赤色 LED がチカチカしているはずです。

極力レジスタを叩くLチカ

お前、甘えてるんじゃないぞと思っている人はいるでしょう。すみません。甘えずにレジスタを叩きます。

#include <gd32vf103.h>

int main(void){
    RCU_APB2EN |= RCU_APB2EN_PCEN;
    GPIO_CTL1(GPIOC) &= ~GPIO_MODE_MASK(13 - 8);
    GPIO_CTL1(GPIOC) |= GPIO_MODE_SET(13 - 8, GPIO_OSPEED_2MHZ | (GPIO_MODE_OUT_PP & 0x10));
    while(1) {
        for(volatile long long i=0; i<100000; i++) asm volatile("nop");
        GPIO_OCTL(GPIOC) ^= GPIO_PIN_13;
    }
    return 0;
}

これで許して。

今後の課題

  • リンク順番を変えることによる動作の可否が変わってしまう問題の解明
    • 次回の記事にて解決。プログラムは何ら問題なく、書き込みツールの問題だった。