Realtek AmebaのSPIを使ってみました。
まとめ
- Realtek AmebaのSPIのAPIはmebd HAL準拠のAPIとして提供される。
- SPIマスタとSPIスレーブの両方をサポート
準備
- コンパイラはlaunchpadからarm-none-eabi-gccをインストールしてください。
- SDKはgithubにある https://github.com/eggman/rtl_ameba_gcc_sample を使います。
SPIのAPI
- ROM内蔵HALのAPIとmbed halのAPIとmbed 拡張halのAPIがあります。
- ROM内蔵HALは情報が不足しているのでよくわかりません。
- mbed拡張HALは今回のSDK環境に入っていないので、また別の機会に説明します。
- mbed halのSPIについて説明していきます。
mbed HAL SPI
- sdk/src/sw/lib/sw_lib/mbed/hal/spi_api.h がAPIのヘッダファイルです。
- このAPIのソースコードは https://github.com/neojou/arm-gcc-blink-example/blob/master/src/sw/lib/sw_lib/mbed/targets/hal/rtl8195a/spi_api.c にあります。
void spi_init (spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel);
void spi_free (spi_t *obj);
void spi_format (spi_t *obj, int bits, int mode, int slave);
void spi_frequency (spi_t *obj, int hz);
int spi_master_write (spi_t *obj, int value);
int spi_slave_receive(spi_t *obj);
int spi_slave_read (spi_t *obj);
void spi_slave_write (spi_t *obj, int value);
int spi_busy (spi_t *obj);
spi_init()
- SPIの初期化、4つの端子 MOSI MISO SCLK CSを設定する。
spi_free()
- SPIの解放。 端子割り当てが解放されるっぽい。
spi_format()
- bits 1転送単位のbit幅を指定、通常は8
- mode 0-3のSPIモードを設定
- slave 0ならマスター、1ならslave
spi_frequency()
- SPIマスターの場合に、SPICLKの周波数を設定する。 SPIブロックに供給されているクロックの分周器の設定。
spi_master_write()
- SPIマスター動作時に使う valueをSPIスレーブに書き込み、読み込んだ値を戻り値として返す。
- 1転送単位ごとに、自動的にCSが無効→有効→無効となります。 マルチ転送したい場合は、CSを別途GPIOで制御が必要。
spi_slave_reeive()
- SPIスレーブ動作時に使う 受信バッファにデータがあるか確認する 0:データなし、0以外:データあり
spi_slave_read()
- SPIスレーブ動作時に使う 受信バッファを読みだし、値を戻り値として返す。
spi_slave_write()
- SPIスレーブ動作時に使う 送信バッファにvalueを設定する。
spi_busy()
- SPIを使用中かどうか確認する。0:空いてる 0以外:使用中
サンプルコード
- SPIマスタの動作を確認してみたときのコードです。
- CSがLowになり、SPIクロックが送信され、8バイトのデータが送信されることを確認しました。
#define SPI0_MOSI PC_2
#define SPI0_MISO PC_3
#define SPI0_SCLK PC_1
#define SPI0_CS PC_0
spi_t spi_master;
spi_init(&spi_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS);
spi_format(&spi_master, 8, 0 , 0);
spi_frequency(&spi_master, 20*1000*1000);
spi_master_write(&spi_master, c);
Ameba の SPI の HWについて
- AmebaのSPIの中身はSynopsys Design Ware SSIです。
- Synopsys Design Ware SSI は Altera の FPGA Cyclone Vに載っていて、Alteraから詳しいマニュアルが入手できます。
- https://www.altera.com/en_US/pdfs/literature/hb/cyclone-v/cv_5v4.pdf
その他
- spi_frequency(20000000)と20MHzを設定した場合の実際のクロックをロジアナで測定したところ5MHzでした。
- 内部のバスクロックを分周しているので、元のバスクロックが低いのか、SPIの分周を設定しているレジスタ baudrのsckdvの設定が正しくないのかもしれません。
- 調べてみたところ、baudrのsckdvが8に設定されており、40/8 = 5MHzになっていました。
DiagPrintf("SSI0 SCKDV %x\r\n", HAL_READ16(SSI0_REG_BASE, REG_DW_SSI_BAUDR));
を実行すると
SSI0 SCKDV 8
と表示されました。
* 下記のコードをしたらbaudrのsckdvが2となり 20MHzで動くようになりました。SDKのlib_platform.aに含まれているspi_freq()に問題があるようです。
PHAL_SSI_ADAPTOR pHalSsiAdaptor;
PHAL_SSI_OP pHalSsiOp;
pHalSsiAdaptor = &pspi->spi_adp;
pHalSsiOp = &pspi->spi_op;
pHalSsiAdaptor->ClockDivider = 2;
pHalSsiOp->HalSsiInit(pHalSsiAdaptor);
- 上記で説明したAPIはポーリング動作のようです。
- 割り込みやDMAを使ったAPIがmed拡張APIで定義されいます。