From d7dbac7c61ca6ea909b2be6803708fd27818e384 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 5 Aug 2016 14:44:09 +0200 Subject: [PATCH 1/3] drivers: added driver for W5100 Ethernet chips --- Makefile.dep | 1 + drivers/Makefile.dep | 4 + drivers/Makefile.include | 3 + drivers/include/w5100.h | 85 ++++++++ drivers/w5100/Makefile | 1 + drivers/w5100/include/w5100_params.h | 62 ++++++ drivers/w5100/include/w5100_regs.h | 140 ++++++++++++ drivers/w5100/w5100.c | 313 +++++++++++++++++++++++++++ 8 files changed, 609 insertions(+) create mode 100644 drivers/include/w5100.h create mode 100644 drivers/w5100/Makefile create mode 100644 drivers/w5100/include/w5100_params.h create mode 100644 drivers/w5100/include/w5100_regs.h create mode 100644 drivers/w5100/w5100.c diff --git a/Makefile.dep b/Makefile.dep index 802f98b2aa..e6f70295b4 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -21,6 +21,7 @@ endif ifneq (,$(filter gnrc_netdev_default,$(USEMODULE))) USEMODULE += gnrc_netif + USEMODULE += gnrc_netdev2 USEMODULE += netdev_default endif diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 77d899f5e2..ce41876d3c 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -136,6 +136,10 @@ ifneq (,$(filter srf08,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter w5100,$(USEMODULE))) + USEMODULE += netdev2_eth +endif + ifneq (,$(filter xbee,$(USEMODULE))) USEMODULE += ieee802154 USEMODULE += xtimer diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 667b05794d..1d2a7feaf8 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -70,3 +70,6 @@ endif ifneq (,$(filter lpd8808,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lpd8808/include endif +ifneq (,$(filter w5100,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/w5100/include +endif diff --git a/drivers/include/w5100.h b/drivers/include/w5100.h new file mode 100644 index 0000000000..9cd72076c9 --- /dev/null +++ b/drivers/include/w5100.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_w5100 W5100 + * @ingroup drivers_netdev_netdev2 + * @brief Driver for W5100 ethernet devices + * + * This device driver only exposes the MACRAW mode of W5100 devices, so it does + * not offer any support for the on-chip IPv4, UDP, and TCP capabilities of + * these chips. In connection with RIOT we are only interested in the RAW + * Ethernet packets, which we can use through netdev2 with any software network + * stack provided by RIOT (e.g. GNRC). This enables W5100 devices to communicate + * via IPv6, enables unlimited connections, and more... + * + * @note This driver expects to be triggered by the external interrupt + * line of the W5100 device. On some Arduino shields this is not + * enabled by default, you have to close the corresponding solder + * bridge to make it work... + * + * @{ + * + * @file + * @brief Interface definition for the W5100 device driver + * + * @author Hauke Petersen + */ + +#ifndef W5100_H +#define W5100_H + +#include + +#include "periph/spi.h" +#include "periph/gpio.h" +#include "net/netdev2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief W5100 error codes + */ +enum { + W5100_ERR_BUS = -1, +}; + +/** + * @brief W5100 device descriptor + */ +typedef struct { + spi_t spi; /**< SPI bus used */ + spi_speed_t spi_speed; /**< clock speed used on the selected SPI bus */ + gpio_t cs; /**< pin connected to the chip select line */ + gpio_t evt; /**< pin connected to the INT line */ +} w5100_params_t; + +/** + * @brief Device descriptor for W5100 devices + */ +typedef struct { + netdev2_t nd; /**< extends the netdev2 structure */ + w5100_params_t p; /**< device configuration parameters */ +} w5100_t; + +/** + * @brief So the initial device setup + * + * This function pre-initializes the netdev2 structure, saves the configuration + * parameters and finally initializes the SPI bus and the used GPIO pins. + */ +void w5100_setup(w5100_t *dev, const w5100_params_t *params); + +#ifdef __cplusplus +} +#endif + +#endif /* W5100_h */ +/* @} */ diff --git a/drivers/w5100/Makefile b/drivers/w5100/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/w5100/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/w5100/include/w5100_params.h b/drivers/w5100/include/w5100_params.h new file mode 100644 index 0000000000..315bfd5b68 --- /dev/null +++ b/drivers/w5100/include/w5100_params.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_w5100 + * @{ + * + * @file + * @brief Default parameters for W5100 Ethernet devices + * + * @author Hauke Petersen + */ + +#ifndef W5100_PARAMS_H +#define W5100_PARAMS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set default configuration parameters for the W5100 driver + * @{ + */ +#ifndef W5100_PARAM_SPI +#define W5100_PARAM_SPI (SPI_0) +#endif +#ifndef W5100_PARAM_SPI_SPEED +#define W5100_PARAM_SPI_SPEED (SPI_SPEED_5MHZ) +#endif +#ifndef W5100_PARAM_CS +#define W5100_PARAM_CS (GPIO_PIN(0, 0)) +#endif +#ifndef W5100_PARAM_EVT +#define W5100_PARAM_EVT (GPIO_PIN(0, 1)) +#endif +/** @} */ + +/** + * @brief W5100 configuration + */ +static const w5100_params_t w5100_params[] = { + { + .spi = W5100_PARAM_SPI, + .spi_speed = W5100_PARAM_SPI_SPEED, + .cs = W5100_PARAM_CS, + .evt = W5100_PARAM_EVT + }, +}; +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* W5100_PARAMS_H */ +/** @} */ diff --git a/drivers/w5100/include/w5100_regs.h b/drivers/w5100/include/w5100_regs.h new file mode 100644 index 0000000000..7d4fe77566 --- /dev/null +++ b/drivers/w5100/include/w5100_regs.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_w5100 + * @{ + * + * @file + * @brief Register definitions for W5100 devices + * + * @author Hauke Petersen + */ + +#ifndef W5100_REGS_H +#define W5100_REGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SPI commands + * @{ + */ +#define CMD_READ (0x0f) +#define CMD_WRITE (0xf0) +/** @} */ + +/** + * @brief Common registers + */ +#define REG_MODE (0x0000) /**< mode */ +#define REG_GAR0 (0x0001) /**< gateway address 0 */ +#define REG_GAR1 (0x0002) /**< gateway address 1 */ +#define REG_GAR2 (0x0003) /**< gateway address 2 */ +#define REG_GAR3 (0x0004) /**< gateway address 3 */ +#define REG_SUB0 (0x0005) /**< subnet mask 0 */ +#define REG_SUB1 (0x0006) /**< subnet mask 1 */ +#define REG_SUB2 (0x0007) /**< subnet mask 2 */ +#define REG_SUB3 (0x0008) /**< subnet mask 3 */ +#define REG_SHAR0 (0x0009) /**< source hardware address 0 */ +#define REG_SHAR1 (0x000a) /**< source hardware address 1 */ +#define REG_SHAR2 (0x000b) /**< source hardware address 2 */ +#define REG_SHAR3 (0x000c) /**< source hardware address 3 */ +#define REG_SHAR4 (0x000d) /**< source hardware address 4 */ +#define REG_SHAR5 (0x000e) /**< source hardware address 5 */ +#define REG_SIPR0 (0x000f) /**< source IP address 0 */ +#define REG_SIPR1 (0x0010) /**< source IP address 1 */ +#define REG_SIPR2 (0x0011) /**< source IP address 2 */ +#define REG_SIPR3 (0x0012) /**< source IP address 3 */ +#define REG_IR (0x0015) /**< interrupt flags */ +#define REG_IMR (0x0016) /**< interrupt masks */ +#define REG_RTR0 (0x0017) /**< retry time 0 */ +#define REG_RTR1 (0x0018) /**< retry time 1 */ +#define REG_RCR (0x0019) /**< retry count */ +#define REG_RMSR (0x001a) /**< RX memory size */ +#define REG_TMSR (0x001b) /**< TX memory size */ +#define REG_PATR0 (0x001c) /**< PPPoE auth type 0 */ +#define REG_PATR1 (0x001d) /**< PPPoE auth type 1 */ +#define REG_PTIMER (0x0028) /**< PPP LCP request timer */ +#define REG_PMAGIC (0x0029) /**< PPP LCP magic number */ +#define REG_UIPR0 (0x002a) /**< unreachable IP address 0 */ +#define REG_UIPR1 (0x002b) /**< unreachable IP address 1 */ +#define REG_UIPR2 (0x002c) /**< unreachable IP address 2 */ +#define REG_UIPR3 (0x002d) /**< unreachable IP address 3 */ +#define REG_UPORT0 (0x00fe) /**< unreachable port 0 */ +#define REG_UPORT1 (0x002f) /**< unreachable port 1 */ +/** @} */ + +/** + * @brief Socket 0 registers + * + * As we are using the device in MACRAW mode, we only need socket 0. + */ +#define S0_MR (0x0400) /**< mode */ +#define S0_CR (0x0401) /**< control */ +#define S0_IR (0x0402) /**< interrupt flags */ +#define S0_SR (0x0403) /**< state */ +#define S0_DHAR0 (0x0406) /**< destination hardware address 0 */ +#define S0_DHAR1 (0x0407) /**< destination hardware address 1 */ +#define S0_DHAR2 (0x0408) /**< destination hardware address 2 */ +#define S0_DHAR3 (0x0409) /**< destination hardware address 3 */ +#define S0_DHAR4 (0x040a) /**< destination hardware address 4 */ +#define S0_DHAR5 (0x040b) /**< destination hardware address 5 */ +#define S0_DIPR0 (0x040c) /**< destination IP address 0 */ +#define S0_DIPR1 (0x040d) /**< destination IP address 1 */ +#define S0_DIPR2 (0x040e) /**< destination IP address 2 */ +#define S0_DIPR3 (0x040f) /**< destination IP address 3 */ +#define S0_DPORT0 (0x0410) /**< destination port 0 */ +#define S0_DPORT1 (0x0411) /**< destination port 1 */ +#define S0_MSSR0 (0x0412) /**< maximum segment size 0 */ +#define S0_MSSR1 (0x0413) /**< maximum segment size 1 */ +#define S0_PROTO (0x0414) /**< protocol in IP raw mode */ +#define S0_TOS (0x0415) /**< IP TOS */ +#define S0_TTL (0x0416) /**< IP TTL */ +#define S0_TX_FSR0 (0x0420) /**< TX free size 0 */ +#define S0_TX_FSR1 (0x0421) /**< TX free size 1 */ +#define S0_TX_RD0 (0x0422) /**< TX read pointer 0 */ +#define S0_TX_RD1 (0x0423) /**< TX read pointer 1 */ +#define S0_TX_WR0 (0x0424) /**< TX write pointer 0 */ +#define S0_TX_WR1 (0x0425) /**< TX write pointer 1 */ +#define S0_RX_RSR0 (0x0426) /**< RX receive size 0 */ +#define S0_RX_RSR1 (0x0427) /**< RX receive size 1 */ +#define S0_RX_RD0 (0x0428) /**< RX read pointer 0 */ +#define S0_RX_RD1 (0x0429) /**< RX read pointer 1 */ +/** @} */ + +/** + * @brief Some selected bitfield definitions + */ +#define MODE_RESET (0x80) /**< device mode: reset */ + +#define RMSR_8KB_TO_S0 (0x03) /**< receive memory size: 8kib */ +#define TMSR_8KB_TO_S0 (0x03) /**< transmit memory size: 8kib */ + +#define IMR_S0_INT (0x01) /**< global socket 0 interrupt mask */ + +#define MR_UDP (0x02) /**< socket mode: UDP */ +#define MR_MACRAW (0x04) /**< socket mode: raw Ethernet */ + +#define CR_OPEN (0x01) /**< socket command: open */ +#define CR_CLOSE (0x10) /**< socket command: close */ +#define CR_SEND_MAC (0x21) /**< socket command: send raw */ +#define CR_RECV (0x40) /**< socket command: receive new data */ + +#define IR_SEND_OK (0x10) /**< socket interrupt: send ok */ +#define IR_RECV (0x04) /**< socket interrupt: data received */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* W5100_REGS_H */ +/** @} */ diff --git a/drivers/w5100/w5100.c b/drivers/w5100/w5100.c new file mode 100644 index 0000000000..3c953553f8 --- /dev/null +++ b/drivers/w5100/w5100.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_w5100 + * @{ + * + * @file + * @brief Device driver implementation for w5100 Ethernet devices + * + * @author Hauke Petersen + * + * @} + */ + +#include +#include + +#include "log.h" +#include "assert.h" +#include "periph/cpuid.h" + +#include "net/ethernet.h" +#include "net/netdev2/eth.h" + +#include "w5100.h" +#include "w5100_regs.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + + +#define SPI_CONF SPI_CONF_FIRST_RISING +#define RMSR_DEFAULT_VALUE (0x55) +#define MAC_SEED (0x23) + +#define S0_MEMSIZE (0x2000) +#define S0_MASK (S0_MEMSIZE - 1) +#define S0_TX_BASE (0x4000) +#define S0_RX_BASE (0x6000) + +static const netdev2_driver_t netdev2_driver_w5100; + +static inline void send_addr(w5100_t *dev, uint16_t addr) +{ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + spi_transfer_byte(dev->p.spi, (addr >> 8), NULL); + spi_transfer_byte(dev->p.spi, (addr & 0xff), NULL); +#else + spi_transfer_byte(dev->p.spi, (addr & 0xff), NULL); + spi_transfer_byte(dev->p.spi, (addr >> 8), NULL); +#endif +} + +static uint8_t rreg(w5100_t *dev, uint16_t reg) +{ + uint8_t data; + + gpio_clear(dev->p.cs); + spi_transfer_byte(dev->p.spi, CMD_READ, NULL); + send_addr(dev, reg++); + spi_transfer_byte(dev->p.spi, 0, (char *)&data); + gpio_set(dev->p.cs); + + return data; +} + +static uint16_t raddr(w5100_t *dev, uint16_t addr_high, uint16_t addr_low) +{ + uint16_t res = (rreg(dev, addr_high) << 8); + res |= rreg(dev, addr_low); + return res; +} + +static void rchunk(w5100_t *dev, uint16_t addr, uint8_t *data, size_t len) +{ + /* reading a chunk must be split in multiple single byte reads, as the + * device does not support auto address increment via SPI */ + for (int i = 0; i < (int)len; i++) { + data[i] = rreg(dev, addr++); + } +} + +static void wreg(w5100_t *dev, uint16_t reg, uint8_t data) +{ + gpio_clear(dev->p.cs); + spi_transfer_byte(dev->p.spi, CMD_WRITE, NULL); + send_addr(dev, reg); + spi_transfer_byte(dev->p.spi, data, NULL); + gpio_set(dev->p.cs); +} + +static void waddr(w5100_t *dev, + uint16_t addr_high, uint16_t addr_low, uint16_t val) +{ + wreg(dev, addr_high, (uint8_t)(val >> 8)); + wreg(dev, addr_low, (uint8_t)(val & 0xff)); +} + +static void wchunk(w5100_t *dev, uint16_t addr, uint8_t *data, size_t len) +{ + /* writing a chunk must be split in multiple single byte writes, as the + * device does not support auto address increment via SPI */ + for (int i = 0; i < (int)len; i++) { + wreg(dev, addr++, data[i]); + } +} + +static void extint(void *arg) +{ + w5100_t *dev = (w5100_t *)arg; + + if (dev->nd.event_callback) { + dev->nd.event_callback(&dev->nd, NETDEV2_EVENT_ISR); + } +} + +void w5100_setup(w5100_t *dev, const w5100_params_t *params) +{ + /* initialize netdev structure */ + dev->nd.driver = &netdev2_driver_w5100; + dev->nd.event_callback = NULL; + dev->nd.context = dev; + + /* initialize the device descriptor */ + memcpy(&dev->p, params, sizeof(w5100_params_t)); + + /* initialize pins and SPI */ + gpio_init(dev->p.cs, GPIO_OUT); + gpio_set(dev->p.cs); + spi_init_master(dev->p.spi, SPI_CONF, dev->p.spi_speed); + + gpio_init_int(dev->p.evt, GPIO_IN, GPIO_FALLING, extint, dev); +} + +static int init(netdev2_t *netdev) +{ + w5100_t *dev = (w5100_t *)netdev; + uint8_t tmp; + uint8_t hwaddr[ETHERNET_ADDR_LEN]; +#if CPUID_LEN + uint8_t cpuid[CPUID_LEN]; +#endif + + /* test the SPI connection by reading the value of the RMSR register */ + tmp = rreg(dev, REG_TMSR); + if (tmp != RMSR_DEFAULT_VALUE) { + LOG_ERROR("[w5100] error: no SPI connection\n"); + return W5100_ERR_BUS; + } + + /* reset the device */ + wreg(dev, REG_MODE, MODE_RESET); + while (rreg(dev, REG_MODE) & MODE_RESET) {}; + + /* initialize the device, start with writing the MAC address */ + memset(hwaddr, MAC_SEED, ETHERNET_ADDR_LEN); +#if CPUID_LEN + cpuid_get(cpuid); + for (int i = 0; i < CPUID_LEN; i++) { + hwaddr[i % ETHERNET_ADDR_LEN] ^= cpuid[i]; + } +#endif + hwaddr[0] &= ~0x03; /* no group address and not globally unique */ + wchunk(dev, REG_SHAR0, hwaddr, ETHERNET_ADDR_LEN); + + /* configure all memory to be used by socket 0 */ + wreg(dev, REG_RMSR, RMSR_8KB_TO_S0); + wreg(dev, REG_TMSR, TMSR_8KB_TO_S0); + + /* configure interrupt pin to trigger on socket 0 events */ + wreg(dev, REG_IMR, IMR_S0_INT); + + /* next we configure socket 0 to work in MACRAW mode */ + wreg(dev, S0_MR, MR_MACRAW); + wreg(dev, S0_CR, CR_OPEN); + + /* start receiving packets */ + wreg(dev, S0_CR, CR_RECV); + + return 0; +} + +static uint16_t tx_upload(w5100_t *dev, uint16_t start, void *data, size_t len) +{ + if ((start + len) >= (S0_TX_BASE + S0_MEMSIZE)) { + size_t limit = ((S0_TX_BASE + S0_MEMSIZE) - start); + wchunk(dev, start, data, limit); + wchunk(dev, S0_TX_BASE, &((uint8_t *)data)[limit], len - limit); + return (S0_TX_BASE + limit); + } + else { + wchunk(dev, start, data, len); + waddr(dev, S0_TX_WR0, S0_TX_WR1, start + len); + return (start + len); + } +} + +static int send(netdev2_t *netdev, const struct iovec *vector, int count) +{ + w5100_t *dev = (w5100_t *)netdev; + int sum = 0; + + uint16_t pos = raddr(dev, S0_TX_WR0, S0_TX_WR1); + + /* the register is only set correctly after the first send pkt, so we need + * this fix here */ + if (pos == 0) { + pos = S0_TX_BASE; + } + + for (int i = 0; i < count; i++) { + pos = tx_upload(dev, pos, vector[i].iov_base, vector[i].iov_len); + sum += vector[i].iov_len; + } + + waddr(dev, S0_TX_WR0, S0_TX_WR1, pos); + + /* trigger the sending process */ + wreg(dev, S0_CR, CR_SEND_MAC); + while (!(rreg(dev, S0_IR) & IR_SEND_OK)) {}; + wreg(dev, S0_IR, IR_SEND_OK); + + DEBUG("[w5100] send: transferred %i byte (at 0x%04x)\n", sum, (int)pos); + + return sum; +} + +static int recv(netdev2_t *netdev, char *buf, int len, void *info) +{ + w5100_t *dev = (w5100_t *)netdev; + int n = 0; + + uint16_t num = raddr(dev, S0_RX_RSR0, S0_RX_RSR1); + + if (num > 0) { + /* find the size of the next packet in the RX buffer */ + uint16_t rp = raddr(dev, S0_RX_RD0, S0_RX_RD1); + uint16_t psize = raddr(dev, (S0_RX_BASE + (rp & S0_MASK)), + (S0_RX_BASE + ((rp + 1) & S0_MASK))); + n = psize - 2; + + DEBUG("[w5100] recv: got packet of %i byte (at 0x%04x)\n", n, (int)rp); + + /* read the actual data into the given buffer if wanted */ + if (buf != NULL) { + uint16_t pos = rp + 2; + len = (n <= len) ? n : len; + for (int i = 0; i < (int)len; i++) { + buf[i] = rreg(dev, (S0_RX_BASE + ((pos++) & S0_MASK))); + } + + DEBUG("[w5100] recv: read %i byte from device (at 0x%04x)\n", + n, (int)rp); + + /* set the new read pointer address */ + waddr(dev, S0_RX_RD0, S0_RX_RD1, rp += psize); + wreg(dev, S0_CR, CR_RECV); + + /* if RX buffer now empty, clear RECV interrupt flag */ + if ((num - psize) == 0) { + wreg(dev, S0_IR, IR_RECV); + } + } + } + + return n; +} + +static void isr(netdev2_t *netdev) +{ + w5100_t *dev = (w5100_t *)netdev; + + /* we only react on RX events, and if we see one, we read from the RX buffer + * until it is empty */ + while (rreg(dev, S0_IR) & IR_RECV) { + DEBUG("[w5100] netdev2 RX complete\n"); + netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE); + } +} + +static int get(netdev2_t *netdev, netopt_t opt, void *value, size_t max_len) +{ + w5100_t *dev = (w5100_t *)netdev; + int res = 0; + + switch (opt) { + case NETOPT_ADDRESS: + assert(max_len >= ETHERNET_ADDR_LEN); + rchunk(dev, REG_SHAR0, value, ETHERNET_ADDR_LEN); + res = ETHERNET_ADDR_LEN; + break; + default: + res = netdev2_eth_get(netdev, opt, value, max_len); + break; + } + + return res; +} + +static const netdev2_driver_t netdev2_driver_w5100 = { + .send = send, + .recv = recv, + .init = init, + .isr = isr, + .get = get, + .set = netdev2_eth_set, +}; From fb24f6d26e302407add640ef09370c20367d0244 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 5 Aug 2016 14:44:38 +0200 Subject: [PATCH 2/3] sys: added auto-init code for W5100 devices --- sys/auto_init/auto_init.c | 5 ++ sys/auto_init/netif/auto_init_w5100.c | 74 +++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 sys/auto_init/netif/auto_init_w5100.c diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 2597f45aa3..9b37ffd48c 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -229,6 +229,11 @@ void auto_init(void) gnrc_nordic_ble_6lowpan_init(); #endif +#ifdef MODULE_W5100 + extern void auto_init_w5100(void); + auto_init_w5100(); +#endif + #endif /* MODULE_AUTO_INIT_GNRC_NETIF */ #ifdef MODULE_GNRC_IPV6_NETIF diff --git a/sys/auto_init/netif/auto_init_w5100.c b/sys/auto_init/netif/auto_init_w5100.c new file mode 100644 index 0000000000..bff96f78b5 --- /dev/null +++ b/sys/auto_init/netif/auto_init_w5100.c @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + */ + +/** + * @ingroup auto_init_gnrc_netif + * @{ + * + * @file + * @brief Auto initialization for W5100 Ethernet devices + * + * @author Hauke Petersen + */ + +#ifdef MODULE_W5100 + +#include "w5100.h" +#include "w5100_params.h" +#include "net/gnrc/netdev2.h" +#include "net/gnrc/netdev2/eth.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Define stack parameters for the MAC layer thread + * @{ + */ +#define MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#define MAC_PRIO (THREAD_PRIORITY_MAIN - 4) +/*** @} */ + +/** + * @brief Find out how many of these devices we need to care for + */ +#define W5100_NUM (sizeof(w5100_params) / sizeof(w5100_params[0])) + +/** + * @brief Allocate memory for the device descriptors + * @{ + */ +static w5100_t dev[W5100_NUM]; +static gnrc_netdev2_t gnrc_adpt[W5100_NUM]; +/** @} */ + +/** + * @brief Stacks for the MAC layer threads + */ +static char stack[MAC_STACKSIZE][W5100_NUM]; + + +void auto_init_w5100(void) +{ + for (int i = 0; i < W5100_NUM; i++) { + DEBUG("auto_init_w5100(): initializing device [%i]...\n", i); + /* setup netdev2 device */ + w5100_setup(&dev[i], &w5100_params[i]); + /* initialize netdev2 <-> gnrc adapter state */ + gnrc_netdev2_eth_init(&gnrc_adpt[i], (netdev2_t *)&dev[i]); + /* start gnrc netdev2 thread */ + gnrc_netdev2_init(stack[i], MAC_STACKSIZE, MAC_PRIO, + "gnrc_w5100", &gnrc_adpt[i]); + } +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_W5100 */ +/** @} */ From 18c6824b38dac8bc1343aa5acca125f2fe6af331 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Fri, 5 Aug 2016 14:50:45 +0200 Subject: [PATCH 3/3] boards/arduino-due: added config for W5100 shields --- boards/arduino-due/include/w5100_params.h | 62 +++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 boards/arduino-due/include/w5100_params.h diff --git a/boards/arduino-due/include/w5100_params.h b/boards/arduino-due/include/w5100_params.h new file mode 100644 index 0000000000..131bed8ec8 --- /dev/null +++ b/boards/arduino-due/include/w5100_params.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup boards_arduino-due + * @{ + * + * @file + * @brief Parameters for W5100 Arduino Ehternet Shields (v4 and v5) + * + * @author Hauke Petersen + */ + +#ifndef W5100_PARAMS_H +#define W5100_PARAMS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set configuration parameters for the W5100 driver + * @{ + */ +#ifndef W5100_PARAM_SPI +#define W5100_PARAM_SPI (SPI_0) +#endif +#ifndef W5100_PARAM_SPI_SPEED +#define W5100_PARAM_SPI_SPEED (SPI_SPEED_5MHZ) +#endif +#ifndef W5100_PARAM_CS +#define W5100_PARAM_CS (GPIO_PIN(2, 29)) +#endif +#ifndef W5100_PARAM_EVT +#define W5100_PARAM_EVT (GPIO_PIN(1, 25)) +#endif +/** @} */ + +/** + * @brief W5100 configuration instance + */ +static const w5100_params_t w5100_params[] = { + { + .spi = W5100_PARAM_SPI, + .spi_speed = W5100_PARAM_SPI_SPEED, + .cs = W5100_PARAM_CS, + .evt = W5100_PARAM_EVT + }, +}; +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* W5100_PARAMS_H */ +/** @} */