안녕하세요.
Edward입니다.
채팅프로그램에 이어서 Wiznet 사에서 배포하여 사용되는 Ethernet Driver 분석을 공유하고자 합니다.
이번은 한글버전이고 다음은 영어버전 그리고 일어 버전을 추가로 업로드 하려고 합니다.
궁금하신부분이 있는 분들은 댓글 남겨주시거나 혹은 http://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 //플래그 모드 Flow 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(); // Socket number Check CHECK_SOCKMODE(Sn_MR_TCP); // 소켓이 TCP 모드인지 체크 CHECK_SOCKINIT(); // 소켓생성 이후 Sn_SR가 SOCK_INIT상태가 되었는지 체크 setSn_CR(sn,Sn_CR_LISTEN); // 커맨드레지스터에 '소켓 대기' 명령 while(getSn_CR(sn)); // 소켓 대기인지 확인 // 에러 Flow (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; // 나누어져 있는 IP를 묶어서 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 setSUBR(0); #endif setSn_CR(sn,Sn_CR_CONNECT); // 커맨드레지스터에 '소켓 접속' 명령 while(getSn_CR(sn)); // 소켓 접속 확인 // Blocking & Nonblocking 설정 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); /* wait to process the command... */ 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; } ---------------------------------------------------------------------------------------------- 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; } // SEND_OK, TIME_OUT 둘 다 아닐경우 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 체크 // 에러 Flow 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를 전송 /* wait to process the command... */ 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' // 에러 Flow 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) // Mode Register 체크 { 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; // 나누어져 있는 IP를 묶어서 IP 체크 (Connect 참고) { 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); // Packet을 보낼 곳의 IP 설정 setSn_DPORT(sn,port); // Packet을 보낼 곳의 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_WR과 TX_RD간의 차이로 자동 계산됨 setSn_CR(sn,Sn_CR_SEND); /* wait to process the command... */ 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); // clear 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로 받은 패킷 중 8Byte만 읽음 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_); // 1 write mode(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); // Control phase 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); // Control phase 1byte 전송(BSB + R/W + OP) // 사용자가 설정한 버퍼에 Ethernet으로 부터 받은 길이 만큼 버퍼에서 읽음 for(i = 0; i < len; i++,j) pBuf[i] = WIZCHIP.IF.SPI._read_byte(); // 1byte read [/code]