1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers: add encx24j600 ethernet driver

This commit is contained in:
Kaspar Schleiser 2015-04-08 19:54:00 +02:00
parent c84199ce10
commit bd698bf574
9 changed files with 835 additions and 0 deletions

View File

@ -278,3 +278,8 @@ endif
ifneq (,$(filter hih6130,$(USEMODULE)))
USEMODULE += vtimer
endif
ifneq (,$(filter encx24j600,$(USEMODULE)))
USEMODULE += timex
USEMODULE += vtimer
endif

View File

@ -43,3 +43,6 @@ endif
ifneq (,$(filter pcd8544,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/pcd8544/include
endif
ifneq (,$(filter encx24j600,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/encx24j600/include
endif

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,447 @@
/*
* Copyright (C) 2015 Ell-i open source co-operative
* Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 driver_encx24j600
* @{
*
* @file
* @brief Internal functions for the ENCX24J600 driver
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
#include <assert.h>
#include <errno.h>
#include "mutex.h"
#include "encx24j600.h"
#include "encx24j600_internal.h"
#include "encx24j600_defines.h"
#include "vtimer.h"
#include "net/netdev2.h"
#include "net/eui64.h"
#include "net/ethernet.h"
//#include "net/ethernet/hdr.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define ENCX24J600_SPI_SPEED SPI_SPEED_1MHZ
#define ENCX24J600_INIT_DELAY 100000U
#define ENC_BUFFER_START 0x0000
#define ENC_BUFFER_SIZE 0x6000
#define ENC_BUFFER_END 0x5FFF
#define RX_BUFFER_START (0x5340) /* Default value */
#define RX_BUFFER_END (ENC_BUFFER_END)
#define TX_BUFFER_LEN (0x2000)
#define TX_BUFFER_END (RX_BUFFER_START)
#define TX_BUFFER_START (TX_BUFFER_END - TX_BUFFER_LEN)
static void cmd(encx24j600_t *dev, char cmd);
static void reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value);
static uint16_t reg_get(encx24j600_t *dev, uint8_t reg);
static void reg_clear_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask);
static inline int _packets_available(encx24j600_t *dev);
static int _get_iid(netdev2_t *netdev, eui64_t *value, size_t max_len);
static void _get_mac_addr(netdev2_t *dev, uint8_t* buf);
/* netdev2 interface */
static int _send(netdev2_t *netdev, const struct iovec *vector, int count);
static int _recv(netdev2_t *netdev, char* buf, int len);
static int _init(netdev2_t *dev);
static void _isr(netdev2_t *dev);
int _get(netdev2_t *dev, netopt_t opt, void *value, size_t max_len);
int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len);
const static netdev2_driver_t netdev2_driver_encx24j600 = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
static inline void lock(encx24j600_t *dev) {
mutex_lock(&dev->mutex);
}
static inline void unlock(encx24j600_t *dev) {
mutex_unlock(&dev->mutex);
}
void encx24j600_setup(encx24j600_t *dev, spi_t spi, gpio_t cs, gpio_t int_pin)
{
dev->netdev.driver = &netdev2_driver_encx24j600;
dev->spi = spi;
dev->cs = cs;
dev->int_pin = int_pin;
dev->rx_next_ptr = RX_BUFFER_START;
mutex_init(&dev->mutex);
}
static void encx24j600_isr(void *arg)
{
encx24j600_t *dev = (encx24j600_t *) arg;
/* disable interrupt line */
gpio_irq_disable(dev->int_pin);
/* call netdev2 hook */
dev->netdev.event_callback((netdev2_t*) dev, NETDEV2_EVENT_ISR, NULL);
}
static void _isr(netdev2_t *netdev)
{
encx24j600_t *dev = (encx24j600_t *) netdev;
uint16_t eir;
lock(dev);
cmd(dev, CLREIE);
eir = reg_get(dev, EIR);
/* check & handle link state change */
if (eir & LINKIF) {
uint16_t estat = reg_get(dev, ESTAT);
netdev2_event_t event = (estat & PHYLNK) ?
NETDEV2_EVENT_LINK_DOWN :
NETDEV2_EVENT_LINK_UP;
netdev->event_callback(netdev, event, NULL);
}
/* check & handle available packets */
if (eir & PKTIF) {
while (_packets_available(dev)) {
unlock(dev);
netdev->event_callback(netdev, NETDEV2_EVENT_RX_COMPLETE,
NULL);
lock(dev);
}
}
/* drop all flags */
reg_clear_bits(dev, EIR, LINKIF);
/* re-enable interrupt */
gpio_irq_enable(dev->int_pin);
cmd(dev, SETEIE);
unlock(dev);
}
static inline void enc_spi_transfer(encx24j600_t *dev, char *out, char *in, int len)
{
spi_acquire(dev->spi);
gpio_clear(dev->cs);
spi_transfer_bytes(dev->spi, out, in, len);
gpio_set(dev->cs);
spi_release(dev->spi);
}
static inline uint16_t reg_get(encx24j600_t *dev, uint8_t reg)
{
char cmd[4] = { RCRU, reg, 0, 0 };
char result[4];
enc_spi_transfer(dev, cmd, result, 4);
return result[2] | (result[3] << 8);
}
static void phy_reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value) {
reg_set(dev, MIREGADR, reg | (1<<8));
reg_set(dev, MIWR, value);
}
static void cmd(encx24j600_t *dev, char cmd) {
spi_acquire(dev->spi);
gpio_clear(dev->cs);
spi_transfer_byte(dev->spi, cmd, NULL);
gpio_set(dev->cs);
spi_release(dev->spi);
}
static void cmdn(encx24j600_t *dev, uint8_t cmd, char *out, char *in, int len) {
spi_acquire(dev->spi);
gpio_clear(dev->cs);
spi_transfer_byte(dev->spi, cmd, NULL);
spi_transfer_bytes(dev->spi, out, in, len);
gpio_set(dev->cs);
spi_release(dev->spi);
}
static void reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value)
{
char cmd[4] = { WCRU, reg, value, value >> 8 };
enc_spi_transfer(dev, cmd, NULL, 4);
}
static void reg_set_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask)
{
char cmd[4] = { BFSU, reg, mask, mask >> 8 };
enc_spi_transfer(dev, cmd, NULL, 4);
}
static void reg_clear_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask)
{
char cmd[4] = { BFCU, reg, mask, mask >> 8 };
enc_spi_transfer(dev, cmd, NULL, 4);
}
/*
* @brief Read/Write to encx24j600's SRAM
*
* @param[in] dev ptr to encx24j600 device handle
* @param[in] cmd either WGPDATA, RGPDATA, WRXDATA, RRXDATA, WUDADATA, RUDADATA
* @param[in] addr SRAM address to start reading. 0xFFFF means continue from old address
* @param ptr pointer to buffer to read from / write to
* @param[in] len nr of bytes to read/write
*/
static void sram_op(encx24j600_t *dev, uint16_t cmd, uint16_t addr, char *ptr, int len)
{
uint16_t reg;
char* in = NULL;
char* out = NULL;
/* determine pointer addr
*
* all SRAM access commands have an
* offset 0x5e to their pointer registers
* */
reg = cmd + 0x5e;
/* read or write? bit 1 tells us */
if (reg & 0x2) {
out = ptr;
} else {
in = ptr;
}
/* set pointer */
if (addr != 0xFFFF) {
reg_set(dev, reg, addr);
}
/* copy data */
cmdn(dev, cmd, in, out, len);
}
static int _init(netdev2_t *encdev)
{
encx24j600_t *dev = (encx24j600_t *) encdev;
DEBUG("encx24j600: starting initialization...\n");
/* setup IO */
gpio_init(dev->cs, GPIO_DIR_OUT, GPIO_PULLUP);
gpio_set(dev->cs);
gpio_init_int(dev->int_pin, GPIO_PULLUP, GPIO_FALLING, encx24j600_isr, (void*)dev);
if (spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, ENCX24J600_SPI_SPEED) < 0) {
return -1;
}
lock(dev);
/* initialization procedure as described in data sheet (39935c.pdf) */
do {
do {
vtimer_usleep(ENCX24J600_INIT_DELAY);
reg_set(dev, EUDAST, 0x1234);
vtimer_usleep(ENCX24J600_INIT_DELAY);
} while (reg_get(dev, EUDAST) != 0x1234);
while (!(reg_get(dev, ESTAT) & CLKRDY));
/* issue System Reset */
cmd(dev, SETETHRST);
/* make sure initialization finalizes */
vtimer_usleep(1000);
} while (!(reg_get(dev, EUDAST) == 0x0000));
/* configure flow control */
phy_reg_set(dev, PHANA, 0x05E1);
reg_set_bits(dev, ECON2, AUTOFC);
/* setup receive buffer */
reg_set(dev, ERXST, RX_BUFFER_START);
reg_set(dev, ERXTAIL, RX_BUFFER_END);
dev->rx_next_ptr = RX_BUFFER_START;
/* configure receive filter to receive multicast frames */
reg_set_bits(dev, ERXFCON, MCEN);
/* setup interrupts */
reg_set_bits(dev, EIE, PKTIE | LINKIE);
cmd(dev, ENABLERX);
cmd(dev, SETEIE);
DEBUG("encx24j600: initialization complete.\n");
unlock(dev);
return 0;
}
static int _send(netdev2_t *netdev, const struct iovec *vector, int count) {
encx24j600_t * dev = (encx24j600_t *) netdev;
lock(dev);
/* wait until previous packet has been sent */
while ((reg_get(dev, ECON1) & TXRTS));
/* copy packet to SRAM */
size_t len = 0;
for (int i = 0; i < count; i++) {
sram_op(dev, WGPDATA, (i ? 0xFFFF : TX_BUFFER_START), vector[i].iov_base, vector[i].iov_len);
len += vector[i].iov_len;
}
/* set start of TX packet and length */
reg_set(dev, ETXST, TX_BUFFER_START);
reg_set(dev, ETXLEN, len);
/* initiate sending */
cmd(dev, SETTXRTS);
/* wait for sending to complete */
/* (not sure if it is needed, keeping the line uncommented) */
/*while ((reg_get(dev, ECON1) & TXRTS));*/
unlock(dev);
return len;
}
static inline int _packets_available(encx24j600_t *dev)
{
/* return PKTCNT (low byte of ESTAT) */
return reg_get(dev, ESTAT) & ~0xFF00;
}
static void _get_mac_addr(netdev2_t *encdev, uint8_t* buf)
{
encx24j600_t * dev = (encx24j600_t *) encdev;
uint16_t *addr = (uint16_t *) buf;
lock(dev);
addr[0] = reg_get(dev, MAADR1);
addr[1] = reg_get(dev, MAADR2);
addr[2] = reg_get(dev, MAADR3);
unlock(dev);
}
static int _recv(netdev2_t *netdev, char* buf, int len)
{
encx24j600_t * dev = (encx24j600_t *) netdev;
encx24j600_frame_hdr_t hdr;
lock(dev);
/* read frame header */
sram_op(dev, RRXDATA, dev->rx_next_ptr, (char*)&hdr, sizeof(hdr));
/* hdr.frame_len given by device contains 4 bytes checksum */
size_t payload_len = hdr.frame_len - 4;
if (buf) {
/* read packet (without 4 bytes checksum) */
sram_op(dev, RRXDATA, 0xFFFF, buf, payload_len);
/* decrement available packet count */
cmd(dev, SETPKTDEC);
dev->rx_next_ptr = hdr.rx_next_ptr;
reg_set(dev, ERXTAIL, dev->rx_next_ptr - 2);
}
unlock(dev);
return payload_len;
}
static int _get_iid(netdev2_t *netdev, eui64_t *value, size_t max_len)
{
if (max_len < sizeof(eui64_t)) {
return -EOVERFLOW;
}
uint8_t addr[ETHERNET_ADDR_LEN];
_get_mac_addr(netdev, addr);
ethernet_get_iid(value, addr);
return sizeof(eui64_t);
}
int _get(netdev2_t *dev, netopt_t opt, void *value, size_t max_len)
{
int res = 0;
switch (opt) {
case NETOPT_DEVICE_TYPE:
{
uint16_t *tgt = (uint16_t *)value;
*tgt = NETDEV2_TYPE_ETHERNET;
res = 2;
break;
}
case NETOPT_ADDRESS:
if (max_len < ETHERNET_ADDR_LEN) {
res = -EINVAL;
}
else {
_get_mac_addr(dev, (uint8_t*)value);
res = ETHERNET_ADDR_LEN;
}
break;
case NETOPT_ADDR_LEN:
case NETOPT_SRC_LEN:
assert(max_len == 2);
uint16_t *tgt = (uint16_t*)value;
*tgt=6;
res = sizeof(uint16_t);
break;
case NETOPT_IPV6_IID:
return _get_iid(dev, value, max_len);
default:
res = -ENOTSUP;
break;
}
return res;
}
int _set(netdev2_t *dev, netopt_t opt, void *value, size_t value_len)
{
int res = 0;
switch (opt) {
default:
return -ENOTSUP;
}
return res;
}

