3年以上前に購入したけど少し遊んで放置していた Sipeed Tang Nano 4K を、ちょっとやりたいことが出来て引っ張りだしてきました。以前試したときは、GOWINのプログラマアプリが Tang Nano 4K との組み合わせでは不安定で、「使えないなぁ」とあきらめたのでした。もちろん、私の実力不足なんですが…
今回、改めて使ってみたところ、以前引っかかったところにまた引っかかり、動かすまでにかなり時間を費やしたので、備忘録として残しておこうと思いました。まぁ他の記事もそうですが、素人なので間違ったことを書いていると思います。個人的メモです(笑)
ツール
開発ツールは、GOWINのWebからダウンロードできます。ユーザー登録が必要ですが無料です。
基本は企業や組織に所属している人が対象でしょうが、個人でもライセンスはもらえるようです。
Education版であればライセンスは不要ですが、利用条件を確認しておきましょう。
Tang Nano 4Kは、ARM Cotex M3(CM3)のハードコアを内蔵しています。
使いこなすには、FPGAの開発に加えて、CM3のソフト開発が必要です。
GOWIN EDAのページから必要なアプリケーション(IDE)を入手します。
バージョンは、更新されると思いますが、執筆時点での最新は以下の通りです。
- Gowin FPGA Designer (Gowin_V1.9.10.03)
FPGAの開発ツールです。
GOWIN Programmer も含まれています。 - GOWIN MCU Designer_V1.2
組み込みマイコン(Tang Nano 4KはハードコアのCM3)の開発ツールです。 - ライセンスは、FPGA Designer ,MCU Designer 別々に必要です。
デバイスの設定
Tang Nano 4Kに使用されているFPGAは、GW1NSR-LV4CQN48P C7/16です。
新規にプロジェクトを作る時に指定します。
回路図、サンプルコード、ドキュメント
- 回路図は、SipeedのWebにあります。
- サンプルコードは、ツールと一緒にインストールされています。C:\Gowin\Gowin_V1.9.10.03_x64\IDE\data\examples
C:\GMD\demo
Tang Nano 4K用は→ C:\GMD\demo\Gowin_EMPU(GW1NS-4C)
RTOSのサンプルコードは、C:\GMD\RTOS
Tang Nano 4K用は→ C:\GMD\RTOS\Gowin_EMPU(GW1NS-4C) - ドキュメントは、C:\Gowin\Gowin_V1.9.10.03_x64\IDE\doc にあります。
Projectの設定
Project→Configuration でプロジェクトの設定をします。
基本は、Synthesize以外はデフォルトで良いと思います。IOが足りなくなったらDual-Purpose Pinを設定ですね。
Synthesize で、トップモジュールの指定と、合成に使用するVerilog, VHDLのバー上ン等を設定します。
特殊機能ピンを通常のIOとして使う場合は、チェックします。
使用していないピンの処理を設定します。
Programmer/プログラマ
Tang nano 4Kに書き込むプログラムは、FPGAのコンフィグ(ビットストリーム)ファイル(拡張子.fs)、マイコンのバイナリーファイル(.bin)の2種類があります。内蔵のマイコンを使わずFPGAだけ使用する場合は、.fsだけ書き込めばOKです。Tang Nano 4KのUSB-C端子から書き込みます。
FPGAのみに書き込む場合
開発中で何度も書き換えるときは、SRAM Programにすると良いでしょう。ただし、電源を切るとコンフィグの内容は消えてしまいます。
電源を切ってもコンフィグが消えないようにするには、Embedded Flash Modeで書き込みます。
Operationは、embFlash Erase, Programを選択します。書き込み速度は速くすると失敗することが多いです。2.5MHzだと大体大丈夫です。私の環境だけかもしれませんがembFlash Erase, Program, Verifyを選ぶとなぜかエラーになります。
FPGAとマイコン両方に書き込む場合
Access ModeをMCU Modeにし、Operationを Firmware Erase, Programにします。
こちらもVerifyを選ぶとエラーになります。Verify ができないなんて、困ったもんです。ケーブルの問題かなぁ…
サンプルコードの確認
とりあえず、FreeRTOSを使いたいので、サンプルコードとして C:\GMD\RTOS\Gowin_EMPU(GW1NS-4C)\V1.2\cm3_free_rtos を使いました。
このサンプルコードは、GPIO_Pin_0とGPIO_Pin_1を交互にON/OFFするプログラムですが、バグがあるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//Initializes GPIO static void GPIOInit(void) { GPIO_InitTypeDef GPIO_InitType; GPIO_InitType.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitType.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitType.GPIO_Int = GPIO_Int_Disable; GPIO_Init(GPIO0,&GPIO_InitType); GPIO_SetBit(GPIO0,GPIO_Pin_0); GPIO_SetBit(GPIO0,GPIO_Pin_1); } |
GPIO_Pin_0は問題なく動作するのですが、GPIO_Pin_1からは信号が出力されませんでした。
GPIO_Pin_1が出力に設定されていないためでした、6行目に | GPIO_Pin_1 を追加しました。
Gowin確認してないな(笑)
ついでに、GPIO_Pin_1の初期値も追加しておきました。
また、確保しているスタックが少なく、プログラムに少し処理を追加するだけでスタックをつぶしてしまうようです。プログラムは問題なさそうなのに…なぜ動かないのか暫く悩みました。
そして、3年前にも同様に悩んだことを思い出したのが、今回このメモを残すきっかけになりました(笑)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//Task 1 #define LED0_TASK_PRIO 1 //#define LED0_STK_SIZE 16 #define LED0_STK_SIZE 128 TaskHandle_t LED0Task_Handler; //volatile int led0_task_flag = 0; volatile bool led0_task_flag = 0; //Task 2 #define LED1_TASK_PRIO 2 //#define LED1_STK_SIZE 16 #define LED1_STK_SIZE 128 TaskHandle_t LED1Task_Handler; //volatile int led1_task_flag = 0; volatile bool led1_task_flag = 0; |
4行目と12行目ですが、とりあえず、128byte確保しました。
FreeRTOSconfig.h のヒープも増やした方が良いと思います。
1 2 |
//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 1 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 2 * 1024 ) ) |
2k確保しましたが、ちょっと多すぎるかな…
マイコンを組み込む
言語を選んで(VHDLを選択)ブロック図の必要な機能をクリックします。
GPIOの選択
- GPIOを使用するには、Enable GPIOをチェックします。
- Enable GPIO I/Oをチェックすると、IN,OUT,Enable(Tri-State-Buffer)を統合したGPIOになりますが、このGPIOはFPGAのピンに接続するしかなく、内部の制御線としては使用できなくなるようです。
※間違っているかも - Enable GPIO I/Oをチェックを外すと、IN,OUT,Enableの3ブロックに分割されます。この状態であれば、内部の制御線としても使用できます。
内蔵マイコンのクロックスピード
スペックには、内蔵マイコンは最大80MHzのクロックで動作すると書かれています。
Tang Nano 4Kに搭載されている発振器は27MHzなので、内蔵のPLLでは81MHzか72MHzしか出すことができません。81MHzでも動作するかな?と思いましたが、残念ながら動作しませんでしたので、72MHzで使用しています。(一説によるとスペックの80MHzでも動作しないらしい…)
FreeRTOSのサンプルプログラムは25MHz用になっているので、修正しないとタイミングが合いません。
FreeRTOSConfig.hを修正しました。(ここで良いのかな?)
1 2 |
//#define configCPU_CLOCK_HZ ( ( unsigned long ) (25000000) ) #define configCPU_CLOCK_HZ ( ( unsigned long ) (72000000) ) |
また、system_gw1ns4c.c にもクロックを80MHzに設定していることろがありましたので72MHzに修正しました。__XTALを142MHzにしても良いのでしょうが…
1 2 3 4 5 6 7 8 9 10 11 12 |
/*---------------------------------------------------------------------------- Define clocks *----------------------------------------------------------------------------*/ #if 0 #define __XTAL (160000000UL) /* Oscillator frequency */ #define __SYSTEM_CLOCK (__XTAL / 2) /* 80MHz */ #else #define __SYSTEM_CLOCK 72000000UL /* 72MHz */ #endif |
FPGAの最適化
1 2 |
gpio_o(0) <= gpio(0); led_o <= gpio(0); |
デバッグの過程で、上記のように gpio_o(0), led_o ともに出力ポートに設定した時に、最適化により一方の出力がなくなる事がありました。
その場合には、以下のように最適化を制限する設定が有効です。
1 2 |
attribute syn_keep: integer; attribute syn_keep of led_o: signal is 1; |
ほかにも、syn_preserveがありますが、GowinSynthesisユーザーガイド.pdfによると、『syn_keep は、wire をプレースホルダーとして指定し、最適化しないままにします。reg を保持するには、「syn_preserve」を使用してください。』とあります。
1 2 |
attribute syn_preserve : integer; attribute syn_preserve of led_o : signal is 1; |