W5200(WIZ820io) network interface

Committer:
va009039
Date:
Thu Apr 19 11:14:43 2012 +0000
Revision:
2:a8df39b4f3aa
Parent:
1:803123933c5a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:61831b843b44 1 /*
va009039 0:61831b843b44 2 * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
va009039 0:61831b843b44 3 *
va009039 0:61831b843b44 4 * This file is free software; you can redistribute it and/or modify
va009039 0:61831b843b44 5 * it under the terms of either the GNU General Public License version 2
va009039 0:61831b843b44 6 * or the GNU Lesser General Public License version 2.1, both as
va009039 0:61831b843b44 7 * published by the Free Software Foundation.
va009039 0:61831b843b44 8 */
va009039 0:61831b843b44 9
va009039 0:61831b843b44 10 #include <stdio.h>
va009039 0:61831b843b44 11 #include <string.h>
va009039 1:803123933c5a 12 #include "mbed.h"
va009039 0:61831b843b44 13 #include "w5100.h"
va009039 0:61831b843b44 14 #ifndef MBED
va009039 0:61831b843b44 15 #include <avr/interrupt.h>
va009039 0:61831b843b44 16 #endif //MBED
va009039 0:61831b843b44 17
va009039 0:61831b843b44 18 // W5100 controller instance
va009039 0:61831b843b44 19 W5100Class W5100;
va009039 0:61831b843b44 20
va009039 0:61831b843b44 21 #define TX_RX_MAX_BUF_SIZE 2048
va009039 0:61831b843b44 22 #define TX_BUF 0x1100
va009039 0:61831b843b44 23 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE)
va009039 0:61831b843b44 24
va009039 0:61831b843b44 25 #ifdef W5200
va009039 0:61831b843b44 26 #define TXBUF_BASE 0x8000
va009039 0:61831b843b44 27 #define RXBUF_BASE 0xC000
va009039 0:61831b843b44 28 #else
va009039 0:61831b843b44 29 #define TXBUF_BASE 0x4000
va009039 0:61831b843b44 30 #define RXBUF_BASE 0x6000
va009039 0:61831b843b44 31 #endif
va009039 0:61831b843b44 32
va009039 0:61831b843b44 33 #ifdef MBED
va009039 1:803123933c5a 34
va009039 1:803123933c5a 35 SPI* pSPI = NULL;
va009039 1:803123933c5a 36 DigitalOut* pCS = NULL;
va009039 0:61831b843b44 37
va009039 1:803123933c5a 38 inline void delay(int n) { wait_ms(n); }
va009039 1:803123933c5a 39 inline static void initSS(){ pCS->write(1); }
va009039 1:803123933c5a 40 inline static void setSS() { pCS->write(0); }
va009039 1:803123933c5a 41 inline static void resetSS() { pCS->write(1); }
va009039 1:803123933c5a 42
va009039 0:61831b843b44 43 #endif //MBED
va009039 0:61831b843b44 44
va009039 0:61831b843b44 45 void W5100Class::init(void)
va009039 0:61831b843b44 46 {
va009039 1:803123933c5a 47 if (!pSPI) {
va009039 1:803123933c5a 48 pSPI = new SPI(p11, p12, p13); // mosi, miso, sclk
va009039 1:803123933c5a 49 }
va009039 1:803123933c5a 50 if (!pCS) {
va009039 1:803123933c5a 51 pCS = new DigitalOut(p14);
va009039 1:803123933c5a 52 }
va009039 0:61831b843b44 53 initSS();
va009039 0:61831b843b44 54 writeMR(1<<RST);
va009039 0:61831b843b44 55
va009039 0:61831b843b44 56 #ifdef W5200
va009039 0:61831b843b44 57 for (int i=0; i<MAX_SOCK_NUM; i++) {
va009039 0:61831b843b44 58 write((0x4000 + i * 0x100 + 0x001F), 2);
va009039 0:61831b843b44 59 write((0x4000 + i * 0x100 + 0x001E), 2);
va009039 0:61831b843b44 60 }
va009039 0:61831b843b44 61 #else
va009039 0:61831b843b44 62 writeTMSR(0x55);
va009039 0:61831b843b44 63 writeRMSR(0x55);
va009039 0:61831b843b44 64 #endif
va009039 0:61831b843b44 65
va009039 0:61831b843b44 66 for (int i=0; i<MAX_SOCK_NUM; i++) {
va009039 0:61831b843b44 67 SBASE[i] = TXBUF_BASE + SSIZE * i;
va009039 0:61831b843b44 68 RBASE[i] = RXBUF_BASE + RSIZE * i;
va009039 0:61831b843b44 69 }
va009039 0:61831b843b44 70 }
va009039 0:61831b843b44 71
va009039 0:61831b843b44 72 uint16_t W5100Class::getTXFreeSize(SOCKET s)
va009039 0:61831b843b44 73 {
va009039 0:61831b843b44 74 uint16_t val=0, val1=0;
va009039 0:61831b843b44 75 do {
va009039 0:61831b843b44 76 val1 = readSnTX_FSR(s);
va009039 0:61831b843b44 77 if (val1 != 0)
va009039 0:61831b843b44 78 val = readSnTX_FSR(s);
va009039 0:61831b843b44 79 }
va009039 0:61831b843b44 80 while (val != val1);
va009039 0:61831b843b44 81 return val;
va009039 0:61831b843b44 82 }
va009039 0:61831b843b44 83
va009039 0:61831b843b44 84 uint16_t W5100Class::getRXReceivedSize(SOCKET s)
va009039 0:61831b843b44 85 {
va009039 0:61831b843b44 86 uint16_t val=0,val1=0;
va009039 0:61831b843b44 87 do {
va009039 0:61831b843b44 88 val1 = readSnRX_RSR(s);
va009039 0:61831b843b44 89 if (val1 != 0)
va009039 0:61831b843b44 90 val = readSnRX_RSR(s);
va009039 0:61831b843b44 91 }
va009039 0:61831b843b44 92 while (val != val1);
va009039 0:61831b843b44 93 return val;
va009039 0:61831b843b44 94 }
va009039 0:61831b843b44 95
va009039 0:61831b843b44 96
va009039 0:61831b843b44 97 void W5100Class::send_data_processing(SOCKET s, const uint8_t *data, uint16_t len)
va009039 0:61831b843b44 98 {
va009039 0:61831b843b44 99 // This is same as having no offset in a call to send_data_processing_offset
va009039 0:61831b843b44 100 send_data_processing_offset(s, 0, data, len);
va009039 0:61831b843b44 101 }
va009039 0:61831b843b44 102
va009039 0:61831b843b44 103 void W5100Class::send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len)
va009039 0:61831b843b44 104 {
va009039 0:61831b843b44 105 uint16_t ptr = readSnTX_WR(s);
va009039 0:61831b843b44 106 ptr += data_offset;
va009039 0:61831b843b44 107 uint16_t offset = ptr & SMASK;
va009039 0:61831b843b44 108 uint16_t dstAddr = offset + SBASE[s];
va009039 0:61831b843b44 109
va009039 0:61831b843b44 110 if (offset + len > SSIZE)
va009039 0:61831b843b44 111 {
va009039 0:61831b843b44 112 // Wrap around circular buffer
va009039 0:61831b843b44 113 uint16_t size = SSIZE - offset;
va009039 0:61831b843b44 114 write(dstAddr, data, size);
va009039 0:61831b843b44 115 write(SBASE[s], data + size, len - size);
va009039 0:61831b843b44 116 }
va009039 0:61831b843b44 117 else {
va009039 0:61831b843b44 118 write(dstAddr, data, len);
va009039 0:61831b843b44 119 }
va009039 0:61831b843b44 120
va009039 0:61831b843b44 121 ptr += len;
va009039 0:61831b843b44 122 writeSnTX_WR(s, ptr);
va009039 0:61831b843b44 123 }
va009039 0:61831b843b44 124
va009039 0:61831b843b44 125
va009039 0:61831b843b44 126 void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek)
va009039 0:61831b843b44 127 {
va009039 0:61831b843b44 128 uint16_t ptr;
va009039 0:61831b843b44 129 ptr = readSnRX_RD(s);
va009039 0:61831b843b44 130 read_data(s, (uint8_t *)ptr, data, len);
va009039 0:61831b843b44 131 if (!peek)
va009039 0:61831b843b44 132 {
va009039 0:61831b843b44 133 ptr += len;
va009039 0:61831b843b44 134 writeSnRX_RD(s, ptr);
va009039 0:61831b843b44 135 }
va009039 0:61831b843b44 136 }
va009039 0:61831b843b44 137
va009039 0:61831b843b44 138 void W5100Class::read_data(SOCKET s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
va009039 0:61831b843b44 139 {
va009039 0:61831b843b44 140 uint16_t size;
va009039 0:61831b843b44 141 uint16_t src_mask;
va009039 0:61831b843b44 142 uint16_t src_ptr;
va009039 0:61831b843b44 143
va009039 0:61831b843b44 144 #ifdef MBED
va009039 0:61831b843b44 145 src_mask = (int)src & RMASK;
va009039 0:61831b843b44 146 #else
va009039 0:61831b843b44 147 src_mask = (uint16_t)src & RMASK;
va009039 0:61831b843b44 148 #endif //MBED
va009039 0:61831b843b44 149 src_ptr = RBASE[s] + src_mask;
va009039 0:61831b843b44 150
va009039 0:61831b843b44 151 if( (src_mask + len) > RSIZE )
va009039 0:61831b843b44 152 {
va009039 0:61831b843b44 153 size = RSIZE - src_mask;
va009039 0:61831b843b44 154 read(src_ptr, (uint8_t *)dst, size);
va009039 0:61831b843b44 155 dst += size;
va009039 0:61831b843b44 156 read(RBASE[s], (uint8_t *) dst, len - size);
va009039 0:61831b843b44 157 }
va009039 0:61831b843b44 158 else
va009039 0:61831b843b44 159 read(src_ptr, (uint8_t *) dst, len);
va009039 0:61831b843b44 160 }
va009039 0:61831b843b44 161
va009039 0:61831b843b44 162
va009039 0:61831b843b44 163 uint8_t W5100Class::write(uint16_t _addr, uint8_t _data)
va009039 0:61831b843b44 164 {
va009039 0:61831b843b44 165 setSS();
va009039 0:61831b843b44 166
va009039 0:61831b843b44 167 #ifdef W5200
va009039 1:803123933c5a 168 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 169 pSPI->write(_addr & 0xFF);
va009039 1:803123933c5a 170 pSPI->write(0x80);
va009039 1:803123933c5a 171 pSPI->write(0x01);
va009039 0:61831b843b44 172 #else
va009039 1:803123933c5a 173 pSPI->write(0xF0);
va009039 1:803123933c5a 174 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 175 pSPI->write(_addr & 0xFF);
va009039 0:61831b843b44 176 #endif
va009039 1:803123933c5a 177 pSPI->write(_data);
va009039 0:61831b843b44 178 resetSS();
va009039 0:61831b843b44 179 return 1;
va009039 0:61831b843b44 180 }
va009039 0:61831b843b44 181
va009039 0:61831b843b44 182 uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len)
va009039 0:61831b843b44 183 {
va009039 0:61831b843b44 184
va009039 0:61831b843b44 185 #ifdef W5200
va009039 0:61831b843b44 186 setSS();
va009039 1:803123933c5a 187 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 188 pSPI->write(_addr & 0xFF);
va009039 1:803123933c5a 189 pSPI->write((0x80 | ((_len & 0x7F00) >> 8)));
va009039 1:803123933c5a 190 pSPI->write(_len & 0x00FF);
va009039 0:61831b843b44 191
va009039 0:61831b843b44 192 for (uint16_t i=0; i<_len; i++)
va009039 0:61831b843b44 193 {
va009039 1:803123933c5a 194 pSPI->write(_buf[i]);
va009039 0:61831b843b44 195
va009039 0:61831b843b44 196 }
va009039 0:61831b843b44 197 resetSS();
va009039 0:61831b843b44 198 #else
va009039 0:61831b843b44 199
va009039 0:61831b843b44 200 for (uint16_t i=0; i<_len; i++)
va009039 0:61831b843b44 201 {
va009039 0:61831b843b44 202 setSS();
va009039 1:803123933c5a 203 pSPI->write(0xF0);
va009039 1:803123933c5a 204 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 205 pSPI->write(_addr & 0xFF);
va009039 0:61831b843b44 206 _addr++;
va009039 1:803123933c5a 207 pSPI->write(_buf[i]);
va009039 0:61831b843b44 208 resetSS();
va009039 0:61831b843b44 209 }
va009039 0:61831b843b44 210 #endif
va009039 0:61831b843b44 211
va009039 0:61831b843b44 212 return _len;
va009039 0:61831b843b44 213 }
va009039 0:61831b843b44 214
va009039 0:61831b843b44 215 uint8_t W5100Class::read(uint16_t _addr)
va009039 0:61831b843b44 216 {
va009039 0:61831b843b44 217 setSS();
va009039 0:61831b843b44 218 #ifdef W5200
va009039 1:803123933c5a 219 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 220 pSPI->write(_addr & 0xFF);
va009039 1:803123933c5a 221 pSPI->write(0x00);
va009039 1:803123933c5a 222 pSPI->write(0x01);
va009039 0:61831b843b44 223 #else
va009039 1:803123933c5a 224 pSPI->write(0x0F);
va009039 1:803123933c5a 225 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 226 pSPI->write(_addr & 0xFF);
va009039 0:61831b843b44 227 #endif
va009039 0:61831b843b44 228
va009039 1:803123933c5a 229 uint8_t _data = pSPI->write(0);
va009039 0:61831b843b44 230 resetSS();
va009039 0:61831b843b44 231 return _data;
va009039 0:61831b843b44 232 }
va009039 0:61831b843b44 233
va009039 0:61831b843b44 234 uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
va009039 0:61831b843b44 235 {
va009039 0:61831b843b44 236 #ifdef W5200
va009039 0:61831b843b44 237 setSS();
va009039 1:803123933c5a 238 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 239 pSPI->write(_addr & 0xFF);
va009039 1:803123933c5a 240 pSPI->write((0x00 | ((_len & 0x7F00) >> 8)));
va009039 1:803123933c5a 241 pSPI->write(_len & 0x00FF);
va009039 0:61831b843b44 242
va009039 0:61831b843b44 243 for (uint16_t i=0; i<_len; i++)
va009039 0:61831b843b44 244 {
va009039 1:803123933c5a 245 _buf[i] = pSPI->write(0);
va009039 0:61831b843b44 246
va009039 0:61831b843b44 247 }
va009039 0:61831b843b44 248 resetSS();
va009039 0:61831b843b44 249
va009039 0:61831b843b44 250 #else
va009039 0:61831b843b44 251
va009039 0:61831b843b44 252 for (uint16_t i=0; i<_len; i++)
va009039 0:61831b843b44 253 {
va009039 0:61831b843b44 254 setSS();
va009039 1:803123933c5a 255 pSPI->write(0x0F);
va009039 1:803123933c5a 256 pSPI->write(_addr >> 8);
va009039 1:803123933c5a 257 pSPI->write(_addr & 0xFF);
va009039 0:61831b843b44 258 _addr++;
va009039 1:803123933c5a 259 _buf[i] = pSPI->write(0);
va009039 0:61831b843b44 260 resetSS();
va009039 0:61831b843b44 261 }
va009039 0:61831b843b44 262 #endif
va009039 0:61831b843b44 263 return _len;
va009039 0:61831b843b44 264 }
va009039 0:61831b843b44 265
va009039 0:61831b843b44 266 void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) {
va009039 0:61831b843b44 267 // Send command to socket
va009039 0:61831b843b44 268 writeSnCR(s, _cmd);
va009039 0:61831b843b44 269 // Wait for command to complete
va009039 0:61831b843b44 270 while (readSnCR(s))
va009039 0:61831b843b44 271 ;
va009039 0:61831b843b44 272 }