Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
w5100.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2006 Pascal Brisset, Antoine Drouin
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22 
23 #include "mcu_periph/sys_time.h"
25 #include "mcu_periph/spi.h"
26 
27 #define TXBUF_BASE 0x4000
28 #define RXBUF_BASE 0x6000
29 #define SOCKETS 4
30 
31 #define CMD_SOCKET 1
32 #define TELEM_SOCKET 0
33 
34 #define SOCK_OPEN 0x01
35 #define SOCK_CLOSE 0x10
36 #define SOCK_SEND 0x20
37 #define SOCK_RECV 0x40
38 #define SNMR_UDP 0x02
39 #define SNMR_MULTI 0x80
40 #define SNIR_SEND_OK 0x10
41 #define SNIR_TIMEOUT 0x08
42 #define CH_BASE 0x0400
43 #define CH_SIZE 0x0100
44 #define SMASK 0x07FF // Tx buffer MASK
45 #define RMASK 0x07FF // Tx buffer MASK
46 
47 #define REG_MR 0x0000
48 #define REG_RX_MEM 0x001A
49 #define REG_TX_MEM 0x001B
50 
51 #define REG_GAR 0x0001
52 #define REG_SUBR 0x0005
53 #define REG_SHAR 0x0009
54 #define REG_SIPR 0x000F
55 
56 #define SOCK_MR 0x0000
57 #define SOCK_CR 0x0001
58 #define SOCK_IR 0x0002
59 #define SOCK_PORT 0x0004
60 #define SOCK_DHAR 0x0006
61 #define SOCK_DIPR 0x000C
62 #define SOCK_DPORT 0x0010
63 #define SOCK_TX_WR 0x0024
64 #define SOCK_RSR 0x0026
65 #define SOCK_RXRD 0x0028
66 
67 #ifndef W5100_SPI_DEV
68 #define W5100_SPI_DEV spi1
69 #endif
70 
71 #ifndef W5100_SLAVE_IDX
72 #define W5100_SLAVE_IDX SPI_SLAVE1
73 #endif
74 
78 
79 // the media access control (ethernet hardware) address for the shield.
80 static uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
81 
82 //the IP address for the shield:
83 static uint8_t ip[] = { W5100_IP };
84 static uint8_t dest[] = { W5100_MULTICAST_IP };
85 static uint8_t subnet[] = { W5100_SUBNET };
86 static uint16_t dport = W5100_MULTICAST_PORT;
87 
88 static const uint8_t RST = 7; // Reset BIT
89 
90 uint16_t SBASE[SOCKETS]; // Tx buffer base address
91 uint16_t RBASE[SOCKETS]; // Rx buffer base address
92 static const uint16_t SSIZE = 2048; // Max Tx buffer size
93 static const uint16_t RSIZE = 2048; // Max Rx buffer size
94 
97 
98 static void w5100_close_socket( uint8_t _s );
99 static void configure_socket( uint8_t _s, uint8_t _flag, uint16_t _lport, uint16_t _dport, uint8_t *_dest );
100 static void w5100_read_data( uint8_t s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len );
101 static uint16_t w5100_read(uint16_t _addr, uint8_t *_buf, uint16_t _len);
102 
103 static inline void w5100_set(uint16_t _reg, uint8_t _val)
104 {
105  w5100_spi.output_buf[0] = 0xF0;
106  w5100_spi.output_buf[1] = _reg >> 8;
107  w5100_spi.output_buf[2] = _reg & 0xFF;
108  w5100_spi.output_buf[3] = _val;
109 
111 
112  // FIXME: no busy waiting! if really needed add a timeout!!!!
113  while(w5100_spi.status != SPITransSuccess);
114 }
115 
116 static inline uint8_t w5100_get(uint16_t _reg)
117 {
118  w5100_spi.output_buf[0] = 0x0F;
119  w5100_spi.output_buf[1] = _reg >> 8;
120  w5100_spi.output_buf[2] = _reg & 0xFF;
121 
123 
124  // FIXME: no busy waiting! if really needed add a timeout!!!!
125  while(w5100_spi.status != SPITransSuccess);
126 
127  return w5100_spi.input_buf[3];
128 }
129 
130 static inline void w5100_set_buffer(uint16_t _reg, volatile uint8_t *_buf, uint16_t _len)
131 {
132  for (int i=0; i<_len; i++) {
133  w5100_set( _reg, _buf[ i ] );
134  _reg++;
135  }
136 }
137 
138 static inline void w5100_sock_set(uint8_t _sock, uint16_t _reg, uint8_t _val) {
139  w5100_set( CH_BASE + _sock * CH_SIZE + _reg, _val );
140 }
141 
142 static inline uint8_t w5100_sock_get(uint8_t _sock, uint16_t _reg) {
143  return w5100_get( CH_BASE + _sock * CH_SIZE + _reg );
144 }
145 
146 static inline uint16_t w5100_sock_get16( uint8_t _sock, uint16_t _reg) {
147  uint16_t res = w5100_sock_get(_sock, _reg);
148  uint16_t res2 = w5100_sock_get(_sock, _reg + 1);
149  res = res << 8;
150  res2 = res2 & 0xFF;
151  res = res | res2;
152  return res;
153 }
154 
155 void w5100_init( void ) {
156 
157  // configure the SPI bus.
167 
169  chip0.curbuf = 0;
172 
173  // wait one second for proper initialization (chip getting powered up).
174  sys_time_usleep(1000000);
175 
176  // @FIXME: should be no arch dependant code here...
177  // set DRDY pin
178  gpio_set_mode( GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO1 );
179  gpio_clear( GPIOB, GPIO1 );
180  sys_time_usleep(200);
181  gpio_set( GPIOB, GPIO1 );
182 
183  // allow some time for the chip to wake up.
184  sys_time_usleep(20000);
185 
186  // write reset bit into mode register
187  w5100_set( REG_MR, 1<<RST );
188 
189  // allow some time to wake up...
190  sys_time_usleep(20000);
191 
192  // receive memory size
193  w5100_set( REG_RX_MEM, 0x55 );
194 
195  // transmit memory size
196  w5100_set( REG_TX_MEM, 0x55 );
197 
198  // Setting the required socket base addresses for reads and writes to/from sockets
199  for (int i=0; i<SOCKETS; i++) {
200  SBASE[i] = TXBUF_BASE + SSIZE * i;
201  RBASE[i] = RXBUF_BASE + RSIZE * i;
202  }
203 
204  uint8_t gateway[4];
205  gateway[0] = ip[0];
206  gateway[1] = ip[1];
207  gateway[2] = ip[2];
208  gateway[3] = 1;
209 
210  // configure gateway, subnet, mac and ip on "NIC".
211  w5100_set_buffer( REG_GAR, gateway, 4 );
215 
216  // create a socket to send telemetry through.
218 
219  // make dest zero and configure socket to receive data
220  dest[ 0 ] = 0x00;
222 }
223 
224 void w5100_transmit( uint8_t data ) {
225 
227 
228  if (temp == chip0.tx_extract_idx[ chip0.curbuf ]) {
229  // no more room in this transaction.
230  return;
231  }
232 
233  // check if in process of sending data
235  chip0.tx_insert_idx[ chip0.curbuf ] = temp;
236 }
237 
238 void w5100_send() {
239  // Now send off spi transaction.
241  uint8_t curbuf = chip0.curbuf;
242 
243  // switch to other buffer to accept more chars.
244  chip0.curbuf++;
245  if ( chip0.curbuf >= W5100_BUFFER_NUM ) {
246  chip0.curbuf = 0;
247  }
248 
250  uint16_t offset = ptr & SMASK;
251  uint16_t dstAddr = offset + SBASE[ TELEM_SOCKET ];
252 
255 
256  if (offset + len > SSIZE) {
257  // Wrap around circular buffer
258  uint16_t size = SSIZE - offset;
259  w5100_set_buffer( dstAddr, &chip0.tx_buf[curbuf][0], size );
260  w5100_set_buffer( SBASE[ TELEM_SOCKET ], &chip0.tx_buf[curbuf][0] + size, len - size);
261  }
262  else {
263  w5100_set_buffer( dstAddr, &chip0.tx_buf[curbuf][0], len);
264  }
265 
266  // Reset write pointer
267  ptr += len;
268  w5100_sock_set( TELEM_SOCKET, SOCK_TX_WR, ptr >> 8 );
269  w5100_sock_set( TELEM_SOCKET, SOCK_TX_WR+1, ptr & 0xFF );
270 
271  // send
273 
275  while ( complete != 0x00 ) {
276  complete = w5100_sock_get( TELEM_SOCKET, SOCK_CR);
277  }
278 }
279 
281  uint16_t val=0,val1=0;
282 
283  do {
284  val1 = w5100_sock_get16( _s, SOCK_RSR );
285  if (val1 != 0)
286  val = w5100_sock_get16( _s, SOCK_RSR );
287  }
288  while (val != val1);
289  return val;
290 }
291 
292 static void w5100_close_socket( uint8_t _s ) {
293  // send command to close socket
295  // clear interrupt registers
296  w5100_sock_set( _s, SOCK_IR, 0xFF );
297 }
298 
299 static void configure_socket( uint8_t _s, uint8_t _flag, uint16_t _lport, uint16_t _dport, uint8_t *_dest ) {
300  // Configure socket that receives data on 1234
301  w5100_close_socket( _s );
302  // configure type of socket
303  w5100_sock_set( _s, SOCK_MR, SNMR_UDP | _flag );
304  // configure MSB+LSB of local port number
305  w5100_sock_set( _s, SOCK_PORT, _lport >> 8 );
306  w5100_sock_set( _s, SOCK_PORT+1, _lport & 0xFF );
307  if ( _dest[0] != 0x00 ) {
308  // configure destination to send stuff to.
309  w5100_set_buffer( CH_BASE + _s * CH_SIZE + SOCK_DIPR, _dest, 4 );
310  }
311 
312  // this mac corresponds to a mac for multicasting....
313  uint8_t mac_multi[] = { 0x01, 0x00, 0x5E, 0x01, 0x01, 0x0B };
314  w5100_set_buffer( CH_BASE + _s * CH_SIZE + SOCK_DHAR, mac_multi, 6 );
315 
316  // configure destination port
317  w5100_sock_set( _s, SOCK_DPORT, _dport >> 8 );
318  w5100_sock_set( _s, SOCK_DPORT+1, _dport & 0xFF );
319 
320  // send command to open the socket
322 }
323 
325  if ( w5100_rx_size( CMD_SOCKET ) > 0 ) {
326  return TRUE;
327  }
328  return FALSE;
329 }
330 
332  uint8_t head[8];
333  uint16_t data_len=0;
334  uint16_t ptr=0;
335 
336  // Get socket read pointer
338  w5100_read_data( CMD_SOCKET, (uint8_t *)ptr, head, 0x08);
339  ptr += 8;
340  data_len = head[6];
341  data_len = (data_len << 8) + head[7];
342 
343  // read data from buffer.
344  w5100_read_data( CMD_SOCKET, (uint8_t *)ptr, buf, data_len); // data copy.
345  ptr += data_len;
346 
347  // update read pointer
348  w5100_sock_set( CMD_SOCKET, SOCK_RXRD, ptr >> 8);
349  w5100_sock_set( CMD_SOCKET, SOCK_RXRD+1, ptr & 0xFF );
350 
351  // finalize read.
353  return data_len;
354 }
355 
356 static void w5100_read_data( uint8_t s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len ) {
357  uint16_t size;
358  uint16_t src_mask;
359  uint16_t src_ptr;
360 
361  src_mask = (uint16_t)src & RMASK;
362  src_ptr = RBASE[CMD_SOCKET] + src_mask;
363 
364  if( (src_mask + len) > RSIZE ) {
365  size = RSIZE - src_mask;
366  w5100_read(src_ptr, (uint8_t *)dst, size);
367  dst += size;
368  w5100_read(RBASE[CMD_SOCKET], (uint8_t *) dst, len - size);
369  } else {
370  w5100_read(src_ptr, (uint8_t *) dst, len);
371  }
372 }
373 
374 static uint16_t w5100_read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
375 {
376  for (int i=0; i<_len; i++) {
377  _buf[i] = w5100_get( _addr );
378  _addr++;
379  }
380  return _len;
381 }
382 
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
unsigned short uint16_t
Definition: types.h:16
volatile uint16_t tx_extract_idx[W5100_BUFFER_NUM]
Definition: w5100.h:54
uint16_t RBASE[SOCKETS]
Definition: w5100.c:91
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
static void w5100_set(uint16_t _reg, uint8_t _val)
Definition: w5100.c:103
#define W5100_TX_BUFFER_SIZE
Definition: w5100.h:34
static uint8_t dest[]
Definition: w5100.c:84
static void w5100_sock_set(uint8_t _sock, uint16_t _reg, uint8_t _val)
Definition: w5100.c:138
uint8_t input_length
number of data words to read
Definition: spi.h:145
#define W5100_SLAVE_IDX
Definition: w5100.c:72
volatile uint8_t tx_buf[W5100_BUFFER_NUM][W5100_TX_BUFFER_SIZE]
Definition: w5100.h:52
static const uint16_t SSIZE
Definition: w5100.c:92
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
volatile uint8_t work_rx[4]
Definition: w5100.h:56
#define RXBUF_BASE
Definition: w5100.c:28
#define SNMR_MULTI
Definition: w5100.c:39
struct w5100_transport w5100_tp
Definition: w5100.c:95
#define SOCK_MR
Definition: w5100.c:56
uint16_t w5100_rx_size(uint8_t _s)
Definition: w5100.c:280
static void sys_time_usleep(uint32_t us)
Busy wait, in microseconds.
Definition: sys_time_arch.h:73
void w5100_init(void)
Definition: w5100.c:155
#define SOCK_CLOSE
Definition: w5100.c:35
#define SMASK
Definition: w5100.c:44
#define REG_MR
Definition: w5100.c:47
#define W5100_SPI_DEV
Definition: w5100.c:68
#define CH_BASE
Definition: w5100.c:42
#define W5100_RX_BUFFER_SIZE
Definition: w5100.h:33
#define CH_SIZE
Definition: w5100.c:43
uint8_t ck_a
Definition: w5100.c:76
#define SOCK_RECV
Definition: w5100.c:37
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
#define SOCK_RSR
Definition: w5100.c:64
#define W5100_BUFFER_NUM
Definition: w5100.h:35
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
int curbuf
Definition: w5100.h:46
#define SOCK_CR
Definition: w5100.c:57
#define REG_SIPR
Definition: w5100.c:54
#define SOCK_PORT
Definition: w5100.c:59
#define FALSE
Definition: imu_chimu.h:141
uint16_t w5100_receive(uint8_t *buf, uint16_t len)
Definition: w5100.c:331
static uint8_t w5100_sock_get(uint8_t _sock, uint16_t _reg)
Definition: w5100.c:142
enum SPITransactionStatus status
Definition: spi.h:156
Architecture independent SPI (Serial Peripheral Interface) API.
static uint8_t ip[]
Definition: w5100.c:83
#define SOCK_RXRD
Definition: w5100.c:65
#define CMD_SOCKET
Definition: w5100.c:31
#define SOCK_TX_WR
Definition: w5100.c:63
#define SOCK_OPEN
Definition: w5100.c:34
volatile uint16_t tx_insert_idx[W5100_BUFFER_NUM]
Definition: w5100.h:53
Definition: spi.h:84
#define TXBUF_BASE
Definition: w5100.c:27
#define SNMR_UDP
Definition: w5100.c:38
#define REG_RX_MEM
Definition: w5100.c:48
uint8_t ck_b
Definition: w5100.c:76
uint8_t rx_buf[W5100_RX_BUFFER_SIZE]
Definition: w5100.c:77
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
bool_t spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit a spi transaction.
Definition: spi_arch.c:469
Architecture independent timing functions.
#define RMASK
Definition: w5100.c:45
#define SOCK_IR
Definition: w5100.c:58
static const uint16_t RSIZE
Definition: w5100.c:93
uint16_t val[TCOUPLE_NB]
#define REG_SUBR
Definition: w5100.c:52
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
uint8_t output_length
number of data words to write
Definition: spi.h:146
static uint16_t w5100_sock_get16(uint8_t _sock, uint16_t _reg)
Definition: w5100.c:146
#define TELEM_SOCKET
Definition: w5100.c:32
enum W5100Status status
Definition: w5100.h:45
static uint16_t w5100_read(uint16_t _addr, uint8_t *_buf, uint16_t _len)
Definition: w5100.c:374
static void w5100_read_data(uint8_t s, volatile uint8_t *src, volatile uint8_t *dst, uint16_t len)
Definition: w5100.c:356
#define SOCK_DPORT
Definition: w5100.c:62
static void w5100_close_socket(uint8_t _s)
Definition: w5100.c:292
struct w5100_periph chip0
Definition: w5100.c:75
CPOL = 0.
Definition: spi.h:77
int gpio_set(int nr, int val)
Definition: gpio_ardrone.c:32
static uint8_t subnet[]
Definition: w5100.c:85
#define TRUE
Definition: imu_chimu.h:144
uint16_t SBASE[SOCKETS]
Definition: w5100.c:90
static void w5100_set_buffer(uint16_t _reg, volatile uint8_t *_buf, uint16_t _len)
Definition: w5100.c:130
struct adc_buf * buf
Definition: adc_arch.c:578
#define SOCKETS
Definition: w5100.c:29
unsigned char uint8_t
Definition: types.h:14
#define SOCK_SEND
Definition: w5100.c:36
#define SOCK_DIPR
Definition: w5100.c:61
CPHA = 0.
Definition: spi.h:68
slave is selected before transaction and unselected after
Definition: spi.h:57
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
#define REG_SHAR
Definition: w5100.c:53
struct spi_transaction w5100_spi
Definition: w5100.c:96
void w5100_send()
Definition: w5100.c:238
volatile uint8_t work_tx[4]
Definition: w5100.h:55
Definition: spi.h:119
static uint8_t w5100_get(uint16_t _reg)
Definition: w5100.c:116
static uint16_t dport
Definition: w5100.c:86
SPI transaction structure.
Definition: spi.h:142
void w5100_transmit(uint8_t data)
Definition: w5100.c:224
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
static uint8_t mac[]
Definition: w5100.c:80
#define REG_TX_MEM
Definition: w5100.c:49
#define SOCK_DHAR
Definition: w5100.c:60
#define REG_GAR
Definition: w5100.c:51
bool_t w5100_ch_available()
Definition: w5100.c:324
static const uint8_t RST
Definition: w5100.c:88
static void configure_socket(uint8_t _s, uint8_t _flag, uint16_t _lport, uint16_t _dport, uint8_t *_dest)
Definition: w5100.c:299