8
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Tang NanoのFPGAとPC間でUART通信をする

概要

Tang Nanoに搭載されているFPGA書き込み用のIC CH552T とFPGAとの間は、書き込みのためのJTAGの信号以外に、UARTの信号が接続されています。

よって、UARTの回路をFPGAに実装すればPCと通信出来ると思われたので、試しにFPGA内でUARTのTXとRXを直結したところ、PCから送信した文字がそのまま返ってくることを確認出来ました。

ただし、PCとFPGAでUART通信を行うにはいくつか作業が必要なので、手順を書いておきます。

プロジェクトの設定

Tang Nanoの回路図より、CH552TのUART信号は、FPGAのRECONFIG_NおよびDONEピンに接続されています。

Tang Nanoの回路図 (1)Tang Nanoの回路図 (2)Tang Nanoの回路図 (3)

このRECONFIG_NおよびDONEピンは、FPGAのコンフィグレーションに用いるピンなので、デフォルトのプロジェクト設定ではユーザー・ロジックから使用することができません。
よって、これらのピンを使用するために、以下のプロジェクトの設定を変更する必要があります。

  1. Project->Configuration メニューを選択して、Configurationsダイアログを表示します。
    image.png

  2. ConfigurationsダイアログでDual-Purpose Pinを選択し、Use DONE as regular IOUse RECONFIG_N as regular IOにチェックを入れてOKボタンを押します。

これでUARTの信号が接続されているピンをユーザー・ロジックから使用できるようになります。

GUIを使わずに合成をしている場合は、gw_shでadd_file -cfgで指定しているdevice.cfgファイルにset DONE regular_io = trueset RECONFIG_N regular_io = true を設定すると、DONEピンと RECONFIG_Nをユーザー・ロジックから使用できるようになります。

device.cfg
set DONE regular_io = true
set RECONFIG_N regular_io = true

CH552Tのファームウェアの更新

上記設定をして、FPGA内部でRECONFIG_NとDONEを接続したデザインを書き込み、PCから送信したデータがそのまま返ってくるかどうか確認しましたが、返ってきませんでした。

という内容をツイートしていたところ、

ということで、ファームウェアが古いということを教えてもらいました。
確かに、Tang Nanoではなく自作GOWIN FPGAボードには上記ファームウェアをビルドして書き込んで使っていましたが、そちらではUARTが使用できていました。

試しにTang NanoのCH552Tのファームウェアを更新してみたところ、PCから送信したデータが返ってくることを確認できました。

ファームウェアのビルド

CH552TのファームウェアのソースコードはGitHubのリポジトリで公開されていますので、以下の手順でビルドします。(筆者の環境はUbuntu 18.04なので、Ubuntu 18.04での手順を示します)
ビルドするのが面倒な人向けにビルド済みバイナリも用意してあります。

  1. ビルドに必要なパッケージ (gitとコンパイラとMakeとbinutils)をインストールします

    $ sudo apt install git sdcc make binutils
    
  2. ソースコードをcloneします

    $ git clone --recursive https://github.com/diodep/ch55x_jtag
    
  3. ファームウェアをビルドします

    $ cd ch55x_jtag/src
    $ make
    

これで、ch55x_jtag/src/usb_jtag.bin が生成されます。

ファームウェアの書き込み

CH552TはUSB経由でファームウェアを更新することができます。Windowsであれば、CH552Tの製造元純正の書き込みツールWCHISPToolで更新できます。Linuxではch552toolというPythonスクリプトで更新できます。

Windowsでの手順

WindowsではWCHISPToolを使用するので、あらかじめ製造元のページからダウンロード してインストールしておきます。

CH552Tにファームウェアを書き込むには、CH552Tを書き込みモード(ブートローダーモード)にする必要があります。そのための方法は以下の2つがあります。

  • CH552Tの14番ピンと20番ピンをショートした状態でUSBケーブルを接続する
  • FT_Progを使う

前者の方法の手順は言葉通りの手順です。14番ピンと20番ピンをピンセットなどで挟んでショートしながら、Tang NanoのUSBケーブルを差し込みます。
ほかのピンに触れるなどするとPCのUSBポートやTang Nanoが壊れる可能性がありますので、慎重に行います。

後者の方法は電気的には安全ですが、FTDIが自社のチップ向けに公開しているFT_Progを他社製のチップのために使うことになりますので、ライセンス的にどうかは微妙なところです。 (そもそもWindowsドライバのライセンスがヤバいという話もある)。
このあたりを承知の上で作業する方向けに手順を記載します。

ちなみに、FT_Progを使う方法もtwitterで教えていただきました。


  1. FT_Progを起動してDEVICES->Scan and Parseメニューを選択する


2. Device Treeにデバイスが表示されたら、DEVICES->Programメニューを選択し、Program DevicesダイアログでProgramボタンを押す

3. Programming Failedとエラーメッセージが表示されるので、OKを押して閉じる

以上でCH552Tが書き込みモードになりました。

