299 lines
12 KiB
C
299 lines
12 KiB
C
/*
|
|
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the Institute nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* Author: Adam Dunkels <adam@sics.se>
|
|
*
|
|
* $Id: netdev.c,v 1.8 2006/06/07 08:39:58 adam Exp $
|
|
*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#include "uip.h"
|
|
#include "uip_arp.h"
|
|
#include "boot.h"
|
|
#include "xmc_gpio.h"
|
|
#include "xmc_eth_mac.h"
|
|
#include "xmc_eth_phy.h"
|
|
#include <string.h>
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#define NETDEV_LINKUP_TIMEOUT_MS (5000)
|
|
|
|
#define NETDEV_DEFAULT_MACADDR0 (0x08)
|
|
#define NETDEV_DEFAULT_MACADDR1 (0x00)
|
|
#define NETDEV_DEFAULT_MACADDR2 (0x27)
|
|
#define NETDEV_DEFAULT_MACADDR3 (0x69)
|
|
#define NETDEV_DEFAULT_MACADDR4 (0x5B)
|
|
#define NETDEV_DEFAULT_MACADDR5 (0x45)
|
|
|
|
#define NETDEV_DEFAULT_MACADDR ((uint64_t)NETDEV_DEFAULT_MACADDR0 | \
|
|
((uint64_t)NETDEV_DEFAULT_MACADDR1 << 8) | \
|
|
((uint64_t)NETDEV_DEFAULT_MACADDR2 << 16) | \
|
|
((uint64_t)NETDEV_DEFAULT_MACADDR3 << 24) | \
|
|
((uint64_t)NETDEV_DEFAULT_MACADDR4 << 32) | \
|
|
((uint64_t)NETDEV_DEFAULT_MACADDR5 << 40))
|
|
|
|
#define ETH_UIP_0_NUM_RX_BUF (4U)
|
|
#define ETH_UIP_0_NUM_TX_BUF (4U)
|
|
|
|
#define ETH_UIP_0_CRS_DV XMC_GPIO_PORT15, 9U
|
|
#define ETH_UIP_0_RXER XMC_GPIO_PORT2, 4U
|
|
#define ETH_UIP_0_RXD0 XMC_GPIO_PORT2, 2U
|
|
#define ETH_UIP_0_RXD1 XMC_GPIO_PORT2, 3U
|
|
#define ETH_UIP_0_TXEN XMC_GPIO_PORT2, 5U
|
|
#define ETH_UIP_0_TXD0 XMC_GPIO_PORT2, 8U
|
|
#define ETH_UIP_0_TXD1 XMC_GPIO_PORT2, 9U
|
|
#define ETH_UIP_0_RMII_CLK XMC_GPIO_PORT15, 8U
|
|
#define ETH_UIP_0_MDC XMC_GPIO_PORT2, 7U
|
|
#define ETH_UIP_0_MDIO XMC_GPIO_PORT2, 0U
|
|
#define ETH_UIP_0_PIN_LIST_SIZE (10U)
|
|
|
|
#define ETH_UIP_0_PHY_ADDR (0)
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#if defined(__ICCARM__)
|
|
#pragma data_alignment=4
|
|
static XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_rx_desc[ETH_UIP_0_NUM_RX_BUF] @ ".iram2";
|
|
#pragma data_alignment=4
|
|
static XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_tx_desc[ETH_UIP_0_NUM_TX_BUF] @ ".iram2";
|
|
#pragma data_alignment=4
|
|
static blt_int8u ETH_UIP_0_rx_buf[ETH_UIP_0_NUM_RX_BUF][XMC_ETH_MAC_BUF_SIZE] @ ".iram2";
|
|
#pragma data_alignment=4
|
|
static blt_int8u ETH_UIP_0_tx_buf[ETH_UIP_0_NUM_TX_BUF][XMC_ETH_MAC_BUF_SIZE] @ ".iram2";
|
|
#elif defined(__CC_ARM)
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_rx_desc[ETH_UIP_0_NUM_RX_BUF] __attribute__((section ("RW_IRAM1")));
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_tx_desc[ETH_UIP_0_NUM_TX_BUF] __attribute__((section ("RW_IRAM1")));
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_rx_buf[ETH_UIP_0_NUM_RX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("RW_IRAM1")));
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_tx_buf[ETH_UIP_0_NUM_TX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("RW_IRAM1")));
|
|
#elif defined(__GNUC__)
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_rx_desc[ETH_UIP_0_NUM_RX_BUF] __attribute__((section ("ETH_RAM")));
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_tx_desc[ETH_UIP_0_NUM_TX_BUF] __attribute__((section ("ETH_RAM")));
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_rx_buf[ETH_UIP_0_NUM_RX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("ETH_RAM")));
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_tx_buf[ETH_UIP_0_NUM_TX_BUF][XMC_ETH_MAC_BUF_SIZE] __attribute__((section ("ETH_RAM")));
|
|
#else
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_rx_desc[ETH_UIP_0_NUM_RX_BUF];
|
|
static __attribute__((aligned(4))) XMC_ETH_MAC_DMA_DESC_t ETH_UIP_0_tx_desc[ETH_UIP_0_NUM_TX_BUF];
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_rx_buf[ETH_UIP_0_NUM_RX_BUF][XMC_ETH_MAC_BUF_SIZE];
|
|
static __attribute__((aligned(4))) blt_int8u ETH_UIP_0_tx_buf[ETH_UIP_0_NUM_TX_BUF][XMC_ETH_MAC_BUF_SIZE];
|
|
#endif
|
|
|
|
const XMC_ETH_PHY_CONFIG_t eth_phy_config =
|
|
{
|
|
.interface = XMC_ETH_LINK_INTERFACE_RMII,
|
|
.enable_auto_negotiate = false,
|
|
.duplex = XMC_ETH_LINK_DUPLEX_FULL,
|
|
.speed = XMC_ETH_LINK_SPEED_100M
|
|
};
|
|
|
|
XMC_ETH_MAC_t eth_mac =
|
|
{
|
|
.regs = ETH0,
|
|
.address = NETDEV_DEFAULT_MACADDR,
|
|
.rx_desc = ETH_UIP_0_rx_desc,
|
|
.tx_desc = ETH_UIP_0_tx_desc,
|
|
.rx_buf = Ð_UIP_0_rx_buf[0][0],
|
|
.tx_buf = Ð_UIP_0_tx_buf[0][0],
|
|
.num_rx_buf = ETH_UIP_0_NUM_RX_BUF,
|
|
.num_tx_buf = ETH_UIP_0_NUM_TX_BUF
|
|
};
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void netdev_init(void)
|
|
{
|
|
XMC_ETH_MAC_PORT_CTRL_t port_control;
|
|
XMC_GPIO_CONFIG_t gpio_config;
|
|
gpio_config.output_level = XMC_GPIO_OUTPUT_LEVEL_LOW;
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
|
|
/* Initialize GPIO pins. */
|
|
XMC_GPIO_Init(ETH_UIP_0_CRS_DV, &gpio_config);
|
|
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
XMC_GPIO_Init(ETH_UIP_0_RXER, &gpio_config);
|
|
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
XMC_GPIO_Init(ETH_UIP_0_RXD0, &gpio_config);
|
|
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
XMC_GPIO_Init(ETH_UIP_0_RXD1, &gpio_config);
|
|
|
|
gpio_config.output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
|
|
gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1;
|
|
XMC_GPIO_Init(ETH_UIP_0_TXEN, &gpio_config);
|
|
|
|
gpio_config.output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
|
|
gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1;
|
|
XMC_GPIO_Init(ETH_UIP_0_TXD0, &gpio_config);
|
|
|
|
gpio_config.output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
|
|
gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1;
|
|
XMC_GPIO_Init(ETH_UIP_0_TXD1, &gpio_config);
|
|
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
XMC_GPIO_Init(ETH_UIP_0_RMII_CLK, &gpio_config);
|
|
|
|
gpio_config.output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_SHARP_EDGE;
|
|
gpio_config.mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL_ALT1;
|
|
XMC_GPIO_Init(ETH_UIP_0_MDC, &gpio_config);
|
|
|
|
gpio_config.mode = XMC_GPIO_MODE_INPUT_TRISTATE;
|
|
XMC_GPIO_Init(ETH_UIP_0_MDIO, &gpio_config);
|
|
|
|
XMC_GPIO_SetHardwareControl(ETH_UIP_0_MDIO, XMC_GPIO_HWCTRL_PERIPHERAL1);
|
|
|
|
port_control.mode = XMC_ETH_MAC_PORT_CTRL_MODE_RMII;
|
|
port_control.rxd0 = (XMC_ETH_MAC_PORT_CTRL_RXD0_t)0U;
|
|
port_control.rxd1 = (XMC_ETH_MAC_PORT_CTRL_RXD1_t)0U;
|
|
port_control.clk_rmii = (XMC_ETH_MAC_PORT_CTRL_CLK_RMII_t)2U;
|
|
port_control.crs_dv = (XMC_ETH_MAC_PORT_CTRL_CRS_DV_t)2U;
|
|
port_control.rxer = (XMC_ETH_MAC_PORT_CTRL_RXER_t)0U;
|
|
port_control.mdio = (XMC_ETH_MAC_PORT_CTRL_MDIO_t)1U;
|
|
XMC_ETH_MAC_SetPortControl(ð_mac, port_control);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void netdev_init_mac(void)
|
|
{
|
|
struct uip_eth_addr macAddress;
|
|
blt_int32u ulLinkTimeOut;
|
|
|
|
(void)XMC_ETH_MAC_Init(ð_mac);
|
|
|
|
XMC_ETH_MAC_DisableJumboFrame(ð_mac);
|
|
|
|
/* Wait for link to become active. */
|
|
ulLinkTimeOut = TimerGet() + NETDEV_LINKUP_TIMEOUT_MS;
|
|
while (XMC_ETH_PHY_GetLinkStatus(ð_mac, ETH_UIP_0_PHY_ADDR) == XMC_ETH_LINK_STATUS_DOWN)
|
|
{
|
|
/* Check for timeout so that the software program can still start if the ethernet
|
|
* cable is not connected.
|
|
*/
|
|
if (TimerGet() >= ulLinkTimeOut)
|
|
{
|
|
break;
|
|
}
|
|
/* Service the watchdog. */
|
|
CopService();
|
|
}
|
|
|
|
XMC_ETH_PHY_Init(ð_mac, ETH_UIP_0_PHY_ADDR, ð_phy_config);
|
|
XMC_ETH_MAC_SetLink(ð_mac, XMC_ETH_LINK_SPEED_100M, XMC_ETH_LINK_DUPLEX_FULL);
|
|
XMC_ETH_MAC_EnableTx(ð_mac);
|
|
XMC_ETH_MAC_EnableRx(ð_mac);
|
|
|
|
/* set the default MAC address */
|
|
macAddress.addr[0] = NETDEV_DEFAULT_MACADDR0;
|
|
macAddress.addr[1] = NETDEV_DEFAULT_MACADDR1;
|
|
macAddress.addr[2] = NETDEV_DEFAULT_MACADDR2;
|
|
macAddress.addr[3] = NETDEV_DEFAULT_MACADDR3;
|
|
macAddress.addr[4] = NETDEV_DEFAULT_MACADDR4;
|
|
macAddress.addr[5] = NETDEV_DEFAULT_MACADDR5;
|
|
uip_setethaddr(macAddress);
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void netdev_get_mac(unsigned char * mac_addr)
|
|
{
|
|
mac_addr[0] = NETDEV_DEFAULT_MACADDR0;
|
|
mac_addr[1] = NETDEV_DEFAULT_MACADDR1;
|
|
mac_addr[2] = NETDEV_DEFAULT_MACADDR2;
|
|
mac_addr[3] = NETDEV_DEFAULT_MACADDR3;
|
|
mac_addr[4] = NETDEV_DEFAULT_MACADDR4;
|
|
mac_addr[5] = NETDEV_DEFAULT_MACADDR5;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
unsigned int netdev_read(void)
|
|
{
|
|
blt_int32u result = 0;
|
|
blt_int32u framelen;
|
|
|
|
/* Check if a new frame was received. */
|
|
framelen = XMC_ETH_MAC_GetRxFrameSize(ð_mac);
|
|
/* Only process the frame if the length is valid. */
|
|
if ((framelen > 0U) && (framelen <= (blt_int32u)XMC_ETH_MAC_BUF_SIZE))
|
|
{
|
|
XMC_ETH_MAC_ReadFrame(ð_mac, uip_buf, framelen);
|
|
result = framelen;
|
|
}
|
|
|
|
/* Give the result back to the caller. */
|
|
return result;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void netdev_send(void)
|
|
{
|
|
uint8_t *buffer;
|
|
uint32_t idx;
|
|
|
|
/* Only send the frame if the length is valid. */
|
|
if ((uip_len > 0U) && (uip_len <= (blt_int32u)XMC_ETH_MAC_BUF_SIZE))
|
|
{
|
|
if (XMC_ETH_MAC_IsTxDescriptorOwnedByDma(ð_mac))
|
|
{
|
|
XMC_ETH_MAC_ResumeTx(ð_mac);
|
|
}
|
|
else
|
|
{
|
|
buffer = XMC_ETH_MAC_GetTxBuffer(ð_mac);
|
|
for (idx = 0; idx < uip_len; idx++)
|
|
{
|
|
buffer[idx] = uip_buf[idx];
|
|
}
|
|
XMC_ETH_MAC_SetTxBufferSize(ð_mac, uip_len);
|
|
/* Return the Tx descriptor but do not use the XMC_ETH_MAC_ReturnTxDescriptor().
|
|
* This function enables the 'checksum insertion control' feature by setting the
|
|
* ETH_MAC_DMA_TDES0_CIC in the eth_mac.tx_desc[eth_mac.tx_index].status. When
|
|
* this feature is enabled, an incorrect checksum of 0x0000 is always added to
|
|
* ICMP reponse messages such as the PING reply.
|
|
*/
|
|
eth_mac.tx_ts_index = eth_mac.tx_index;
|
|
eth_mac.tx_desc[eth_mac.tx_index].status |= ETH_MAC_DMA_TDES0_OWN;
|
|
eth_mac.tx_index++;
|
|
if (eth_mac.tx_index == eth_mac.num_tx_buf)
|
|
{
|
|
eth_mac.tx_index = 0U;
|
|
}
|
|
eth_mac.frame_end = NULL;
|
|
XMC_ETH_MAC_ResumeTx(ð_mac);
|
|
}
|
|
}
|
|
}
|
|
|