📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の6版が非表示) | |||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
MSPM0G3519は、Texas Instruments社の32ビットARM Cortex-M0+コアを搭載したマイコンである。<br> | |||
しかし、イーサネット機能は内蔵していないため、TCP/IP通信を行うには、外付けのイーサネットコントローラIC (ENC28J60等) | 最大80[MHz]で動作し、512[KB]のフラッシュROMと128[KB]のSRAMを搭載している。<br> | ||
しかし、イーサネット機能は内蔵していないため、TCP/IP通信を行うには、外付けのイーサネットコントローラIC (ENC28J60等) とlwIPまたはuIPライブラリを組み合わせて使用する。<br> | |||
<br> | <br> | ||
lwIPは、スウェーデンのAdam Dunkels氏が開発した軽量TCP/IPスタックで、uIPの後継として位置付けられている。<br> | |||
MSPM0G3519は十分なRAM容量 (128[KB]) を持つため、lwIPの使用が推奨される。<br> | |||
<br> | |||
lwIPは、より高速で安定したTCP/IP通信を実現し、多数の同時接続に対応できる。<br> | |||
<br> | <br> | ||
主な構成は以下の通りである。<br> | 主な構成は以下の通りである。<br> | ||
* | * MSPM0G3519 (マイコン) | ||
* ENC28J60 (イーサネットコントローラ) | * ENC28J60 (イーサネットコントローラ) | ||
* SPIインターフェース | |||
* lwIPライブラリ (TCP/IPスタック) | |||
*: <u>推奨</u> | |||
* uIPライブラリ (TCP/IPスタック) | * uIPライブラリ (TCP/IPスタック) | ||
* | *: 軽量版 : 非推奨 (メンテナンスされていない) | ||
<br> | |||
この構成により、MSPM0G3519を使用したWebサーバ、HTTPクライアント、Telnetサーバ、UDPアプリケーション、DHCPクライアント、DNSクライアント等の構築が可能となる。<br> | |||
<br><br> | |||
== ENC28J60 と W5500 == | |||
イーサネット通信を実現するには、大きく分けて2つの階層がある。 | |||
* 上位層 | |||
*: ネットワーク層以上で、TCP/IPプロトコルの処理を行う。 | |||
* 下位層 | |||
*: <u>物理層</u> および <u>データリンク層</u> で、イーサネットフレームの送受信を担当する。 | |||
<br> | |||
ENC28J60は下位層のみを持つICである。<br> | |||
イーサネットフレームの送受信はできるが、TCP/IPプロトコルの処理機能は持たない。<br> | |||
これを <u>イーサネットMAC/PHYコントローラ</u> と呼ぶ。<br> | |||
<br> | <br> | ||
一方、W5500は、上位層および下位層の両方をIC内に持つため、TCP/IPの複雑な処理も含めて全てW5500が自動的に処理する。<br> | |||
これを <u>ハードウェアTCP/IPスタック内蔵型</u> と呼ぶ。<br> | |||
<br><br> | <br><br> | ||
| 31行目: | 53行目: | ||
* マルチスレッド対応 | * マルチスレッド対応 | ||
*: RTOSと組み合わせた使用が可能 | *: RTOSと組み合わせた使用が可能 | ||
*: | *: ただし、MSPM0G3519では通常はシングルスレッド構成 (NO_SYS=1) で使用する | ||
* 移植性 | * 移植性 | ||
*: C言語で記述されており、様々なマイコンに移植可能 | *: C言語で記述されており、様々なマイコンに移植可能 | ||
*: ハードウェア依存部分が明確に分離されている | *: ハードウェア依存部分が明確に分離されている | ||
<br> | <br> | ||
<u> | <u>※MSPM0G3519でのlwIP使用について</u><br> | ||
<u> | <u>MSPM0G3519は、512[KB]のフラッシュと128[KB]のSRAMを持つため、lwIPを標準構成で十分に使用できる。</u><br> | ||
<u>これにより、以下に示すメリットが得られる。</u><br> | |||
* メリット | * メリット | ||
*: より多くの同時接続に対応 (通常10〜50接続以上) | *: より多くの同時接続に対応 (通常10〜50接続以上) | ||
| 43行目: | 66行目: | ||
*: DHCP、DNS等の上位機能を標準サポート | *: DHCP、DNS等の上位機能を標準サポート | ||
*: より安定したTCP実装 | *: より安定したTCP実装 | ||
*: パケットの分割送信と再送処理が効率的 | |||
*: ゼロコピー機能によるメモリ効率の向上 | |||
*: <br> | *: <br> | ||
* デメリット | * デメリット | ||
*: | *: uIPと比較して、初期設定がやや複雑 | ||
*: | *: コードサイズが大きい (ただし、MSPM0G3519のフラッシュ容量で十分に収まる) | ||
<br> | <br> | ||
MSPM0G3519では、lwIPの使用を推奨する。<br> | |||
RAMとフラッシュROMに十分な余裕があるため、lwIPの高機能性を最大限活用できる。<br> | |||
軽量なアプリケーションにはuIPも使用可能であるが、将来的な機能拡張を考慮すると、lwIPの採用がより適切である。<br> | |||
<br><br> | <br><br> | ||
== uIPライブラリの特徴 == | == uIPライブラリの特徴 == | ||
<u>uIPは既にメンテナンスされていないため、使用は非推奨である。</u><br> | |||
<br> | |||
uIPは、組み込みシステム向けに最適化された軽量TCP/IPプロトコルスタックである。<br> | uIPは、組み込みシステム向けに最適化された軽量TCP/IPプロトコルスタックである。<br> | ||
<br> | <br> | ||
| 79行目: | 101行目: | ||
<u>同時接続数が限られており (通常1〜10接続程度)、スループットよりも省メモリを優先した設計となっている。</u><br> | <u>同時接続数が限られており (通常1〜10接続程度)、スループットよりも省メモリを優先した設計となっている。</u><br> | ||
<u>高速通信や多数の同時接続が必要な場合は、lwIP等のより高機能なスタックの使用を検討する必要がある。</u><br> | <u>高速通信や多数の同時接続が必要な場合は、lwIP等のより高機能なスタックの使用を検討する必要がある。</u><br> | ||
<br> | |||
<u>MSPM0G3519は128[KB]の十分なRAMを持つため、特別な理由がない限りlwIPの使用を推奨する。</u><br> | |||
<br><br> | <br><br> | ||
== ENC28J60イーサネットコントローラ == | == ENC28J60イーサネットコントローラ == | ||
MSPM0G3519はイーサネットコントローラを内蔵していないため、外付けのイーサネットコントローラチップが必要となる。<br> | |||
<br> | <br> | ||
Microchip社のENC28J60は、SPI接続のイーサネットコントローラで、組み込みシステムで広く使用されている。<br> | |||
<br> | <br> | ||
* IEEE 802.3準拠の10BASE-T Ethernetコントローラ | * IEEE 802.3準拠の10BASE-T Ethernetコントローラ | ||
* SPIインターフェース ( | * SPIインターフェース (最大20[MHz]) | ||
* 内蔵8KBのバッファRAM | * 内蔵8KBのバッファRAM | ||
* MACおよびPHY機能を統合 | * MACおよびPHY機能を統合 | ||
| 99行目: | 123行目: | ||
* 入手性が良好で、価格も比較的安価 | * 入手性が良好で、価格も比較的安価 | ||
* 豊富なサンプルコードとドキュメント | * 豊富なサンプルコードとドキュメント | ||
* | * MSPM0G3519のSPIペリフェラルで容易に接続可能 | ||
<br> | <br> | ||
<u>デメリット</u><br> | <u>デメリット</u><br> | ||
* | * 10[Mbps]のみの対応 (100[Mbps]非対応) | ||
* SPIのオーバーヘッドによりスループットが制限される。 | * SPIのオーバーヘッドによりスループットが制限される。 | ||
<br> | <br> | ||
| 109行目: | 133行目: | ||
<br><br> | <br><br> | ||
== | == MSPM0G3519の特徴 == | ||
MSPM0G3519は、Texas Instruments社の32ビットARM Cortex-M0+コアを搭載したマイコンで、MSPM0ファミリの上位モデルである。<br> | |||
<br> | <br> | ||
MSPM0G3519の主な特徴を以下に示す。<br> | |||
<br> | <br> | ||
* 128[KB] | * コア | ||
* | *: ARM 32ビット Cortex-M0+ CPU (最大80[MHz]) | ||
* | *: メモリ保護ユニット (MPU) 搭載 | ||
* | * メモリ | ||
* | *: 512[KB] フラッシュROM (デュアルバンク、ECC付き) | ||
* | *: 128[KB] SRAM (合計) | ||
* | **: SRAM バンク0: 64[KB] (ECC保護またはハードウェアパリティ、スタンバイモードまで保持) | ||
* | **: SRAM バンク1: 64[KB] (STOPモードまで保持) | ||
* | *: 16[KB] データフラッシュバンク (ECC保護) | ||
* | * 高性能アナログペリフェラル | ||
* | *: 2個の同時サンプリング12ビット4[Msps] ADC (最大27外部チャネル) | ||
*: 1個の12ビット1Msps DAC (出力バッファ内蔵) | |||
*: 3個の高速コンパレータ (8ビットリファレンスDAC内蔵) | |||
*: 内部共有電圧リファレンス (1.4[V] または 2.5[V]) | |||
*: 温度センサ内蔵 | |||
* 通信インターフェース | |||
*: 7個のUARTインターフェース | |||
**: 2個はLIN、IrDA、DALI、スマートカード、マンチェスターをサポート | |||
**: 3個はスタンバイモードでの低消費電力動作をサポート | |||
*: 3個のI2Cインターフェース (FM+ 1[Mbit/s]対応、STOP モードからのウェークアップ対応) | |||
*: 3個のSPIインターフェース (1個は最大32[Mbit/s]) | |||
*: 2個のCAN-FDインターフェース (CAN 2.0 A/B、CAN-FD対応) | |||
* タイマ / DMA | |||
*: 9個のタイマ (最大28個のPWMチャネル対応) | |||
*: 12チャネルDMAコントローラ | |||
* セキュリティ機能 | |||
*: AES-128/256アクセラレータ (GCM/GMAC、CCM/CBC-MAC、CBC、CTR対応) | |||
*: セキュアキーストレージ (最大4個のAESキー) | |||
*: 真性乱数生成器 (TRNG) | |||
*: フレキシブルなファイアウォール | |||
* その他 | |||
*: 最大94個のGPIO | |||
*: RTC (アラームおよびカレンダーモード付き) | |||
*: ウォッチドッグタイマ | |||
*: 低消費電力モード対応 | |||
*: 動作電圧: 1.62[V]〜3.6[V] | |||
*: 動作温度範囲: -40[℃]〜125[℃] | |||
<br> | <br> | ||
lwIP実装に必要なリソース要件は以下の通りである。<br> | |||
* フラッシュROM | * フラッシュROM | ||
*: | *: 約50〜80[KB] (lwIP本体+ドライバ+アプリケーション) | ||
* RAM | * RAM | ||
*: | *: 約20〜40[KB] (バッファ+メモリプール+スタック変数) | ||
<br> | <br> | ||
MSPM0G3519のリソースは、これらの要件を十分に満たしているため、lwIPの実装に適している。<br> | |||
MSP430F5529と比較して、以下の点で大幅に優位性がある。<br> | |||
* RAMが16倍 (8[KB] → 128[KB]) で、多数の同時接続とバッファを確保可能 | |||
* フラッシュが4倍 (128[KB] → 512[KB]) で、より多くの機能を実装可能 | |||
* 32ビットアーキテクチャにより、TCP/IP処理が高速 | |||
* 高速クロック (80[MHz]) により、SPIスループットが向上 | |||
* 12チャネルDMAコントローラにより、CPUを介さずにSPIデータ転送が可能 | |||
* CAN-FD対応により、車載やFA分野での応用が可能 | |||
<br><br> | <br><br> | ||
== ハードウェア接続 == | == ハードウェア接続 == | ||
MSPM0G3519とENC28J60は、SPIインターフェースで接続する。<br> | |||
<br> | <br> | ||
下表にMSPM0G3519のSPI0モジュールを使用する接続例を示す。<br> | |||
<br> | <br> | ||
<center> | <center> | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ ピン接続表 (ENC28J60) | |+ ピン接続表 (ENC28J60) | ||
! | ! MSPM0G3519 !! ENC28J60 !! 機能 !! 説明 | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PB8 (SPI0_PICO) || style="text-align:center;" | MOSI (SI) || SPI || コントローラ出力/ペリフェラル入力 | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PB7 (SPI0_POCI) || style="text-align:center;" | MISO (SO) || SPI || コントローラ入力/ペリフェラル出力 | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PB9 (SPI0_SCLK) || style="text-align:center;" | SCLK (SCK) || SPI || シリアルクロック | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PB6 (GPIO) || style="text-align:center;" | CS# || 制御信号 || チップセレクト<br> (アクティブLow) | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PA18 (GPIO) || style="text-align:center;" | RESET# || 制御信号 || リセット信号<br> (アクティブLow) | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | PA17 (GPIO) || style="text-align:center;" | INT || 割り込み || 割り込み信号<br> (アクティブLow) | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | VDD || style="text-align:center;" | VCC || 電源 || 3.3V | ||
|- | |- | ||
| style="text-align:center;" | | | style="text-align:center;" | VSS || style="text-align:center;" | VSS || GND || グランド | ||
|} | |} | ||
</center> | </center> | ||
| 172行目: | 229行目: | ||
* LEDインジケータ | * LEDインジケータ | ||
*: LEDA (ピン15)、LEDB (ピン14) に接続可能 | *: LEDA (ピン15)、LEDB (ピン14) に接続可能 | ||
* ピン配置 | |||
*: 上記のピン配置は一例であり、MSPM0G3519の他のSPIペリフェラルやGPIOピンも使用可能 | |||
*: 使用するパッケージに応じて適切なピンを選択する | |||
*: MSPM0G3519は最大100ピンのパッケージがあり、ピン配置の自由度が高い | |||
<br> | <br> | ||
SPIインターフェースは、MSPM0G3519のSPI0ペリフェラルを使用する。<br> | |||
このペリフェラルはハードウェアSPIをサポートしており、DMAと組み合わせることで効率的な通信が可能である。<br> | |||
MSPM0G3519のSPI0は最大32[Mbit/s]に対応しているが、ENC28J60の最大速度は20[MHz]であるため、実際の動作速度はENC28J60の制限となる。<br> | |||
<br> | <br> | ||
制御信号 (CS#、RESET#) および 割り込み信号 (INT) は任意のGPIOピンに接続できるが、割り込み機能を使用する場合は、割り込み対応ピンを選択する必要がある。<br> | 制御信号 (CS#、RESET#) および 割り込み信号 (INT) は任意のGPIOピンに接続できるが、割り込み機能を使用する場合は、割り込み対応ピンを選択する必要がある。<br> | ||
<br> | <br> | ||
ENC28J60の電源は3.3[V] | ENC28J60の電源は3.3[V]であり、MSPM0G3519と同じ電圧で動作するため、レベル変換回路は不要である。<br> | ||
ただし、電源の安定性を確保するため、各電源ピン近くに適切なデカップリングコンデンサを配置することが重要である。<br> | ただし、電源の安定性を確保するため、各電源ピン近くに適切なデカップリングコンデンサを配置することが重要である。<br> | ||
<br><br> | |||
== lwIPライブラリの構成 == | |||
lwIPライブラリは、以下に示すような階層構造を持っている。<br> | |||
<br> | |||
* アプリケーション層 | |||
*: ユーザアプリケーション (Webサーバ、HTTPクライアント等) | |||
* API層 | |||
*: Sequential API (netconn API) : ※RTOS使用時 | |||
*: Raw API (コールバックベース、低レベルAPI) : ※NO_SYS=1の時 | |||
* lwIPコア層 | |||
*: TCP、UDP、IP、ICMP、ARPプロトコル実装 | |||
* ネットワークインターフェース層 | |||
*: イーサネットコントローラドライバ (ENC28J60) | |||
* メモリ管理層 | |||
*: メモリプール、バッファ管理 (pbuf) | |||
<br> | |||
lwIPの主要なソースファイルを以下に示す。<br> | |||
* lwip/src/core/ | |||
*: lwIPコア実装ファイル群 | |||
*: tcp.c、udp.c、ip.c、icmp.c、arp.c等 | |||
* lwip/src/api/ | |||
*: Sequential API実装 (RTOS使用時) | |||
*: netconn.c、api_lib.c、api_msg.c等 | |||
* lwip/src/netif/ | |||
*: ネットワークインターフェース | |||
*: ethernet.c、etharp.c等 | |||
* lwip/src/include/lwip/ | |||
*: lwIPヘッダファイル群 | |||
* lwip/src/apps/ | |||
*: アプリケーション層実装 | |||
*: httpd.c、mqtt.c、snmp.c等 | |||
* arch/ | |||
*: アーキテクチャ依存部分 (移植先マイコン依存) | |||
*: cc.h、perf.h、sys_arch.h等 | |||
* lwipopts.h | |||
*: lwIP設定ファイル (移植先マイコン依存) | |||
* enc28j60_lwip.c / enc28j60_lwip.h | |||
*: ENC28J60ドライバ (移植先マイコン依存) | |||
<br> | |||
この階層構造により、lwIPの中核部分とハードウェア依存部分が明確に分離されている。<br> | |||
MSPM0G3519では、主にアーキテクチャ依存部分 (arch/)、ネットワークインターフェース層 (enc28j60_lwip.c)、設定ファイル (lwipopts.h) を実装または修正する必要がある。<br> | |||
<br> | |||
MSPM0G3519では、一般的にRaw APIを使用して実装する。(NO_SYS=1時)<br> | |||
Raw APIは、コールバック関数ベースの低レベルAPIで、RTOSを必要とせずに動作する。<br> | |||
Sequential APIは、よりシンプルな記述が可能であるが、RTOSが必要となる。<br> | |||
<br> | |||
MSPM0G3519のリソースは十分であるため、将来的にRTOSの導入を検討する場合は、Sequential APIへの移行も容易である。<br> | |||
<br> | |||
* lwIPの公式Webサイト | |||
*: https://savannah.nongnu.org/projects/lwip/ | |||
* lwIPのGithub | |||
*: https://github.com/lwip-tcpip/lwip | |||
* lwIP Documentation | |||
*: http://www.nongnu.org/lwip/2_1_x/index.html | |||
<br><br> | <br><br> | ||
| 217行目: | 334行目: | ||
<br> | <br> | ||
この階層構造により、uIPの中核部分とハードウェア依存部分が明確に分離されている。<br> | この階層構造により、uIPの中核部分とハードウェア依存部分が明確に分離されている。<br> | ||
MSPM0G3519への移植では、主にドライバ層 (enc28j60.c)、タイマ管理 (clock-arch.c)、設定ファイル (uip-conf.h) を追加または修正する必要がある。<br> | |||
また、多くの場合、uIPコア層はそのまま使用できる。<br> | また、多くの場合、uIPコア層はそのまま使用できる。<br> | ||
<br> | <br> | ||
| 224行目: | 341行目: | ||
* uIPのGithub | * uIPのGithub | ||
*: https://github.com/adamdunkels/uip | *: https://github.com/adamdunkels/uip | ||
<br><br> | |||
== lwIP : サンプルコード == | |||
以下の例では、ENC28J60およびlwIPを使用して、簡単なWebサーバを構築してHTTPリクエストに応答している。<br> | |||
MSPM0G3519の豊富なリソースを活用し、lwIPのRaw APIを使用している。<br> | |||
<br> | |||
==== lwIP設定ファイル (lwipopts.h) ==== | |||
まず、lwIPの動作パラメータを設定する。<br> | |||
<br> | |||
この設定ファイルでは、NO_SYS=1によりRTOSを使用しないスタンドアロン構成を指定している。<br> | |||
MSPM0G3519の128[KB] RAMを活用し、複数の同時接続とDHCPクライアント機能を有効化している。<br> | |||
<br> | |||
* メモリプール設定 | |||
*: MSPM0G3519の豊富なRAM容量に応じて、メモリプールサイズを最適化している。 | |||
*: pbufプールやヒープサイズは、アプリケーションの要件に応じて柔軟に変更可能である。 | |||
* TCP接続数 | |||
*: 16接続に設定しているが、これはアプリケーションの要件に応じて調整できる。 | |||
*: MSPM0G3519では、20〜30接続以上も十分に対応可能である。 | |||
* DHCP機能 | |||
*: DHCPクライアント機能を有効化することで、IPアドレスの自動取得が可能となる。 | |||
<br> | |||
<syntaxhighlight lang="c"> | |||
#ifndef __LWIPOPTS_H__ | |||
#define __LWIPOPTS_H__ | |||
// NO_SYS==1: RTOSを使用しないスタンドアロン構成 | |||
#define NO_SYS 1 | |||
// メモリ管理設定 (MSPM0G3519の128KB RAMを活用) | |||
#define MEM_ALIGNMENT 4 | |||
#define MEM_SIZE (32*1024) // 32KB ヒープ (十分なRAMがあるため大きめに設定) | |||
#define MEMP_NUM_PBUF 32 | |||
#define MEMP_NUM_TCP_PCB 16 | |||
#define MEMP_NUM_TCP_PCB_LISTEN 8 | |||
#define MEMP_NUM_TCP_SEG 32 | |||
#define MEMP_NUM_SYS_TIMEOUT 16 | |||
// pbuf設定 | |||
#define PBUF_POOL_SIZE 32 | |||
#define PBUF_POOL_BUFSIZE 512 | |||
// TCP設定 | |||
#define LWIP_TCP 1 | |||
#define TCP_MSS 1460 | |||
#define TCP_WND (8 * TCP_MSS) // 8 MSS ウィンドウサイズ | |||
#define TCP_SND_BUF (8 * TCP_MSS) // 8 MSS 送信バッファ | |||
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) | |||
// UDP設定 | |||
#define LWIP_UDP 1 | |||
#define MEMP_NUM_UDP_PCB 8 | |||
// ICMP設定 | |||
#define LWIP_ICMP 1 | |||
// DHCP設定 | |||
#define LWIP_DHCP 1 | |||
#define LWIP_NETIF_HOSTNAME 1 | |||
// DNS設定 | |||
#define LWIP_DNS 1 // DNS有効化 | |||
#define DNS_TABLE_SIZE 4 | |||
#define DNS_MAX_SERVERS 2 | |||
// ARP設定 | |||
#define LWIP_ARP 1 | |||
#define ARP_TABLE_SIZE 10 | |||
#define ARP_QUEUEING 1 | |||
// IP設定 | |||
#define LWIP_IPV4 1 | |||
#define LWIP_IPV6 0 | |||
#define IP_REASSEMBLY 1 // IPフラグメント再構築を有効化 | |||
#define IP_FRAG 1 // IPフラグメント分割を有効化 | |||
// チェックサム設定 | |||
#define CHECKSUM_GEN_IP 1 | |||
#define CHECKSUM_GEN_UDP 1 | |||
#define CHECKSUM_GEN_TCP 1 | |||
#define CHECKSUM_CHECK_IP 1 | |||
#define CHECKSUM_CHECK_UDP 1 | |||
#define CHECKSUM_CHECK_TCP 1 | |||
// 統計情報 (開発時は有効化、製品版では無効化してRAM節約) | |||
#define LWIP_STATS 1 | |||
#define LWIP_STATS_DISPLAY 1 | |||
// デバッグ設定 (開発時は有効化可能) | |||
#define LWIP_DEBUG 0 | |||
// その他 | |||
#define LWIP_NETCONN 0 // Raw API使用のため無効化 | |||
#define LWIP_SOCKET 0 // ソケットAPI不使用 | |||
#define LWIP_NETIF_LINK_CALLBACK 1 | |||
#define LWIP_NETIF_STATUS_CALLBACK 1 | |||
// プラットフォーム依存の型定義 | |||
#define U16_F "hu" | |||
#define S16_F "hd" | |||
#define X16_F "hx" | |||
#define U32_F "u" | |||
#define S32_F "d" | |||
#define X32_F "x" | |||
#endif /* __LWIPOPTS_H__ */ | |||
</syntaxhighlight> | |||
<br> | |||
==== ENC28J60ドライバ (enc28j60.c) ==== | |||
ENC28J60との通信を行うドライバ制御 (SPIを使用したレジスタアクセスやパケット送受信等) を記述する。<br> | |||
<br> | |||
このドライバでは、MSPM0G3519のSPIペリフェラルを使用してENC28J60を制御する。<br> | |||
MSPM0G3519のSPI通信速度は最大32[Mbit/s]であり、ENC28J60の最大速度である20[MHz]に近い動作が可能である。<br> | |||
<br> | |||
以下の例では、基本的なレジスタアクセスとパケット送受信機能を提供している。<br> | |||
必要に応じて、DMAを使用した高速データ転送や、割り込み駆動の受信処理を追加することも可能である。<br> | |||
<br> | |||
<syntaxhighlight lang="c"> | |||
// enc28j60.c : ENC28J60ドライバ | |||
#include "ti_msp_dl_config.h" // MSPM0G3519 SDK設定 | |||
#include "enc28j60.h" | |||
#include <stdint.h> | |||
// ENC28J60レジスタアドレス定義 | |||
#define ERDPTL 0x00 | |||
#define ERDPTH 0x01 | |||
#define EWRPTL 0x02 | |||
#define EWRPTH 0x03 | |||
#define ETXSTL 0x04 | |||
#define ETXSTH 0x05 | |||
#define ETXNDL 0x06 | |||
#define ETXNDH 0x07 | |||
#define ERXSTL 0x08 | |||
#define ERXSTH 0x09 | |||
#define ERXNDL 0x0A | |||
#define ERXNDH 0x0B | |||
#define ERXRDPTL 0x0C | |||
#define ERXRDPTH 0x0D | |||
#define EIE 0x1B | |||
#define EIR 0x1C | |||
#define ESTAT 0x1D | |||
#define ECON2 0x1E | |||
#define ECON1 0x1F | |||
// MACレジスタ | |||
#define MACON1 0x00 | 0x40 | |||
#define MACON3 0x02 | 0x40 | |||
#define MAMXFLL 0x0A | 0x40 | |||
#define MAMXFLH 0x0B | 0x40 | |||
#define MABBIPG 0x04 | 0x40 | |||
#define MAIPGL 0x06 | 0x40 | |||
#define MAIPGH 0x07 | 0x40 | |||
// SPIコマンド定義 | |||
#define ENC28J60_READ_CTRL_REG 0x00 | |||
#define ENC28J60_WRITE_CTRL_REG 0x40 | |||
#define ENC28J60_BIT_FIELD_SET 0x80 | |||
#define ENC28J60_BIT_FIELD_CLR 0xA0 | |||
#define ENC28J60_READ_BUF_MEM 0x3A | |||
#define ENC28J60_WRITE_BUF_MEM 0x7A | |||
#define ENC28J60_SOFT_RESET 0xFF | |||
// ビット定義 | |||
#define ECON1_TXRTS 0x08 | |||
#define ECON1_RXEN 0x04 | |||
#define ECON2_AUTOINC 0x80 | |||
#define ECON2_PKTDEC 0x40 | |||
#define ESTAT_CLKRDY 0x01 | |||
#define MACON1_MARXEN 0x01 | |||
#define MACON3_PADCFG0 0x20 | |||
#define MACON3_TXCRCEN 0x10 | |||
#define MACON3_FRMLNEN 0x02 | |||
// チップセレクト制御 (実際のピン定義に応じて変更) | |||
#define ENC28J60_CS_LOW() DL_GPIO_clearPins(GPIO_ENC_CS_PORT, GPIO_ENC_CS_PIN) | |||
#define ENC28J60_CS_HIGH() DL_GPIO_setPins(GPIO_ENC_CS_PORT, GPIO_ENC_CS_PIN) | |||
static uint8_t current_bank = 0; | |||
// 遅延関数 (80[MHz]駆動時) | |||
static void delay_us(uint32_t us) | |||
{ | |||
// 80[MHz] = 80 cycles/us | |||
// 簡易的な遅延実装 (正確に計測する場合はタイマを使用すること) | |||
volatile uint32_t cycles = us * 80; | |||
while (cycles--); | |||
} | |||
// SPIバイト送受信 | |||
static uint8_t spi_transfer(uint8_t data) | |||
{ | |||
// SPIにデータ送信 | |||
DL_SPI_transmitData8(SPI_0_INST, data); | |||
// 送信完了待ち | |||
while (DL_SPI_isBusy(SPI_0_INST)); | |||
// 受信データ取得 | |||
return DL_SPI_receiveData8(SPI_0_INST); | |||
} | |||
// バンク選択 | |||
static void enc28j60_set_bank(uint8_t address) | |||
{ | |||
uint8_t bank = (address & 0x60) >> 5; | |||
if (bank != current_bank) { | |||
enc28j60_write_op(ENC28J60_BIT_FIELD_CLR, ECON1, 0x03); | |||
enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON1, bank); | |||
current_bank = bank; | |||
} | |||
} | |||
// レジスタ読み出し | |||
uint8_t enc28j60_read(uint8_t address) | |||
{ | |||
uint8_t data; | |||
enc28j60_set_bank(address); | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(ENC28J60_READ_CTRL_REG | (address & 0x1F)); | |||
// MACおよびMIIレジスタの場合、ダミーバイトを読む | |||
if (address & 0x80) { | |||
spi_transfer(0x00); | |||
} | |||
data = spi_transfer(0x00); | |||
ENC28J60_CS_HIGH(); | |||
return data; | |||
} | |||
// レジスタ書き込み | |||
void enc28j60_write(uint8_t address, uint8_t data) | |||
{ | |||
enc28j60_set_bank(address); | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(ENC28J60_WRITE_CTRL_REG | (address & 0x1F)); | |||
spi_transfer(data); | |||
ENC28J60_CS_HIGH(); | |||
} | |||
// ビット操作 | |||
void enc28j60_write_op(uint8_t op, uint8_t address, uint8_t data) | |||
{ | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(op | (address & 0x1F)); | |||
spi_transfer(data); | |||
ENC28J60_CS_HIGH(); | |||
} | |||
// バッファメモリ読み出し | |||
void enc28j60_read_buffer(uint8_t *buffer, uint16_t len) | |||
{ | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(ENC28J60_READ_BUF_MEM); | |||
while (len--) { | |||
*buffer++ = spi_transfer(0x00); | |||
} | |||
ENC28J60_CS_HIGH(); | |||
} | |||
// バッファメモリ書き込み | |||
void enc28j60_write_buffer(const uint8_t *buffer, uint16_t len) | |||
{ | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(ENC28J60_WRITE_BUF_MEM); | |||
while (len--) { | |||
spi_transfer(*buffer++); | |||
} | |||
ENC28J60_CS_HIGH(); | |||
} | |||
// ENC28J60初期化 | |||
void enc28j60_init(const uint8_t *mac_address) | |||
{ | |||
// ソフトウェアリセット | |||
ENC28J60_CS_LOW(); | |||
spi_transfer(ENC28J60_SOFT_RESET); | |||
ENC28J60_CS_HIGH(); | |||
delay_us(1000); // 1ms待機 | |||
// クロックが安定するまで待機 | |||
while (!(enc28j60_read(ESTAT) & ESTAT_CLKRDY)); | |||
// 受信バッファ設定 (0x0000 - 0x19FF) | |||
enc28j60_write(ERXSTL, 0x00); | |||
enc28j60_write(ERXSTH, 0x00); | |||
enc28j60_write(ERXNDL, 0xFF); | |||
enc28j60_write(ERXNDH, 0x19); | |||
enc28j60_write(ERXRDPTL, 0x00); | |||
enc28j60_write(ERXRDPTH, 0x00); | |||
// 送信バッファ設定 (0x1A00 - 0x1FFF) | |||
enc28j60_write(ETXSTL, 0x00); | |||
enc28j60_write(ETXSTH, 0x1A); | |||
enc28j60_write(ETXNDL, 0xFF); | |||
enc28j60_write(ETXNDH, 0x1F); | |||
// MAC初期化 | |||
enc28j60_write(MACON1, MACON1_MARXEN); | |||
enc28j60_write(MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); | |||
enc28j60_write(MAMXFLL, 0xEE); | |||
enc28j60_write(MAMXFLH, 0x05); | |||
enc28j60_write(MABBIPG, 0x12); | |||
enc28j60_write(MAIPGL, 0x12); | |||
enc28j60_write(MAIPGH, 0x0C); | |||
// MACアドレス設定 | |||
enc28j60_write(0x00 | 0x60, mac_address[0]); // MAADR1 | |||
enc28j60_write(0x01 | 0x60, mac_address[1]); // MAADR2 | |||
enc28j60_write(0x02 | 0x60, mac_address[2]); // MAADR3 | |||
enc28j60_write(0x03 | 0x60, mac_address[3]); // MAADR4 | |||
enc28j60_write(0x04 | 0x60, mac_address[4]); // MAADR5 | |||
enc28j60_write(0x05 | 0x60, mac_address[5]); // MAADR6 | |||
// 割り込み有効化 | |||
enc28j60_write(EIE, 0xC0); // INTIE | PKTIE | |||
// 受信有効化 | |||
enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); | |||
} | |||
// パケット送信 | |||
void enc28j60_packet_send(const uint8_t *buffer, uint16_t len) | |||
{ | |||
// 送信バッファポインタ設定 | |||
enc28j60_write(EWRPTL, 0x00); | |||
enc28j60_write(EWRPTH, 0x1A); | |||
// 制御バイト書き込み | |||
enc28j60_write_buffer((uint8_t[]){0x00}, 1); | |||
// パケットデータ書き込み | |||
enc28j60_write_buffer(buffer, len); | |||
// 送信終了ポインタ設定 | |||
enc28j60_write(ETXNDL, (0x1A00 + len) & 0xFF); | |||
enc28j60_write(ETXNDH, ((0x1A00 + len) >> 8) & 0xFF); | |||
// 送信開始 | |||
enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); | |||
// 送信完了待ち (オプション: タイムアウト処理を追加することを推奨) | |||
while (enc28j60_read(ECON1) & ECON1_TXRTS); | |||
} | |||
// パケット受信 | |||
uint16_t enc28j60_packet_receive(uint8_t *buffer, uint16_t max_len) | |||
{ | |||
uint16_t len = 0; | |||
uint8_t header[6]; | |||
// 受信パケット数確認 | |||
if (enc28j60_read(0x19) == 0) { // EPKTCNT | |||
return 0; | |||
} | |||
// ヘッダ読み出し | |||
enc28j60_read_buffer(header, 6); | |||
// パケット長取得 | |||
len = (header[3] << 8) | header[2]; | |||
len -= 4; // CRCを除く | |||
// バッファに収まる場合のみデータを読み出し | |||
if (len <= max_len) { | |||
enc28j60_read_buffer(buffer, len); | |||
} | |||
// 次のパケットポインタ更新 | |||
uint16_t next_packet = (header[1] << 8) | header[0]; | |||
enc28j60_write(ERXRDPTL, next_packet & 0xFF); | |||
enc28j60_write(ERXRDPTH, (next_packet >> 8) & 0xFF); | |||
// パケットデクリメント | |||
enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); | |||
return (len <= max_len) ? len : 0; | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== lwIPネットワークインターフェース (netif_enc28j60.c) ==== | |||
lwIPとENC28J60ドライバを接続するネットワークインターフェース層を実装する。<br> | |||
この層は、lwIPのpbuf構造体とENC28J60のパケットバッファ間でデータを変換する役割を持つ。<br> | |||
<br> | |||
<syntaxhighlight lang="c"> | |||
// netif_enc28j60.c : lwIPネットワークインターフェース | |||
#include "lwip/opt.h" | |||
#include "lwip/def.h" | |||
#include "lwip/mem.h" | |||
#include "lwip/pbuf.h" | |||
#include "lwip/sys.h" | |||
#include "lwip/stats.h" | |||
#include "netif/etharp.h" | |||
#include "enc28j60.h" | |||
#include <string.h> | |||
#define IFNAME0 'e' | |||
#define IFNAME1 'n' | |||
// パケット送信 | |||
static err_t low_level_output(struct netif *netif, struct pbuf *p) | |||
{ | |||
struct pbuf *q; | |||
uint8_t buffer[1518]; | |||
uint16_t len = 0; | |||
// pbufチェーンからバッファにコピー | |||
for (q = p; q != NULL; q = q->next) { | |||
if (len + q->len > sizeof(buffer)) { | |||
return ERR_BUF; | |||
} | |||
memcpy(&buffer[len], q->payload, q->len); | |||
len += q->len; | |||
} | |||
// ENC28J60で送信 | |||
enc28j60_packet_send(buffer, len); | |||
return ERR_OK; | |||
} | |||
// パケット受信 | |||
static struct pbuf *low_level_input(struct netif *netif) | |||
{ | |||
struct pbuf *p, *q; | |||
uint8_t buffer[1518]; | |||
uint16_t len; | |||
// ENC28J60からパケット受信 | |||
len = enc28j60_packet_receive(buffer, sizeof(buffer)); | |||
if (len == 0) { | |||
return NULL; | |||
} | |||
// pbuf割り当て | |||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); | |||
if (p != NULL) { | |||
uint16_t offset = 0; | |||
// pbufチェーンにデータをコピー | |||
for (q = p; q != NULL; q = q->next) { | |||
memcpy(q->payload, &buffer[offset], q->len); | |||
offset += q->len; | |||
} | |||
} | |||
return p; | |||
} | |||
// ネットワークインターフェース初期化 | |||
err_t netif_enc28j60_init(struct netif *netif) | |||
{ | |||
netif->name[0] = IFNAME0; | |||
netif->name[1] = IFNAME1; | |||
netif->output = etharp_output; | |||
netif->linkoutput = low_level_output; | |||
netif->mtu = 1500; | |||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; | |||
// MACアドレス設定 | |||
netif->hwaddr_len = 6; | |||
netif->hwaddr[0] = 0x02; | |||
netif->hwaddr[1] = 0x00; | |||
netif->hwaddr[2] = 0x00; | |||
netif->hwaddr[3] = 0x00; | |||
netif->hwaddr[4] = 0x00; | |||
netif->hwaddr[5] = 0x01; | |||
// ENC28J60初期化 | |||
enc28j60_init(netif->hwaddr); | |||
return ERR_OK; | |||
} | |||
// パケット受信処理 (メインループから定期的に呼び出す) | |||
void netif_enc28j60_input(struct netif *netif) | |||
{ | |||
struct pbuf *p; | |||
// 受信可能なパケットを全て処理 | |||
while ((p = low_level_input(netif)) != NULL) { | |||
if (netif->input(p, netif) != ERR_OK) { | |||
pbuf_free(p); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== メイン処理 ==== | |||
メイン処理では、MSPM0G3519の初期化、lwIPの初期化、HTTPサーバの起動を記述する。<br> | |||
<br> | |||
<syntaxhighlight lang="c"> | |||
// main.c : メイン処理 | |||
#include "ti_msp_dl_config.h" | |||
#include "lwip/init.h" | |||
#include "lwip/netif.h" | |||
#include "lwip/timeouts.h" | |||
#include "lwip/dhcp.h" | |||
#include "netif/etharp.h" | |||
#include "netif_enc28j60.h" | |||
#include "lwip/apps/httpd.h" | |||
// lwIP用タイマ (1[ms]周期) | |||
volatile uint32_t lwip_timer_ms = 0; | |||
// タイマ割り込みハンドラ (1[ms]周期) | |||
void TIMER_0_INST_IRQHandler(void) | |||
{ | |||
lwip_timer_ms++; | |||
} | |||
int main(void) | |||
{ | |||
struct netif netif; | |||
ip4_addr_t ipaddr, netmask, gw; | |||
// MSPM0G3519ペリフェラル初期化 | |||
SYSCFG_DL_init(); | |||
// タイマ割り込み有効化 | |||
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); | |||
// lwIP初期化 | |||
lwip_init(); | |||
// 静的IPアドレス設定 (DHCPを使用しない場合) | |||
IP4_ADDR(&ipaddr, 192, 168, 1, 100); | |||
IP4_ADDR(&netmask, 255, 255, 255, 0); | |||
IP4_ADDR(&gw, 192, 168, 1, 1); | |||
// ネットワークインターフェース追加 | |||
netif_add(&netif, &ipaddr, &netmask, &gw, NULL, netif_enc28j60_init, ethernet_input); | |||
netif_set_default(&netif); | |||
netif_set_up(&netif); | |||
// DHCPクライアント起動 (オプション) | |||
// dhcp_start(&netif); | |||
// HTTPサーバ初期化 | |||
httpd_init(); | |||
// メインループ | |||
while (1) { | |||
// パケット受信処理 | |||
netif_enc28j60_input(&netif); | |||
// lwIPタイムアウト処理 (周期的なタイマイベント処理) | |||
sys_check_timeouts(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 簡易HTTPサーバの構築 ==== | |||
lwIPには、HTTPサーバ実装 (httpd.c) が含まれているため、これを利用することで簡単にWebサーバを構築できる。<br> | |||
以下の例では、カスタムCGIハンドラを追加して、動的なコンテンツを生成している。<br> | |||
<br> | |||
<syntaxhighlight lang="c"> | |||
// httpd_cgi.c - CGIハンドラ | |||
#include "lwip/apps/httpd.h" | |||
#include "ti_msp_dl_config.h" | |||
#include <string.h> | |||
// LED状態取得CGI | |||
const char *led_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) | |||
{ | |||
// LEDの状態を確認 | |||
uint32_t led_state = DL_GPIO_readPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); | |||
if (led_state) { | |||
return "/led_on.ssi"; | |||
} | |||
else { | |||
return "/led_off.ssi"; | |||
} | |||
} | |||
// LED制御CGI | |||
const char *led_control_cgi_handler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[]) | |||
{ | |||
int i; | |||
for (i = 0; i < iNumParams; i++) { | |||
if (strcmp(pcParam[i], "led") == 0) { | |||
if (strcmp(pcValue[i], "on") == 0) { | |||
DL_GPIO_setPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); | |||
} | |||
else if (strcmp(pcValue[i], "off") == 0) { | |||
DL_GPIO_clearPins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN); | |||
} | |||
} | |||
} | |||
return "/index.html"; | |||
} | |||
// CGIハンドラテーブル | |||
static const tCGI cgi_handlers[] = { | |||
{ "/led_status.cgi", led_cgi_handler }, | |||
{ "/led_control.cgi", led_control_cgi_handler } | |||
}; | |||
// CGI初期化 | |||
void httpd_cgi_init(void) | |||
{ | |||
http_set_cgi_handlers(cgi_handlers, sizeof(cgi_handlers) / sizeof(tCGI)); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
lwIPのHTTPサーバは、ファイルシステムを持たないため、Webページのコンテンツはプログラムに埋め込む必要がある。<br> | |||
lwIPには、makefsdataツールが付属しており、HTMLファイルをC言語のヘッダファイルに変換することができる。<br> | |||
<br> | |||
<syntaxhighlight lang="html"> | |||
<!-- index.html --> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<title>MSPM0G3519 Web Server</title> | |||
<style> | |||
body { font-family: Arial, sans-serif; margin: 40px; } | |||
h1 { color: #333; } | |||
.info { background-color: #f0f0f0; padding: 20px; border-radius: 5px; } | |||
.controls { margin-top: 20px; } | |||
button { padding: 10px 20px; margin: 5px; } | |||
</style> | |||
</head> | |||
<body> | |||
<h1>MSPM0G3519 Web Server</h1> | |||
<div class="info"> | |||
<p>This is running on lwIP stack with ENC28J60 Ethernet controller.</p> | |||
<ul> | |||
<li>MCU: MSPM0G3519 (ARM Cortex-M0+, 80MHz)</li> | |||
<li>Flash: 512KB</li> | |||
<li>RAM: 128KB</li> | |||
<li>Ethernet: ENC28J60 (10Mbps)</li> | |||
</ul> | |||
</div> | |||
<div class="controls"> | |||
<h2>LED Control</h2> | |||
<form action="/led_control.cgi" method="get"> | |||
<button type="submit" name="led" value="on">LED ON</button> | |||
<button type="submit" name="led" value="off">LED OFF</button> | |||
</form> | |||
</div> | |||
</body> | |||
</html> | |||
</syntaxhighlight> | |||
<br><br> | |||
== その他の注意事項 == | |||
lwIPを使用したTCP/IP通信を実装する場合の注意事項を以下に示す。<br> | |||
<br> | |||
==== タイマ管理 ==== | |||
lwIPは、sys_check_timeouts関数を定期的に呼び出す必要がある。<br> | |||
メインループ内で適切な間隔 (推奨 : 数[ms]〜数十[ms]) で呼び出すことを推奨する。<br> | |||
<br> | |||
タイマの精度は、TCP通信の品質に影響するため、正確なタイマ実装が重要である。<br> | |||
<br> | |||
==== メモリ管理 ==== | |||
lwIPは、メモリプール方式を採用しているため、lwipopts.hで適切なプールサイズを設定する必要がある。<br> | |||
メモリ不足が発生すると、パケットのドロップや接続の失敗が生じる可能性がある。<br> | |||
<br> | |||
MSPM0G3519は128[KB]のRAMを持つため、メモリプールサイズは柔軟に調整できる。<br> | |||
<br> | |||
==== pbuf処理 ==== | |||
pbuf構造体は、参照カウント方式でメモリ管理されている。<br> | |||
pbuf_free関数を適切に呼び出さないと、メモリリークが発生する。<br> | |||
<br> | |||
特に、パケット受信処理やエラー処理時には注意が必要である。<br> | |||
<br> | |||
==== 割り込みコンテキスト ==== | |||
lwIPの関数は、基本的に割り込みコンテキストから呼び出すべきではない。<br> | |||
パケット受信処理は、メインループで行うことを推奨する。<br> | |||
<br> | |||
ENC28J60の割り込み信号を使用する場合は、割り込みハンドラ内ではフラグを立てるのみとし、実際の処理はメインループで行う。<br> | |||
<br> | |||
==== DHCPの使用 ==== | |||
DHCPクライアントを使用する場合、IPアドレスの取得に時間がかかる場合がある。<br> | |||
netif_set_link_callback関数を使用して、リンクアップ時にDHCPを起動することを推奨する。<br> | |||
<br> | |||
DHCPによるIPアドレス取得中は、TCP/UDP通信ができないため、アプリケーションの実装時に考慮する必要がある。<br> | |||
<br> | |||
==== エンディアン変換 ==== | |||
ネットワークバイトオーダー (ビッグエンディアン) とホストバイトオーダーの変換に注意する。<br> | |||
<br> | |||
lwIPは、htons()、ntohs()、htonl()、ntohl()等のマクロを提供している。<br> | |||
<br> | |||
ARM Cortex-M0+はリトルエンディアンであるため、適切な変換が必要である。<br> | |||
<br><br> | |||
== トラブルシューティング == | |||
==== パケットが受信できない ==== | |||
* ENC28J60の初期化、MACアドレス設定、ネットワークインターフェースの設定を確認する。 | |||
* netif_set_up()が呼ばれているか、NETIF_FLAG_LINK_UPが設定されているかを確認する。 | |||
* SPIの通信速度が高すぎる場合、通信が不安定になる可能性があるため、速度を下げてみる。 | |||
<br> | |||
==== ARPが応答しない ==== | |||
*: MACアドレスが正しく設定されているか、etharp_output()が正しく設定されているかを確認する。 | |||
* ARP_TABLE_SIZEが適切に設定されているかを確認する。 | |||
<br> | |||
==== TCP接続が確立しない ==== | |||
* ファイアウォールやルータの設定を確認する。 | |||
* sys_check_timeouts()が定期的に呼ばれているかを確認する。 | |||
* TCPの3ウェイハンドシェイクが正常に行われているか、パケットキャプチャで確認する。 | |||
<br> | |||
==== メモリ不足エラー ==== | |||
* lwipopts.hのメモリプールサイズを増やす。 | |||
* LWIP_STATS=1を有効化して、メモリ使用状況を確認する。 | |||
* MSPM0G3519は128[KB]のRAMを持つため、十分なメモリを割り当てることができる。 | |||
<br> | |||
==== HTTPサーバが応答しない ==== | |||
* httpd_init関数が呼ばれているか、または、ポート80がリッスンされているかを確認する。 | |||
* fsdata.cが正しく生成されているかを確認する。 | |||
* makefsdata.pyを使用して、HTMLファイルを正しく変換する。 | |||
<br><br> | <br><br> | ||
== uIP : サンプルコード == | == uIP : サンプルコード == | ||
以下の例では、ENC28J60およびuIPを使用して、Webサーバを構築してHTTPリクエストに応答している。<br> | |||
uIPは軽量であるため、MSPM0G3519の豊富なリソースを考慮すると軽量すぎる可能性があるが、簡単な実装や学習目的には適している。<br> | |||
<br> | <br> | ||
==== uIP設定ファイル (uip-conf.h) ==== | ==== uIP設定ファイル (uip-conf.h) ==== | ||
| 234行目: | 1,080行目: | ||
この設定ファイルでは、デバイスのネットワーク設定 (IPアドレス、ネットマスク、ゲートウェイ) を定義している。<br> | この設定ファイルでは、デバイスのネットワーク設定 (IPアドレス、ネットマスク、ゲートウェイ) を定義している。<br> | ||
これらの値は、使用するネットワーク環境に合わせて変更する必要がある。<br> | これらの値は、使用するネットワーク環境に合わせて変更する必要がある。<br> | ||
MSPM0G3519は128[KB]のRAMを持つため、バッファサイズや接続数を比較的大きく設定できる。<br> | |||
<br> | <br> | ||
* バッファサイズ | * バッファサイズ | ||
*: 標準的なイーサネットフレームのMTU (Maximum Transmission Unit) である1500バイトに設定している。 | *: 標準的なイーサネットフレームのMTU (Maximum Transmission Unit) である1500バイトに設定している。 | ||
* TCP接続数 | * TCP接続数 | ||
*: | *: 8に設定しているが、これはRAM容量と必要な同時接続数に応じて調整できる。 | ||
*: MSPM0G3519の豊富なRAMを活かし、MSP430F5529の設定 (4接続) より多めに設定している。 | |||
*: 接続数を増やすと、より多くのクライアントを同時に処理できるが、RAM使用量も増加する点に注意が必要である。 | *: 接続数を増やすと、より多くのクライアントを同時に処理できるが、RAM使用量も増加する点に注意が必要である。 | ||
<br> | <br> | ||
| 273行目: | 1,121行目: | ||
#define UIP_CONF_RECEIVE_WINDOW 1460 // TCP受信ウィンドウサイズ | #define UIP_CONF_RECEIVE_WINDOW 1460 // TCP受信ウィンドウサイズ | ||
// TCP/UDP接続数 | // TCP/UDP接続数 (MSPM0G3519の豊富なRAMを活用) | ||
#define UIP_CONF_MAX_CONNECTIONS | #define UIP_CONF_MAX_CONNECTIONS 8 // 最大TCP接続数 (MSP430より多め) | ||
#define UIP_CONF_MAX_LISTENPORTS | #define UIP_CONF_MAX_LISTENPORTS 8 // 最大TCP待受ポート数 | ||
#define UIP_CONF_UDP_CONNS | #define UIP_CONF_UDP_CONNS 4 // 最大UDP接続数 | ||
// プロトコル有効化 | // プロトコル有効化 | ||
| 283行目: | 1,131行目: | ||
#define UIP_CONF_BROADCAST 1 // ブロードキャストを有効化 | #define UIP_CONF_BROADCAST 1 // ブロードキャストを有効化 | ||
// 統計情報 | // 統計情報 (開発時は有効化、製品版では無効化してRAM節約) | ||
#define UIP_CONF_STATISTICS 0 // 統計情報を無効化 | #define UIP_CONF_STATISTICS 0 // 統計情報を無効化 | ||
// アプリケーション名 | // アプリケーション名 | ||
| 304行目: | 1,152行目: | ||
バンク選択は、ECON1レジスタの下位2ビットで制御される。<br> | バンク選択は、ECON1レジスタの下位2ビットで制御される。<br> | ||
ドライバでは、現在のバンクを追跡し、必要な場合のみバンク切り替えを行うことにより、不要なSPI通信を削減している。<br> | ドライバでは、現在のバンクを追跡し、必要な場合のみバンク切り替えを行うことにより、不要なSPI通信を削減している。<br> | ||
<br> | |||
MSPM0G3519のSPIペリフェラルは、DL_SPI関数を使用して制御する。<br> | |||
最大80[MHz]の高速動作により、SPIクロックも高速に設定できるが、ENC28J60の最大速度 (20[MHz]) を超えないように注意する必要がある。<br> | |||
<br> | <br> | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
#include | // enc28j60.c : ENC28J60ドライバ (MSPM0G3519 uIP用) | ||
#include "ti_msp_dl_config.h" // MSPM0G3519 SDK設定 | |||
#include "enc28j60.h" | #include "enc28j60.h" | ||
#include <stdint.h> | #include <stdint.h> | ||
| 351行目: | 1,204行目: | ||
// MACON1 : MACコントロールレジスタ1 | // MACON1 : MACコントロールレジスタ1 | ||
#define MACON1 0x00 | #define MACON1 0x00 | 0x40 | ||
#define MARXEN 0x01 | #define MARXEN 0x01 | ||
#define TXPAUS 0x08 | #define TXPAUS 0x08 | ||
| 357行目: | 1,210行目: | ||
// MACON3 : MACコントロールレジスタ3 | // MACON3 : MACコントロールレジスタ3 | ||
#define MACON3 0x02 | #define MACON3 0x02 | 0x40 | ||
#define PADCFG0 0x20 | #define PADCFG0 0x20 | ||
#define TXCRCEN 0x10 | #define TXCRCEN 0x10 | ||
| 364行目: | 1,217行目: | ||
// MAMXFLL/MAMXFLH : 最大フレーム長レジスタ | // MAMXFLL/MAMXFLH : 最大フレーム長レジスタ | ||
#define MAMXFLL 0x0A | #define MAMXFLL 0x0A | 0x40 | ||
#define MAMXFLH 0x0B | #define MAMXFLH 0x0B | 0x40 | ||
// MABBIPG : バックツーバックパケット間隙レジスタ | // MABBIPG : バックツーバックパケット間隙レジスタ | ||
#define MABBIPG 0x04 | #define MABBIPG 0x04 | 0x40 | ||
// MAIPGL/MAIPGH : 非バックツーバックパケット間隙レジスタ | // MAIPGL/MAIPGH : 非バックツーバックパケット間隙レジスタ | ||
#define MAIPGL 0x06 | #define MAIPGL 0x06 | 0x40 | ||
#define MAIPGH 0x07 | #define MAIPGH 0x07 | 0x40 | ||
// SPIコマンド定義 | // SPIコマンド定義 | ||
| 389行目: | 1,242行目: | ||
#define BANK3 0x03 | #define BANK3 0x03 | ||
// チップセレクト制御 | // チップセレクト制御 (実際のピン定義に応じて変更) | ||
#define ENC28J60_CS_LOW() ( | #define ENC28J60_CS_LOW() DL_GPIO_clearPins(GPIO_ENC_CS_PORT, GPIO_ENC_CS_PIN) | ||
#define ENC28J60_CS_HIGH() ( | #define ENC28J60_CS_HIGH() DL_GPIO_setPins(GPIO_ENC_CS_PORT, GPIO_ENC_CS_PIN) | ||
static uint8_t current_bank = 0; | static uint8_t current_bank = 0; | ||
// 遅延関数 (80[MHz]駆動の場合) | |||
static void delay_us(uint32_t us) | |||
{ | |||
// 80[MHz] = 80 cycles/us | |||
// 簡易的な遅延実装のため、精度が必要な場合はタイマの割り込みを使用する | |||
volatile uint32_t cycles = us * 80; | |||
while (cycles--); | |||
} | |||
// SPIバイト送受信 | // SPIバイト送受信 | ||
static uint8_t spi_transfer(uint8_t data) | static uint8_t spi_transfer(uint8_t data) | ||
{ | { | ||
// SPIにデータ送信 | |||
DL_SPI_transmitData8(SPI_0_INST, data); | |||
while ( | |||
return | // 送信完了待ち | ||
while (DL_SPI_isBusy(SPI_0_INST)); | |||
// 受信データ取得 | |||
return DL_SPI_receiveData8(SPI_0_INST); | |||
} | } | ||
| 492行目: | 1,358行目: | ||
ENC28J60_CS_HIGH(); | ENC28J60_CS_HIGH(); | ||
delay_us(1000); // 1[ms]待機 | |||
// クロックが安定するまで待機 | // クロックが安定するまで待機 | ||
| 511行目: | 1,377行目: | ||
enc28j60_write(ETXNDH, 0x1F); | enc28j60_write(ETXNDH, 0x1F); | ||
// MAC初期化 | // MAC初期化 | ||
enc28j60_write(MACON1, MARXEN); | enc28j60_write(MACON1, MARXEN); // MAC受信有効 | ||
enc28j60_write(MACON3, PADCFG0 | TXCRCEN | FRMLNEN); // パディング、CRC、フレーム長チェック有効 | enc28j60_write(MACON3, PADCFG0 | TXCRCEN | FRMLNEN); // パディング、CRC、フレーム長チェック有効 | ||
enc28j60_write(MAMXFLL, 0xEE); | enc28j60_write(MAMXFLL, 0xEE); // 最大フレーム長1518バイト | ||
enc28j60_write(MAMXFLH, 0x05); | enc28j60_write(MAMXFLH, 0x05); | ||
enc28j60_write(MABBIPG, 0x12); | enc28j60_write(MABBIPG, 0x12); // バックツーバック間隔 | ||
enc28j60_write(MAIPGL, 0x12); | enc28j60_write(MAIPGL, 0x12); // 非バックツーバック間隔 | ||
enc28j60_write(MAIPGH, 0x0C); | enc28j60_write(MAIPGH, 0x0C); | ||
// MACアドレス設定 | // MACアドレス設定 | ||
enc28j60_write(0x00 | 0x60, mac_address[0]); // MAADR1 | enc28j60_write(0x00 | 0x60, mac_address[0]); // MAADR1 | ||
enc28j60_write(0x01 | 0x60, mac_address[1]); // MAADR2 | enc28j60_write(0x01 | 0x60, mac_address[1]); // MAADR2 | ||
| 554行目: | 1,420行目: | ||
// 送信開始 | // 送信開始 | ||
enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON1, TXRTS); | enc28j60_write_op(ENC28J60_BIT_FIELD_SET, ECON1, TXRTS); | ||
// 送信完了待ち (オプション) | |||
while (enc28j60_read(ECON1) & TXRTS); | |||
} | } | ||
| 592行目: | 1,461行目: | ||
<br> | <br> | ||
==== メイン処理 ==== | ==== メイン処理 ==== | ||
メイン処理では、MSPM0G3519の初期化、uIPの初期化等を記述する。<br> | |||
<br> | |||
MSPM0G3519のタイマペリフェラルを使用して、uIPに必要な周期的なタイマイベントを生成する。<br> | |||
uIPは、TCPの再送タイマやARPのタイムアウト管理のために、定期的なタイマ処理を必要とする。<br> | |||
一般的には、TCPタイマは500[ms]周期、ARPタイマは10秒周期で処理する。<br> | |||
<br> | |||
MSPM0G3519の80MHz動作により、uIPのTCP/IP処理は非常に高速に実行できる。<br> | |||
また、128[KB]のRAMにより、uIPのバッファやスタック変数に十分なメモリを割り当てることができる。<br> | |||
<br> | <br> | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
#include | // main.c : メイン処理 (MSPM0G3519 uIP) | ||
#include "ti_msp_dl_config.h" | |||
#include "uip.h" | #include "uip.h" | ||
#include "uip_arp.h" | #include "uip_arp.h" | ||
| 609行目: | 1,487行目: | ||
#define MAC_ADDR5 0x01 | #define MAC_ADDR5 0x01 | ||
// グローバルバッファ | // グローバルバッファ (uIP用) | ||
uint8_t uip_buf[UIP_BUFSIZE + 2]; | // MSPM0G3519は128KB RAMを持つため、余裕を持ったバッファサイズを確保可能 | ||
uint8_t uip_buf[UIP_BUFSIZE + 2]; | |||
// タイマ管理用 | // タイマ管理用 | ||
| 616行目: | 1,495行目: | ||
volatile uint16_t arp_timer = 0; | volatile uint16_t arp_timer = 0; | ||
// | // タイマ割り込みハンドラ (10ms周期想定) | ||
void | void TIMER_0_INST_IRQHandler(void) | ||
{ | { | ||
periodic_timer++; | periodic_timer++; | ||
| 708行目: | 1,546行目: | ||
uint8_t mac_address[6] = {MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5}; | uint8_t mac_address[6] = {MAC_ADDR0, MAC_ADDR1, MAC_ADDR2, MAC_ADDR3, MAC_ADDR4, MAC_ADDR5}; | ||
// MSPM0G3519ペリフェラル初期化 | |||
SYSCFG_DL_init(); | |||
// | // タイマ割り込み有効化 | ||
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); | |||
// ENC28J60初期化 | // ENC28J60初期化 | ||
| 739行目: | 1,576行目: | ||
uip_listen(HTONS(80)); | uip_listen(HTONS(80)); | ||
// グローバル割り込み有効化 | |||
__enable_irq(); | |||
// メインループ | |||
while (1) { | while (1) { | ||
// パケット受信チェック | // パケット受信チェック | ||
| 769行目: | 1,608行目: | ||
} | } | ||
// 周期処理 | // 周期処理 (TCP再送、ARPタイムアウト等) | ||
uip_periodic_handler(); | uip_periodic_handler(); | ||
} | } | ||
| 775行目: | 1,614行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
初期化フェーズでは、MSPM0G3519のペリフェラル設定、SPI通信の設定、タイマの設定、ENC28J60およびuIPの初期化を実行する。<br> | |||
SYSCFG_DL_init関数は、TI MSPM0 SDKによって自動生成される設定関数であり、クロック、GPIO、SPI、タイマ等のペリフェラルを一括で初期化する。<br> | |||
<br> | <br> | ||
メイン処理では、受信パケットの確認と周期処理を繰り返し実行する。<br> | メイン処理では、受信パケットの確認と周期処理を繰り返し実行する。<br> | ||
| 781行目: | 1,621行目: | ||
* 受信パケットの確認 | * 受信パケットの確認 | ||
** IPパケットの場合 | ** IPパケットの場合 | ||
**: uIPスタックに渡して、TCP / UDP処理を行う。 | **: uIPスタックに渡して、TCP/UDP処理を行う。 | ||
**: MSPM0G3519の80MHz動作により、TCP/IP処理は非常に高速に実行される。 | |||
** ARPパケットの場合 | ** ARPパケットの場合 | ||
**: ARPテーブルの更新や応答を行う。 | **: ARPテーブルの更新や応答を行う。 | ||
| 790行目: | 1,631行目: | ||
*: これらのタイミングは、uIPの仕様に基づいて設定されており、変更する場合は慎重に検討する必要がある。 | *: これらのタイミングは、uIPの仕様に基づいて設定されており、変更する場合は慎重に検討する必要がある。 | ||
<br> | <br> | ||
==== | ==== HTTPサーバの構築 ==== | ||
HTTPリクエストに応答する簡単なWebサーバを構築する。<br> | HTTPリクエストに応答する簡単なWebサーバを構築する。<br> | ||
<br> | <br> | ||
uIPはイベント駆動型のアーキテクチャを採用しており、アプリケーション関数 (httpd_appcall関数) は、様々なイベントが発生したときに呼び出される。<br> | uIPはイベント駆動型のアーキテクチャを採用しており、アプリケーション関数 (httpd_appcall関数) は、様々なイベントが発生したときに呼び出される。<br> | ||
主なイベントは以下の通りである。<br> | |||
* 新規接続が確立された場合 | * 新規接続が確立された場合 | ||
*: uip_connected | *: uip_connected | ||
| 807行目: | 1,649行目: | ||
<br> | <br> | ||
以下の例では、GETリクエストを受信した時、予め用意されたHTMLページを送信する。<br> | 以下の例では、GETリクエストを受信した時、予め用意されたHTMLページを送信する。<br> | ||
MSPM0G3519の豊富なフラッシュメモリ (512[KB]) により、複数のHTMLページや画像データを格納することも可能である。<br> | |||
実務では、URLに応じて異なるコンテンツを返したり、ADCで取得したセンサデータを含む動的なページを生成することも可能である。<br> | |||
<br> | <br> | ||
uIPは限られたRAMで動作するように設計されているが、MSPM0G3519の128[KB] RAMにより、比較的大きなコンテンツも扱うことができる。<br> | |||
ただし、非常に大きなコンテンツを扱う場合は、分割送信やフラッシュROMからの直接読み出し等の工夫が推奨される。<br> | |||
<br> | <br> | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
// httpd.c : HTTPサーバ実装 | |||
#include "uip.h" | #include "uip.h" | ||
#include <string.h> | #include <string.h> | ||
// HTTPレスポンス (HTMLページ) | // HTTPレスポンス (HTMLページ) | ||
// MSPM0G3519のフラッシュROM (512[KB]) により、複数のページを格納可能 | |||
const char http_response[] = | const char http_response[] = | ||
"HTTP/1.0 200 OK\r\n" | "HTTP/1.0 200 OK\r\n" | ||
| 823行目: | 1,670行目: | ||
"<!DOCTYPE html>" | "<!DOCTYPE html>" | ||
"<html>" | "<html>" | ||
"<head><title> | "<head>" | ||
" <title>MSPM0G3519 uIP Server</title>" | |||
" <meta charset=\"UTF-8\">" | |||
" <style>" | |||
" body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }" | |||
" .container { max-width: 800px; margin: 0 auto; background-color: white; padding: 30px; border-radius: 10px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }" | |||
" h1 { color: #c00; border-bottom: 2px solid #c00; padding-bottom: 10px; }" | |||
" .specs { background-color: #f9f9f9; padding: 15px; border-left: 4px solid #c00; margin: 20px 0; }" | |||
" .specs h2 { margin-top: 0; color: #333; }" | |||
" ul { line-height: 1.8; }" | |||
" .footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; text-align: center; color: #666; font-size: 0.9em; }" | |||
" </style>" | |||
"</head>" | |||
"<body>" | "<body>" | ||
"<h1>Welcome to | " <div class=\"container\">" | ||
"<p>This | " <h1>Welcome to MSPM0G3519 uIP Server!</h1>" | ||
"<p> | " <div class=\"specs\">" | ||
" <h2>System Specifications</h2>" | |||
" <ul>" | |||
" <li><strong>MCU:</strong> MSPM0G3519 (ARM Cortex-M0+)</li>" | |||
" <li><strong>Clock Speed:</strong> 80 MHz</li>" | |||
" <li><strong>Flash Memory:</strong> 512 KB (Dual-bank with ECC)</li>" | |||
" <li><strong>SRAM:</strong> 128 KB</li>" | |||
" <li><strong>Ethernet Controller:</strong> ENC28J60 (10 Mbps)</li>" | |||
" <li><strong>TCP/IP Stack:</strong> uIP (Lightweight Implementation)</li>" | |||
" </ul>" | |||
" </div>" | |||
" <p>This embedded web server demonstrates the power of the MSPM0G3519 microcontroller combined with the uIP TCP/IP stack.</p>" | |||
" <p>The MSPM0G3519 offers excellent performance with its 80 MHz ARM Cortex-M0+ core and generous memory resources, making it ideal for IoT and embedded networking applications.</p>" | |||
" <div class=\"footer\">" | |||
" <p>© 2025 MSPM0G3519 Embedded Web Server</p>" | |||
" </div>" | |||
" </div>" | |||
"</body>" | "</body>" | ||
"</html>"; | "</html>"; | ||
| 836行目: | 1,711行目: | ||
// 新規接続時 | // 新規接続時 | ||
if (uip_connected()) { | if (uip_connected()) { | ||
// 特に処理なし (GETリクエスト待ち) | |||
} | } | ||
// データ受信時 | // データ受信時 | ||
if (uip_newdata()) { | if (uip_newdata()) { | ||
// 簡易的にGETリクエストをチェック | |||
// より高度な実装では、HTTPヘッダの完全なパースを行う | |||
if (strncmp((char *)uip_appdata, "GET ", 4) == 0) { | |||
// HTTPレスポンス送信 | |||
uip_send((void *)http_response, sizeof(http_response) - 1); | |||
} | |||
} | } | ||
// 再送要求時 | // 再送要求時 | ||
if (uip_rexmit()) { | if (uip_rexmit()) { | ||
uip_send((void *)http_response, sizeof(http_response) - 1); | |||
} | } | ||
// 接続クローズ時 | // 接続クローズ時 | ||
if (uip_closed() || uip_aborted() || uip_timedout()) { | if (uip_closed() || uip_aborted() || uip_timedout()) { | ||
// 特に処理なし | |||
// 必要に応じてクリーンアップ処理を追加 | |||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | |||
MSPM0G3519の豊富なリソースを活かすことにより、高度な機能を追加することも可能である。<br> | |||
例えば、以下のような拡張が考えられる。<br> | |||
* URLルーティング | |||
*: リクエストされたURLに応じて、異なるHTMLページを返す。 | |||
*: 複数のページを用意し、ナビゲーション機能を実装する。 | |||
*: <br> | |||
* 動的コンテンツ生成 | |||
*: ADCで取得したセンサデータをリアルタイムでWebページに表示する。 | |||
*: GPIO状態を読み取り、LEDの点灯状態等をWebページに反映する。 | |||
*: <br> | |||
* フォーム処理 | |||
*: POSTリクエストを処理し、Webブラウザから設定値を変更する。 | |||
*: LEDの制御、PWMのデューティ比設定等をWebインターフェースから行う。 | |||
*: <br> | |||
* JSON API | |||
*: REST APIを実装し、JSON形式でデータを送受信する。 | |||
*: IoTデバイスとしての機能を強化する。 | |||
<br><br> | <br><br> | ||
== | == SPI通信の速度 == | ||
MSPM0G3519のSPI0は最大32[Mbit/s]に対応しているが、ENC28J60の最大速度は20[MHz]である。<br> | |||
そのため、実際の動作速度はENC28J60の制限となる。<br> | |||
<br> | <br> | ||
SPIクロック周波数は、MSPM0G3519のクロック設定により調整可能である。<br> | |||
通信が不安定な場合は、SPIクロック周波数を下げて (例: 10[MHz]、5[MHz]) 通信の安定性を確認することを推奨する。<br> | |||
配線長やノイズの影響により、実際の動作速度は制限される場合がある。<br> | |||
<br><br> | |||
== DMAの活用 == | |||
MSPM0G3519の12チャネルDMAコントローラを使用することで、CPUの負荷を軽減しつつ、高速なデータ転送が可能となる。<br> | |||
特に、大きなパケットを連続的に送受信する場合、DMAの活用により大幅なパフォーマンス向上が期待できる。<br> | |||
<br> | <br> | ||
DMAを使用する場合は、以下の点に注意する必要がある。<br> | |||
* DMAチャネルの割り当て | |||
* | *: 他のペリフェラルとDMAチャネルが競合しないように設定する。 | ||
*: | *: MSPM0G3519は12チャネルのDMAを持つため、柔軟に割り当てが可能である。 | ||
* | * バッファアライメント | ||
*: | *: DMA転送用のバッファは、適切なアライメント (4バイト境界等) に配置する。 | ||
* | * 割り込みハンドリング | ||
*: | *: DMA転送完了割り込みを適切に処理する。 | ||
*: DMA転送完了後に、次の処理 (パケット受信処理等) を行う。 | |||
*: | <br><br> | ||
<br> | |||
== | == CAN-FDインターフェースの活用 == | ||
MSPM0G3519は2個のCAN-FDインターフェースを搭載しているため、イーサネット通信とCAN通信を組み合わせたゲートウェイ応用が可能である。<br> | |||
例えば、以下のような応用が考えられる。<br> | |||
* CANバスとイーサネットを接続するゲートウェイ | |||
*: 車載ネットワークやFA機器のデータをイーサネット経由でクラウドに送信 | |||
* CANデータのロギングとWeb表示 | |||
*: CANバスのデータをリアルタイムでWebブラウザに表示 | |||
* イーサネット経由でのCAN制御 | |||
*: Webブラウザから車載機器やFA機器を制御 | |||
<br><br> | <br><br> | ||
== 参考資料 == | == 参考資料 == | ||
* | * MSPM0G3519データシート | ||
*: https://www.ti.com/product/ja-jp/ | *: https://www.ti.com/product/ja-jp/MSPM0G3519 | ||
* MSPM0 SDK | |||
*: https://www.ti.com/tool/MSPM0-SDK | |||
* MSPM0 G-Series 80-MHz Microcontrollers Technical Reference Manual | |||
*: https://www.ti.com/lit/pdf/SLAU846 | |||
* ENC28J60データシート | * ENC28J60データシート | ||
*: https://www.microchip.com/en-us/product/ENC28J60 | *: https://www.microchip.com/en-us/product/ENC28J60 | ||
* | * lwIP公式ドキュメント | ||
*: | *: http://www.nongnu.org/lwip/2_1_x/index.html | ||
*: https://github.com/ | * lwIP Github | ||
*: https://github.com/lwip-tcpip/lwip | |||
* [https://www.rfc-editor.org/rfc/rfc793 RFC 793] | * [https://www.rfc-editor.org/rfc/rfc793 RFC 793] | ||
*: Transmission Control Protocol (TCP) | *: Transmission Control Protocol (TCP) | ||
* [https://www.rfc-editor.org/rfc/rfc826 RFC 826] | * [https://www.rfc-editor.org/rfc/rfc826 RFC 826] | ||
*: An Ethernet Address Resolution Protocol (ARP) | *: An Ethernet Address Resolution Protocol (ARP) | ||
* [https://www.rfc-editor.org/rfc/rfc2131 RFC 2131] | |||
*: Dynamic Host Configuration Protocol (DHCP) | |||
<br><br> | <br><br> | ||
{{#seo: | {{#seo: | ||
|title={{PAGENAME}} : | |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki | ||
|keywords=MochiuWiki,MSP430, | |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 | ||
|description={{PAGENAME}} - | |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux | ||
|image=/resources/assets/MochiuLogo_Single_Blue.png | |||
}} | }} | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:MSP430]] | [[カテゴリ:MSP430]] | ||