diff --git a/Makefile.dep b/Makefile.dep index a40aae3c39..07d2a27027 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -278,3 +278,8 @@ endif ifneq (,$(filter hih6130,$(USEMODULE))) USEMODULE += vtimer endif + +ifneq (,$(filter encx24j600,$(USEMODULE))) + USEMODULE += timex + USEMODULE += vtimer +endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index e15584f92d..23cc3d0007 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -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 diff --git a/drivers/encx24j600/Makefile b/drivers/encx24j600/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/encx24j600/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/encx24j600/encx24j600.c b/drivers/encx24j600/encx24j600.c new file mode 100644 index 0000000000..a9b8ab060f --- /dev/null +++ b/drivers/encx24j600/encx24j600.c @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2015 Ell-i open source co-operative + * Kaspar Schleiser + * + * 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 + * + * @} + */ + +#include +#include + +#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; +} diff --git a/drivers/encx24j600/include/encx24j600_defines.h b/drivers/encx24j600/include/encx24j600_defines.h new file mode 100644 index 0000000000..7f96f691db --- /dev/null +++ b/drivers/encx24j600/include/encx24j600_defines.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2015 Ell-i open source co-operative + * Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */ diff --git a/drivers/encx24j600/include/encx24j600_internal.h b/drivers/encx24j600/include/encx24j600_internal.h new file mode 100644 index 0000000000..b718465a68 --- /dev/null +++ b/drivers/encx24j600/include/encx24j600_internal.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Ell-i open source co-operative + * Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */ diff --git a/drivers/include/encx24j600.h b/drivers/include/encx24j600.h new file mode 100644 index 0000000000..28d5e200a1 --- /dev/null +++ b/drivers/include/encx24j600.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */ diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 32692045fd..1244f6b2c4 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -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(); diff --git a/sys/auto_init/netif/auto_init_encx24j600.c b/sys/auto_init/netif/auto_init_encx24j600.c new file mode 100644 index 0000000000..3236dfb02d --- /dev/null +++ b/sys/auto_init/netif/auto_init_encx24j600.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 + */ + +#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 */ +/** @} */