WIZ820io(W5200) network interface、EthernetNetIf compatible.
example
#include "WIZ820ioNetIf.h" #include "HTTPClient.h" #include "HTTPServer.h" #if defined(TARGET_KL25Z) WIZ820ioNetIf eth(PTD2,PTD3,PTD1,PTD0,PTD5); #endif HTTPClient http; HTTPStream stream; void callback(HTTPResult r){ printf("callback %d %s\n", r, HTTPClient::ResultStr(r)); } int main() { int err = eth.setup(); if (err < 0) { printf("setup error %d\n", err); exit(-1); } HTTPServer svr; svr.addHandler<SimpleHandler>("/"); svr.bind(80); const char* uri = "http://va009039-mbed.appspot.com/kl25z/"; http.get(uri, &stream, callback); uint8_t buf[256]; int total = 0; stream.readNext(buf, sizeof(buf)); while(1) { if(stream.readable()) { int len = stream.readLen(); total += len; printf("%d %d\n", total, len); stream.readNext(buf, sizeof(buf)); } Net::poll(); } }
Revision 0:bdeec5f86894, committed 2013-03-22
- Comitter:
- va009039
- Date:
- Fri Mar 22 11:51:24 2013 +0000
- Child:
- 1:22b9052d864d
- Commit message:
- [mbed] converted /w5200NetIf/w5200NetIf
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DHCPClient.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,170 @@ +// DHCPClient.cpp 2012/4/21 +// DHCP Client for WIZ820io(W5200) +#include "mbed.h" +#include "w5100.h" +#include "UDPSocket.h" +#include "DHCPClient.h" +//#define __DEBUG +#include "dbg/dbg.h" + +#ifdef __DEBUG +#define DBG2(...) do{ DebugStream::debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); DebugStream::debug(__VA_ARGS__); } while(0); +#else +#define DBG2(...) while(0); +#endif //__DEBUG + +//#define DEBUG + +#ifdef DEBUG +#include "Utils.h" +#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) +#else //DEBUG +#define PRINT_FUNC() +#endif //DEBUG + +int DHCPClient::discover(uint8_t buf[], int size) { + memset(buf, 0x00, size); + const uint8_t headers[] = {0x01,0x01,0x06,0x00, + 0x12,0x34,0x56,0x78}; // xid + memcpy(buf, headers, sizeof(headers)); + int t = clock(); + xid[0] = t<<24; + xid[1] = t<<16; + xid[2] = t<<8; + xid[3] = t; + memcpy(buf+DHCP_OFFSET_XID, xid, 4); + W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); + const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie + 0x35,0x01,0x01, // DHCP DISCOVER + 0xff}; + memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); + uint8_t ip[4] = {0,0,0,0}; + W5100.setIPAddress(ip); + return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); +} + +int DHCPClient::request(uint8_t buf[], int size) { + memset(buf, 0x00, size); + const uint8_t headers[] = {0x01,0x01,0x06,0x00, + 0x12,0x34,0x56,0x78}; // xid + memcpy(buf, headers, sizeof(headers)); + memcpy(buf+DHCP_OFFSET_XID, xid, 4); + memcpy(buf+DHCP_OFFSET_YIADDR, yiaddr, 4); + W5100.getMACAddress(buf+DHCP_OFFSET_CHADDR); + const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie + 0x35,0x01,0x03, // DHCP REQUEST + 0x32,0x04,0x00,0x00,0x00,0x00, // request IP + 0xff}; + memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE, options, sizeof(options)); + memcpy(buf+DHCP_OFFSET_MAGIC_COOKIE+9, yiaddr, 4); + return DHCP_OFFSET_MAGIC_COOKIE + sizeof(options); +} + +int DHCPClient::offer_ack(uint8_t buf[], int size) { + memcpy(yiaddr, &buf[DHCP_OFFSET_YIADDR], 4); + uint8_t *p; + int msg_type = -1; + p = buf + DHCP_OFFSET_OPTIONS; + while(*p != 0xff && p < (uint8_t*)&buf[DHCP_MAX_PACKET_SIZE]) { + int code = *p++; + if (code == 0x00) { + continue; + } + int len = *p++; +#ifdef DEBUG + char codeStr[24]; + snprintf(codeStr, sizeof(codeStr), "DHCP option: %d", code); + printfBytes(codeStr, p, len); +#endif //DEBUG + if (code == 53) { + msg_type = *p; + } else if (code == 1) { + memcpy(netmask, p, 4); // Subnet mask address + } else if (code == 3) { + memcpy(gateway, p, 4); // Gateway IP address + } else if (code == 6) {// DNS + memcpy(dnsaddr, p, 4); + } + p += len; + } + return msg_type; +} + +bool DHCPClient::verify(uint8_t buf[], int len) { + if (len < DHCP_OFFSET_OPTIONS) { + return false; + } + if (buf[DHCP_OFFSET_OP] != 0x02) { + return false; + } + if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { + return false; + } + return true; +} + +void DHCPClient::callback(UDPSocketEvent e) +{ + PRINT_FUNC(); + uint8_t buf[DHCP_MAX_PACKET_SIZE]; + Host host; + int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host); + if (!verify(buf, len)) { + return; + } + int r = offer_ack(buf, len); + if (r == 2) { // OFFER + request(buf, 300); + Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast + m_udp->sendto((char*)buf, 300, &server); + } else if (r == 5) { // ACK + exit_flag = true; + } +} + +int DHCPClient::setup(int timeout_ms) +{ + PRINT_FUNC(); + int interval_ms = 2000; // 2000msec + if (timeout_ms < interval_ms) { + interval_ms = timeout_ms; + } + m_retry = 0; + m_interval.start(); + m_udp = new UDPSocket; + m_udp->setOnEvent(this, &DHCPClient::callback); + Host local(IpAddr(0,0,0,0), 68); + Host server(IpAddr(255,255,255,255), 67); // DHCP broadcast + m_udp->bind(local); + uint8_t buf[300]; + discover(buf, sizeof(buf)); + m_udp->sendto((char*)buf, sizeof(buf), &server); + m_interval.reset(); + exit_flag = false; + int err = 0; + while(1) { + Net::poll(); + if (exit_flag) { + DBG2("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); + break; + } + if (m_interval.read_ms() > interval_ms) { + DBG2("m_retry: %d\n", m_retry); + if (++m_retry >= (timeout_ms/interval_ms)) { + err = -1; + break; + } + m_udp->sendto((char*)buf, sizeof(buf), &server); + m_interval.reset(); + } +#ifdef DEBUG + wait_ms(500); +#endif //DEBUG + } + delete m_udp; + return err; +} + +DHCPClient::DHCPClient() { + m_udp = NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DHCPClient.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,36 @@ +// DHCPClient.h 2012/4/21 +#ifndef DHCPCLIENT_H +#define DHCPCLIENT_H +#include "UDPSocket.h" + + +#define DHCP_OFFSET_OP 0 +#define DHCP_OFFSET_XID 4 +#define DHCP_OFFSET_YIADDR 16 +#define DHCP_OFFSET_CHADDR 28 +#define DHCP_OFFSET_MAGIC_COOKIE 236 +#define DHCP_OFFSET_OPTIONS 240 +#define DHCP_MAX_PACKET_SIZE 600 + +class DHCPClient { + int discover(uint8_t buf[], int size); + int request(uint8_t buf[], int size); + int offer_ack(uint8_t buf[], int size); + bool verify(uint8_t buf[], int len); +public: + void callback(UDPSocketEvent e); + int setup(int timeout_ms = 15000); + DHCPClient(); + uint8_t chaddr[6]; // MAC + uint8_t yiaddr[4]; // IP + uint8_t dnsaddr[4]; // DNS + uint8_t gateway[4]; + uint8_t netmask[4]; +private: + UDPSocket* m_udp; + uint8_t xid[4]; + bool exit_flag; + Timer m_interval; + int m_retry; +}; +#endif //DHCPCLIENT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetDnsRequest.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,199 @@ +// MyNetDnsRequest.cpp 2012/4/22 +#include "mbed.h" +#include "MyNetDnsRequest.h" +#include "UDPSocket.h" +#include <string> +#include "dnsname.h" +#include "W5200NetIf.h" +//#define __DEBUG +#include "dbg/dbg.h" + +#ifdef __DEBUG +#define DBG2(...) do{ DebugStream::debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); DebugStream::debug(__VA_ARGS__); } while(0); +#else +#define DBG2(...) while(0); +#endif //__DEBUG + +//#define DEBUG + +#ifdef DEBUG +#include "Utils.h" +#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) +#else //DEBUG +#define PRINT_FUNC() +#endif //DEBUG + + +MyNetDnsRequest::MyNetDnsRequest(const char* hostname) : NetDnsRequest(hostname), + m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) { + PRINT_FUNC(); +} + +MyNetDnsRequest::MyNetDnsRequest(Host* pHost) : NetDnsRequest(pHost), + m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) { + PRINT_FUNC(); +} + +MyNetDnsRequest::~MyNetDnsRequest() { + PRINT_FUNC(); + if (m_udp) { + delete m_udp; + } +} + +void MyNetDnsRequest::callback(UDPSocketEvent e) +{ + PRINT_FUNC(); + DBG2("m_id[]=%02x:%02x\n", m_id[0], m_id[1]); + uint8_t buf[512]; + Host host; + int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host); + if (memcmp(buf+0, m_id, 2) != 0) { //verify + return; + } + int rcode = response(buf, len); + if (rcode == 0) { + m_state = MYNETDNS_OK; + } else { + m_state = MYNETDNS_NOTFOUND; + } +} + +int MyNetDnsRequest::response(uint8_t buf[], int size) { + PRINT_FUNC(); +#ifdef DEBUG + printHex(buf, size); +#endif //DEBUG + int rcode = buf[3] & 0x0f; + if (rcode != 0) { + return rcode; + } + int qdcount = buf[4]<<8|buf[5]; + int ancount = buf[6]<<8|buf[7]; + int pos = 12; + while(qdcount-- > 0) { + dnsname qname(buf); + pos = qname.decode(pos); // qname + pos += 4; // qtype qclass + } + while(ancount-- > 0) { + dnsname name(buf); + pos = name.decode(pos); // name + int type = buf[pos]<<8|buf[pos+1]; + pos += 8; // type class TTL + int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2; + int rdata_pos = pos; + pos += rdlength; + if (type == 1) { // A record + m_ip = IpAddr(buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]); + } +#ifdef DEBUG + printf("%s", name.str.c_str()); + if (type == 1) { + printf(" A %d.%d.%d.%d\n", + buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]); + } else if (type == 5) { + dnsname rdname(buf); + rdname.decode(rdata_pos); + printf(" CNAME %s\n", rdname.str.c_str()); + } else { + printf(" TYPE:%d", type); + printfBytes(" RDATA:", &buf[rdata_pos], rdlength); + } +#endif //DEBUG + } + return rcode; +} + +int MyNetDnsRequest::query(uint8_t buf[], int size, const char* hostname) { + PRINT_FUNC(); + const uint8_t header[] = { + 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0 + 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0 + 0x00,0x00,0x00,0x00};// nscount=0 arcount=0 + const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN + memcpy(buf, header, sizeof(header)); + int t = clock(); + m_id[0] = t>>8; + m_id[1] = t; + memcpy(buf, m_id, 2); + dnsname qname(buf); + int pos = qname.encode(sizeof(header), (char*)hostname); + memcpy(buf+pos, tail, sizeof(tail)); + pos += sizeof(tail); + return pos; +} + +void MyNetDnsRequest::resolve(const char* hostname) { + PRINT_FUNC(); + if (m_udp == NULL) { + m_udp = new UDPSocket; + } + m_udp->setOnEvent(this, &MyNetDnsRequest::callback); + Host local(IpAddr(0,0,0,0), 1024 + rand()&0x7fff); + IpAddr dns(8,8,8,8); + NetIf* pIf = Net::getDefaultIf(); + if (pIf) { + dns = ((W5200NetIf*)pIf)->m_dns; + } + Host server(dns, 53); // DNS + m_udp->bind(local); + uint8_t buf[256]; + int size = query(buf, sizeof(buf), hostname); +#ifdef DEBUG + printf("hostname:[%s]\n", hostname); + printHex(buf, size); +#endif + m_udp->sendto((char*)buf, size, &server); + m_interval.reset(); + m_interval.start(); +} + +void MyNetDnsRequest::poll() { + PRINT_FUNC(); +#ifdef DEBUG + printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp); + wait_ms(400); +#endif //DEBUG + switch(m_state) { + case MYNETDNS_START: + m_retry = 0; + resolve(m_hostname); + m_state = MYNETDNS_PROCESSING; + break; + case MYNETDNS_PROCESSING: + break; + case MYNETDNS_NOTFOUND: + onReply(NETDNS_FOUND); + break; + case MYNETDNS_ERROR: + onReply(NETDNS_ERROR); + break; + case MYNETDNS_OK: + DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms()); + onReply(NETDNS_FOUND); + break; + } + if (m_interval.read_ms() > 1000) { + m_interval.stop(); + DBG2("timeout m_retry=%d\n", m_retry); + if (++m_retry >= 2) { + m_state = MYNETDNS_ERROR; + } else { + resolve(m_hostname); + m_state = MYNETDNS_PROCESSING; + } + } + if(m_closing && (m_state!=MYNETDNS_PROCESSING)) { + NetDnsRequest::close(); + } +} + +void MyNetDnsRequest::close() { + PRINT_FUNC(); + if(m_state != MYNETDNS_PROCESSING) { + NetDnsRequest::close(); + } else { + m_closing = true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetDnsRequest.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,36 @@ +// MyNetDnsRequest.h 2012/4/19 +#ifndef MYNETDNSREQUEST_H +#define MYNETDNSREQUEST_H +#include "if/net/netdnsrequest.h" +#include "UDPSocket.h" + +class MyNetDnsRequest : public NetDnsRequest { +public: + MyNetDnsRequest(const char* hostname); + MyNetDnsRequest(Host* pHost); + virtual ~MyNetDnsRequest(); + virtual void poll(); + virtual void close(); +protected: + void callback(UDPSocketEvent e); + int response(uint8_t buf[], int size); + int query(uint8_t buf[], int size, const char* hostname); + void resolve(const char* hostname); + uint8_t m_id[2]; + Timer m_interval; + int m_retry; +private: + enum MyNetDnsState + { + MYNETDNS_START, + MYNETDNS_PROCESSING, //Req has not completed + MYNETDNS_NOTFOUND, + MYNETDNS_ERROR, + MYNETDNS_OK + }; + MyNetDnsState m_state; + bool m_cbFired; + bool m_closing; + UDPSocket *m_udp; +}; +#endif //MYNETDNSREQUEST_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetIf.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,80 @@ +// MyNetIf.cpp 2012/4/17 +#include "mbed.h" +#include "MyNetIf.h" +#include "MyNetTcpSocket.h" +#include "MyNetUdpSocket.h" +#include "MyNetDnsRequest.h" + +//#define DEBUG + +#ifdef DEBUG +#include "w5100.h" +#include "Utils.h" +#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) +#else //DEBUG +#define PRINT_FUNC() +#endif //DEBUG + +MyNetIf::MyNetIf() : NetIf(), m_init(false) +{ + PRINT_FUNC(); +} + +MyNetIf::~MyNetIf() { + PRINT_FUNC(); +} + +void MyNetIf::init() { + PRINT_FUNC(); +} + +NetTcpSocket* MyNetIf::tcpSocket() { + PRINT_FUNC(); + return new MyNetTcpSocket(); +} + +NetUdpSocket* MyNetIf::udpSocket() { + PRINT_FUNC(); + return new MyNetUdpSocket(); +} + +NetDnsRequest* MyNetIf::dnsRequest(const char* hostname) { + PRINT_FUNC(); + return new MyNetDnsRequest(hostname); +} + +NetDnsRequest* MyNetIf::dnsRequest(Host* pHost) { + PRINT_FUNC(); + return new MyNetDnsRequest(pHost); +} + +void MyNetIf::poll() { + PRINT_FUNC(); +#ifdef DEBUG + printf("SnMR:"); + for(int s = 0; s < MAX_SOCK_NUM; s++) { + printf(" %02x", W5100.readSnMR(s)); + } + printf("\n"); + + printf("SnIR:"); + for(int s = 0; s < MAX_SOCK_NUM; s++) { + printf(" %02x", W5100.readSnIR(s)); + } + printf("\n"); + + printf("SnSR:"); + for(int s = 0; s < MAX_SOCK_NUM; s++) { + printf(" %02x", W5100.readSnSR(s)); + } + printf("\n"); + + printf("SnPORT:"); + for(int s = 0; s < MAX_SOCK_NUM; s++) { + printf(" %d", W5100.readSnPORT(s)); + } + printf("\n"); + + wait_ms(500); +#endif //DEBUG +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetIf.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,24 @@ +// MyNetIf.h 2012/4/15 +#ifndef MYIPNETIF_H +#define MYIPNETIF_H +#include "mbed.h" +#include "core/net.h" +#include "if/net/netif.h" + +class MyNetIf : public NetIf { +public: + MyNetIf(); + + void init(); + + virtual ~MyNetIf(); + virtual NetTcpSocket* tcpSocket(); + virtual NetUdpSocket* udpSocket(); + virtual NetDnsRequest* dnsRequest(const char* hostname); + virtual NetDnsRequest* dnsRequest(Host* pHost); + + virtual void poll(); +private: + bool m_init; +}; +#endif //MYIPNETIF_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetTcpSocket.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,259 @@ +// MyNetTcpSocket.cpp 2012/4/22 +#include "mbed.h" +#include "w5100.h" +#include "MyNetTcpSocket.h" +//#define __DEBUG +#include "dbg/dbg.h" + +#ifdef __DEBUG +#define DBG2(...) do{ DebugStream::debug("%p %s ", this,__PRETTY_FUNCTION__); DebugStream::debug(__VA_ARGS__); } while(0); +#else +#define DBG2(...) while(0); +#endif //__DEBUG + +//#define DEBUG + +#ifdef DEBUG +#include "Utils.h" +#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) +#else //DEBUG +#define PRINT_FUNC() +#endif //DEBUG + +#define USE_NO_DELAYED_ACK 1 + +int w5200_new_socket() +{ + for(int i = 0; i < MAX_SOCK_NUM; i++) { + if (W5100.readSnMR(i) == SnMR::CLOSE) { // 0x00 + if (W5100.readSnSR(i) != SnSR::LISTEN) { // 0x14 + return i; + } + } + } + return -1; // not found +} + +MyNetTcpSocket::MyNetTcpSocket(int socket) : NetTcpSocket(),_socket(socket),wait_accept(false) { + PRINT_FUNC(); + DBG2("socket: %d\n", socket); + if (_socket == (-1)) { + _socket = w5200_new_socket(); + } +#ifdef DEBUG + printf("%p socket: %d\n", this, _socket); +#endif //DEBUG + if (_socket != (-1)) { + uint8_t Sn_MR = SnMR::TCP; // set TCP mode +#if USE_NO_DELAYED_ACK + Sn_MR |= SnMR::ND; +#endif + W5100.writeSnMR(_socket, Sn_MR); + } +} + +MyNetTcpSocket::~MyNetTcpSocket() { + PRINT_FUNC(); + DBG2("socket=%d\n", _socket); + close(); + if (_socket != (-1)) { + W5100.writeSnMR(_socket, SnMR::CLOSE); + } +} + +NetTcpSocketErr MyNetTcpSocket::bind(const Host& me) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + int port = me.getPort(); + W5100.writeSnPORT(_socket, port); + return NETTCPSOCKET_OK; +} + +NetTcpSocketErr MyNetTcpSocket::listen() { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + W5100.execCmdSn(_socket, Sock_OPEN); // set OPEN command + W5100.execCmdSn(_socket, Sock_LISTEN); // listen +#ifdef DEBUG + uint8_t ip[4]; + printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, + W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket)); + W5100.getIPAddress(ip); + printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket)); +#endif //DEBUG + wait_accept = true; + return NETTCPSOCKET_OK; +} + +NetTcpSocketErr MyNetTcpSocket::connect(const Host& host) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + uint8_t ip[4]; + ip[0] = host.getIp()[0]; + ip[1] = host.getIp()[1]; + ip[2] = host.getIp()[2]; + ip[3] = host.getIp()[3]; + int port = host.getPort(); + W5100.writeSnDIPR(_socket, ip); + W5100.writeSnDPORT(_socket, port); + if (W5100.readSnPORT(_socket) == 0) { + W5100.writeSnPORT(_socket, 1024 + _socket); + } + W5100.execCmdSn(_socket, Sock_OPEN); // set OPEN command + W5100.execCmdSn(_socket, Sock_CONNECT); +#ifdef DEBUG + printf("socket:%d SnMR:%02x SnIR:%02x SnSR:%02x\n", _socket, + W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket)); + W5100.getIPAddress(ip); + printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket)); + W5100.readSnDIPR(_socket, ip); + printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket)); +#endif //DEBUG + return NETTCPSOCKET_OK; +} + +NetTcpSocketErr MyNetTcpSocket::accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + uint8_t ip[4]; + W5100.readSnDIPR(_socket, ip); + pClient->setIp(IpAddr(ip[0],ip[1],ip[2],ip[3])); + int port = W5100.readSnDPORT(_socket); + pClient->setPort(port); + Host me; + me.setPort(W5100.readSnPORT(_socket)); + MyNetTcpSocket* pNewNetTcpSocket = new MyNetTcpSocket(_socket); + if (pNewNetTcpSocket == NULL) { + return NETTCPSOCKET_EMPTY; + } + pNewNetTcpSocket->m_refs++; + *ppNewNetTcpSocket = pNewNetTcpSocket; + _socket = w5200_new_socket(); + if (_socket != (-1)) { + uint8_t Sn_MR = SnMR::TCP; // set TCP mode +#if USE_NO_DELAYED_ACK + Sn_MR |= SnMR::ND; +#endif + W5100.writeSnMR(_socket, Sn_MR); + bind(me); + listen(); + } + return NETTCPSOCKET_OK; +} + +int /*if < 0 : NetTcpSocketErr*/ MyNetTcpSocket::send(const char* buf, int len) { + PRINT_FUNC(); +#ifdef DEBUG + printf("buf:%p, len=%d\n", buf, len); + printHex((u8*)buf, len); +#endif //DEBUG + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + if (len > 0) { + W5100.send_data_processing(_socket, (uint8_t*)buf, len); + W5100.execCmdSn(_socket, Sock_SEND); + } + return len; +} + +int /*if < 0 : NetTcpSocketErr*/ MyNetTcpSocket::recv(char* buf, int len){ + PRINT_FUNC(); + if (_socket == (-1)) { + return NETTCPSOCKET_MEM; + } + int size = W5100.getRXReceivedSize(_socket); + if (size > len) { + size = len; + } + if (size > 0) { + W5100.recv_data_processing(_socket, (uint8_t*)buf, size); + W5100.execCmdSn(_socket, Sock_RECV); + } +#ifdef DEBUG + printHex((uint8_t*)buf, size); +#endif //DEBUG + return size; +} + +NetTcpSocketErr MyNetTcpSocket::close() { + PRINT_FUNC(); + DBG2("m_closed=%d m_refs=%d\n", m_closed, m_refs); + if(m_closed) { + return NETTCPSOCKET_OK; + } + m_closed = true; + cleanUp(); + if (_socket != (-1)) { + W5100.execCmdSn(_socket, Sock_DISCON); + W5100.execCmdSn(_socket, Sock_CLOSE); + } + return NETTCPSOCKET_OK; +} + +NetTcpSocketErr MyNetTcpSocket::poll(){ + PRINT_FUNC(); + NetTcpSocket::flushEvents(); +#ifdef DEBUG + printf("%p socket:%d\n", this,_socket); + if (_socket != (-1)) { + printf("SnMR:%02x SnIR:%02x SnSR:%02x\n", + W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket)); + uint8_t ip[4]; + W5100.readSnDIPR(_socket, ip); + printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT: %d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket)); + printf("Sn_RX_RSR:%5d, Sn_RX_RD:%5d, Sn_RX_WR:%5d\n", + W5100.readSnRX_RSR(_socket), W5100.readSnRX_RD(_socket), W5100.readSnRX_WR(_socket)); + printf("Sn_TX_FSR:%5d, Sn_TX_RD:%5d, Sn_TX_WR:%5d\n", + W5100.readSnTX_FSR(_socket), W5100.readSnTX_RD(_socket), W5100.readSnTX_WR(_socket)); + } + wait_ms(200); +#endif //DEBUG + if (_socket == (-1)) { + return NETTCPSOCKET_OK; + } + uint8_t Sn_SR = W5100.readSnSR(_socket); + if (wait_accept) { + if (Sn_SR == 0x17) { + queueEvent(NETTCPSOCKET_ACCEPT); + wait_accept = false; + } + } + if (Sn_SR == 0x1c) { + queueEvent(NETTCPSOCKET_CONRST); + } + if (W5100.getRXReceivedSize(_socket) > 0) { + queueEvent(NETTCPSOCKET_READABLE); + } + if (Sn_SR == 0x17) { + queueEvent(NETTCPSOCKET_CONNECTED); + if (W5100.getTXFreeSize(_socket) > 0) { + queueEvent(NETTCPSOCKET_WRITEABLE); + } + } + if (Sn_SR == 0x00) { + queueEvent(NETTCPSOCKET_DISCONNECTED); + } + return NETTCPSOCKET_OK; +} + +void MyNetTcpSocket::cleanUp() //Flush input buffer +{ + PRINT_FUNC(); + if (_socket == (-1)) { + return; + } + while(W5100.getRXReceivedSize(_socket) > 0) { + uint8_t temp[1]; + W5100.recv_data_processing(_socket, temp, 1); + W5100.execCmdSn(_socket, Sock_RECV); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetTcpSocket.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,25 @@ +// MyNetTcpSocket.h 2012/4/16 +#ifndef MYNETTCPSOCKET_H +#define MYNETTCPSOCKET_H +#include "if/net/nettcpsocket.h" + +class MyNetTcpSocket : public NetTcpSocket { +public: + MyNetTcpSocket(int socket = (-1)); + virtual ~MyNetTcpSocket(); + virtual NetTcpSocketErr bind(const Host& me); + virtual NetTcpSocketErr listen(); + virtual NetTcpSocketErr connect(const Host& host); + virtual NetTcpSocketErr accept(Host* pClient, NetTcpSocket** ppNewNetTcpSocket); + virtual int /*if < 0 : NetTcpSocketErr*/ send(const char* buf, int len); + virtual int /*if < 0 : NetTcpSocketErr*/ recv(char* buf, int len); + virtual NetTcpSocketErr close(); + virtual NetTcpSocketErr poll(); +protected: + int _socket; + bool wait_accept; +private: + void cleanUp(); //Flush input buffer + queue<MyNetTcpSocket*> m_lpInNetTcpSocket; +}; +#endif //MYNETTCPSOCKET_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetUdpSocket.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,152 @@ +// MyNetUdpSocket.cpp 2012/4/16 +#include "mbed.h" +#include "MyNetUdpSocket.h" +#include "w5100.h" + +//#define DEBUG + +#ifdef DEBUG +#include "Utils.h" +#define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__) +#else //DEBUG +#define PRINT_FUNC() +#endif //DEBUG + +extern int w5200_new_socket(); // MyNetTcpSocket.cpp + +MyNetUdpSocket::MyNetUdpSocket(int socket) : NetUdpSocket(),_socket(socket) { + PRINT_FUNC(); + if (_socket == (-1)) { + _socket = w5200_new_socket(); + } + if (_socket != (-1)) { + W5100.writeSnMR(_socket, SnMR::UDP); // set UDP mode + } +} + +MyNetUdpSocket::~MyNetUdpSocket() { + PRINT_FUNC(); + close(); + if (_socket != (-1)) { + W5100.writeSnMR(_socket, SnMR::CLOSE); + } +} + +NetUdpSocketErr MyNetUdpSocket::bind(const Host& me) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETUDPSOCKET_MEM; + } + int port = me.getPort(); + W5100.writeSnPORT(_socket, port); + W5100.execCmdSn( _socket, Sock_OPEN); // set OPEN command + return NETUDPSOCKET_OK; +} + +int /*if < 0 : NetUdpSocketErr*/ MyNetUdpSocket::sendto(const char* buf, int len, Host* pHost) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETUDPSOCKET_MEM; + } + uint8_t ip[4]; + ip[0] = pHost->getIp()[0]; + ip[1] = pHost->getIp()[1]; + ip[2] = pHost->getIp()[2]; + ip[3] = pHost->getIp()[3]; + int port = pHost->getPort(); + W5100.writeSnDIPR(_socket, ip); + W5100.writeSnDPORT(_socket, port); + W5100.send_data_processing(_socket, (uint8_t*)buf, len); + W5100.execCmdSn(_socket, Sock_SEND); +#ifdef DEBUG + printHex((u8*)buf, len); + W5100.getIPAddress(ip); + printf("SIPR: %d.%d.%d.%d Sn_PORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnPORT(_socket)); + W5100.readSnDIPR(_socket, ip); + printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT:%d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket)); +#endif //DEBUG + return len; +} + +int /*if < 0 : NetUdpSocketErr*/ MyNetUdpSocket::recvfrom(char* buf, int len, Host* pHost) { + PRINT_FUNC(); + if (_socket == (-1)) { + return NETUDPSOCKET_MEM; + } + int size = W5100.getRXReceivedSize(_socket); + if (size < 8) { + return -1; + } + uint8_t info[8]; + W5100.recv_data_processing(_socket, info, 8); + W5100.execCmdSn(_socket, Sock_RECV); + pHost->setIp(IpAddr(info[0],info[1],info[2],info[3])); + pHost->setPort(info[4]<<8|info[5]); + size -= 8; + if (size > len) { + size = len; + } + W5100.recv_data_processing(_socket, (uint8_t*)buf, size); + W5100.execCmdSn(_socket, Sock_RECV); +#ifdef DEBUG + printfBytes("UDP PACKET-INFO", (u8*)info, 8); + printHex((u8*)buf, size); +#endif //DEBUG + return size; +} + +NetUdpSocketErr MyNetUdpSocket::close() { + PRINT_FUNC(); + if(m_closed) { + return NETUDPSOCKET_OK; + } + if (_socket == (-1)) { + return NETUDPSOCKET_MEM; + } + m_closed = true; + cleanUp(); + W5100.writeSnMR(_socket, SnMR::CLOSE); + return NETUDPSOCKET_OK; +} + +NetUdpSocketErr MyNetUdpSocket::poll() { + PRINT_FUNC(); + NetUdpSocket::flushEvents(); +#ifdef DEBUG + printf("%p socket:%d\n", this,_socket); + if (_socket != (-1)) { + printf("SnMR:%02x SnIR:%02x SnSR:%02x\n", + W5100.readSnMR(_socket), W5100.readSnIR(_socket), W5100.readSnSR(_socket)); + uint8_t ip[4]; + W5100.readSnDIPR(_socket, ip); + printf("Sn_DIPR: %d.%d.%d.%d Sn_DPORT: %d\n", ip[0], ip[1], ip[2], ip[3], W5100.readSnDPORT(_socket)); + uint8_t mac[6]; + W5100.readSnDHAR(_socket, mac); + printf("Sn_DHAR: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("Sn_RX_RSR:%5d, Sn_RX_RD:%5d, Sn_RX_WR:%5d\n", + W5100.readSnRX_RSR(_socket), W5100.readSnRX_RD(_socket), W5100.readSnRX_WR(_socket)); + printf("Sn_TX_FSR:%5d, Sn_TX_RD:%5d, Sn_TX_WR:%5d\n", + W5100.readSnTX_FSR(_socket), W5100.readSnTX_RD(_socket), W5100.readSnTX_WR(_socket)); + } + wait_ms(200); +#endif //DEBUG + if (_socket != (-1)) { + if (W5100.getRXReceivedSize(_socket) > 0) { + queueEvent(NETUDPSOCKET_READABLE); + } + } + return NETUDPSOCKET_OK; +} + +void MyNetUdpSocket::cleanUp() //Flush input buffer +{ + PRINT_FUNC(); + if (_socket == (-1)) { + return; + } + while(W5100.getRXReceivedSize(_socket) > 0) { + uint8_t temp[1]; + W5100.recv_data_processing(_socket, temp, 1); + W5100.execCmdSn(_socket, Sock_RECV); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyNetUdpSocket.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,20 @@ +// MyNetUdpSocket.h 2012/4/16 +#ifndef MYNETUDPSOCKET_H +#define MYNETUDPSOCKET_H +#include "if/net/netudpsocket.h" + +class MyNetUdpSocket: public NetUdpSocket { +public: + MyNetUdpSocket(int socket = (-1)); + virtual ~MyNetUdpSocket(); + virtual NetUdpSocketErr bind(const Host& me); + virtual int /*if < 0 : NetUdpSocketErr*/ sendto(const char* buf, int len, Host* pHost); + virtual int /*if < 0 : NetUdpSocketErr*/ recvfrom(char* buf, int len, Host* pHost); + virtual NetUdpSocketErr close(); + virtual NetUdpSocketErr poll(); +protected: + int _socket; +private: + void cleanUp(); //Flush input buffer +}; +#endif //MYNETUDPSOCKET_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/W5200NetIf.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,88 @@ +// W5200NetIf.cpp 2012/4/23 +#include "W5200NetIf.h" +#include "DHCPClient.h" +#include "w5100.h" + +extern SPI* pSPI; // w5100.cpp +extern DigitalOut* pCS; // w5100.cpp + +W5200NetIf:: W5200NetIf():MyNetIf(), m_netmask(255,255,255,255), m_gateway(), m_hostname(NULL) { + m_hostname = NULL; + m_useDhcp = true; +} + +W5200NetIf::W5200NetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) :MyNetIf(), m_hostname(NULL) { + m_hostname = NULL; + m_ip = ip; + m_netmask = netmask; + m_gateway = gateway; + m_dns = dns; + m_useDhcp = false; +} + +W5200Err W5200NetIf::IPrenew(int timeout_ms) { + if (pSPI == NULL || pCS == NULL) { + return W5200_SETUP_ERR; + } + printf("DHCP Started, waiting for IP...\n"); + DHCPClient dhcp; + int err = dhcp.setup(timeout_ms); + if (err == (-1)) { + printf("Timeout.\n"); + return W5200_TIMEOUT; + } + printf("Connected, IP: %d.%d.%d.%d\n", dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]); + m_ip = IpAddr(dhcp.yiaddr[0], dhcp.yiaddr[1], dhcp.yiaddr[2], dhcp.yiaddr[3]); + m_netmask = IpAddr(dhcp.netmask[0],dhcp.netmask[1],dhcp.netmask[2],dhcp.netmask[3]); + m_gateway = IpAddr(dhcp.gateway[0],dhcp.gateway[1],dhcp.gateway[2],dhcp.gateway[3]); + uint8_t t[4]; + t[0] = m_ip[0]; + t[1] = m_ip[1]; + t[2] = m_ip[2]; + t[3] = m_ip[3]; + W5100.writeSIPR(t); + t[0] = m_netmask[0]; + t[1] = m_netmask[1]; + t[2] = m_netmask[2]; + t[3] = m_netmask[3]; + W5100.writeSUBR(t); + t[0] = m_gateway[0]; + t[1] = m_gateway[1]; + t[2] = m_gateway[2]; + t[3] = m_gateway[3]; + W5100.writeGAR(t); + m_dns = IpAddr(dhcp.dnsaddr[0],dhcp.dnsaddr[1],dhcp.dnsaddr[2],dhcp.dnsaddr[3]); + return W5200_OK; +} + +W5200Err W5200NetIf::IPrelease(int timeout_ms) { + return W5200_OK; +} + +W5200Err W5200NetIf::setup(int timeout_ms) { + if (pSPI == NULL || pCS == NULL) { + return W5200_SETUP_ERR; + } + MyNetIf::init(); + uint8_t mac[6] = {0x00,0x00,0x5e,0x00,0x01,0x01}; + W5100.setMACAddress(mac); + printf("HW Addr is : %02x:%02x:%02x:%02x:%02x:%02x.\n", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); + if(! m_useDhcp) { + return W5200_OK; + } + return IPrenew(timeout_ms); +} + +SPI* W5200NetIf::attachSPI(SPI* spi) { + if (spi) { + pSPI = spi; + } + return pSPI; +} + +DigitalOut* W5200NetIf::attachCS(DigitalOut* cs) { + if (cs) { + pCS = cs; + } + return pCS; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/W5200NetIf.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,46 @@ +// W5200NetIf.h 2012/4/19 +/** \file +W5200 network interface header file +*/ +#ifndef W5200_NETIF_H +#define W5200_NETIF_H +#include "MyNetIf.h" + +///W5200 network interface return codes +enum W5200Err +{ + __W5200_MIN = -0xFFFF, + W5200_TIMEOUT, ///<Timeout during setup + W5200_SETUP_ERR, + W5200_OK = 0 ///<Success +}; + +///W5200 network interface +class W5200NetIf : public MyNetIf { +public: + ///Instantiates the Interface and register it against the stack, DHCP will be used + W5200NetIf(); //W/ DHCP + ///Instantiates the Interface and register it against the stack, DHCP will not be used + /** + IpAddr is a container class that can be constructed with either 4 bytes or no parameters for a null IP address. + */ + W5200NetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns); //W/o DHCP + W5200Err IPrenew(int timeout_ms = 15000); + W5200Err IPrelease(int timeout_ms = 15000); + ///Brings the interface up + /** + Uses DHCP if necessary + @param timeout_ms : You can set the timeout parameter in milliseconds, if not it defaults to 15s + @return : W5200_OK on success or W5200_TIMEOUT on timeout + */ + W5200Err setup(int timeout_ms = 15000); + SPI* attachSPI(SPI* spi); + DigitalOut* attachCS(DigitalOut* cs); + IpAddr m_dns; +private: + bool m_useDhcp; + IpAddr m_netmask; + IpAddr m_gateway; + const char* m_hostname; +}; +#endif //W5200_NETIF_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WIZ820ioNetIf.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,49 @@ +// WIZ820ioNetIf.cpp 2012/4/22 +#include "WIZ820ioNetIf.h" +#include "w5100.h" + +DigitalOut* pRESET = NULL; + +void hardware_reset() { + if (!pRESET) { + pRESET = new DigitalOut(p15); + } + if (pRESET) { + pRESET->write(1); + pRESET->write(0); + wait_us(2); + pRESET->write(1); + wait_ms(150); + } +} + +bool wait_linkup(int timeout = 5000) { + Timer link_t; + link_t.start(); + while(link_t.read_ms() < timeout) { + if (0x20 & W5100.readPHYSTATUS()) { + return true; + } + wait_ms(50); + } + return false; +} + +void WIZ820ioNetIf::reset(PinName _reset) { + pRESET = new DigitalOut(_reset); +} + +int WIZ820ioNetIf::setup(int timeout_ms) { + hardware_reset(); + if (!attachSPI(NULL)) { + SPI* spi = new SPI(p11, p12, p13); // mosi, miso, sclk + attachSPI(spi); + } + if (!attachCS(NULL)) { + DigitalOut* cs = new DigitalOut(p14); + attachCS(cs); + } + W5100.init(); + wait_linkup(); + return W5200NetIf::setup(timeout_ms); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WIZ820ioNetIf.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,22 @@ +// WIZ820ioNetIf.h 2012/4/23 + +/** \file +WIZ820io network interface header file +*/ +#ifndef WIZ820IO_NETIF_H +#define WIZ820IO_NETIF_H +#include "W5200NetIf.h" + +///WIZ820io network interface +class WIZ820ioNetIf : public W5200NetIf { +public: + void reset(PinName _reset); + ///Brings the interface up + /** + Uses DHCP if necessary + @param timeout_ms : You can set the timeout parameter in milliseconds, if not it defaults to 15s + @return : 0 on success or -1 on timeout + */ + int setup(int timeout_ms = 15000); +}; +#endif //WIZ820IO_NETIF_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dnsname.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,51 @@ +// dnsname.h 2012/4/13 +#ifndef DNSNAME_H +#define DNSNAME_H +class dnsname { +public: + uint8_t *buf; + string str; + dnsname(uint8_t *s) { + buf = s; + } + int decode(int pos) { + while(1) { + int len = buf[pos++]; + if (len == 0x00) { + break; + } + if ((len&0xc0) == 0xc0) { //compress + int offset = (len&0x3f)<<8|buf[pos]; + decode(offset); + return pos+1; + } + if (!str.empty()) { + str.append("."); + } + str.append((const char*)(buf+pos), len); + pos += len; + } + return pos; + } + + int encode(int pos, char* s) { + while(*s) { + char *f = strchr(s, '.'); + if (f == NULL) { + int len = strlen(s); + buf[pos++] = len; + memcpy(buf+pos, s, len); + pos += len; + break; + } + int len = f - s; + buf[pos++] = len; + memcpy(buf+pos, s, len); + s = f+1; + pos += len; + } + buf[pos++] = 0x00; + return pos; + } +}; +#endif //DNSNAME_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/w5100.cpp Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include <stdio.h> +#include <string.h> +#include "mbed.h" +#include "w5100.h" +#ifndef MBED +#include <avr/interrupt.h> +#endif //MBED + +// W5100 controller instance +W5100Class W5100; + +#define TX_RX_MAX_BUF_SIZE 2048 +#define TX_BUF 0x1100 +#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) + +#ifdef W5200 +#define TXBUF_BASE 0x8000 +#define RXBUF_BASE 0xC000 +#else +#define TXBUF_BASE 0x4000 +#define RXBUF_BASE 0x6000 +#endif + +#ifdef MBED + +SPI* pSPI = NULL; +DigitalOut* pCS = NULL; + +inline void delay(int n) { wait_ms(n); } +inline static void initSS(){ pCS->write(1); } +inline static void setSS() { pCS->write(0); } +inline static void resetSS() { pCS->write(1); } + +#endif //MBED + +void W5100Class::init(void) +{ + if (!pSPI) { + pSPI = new SPI(p11, p12, p13); // mosi, miso, sclk + } + if (!pCS) { + pCS = new DigitalOut(p14); + } + initSS(); + writeMR(1<<RST); + +#ifdef W5200 + for (int i=0; i<MAX_SOCK_NUM; i++) { + write((0x4000 + i * 0x100 + 0x001F), 2); + write((0x4000 + i * 0x100 + 0x001E), 2); + } +#else + writeTMSR(0x55); + writeRMSR(0x55); +#endif + + for (int i=0; i<MAX_SOCK_NUM; i++) { + SBASE[i] = TXBUF_BASE + SSIZE * i; + RBASE[i] = RXBUF_BASE + RSIZE * i; + } +} + +uint16_t W5100Class::getTXFreeSize(SOCKET s) +{ + uint16_t val=0, val1=0; + do { + val1 = readSnTX_FSR(s); + if (val1 != 0) + val = readSnTX_FSR(s); + } + while (val != val1); + return val; +} + +uint16_t W5100Class::getRXReceivedSize(SOCKET s) +{ + uint16_t val=0,val1=0; + do { + val1 = readSnRX_RSR(s); + if (val1 != 0) + val = readSnRX_RSR(s); + } + while (val != val1); + return val; +} + + +void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len) +{ + // This is same as having no offset in a call to send_data_processing_offset + send_data_processing_offset(s, 0, data, len); +} + +void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len) +{ + uint16_t ptr = readSnTX_WR(s); + ptr += data_offset; + uint16_t offset = ptr & SMASK; + uint16_t dstAddr = offset + SBASE[s]; + + if (offset + len > SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, data, size); + write(SBASE[s], data + size, len - size); + } + else { + write(dstAddr, data, len); + } + + ptr += len; + writeSnTX_WR(s, ptr); +} + + +void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +{ + uint16_t ptr; + ptr = readSnRX_RD(s); + read_data(s, (uint8_t *)ptr, data, len); + if (!peek) + { + ptr += len; + writeSnRX_RD(s, ptr); + } +} + +void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len) +{ + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + +#ifdef MBED + src_mask = (int)src & RMASK; +#else + src_mask = (uint16_t)src & RMASK; +#endif //MBED + src_ptr = RBASE[s] + src_mask; + + if( (src_mask + len) > RSIZE ) + { + size = RSIZE - src_mask; + read(src_ptr, (uint8_t *)dst, size); + dst += size; + read(RBASE[s], (uint8_t *) dst, len - size); + } + else + read(src_ptr, (uint8_t *) dst, len); +} + + +uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) +{ + setSS(); + +#ifdef W5200 + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + pSPI->write(0x80); + pSPI->write(0x01); +#else + pSPI->write(0xF0); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); +#endif + pSPI->write(_data); + resetSS(); + return 1; +} + +uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +{ + +#ifdef W5200 + setSS(); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + pSPI->write((0x80 | ((_len & 0x7F00) >> 8))); + pSPI->write(_len & 0x00FF); + + for (uint16_t i=0; i<_len; i++) + { + pSPI->write(_buf[i]); + + } + resetSS(); +#else + + for (uint16_t i=0; i<_len; i++) + { + setSS(); + pSPI->write(0xF0); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + _addr++; + pSPI->write(_buf[i]); + resetSS(); + } +#endif + + return _len; +} + +uint8_t W5100Class::read(uint16_t _addr) +{ + setSS(); +#ifdef W5200 + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + pSPI->write(0x00); + pSPI->write(0x01); +#else + pSPI->write(0x0F); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); +#endif + + uint8_t _data = pSPI->write(0); + resetSS(); + return _data; +} + +uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +{ +#ifdef W5200 + setSS(); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + pSPI->write((0x00 | ((_len & 0x7F00) >> 8))); + pSPI->write(_len & 0x00FF); + + for (uint16_t i=0; i<_len; i++) + { + _buf[i] = pSPI->write(0); + + } + resetSS(); + +#else + + for (uint16_t i=0; i<_len; i++) + { + setSS(); + pSPI->write(0x0F); + pSPI->write(_addr >> 8); + pSPI->write(_addr & 0xFF); + _addr++; + _buf[i] = pSPI->write(0); + resetSS(); + } +#endif + return _len; +} + +void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/w5100.h Fri Mar 22 11:51:24 2013 +0000 @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st> + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED +#define MBED +#ifdef MBED +#include "mbed.h" +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +#else //MBED +#include <avr/pgmspace.h> +#include <SPI.h> +#endif //MBED +#define W5200 + +#ifdef W5200 +#define MAX_SOCK_NUM 8 +#else +#define MAX_SOCK_NUM 4 +#endif + + +typedef uint8_t SOCKET; + +#ifndef W5200 +#define IDM_OR 0x8000 +#define IDM_AR0 0x8001 +#define IDM_AR1 0x8002 +#define IDM_DR 0x8003 +#endif + +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5100Class { +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint8_t * src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ +// FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5100 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _data); + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr); + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, _data >> 8); \ + write(address+1, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address); \ + res = (res << 8) + read(address + 1); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + + #ifndef W5200 + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size + #endif + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + + __GP_REGISTER8 (VERSIONR,0x001f); // Chip version + + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + #ifndef W5200 + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode +#endif + __GP_REGISTER8 (PHYSTATUS,0x0035); // PHY Status + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5100 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + +#ifdef W5200 + static const uint16_t CH_BASE = 0x4000; +#else + static const uint16_t CH_BASE = 0x0400; +#endif + + static const uint16_t CH_SIZE = 0x0100; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + res = (res << 8) + readSn(_s, address + 1); \ + return res; \ + } +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + +#ifdef W5200 + static const int SOCKETS = 8; +#else + static const int SOCKETS = 4; +#endif + + static const uint16_t SMASK = 0x07FF; // Tx buffer MASK + static const uint16_t RMASK = 0x07FF; // Rx buffer MASK +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + uint16_t SBASE[SOCKETS]; // Tx buffer base address + uint16_t RBASE[SOCKETS]; // Rx buffer base address + +private: +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; +#elif defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; +#else +#ifndef MBED + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; +#endif //MBED +#endif + +}; + +extern W5100Class W5100; + +uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { + return read(CH_BASE + _s * CH_SIZE + _addr); +} + +uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + return write(CH_BASE + _s * CH_SIZE + _addr, _data); +} + +uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +void W5100Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5100Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5100Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5100Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5100Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5100Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5100Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5100Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5100Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5100Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} + +#endif