Spresense SDK 【HostIF】にワクワクしている話

この記事は[Spresense Advent Calendar 2023](https://qiita.com/advent-calendar/2023/spresense)の5日目（12/5分）です。

# 概要
Spresense SDKのチュートリアルに**HostIF**チュートリアルの記載があります。
このHostIFについて個人的にワクワクしています。その理由について掘り下げたいと考えています。

Spresense SDKでの開発 -> チュートリアル -> 13. HostIF チュートリアル

https://developer.sony.com/spresense/development-guides/sdk_tutorials_ja.html#_hostif_%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB

# 背景
去る2023/8/31にSWEST25に参加しました。SWEST25のコンテンツEmbLTで**NervesとSpresenseをHostIFで通信してみた**というタイトルでLTしました。

<script async class="docswell-embed" src="https://www.docswell.com/assets/libs/docswell-embed/docswell-embed.min.js" data-src="https://www.docswell.com/slide/5M1Q2G/embed" data-aspect="0.5625"></script><div class="docswell-link"><a href="https://www.docswell.com/s/juraruming/5M1Q2G-2023-09-01-172314">SWEST25_EmbLT_NervesとSpresenseをHostIFで通信してみた by @juraruming</a></div>

このLT・LT資料の中でSpresenseのHostIFについて触れました。

## HostIFに興味を持ったきっかけ
Spresenseは以前から興味をもっており、技術書を書いたりしていました。

リーマンサットプロジェクトの衛星RSP-02の記事でSpresenseのHostIF機能について具体的に知り、興味を持ちました。

https://www.rymansat.com/archives/14590

その後、リーマンサットプロジェクトにも参加し、今は広報の活動をしています。


## HostIFにワクワクしている理由
私がHostIF機能にワクワクしている理由は、

* Spresenseをサブシステムとして使う

という視点に魅力を感じているからです。
私はいままでSpresenseをシステムのメインマイコンとして使うことばかり考えてきましたが、HostIFはSpresenseとは別のマイコン・デバイスをHostにする構成となります。
Spresenseが持つ豊富な機能をホスト側に提供する、という視点を持つと何か新しいもの・システムが生まれそうな気がしています。

つぎの図はSpresense SDKのチュートリアル目次です。これらSpresenseが持つ多彩な機能をHostIF機能を通じて提供することが可能になるのでは?、と思いました。

![Spresenseチュートリアル目次.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/a74df104-95fa-26a0-63f9-c6c73e5e1ca5.png)


# HostIFについて
HostIF機能について説明します。

* SpresenseがHostIFを機能提供する側になる
* HostIFはSpresenseと外部のホスト役になるマイコン・デバイスとの通信機能
* 外部のホストマイコン・デバイスとの通信インタフェースはI2CかSPIを選択可能
* 1KByteの通信バッファに任意のサイズ、転送方向を設定可能
* **バッファに排他ロック機構**がある
ホストとSpresenseは安全にデータ送受信が可能!!!

## HostIF ホスト受信シーケンス
HostIF ホスト受信シーケンスの説明です。
図は下記のリンクからの引用です。

Spresense SDKの開発
-> 開発ガイド
-> 5.15.3.5.1. HOST 受信シーケンス

https://developer.sony.com/spresense/development-guides/sdk_developer_guide_ja.html#_host_%E5%8F%97%E4%BF%A1%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9

注目ポイントとしてSpresense Lock, Host Lockの箇所だと思います。
以下のようにデータ読み書きを排他制御することが可能です。

* Spreseseがデータ書込み中にホストが読込みすると失敗
* ホストが読込み中にSpresenseは書込みすると失敗

![host_receive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/85fb4e5e-30f6-acc0-f4b9-b95e9ed9b4e9.png)

## HostIF ホスト送信シーケンス
HostIF ホスト送信シーケンスの説明です。
図は下記のリンクからの引用です。

Spresense SDKの開発
-> 開発ガイド
-> 5.15.3.5.2. HOST 送信シーケンス

https://developer.sony.com/spresense/development-guides/sdk_developer_guide_ja.html#_host_%E9%80%81%E4%BF%A1%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9

注目ポイントとして受信シーケンスと同様にSpresense Lock, Host Lockの箇所だと思います。
以下のようにデータ読み書きを排他制御することが可能です。

* ホストがデータ書込み中にSpresenseが読込みすると失敗
* Spresenseが読込み中にホストが書込みすると失敗

![host_send.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/cfbaff41-75a8-ab8c-116b-aa7cd508e950.png)

## HostIFの配線
HostIFの配線について説明します。

## HostIFの信号線の引き出し
HostIFを提供するSpresenseですが、[SPRESENSE用 100ピンB2Bコネクタ ピッチ変換基板](https://www.switch-science.com/products/3999/)などでHostIFの信号線を引き出す必要があります。
理由としては **【Spresenseメインボード、Spresense拡張ボードにHostIFの信号線がないため】** です。

## ホストとの電圧の違いに気をつける
Spresenseメインボード + 100ピンB2Bコネクタ ピッチ変換基板でHostIFの信号を引き出したとして、接続するホストとの電圧に気をつけます。
Spresenseメインボードは1.8Vなので3.3V, 5VのデバイスとHostIFで通信する場合はレベル変換ICを利用するなどしてレベル変換の必要があります。

# Spresense SDKのHostIFチュートリアルのサンプルプログラムについて
## 配線
チュートリアルのサンプルプログラムはI2CまたはSPI接続を選択可能です。
**ホストがSpresenseで1.8Vのため、HostIF提供側との間にレベル変換は不要**です。

下図はI2Cの場合の配線図です。

![hostif_i2c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/478c7a78-87fb-7256-9ec0-0eece9a396c1.png)

配線図はSpresenseの下記のドキュメントからの引用です。

Spresense SDK チュートリアル -> 13. HostIF チュートリアル -> 13.1. HostIF サンプルアプリケーション -> 13.1.1. 動作環境 -> I2C 接続構成

https://developer.sony.com/spresense/development-guides/sdk_tutorials_ja.html#_%E5%8B%95%E4%BD%9C%E7%92%B0%E5%A2%83_16


下図はSPIの場合の配線図です。

![hostif_spi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/26c3d2ad-dbbf-2c7b-ae2b-7d5d15b97672.png)

配線図はI2C同様、Spresenseのドキュメントからの引用です。


## サンプルプログラム概要
Spresense SDKのHostIFチュートリアルのサンプルプログラムについて説明します。
サンプルプログラムのホストはSpresense（開発環境はSpresense SDK）です。

下図はサンプルプログラムのアクティビティ図です。
ホスト, Spresense間でHostIF機能を使いデータの読み書きを行います。

![HostIFチュートリアルサンプルプログラム概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/79c7cfd2-3038-8316-1435-2ea1dedae9bf.png)

下図はサンプルプログラムのHostIFバッファ構成です。

![HostIF通信バッファ構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/4244b324-8e9e-f085-3ad8-2e950ad5bb4f.png)



# 確認したこと
今回Spresense SDKのチュートリアルのサンプルプログラムのホスト役を以下に示すシステム・マイコンに変更してHostIF機能を試してみました。

## ホストがSpresense（Arduino IDE, C/C++）
### 配線
ホストはSpresenseでチュートリアルのサンプルプログラムと変わりません。
Spresenseの開発環境をArduino IDEに変更しました。
ホストはSpresenseで電圧が1.8Vのため、HostIF提供側のSpresenseとレベル変換なしで直結できます。
通信はSPIを試しました。

![hostif_arduino_ide.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/c3207787-75eb-4686-1424-ec9504645cd3.png)

### コード
確認に使用したコードはつぎになります。
とくに問題なく、HostIFで通信ができました。
これでSpresense SDKの開発環境に限定されず、SPI（またはI2C）のインタフェースを持つデバイス・マイコンと通信できることが確認できました。

https://github.com/grace2riku/spresense_host_if_test


## ホストがラズパイ4（Nerves, Elixir）
### 配線
ホストはラズパイ4としました。
ラズパイ4はNerves上で動き、HostIFのホストとしての動きはElixirで実装しました。
システムの構成をNervesとした理由ですがNervesが好きで、低レベルのデバイス制御をやってみたかったという個人的な理由です。
ラズパイは電圧が3.3Vのため、HostIF提供側のSpresenseとの間にレベル変換ICを置き、接続しました。
通信はSPIとしました。

![hostif_nerves.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/40a26bdf-b689-efbf-876c-99a3d3d58d0b.png)

### コード
確認に使用したコードはつぎになります。
ホストからの読込みは確認できましたが、書込みは未実装です。

https://github.com/grace2riku/nerves_laboratory

spresense_hostifディレクトリ以下がコードになっています。

Nerves, Elixirについては背景の章で紹介した資料に書きました。適宜、参照ください。

## ホストがSTM32（NUCLEO-F446RE）
### 配線
ホストはSTマイクロエレクトにクス社のマイコンSTM32でマイコンボードはNUCLEO-F446REとしました。
STM32はOSなしのベアメタルで、統合開発環境STM32CubeIDEのコード（HAL）を使いました。
このマイコンボードは電圧が3.3Vのため、HostIF提供側のSpresenseとの間にレベル変換ICを置き、接続しました。
通信はSPIとしました。

![hostif_stm32_NUCLEO-F446RE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/ce713055-6bbf-c4a8-7fc0-96e90ef004c1.png)

### コード
確認に使用したコードはつぎになります。
こちらのコードは文字化けが発生しており、ハードウェア要因かソフトウェア要因か切り分けがついていない状態です。
参考までに掲載します。

https://github.com/grace2riku/spresense_hostif_host_at_stm32


## その他、考えられる構成
前述の構成以外でHostIFのホストを考えてみました。動作は確認していません。

### ホストがPC + FTDI USB MPSSEケーブル（Windows）
#### 配線
ホストがPCでOSがWindowsの構成です。
ホストPCとFTDI USB MPSSEケーブルをUSBで接続し、MPSSEケーブルをI2CまたはSPIでSpresenseと接続します。
MPSSEケーブルは電圧が3.3Vのため、HostIF提供側のSpresenseとの間にレベル変換ICを置く必要があります。

![hostif_windows_ftdi_mpsse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/b9ce3c30-5d0b-502d-544a-41d35a77d55f.png)

##### FTDI USB MPSSEケーブルについて
PCとこのケーブルを接続し、シリアル通信（I2C、SPI、JTAG）が可能になります。
PCとターゲットデバイスを直結することが可能になります。

https://www.ftdichip.com/old2020/Products/Cables/USBMPSSE.htm

* [FTDI USB MPSSEケーブル C232HM-DDHSL-0（3.3V）, C232HM-EDHSL-0（5V）のデータシート](https://www.ftdichip.com/old2020/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.pdf)

### ホストがPC + FTDI USB MPSSEケーブル（Linux）
#### 配線
ホストがPCでOSがLinunxの構成です。
前述のPC（Windows）とOSだけが異なり、その他は同じ構成です。

![hostif_linux_ftdi_mpsse.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/df56dc23-1b69-f466-3037-e492f84b4b0d.png)


### ホストがFPGA
#### 配線
ホストがFPGAの構成です。
Spresenseとリアルタイムな制御を行いたいシステム構成にマッチするかもしれません。

![hostif_fpga.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171866/01656b19-9a48-4ed8-5606-342ddcdb42d4.png)

# まとめ
SpresenseのHostIFに注目して記事を書きました。
個人的なHostIFの推しポイントはつぎになります。

* ホストとの間の排他制御機能で安全な通信が実現できる
* Spresenseの豊富な機能をホストに提供する、というアプローチができる

気になった方はSpresenseのHostIF機能を使ってみては如何でしょうか?