次に、WCHISPToolでファームウェアを書き込みます。インストールしたWCHISPToolを起動します。

  1. 8 Bit CH55X series タブを選択し、Chip-optionグループのChip modelリストボックスからCH552を選びます。
  2. BeginDownloadグループのDeviceListにデバイス名が表示されていることを確認します。表示されない場合はCH552Tが書き込みモードになっていませんので、再度書き込みモードにする作業を行います。
  3. User Fileの右側のボタンをおして、ビルドしたusb_jtag.binを選択します。
  4. Download(D)ボタンを押して書き込み処理を実行します。
  5. Tang NanoからUSBケーブルを抜いて再度差し込みます。

以上で、ファームウェアのアップデート処理は終わりです。

Linuxでの手順

LinuxでCH552Tのファームウェアの更新を行うには、GitHubで公開されているch552toolを使います。

ch552toolはPythonで記述されており、USBデバイスの操作のためにPyUSBを使っているため、あらかじめPython及びPyUSBを入れておきます。
参考までにUbuntu 18.04での手順を記載します。

$ sudo apt install python3-pip
$ pip3 install pyusb

ch552toolはWindowsでのWCHISPtool同様に書き込みの処理を行いますが、書き込みモードに切り替える機能はありません。
一方、FT_ProgはWindows用のプログラムですので、Linuxでは使用できません。
対策として、FT_Progが送っているコマンドを送るPythonスクリプトを教えてもらったので、このスクリプトとch552toolを使った方法を以下に記載します。

  1. ch552toolをcloneします。

    $ git clone https://github.com/MarsTechHAN/ch552tool
    
  2. 以下のスクリプトをto_dfu.pyとしてch552toolをcloneしたディレクトリに保存します。

    to_dfu.py
    import sys
    import time
    import usb.core
    import usb.util
    
    dev = usb.core.find(idVendor=0x0403, idProduct=0x6010)
    
    if dev is None:
        dev = usb.core.find(idVendor=0x4348, idProduct=0x55e0) # WCH bootloader
        if dev is None:
            print("No devices are found.")
            sys.exit()
    else:    
        try:
            dev.ctrl_transfer(0x40, 0x91, 0, 0, 0)
        except usb.core.USBError as e:
            print('Apply magic success.')
    
    retryCounter = 20
    while retryCounter:
        print(".", end="")
        retryCounter = retryCounter - 1
        dev = usb.core.find(idVendor=0x4348, idProduct=0x55e0)
        time.sleep(0.5)
        if dev is not None:
            break
    print("CH552 is now in DFU mode.")
    
  3. to_dfu.pyを実行します。

    $ cd ch552tool
    $ python3 ./to_dfu.py
    Apply magic success.
    ..CH552 is now in DFU mode.
    
  4. ch552tool.pyを使ってusb_jtag.binを書き込みます。(~/ch55x_jtag/src/usb_jtag.binはusb_jtag.binのパスに置き換えてください)

    $ sudo python3 ch55xtool.py -f ~/ch55x_jtag/src/usb_jtag.bin -r
    Found CH552.
    BTVER: V2.31.
    Flash done.
    Restart and run.
    

以上でCH552Tのファームウェアの更新作業は完了です。

動作確認

前に作ったLチカプロジェクトにUARTのループバックを追加して動作確認しました。

blinky.sv

module blinky_top (
    input  wire resetn,
    output wire [2:0] gpio,
    input wire fpga_rx,
    output wire fpga_tx
);
    logic clk;
    OSCH #(
        .FREQ_DIV(125) // 250[MHz] / FREQ_DIV = output
    ) osc_inst (
        .OSCOUT(clk)
    );

    localparam int COUNTER_TOP = 32'd2_000_000 - 32'd1;

    assign fpga_tx = fpga_rx;
blinky.cst
IO_LOC "resetn" 15;
IO_PORT "resetn" IO_TYPE=LVCMOS33;

IO_LOC "gpio[0]" 18;
IO_PORT "gpio[0]" IO_TYPE=LVCMOS33;
IO_LOC "gpio[1]" 16;
IO_PORT "gpio[1]" IO_TYPE=LVCMOS33;
IO_LOC "gpio[2]" 17;
IO_PORT "gpio[2]" IO_TYPE=LVCMOS33;

IO_LOC "fpga_rx" 9;
IO_PORT "fpga_rx" IO_TYPE=LVCMOS33;
IO_LOC "fpga_tx" 8;
IO_PORT "fpga_tx" IO_TYPE=LVCMOS33;

合成したデザインを描き込んだ後、screenコマンドなどで、CH552Tに対する2個目のデバイスを開きます。(筆者の環境では/dev/ttyUSB1です)
ちなみに、UARTのボーレートはあまり速すぎない限りいくらでもいいです。今回は115200を指定しています。

$ screen /dev/ttyUSB1 115200

screen起動後文字入力すると、入力した文字が画面に表示されます。screenはローカルエコーをしないので、画面に入力文字が表示されるということは、UARTで送信した文字が返ってきていることを表します。
試しにUSBケーブルを抜き差しして、FPGAのデザインを元に戻してからscreenを実行すると、入力文字が返ってこないことが確認できます。

おわりに

Tang NanoでもPCとのUART通信が手軽に出来るようになりましたので、Tang Nanoの使い道が広がります。
合成後にパラメータをUARTで送ったり、デバッグ用データを送るなどが可能です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
8
Help us understand the problem. What are the problem?