stm 32 f 103 w 5500 tcp server
35669 ワード
背景
プロジェクトの中でネットを使う必要があります。STm 32 f 4+lwipの方案を使い始めます。しかし、ハードウエアのコストが少し高いです。もっと主要なのはlwipがよくないので、いつも切れています。長い間の研究論証を経て、最終的にw 5500というチップを選択しました。TCP/IPネットワークプロトコルスタックをハードウェアチップに硬化させ、ユーザーのためにアプリケーション層インターフェースを残して、簡単で安定している。
移植プロセス
まずはhttps://w5500.com/チップマニュアルと参照コードをダウンロードしてチップの原理と基本的な使い方を理解します。内容はそんなに複雑ではありません。プロジェクトには、TCP ServerとしてW 5500が必要です。三つのクライアントが接続されます。関連コードを参照して、プロジェクトに移植します。具体的なコードは以下の通りです。
設定
問題
公式サイトの設定により、正常に運行できるはずです。確かに実行できます。三つのクライアントも接続できます。しかし、デバイスの長時間テストで、クライアントとサーバの間の接続が常に切断されていることが分かりました。いったん切断したら、あるクライアントは接続できます。あるクライアントはもう接続できなくなりました。解決の方法は設備を再起動するしかないです。これはきっとだめです。
クライアントは再接続機構があります。定期的に心拍カバンをサーバーに送ります。タイムアウト後にサーバーに再接続します。全体の仕組みは大丈夫です。問題はサーバーに接続できなくなります。採用した有線接続は、本来切断すべきではないです。この問題は一ヶ月以上繰り返しましたが、まだ分からないです。設備の出荷日も延期するしかないです。
ソリューション
まず、ネットワークデバッグアシスタントを通じてクライアントをシミュレートして、長時間運転してみます。Wirestharkでカバンをひっかきましたが、keepaliveときめきバッグがないことに気づきました。なぜサーバから送られてきませんでしたか?同僚と浩然電子杜工の提案を参考にして、次のように修正しました。問題は解決されました。現在十数日間運行しています。設備は一回も切れたことがありません。予備のsocketは3つのクライアントがあります。6つのクライアントを開きます。各クライアントは正常に使用されています。一つの予備のものがあります。接続が切断されると、もう一つは即時に有効になり、シームレスに切り替えられます。 心拍処理は自動的に心拍を送信して手動送信に変更されます。 延長公式サイトの資料パッケージは全部裸機によるデモンストレーションプログラムです。私達のプロジェクトはマルチスレッドです。だから、死ぬなどのところで延長する必要があります。 設定
ステートマシン
実行
時間を延ばす
また、非常に重要な点は、socketの送信や受信関数の中で死などの場所にオペレーティングシステムの遅延を増やすことである。
締め括りをつける
問題があったら焦らないでください。解決策があります。今は時間がないだけです。現在把握している手がかりがまだ解決に足りないと説明し、引き続き分析研究を行う必要がある。窮地に陥ったら、同僚と相談してもいいです。他の人の話によっては、いい手がかりが提供されるかもしれません。
再度浩然電子の杜工さんの親切な助けに感謝します。この記録で辛い過程を記録して、他の人に手伝いたいです。
プロジェクトの中でネットを使う必要があります。STm 32 f 4+lwipの方案を使い始めます。しかし、ハードウエアのコストが少し高いです。もっと主要なのはlwipがよくないので、いつも切れています。長い間の研究論証を経て、最終的にw 5500というチップを選択しました。TCP/IPネットワークプロトコルスタックをハードウェアチップに硬化させ、ユーザーのためにアプリケーション層インターフェースを残して、簡単で安定している。
移植プロセス
まずはhttps://w5500.com/チップマニュアルと参照コードをダウンロードしてチップの原理と基本的な使い方を理解します。内容はそんなに複雑ではありません。プロジェクトには、TCP ServerとしてW 5500が必要です。三つのクライアントが接続されます。関連コードを参照して、プロジェクトに移植します。具体的なコードは以下の通りです。
設定
static void net_set_config(void)
{
unsigned char mac[6] = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11};
unsigned char ip[4] = {192, 168, 1, 100};
unsigned char sub[4] = {255, 255, 255, 0};
unsigned char gw[4] = {192, 168, 1, 1};
unsigned char tx_size[8] = {2,2,2,2,2,2,2,2};
unsigned char rx_size[8] = {2,2,2,2,2,2,2,2};
/* Mac */
set_mac_addr(mac);
/* IP */
set_source_ip_addr(ip);
/* */
set_subnet_mask(sub);
/* */
set_gateway(gw);
/* 8 socket */
sys_init(tx_size, rx_size);
/* */
set_retrans_time(2000);
/* */
set_retrans_num(3);
/* */
set_keepalive(SOCKET_ID_0);
set_keepalive(SOCKET_ID_1);
set_keepalive(SOCKET_ID_2);
}
ステートマシンint net_process_socket(SOCKET sock, unsigned short port)
{
int ret = -1;
unsigned char state = SOCK_CLOSED;
unsigned short len = 0;
unsigned char data[MAX_MSG_LEN];
state = get_sock_status(sock);
switch (state) {
case SOCK_INIT:
listen(sock);
break;
case SOCK_ESTABLISHED:
if (get_sock_interrupt_status(sock) & Sn_IR_CON) {
set_sock_interrupt_status(sock, Sn_IR_CON);
}
len = get_sock_rx_free_buff_size(sock);
if (len > 0) {
recv(sock, data, MAX_MSG_LEN);
/* process the recv data */
}
break;
case SOCK_CLOSE_WAIT:
disconnect(sock);
break;
case SOCK_CLOSED:
ret = socket(sock, Sn_MR_TCP, port, Sn_MR_ND);
break;
default:
break;
}
return 0;
}
実行void net_task(void *arg)
{
/* */
net_set_config();
while (1) {
net_process_socket(SOCKET_ID_0, 12345);
net_process_socket(SOCKET_ID_1, 12345);
net_process_socket(SOCKET_ID_2, 12345);
/* 20ms */
vTaskDelay(100);
}
}
w 5500は最大8つのsocket接続をサポートしています。プロジェクトに三つのクライアントが必要なので、三つのsocketを配置しました。そして、それぞれのsocketに対応するステートマシンを個々のスレッドで順次実行します。具体的な基礎知識は詳しく説明しないで、公式サイトとブログの中でとても多い説明があります。問題
公式サイトの設定により、正常に運行できるはずです。確かに実行できます。三つのクライアントも接続できます。しかし、デバイスの長時間テストで、クライアントとサーバの間の接続が常に切断されていることが分かりました。いったん切断したら、あるクライアントは接続できます。あるクライアントはもう接続できなくなりました。解決の方法は設備を再起動するしかないです。これはきっとだめです。
クライアントは再接続機構があります。定期的に心拍カバンをサーバーに送ります。タイムアウト後にサーバーに再接続します。全体の仕組みは大丈夫です。問題はサーバーに接続できなくなります。採用した有線接続は、本来切断すべきではないです。この問題は一ヶ月以上繰り返しましたが、まだ分からないです。設備の出荷日も延期するしかないです。
ソリューション
まず、ネットワークデバッグアシスタントを通じてクライアントをシミュレートして、長時間運転してみます。Wirestharkでカバンをひっかきましたが、keepaliveときめきバッグがないことに気づきました。なぜサーバから送られてきませんでしたか?同僚と浩然電子杜工の提案を参考にして、次のように修正しました。問題は解決されました。現在十数日間運行しています。設備は一回も切れたことがありません。
static void net_set_config(void)
{
unsigned char mac[6] = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11};
unsigned char ip[4] = {192, 168, 1, 100};
unsigned char sub[4] = {255, 255, 255, 0};
unsigned char gw[4] = {192, 168, 1, 1};
unsigned char tx_size[8] = {2,2,2,2,2,2,2,2};
unsigned char rx_size[8] = {2,2,2,2,2,2,2,2};
/* Mac */
set_mac_addr(mac);
/* IP */
set_source_ip_addr(ip);
/* */
set_subnet_mask(sub);
/* */
set_gateway(gw);
/* 8 socket */
sys_init(tx_size, rx_size);
/* */
set_retrans_time(2000);
/* */
set_retrans_num(3);
}
動悸自動送信機構を開けません。ステートマシン
int net_process_socket(SOCKET sock, unsigned short port)
{
int ret = -1;
unsigned char state = SOCK_CLOSED;
unsigned short len = 0;
unsigned char data[MAX_MSG_LEN];
static unsigned char sock_est_flag[8] = {1, 1, 1, 1, 1, 1, 1, 1};
SOCKET another_sock;
state = get_sock_status(sock);
switch (state) {
case SOCK_INIT:
listen(sock);
sock_est_flag[sock] = 1;
break;
case SOCK_ESTABLISHED:
if (sock_est_flag[sock] == 1) {
sock_est_flag[sock] = 0;
if ((sock % 2) == 0) {
another_sock = sock + 1;
} else {
another_sock = sock - 1;
}
if (get_sock_status(another_sock) == SOCK_ESTABLISHED) {
close(another_sock);
}
}
if (get_sock_interrupt_status(sock) & Sn_IR_CON) {
set_sock_interrupt_status(sock, Sn_IR_CON);
}
len = get_sock_rx_free_buff_size(sock);
if (len > 0) {
recv(sock, data, MAX_MSG_LEN);
/* process the recv data */
}
break;
case SOCK_CLOSE_WAIT:
disconnect(sock);
break;
case SOCK_CLOSED:
ret = socket(sock, Sn_MR_TCP, port, Sn_MR_ND);
break;
default:
break;
}
return 0;
}
バックアップsocketを追加します。予備のsocketはいつもlisten状態です。実行
void net_task(void *arg)
{
int i = 0;
int counter = 0;
/* */
net_set_config();
while (1) {
net_process_socket(SOCKET_ID_0, 12345);
net_process_socket(SOCKET_ID_1, 12345);
net_process_socket(SOCKET_ID_2, 12346);
net_process_socket(SOCKET_ID_3, 12346);
net_process_socket(SOCKET_ID_4, 12347);
net_process_socket(SOCKET_ID_5, 12347);
if ((counter++ % 100) == 0) {
for (i = 0 ; i < 6; i++) {
iinchip_write_data(Sn_CR(i),Sn_CR_SEND_KEEP);
}
}
/* 20ms */
vTaskDelay(100);
}
}
手动でkeepaliveときめきパックを送ります。10 sごとに一回送ります。時間を延ばす
また、非常に重要な点は、socketの送信や受信関数の中で死などの場所にオペレーティングシステムの遅延を増やすことである。
締め括りをつける
問題があったら焦らないでください。解決策があります。今は時間がないだけです。現在把握している手がかりがまだ解決に足りないと説明し、引き続き分析研究を行う必要がある。窮地に陥ったら、同僚と相談してもいいです。他の人の話によっては、いい手がかりが提供されるかもしれません。
再度浩然電子の杜工さんの親切な助けに感謝します。この記録で辛い過程を記録して、他の人に手伝いたいです。