View File

@ -0,0 +1,206 @@
/*
* Copyright (C) 2015 Ell-i open source co-operative
* Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 driver_encx24j600
* @{
*
* @file
* @brief Register definitions for the ENCX24J600 Ethernet device
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef ENCX24J600_REGS_H
#define ENCX24J600_REGS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name SPI instruction set
* @{
*/
#define RCR 0x00 /* read control register */
#define WCR 0x04 /* write control register */
#define RCRU 0x20 /* read control register unbanked */
#define WCRU 0x22 /* write control register unbanked */
#define BFSU 0x24 /* set bits unbanked */
#define BFCU 0x26 /* clear bits unbanked */
#define RGPDATA 0x28 /* Read EGPDATA */
#define WGPDATA 0x2a /* Write EGPDATA */
#define RRXDATA 0x2c /* Read ERXDATA */
#define WRXDATA 0x2e /* Write ERXDATA */
#define RUDADATA 0x30 /* Read EUDADATA */
#define WUDADATA 0x32 /* Write EUDADATA */
#define BFS 0x80 /* Bit Field Set */
#define BFC 0xa0 /* Bit Field Clear */
#define SETETHRST 0xca /* System Reset */
#define SETPKTDEC 0xcc /* Decrements PKTCNT by setting PKTDEC (ECON1<5>) */
#define ENABLERX 0xe8 /* Enables packet reception by setting RXEN (ECON1<0>) */
#define DISABLERX 0xea /* Disable packet reception by clearing RXEN (ECON1<0>) */
#define SETEIE 0xec /* Enable Ethernet Interrupts by setting INT (ESTAT<16>) */
#define CLREIE 0xee /* Disable Ethernet Interrupts by clearing INT (ESTAT<16>) */
#define B0SEL 0xc0 /* select bank 0 */
#define B1SEL 0xc2 /* select bank 0 */
#define B2SEL 0xc4 /* select bank 0 */
#define B3SEL 0xc6 /* select bank 0 */
#define RBSEL 0xc8 /* Read Bank Select */
#define SETTXRTS 0xd4 /* Sets TXRTS (ECON1<1>), sends an Ethernet packet */
/** @} */
/**
* @name 16bit Registers
* @{
*/
#define ETXST 0x00
#define ETXLEN 0x02
#define ERXST 0x04
#define ERXTAIL 0x06
#define ERXHEAD 0x08
#define ETXSTAT 0x12
#define ETXWIRE 0x14
#define EUDAST 0x16
#define ESTAT 0x1a
#define EIR 0x1c /* Interrupt Flag Register */
#define ECON1 0x1e
#define ERXFCON 0x34 /* Receive filter control register */
#define MACON2 0x42
#define MAMXFL 0x4a /* MAC maximum frame length */
#define MAADR3 0x60 /* MAC address byte 5&6 */
#define MAADR2 0x62 /* MAC address byte 3&4 */
#define MAADR1 0x64 /* MAC address byte 1&2 */
#define MIWR 0x66
#define MIREGADR 0x54
#define ECON2 0x6e
#define EIE 0x72 /* Interrupt Enable Register */
#define EGPRDPT 0x86 /* General Purpose SRAM read pointer */
#define EGPWRPT 0x88 /* General Purpose SRAM write pointer */
#define ERXRDPT 0x8a /* RX buffer read pointer */
#define ERXWRPT 0x8c /* RX buffer write pointer */
/** @} */
/**
* @name PHY Registers
*
* (access with phy_reg_* functions)
*
* @{
*/
#define PHCON1 0x00
#define PHSTAT1 0x01
#define PHANA 0x04
#define PHANLPA 0x05
#define PHANE 0x06
#define PHCON2 0x11
#define PHSTAT2 0x1b
#define PHSTAT3 0x1f
/** @} */
/**
* @name ESTAT bits
* @{
*/
#define PHYLNK (1<<8)
#define CLKRDY (1<<12)
/** @} */
/**
* @name ECON1 bits
* @{
*/
#define RXEN (1<<0)
#define TXRTS (1<<1)
#define DMANOCS (1<<2)
#define DMACSSD (1<<3)
#define DMACPY (1<<4)
#define DMAST (1<<5)
#define FCOP0 (1<<6)
#define FCOP1 (1<<7)
#define PKTDEC (1<<8)
#define AESOP0 (1<<9)
#define AESOP1 (1<<10)
#define AESST (1<<11)
#define HASHLST (1<<12)
#define HASHOP (1<<13)
#define HASHEN (1<<14)
#define MODEXST (1<<15)
/** @} */
/**
* @name ECON2 bits
* @{
*/
#define ETHRST (1<<4)
#define AUTOFC (1<<7) /* automatic flow control enable bit */
/** @} */
/**
* @name EIR bits
* @{
*/
#define PCFULIE (1<<0)
#define RXABTIE (1<<1)
#define TXABTIE (1<<2)
#define TXIE (1<<3)
#define DMAIE (1<<5)
#define PKTIE (1<<6)
#define LINKIE (1<<11)
#define AESIE (1<<12)
#define HASHIE (1<<13)
#define MODEXIE (1<<14)
#define INTIE (1<<15)
/** @} */
/**
* @name EIR bits
* @{
*/
#define PCFULIF (1<<0)
#define RXABTIF (1<<1)
#define TXABTIF (1<<2)
#define TXIF (1<<3)
#define DMAIF (1<<5)
#define PKTIF (1<<6)
#define LINKIF (1<<11)
#define AESIF (1<<12)
#define HASHIF (1<<13)
#define MODEXIF (1<<14)
#define CRYPTEN (1<<15)
/** @} */
/**
* @name ERXFCON bits
*/
#define MCEN (1<<1)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* ENCX24J600_REGS_H */
/** @} */

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2015 Ell-i open source co-operative
* Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 driver_encx24j600
* @{
*
* @file
* @brief Internal definitions for the ENCX24J600 Ethernet device
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef ENCX24J600_INTERNAL_H
#define ENCX24J600_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief structure resembling format as sent by device
*/
typedef struct __attribute__((packed)) encx24j600_frame_hdr {
uint16_t rx_next_ptr; /**< ptr to next packet whithin devices memory */
/* Receive Status Vector */
uint16_t frame_len; /**< lenght of ethernet frame including 4 bytes
checksum */
uint32_t flags; /**< random flag field just mentioned for the
sake of documentation completeness */
} encx24j600_frame_hdr_t;
#ifdef __cplusplus
}
#endif
#endif /* ENCX24J600_INTERNAL_H */
/** @} */

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 driver_encx24j600 ENCX24J600
* @ingroup drivers
* @brief Driver for the ENCX24J600 Ethernet Adapter
* @{
*
* @file
* @brief Interface definition for the ENCX24J600 driver
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef ENCX24J600_H
#define ENCX24J600_H
#include "mutex.h"
#include "kernel_types.h"
#include "periph/spi.h"
#include "periph/gpio.h"
#include "net/netdev2.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief encx24j600 netdev2 device
* @extends netdev2_t
*/
typedef struct {
netdev2_t netdev; /**< extended netdev2 structure */
spi_t spi; /**< SPI device the enc is connected to*/
gpio_t cs; /**< SPI chip select pin */
gpio_t int_pin; /**< SPI interrupt pin */
uint16_t rx_next_ptr; /**< ptr to next packet whithin devices memory */
mutex_t mutex; /**< mutex used to lock device access */
} encx24j600_t;
/**
* @brief Setup an encx24j600 based device state.
*
* This function sets SPI pins, initializes the device state structure.
* It does not initialize the device itself.
*
* @param[out] dev the handle of the device to initialize
* @param[in] spi SPI device the device is connected to
* @param[in] cs_pin SPI chip select pin used to select the device
* @param[in] int_pin pin the device will trigger an interrupt on
*/
void encx24j600_setup(encx24j600_t *dev, spi_t spi, gpio_t cs_pin, gpio_t int_pin);
#ifdef __cplusplus
}
#endif
#endif /* ENCX24J600_H */
/** @} */

