こんにちは。皆さん
エドワードと呼ばれます。
韓国の名前はアンジンフイです。
よろしくお願いします。
以下のコードは、TCP / IPチップのW5500 iolibraryソースです。
このコードは、韓国バージョンと英語バージョン、そして日本バージョンがあります。参照してください。
WIZnet社のW5500イーサネットソースコードをより簡単に説明しました。
ご覧になって気になる部分があればjinhee.ahn@wiznet.co.krまたは
wizwiki.net/forumにお問い合わせください。
ありがとうございます。
[code language="c"] //***************************************************************************** // //! \file socket.c //! \brief SOCKET APIs Implements file. //! \details SOCKET APIs like as Berkeley Socket APIs. //! \version 1.0.3 //! \date 2013/10/21 //! \par Revision history //! <2014/05/01> V1.0.3. Refer to M20140501 //! 1. Implicit type casting -> Explicit type casting. //! 2. replace 0x01 with PACK_REMAINED in recvfrom() //! 3. Validation a destination ip in connect() & sendto(): //! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. //! Copy 4 byte addr value into temporary uint32 variable and then compares it. //! <2013/12/20> V1.0.2 Refer to M20131220 //! Remove Warning. //! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". //! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) //! <2013/10/21> 1st Release //! \author MidnightCow //! \copyright //! //! Copyright (c) 2013, WIZnet Co., LTD. //! All rights reserved. //! //! Redistribution and use in source and binary forms, with or without //! modification, are permitted provided that the following conditions //! are met: //! //! * Redistributions of source code must retain the above copyright //! notice, this list of conditions and the following disclaimer. //! * Redistributions in binary form must reproduce the above copyright //! notice, this list of conditions and the following disclaimer in the //! documentation and/or other materials provided with the distribution. //! * Neither the name of the <ORGANIZATION> nor the names of its //! contributors may be used to endorse or promote products derived //! from this software without specific prior written permission. //! //! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" //! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE //! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE //! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE //! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR //! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF //! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS //! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) //! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF //! THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** #include "socket.h" #define SOCK_ANY_PORT_NUM 0xC000; static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; static uint16_t sock_io_mode = 0; static uint16_t sock_is_sending = 0; static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; #if _WIZCHIP_ == 5200 static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; #endif #define CHECK_SOCKNUM() \ do{ \ if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ }while(0); \ #define CHECK_SOCKMODE(mode) \ do{ \ if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ }while(0); \ #define CHECK_SOCKINIT() \ do{ \ if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ }while(0); \ #define CHECK_SOCKDATA() \ do{ \ if(len == 0) return SOCKERR_DATALEN; \ }while(0); \ ---------------------------------------------------------------------------------------------- int8_t socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) { CHECK_SOCKNUM(); // ソケット番号チェック switch(protocol) { case Sn_MR_TCP : // 0x01('0001') case Sn_MR_UDP : // 0x02('0010') case Sn_MR_MACRAW : // 0x04('0100') break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW : case Sn_MR_PPPoE : break; #endif default : return SOCKERR_SOCKMODE; } if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; // same not to the Flag zero(0) is return Error Flag(Invalid) #if _WIZCHIP_ == 5200 if(flag & 0x10) return SOCKERR_SOCKFLAG; #endif //フラグモードフラグ if(flag != 0) { switch(protocol) { case Sn_MR_TCP: if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; ///< Invalid socket flag break; case Sn_MR_UDP: if(flag & SF_IGMP_VER2) { if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; } #if _WIZCHIP_ == 5500 if(flag & SF_UNI_BLOCK) { if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; } #endif break; default: break; } } close(sn); // ソケットを閉じる //モードレジスタ設定 setSn_MR(sn, (protocol | (flag & 0xF0))); if(!port) { port = sock_any_port++; if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; } setSn_PORT(sn,port); setSn_CR(sn,Sn_CR_OPEN); // コマンドレジスタに「ソケットオ?プン」 セット while(getSn_CR(sn)); // ソケットオ?プンを確認 sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); // 0 sock_is_sending &= ~(1<<sn); // 0 sock_remained_size[sn] = 0; // 0 sock_pack_info[sn] = 0; // 0 while(getSn_SR(sn) == SOCK_CLOSED); return (int8_t)sn; } ---------------------------------------------------------------------------------------------- int8_t close(uint8_t sn) { CHECK_SOCKNUM(); setSn_CR(sn,Sn_CR_CLOSE); // コマンド セット (Hostから W5500まで) /* コマンド プロセッサ 処理 待つ... */ while( getSn_CR(sn) ); /* ソケットのすべての割り込み初期化 */ setSn_IR(sn, 0xFF); sock_is_sending &= ~(1<<sn); sock_remained_size[sn] = 0; sock_pack_info[sn] = 0; while(getSn_SR(sn) != SOCK_CLOSED); return SOCK_OK; } ---------------------------------------------------------------------------------------------- int8_t listen(uint8_t sn) { CHECK_SOCKNUM(); // ソケットナンバーチェック CHECK_SOCKMODE(Sn_MR_TCP); // ソケットがTCPモードであるかチェック CHECK_SOCKINIT(); // ソケットの作成いがいSn_SRがSOCK_INIT状態がいるかチェックし setSn_CR(sn,Sn_CR_LISTEN); // コマンドレジスタに「ソケット待機」セット while(getSn_CR(sn)); // ソケット待機確認 // エラーフロー(Sn_SRがListen状態でなければエラー) while(getSn_SR(sn) != SOCK_LISTEN) { if(getSn_CR(sn) == SOCK_CLOSED) { close(sn); return SOCKERR_SOCKCLOSED; } } return SOCK_OK; // Sn_IR(0x10) -> 通常動作と完了したこと割り込み } ---------------------------------------------------------------------------------------------- int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) { CHECK_SOCKNUM(); CHECK_SOCKMODE(Sn_MR_TCP); CHECK_SOCKINIT(); //M20140501 : For avoiding fatal error on memory align mismatched //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; // 4 Byte IPを2進数に変換してまとめてIPチェック { //IPチェック変数 uint32_t taddr; //入力されたIPを計算して変数に入れてチェック taddr = ((uint32_t)addr[0] & 0x000000FF); taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); //込められているIPアドレスが255.255.255.255 or 0.0.0.0であればエラー if( taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID; } if(port == 0) return SOCKERR_PORTZERO; // ポートが0の場合、エラー setSn_DIPR(sn,addr); // 接続したサーバのIP設定 setSn_DPORT(sn,port); // 接続サーバーPORT設定 #if _WIZCHIP_ == 5200 // for W5200 ARP errata (これはW5200用) setSUBR(0); #endif setSn_CR(sn,Sn_CR_CONNECT); // コマンドレジスタに「ソケット接続」セット while(getSn_CR(sn)); // ソケット接続確認 // ブロッキング及びノンブロッキング設定 if(sock_io_mode & (1<<sn)) return SOCK_BUSY; // エラーフロー while(getSn_SR(sn) != SOCK_ESTABLISHED) { if (getSn_IR(sn) & Sn_IR_TIMEOUT) { setSn_IR(sn, Sn_IR_TIMEOUT); #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR((uint8_t*)"\x00\x00\x00\x00"); #endif return SOCKERR_TIMEOUT; } } #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR((uint8_t*)"\x00\x00\x00\x00"); #endif return SOCK_OK; } int8_t disconnect(uint8_t sn) { CHECK_SOCKNUM(); CHECK_SOCKMODE(Sn_MR_TCP); setSn_CR(sn,Sn_CR_DISCON); /* コマンドの処理を待っている。... */ while(getSn_CR(sn)); sock_is_sending &= ~(1<<sn); if(sock_io_mode & (1<<sn)) return SOCK_BUSY; while(getSn_SR(sn) != SOCK_CLOSED) { if(getSn_IR(sn) & Sn_IR_TIMEOUT) { close(sn); return SOCKERR_TIMEOUT; } } return SOCK_OK; } ---------------------------------------------------------------------------------------------- /*TCPがデータからの重要な部分*/ int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) { uint8_t tmp=0; uint16_t freesize=0; CHECK_SOCKNUM(); CHECK_SOCKMODE(Sn_MR_TCP); CHECK_SOCKDATA(); // コマンドの処理を待っている。 tmp = getSn_SR(sn); // ソケットの状態を変数に保存 // 保存した変数の2つの状態と比較 if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS; // 直前データあり/なしをチェック if( sock_is_sending & (1<<sn) ) // sock_is_sending フラグ「1」であれば { tmp = getSn_IR(sn); if(tmp & Sn_IR_SENDOK) // データ転送が終了したら、SEND_OKフラグを「1」に設定(0x10) { setSn_IR(sn, Sn_IR_SENDOK); // 割り込みレジスタの初期化 #if _WIZCHIP_ == 5200 if(getSn_TX_RD(sn) != sock_next_rd[sn]) { setSn_CR(sn,Sn_CR_SEND); while(getSn_CR(sn)); return SOCKERR_BUSY; } #endif sock_is_sending &= ~(1<<sn); // sock_is_sending フラグ「0」設定 } else if(tmp & Sn_IR_TIMEOUT) // 0x08 { close(sn); return SOCKERR_TIMEOUT; } // SENDOK、TIMEOUT両方ない場合SOCK_BUSYになる。 else return SOCK_BUSY; // まだdata処理が取れない (0x00) } // W5500は、初期設定Default 2Kbyte、MAX 16Kbyteすることができる。 // Sn_TX_FSR(Free Size Register)は、空いているスペースを示す。 freesize = getSn_TxMAX(sn); // TX_buffer_size 読む // ユーザーが送信したDataがTx Bufferよりも大きい場合Tx Buffer分だけ送信 if (len > freesize) len = freesize; // 残っている容量をチェック while(1) { freesize = getSn_TX_FSR(sn); // 残りのsizeチェック // エラーフロー tmp = getSn_SR(sn); if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) // compare to socket n state { close(sn); return SOCKERR_SOCKSTATUS; } // もう一度エラーチェック(安全性の要求) if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; // nonblocking // データがTx Bufferに入ってくると構文の脱出 if(len <= freesize) break; } // SPI転送 wiz_send_data(sn, buf, len); #if _WIZCHIP_ == 5200 sock_next_rd[sn] = getSn_TX_RD(sn) + len; #endif setSn_CR(sn,Sn_CR_SEND); // 更新された長さだけDataを送信 /* コマンドの処理を待っている。... */ while(getSn_CR(sn)); // Sn_CRが「0」に設定されていることを確認(正常動作していることを確認) sock_is_sending |= (1 << sn); // sock_is_sending フラグ「1」に設定 return len; } ---------------------------------------------------------------------------------------------- int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) { uint8_t tmp = 0; uint16_t recvsize = 0; CHECK_SOCKNUM(); CHECK_SOCKMODE(Sn_MR_TCP); CHECK_SOCKDATA(); // W5500は、初期設定Default 2Kbyte、MAX 16Kbyteすることができる。 // RX_buffer_sizeレジスタ読む recvsize = getSn_RxMAX(sn); // Ethernetで受けたDataが初期設定されたRX_buffer_sizeよりも大きい場合、RX_buffer_size分だけ読む。 if(recvsize < len) len = recvsize; //Data あり/なしを判別 while(1) { // RX_BUFのSize読む recvsize = getSn_RX_RSR(sn); // 'Receive Size Register' // エラーフロー tmp = getSn_SR(sn); if (tmp != SOCK_ESTABLISHED) { if(tmp == SOCK_CLOSE_WAIT) { if(recvsize != 0) break; // まだ残っているDataがある場合、再処理 else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) { close(sn); return SOCKERR_SOCKSTATUS; } } else // close socket { close(sn); return SOCKERR_SOCKSTATUS; } } // もう一度チェック if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY; if(recvsize != 0) break; // RSRにRX bufferの長さを読めば、無限ループの脱出 }; if(recvsize < len) len = recvsize; wiz_recv_data(sn, buf, len); // SPI 転送 //元々あったRX_RDポインタの位置から読み取ったデータの長さだけ更新されたポインタの増加を適用 setSn_CR(sn,Sn_CR_RECV); while(getSn_CR(sn)); // Sn_CRが「0」に設定されていることを確認(正常動作していることを確認) return len; } ---------------------------------------------------------------------------------------------- int32_t sendto(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) { uint8_t tmp = 0; uint16_t freesize = 0; CHECK_SOCKNUM(); switch(getSn_MR(sn) & 0x0F) // モードレジスタチェック { case Sn_MR_UDP: // P[3:0] -> '0010' case Sn_MR_MACRAW: // P[3:0] -> '0100' break; default: return SOCKERR_SOCKMODE; } CHECK_SOCKDATA(); //M20140501 : For avoiding fatal error on memory align mismatched //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; // 4 Byte IPを2進数に変換してまとめてIPチェック { uint32_t taddr; taddr = ((uint32_t)addr[0]) & 0x000000FF; taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); } // IPが0.0.0.0チェック(UDP(Broadcast)は、255.255.255.255チェックしない) // 理由は、ブロードキャストの説明を確認 if(*((uint32_t*)taddr) == 0) return SOCKERR_IPINVALID; if(port == 0) return SOCKERR_PORTZERO; //エラーフロー tmp = getSn_SR(sn); if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS; setSn_DIPR(sn,addr); // パケットを送信したところのIP設定 setSn_DPORT(sn,port); // パケットを送信するところPORT設定 //TX_buffer_size 読む freesize = getSn_TxMAX(sn); if (len > freesize) len = freesize; //비어있는 Tx_buffer サイズチェック while(1) { freesize = getSn_TX_FSR(sn); // エラーチェック if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; // HostからDataが入ってくると構文の脱出 if(len <= freesize) break; }; wiz_send_data(sn, buf, len); // SPI転送 #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR(0); #endif // コマンドセットが入ってくるどきにTX_WRが増えた分FSRスペースが減る。 // つまり、TX_ERとTX RDとの間の差で自動計算される setSn_CR(sn,Sn_CR_SEND); /* コマンドの処理を待っている... */ while(getSn_CR(sn)); // コマンド正常動作確認 #if _WIZCHIP_ == 5200 // for W5200 ARP errata setSUBR((uint8_t*)"\x00\x00\x00\x00"); #endif // Data転送判別チェック while(1) { tmp = getSn_IR(sn); // UDPであるため、相手からACKこない // だからData転送が完了したらSn_IR_SENDOK自動Set // そして減ったFSRのスペースがRDが更新され増える。 if(tmp & Sn_IR_SENDOK) { setSn_IR(sn, Sn_IR_SENDOK); // Sn IRクリア break; } //M:20131104 //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; else if(tmp & Sn_IR_TIMEOUT) { setSn_IR(sn, Sn_IR_TIMEOUT); return SOCKERR_TIMEOUT; } //////////// } return len; } ---------------------------------------------------------------------------------------------- int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) { uint8_t mr; uint8_t head[8]; uint16_t pack_len=0; CHECK_SOCKNUM(); //CHECK_SOCKMODE(Sn_MR_UDP); switch((mr=getSn_MR(sn)) & 0x0F) { case Sn_MR_UDP: // '0010', 0x02 case Sn_MR_MACRAW: // '0100', 0x04 break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW: case Sn_MR_PPPoE: break; #endif default: return SOCKERR_SOCKMODE; } CHECK_SOCKDATA(); if(sock_remained_size[sn] == 0) { // Data あり/なしを判別 while(1) { // RX buffer size 読む pack_len = getSn_RX_RSR(sn); // エラーチェック if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY; // Data 読めば構文脱出 if(pack_len != 0) break; }; } sock_pack_info[sn] = PACK_COMPLETED; // Data 読み取り完了 switch (mr & 0x07) { case Sn_MR_UDP : if(sock_remained_size[sn] == 0) { wiz_recv_data(sn, head, 8); // UDPで受けたパケットのうち8 Byteのみ読む setSn_CR(sn,Sn_CR_RECV); while(getSn_CR(sn)); // read peer's IP address, port number & packet length // IP アドレス addr[0] = head[0]; addr[1] = head[1]; addr[2] = head[2]; addr[3] = head[3]; // ポート番号 *port = head[4]; *port = (*port << 8) + head[5]; // 送信されたDataパケットの長さ sock_remained_size[sn] = head[6]; sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7]; // UDPでパケット全体(Data)を受けてきた後、定められたHeader(8byte)を別々に持って来る。 // この状態の時info Flagは下の変数として宣言 sock_pack_info[sn] = PACK_FIRST; // 0x80 } // UDPで受けたパケットの長さが、ユーザーが設定したバッファの長さよりも大きい場合Rx bufferサイズ分だけ受ける if(len < sock_remained_size[sn]) pack_len = len; // そうでない場合、受けたパケットの長さだけData受ける else pack_len = sock_remained_size[sn]; // // Need to packet length check (default 1472) // //pack_lenが、実際のdata wiz_recv_data(sn, buf, pack_len); // data copy. break; case Sn_MR_MACRAW : if(sock_remained_size[sn] == 0) { wiz_recv_data(sn, head, 2); setSn_CR(sn,Sn_CR_RECV); while(getSn_CR(sn)); // read peer's IP address, port number & packet length sock_remained_size[sn] = head[0]; sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1]; if(sock_remained_size[sn] > 1514) { close(sn); return SOCKFATAL_PACKLEN; } sock_pack_info[sn] = PACK_FIRST; } if(len < sock_remained_size[sn]) pack_len = len; else pack_len = sock_remained_size[sn]; wiz_recv_data(sn,buf,pack_len); break; #if ( _WIZCHIP_ < 5200 ) case Sn_MR_IPRAW: if(sock_remained_size[sn] == 0) { wiz_recv_data(sn, head, 6); setSn_CR(sn,Sn_CR_RECV); while(getSn_CR(sn)); addr[0] = head[0]; addr[1] = head[1]; addr[2] = head[2]; addr[3] = head[3]; sock_remained_size[sn] = head[4]; sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; sock_pack_info[sn] = PACK_FIRST; } // // Need to packet length check // if(len < sock_remained_size[sn]) pack_len = len; else pack_len = sock_remained_size[sn]; wiz_recv_data(sn, buf, pack_len); // data copy. break; #endif default: // パケットを受けてい(RX bufferポインタの増加) wiz_recv_ignore(sn, pack_len); // data copy. // パケット全体をremained変数に入れて、再びループ回したときに読む sock_remained_size[sn] = pack_len; break; } setSn_CR(sn,Sn_CR_RECV); /* wait to process the command... */ while(getSn_CR(sn)) ; // もし受けたパケットが、ユーザーが設定したバッファサイズよりも大きい場合、その差の数値分抜く。 // そしてsock_remained_sizeに残ったパケットサイズを保存する。 sock_remained_size[sn] -= pack_len; //M20140501 : replace 0x01 with PACK_REMAINED //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; // パケットがまだW5500バッファに残っている場合info変数をREMAINEDに設定 // もう一度繰り返し、残りのパケットデータもHostに送る。 if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; //0x01 // return pack_len; // 実際のdataパケットのみをHostに送る。 } ---------------------------------------------------------------------------------------------- // SPI ADDRESS + BSB + R/W , OP(VDM, FDM) 割り当て void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { uint16_t ptr = 0; uint32_t addrsel = 0; if(len == 0) return; //Hostは送信するDataを保存開始Addressであるこの値を読む。 ptr = getSn_TX_WR(sn); // Tx bufferの書き込みポインタ //M20140501 : implict type casting -> explict type casting //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); //ADDRESS[15:8] + BSB[7:3] 割り当て //0b 0000:0000:0000:0XXX addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); //Hostは、この値を開始AddressしてdataをSocket n TX Bufferに保存する。 WIZCHIP_WRITE_BUF(addrsel,wizdata, len); //元々あったTX_WRポインタの位置からバッファに保存されたdataのサイズだけ合わせてTX_WRの位置の値を更新する。 ptr += len; setSn_TX_WR(sn,ptr); // ポインタ更新 } ---------------------------------------------------------------------------------------------- // SPI ADDRESS + BSB + R/W , OP(VDM, FDM) 割り当て void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { uint16_t ptr = 0; uint32_t addrsel = 0; if(len == 0) return; //Hostは送信するDataを保存開始Addressであるこの値を読む。 ptr = getSn_RX_RD(sn); // RX bufferの読み取りポインタ //M20140501 : implict type casting -> explict type casting //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); //ADDRESS[15:8] + BSB[7:3] 割り当て //0b 0000:0000:0000:0XXX addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); //Hostは、この開始Addressからdataを読む。 WIZCHIP_READ_BUF(addrsel, wizdata, len); //元々あったRX_RDポインタの位置から読み取ったデータの長さだけポインタ増加 ptr += len; setSn_RX_RD(sn,ptr); // 増加した後、ポインタ更新 } void wiz_recv_ignore(uint8_t sn, uint16_t len) { uint16_t ptr = 0; ptr = getSn_RX_RD(sn); ptr += len; setSn_RX_RD(sn,ptr); } ---------------------------------------------------------------------------------------------- void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { uint16_t i = 0; uint16_t j = 0; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); // CSがLowのとき - > SPI転送を開始する #if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) // SPIインタフェースモードチェック #if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_ ) // VDMモードチェック // R/W, OP(VDM,FDM) 割り当て // XXXX:XXXX:XXXX:X000 AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); // 書き込みモード(MOSI) WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); // Address上位1byte転送 WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); // Address下位1byte転送 WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); // コントロール 位相 1byte 転送(BSB + R/W + OP) // ユーザーが設定したバッファにユーザーが入力した長さだけバッファへの書き込み for(i = 0; i < len; i++,j) WIZCHIP.IF.SPI._write_byte(pBuf[i]); ---------------------------------------------------------------------------------------------- void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { uint16_t i = 0; uint16_t j = 0; WIZCHIP_CRITICAL_ENTER(); WIZCHIP.CS._select(); // CSがLowのとき - > SPI転送を開始する #if( (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SPI_)) // SPIインタフェースモードチェック #if ( _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_ ) // VDMモードチェック // R/W, OP(VDM,FDM) 할당 // XXXX:XXXX:XXXX:X000 AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); // 0 read mode(MISO) WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); // Address上位1byte転送 WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); // Address下位1byte転送 WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); // コントロール 位相 1byte 転送(BSB + R/W + OP) // ユーザーが設定したバッファにEthernetから受けた長さだけバッファから読む for(i = 0; i < len; i++,j) pBuf[i] = WIZCHIP.IF.SPI._read_byte(); // 1byte read [/code]
お疲れ様でした。