View File

@ -166,6 +166,11 @@ void auto_init(void)
auto_init_at86rf2xx();
#endif
#ifdef MODULE_ENCX24J600
extern void auto_init_encx24j600(void);
auto_init_encx24j600();
#endif
#ifdef MODULE_GNRC_SLIP
extern void auto_init_slip(void);
auto_init_slip();

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 ENCx24j600 ethernet devices
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifdef MODULE_ENCX24J600
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "encx24j600.h"
#include "net/gnrc/gnrc_netdev2_eth.h"
static encx24j600_t encx24j600;
/**
* @brief Define stack parameters for the MAC layer thread
* @{
*/
#define MAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE)
#define MAC_PRIO (THREAD_PRIORITY_MAIN - 4)
/**
* @brief Stacks for the MAC layer threads
*/
static char _netdev2_eth_stack[MAC_STACKSIZE + DEBUG_EXTRA_STACKSIZE];
static gnrc_netdev2_t _gnrc_encx24j600;
void auto_init_encx24j600(void)
{
DEBUG("auto_init_encx24j600(): initializing device...\n");
/* setup netdev2 device */
encx24j600_setup(&encx24j600, ENCX24J600_SPI, ENCX24J600_CS, ENCX24J600_INT);
/* initialize netdev2<->gnrc adapter state */
gnrc_netdev2_eth_init(&_gnrc_encx24j600, (netdev2_t*)&encx24j600);
/* start gnrc netdev2 thread */
gnrc_netdev2_init(_netdev2_eth_stack, MAC_STACKSIZE,
MAC_PRIO, "gnrc_encx24j600", &_gnrc_encx24j600);
}
#else
typedef int dont_be_pedantic;
#endif /* MODULE_ENCX24J600 */
/** @} */