Squashed 'tmk_core/' changes from 7967731..b9e0ea0
b9e0ea0 Merge commit '7fa9d8bdea3773d1195b04d98fcf27cf48ddd81d' as 'tool/mbed/mbed-sdk' 7fa9d8b Squashed 'tool/mbed/mbed-sdk/' content from commit 7c21ce5 git-subtree-dir: tmk_core git-subtree-split: b9e0ea08cb940de20b3610ecdda18e9d8cd7c552
This commit is contained in:
parent
a20ef7052c
commit
1fe4406f37
4198 changed files with 2016457 additions and 0 deletions
|
@ -0,0 +1,156 @@
|
|||
/* EthernetInterface.cpp */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "EthernetInterface.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "eth_arch.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#include "mbed.h"
|
||||
|
||||
/* TCP/IP and Network Interface Initialisation */
|
||||
static struct netif netif;
|
||||
|
||||
static char mac_addr[19];
|
||||
static char ip_addr[17] = "\0";
|
||||
static char gateway[17] = "\0";
|
||||
static char networkmask[17] = "\0";
|
||||
static bool use_dhcp = false;
|
||||
|
||||
static Semaphore tcpip_inited(0);
|
||||
static Semaphore netif_linked(0);
|
||||
static Semaphore netif_up(0);
|
||||
|
||||
static void tcpip_init_done(void *arg) {
|
||||
tcpip_inited.release();
|
||||
}
|
||||
|
||||
static void netif_link_callback(struct netif *netif) {
|
||||
if (netif_is_link_up(netif)) {
|
||||
netif_linked.release();
|
||||
}
|
||||
}
|
||||
|
||||
static void netif_status_callback(struct netif *netif) {
|
||||
if (netif_is_up(netif)) {
|
||||
strcpy(ip_addr, inet_ntoa(netif->ip_addr));
|
||||
strcpy(gateway, inet_ntoa(netif->gw));
|
||||
strcpy(networkmask, inet_ntoa(netif->netmask));
|
||||
netif_up.release();
|
||||
}
|
||||
}
|
||||
|
||||
static void init_netif(ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw) {
|
||||
tcpip_init(tcpip_init_done, NULL);
|
||||
tcpip_inited.wait();
|
||||
|
||||
memset((void*) &netif, 0, sizeof(netif));
|
||||
netif_add(&netif, ipaddr, netmask, gw, NULL, eth_arch_enetif_init, tcpip_input);
|
||||
netif_set_default(&netif);
|
||||
|
||||
netif_set_link_callback (&netif, netif_link_callback);
|
||||
netif_set_status_callback(&netif, netif_status_callback);
|
||||
}
|
||||
|
||||
static void set_mac_address(void) {
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", MBED_MAC_ADDR_0, MBED_MAC_ADDR_1, MBED_MAC_ADDR_2,
|
||||
MBED_MAC_ADDR_3, MBED_MAC_ADDR_4, MBED_MAC_ADDR_5);
|
||||
#else
|
||||
char mac[6];
|
||||
mbed_mac_address(mac);
|
||||
snprintf(mac_addr, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
#endif
|
||||
}
|
||||
|
||||
int EthernetInterface::init() {
|
||||
use_dhcp = true;
|
||||
set_mac_address();
|
||||
init_netif(NULL, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EthernetInterface::init(const char* ip, const char* mask, const char* gateway) {
|
||||
use_dhcp = false;
|
||||
|
||||
set_mac_address();
|
||||
strcpy(ip_addr, ip);
|
||||
|
||||
ip_addr_t ip_n, mask_n, gateway_n;
|
||||
inet_aton(ip, &ip_n);
|
||||
inet_aton(mask, &mask_n);
|
||||
inet_aton(gateway, &gateway_n);
|
||||
init_netif(&ip_n, &mask_n, &gateway_n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EthernetInterface::connect(unsigned int timeout_ms) {
|
||||
eth_arch_enable_interrupts();
|
||||
|
||||
int inited;
|
||||
if (use_dhcp) {
|
||||
dhcp_start(&netif);
|
||||
|
||||
// Wait for an IP Address
|
||||
// -1: error, 0: timeout
|
||||
inited = netif_up.wait(timeout_ms);
|
||||
} else {
|
||||
netif_set_up(&netif);
|
||||
|
||||
// Wait for the link up
|
||||
inited = netif_linked.wait(timeout_ms);
|
||||
}
|
||||
|
||||
return (inited > 0) ? (0) : (-1);
|
||||
}
|
||||
|
||||
int EthernetInterface::disconnect() {
|
||||
if (use_dhcp) {
|
||||
dhcp_release(&netif);
|
||||
dhcp_stop(&netif);
|
||||
} else {
|
||||
netif_set_down(&netif);
|
||||
}
|
||||
|
||||
eth_arch_disable_interrupts();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* EthernetInterface::getMACAddress() {
|
||||
return mac_addr;
|
||||
}
|
||||
|
||||
char* EthernetInterface::getIPAddress() {
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
char* EthernetInterface::getGateway() {
|
||||
return gateway;
|
||||
}
|
||||
|
||||
char* EthernetInterface::getNetworkMask() {
|
||||
return networkmask;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/* EthernetInterface.h */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ETHERNETINTERFACE_H_
|
||||
#define ETHERNETINTERFACE_H_
|
||||
|
||||
#if !defined(TARGET_LPC1768) && !defined(TARGET_LPC4088) && !defined(TARGET_LPC4088_DM) && !defined(TARGET_K64F) && !defined(TARGET_RZ_A1H) && !defined(TARGET_STM32F4)
|
||||
#error The Ethernet Interface library is not supported on this target
|
||||
#endif
|
||||
|
||||
#include "rtos.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/** Interface using Ethernet to connect to an IP-based network
|
||||
*
|
||||
*/
|
||||
class EthernetInterface {
|
||||
public:
|
||||
/** Initialize the interface with DHCP.
|
||||
* Initialize the interface and configure it to use DHCP (no connection at this point).
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
static int init(); //With DHCP
|
||||
|
||||
/** Initialize the interface with a static IP address.
|
||||
* Initialize the interface and configure it with the following static configuration (no connection at this point).
|
||||
* \param ip the IP address to use
|
||||
* \param mask the IP address mask
|
||||
* \param gateway the gateway to use
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
static int init(const char* ip, const char* mask, const char* gateway);
|
||||
|
||||
/** Connect
|
||||
* Bring the interface up, start DHCP if needed.
|
||||
* \param timeout_ms timeout in ms (default: (15)s).
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
static int connect(unsigned int timeout_ms=15000);
|
||||
|
||||
/** Disconnect
|
||||
* Bring the interface down
|
||||
* \return 0 on success, a negative number on failure
|
||||
*/
|
||||
static int disconnect();
|
||||
|
||||
/** Get the MAC address of your Ethernet interface
|
||||
* \return a pointer to a string containing the MAC address
|
||||
*/
|
||||
static char* getMACAddress();
|
||||
|
||||
/** Get the IP address of your Ethernet interface
|
||||
* \return a pointer to a string containing the IP address
|
||||
*/
|
||||
static char* getIPAddress();
|
||||
|
||||
/** Get the Gateway address of your Ethernet interface
|
||||
* \return a pointer to a string containing the Gateway address
|
||||
*/
|
||||
static char* getGateway();
|
||||
|
||||
/** Get the Network mask of your Ethernet interface
|
||||
* \return a pointer to a string containing the Network mask
|
||||
*/
|
||||
static char* getNetworkMask();
|
||||
};
|
||||
|
||||
#include "TCPSocketConnection.h"
|
||||
#include "TCPSocketServer.h"
|
||||
|
||||
#include "Endpoint.h"
|
||||
#include "UDPSocket.h"
|
||||
|
||||
#endif /* ETHERNETINTERFACE_H_ */
|
|
@ -0,0 +1,41 @@
|
|||
/* EthernetInterface.h */
|
||||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Architecture specific Ethernet interface
|
||||
// Must be implemented by each target
|
||||
|
||||
#ifndef ETHARCH_H_
|
||||
#define ETHARCH_H_
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void eth_arch_enable_interrupts(void);
|
||||
void eth_arch_disable_interrupts(void);
|
||||
err_t eth_arch_enetif_init(struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #ifndef ETHARCHINTERFACE_H_
|
||||
|
|
@ -0,0 +1,469 @@
|
|||
/*
|
||||
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
/* Modified by mbed for the lwIP port */
|
||||
|
||||
#include "fsl_enet_driver.h"
|
||||
#include "fsl_enet_hal.h"
|
||||
#include "fsl_clock_manager.h"
|
||||
#include "fsl_interrupt_manager.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "sys_arch.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
/*! @brief Define ENET's IRQ list */
|
||||
|
||||
void *enetIfHandle;
|
||||
|
||||
/*! @brief Define MAC driver API structure and for application of stack adaptor layer*/
|
||||
const enet_mac_api_t g_enetMacApi =
|
||||
{
|
||||
enet_mac_init,
|
||||
NULL, // enet_mac_deinit,
|
||||
NULL, // enet_mac_send,
|
||||
#if !ENET_RECEIVE_ALL_INTERRUPT
|
||||
NULL, // enet_mac_receive,
|
||||
#endif
|
||||
enet_mii_read,
|
||||
enet_mii_write,
|
||||
NULL, // enet_mac_add_multicast_group,
|
||||
NULL, //enet_mac_leave_multicast_group,
|
||||
};
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
|
||||
// NOTE: we need these functions to be non-blocking fpr the PHY task, hence the
|
||||
// osDelay() below
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mii_read
|
||||
* Return Value: The execution status.
|
||||
* Description: Read function.
|
||||
* This interface read data over the (R)MII bus from the specified PHY register,
|
||||
* This function is called by all PHY interfaces.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mii_read(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
|
||||
{
|
||||
uint32_t counter;
|
||||
|
||||
/* Check the input parameters*/
|
||||
if (!dataPtr)
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
/* Check if the mii is enabled*/
|
||||
if (!enet_hal_is_mii_enabled(instance))
|
||||
{
|
||||
return kStatus_ENET_Miiuninitialized;
|
||||
}
|
||||
|
||||
/* Clear the MII interrupt event*/
|
||||
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
|
||||
|
||||
/* Read command operation*/
|
||||
enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetReadValidFrame, 0);
|
||||
|
||||
/* Poll for MII complete*/
|
||||
for (counter = 0; counter < kEnetMaxTimeout; counter++)
|
||||
{
|
||||
if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
|
||||
{
|
||||
break;
|
||||
}
|
||||
osDelay(1);
|
||||
}
|
||||
|
||||
/* Check for timeout*/
|
||||
if (counter == kEnetMaxTimeout)
|
||||
{
|
||||
return kStatus_ENET_TimeOut;
|
||||
}
|
||||
|
||||
/* Get data from mii register*/
|
||||
*dataPtr = enet_hal_get_mii_data(instance);
|
||||
|
||||
/* Clear MII interrupt event*/
|
||||
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mii_write
|
||||
* Return Value: The execution status.
|
||||
* Description: Write function.
|
||||
* This interface write data over the (R)MII bus to the specified PHY register.
|
||||
* This function is called by all PHY interfaces.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mii_write(uint32_t instance, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
|
||||
{
|
||||
uint32_t counter;
|
||||
|
||||
/* Check if the mii is enabled*/
|
||||
if (!enet_hal_is_mii_enabled(instance))
|
||||
{
|
||||
return kStatus_ENET_Miiuninitialized;
|
||||
}
|
||||
|
||||
/* Clear the MII interrupt event*/
|
||||
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
|
||||
|
||||
/* Read command operation*/
|
||||
enet_hal_set_mii_command(instance, phyAddr, phyReg, kEnetWriteValidFrame, data);
|
||||
|
||||
/* Poll for MII complete*/
|
||||
for (counter = 0; counter < kEnetMaxTimeout; counter++)
|
||||
{
|
||||
if (enet_hal_get_interrupt_status(instance, kEnetMiiInterrupt))
|
||||
{
|
||||
break;
|
||||
}
|
||||
osDelay(1);
|
||||
}
|
||||
|
||||
/* Check for timeout*/
|
||||
if (counter == kEnetMaxTimeout)
|
||||
{
|
||||
return kStatus_ENET_TimeOut;
|
||||
}
|
||||
|
||||
/* Clear MII intrrupt event*/
|
||||
enet_hal_clear_interrupt(instance, kEnetMiiInterrupt);
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_mii_init
|
||||
* Return Value: The execution status.
|
||||
* Description:Initialize the ENET Mac mii(mdc/mdio)interface.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_mii_init(enet_dev_if_t * enetIfPtr)
|
||||
{
|
||||
uint32_t frequency;
|
||||
|
||||
/* Check the input parameters*/
|
||||
if (enetIfPtr == NULL)
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
/* Configure mii speed*/
|
||||
CLOCK_SYS_GetFreq(kSystemClock, &frequency);
|
||||
enet_hal_config_mii(enetIfPtr->deviceNumber, (frequency/(2 * enetIfPtr->macCfgPtr->miiClock) + 1),
|
||||
kEnetMdioHoldOneClkCycle, false);
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_rxbd_init
|
||||
* Return Value: The execution status.
|
||||
* Description:Initialize the ENET receive buffer descriptors.
|
||||
* Note: If you do receive on receive interrupt handler the receive
|
||||
* data buffer number can be the same as the receive descriptor numbers.
|
||||
* But if you are polling receive frames please make sure the receive data
|
||||
* buffers are more than buffer descriptors to guarantee a good performance.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_rxbd_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg)
|
||||
{
|
||||
/* Check the input parameters*/
|
||||
if ((!enetIfPtr) || (!rxbdCfg))
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
enetIfPtr->macContextPtr->bufferdescSize = enet_hal_get_bd_size();
|
||||
|
||||
/* Initialize the bd status*/
|
||||
enetIfPtr->macContextPtr->isRxFull = false;
|
||||
|
||||
/* Initialize receive bd base address and current address*/
|
||||
enetIfPtr->macContextPtr->rxBdBasePtr = rxbdCfg->rxBdPtrAlign;
|
||||
enetIfPtr->macContextPtr->rxBdCurPtr = enetIfPtr->macContextPtr->rxBdBasePtr;
|
||||
enetIfPtr->macContextPtr->rxBdDirtyPtr = enetIfPtr->macContextPtr->rxBdBasePtr;
|
||||
enet_hal_set_rxbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->rxBdBasePtr));
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_txbd_init
|
||||
* Return Value: The execution status.
|
||||
* Description:Initialize the ENET transmit buffer descriptors.
|
||||
* This function prepare all of the transmit buffer descriptors.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_txbd_init(enet_dev_if_t * enetIfPtr, enet_txbd_config_t *txbdCfg)
|
||||
{
|
||||
/* Check the input parameters*/
|
||||
if ((!enetIfPtr) || (!txbdCfg))
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
/* Initialize the bd status*/
|
||||
enetIfPtr->macContextPtr->isTxFull = false;
|
||||
|
||||
/* Initialize transmit bd base address and current address*/
|
||||
enetIfPtr->macContextPtr->txBdBasePtr = txbdCfg->txBdPtrAlign;
|
||||
enetIfPtr->macContextPtr->txBdCurPtr = enetIfPtr->macContextPtr->txBdBasePtr;
|
||||
enetIfPtr->macContextPtr->txBdDirtyPtr = enetIfPtr->macContextPtr->txBdBasePtr;
|
||||
enet_hal_set_txbd_address(enetIfPtr->deviceNumber, (uint32_t)(enetIfPtr->macContextPtr->txBdBasePtr));
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_configure_fifo_accel
|
||||
* Return Value: The execution status.
|
||||
* Description: Configure the ENET FIFO and Accelerator.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_configure_fifo_accel(enet_dev_if_t * enetIfPtr)
|
||||
{
|
||||
enet_config_rx_fifo_t rxFifo;
|
||||
enet_config_tx_fifo_t txFifo;
|
||||
|
||||
/* Check the input parameters*/
|
||||
if (!enetIfPtr)
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
/* Initialize values that will not be initialized later on */
|
||||
rxFifo.rxEmpty = 0;
|
||||
rxFifo.rxFull = 0;
|
||||
txFifo.isStoreForwardEnabled = 0;
|
||||
txFifo.txFifoWrite = 0;
|
||||
txFifo.txEmpty = 0;
|
||||
|
||||
/* Configure tx/rx accelerator*/
|
||||
if (enetIfPtr->macCfgPtr->isRxAccelEnabled)
|
||||
{
|
||||
enet_hal_config_rx_accelerator(enetIfPtr->deviceNumber,
|
||||
(enet_config_rx_accelerator_t *)&(enetIfPtr->macCfgPtr->rxAcceler));
|
||||
if ((enetIfPtr->macCfgPtr->rxAcceler.isIpcheckEnabled) || (enetIfPtr->macCfgPtr->rxAcceler.isProtocolCheckEnabled))
|
||||
{
|
||||
rxFifo.rxFull = 0;
|
||||
}
|
||||
}
|
||||
if (enetIfPtr->macCfgPtr->isTxAccelEnabled)
|
||||
{
|
||||
enet_hal_config_tx_accelerator(enetIfPtr->deviceNumber,
|
||||
(enet_config_tx_accelerator_t *)&(enetIfPtr->macCfgPtr->txAcceler));
|
||||
if ((enetIfPtr->macCfgPtr->txAcceler.isIpCheckEnabled) || (enetIfPtr->macCfgPtr->txAcceler.isProtocolCheckEnabled))
|
||||
{
|
||||
txFifo.isStoreForwardEnabled = 1;
|
||||
}
|
||||
}
|
||||
if (enetIfPtr->macCfgPtr->isStoreAndFwEnabled)
|
||||
{
|
||||
rxFifo.rxFull = 0;
|
||||
txFifo.isStoreForwardEnabled = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Set TFWR value if STRFWD is not being used */
|
||||
if (txFifo.isStoreForwardEnabled == 1)
|
||||
txFifo.txFifoWrite = 0;
|
||||
else
|
||||
/* TFWR value is a trade-off between transmit latency and risk of transmit FIFO underrun due to contention for the system bus
|
||||
TFWR = 15 means transmission will begin once 960 bytes has been written to the Tx FIFO (for frames larger than 960 bytes)
|
||||
See Section 45.4.18 - Transmit FIFO Watermark Register of the K64F Reference Manual for details */
|
||||
txFifo.txFifoWrite = 15;
|
||||
|
||||
/* Configure tx/rx FIFO with default value*/
|
||||
rxFifo.rxAlmostEmpty = 4;
|
||||
rxFifo.rxAlmostFull = 4;
|
||||
txFifo.txAlmostEmpty = 4;
|
||||
txFifo.txAlmostFull = 8;
|
||||
enet_hal_config_rx_fifo(enetIfPtr->deviceNumber, &rxFifo);
|
||||
enet_hal_config_tx_fifo(enetIfPtr->deviceNumber, &txFifo);
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_configure_controller
|
||||
* Return Value: The execution status.
|
||||
* Description: Configure the ENET controller with the basic configuration.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_configure_controller(enet_dev_if_t * enetIfPtr)
|
||||
{
|
||||
uint32_t macCtlCfg;
|
||||
|
||||
/* Check the input parameters*/
|
||||
if (enetIfPtr == NULL)
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
macCtlCfg = enetIfPtr->macCfgPtr->macCtlConfigure;
|
||||
/* Configure rmii/mii interface*/
|
||||
enet_hal_config_rmii(enetIfPtr->deviceNumber, enetIfPtr->macCfgPtr->rmiiCfgMode,
|
||||
enetIfPtr->macCfgPtr->speed, enetIfPtr->macCfgPtr->duplex, false,
|
||||
(macCtlCfg & kEnetRxMiiLoopback));
|
||||
/* Configure receive buffer size*/
|
||||
if (enetIfPtr->macCfgPtr->isVlanEnabled)
|
||||
{
|
||||
enetIfPtr->maxFrameSize = kEnetMaxFrameVlanSize;
|
||||
enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
|
||||
enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameVlanSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
enetIfPtr->maxFrameSize = kEnetMaxFrameSize;
|
||||
enet_hal_set_rx_max_size(enetIfPtr->deviceNumber,
|
||||
enetIfPtr->macContextPtr->rxBufferSizeAligned, kEnetMaxFrameSize);
|
||||
}
|
||||
|
||||
/* Set receive controller promiscuous */
|
||||
enet_hal_config_promiscuous(enetIfPtr->deviceNumber, macCtlCfg & kEnetRxPromiscuousEnable);
|
||||
/* Set receive flow control*/
|
||||
enet_hal_enable_flowcontrol(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxFlowControlEnable));
|
||||
/* Set received PAUSE frames are forwarded/terminated*/
|
||||
enet_hal_enable_pauseforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPauseFwdEnable));
|
||||
/* Set receive broadcast frame reject*/
|
||||
enet_hal_enable_broadcastreject(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxBcRejectEnable));
|
||||
/* Set padding is removed from the received frame*/
|
||||
enet_hal_enable_padremove(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxPadRemoveEnable));
|
||||
/* Set the crc of the received frame is stripped from the frame*/
|
||||
enet_hal_enable_rxcrcforward(enetIfPtr->deviceNumber, (macCtlCfg & kEnetRxCrcFwdEnable));
|
||||
/* Set receive payload length check*/
|
||||
enet_hal_enable_payloadcheck(enetIfPtr->deviceNumber, (macCtlCfg & kEnetPayloadlenCheckEnable));
|
||||
/* Set control sleep mode*/
|
||||
enet_hal_enable_sleep(enetIfPtr->deviceNumber, (macCtlCfg & kEnetSleepModeEnable));
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_mac_init
|
||||
* Return Value: The execution status.
|
||||
* Description:Initialize the ENET device with the basic configuration
|
||||
* When ENET is used, this function need to be called by the NET initialize
|
||||
* interface.
|
||||
*END*********************************************************************/
|
||||
uint32_t enet_mac_init(enet_dev_if_t * enetIfPtr, enet_rxbd_config_t *rxbdCfg,
|
||||
enet_txbd_config_t *txbdCfg)
|
||||
{
|
||||
uint32_t timeOut = 0;
|
||||
uint32_t devNumber, result = 0;
|
||||
|
||||
/* Check the input parameters*/
|
||||
if (enetIfPtr == NULL)
|
||||
{
|
||||
return kStatus_ENET_InvalidInput;
|
||||
}
|
||||
|
||||
/* Get device number and check the parameter*/
|
||||
devNumber = enetIfPtr->deviceNumber;
|
||||
|
||||
/* Store the global ENET structure for ISR input parameters */
|
||||
enetIfHandle = enetIfPtr;
|
||||
|
||||
/* Turn on ENET module clock gate */
|
||||
CLOCK_SYS_EnableEnetClock(0U);
|
||||
|
||||
/* Reset ENET mac*/
|
||||
enet_hal_reset_ethernet(devNumber);
|
||||
while ((!enet_hal_is_reset_completed(devNumber)) && (timeOut < kEnetMaxTimeout))
|
||||
{
|
||||
time_delay(1);
|
||||
timeOut++;
|
||||
}
|
||||
|
||||
/* Check out if timeout*/
|
||||
if (timeOut == kEnetMaxTimeout)
|
||||
{
|
||||
return kStatus_ENET_TimeOut;
|
||||
}
|
||||
|
||||
/* Disable all ENET mac interrupt and Clear all interrupt events*/
|
||||
enet_hal_config_interrupt(devNumber, kEnetAllInterrupt, false);
|
||||
enet_hal_clear_interrupt(devNumber, kEnetAllInterrupt);
|
||||
|
||||
/* Program this station's physical address*/
|
||||
enet_hal_set_mac_address(devNumber, enetIfPtr->macCfgPtr->macAddr);
|
||||
|
||||
/* Clear group and individual hash register*/
|
||||
enet_hal_set_group_hashtable(devNumber, 0, kEnetSpecialAddressInit);
|
||||
enet_hal_set_individual_hashtable(devNumber, 0, kEnetSpecialAddressInit);
|
||||
|
||||
/* Configure mac controller*/
|
||||
result = enet_mac_configure_controller(enetIfPtr);
|
||||
if(result != kStatus_ENET_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
/* Clear mib zero counters*/
|
||||
enet_hal_clear_mib(devNumber, true);
|
||||
|
||||
/* Initialize FIFO and accelerator*/
|
||||
result = enet_mac_configure_fifo_accel(enetIfPtr);
|
||||
if(result != kStatus_ENET_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
/* Initialize receive buffer descriptors*/
|
||||
result = enet_mac_rxbd_init(enetIfPtr, rxbdCfg);
|
||||
if(result != kStatus_ENET_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
/* Initialize transmit buffer descriptors*/
|
||||
result = enet_mac_txbd_init(enetIfPtr, txbdCfg);
|
||||
if(result != kStatus_ENET_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
/* Initialize rmii/mii interface*/
|
||||
result = enet_mac_mii_init(enetIfPtr);
|
||||
if (result != kStatus_ENET_Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return kStatus_ENET_Success;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
|
||||
#include "fsl_port_hal.h"
|
||||
#include "fsl_clock_manager.h"
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_sim_hal.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Code
|
||||
******************************************************************************/
|
||||
void k64f_init_eth_hardware(void)
|
||||
{
|
||||
uint8_t count;
|
||||
|
||||
/* Disable the mpu*/
|
||||
BW_MPU_CESR_VLD(MPU_BASE, 0);
|
||||
|
||||
/* Open POTR clock gate*/
|
||||
for (count = 0; count < HW_PORT_INSTANCE_COUNT; count++)
|
||||
{
|
||||
CLOCK_SYS_EnablePortClock(count);
|
||||
}
|
||||
|
||||
/* Configure gpio*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 12, kPortMuxAlt4); /*!< ENET RMII0_RXD1/MII0_RXD1*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 13, kPortMuxAlt4); /*!< ENET RMII0_RXD0/MII0_RXD0*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 14, kPortMuxAlt4); /*!< ENET RMII0_CRS_DV/MII0_RXDV*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 15, kPortMuxAlt4); /*!< ENET RMII0_TXEN/MII0_TXEN*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 16, kPortMuxAlt4); /*!< ENET RMII0_TXD0/MII0_TXD0*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 17, kPortMuxAlt4); /*!< ENET RMII0_TXD01/MII0_TXD1*/
|
||||
PORT_HAL_SetMuxMode(PORTB_BASE, 0, kPortMuxAlt4); /*!< ENET RMII0_MDIO/MII0_MDIO*/
|
||||
PORT_HAL_SetOpenDrainCmd(PORTB_BASE,0, true); /*!< ENET RMII0_MDC/MII0_MDC*/
|
||||
|
||||
// Added for FRDM-K64F
|
||||
PORT_HAL_SetPullMode(PORTB_BASE, 0, kPortPullUp);
|
||||
PORT_HAL_SetPullCmd(PORTB_BASE, 0, true);
|
||||
|
||||
PORT_HAL_SetMuxMode(PORTB_BASE, 1, kPortMuxAlt4);
|
||||
/* Configure GPIO for MII interface */
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 9, kPortMuxAlt4); /*!< ENET MII0_RXD3*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 10, kPortMuxAlt4); /*!< ENET MII0_RXD2*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 11, kPortMuxAlt4); /*!< ENET MII0_RXCLK*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 24, kPortMuxAlt4); /*!< ENET MII0_TXD2*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 25, kPortMuxAlt4); /*!< ENET MII0_TXCLK*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 26, kPortMuxAlt4); /*!< ENET MII0_TXD3*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 27, kPortMuxAlt4); /*!< ENET MII0_CRS*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 28, kPortMuxAlt4); /*!< ENET MII0_TXER*/
|
||||
PORT_HAL_SetMuxMode(PORTA_BASE, 29, kPortMuxAlt4); /*!< ENET MII0_COL*/
|
||||
#if FSL_FEATURE_ENET_SUPPORT_PTP
|
||||
PORT_HAL_SetMuxMode(PORTC_BASE, (16 + ENET_TIMER_CHANNEL_NUM), kPortMuxAlt4); /* ENET ENET0_1588_TMR0*/
|
||||
PORT_HAL_SetDriveStrengthMode(PORTC_BASE, (16 + ENET_TIMER_CHANNEL_NUM), kPortHighDriveStrength);
|
||||
#endif
|
||||
|
||||
/* Open ENET clock gate*/
|
||||
CLOCK_SYS_EnableEnetClock( 0U);
|
||||
|
||||
/* Select the ptp timer outclk*/
|
||||
CLOCK_HAL_SetSource(g_simBaseAddr[0], kClockTimeSrc, 2);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* EOF
|
||||
******************************************************************************/
|
||||
|
||||
|
|
@ -0,0 +1,885 @@
|
|||
#include "lwip/opt.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "netif/ppp_oe.h"
|
||||
|
||||
#include "eth_arch.h"
|
||||
#include "sys_arch.h"
|
||||
|
||||
#include "fsl_enet_driver.h"
|
||||
#include "fsl_enet_hal.h"
|
||||
#include "fsl_device_registers.h"
|
||||
#include "fsl_phy_driver.h"
|
||||
#include "fsl_interrupt_manager.h"
|
||||
#include "k64f_emac_config.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mbed_interface.h"
|
||||
|
||||
extern IRQn_Type enet_irq_ids[HW_ENET_INSTANCE_COUNT][FSL_FEATURE_ENET_INTERRUPT_COUNT];
|
||||
extern uint8_t enetIntMap[kEnetIntNum];
|
||||
extern void *enetIfHandle;
|
||||
|
||||
/********************************************************************************
|
||||
* Internal data
|
||||
********************************************************************************/
|
||||
|
||||
extern void k64f_init_eth_hardware(void);
|
||||
|
||||
/* K64F EMAC driver data structure */
|
||||
struct k64f_enetdata {
|
||||
struct netif *netif; /**< Reference back to LWIP parent netif */
|
||||
sys_sem_t RxReadySem; /**< RX packet ready semaphore */
|
||||
sys_sem_t TxCleanSem; /**< TX cleanup thread wakeup semaphore */
|
||||
sys_mutex_t TXLockMutex; /**< TX critical section mutex */
|
||||
sys_sem_t xTXDCountSem; /**< TX free buffer counting semaphore */
|
||||
volatile u32_t rx_free_descs; /**< Count of free RX descriptors */
|
||||
struct pbuf *rxb[ENET_RX_RING_LEN]; /**< RX pbuf pointer list, zero-copy mode */
|
||||
uint8_t *rx_desc_start_addr; /**< RX descriptor start address */
|
||||
uint8_t *tx_desc_start_addr; /**< TX descriptor start address */
|
||||
uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */
|
||||
uint8_t rx_fill_index; /**< RX ring fill index */
|
||||
struct pbuf *txb[ENET_TX_RING_LEN]; /**< TX pbuf pointer list, zero-copy mode */
|
||||
void *txb_aligned[ENET_TX_RING_LEN]; /**< TX aligned buffers (if needed) */
|
||||
};
|
||||
|
||||
static struct k64f_enetdata k64f_enetdata;
|
||||
|
||||
static enet_dev_if_t enetDevIf[HW_ENET_INSTANCE_COUNT];
|
||||
static enet_mac_config_t g_enetMacCfg[HW_ENET_INSTANCE_COUNT] =
|
||||
{
|
||||
{
|
||||
ENET_ETH_MAX_FLEN , /*!< enet receive buffer size*/
|
||||
ENET_RX_LARGE_BUFFER_NUM, /*!< enet large receive buffer number*/
|
||||
ENET_RX_RING_LEN, /*!< enet receive bd number*/
|
||||
ENET_TX_RING_LEN, /*!< enet transmit bd number*/
|
||||
{0}, /*!< enet mac address*/
|
||||
kEnetCfgRmii, /*!< enet rmii interface*/
|
||||
kEnetCfgSpeed100M, /*!< enet rmii 100M*/
|
||||
kEnetCfgFullDuplex, /*!< enet rmii Full- duplex*/
|
||||
/*!< enet mac control flag recommended to use enet_mac_control_flag_t
|
||||
we send frame with crc so receive crc forward for data length check test*/
|
||||
kEnetRxCrcFwdEnable | kEnetRxFlowControlEnable,
|
||||
true, /*!< enet txaccelerator enabled*/
|
||||
true, /*!< enet rxaccelerator enabled*/
|
||||
false, /*!< enet store and forward*/
|
||||
{false, false, true, false, true}, /*!< enet rxaccelerator config*/
|
||||
{false, false, true}, /*!< enet txaccelerator config*/
|
||||
true, /*!< vlan frame support*/
|
||||
true, /*!< phy auto discover*/
|
||||
ENET_MII_CLOCK, /*!< enet MDC clock*/
|
||||
},
|
||||
};
|
||||
|
||||
static enet_phy_config_t g_enetPhyCfg[HW_ENET_INSTANCE_COUNT] =
|
||||
{
|
||||
{0, false}
|
||||
};
|
||||
|
||||
/** \brief Driver transmit and receive thread priorities
|
||||
*
|
||||
* Thread priorities for receive thread and TX cleanup thread. Alter
|
||||
* to prioritize receive or transmit bandwidth. In a heavily loaded
|
||||
* system or with LEIP_DEBUG enabled, the priorities might be better
|
||||
* the same. */
|
||||
#define RX_PRIORITY (osPriorityNormal)
|
||||
#define TX_PRIORITY (osPriorityNormal)
|
||||
#define PHY_PRIORITY (osPriorityNormal)
|
||||
|
||||
/** \brief Debug output formatter lock define
|
||||
*
|
||||
* When using FreeRTOS and with LWIP_DEBUG enabled, enabling this
|
||||
* define will allow RX debug messages to not interleave with the
|
||||
* TX messages (so they are actually readable). Not enabling this
|
||||
* define when the system is under load will cause the output to
|
||||
* be unreadable. There is a small tradeoff in performance for this
|
||||
* so use it only for debug. */
|
||||
//#define LOCK_RX_THREAD
|
||||
|
||||
/** \brief Signal used for ethernet ISR to signal packet_rx() thread.
|
||||
*/
|
||||
#define RX_SIGNAL 1
|
||||
|
||||
// K64F-specific macros
|
||||
#define RX_PBUF_AUTO_INDEX (-1)
|
||||
|
||||
/********************************************************************************
|
||||
* Buffer management
|
||||
********************************************************************************/
|
||||
|
||||
/** \brief Queues a pbuf into the RX descriptor list
|
||||
*
|
||||
* \param[in] k64f_enet Pointer to the drvier data structure
|
||||
* \param[in] p Pointer to pbuf to queue
|
||||
* \param[in] bidx Index to queue into
|
||||
*/
|
||||
static void k64f_rxqueue_pbuf(struct k64f_enetdata *k64f_enet, struct pbuf *p, int bidx)
|
||||
{
|
||||
enet_bd_struct_t *start = (enet_bd_struct_t *)k64f_enet->rx_desc_start_addr;
|
||||
int idx;
|
||||
|
||||
/* Get next free descriptor index */
|
||||
if (bidx == RX_PBUF_AUTO_INDEX)
|
||||
idx = k64f_enet->rx_fill_index;
|
||||
else
|
||||
idx = bidx;
|
||||
|
||||
/* Setup descriptor and clear statuses */
|
||||
enet_hal_init_rxbds(start + idx, (uint8_t*)p->payload, idx == ENET_RX_RING_LEN - 1);
|
||||
|
||||
/* Save pbuf pointer for push to network layer later */
|
||||
k64f_enet->rxb[idx] = p;
|
||||
|
||||
/* Wrap at end of descriptor list */
|
||||
idx = (idx + 1) % ENET_RX_RING_LEN;
|
||||
|
||||
/* Queue descriptor(s) */
|
||||
k64f_enet->rx_free_descs -= 1;
|
||||
|
||||
if (bidx == RX_PBUF_AUTO_INDEX)
|
||||
k64f_enet->rx_fill_index = idx;
|
||||
|
||||
enet_hal_active_rxbd(BOARD_DEBUG_ENET_INSTANCE_ADDR);
|
||||
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64f_rxqueue_pbuf: pbuf packet queued: %p (free desc=%d)\n", p,
|
||||
k64f_enet->rx_free_descs));
|
||||
}
|
||||
|
||||
/** \brief Attempt to allocate and requeue a new pbuf for RX
|
||||
*
|
||||
* \param[in] netif Pointer to the netif structure
|
||||
* \returns number of queued packets
|
||||
*/
|
||||
s32_t k64f_rx_queue(struct netif *netif, int idx)
|
||||
{
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
struct pbuf *p;
|
||||
int queued = 0;
|
||||
|
||||
/* Attempt to requeue as many packets as possible */
|
||||
while (k64f_enet->rx_free_descs > 0) {
|
||||
/* Allocate a pbuf from the pool. We need to allocate at the
|
||||
maximum size as we don't know the size of the yet to be
|
||||
received packet. */
|
||||
p = pbuf_alloc(PBUF_RAW, enetIfPtr->macCfgPtr->rxBufferSize + RX_BUF_ALIGNMENT, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64_rx_queue: could not allocate RX pbuf (free desc=%d)\n",
|
||||
k64f_enet->rx_free_descs));
|
||||
return queued;
|
||||
}
|
||||
/* K64F note: the next line ensures that the RX buffer is properly aligned for the K64F
|
||||
RX descriptors (16 bytes alignment). However, by doing so, we're effectively changing
|
||||
a data structure which is internal to lwIP. This might not prove to be a good idea
|
||||
in the long run, but a better fix would probably involve modifying lwIP itself */
|
||||
p->payload = (void*)ENET_ALIGN((uint32_t)p->payload, RX_BUF_ALIGNMENT);
|
||||
|
||||
/* pbufs allocated from the RAM pool should be non-chained. */
|
||||
LWIP_ASSERT("k64f_rx_queue: pbuf is not contiguous (chained)", pbuf_clen(p) <= 1);
|
||||
|
||||
/* Queue packet */
|
||||
k64f_rxqueue_pbuf(k64f_enet, p, idx);
|
||||
queued++;
|
||||
}
|
||||
|
||||
return queued;
|
||||
}
|
||||
|
||||
/** \brief Sets up the RX descriptor ring buffers.
|
||||
*
|
||||
* This function sets up the descriptor list used for receive packets.
|
||||
*
|
||||
* \param[in] netif Pointer to driver data structure
|
||||
* \returns ERR_MEM if out of memory, ERR_OK otherwise
|
||||
*/
|
||||
static err_t k64f_rx_setup(struct netif *netif, enet_rxbd_config_t *rxbdCfg) {
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
uint8_t *rxBdPtr;
|
||||
uint32_t rxBufferSizeAligned;
|
||||
|
||||
// Allocate RX descriptors
|
||||
rxBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->rxBdNumber + ENET_BD_ALIGNMENT);
|
||||
if(!rxBdPtr)
|
||||
return ERR_MEM;
|
||||
k64f_enet->rx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)rxBdPtr, ENET_BD_ALIGNMENT);
|
||||
k64f_enet->rx_free_descs = enetIfPtr->macCfgPtr->rxBdNumber;
|
||||
k64f_enet->rx_fill_index = 0;
|
||||
|
||||
rxBufferSizeAligned = ENET_ALIGN(enetIfPtr->macCfgPtr->rxBufferSize, ENET_RX_BUFFER_ALIGNMENT);
|
||||
enetIfPtr->macContextPtr->rxBufferSizeAligned = rxBufferSizeAligned;
|
||||
rxbdCfg->rxBdPtrAlign = k64f_enet->rx_desc_start_addr;
|
||||
rxbdCfg->rxBdNum = enetIfPtr->macCfgPtr->rxBdNumber;
|
||||
rxbdCfg->rxBufferNum = enetIfPtr->macCfgPtr->rxBdNumber;
|
||||
|
||||
k64f_rx_queue(netif, RX_PBUF_AUTO_INDEX);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/** \brief Sets up the TX descriptor ring buffers.
|
||||
*
|
||||
* This function sets up the descriptor list used for transmit packets.
|
||||
*
|
||||
* \param[in] netif Pointer to driver data structure
|
||||
* \returns ERR_MEM if out of memory, ERR_OK otherwise
|
||||
*/
|
||||
static err_t k64f_tx_setup(struct netif *netif, enet_txbd_config_t *txbdCfg) {
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
enet_dev_if_t *enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
uint8_t *txBdPtr;
|
||||
|
||||
// Allocate TX descriptors
|
||||
txBdPtr = (uint8_t *)calloc(1, enet_hal_get_bd_size() * enetIfPtr->macCfgPtr->txBdNumber + ENET_BD_ALIGNMENT);
|
||||
if(!txBdPtr)
|
||||
return ERR_MEM;
|
||||
|
||||
k64f_enet->tx_desc_start_addr = (uint8_t *)ENET_ALIGN((uint32_t)txBdPtr, ENET_BD_ALIGNMENT);
|
||||
k64f_enet->tx_consume_index = k64f_enet->tx_produce_index = 0;
|
||||
|
||||
txbdCfg->txBdPtrAlign = k64f_enet->tx_desc_start_addr;
|
||||
txbdCfg->txBufferNum = enetIfPtr->macCfgPtr->txBdNumber;
|
||||
txbdCfg->txBufferSizeAlign = ENET_ALIGN(enetIfPtr->maxFrameSize, ENET_TX_BUFFER_ALIGNMENT);
|
||||
|
||||
// Make the TX descriptor ring circular
|
||||
enet_hal_init_txbds(k64f_enet->tx_desc_start_addr + enet_hal_get_bd_size() * (ENET_TX_RING_LEN - 1), 1);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/** \brief Free TX buffers that are complete
|
||||
*
|
||||
* \param[in] k64f_enet Pointer to driver data structure
|
||||
*/
|
||||
static void k64f_tx_reclaim(struct k64f_enetdata *k64f_enet)
|
||||
{
|
||||
uint8_t i;
|
||||
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)k64f_enet->tx_desc_start_addr;
|
||||
|
||||
/* Get exclusive access */
|
||||
sys_mutex_lock(&k64f_enet->TXLockMutex);
|
||||
|
||||
// Traverse all descriptors, looking for the ones modified by the uDMA
|
||||
i = k64f_enet->tx_consume_index;
|
||||
while(i != k64f_enet->tx_produce_index && !(bdPtr[i].control & kEnetTxBdReady)) {
|
||||
if (k64f_enet->txb_aligned[i]) {
|
||||
free(k64f_enet->txb_aligned[i]);
|
||||
k64f_enet->txb_aligned[i] = NULL;
|
||||
} else if (k64f_enet->txb[i]) {
|
||||
pbuf_free(k64f_enet->txb[i]);
|
||||
k64f_enet->txb[i] = NULL;
|
||||
}
|
||||
osSemaphoreRelease(k64f_enet->xTXDCountSem.id);
|
||||
bdPtr[i].controlExtend2 &= ~TX_DESC_UPDATED_MASK;
|
||||
i = (i + 1) % ENET_TX_RING_LEN;
|
||||
}
|
||||
k64f_enet->tx_consume_index = i;
|
||||
|
||||
/* Restore access */
|
||||
sys_mutex_unlock(&k64f_enet->TXLockMutex);
|
||||
}
|
||||
|
||||
/** \brief Low level init of the MAC and PHY.
|
||||
*
|
||||
* \param[in] netif Pointer to LWIP netif structure
|
||||
*/
|
||||
static err_t low_level_init(struct netif *netif)
|
||||
{
|
||||
enet_dev_if_t * enetIfPtr;
|
||||
uint32_t device = BOARD_DEBUG_ENET_INSTANCE_ADDR;
|
||||
enet_rxbd_config_t rxbdCfg;
|
||||
enet_txbd_config_t txbdCfg;
|
||||
enet_phy_speed_t phy_speed;
|
||||
enet_phy_duplex_t phy_duplex;
|
||||
|
||||
k64f_init_eth_hardware();
|
||||
|
||||
/* Initialize device*/
|
||||
enetIfPtr = (enet_dev_if_t *)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
enetIfPtr->deviceNumber = device;
|
||||
enetIfPtr->macCfgPtr = &g_enetMacCfg[BOARD_DEBUG_ENET_INSTANCE];
|
||||
enetIfPtr->phyCfgPtr = &g_enetPhyCfg[BOARD_DEBUG_ENET_INSTANCE];
|
||||
enetIfPtr->macApiPtr = &g_enetMacApi;
|
||||
enetIfPtr->phyApiPtr = (void *)&g_enetPhyApi;
|
||||
memcpy(enetIfPtr->macCfgPtr->macAddr, (char*)netif->hwaddr, kEnetMacAddrLen);
|
||||
|
||||
/* Allocate buffer for ENET mac context*/
|
||||
enetIfPtr->macContextPtr = (enet_mac_context_t *)calloc(1, sizeof(enet_mac_context_t));
|
||||
if (!enetIfPtr->macContextPtr) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
/* Initialize enet buffers*/
|
||||
if(k64f_rx_setup(netif, &rxbdCfg) != ERR_OK) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
/* Initialize enet buffers*/
|
||||
if(k64f_tx_setup(netif, &txbdCfg) != ERR_OK) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
/* Initialize enet module*/
|
||||
if (enet_mac_init(enetIfPtr, &rxbdCfg, &txbdCfg) == kStatus_ENET_Success)
|
||||
{
|
||||
/* Initialize PHY*/
|
||||
if (enetIfPtr->macCfgPtr->isPhyAutoDiscover) {
|
||||
if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_auto_discover(enetIfPtr) != kStatus_PHY_Success)
|
||||
return ERR_IF;
|
||||
}
|
||||
if (((enet_phy_api_t *)(enetIfPtr->phyApiPtr))->phy_init(enetIfPtr) != kStatus_PHY_Success)
|
||||
return ERR_IF;
|
||||
|
||||
enetIfPtr->isInitialized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODOETH: cleanup memory
|
||||
return ERR_IF;
|
||||
}
|
||||
|
||||
/* Get link information from PHY */
|
||||
phy_get_link_speed(enetIfPtr, &phy_speed);
|
||||
phy_get_link_duplex(enetIfPtr, &phy_duplex);
|
||||
BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, phy_speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
|
||||
BW_ENET_TCR_FDEN(enetIfPtr->deviceNumber, phy_duplex == kEnetFullDuplex ? kEnetCfgFullDuplex : kEnetCfgHalfDuplex);
|
||||
|
||||
/* Enable Ethernet module*/
|
||||
enet_hal_config_ethernet(BOARD_DEBUG_ENET_INSTANCE_ADDR, true, true);
|
||||
|
||||
/* Active Receive buffer descriptor must be done after module enable*/
|
||||
enet_hal_active_rxbd(enetIfPtr->deviceNumber);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* LWIP port
|
||||
********************************************************************************/
|
||||
|
||||
/** \brief Ethernet receive interrupt handler
|
||||
*
|
||||
* This function handles the receive interrupt of K64F.
|
||||
*/
|
||||
void enet_mac_rx_isr(void *enetIfPtr)
|
||||
{
|
||||
/* Clear interrupt */
|
||||
enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetRxFrameInterrupt);
|
||||
sys_sem_signal(&k64f_enetdata.RxReadySem);
|
||||
}
|
||||
|
||||
void enet_mac_tx_isr(void *enetIfPtr)
|
||||
{
|
||||
/*Clear interrupt*/
|
||||
enet_hal_clear_interrupt(((enet_dev_if_t *)enetIfPtr)->deviceNumber, kEnetTxFrameInterrupt);
|
||||
sys_sem_signal(&k64f_enetdata.TxCleanSem);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is the ethernet packet send function. It calls
|
||||
* etharp_output after checking link status.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure for this enetif
|
||||
* \param[in] q Pointer to pbug to send
|
||||
* \param[in] ipaddr IP address
|
||||
* \return ERR_OK or error code
|
||||
*/
|
||||
err_t k64f_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
|
||||
{
|
||||
/* Only send packet is link is up */
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP)
|
||||
return etharp_output(netif, q, ipaddr);
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
/** \brief Allocates a pbuf and returns the data from the incoming packet.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure
|
||||
* \param[in] idx index of packet to be read
|
||||
* \return a pbuf filled with the received packet (including MAC header)
|
||||
*/
|
||||
static struct pbuf *k64f_low_level_input(struct netif *netif, int idx)
|
||||
{
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
|
||||
struct pbuf *p = NULL;
|
||||
u32_t length = 0, orig_length;
|
||||
const u16_t err_mask = kEnetRxBdTrunc | kEnetRxBdCrc | kEnetRxBdNoOctet | kEnetRxBdLengthViolation;
|
||||
|
||||
#ifdef LOCK_RX_THREAD
|
||||
/* Get exclusive access */
|
||||
sys_mutex_lock(&k64f_enet->TXLockMutex);
|
||||
#endif
|
||||
|
||||
/* Determine if a frame has been received */
|
||||
if ((bdPtr[idx].control & err_mask) != 0) {
|
||||
#if LINK_STATS
|
||||
if ((bdPtr[idx].control & kEnetRxBdLengthViolation) != 0)
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
else
|
||||
LINK_STATS_INC(link.chkerr);
|
||||
#endif
|
||||
LINK_STATS_INC(link.drop);
|
||||
|
||||
/* Re-queue the same buffer */
|
||||
k64f_enet->rx_free_descs++;
|
||||
p = k64f_enet->rxb[idx];
|
||||
k64f_enet->rxb[idx] = NULL;
|
||||
k64f_rxqueue_pbuf(k64f_enet, p, idx);
|
||||
p = NULL;
|
||||
} else {
|
||||
/* A packet is waiting, get length */
|
||||
length = enet_hal_get_bd_length(bdPtr + idx);
|
||||
|
||||
/* Zero-copy */
|
||||
p = k64f_enet->rxb[idx];
|
||||
orig_length = p->len;
|
||||
p->len = (u16_t) length;
|
||||
|
||||
/* Free pbuf from descriptor */
|
||||
k64f_enet->rxb[idx] = NULL;
|
||||
k64f_enet->rx_free_descs++;
|
||||
|
||||
/* Attempt to queue new buffer */
|
||||
if (k64f_rx_queue(netif, idx) == 0) {
|
||||
/* Drop frame (out of memory) */
|
||||
LINK_STATS_INC(link.drop);
|
||||
|
||||
/* Re-queue the same buffer */
|
||||
p->len = orig_length;
|
||||
k64f_rxqueue_pbuf(k64f_enet, p, idx);
|
||||
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64f_low_level_input: Packet index %d dropped for OOM\n",
|
||||
idx));
|
||||
#ifdef LOCK_RX_THREAD
|
||||
sys_mutex_unlock(&k64f_enet->TXLockMutex);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64f_low_level_input: Packet received: %p, size %d (index=%d)\n",
|
||||
p, length, idx));
|
||||
|
||||
/* Save size */
|
||||
p->tot_len = (u16_t) length;
|
||||
LINK_STATS_INC(link.recv);
|
||||
}
|
||||
|
||||
#ifdef LOCK_RX_THREAD
|
||||
sys_mutex_unlock(&k64f_enet->TXLockMutex);
|
||||
#endif
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/** \brief Attempt to read a packet from the EMAC interface.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure
|
||||
* \param[in] idx index of packet to be read
|
||||
*/
|
||||
void k64f_enetif_input(struct netif *netif, int idx)
|
||||
{
|
||||
struct eth_hdr *ethhdr;
|
||||
struct pbuf *p;
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
p = k64f_low_level_input(netif, idx);
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
ethhdr = (struct eth_hdr*)p->payload;
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
case ETHTYPE_IP:
|
||||
case ETHTYPE_ARP:
|
||||
#if PPPOE_SUPPORT
|
||||
case ETHTYPE_PPPOEDISC:
|
||||
case ETHTYPE_PPPOE:
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("k64f_enetif_input: IP input error\n"));
|
||||
/* Free buffer */
|
||||
pbuf_free(p);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Return buffer */
|
||||
pbuf_free(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Packet reception task
|
||||
*
|
||||
* This task is called when a packet is received. It will
|
||||
* pass the packet to the LWIP core.
|
||||
*
|
||||
* \param[in] pvParameters pointer to the interface data
|
||||
*/
|
||||
static void packet_rx(void* pvParameters) {
|
||||
struct k64f_enetdata *k64f_enet = pvParameters;
|
||||
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t*)k64f_enet->rx_desc_start_addr;
|
||||
int idx = 0;
|
||||
|
||||
while (1) {
|
||||
/* Wait for receive task to wakeup */
|
||||
sys_arch_sem_wait(&k64f_enet->RxReadySem, 0);
|
||||
|
||||
if ((bdPtr[idx].control & kEnetRxBdEmpty) == 0) {
|
||||
k64f_enetif_input(k64f_enet->netif, idx);
|
||||
idx = (idx + 1) % ENET_RX_RING_LEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Transmit cleanup task
|
||||
*
|
||||
* This task is called when a transmit interrupt occurs and
|
||||
* reclaims the pbuf and descriptor used for the packet once
|
||||
* the packet has been transferred.
|
||||
*
|
||||
* \param[in] pvParameters pointer to the interface data
|
||||
*/
|
||||
static void packet_tx(void* pvParameters) {
|
||||
struct k64f_enetdata *k64f_enet = pvParameters;
|
||||
|
||||
while (1) {
|
||||
/* Wait for transmit cleanup task to wakeup */
|
||||
sys_arch_sem_wait(&k64f_enet->TxCleanSem, 0);
|
||||
// TODOETH: handle TX underrun?
|
||||
k64f_tx_reclaim(k64f_enet);
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Polls if an available TX descriptor is ready. Can be used to
|
||||
* determine if the low level transmit function will block.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure
|
||||
* \return 0 if no descriptors are read, or >0
|
||||
*/
|
||||
s32_t k64f_tx_ready(struct netif *netif)
|
||||
{
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
s32_t fb;
|
||||
u32_t idx, cidx;
|
||||
|
||||
cidx = k64f_enet->tx_consume_index;
|
||||
idx = k64f_enet->tx_produce_index;
|
||||
|
||||
/* Determine number of free buffers */
|
||||
if (idx == cidx)
|
||||
fb = ENET_TX_RING_LEN;
|
||||
else if (cidx > idx)
|
||||
fb = (ENET_TX_RING_LEN - 1) -
|
||||
((idx + ENET_TX_RING_LEN) - cidx);
|
||||
else
|
||||
fb = (ENET_TX_RING_LEN - 1) - (cidx - idx);
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
/*FUNCTION****************************************************************
|
||||
*
|
||||
* Function Name: enet_hal_update_txbds
|
||||
* Description: Update ENET transmit buffer descriptors.
|
||||
*END*********************************************************************/
|
||||
void k64f_update_txbds(struct k64f_enetdata *k64f_enet, int idx, uint8_t *buffer, uint16_t length, bool isLast)
|
||||
{
|
||||
volatile enet_bd_struct_t * bdPtr = (enet_bd_struct_t *)(k64f_enet->tx_desc_start_addr + idx * enet_hal_get_bd_size());
|
||||
|
||||
bdPtr->length = HTONS(length); /* Set data length*/
|
||||
bdPtr->buffer = (uint8_t *)HTONL((uint32_t)buffer); /* Set data buffer*/
|
||||
if (isLast)
|
||||
bdPtr->control |= kEnetTxBdLast;
|
||||
else
|
||||
bdPtr->control &= ~kEnetTxBdLast;
|
||||
bdPtr->controlExtend1 |= kEnetTxBdTxInterrupt;
|
||||
bdPtr->controlExtend2 &= ~TX_DESC_UPDATED_MASK; // descriptor not updated by DMA
|
||||
bdPtr->control |= kEnetTxBdTransmitCrc | kEnetTxBdReady;
|
||||
}
|
||||
|
||||
/** \brief Low level output of a packet. Never call this from an
|
||||
* interrupt context, as it may block until TX descriptors
|
||||
* become available.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure for this netif
|
||||
* \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
||||
* \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent
|
||||
*/
|
||||
static err_t k64f_low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct k64f_enetdata *k64f_enet = netif->state;
|
||||
struct pbuf *q;
|
||||
u32_t idx;
|
||||
s32_t dn;
|
||||
uint8_t *psend = NULL, *dst;
|
||||
|
||||
/* Get free TX buffer index */
|
||||
idx = k64f_enet->tx_produce_index;
|
||||
|
||||
/* Check the pbuf chain for payloads that are not 8-byte aligned.
|
||||
If found, a new properly aligned buffer needs to be allocated
|
||||
and the data copied there */
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
if (((u32_t)q->payload & (TX_BUF_ALIGNMENT - 1)) != 0)
|
||||
break;
|
||||
if (q != NULL) {
|
||||
// Allocate properly aligned buffer
|
||||
psend = (uint8_t*)malloc(p->tot_len);
|
||||
if (NULL == psend)
|
||||
return ERR_MEM;
|
||||
LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)psend & (TX_BUF_ALIGNMENT - 1)) == 0);
|
||||
for (q = p, dst = psend; q != NULL; q = q->next) {
|
||||
MEMCPY(dst, q->payload, q->len);
|
||||
dst += q->len;
|
||||
}
|
||||
k64f_enet->txb_aligned[idx] = psend;
|
||||
dn = 1;
|
||||
} else {
|
||||
k64f_enet->txb_aligned[idx] = NULL;
|
||||
dn = (s32_t) pbuf_clen(p);
|
||||
pbuf_ref(p);
|
||||
}
|
||||
|
||||
/* Wait until enough descriptors are available for the transfer. */
|
||||
/* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
|
||||
while (dn > k64f_tx_ready(netif))
|
||||
osSemaphoreWait(k64f_enet->xTXDCountSem.id, osWaitForever);
|
||||
|
||||
/* Get exclusive access */
|
||||
sys_mutex_lock(&k64f_enet->TXLockMutex);
|
||||
|
||||
/* Setup transfers */
|
||||
q = p;
|
||||
while (dn > 0) {
|
||||
dn--;
|
||||
if (psend != NULL) {
|
||||
k64f_update_txbds(k64f_enet, idx, psend, p->tot_len, 1);
|
||||
k64f_enet->txb[idx] = NULL;
|
||||
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64f_low_level_output: aligned packet(%p) sent"
|
||||
" size = %d (index=%d)\n", psend, p->tot_len, idx));
|
||||
} else {
|
||||
LWIP_ASSERT("k64f_low_level_output: buffer not properly aligned", ((u32_t)q->payload & 0x07) == 0);
|
||||
|
||||
/* Only save pointer to free on last descriptor */
|
||||
if (dn == 0) {
|
||||
/* Save size of packet and signal it's ready */
|
||||
k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 1);
|
||||
k64f_enet->txb[idx] = p;
|
||||
}
|
||||
else {
|
||||
/* Save size of packet, descriptor is not last */
|
||||
k64f_update_txbds(k64f_enet, idx, q->payload, q->len, 0);
|
||||
k64f_enet->txb[idx] = NULL;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
|
||||
("k64f_low_level_output: pbuf packet(%p) sent, chain#=%d,"
|
||||
" size = %d (index=%d)\n", q->payload, dn, q->len, idx));
|
||||
}
|
||||
|
||||
q = q->next;
|
||||
|
||||
idx = (idx + 1) % ENET_TX_RING_LEN;
|
||||
}
|
||||
|
||||
k64f_enet->tx_produce_index = idx;
|
||||
enet_hal_active_txbd(BOARD_DEBUG_ENET_INSTANCE_ADDR);
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
/* Restore access */
|
||||
sys_mutex_unlock(&k64f_enet->TXLockMutex);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* PHY task: monitor link
|
||||
*******************************************************************************/
|
||||
|
||||
#define PHY_TASK_PERIOD_MS 200
|
||||
#define STATE_UNKNOWN (-1)
|
||||
|
||||
typedef struct {
|
||||
int connected;
|
||||
enet_phy_speed_t speed;
|
||||
enet_phy_duplex_t duplex;
|
||||
} PHY_STATE;
|
||||
|
||||
int phy_link_status() {
|
||||
bool connection_status;
|
||||
enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
phy_get_link_status(enetIfPtr, &connection_status);
|
||||
return (int)connection_status;
|
||||
}
|
||||
|
||||
static void k64f_phy_task(void *data) {
|
||||
struct netif *netif = (struct netif*)data;
|
||||
bool connection_status;
|
||||
enet_dev_if_t * enetIfPtr = (enet_dev_if_t*)&enetDevIf[BOARD_DEBUG_ENET_INSTANCE];
|
||||
PHY_STATE crt_state = {STATE_UNKNOWN, (enet_phy_speed_t)STATE_UNKNOWN, (enet_phy_duplex_t)STATE_UNKNOWN};
|
||||
PHY_STATE prev_state;
|
||||
|
||||
prev_state = crt_state;
|
||||
while (true) {
|
||||
// Get current status
|
||||
phy_get_link_status(enetIfPtr, &connection_status);
|
||||
crt_state.connected = connection_status ? 1 : 0;
|
||||
phy_get_link_speed(enetIfPtr, &crt_state.speed);
|
||||
phy_get_link_duplex(enetIfPtr, &crt_state.duplex);
|
||||
|
||||
// Compare with previous state
|
||||
if (crt_state.connected != prev_state.connected) {
|
||||
if (crt_state.connected)
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
|
||||
else
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
}
|
||||
|
||||
if (crt_state.speed != prev_state.speed)
|
||||
BW_ENET_RCR_RMII_10T(enetIfPtr->deviceNumber, crt_state.speed == kEnetSpeed10M ? kEnetCfgSpeed10M : kEnetCfgSpeed100M);
|
||||
|
||||
// TODO: duplex change requires disable/enable of Ethernet interface, to be implemented
|
||||
|
||||
prev_state = crt_state;
|
||||
osDelay(PHY_TASK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called at the beginning of the program to set up the
|
||||
* network interface.
|
||||
*
|
||||
* This function should be passed as a parameter to netif_add().
|
||||
*
|
||||
* @param[in] netif the lwip network interface structure for this netif
|
||||
* @return ERR_OK if the loopif is initialized
|
||||
* ERR_MEM if private data couldn't be allocated
|
||||
* any other err_t on error
|
||||
*/
|
||||
err_t eth_arch_enetif_init(struct netif *netif)
|
||||
{
|
||||
err_t err;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||
|
||||
k64f_enetdata.netif = netif;
|
||||
|
||||
/* set MAC hardware address */
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
netif->hwaddr[0] = MBED_MAC_ADDR_0;
|
||||
netif->hwaddr[1] = MBED_MAC_ADDR_1;
|
||||
netif->hwaddr[2] = MBED_MAC_ADDR_2;
|
||||
netif->hwaddr[3] = MBED_MAC_ADDR_3;
|
||||
netif->hwaddr[4] = MBED_MAC_ADDR_4;
|
||||
netif->hwaddr[5] = MBED_MAC_ADDR_5;
|
||||
#else
|
||||
mbed_mac_address((char *)netif->hwaddr);
|
||||
#endif
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* device capabilities */
|
||||
// TODOETH: check if the flags are correct below
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
|
||||
|
||||
/* Initialize the hardware */
|
||||
netif->state = &k64f_enetdata;
|
||||
err = low_level_init(netif);
|
||||
if (err != ERR_OK)
|
||||
return err;
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwipk64f";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
|
||||
netif->output = k64f_etharp_output;
|
||||
netif->linkoutput = k64f_low_level_output;
|
||||
|
||||
/* CMSIS-RTOS, start tasks */
|
||||
#ifdef CMSIS_OS_RTX
|
||||
memset(k64f_enetdata.xTXDCountSem.data, 0, sizeof(k64f_enetdata.xTXDCountSem.data));
|
||||
k64f_enetdata.xTXDCountSem.def.semaphore = k64f_enetdata.xTXDCountSem.data;
|
||||
#endif
|
||||
k64f_enetdata.xTXDCountSem.id = osSemaphoreCreate(&k64f_enetdata.xTXDCountSem.def, ENET_TX_RING_LEN);
|
||||
|
||||
LWIP_ASSERT("xTXDCountSem creation error", (k64f_enetdata.xTXDCountSem.id != NULL));
|
||||
|
||||
err = sys_mutex_new(&k64f_enetdata.TXLockMutex);
|
||||
LWIP_ASSERT("TXLockMutex creation error", (err == ERR_OK));
|
||||
|
||||
/* Packet receive task */
|
||||
err = sys_sem_new(&k64f_enetdata.RxReadySem, 0);
|
||||
LWIP_ASSERT("RxReadySem creation error", (err == ERR_OK));
|
||||
sys_thread_new("receive_thread", packet_rx, netif->state, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY);
|
||||
|
||||
/* Transmit cleanup task */
|
||||
err = sys_sem_new(&k64f_enetdata.TxCleanSem, 0);
|
||||
LWIP_ASSERT("TxCleanSem creation error", (err == ERR_OK));
|
||||
sys_thread_new("txclean_thread", packet_tx, netif->state, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY);
|
||||
|
||||
/* PHY monitoring task */
|
||||
sys_thread_new("phy_thread", k64f_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_PRIORITY);
|
||||
|
||||
/* Allow the PHY task to detect the initial link state and set up the proper flags */
|
||||
osDelay(10);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void eth_arch_enable_interrupts(void) {
|
||||
enet_hal_config_interrupt(BOARD_DEBUG_ENET_INSTANCE_ADDR, (kEnetTxFrameInterrupt | kEnetRxFrameInterrupt), true);
|
||||
INT_SYS_EnableIRQ(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
|
||||
INT_SYS_EnableIRQ(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
|
||||
}
|
||||
|
||||
void eth_arch_disable_interrupts(void) {
|
||||
INT_SYS_DisableIRQ(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetRxfInt]]);
|
||||
INT_SYS_DisableIRQ(enet_irq_ids[BOARD_DEBUG_ENET_INSTANCE][enetIntMap[kEnetTxfInt]]);
|
||||
}
|
||||
|
||||
void ENET_Transmit_IRQHandler(void)
|
||||
{
|
||||
enet_mac_tx_isr(enetIfHandle);
|
||||
}
|
||||
|
||||
void ENET_Receive_IRQHandler(void)
|
||||
{
|
||||
enet_mac_rx_isr(enetIfHandle);
|
||||
}
|
||||
|
||||
#if FSL_FEATURE_ENET_SUPPORT_PTP
|
||||
void ENET_1588_Timer_IRQHandler(void)
|
||||
{
|
||||
enet_mac_ts_isr(enetIfHandle);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o 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.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
|
||||
*/
|
||||
#ifndef K64F_EMAC_CONFIG_H__
|
||||
#define K64F_EMAC_CONFIG_H__
|
||||
|
||||
#define ENET_RX_RING_LEN (16)
|
||||
#define ENET_TX_RING_LEN (8)
|
||||
#define ENET_RX_LARGE_BUFFER_NUM (0)
|
||||
#define ENET_RX_BUFFER_ALIGNMENT (16)
|
||||
#define ENET_TX_BUFFER_ALIGNMENT (16)
|
||||
#define ENET_BD_ALIGNMENT (16)
|
||||
#define ENET_MII_CLOCK (2500000L)
|
||||
#define RX_BUF_ALIGNMENT (16)
|
||||
#define TX_BUF_ALIGNMENT (8)
|
||||
#define BOARD_DEBUG_ENET_INSTANCE (0)
|
||||
#define BOARD_DEBUG_ENET_INSTANCE_ADDR (ENET_BASE)
|
||||
|
||||
#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int phy_link_status(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #define K64F_EMAC_CONFIG_H__
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LWIPOPTS_CONF_H
|
||||
#define LWIPOPTS_CONF_H
|
||||
|
||||
#include "k64f_emac_config.h"
|
||||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
#define ETH_PAD_SIZE 2
|
||||
|
||||
#define MEM_SIZE (ENET_RX_RING_LEN * (ENET_ETH_MAX_FLEN + RX_BUF_ALIGNMENT) + ENET_TX_RING_LEN * ENET_ETH_MAX_FLEN)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,661 @@
|
|||
/**********************************************************************
|
||||
* $Id$ lpc17xx_emac.h 2010-05-21
|
||||
*//**
|
||||
* @file lpc17xx_emac.h
|
||||
* @brief Contains all macro definitions and function prototypes
|
||||
* support for Ethernet MAC firmware library on LPC17xx
|
||||
* @version 2.0
|
||||
* @date 21. May. 2010
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2010, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
/* Peripheral group ----------------------------------------------------------- */
|
||||
/** @defgroup EMAC EMAC (Ethernet Media Access Controller)
|
||||
* @ingroup LPC1700CMSIS_FwLib_Drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef LPC17XX_EMAC_H_
|
||||
#define LPC17XX_EMAC_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------- */
|
||||
#include "cmsis.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define MCB_LPC_1768
|
||||
//#define IAR_LPC_1768
|
||||
|
||||
/* Public Macros -------------------------------------------------------------- */
|
||||
/** @defgroup EMAC_Public_Macros EMAC Public Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/* EMAC PHY status type definitions */
|
||||
#define EMAC_PHY_STAT_LINK (0) /**< Link Status */
|
||||
#define EMAC_PHY_STAT_SPEED (1) /**< Speed Status */
|
||||
#define EMAC_PHY_STAT_DUP (2) /**< Duplex Status */
|
||||
|
||||
/* EMAC PHY device Speed definitions */
|
||||
#define EMAC_MODE_AUTO (0) /**< Auto-negotiation mode */
|
||||
#define EMAC_MODE_10M_FULL (1) /**< 10Mbps FullDuplex mode */
|
||||
#define EMAC_MODE_10M_HALF (2) /**< 10Mbps HalfDuplex mode */
|
||||
#define EMAC_MODE_100M_FULL (3) /**< 100Mbps FullDuplex mode */
|
||||
#define EMAC_MODE_100M_HALF (4) /**< 100Mbps HalfDuplex mode */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private Macros ------------------------------------------------------------- */
|
||||
/** @defgroup EMAC_Private_Macros EMAC Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/* EMAC Memory Buffer configuration for 16K Ethernet RAM */
|
||||
#define EMAC_NUM_RX_FRAG 4 /**< Num.of RX Fragments 4*1536= 6.0kB */
|
||||
#define EMAC_NUM_TX_FRAG 3 /**< Num.of TX Fragments 3*1536= 4.6kB */
|
||||
#define EMAC_ETH_MAX_FLEN 1536 /**< Max. Ethernet Frame Size */
|
||||
#define EMAC_TX_FRAME_TOUT 0x00100000 /**< Frame Transmit timeout count */
|
||||
|
||||
/* --------------------- BIT DEFINITIONS -------------------------------------- */
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MAC Configuration Register 1
|
||||
**********************************************************************/
|
||||
#define EMAC_MAC1_REC_EN 0x00000001 /**< Receive Enable */
|
||||
#define EMAC_MAC1_PASS_ALL 0x00000002 /**< Pass All Receive Frames */
|
||||
#define EMAC_MAC1_RX_FLOWC 0x00000004 /**< RX Flow Control */
|
||||
#define EMAC_MAC1_TX_FLOWC 0x00000008 /**< TX Flow Control */
|
||||
#define EMAC_MAC1_LOOPB 0x00000010 /**< Loop Back Mode */
|
||||
#define EMAC_MAC1_RES_TX 0x00000100 /**< Reset TX Logic */
|
||||
#define EMAC_MAC1_RES_MCS_TX 0x00000200 /**< Reset MAC TX Control Sublayer */
|
||||
#define EMAC_MAC1_RES_RX 0x00000400 /**< Reset RX Logic */
|
||||
#define EMAC_MAC1_RES_MCS_RX 0x00000800 /**< Reset MAC RX Control Sublayer */
|
||||
#define EMAC_MAC1_SIM_RES 0x00004000 /**< Simulation Reset */
|
||||
#define EMAC_MAC1_SOFT_RES 0x00008000 /**< Soft Reset MAC */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MAC Configuration Register 2
|
||||
**********************************************************************/
|
||||
#define EMAC_MAC2_FULL_DUP 0x00000001 /**< Full-Duplex Mode */
|
||||
#define EMAC_MAC2_FRM_LEN_CHK 0x00000002 /**< Frame Length Checking */
|
||||
#define EMAC_MAC2_HUGE_FRM_EN 0x00000004 /**< Huge Frame Enable */
|
||||
#define EMAC_MAC2_DLY_CRC 0x00000008 /**< Delayed CRC Mode */
|
||||
#define EMAC_MAC2_CRC_EN 0x00000010 /**< Append CRC to every Frame */
|
||||
#define EMAC_MAC2_PAD_EN 0x00000020 /**< Pad all Short Frames */
|
||||
#define EMAC_MAC2_VLAN_PAD_EN 0x00000040 /**< VLAN Pad Enable */
|
||||
#define EMAC_MAC2_ADET_PAD_EN 0x00000080 /**< Auto Detect Pad Enable */
|
||||
#define EMAC_MAC2_PPREAM_ENF 0x00000100 /**< Pure Preamble Enforcement */
|
||||
#define EMAC_MAC2_LPREAM_ENF 0x00000200 /**< Long Preamble Enforcement */
|
||||
#define EMAC_MAC2_NO_BACKOFF 0x00001000 /**< No Backoff Algorithm */
|
||||
#define EMAC_MAC2_BACK_PRESSURE 0x00002000 /**< Backoff Presurre / No Backoff */
|
||||
#define EMAC_MAC2_EXCESS_DEF 0x00004000 /**< Excess Defer */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Back-to-Back Inter-Packet-Gap Register
|
||||
**********************************************************************/
|
||||
/** Programmable field representing the nibble time offset of the minimum possible period
|
||||
* between the end of any transmitted packet to the beginning of the next */
|
||||
#define EMAC_IPGT_BBIPG(n) (n&0x7F)
|
||||
/** Recommended value for Full Duplex of Programmable field representing the nibble time
|
||||
* offset of the minimum possible period between the end of any transmitted packet to the
|
||||
* beginning of the next */
|
||||
#define EMAC_IPGT_FULL_DUP (EMAC_IPGT_BBIPG(0x15))
|
||||
/** Recommended value for Half Duplex of Programmable field representing the nibble time
|
||||
* offset of the minimum possible period between the end of any transmitted packet to the
|
||||
* beginning of the next */
|
||||
#define EMAC_IPGT_HALF_DUP (EMAC_IPGT_BBIPG(0x12))
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Non Back-to-Back Inter-Packet-Gap Register
|
||||
**********************************************************************/
|
||||
/** Programmable field representing the Non-Back-to-Back Inter-Packet-Gap */
|
||||
#define EMAC_IPGR_NBBIPG_P2(n) (n&0x7F)
|
||||
/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 1 */
|
||||
#define EMAC_IPGR_P2_DEF (EMAC_IPGR_NBBIPG_P2(0x12))
|
||||
/** Programmable field representing the optional carrierSense window referenced in
|
||||
* IEEE 802.3/4.2.3.2.1 'Carrier Deference' */
|
||||
#define EMAC_IPGR_NBBIPG_P1(n) ((n&0x7F)<<8)
|
||||
/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 2 */
|
||||
#define EMAC_IPGR_P1_DEF EMAC_IPGR_NBBIPG_P1(0x0C)
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Collision Window/Retry Register
|
||||
**********************************************************************/
|
||||
/** Programmable field specifying the number of retransmission attempts following a collision before
|
||||
* aborting the packet due to excessive collisions */
|
||||
#define EMAC_CLRT_MAX_RETX(n) (n&0x0F)
|
||||
/** Programmable field representing the slot time or collision window during which collisions occur
|
||||
* in properly configured networks */
|
||||
#define EMAC_CLRT_COLL(n) ((n&0x3F)<<8)
|
||||
/** Default value for Collision Window / Retry register */
|
||||
#define EMAC_CLRT_DEF ((EMAC_CLRT_MAX_RETX(0x0F))|(EMAC_CLRT_COLL(0x37)))
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Maximum Frame Register
|
||||
**********************************************************************/
|
||||
/** Represents a maximum receive frame of 1536 octets */
|
||||
#define EMAC_MAXF_MAXFRMLEN(n) (n&0xFFFF)
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Support Register
|
||||
**********************************************************************/
|
||||
#define EMAC_SUPP_SPEED 0x00000100 /**< Reduced MII Logic Current Speed */
|
||||
#define EMAC_SUPP_RES_RMII 0x00000800 /**< Reset Reduced MII Logic */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Test Register
|
||||
**********************************************************************/
|
||||
#define EMAC_TEST_SHCUT_PQUANTA 0x00000001 /**< Shortcut Pause Quanta */
|
||||
#define EMAC_TEST_TST_PAUSE 0x00000002 /**< Test Pause */
|
||||
#define EMAC_TEST_TST_BACKP 0x00000004 /**< Test Back Pressure */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Configuration Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MCFG_SCAN_INC 0x00000001 /**< Scan Increment PHY Address */
|
||||
#define EMAC_MCFG_SUPP_PREAM 0x00000002 /**< Suppress Preamble */
|
||||
#define EMAC_MCFG_CLK_SEL(n) ((n&0x0F)<<2) /**< Clock Select Field */
|
||||
#define EMAC_MCFG_RES_MII 0x00008000 /**< Reset MII Management Hardware */
|
||||
#define EMAC_MCFG_MII_MAXCLK 2500000UL /**< MII Clock max */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Command Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MCMD_READ 0x00000001 /**< MII Read */
|
||||
#define EMAC_MCMD_SCAN 0x00000002 /**< MII Scan continuously */
|
||||
|
||||
#define EMAC_MII_WR_TOUT 0x00050000 /**< MII Write timeout count */
|
||||
#define EMAC_MII_RD_TOUT 0x00050000 /**< MII Read timeout count */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Address Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MADR_REG_ADR(n) (n&0x1F) /**< MII Register Address field */
|
||||
#define EMAC_MADR_PHY_ADR(n) ((n&0x1F)<<8) /**< PHY Address Field */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Write Data Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MWTD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Write Data register */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Read Data Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MRDD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Read Data register */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for MII Management Indicators Register
|
||||
**********************************************************************/
|
||||
#define EMAC_MIND_BUSY 0x00000001 /**< MII is Busy */
|
||||
#define EMAC_MIND_SCAN 0x00000002 /**< MII Scanning in Progress */
|
||||
#define EMAC_MIND_NOT_VAL 0x00000004 /**< MII Read Data not valid */
|
||||
#define EMAC_MIND_MII_LINK_FAIL 0x00000008 /**< MII Link Failed */
|
||||
|
||||
/* Station Address 0 Register */
|
||||
/* Station Address 1 Register */
|
||||
/* Station Address 2 Register */
|
||||
|
||||
|
||||
/* Control register definitions --------------------------------------------------------------------------- */
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Command Register
|
||||
**********************************************************************/
|
||||
#define EMAC_CR_RX_EN 0x00000001 /**< Enable Receive */
|
||||
#define EMAC_CR_TX_EN 0x00000002 /**< Enable Transmit */
|
||||
#define EMAC_CR_REG_RES 0x00000008 /**< Reset Host Registers */
|
||||
#define EMAC_CR_TX_RES 0x00000010 /**< Reset Transmit Datapath */
|
||||
#define EMAC_CR_RX_RES 0x00000020 /**< Reset Receive Datapath */
|
||||
#define EMAC_CR_PASS_RUNT_FRM 0x00000040 /**< Pass Runt Frames */
|
||||
#define EMAC_CR_PASS_RX_FILT 0x00000080 /**< Pass RX Filter */
|
||||
#define EMAC_CR_TX_FLOW_CTRL 0x00000100 /**< TX Flow Control */
|
||||
#define EMAC_CR_RMII 0x00000200 /**< Reduced MII Interface */
|
||||
#define EMAC_CR_FULL_DUP 0x00000400 /**< Full Duplex */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Status Register
|
||||
**********************************************************************/
|
||||
#define EMAC_SR_RX_EN 0x00000001 /**< Enable Receive */
|
||||
#define EMAC_SR_TX_EN 0x00000002 /**< Enable Transmit */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Transmit Status Vector 0 Register
|
||||
**********************************************************************/
|
||||
#define EMAC_TSV0_CRC_ERR 0x00000001 /**< CRC error */
|
||||
#define EMAC_TSV0_LEN_CHKERR 0x00000002 /**< Length Check Error */
|
||||
#define EMAC_TSV0_LEN_OUTRNG 0x00000004 /**< Length Out of Range */
|
||||
#define EMAC_TSV0_DONE 0x00000008 /**< Tramsmission Completed */
|
||||
#define EMAC_TSV0_MCAST 0x00000010 /**< Multicast Destination */
|
||||
#define EMAC_TSV0_BCAST 0x00000020 /**< Broadcast Destination */
|
||||
#define EMAC_TSV0_PKT_DEFER 0x00000040 /**< Packet Deferred */
|
||||
#define EMAC_TSV0_EXC_DEFER 0x00000080 /**< Excessive Packet Deferral */
|
||||
#define EMAC_TSV0_EXC_COLL 0x00000100 /**< Excessive Collision */
|
||||
#define EMAC_TSV0_LATE_COLL 0x00000200 /**< Late Collision Occured */
|
||||
#define EMAC_TSV0_GIANT 0x00000400 /**< Giant Frame */
|
||||
#define EMAC_TSV0_UNDERRUN 0x00000800 /**< Buffer Underrun */
|
||||
#define EMAC_TSV0_BYTES 0x0FFFF000 /**< Total Bytes Transferred */
|
||||
#define EMAC_TSV0_CTRL_FRAME 0x10000000 /**< Control Frame */
|
||||
#define EMAC_TSV0_PAUSE 0x20000000 /**< Pause Frame */
|
||||
#define EMAC_TSV0_BACK_PRESS 0x40000000 /**< Backpressure Method Applied */
|
||||
#define EMAC_TSV0_VLAN 0x80000000 /**< VLAN Frame */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Transmit Status Vector 1 Register
|
||||
**********************************************************************/
|
||||
#define EMAC_TSV1_BYTE_CNT 0x0000FFFF /**< Transmit Byte Count */
|
||||
#define EMAC_TSV1_COLL_CNT 0x000F0000 /**< Transmit Collision Count */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Receive Status Vector Register
|
||||
**********************************************************************/
|
||||
#define EMAC_RSV_BYTE_CNT 0x0000FFFF /**< Receive Byte Count */
|
||||
#define EMAC_RSV_PKT_IGNORED 0x00010000 /**< Packet Previously Ignored */
|
||||
#define EMAC_RSV_RXDV_SEEN 0x00020000 /**< RXDV Event Previously Seen */
|
||||
#define EMAC_RSV_CARR_SEEN 0x00040000 /**< Carrier Event Previously Seen */
|
||||
#define EMAC_RSV_REC_CODEV 0x00080000 /**< Receive Code Violation */
|
||||
#define EMAC_RSV_CRC_ERR 0x00100000 /**< CRC Error */
|
||||
#define EMAC_RSV_LEN_CHKERR 0x00200000 /**< Length Check Error */
|
||||
#define EMAC_RSV_LEN_OUTRNG 0x00400000 /**< Length Out of Range */
|
||||
#define EMAC_RSV_REC_OK 0x00800000 /**< Frame Received OK */
|
||||
#define EMAC_RSV_MCAST 0x01000000 /**< Multicast Frame */
|
||||
#define EMAC_RSV_BCAST 0x02000000 /**< Broadcast Frame */
|
||||
#define EMAC_RSV_DRIB_NIBB 0x04000000 /**< Dribble Nibble */
|
||||
#define EMAC_RSV_CTRL_FRAME 0x08000000 /**< Control Frame */
|
||||
#define EMAC_RSV_PAUSE 0x10000000 /**< Pause Frame */
|
||||
#define EMAC_RSV_UNSUPP_OPC 0x20000000 /**< Unsupported Opcode */
|
||||
#define EMAC_RSV_VLAN 0x40000000 /**< VLAN Frame */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Flow Control Counter Register
|
||||
**********************************************************************/
|
||||
#define EMAC_FCC_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter */
|
||||
#define EMAC_FCC_PAUSE_TIM(n) ((n&0xFFFF)<<16) /**< Pause Timer */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Flow Control Status Register
|
||||
**********************************************************************/
|
||||
#define EMAC_FCS_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter Current */
|
||||
|
||||
|
||||
/* Receive filter register definitions -------------------------------------------------------- */
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Receive Filter Control Register
|
||||
**********************************************************************/
|
||||
#define EMAC_RFC_UCAST_EN 0x00000001 /**< Accept Unicast Frames Enable */
|
||||
#define EMAC_RFC_BCAST_EN 0x00000002 /**< Accept Broadcast Frames Enable */
|
||||
#define EMAC_RFC_MCAST_EN 0x00000004 /**< Accept Multicast Frames Enable */
|
||||
#define EMAC_RFC_UCAST_HASH_EN 0x00000008 /**< Accept Unicast Hash Filter Frames */
|
||||
#define EMAC_RFC_MCAST_HASH_EN 0x00000010 /**< Accept Multicast Hash Filter Fram.*/
|
||||
#define EMAC_RFC_PERFECT_EN 0x00000020 /**< Accept Perfect Match Enable */
|
||||
#define EMAC_RFC_MAGP_WOL_EN 0x00001000 /**< Magic Packet Filter WoL Enable */
|
||||
#define EMAC_RFC_PFILT_WOL_EN 0x00002000 /**< Perfect Filter WoL Enable */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Receive Filter WoL Status/Clear Registers
|
||||
**********************************************************************/
|
||||
#define EMAC_WOL_UCAST 0x00000001 /**< Unicast Frame caused WoL */
|
||||
#define EMAC_WOL_BCAST 0x00000002 /**< Broadcast Frame caused WoL */
|
||||
#define EMAC_WOL_MCAST 0x00000004 /**< Multicast Frame caused WoL */
|
||||
#define EMAC_WOL_UCAST_HASH 0x00000008 /**< Unicast Hash Filter Frame WoL */
|
||||
#define EMAC_WOL_MCAST_HASH 0x00000010 /**< Multicast Hash Filter Frame WoL */
|
||||
#define EMAC_WOL_PERFECT 0x00000020 /**< Perfect Filter WoL */
|
||||
#define EMAC_WOL_RX_FILTER 0x00000080 /**< RX Filter caused WoL */
|
||||
#define EMAC_WOL_MAG_PACKET 0x00000100 /**< Magic Packet Filter caused WoL */
|
||||
#define EMAC_WOL_BITMASK 0x01BF /**< Receive Filter WoL Status/Clear bitmasl value */
|
||||
|
||||
|
||||
/* Module control register definitions ---------------------------------------------------- */
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Interrupt Status/Enable/Clear/Set Registers
|
||||
**********************************************************************/
|
||||
#define EMAC_INT_RX_OVERRUN 0x00000001 /**< Overrun Error in RX Queue */
|
||||
#define EMAC_INT_RX_ERR 0x00000002 /**< Receive Error */
|
||||
#define EMAC_INT_RX_FIN 0x00000004 /**< RX Finished Process Descriptors */
|
||||
#define EMAC_INT_RX_DONE 0x00000008 /**< Receive Done */
|
||||
#define EMAC_INT_TX_UNDERRUN 0x00000010 /**< Transmit Underrun */
|
||||
#define EMAC_INT_TX_ERR 0x00000020 /**< Transmit Error */
|
||||
#define EMAC_INT_TX_FIN 0x00000040 /**< TX Finished Process Descriptors */
|
||||
#define EMAC_INT_TX_DONE 0x00000080 /**< Transmit Done */
|
||||
#define EMAC_INT_SOFT_INT 0x00001000 /**< Software Triggered Interrupt */
|
||||
#define EMAC_INT_WAKEUP 0x00002000 /**< Wakeup Event Interrupt */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Power Down Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PD_POWER_DOWN 0x80000000 /**< Power Down MAC */
|
||||
|
||||
/* Descriptor and status formats ---------------------------------------------------- */
|
||||
/*********************************************************************//**
|
||||
* Macro defines for RX Descriptor Control Word
|
||||
**********************************************************************/
|
||||
#define EMAC_RCTRL_SIZE(n) (n&0x7FF) /**< Buffer size field */
|
||||
#define EMAC_RCTRL_INT 0x80000000 /**< Generate RxDone Interrupt */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for RX Status Hash CRC Word
|
||||
**********************************************************************/
|
||||
#define EMAC_RHASH_SA 0x000001FF /**< Hash CRC for Source Address */
|
||||
#define EMAC_RHASH_DA 0x001FF000 /**< Hash CRC for Destination Address */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for RX Status Information Word
|
||||
**********************************************************************/
|
||||
#define EMAC_RINFO_SIZE 0x000007FF /**< Data size in bytes */
|
||||
#define EMAC_RINFO_CTRL_FRAME 0x00040000 /**< Control Frame */
|
||||
#define EMAC_RINFO_VLAN 0x00080000 /**< VLAN Frame */
|
||||
#define EMAC_RINFO_FAIL_FILT 0x00100000 /**< RX Filter Failed */
|
||||
#define EMAC_RINFO_MCAST 0x00200000 /**< Multicast Frame */
|
||||
#define EMAC_RINFO_BCAST 0x00400000 /**< Broadcast Frame */
|
||||
#define EMAC_RINFO_CRC_ERR 0x00800000 /**< CRC Error in Frame */
|
||||
#define EMAC_RINFO_SYM_ERR 0x01000000 /**< Symbol Error from PHY */
|
||||
#define EMAC_RINFO_LEN_ERR 0x02000000 /**< Length Error */
|
||||
#define EMAC_RINFO_RANGE_ERR 0x04000000 /**< Range Error (exceeded max. size) */
|
||||
#define EMAC_RINFO_ALIGN_ERR 0x08000000 /**< Alignment Error */
|
||||
#define EMAC_RINFO_OVERRUN 0x10000000 /**< Receive overrun */
|
||||
#define EMAC_RINFO_NO_DESCR 0x20000000 /**< No new Descriptor available */
|
||||
#define EMAC_RINFO_LAST_FLAG 0x40000000 /**< Last Fragment in Frame */
|
||||
#define EMAC_RINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */
|
||||
#define EMAC_RINFO_ERR_MASK (EMAC_RINFO_FAIL_FILT | EMAC_RINFO_CRC_ERR | EMAC_RINFO_SYM_ERR | \
|
||||
EMAC_RINFO_LEN_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_OVERRUN)
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for TX Descriptor Control Word
|
||||
**********************************************************************/
|
||||
#define EMAC_TCTRL_SIZE 0x000007FF /**< Size of data buffer in bytes */
|
||||
#define EMAC_TCTRL_OVERRIDE 0x04000000 /**< Override Default MAC Registers */
|
||||
#define EMAC_TCTRL_HUGE 0x08000000 /**< Enable Huge Frame */
|
||||
#define EMAC_TCTRL_PAD 0x10000000 /**< Pad short Frames to 64 bytes */
|
||||
#define EMAC_TCTRL_CRC 0x20000000 /**< Append a hardware CRC to Frame */
|
||||
#define EMAC_TCTRL_LAST 0x40000000 /**< Last Descriptor for TX Frame */
|
||||
#define EMAC_TCTRL_INT 0x80000000 /**< Generate TxDone Interrupt */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for TX Status Information Word
|
||||
**********************************************************************/
|
||||
#define EMAC_TINFO_COL_CNT 0x01E00000 /**< Collision Count */
|
||||
#define EMAC_TINFO_DEFER 0x02000000 /**< Packet Deferred (not an error) */
|
||||
#define EMAC_TINFO_EXCESS_DEF 0x04000000 /**< Excessive Deferral */
|
||||
#define EMAC_TINFO_EXCESS_COL 0x08000000 /**< Excessive Collision */
|
||||
#define EMAC_TINFO_LATE_COL 0x10000000 /**< Late Collision Occured */
|
||||
#define EMAC_TINFO_UNDERRUN 0x20000000 /**< Transmit Underrun */
|
||||
#define EMAC_TINFO_NO_DESCR 0x40000000 /**< No new Descriptor available */
|
||||
#define EMAC_TINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */
|
||||
|
||||
#ifdef MCB_LPC_1768
|
||||
/* DP83848C PHY definition ------------------------------------------------------------ */
|
||||
|
||||
/** PHY device reset time out definition */
|
||||
#define EMAC_PHY_RESP_TOUT 0x100000UL
|
||||
|
||||
/* ENET Device Revision ID */
|
||||
#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for DP83848C PHY Registers
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */
|
||||
#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */
|
||||
#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */
|
||||
#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */
|
||||
#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */
|
||||
#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */
|
||||
#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */
|
||||
#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */
|
||||
#define EMAC_PHY_REG_LPNPA 0x08
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Extended Registers
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_REG_STS 0x10 /**< Status Register */
|
||||
#define EMAC_PHY_REG_MICR 0x11 /**< MII Interrupt Control Register */
|
||||
#define EMAC_PHY_REG_MISR 0x12 /**< MII Interrupt Status Register */
|
||||
#define EMAC_PHY_REG_FCSCR 0x14 /**< False Carrier Sense Counter */
|
||||
#define EMAC_PHY_REG_RECR 0x15 /**< Receive Error Counter */
|
||||
#define EMAC_PHY_REG_PCSR 0x16 /**< PCS Sublayer Config. and Status */
|
||||
#define EMAC_PHY_REG_RBR 0x17 /**< RMII and Bypass Register */
|
||||
#define EMAC_PHY_REG_LEDCR 0x18 /**< LED Direct Control Register */
|
||||
#define EMAC_PHY_REG_PHYCR 0x19 /**< PHY Control Register */
|
||||
#define EMAC_PHY_REG_10BTSCR 0x1A /**< 10Base-T Status/Control Register */
|
||||
#define EMAC_PHY_REG_CDCTRL1 0x1B /**< CD Test Control and BIST Extens. */
|
||||
#define EMAC_PHY_REG_EDCR 0x1D /**< Energy Detect Control Register */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Basic Mode Control Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */
|
||||
#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */
|
||||
#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */
|
||||
#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */
|
||||
#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */
|
||||
#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */
|
||||
#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */
|
||||
#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Basic Mode Status Status Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */
|
||||
#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */
|
||||
#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */
|
||||
#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */
|
||||
#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */
|
||||
#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */
|
||||
#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */
|
||||
#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */
|
||||
#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */
|
||||
#define EMAC_PHY_BMSR_LINK_ESTABLISHED (1<<2) /**< Link status */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Status Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_SR_REMOTE_FAULT (1<<6) /**< Remote Fault */
|
||||
#define EMAC_PHY_SR_JABBER (1<<5) /**< Jabber detect */
|
||||
#define EMAC_PHY_SR_AUTO_DONE (1<<4) /**< Auto Negotiation complete */
|
||||
#define EMAC_PHY_SR_LOOPBACK (1<<3) /**< Loop back status */
|
||||
#define EMAC_PHY_SR_DUP (1<<2) /**< Duplex status */
|
||||
#define EMAC_PHY_SR_SPEED (1<<1) /**< Speed status */
|
||||
#define EMAC_PHY_SR_LINK (1<<0) /**< Link Status */
|
||||
|
||||
#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */
|
||||
#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */
|
||||
#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */
|
||||
#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */
|
||||
#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */
|
||||
|
||||
#define EMAC_DEF_ADR 0x0100 /**< Default PHY device address */
|
||||
#define EMAC_DP83848C_ID 0x20005C90 /**< PHY Identifier */
|
||||
|
||||
#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13))
|
||||
#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12))
|
||||
#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */
|
||||
|
||||
#elif defined(IAR_LPC_1768)
|
||||
/* KSZ8721BL PHY definition ------------------------------------------------------------ */
|
||||
/** PHY device reset time out definition */
|
||||
#define EMAC_PHY_RESP_TOUT 0x100000UL
|
||||
|
||||
/* ENET Device Revision ID */
|
||||
#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for KSZ8721BL PHY Registers
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */
|
||||
#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */
|
||||
#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */
|
||||
#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */
|
||||
#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */
|
||||
#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */
|
||||
#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */
|
||||
#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */
|
||||
#define EMAC_PHY_REG_LPNPA 0x08 /**< Link Partner Next Page Ability */
|
||||
#define EMAC_PHY_REG_REC 0x15 /**< RXError Counter Register */
|
||||
#define EMAC_PHY_REG_ISC 0x1b /**< Interrupt Control/Status Register */
|
||||
#define EMAC_PHY_REG_100BASE 0x1f /**< 100BASE-TX PHY Control Register */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Basic Mode Control Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */
|
||||
#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */
|
||||
#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */
|
||||
#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */
|
||||
#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */
|
||||
#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */
|
||||
#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */
|
||||
#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */
|
||||
#define EMAC_PHY_BMCR_COLLISION (1<<7) /**< Collision test */
|
||||
#define EMAC_PHY_BMCR_TXDIS (1<<0) /**< Disable transmit */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Basic Mode Status Register
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */
|
||||
#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */
|
||||
#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */
|
||||
#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */
|
||||
#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */
|
||||
#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */
|
||||
#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */
|
||||
#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */
|
||||
#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */
|
||||
#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */
|
||||
#define EMAC_PHY_BMSR_JABBER_DETECT (1<<1) /**< Jabber detect */
|
||||
#define EMAC_PHY_BMSR_EXTEND (1<<0) /**< Extended support */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for PHY Identifier
|
||||
**********************************************************************/
|
||||
/* PHY Identifier 1 bitmap definitions */
|
||||
#define EMAC_PHY_IDR1(n) (n & 0xFFFF) /**< PHY ID1 Number */
|
||||
|
||||
/* PHY Identifier 2 bitmap definitions */
|
||||
#define EMAC_PHY_IDR2(n) (n & 0xFFFF) /**< PHY ID2 Number */
|
||||
|
||||
/*********************************************************************//**
|
||||
* Macro defines for Auto-Negotiation Advertisement
|
||||
**********************************************************************/
|
||||
#define EMAC_PHY_AN_NEXTPAGE (1<<15) /**< Next page capable */
|
||||
#define EMAC_PHY_AN_REMOTE_FAULT (1<<13) /**< Remote Fault support */
|
||||
#define EMAC_PHY_AN_PAUSE (1<<10) /**< Pause support */
|
||||
#define EMAC_PHY_AN_100BASE_T4 (1<<9) /**< T4 capable */
|
||||
#define EMAC_PHY_AN_100BASE_TX_FD (1<<8) /**< TX with Full-duplex capable */
|
||||
#define EMAC_PHY_AN_100BASE_TX (1<<7) /**< TX capable */
|
||||
#define EMAC_PHY_AN_10BASE_T_FD (1<<6) /**< 10Mbps with full-duplex capable */
|
||||
#define EMAC_PHY_AN_10BASE_T (1<<5) /**< 10Mbps capable */
|
||||
#define EMAC_PHY_AN_FIELD(n) (n & 0x1F) /**< Selector Field */
|
||||
|
||||
#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */
|
||||
#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */
|
||||
#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */
|
||||
#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */
|
||||
#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */
|
||||
|
||||
#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13))
|
||||
#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12))
|
||||
|
||||
#define EMAC_DEF_ADR (0x01<<8) /**< Default PHY device address */
|
||||
#define EMAC_KSZ8721BL_ID ((0x22 << 16) | 0x1619 ) /**< PHY Identifier */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Public Types --------------------------------------------------------------- */
|
||||
/** @defgroup EMAC_Public_Types EMAC Public Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Descriptor and status formats ---------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief RX Descriptor structure type definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Packet; /**< Receive Packet Descriptor */
|
||||
uint32_t Ctrl; /**< Receive Control Descriptor */
|
||||
} RX_Desc;
|
||||
|
||||
/**
|
||||
* @brief RX Status structure type definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Info; /**< Receive Information Status */
|
||||
uint32_t HashCRC; /**< Receive Hash CRC Status */
|
||||
} RX_Stat;
|
||||
|
||||
/**
|
||||
* @brief TX Descriptor structure type definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Packet; /**< Transmit Packet Descriptor */
|
||||
uint32_t Ctrl; /**< Transmit Control Descriptor */
|
||||
} TX_Desc;
|
||||
|
||||
/**
|
||||
* @brief TX Status structure type definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Info; /**< Transmit Information Status */
|
||||
} TX_Stat;
|
||||
|
||||
|
||||
/**
|
||||
* @brief TX Data Buffer structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t ulDataLen; /**< Data length */
|
||||
uint32_t *pbDataBuf; /**< A word-align data pointer to data buffer */
|
||||
} EMAC_PACKETBUF_Type;
|
||||
|
||||
/**
|
||||
* @brief EMAC configuration structure definition
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Mode; /**< Supported EMAC PHY device speed, should be one of the following:
|
||||
- EMAC_MODE_AUTO
|
||||
- EMAC_MODE_10M_FULL
|
||||
- EMAC_MODE_10M_HALF
|
||||
- EMAC_MODE_100M_FULL
|
||||
- EMAC_MODE_100M_HALF
|
||||
*/
|
||||
uint8_t *pbEMAC_Addr; /**< Pointer to EMAC Station address that contains 6-bytes
|
||||
of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5])
|
||||
*/
|
||||
} EMAC_CFG_Type;
|
||||
|
||||
/** Ethernet block power/clock control bit*/
|
||||
#define CLKPWR_PCONP_PCENET ((uint32_t)(1<<30))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LPC17XX_EMAC_H_ */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
|
@ -0,0 +1,111 @@
|
|||
/**********************************************************************
|
||||
* $Id$ lpc_emac_config.h 2011-11-20
|
||||
*//**
|
||||
* @file lpc_emac_config.h
|
||||
* @brief PHY and EMAC configuration file
|
||||
* @version 1.0
|
||||
* @date 20 Nov. 2011
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __LPC_EMAC_CONFIG_H
|
||||
#define __LPC_EMAC_CONFIG_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** @defgroup lwip_phy_config LWIP PHY configuration
|
||||
* @ingroup lwip_phy
|
||||
*
|
||||
* Configuration options for the PHY connected to the LPC EMAC.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief The PHY address connected the to MII/RMII
|
||||
*/
|
||||
#define LPC_PHYDEF_PHYADDR 1 /**< The PHY address on the PHY device. */
|
||||
|
||||
/** \brief Enable autonegotiation mode.
|
||||
* If this is enabled, the PHY will attempt to auto-negotiate the
|
||||
* best link mode if the PHY supports it. If this is not enabled,
|
||||
* the PHY_USE_FULL_DUPLEX and PHY_USE_100MBS defines will be
|
||||
* used to select the link mode. Note that auto-negotiation may
|
||||
* take a few seconds to complete.
|
||||
*/
|
||||
#define PHY_USE_AUTONEG 1 /**< Enables auto-negotiation mode. */
|
||||
|
||||
/** \brief Sets up the PHY interface to either full duplex operation or
|
||||
* half duplex operation if PHY_USE_AUTONEG is not enabled.
|
||||
*/
|
||||
#define PHY_USE_FULL_DUPLEX 1 /**< Sets duplex mode to full. */
|
||||
|
||||
/** \brief Sets up the PHY interface to either 100MBS operation or 10MBS
|
||||
* operation if PHY_USE_AUTONEG is not enabled.
|
||||
*/
|
||||
#define PHY_USE_100MBS 1 /**< Sets data rate to 100Mbps. */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup lwip_emac_config LWIP EMAC configuration
|
||||
* @ingroup lwip_emac
|
||||
*
|
||||
* Configuration options for the LPC EMAC.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Selects RMII or MII connection type in the EMAC peripheral
|
||||
*/
|
||||
#define LPC_EMAC_RMII 1 /**< Use the RMII or MII driver variant .*/
|
||||
|
||||
/** \brief Defines the number of descriptors used for RX. This
|
||||
* must be a minimum value of 2.
|
||||
*/
|
||||
#define LPC_NUM_BUFF_RXDESCS 3
|
||||
|
||||
/** \brief Defines the number of descriptors used for TX. Must
|
||||
* be a minimum value of 2.
|
||||
*/
|
||||
#define LPC_NUM_BUFF_TXDESCS (TCP_SND_QUEUELEN + 1)
|
||||
|
||||
/** \brief Set this define to 1 to enable bounce buffers for transmit pbufs
|
||||
* that cannot be sent via the zero-copy method. Some chained pbufs
|
||||
* may have a payload address that links to an area of memory that
|
||||
* cannot be used for transmit DMA operations. If this define is
|
||||
* set to 1, an extra check will be made with the pbufs. If a buffer
|
||||
* is determined to be non-usable for zero-copy, a temporary bounce
|
||||
* buffer will be created and used instead.
|
||||
*/
|
||||
#define LPC_TX_PBUF_BOUNCE_EN 1
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LPC_EMAC_CONFIG_H */
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
|
@ -0,0 +1,151 @@
|
|||
/**********************************************************************
|
||||
* $Id$ lpc_phy.h 2011-11-20
|
||||
*//**
|
||||
* @file lpc_phy.h
|
||||
* @brief Common PHY definitions used with all PHYs
|
||||
* @version 1.0
|
||||
* @date 20 Nov. 2011
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __LPC_PHY_H_
|
||||
#define __LPC_PHY_H_
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* These PHY functions are usually part of the EMAC driver */
|
||||
|
||||
/** \brief Phy status update state machine
|
||||
*
|
||||
* This function provides a state machine for maintaining the PHY
|
||||
* status without blocking. It must be occasionally called for the
|
||||
* PHY status to be maintained.
|
||||
*
|
||||
* \param[in] netif NETIF structure
|
||||
*/
|
||||
s32_t lpc_phy_sts_sm(struct netif *netif);
|
||||
|
||||
/** \brief Initialize the PHY
|
||||
*
|
||||
* This function initializes the PHY. It will block until complete.
|
||||
* This function is called as part of the EMAC driver
|
||||
* initialization. Configuration of the PHY at startup is
|
||||
* controlled by setting up configuration defines in lpc_phy.h.
|
||||
*
|
||||
* \param[in] netif NETIF structure
|
||||
* \param[in] rmii If set, configures the PHY for RMII mode
|
||||
* \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
|
||||
*/
|
||||
err_t lpc_phy_init(struct netif *netif, int rmii);
|
||||
|
||||
/** \brief Write a value via the MII link (non-blocking)
|
||||
*
|
||||
* This function will write a value on the MII link interface to a PHY
|
||||
* or a connected device. The function will return immediately without
|
||||
* a status. Status needs to be polled later to determine if the write
|
||||
* was successful.
|
||||
*
|
||||
* \param[in] PhyReg PHY register to write to
|
||||
* \param[in] Value Value to write
|
||||
*/
|
||||
void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value);
|
||||
|
||||
/** \brief Write a value via the MII link (blocking)
|
||||
*
|
||||
* This function will write a value on the MII link interface to a PHY
|
||||
* or a connected device. The function will block until complete.
|
||||
*
|
||||
* \param[in] PhyReg PHY register to write to
|
||||
* \param[in] Value Value to write
|
||||
* \returns 0 if the write was successful, otherwise !0
|
||||
*/
|
||||
err_t lpc_mii_write(u32_t PhyReg, u32_t Value);
|
||||
|
||||
/** \brief Reads current MII link busy status
|
||||
*
|
||||
* This function will return the current MII link busy status and is meant to
|
||||
* be used with non-blocking functions for monitor PHY status such as
|
||||
* connection state.
|
||||
*
|
||||
* \returns !0 if the MII link is busy, otherwise 0
|
||||
*/
|
||||
u32_t lpc_mii_is_busy(void);
|
||||
|
||||
/** \brief Starts a read operation via the MII link (non-blocking)
|
||||
*
|
||||
* This function returns the current value in the MII data register. It is
|
||||
* meant to be used with the non-blocking oeprations. This value should
|
||||
* only be read after a non-block read command has been issued and the
|
||||
* MII status has been determined to be good.
|
||||
*
|
||||
* \returns The current value in the MII value register
|
||||
*/
|
||||
u32_t lpc_mii_read_data(void);
|
||||
|
||||
/** \brief Starts a read operation via the MII link (non-blocking)
|
||||
*
|
||||
* This function will start a read operation on the MII link interface
|
||||
* from a PHY or a connected device. The function will not block and
|
||||
* the status mist be polled until complete. Once complete, the data
|
||||
* can be read.
|
||||
*
|
||||
* \param[in] PhyReg PHY register to read from
|
||||
*/
|
||||
err_t lpc_mii_read(u32_t PhyReg, u32_t *data);
|
||||
|
||||
/** \brief Read a value via the MII link (blocking)
|
||||
*
|
||||
* This function will read a value on the MII link interface from a PHY
|
||||
* or a connected device. The function will block until complete.
|
||||
*
|
||||
* \param[in] PhyReg PHY register to read from
|
||||
* \param[in] data Pointer to where to save data read via MII
|
||||
* \returns 0 if the read was successful, otherwise !0
|
||||
*/
|
||||
void lpc_mii_read_noblock(u32_t PhyReg);
|
||||
|
||||
/**
|
||||
* This function provides a method for the PHY to setup the EMAC
|
||||
* for the PHY negotiated duplex mode.
|
||||
*
|
||||
* @param[in] full_duplex 0 = half duplex, 1 = full duplex
|
||||
*/
|
||||
void lpc_emac_set_duplex(int full_duplex);
|
||||
|
||||
/**
|
||||
* This function provides a method for the PHY to setup the EMAC
|
||||
* for the PHY negotiated bit rate.
|
||||
*
|
||||
* @param[in] mbs_100 0 = 10mbs mode, 1 = 100mbs mode
|
||||
*/
|
||||
void lpc_emac_set_speed(int mbs_100);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LPC_PHY_H_ */
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
|
@ -0,0 +1,438 @@
|
|||
/**********************************************************************
|
||||
* $Id$ lpc_phy_dp83848.c 2011-11-20
|
||||
*//**
|
||||
* @file lpc_phy_dp83848.c
|
||||
* @brief DP83848C PHY status and control.
|
||||
* @version 1.0
|
||||
* @date 20 Nov. 2011
|
||||
* @author NXP MCU SW Application Team
|
||||
*
|
||||
* Copyright(C) 2011, NXP Semiconductor
|
||||
* All rights reserved.
|
||||
*
|
||||
***********************************************************************
|
||||
* Software that is described herein is for illustrative purposes only
|
||||
* which provides customers with programming information regarding the
|
||||
* products. This software is supplied "AS IS" without any warranties.
|
||||
* NXP Semiconductors assumes no responsibility or liability for the
|
||||
* use of the software, conveys no license or title under any patent,
|
||||
* copyright, or mask work right to the product. NXP Semiconductors
|
||||
* reserves the right to make changes in the software without
|
||||
* notification. NXP Semiconductors also make no representation or
|
||||
* warranty that such application will be suitable for the specified
|
||||
* use without further testing or modification.
|
||||
**********************************************************************/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lpc_emac_config.h"
|
||||
#include "lpc_phy.h"
|
||||
#include "lpc17xx_emac.h"
|
||||
|
||||
/** @defgroup dp83848_phy PHY status and control for the DP83848.
|
||||
* @ingroup lwip_phy
|
||||
*
|
||||
* Various functions for controlling and monitoring the status of the
|
||||
* DP83848 PHY. In polled (standalone) systems, the PHY state must be
|
||||
* monitored as part of the application. In a threaded (RTOS) system,
|
||||
* the PHY state is monitored by the PHY handler thread. The MAC
|
||||
* driver will not transmit unless the PHY link is active.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief DP83848 PHY register offsets */
|
||||
#define DP8_BMCR_REG 0x0 /**< Basic Mode Control Register */
|
||||
#define DP8_BMSR_REG 0x1 /**< Basic Mode Status Reg */
|
||||
#define DP8_IDR1_REG 0x2 /**< Basic Mode Status Reg */
|
||||
#define DP8_IDR2_REG 0x3 /**< Basic Mode Status Reg */
|
||||
#define DP8_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */
|
||||
#define DP8_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */
|
||||
#define DP8_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */
|
||||
#define DP8_PHY_STAT_REG 0x10 /**< PHY Status Register */
|
||||
#define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
|
||||
#define DP8_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */
|
||||
#define DP8_PHY_STS_REG 0x19 /**< PHY Status Register */
|
||||
|
||||
#define DP8_PHY_SCSR_REG 0x1f /**< PHY Special Control/Status Register (LAN8720) */
|
||||
|
||||
/** \brief DP83848 Control register definitions */
|
||||
#define DP8_RESET (1 << 15) /**< 1= S/W Reset */
|
||||
#define DP8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */
|
||||
#define DP8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */
|
||||
#define DP8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */
|
||||
#define DP8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */
|
||||
#define DP8_ISOLATE (1 << 10) /**< 1=Isolate PHY */
|
||||
#define DP8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */
|
||||
#define DP8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */
|
||||
#define DP8_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */
|
||||
|
||||
/** \brief DP83848 Status register definitions */
|
||||
#define DP8_100BASE_T4 (1 << 15) /**< T4 mode */
|
||||
#define DP8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */
|
||||
#define DP8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */
|
||||
#define DP8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */
|
||||
#define DP8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */
|
||||
#define DP8_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */
|
||||
#define DP8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */
|
||||
#define DP8_RMT_FAULT (1 << 4) /**< Fault */
|
||||
#define DP8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */
|
||||
#define DP8_LINK_STATUS (1 << 2) /**< 1=Link active */
|
||||
#define DP8_JABBER_DETECT (1 << 1) /**< Jabber detect */
|
||||
#define DP8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */
|
||||
|
||||
/** \brief DP83848 PHY RBR MII dode definitions */
|
||||
#define DP8_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */
|
||||
|
||||
/** \brief DP83848 PHY status definitions */
|
||||
#define DP8_REMOTEFAULT (1 << 6) /**< Remote fault */
|
||||
#define DP8_FULLDUPLEX (1 << 2) /**< 1=full duplex */
|
||||
#define DP8_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */
|
||||
#define DP8_VALID_LINK (1 << 0) /**< 1=Link active */
|
||||
|
||||
/** \brief DP83848 PHY ID register definitions */
|
||||
#define DP8_PHYID1_OUI 0x2000 /**< Expected PHY ID1 */
|
||||
#define DP8_PHYID2_OUI 0x5c90 /**< Expected PHY ID2 */
|
||||
|
||||
/** \brief LAN8720 PHY Special Control/Status Register */
|
||||
#define PHY_SCSR_100MBIT 0x0008 /**< Speed: 1=100 MBit, 0=10Mbit */
|
||||
#define PHY_SCSR_DUPLEX 0x0010 /**< PHY Duplex Mask */
|
||||
|
||||
/** \brief Link status bits */
|
||||
#define LNK_STAT_VALID 0x01
|
||||
#define LNK_STAT_FULLDUPLEX 0x02
|
||||
#define LNK_STAT_SPEED10MPS 0x04
|
||||
|
||||
/** \brief PHY ID definitions */
|
||||
#define DP83848C_ID 0x20005C90 /**< PHY Identifier - DP83848C */
|
||||
#define LAN8720_ID 0x0007C0F0 /**< PHY Identifier - LAN8720 */
|
||||
|
||||
/** \brief PHY status structure used to indicate current status of PHY.
|
||||
*/
|
||||
typedef struct {
|
||||
u32_t phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
|
||||
u32_t phy_full_duplex:1; /**< Half/full duplex connection speed flag. */
|
||||
u32_t phy_link_active:1; /**< Phy link active flag. */
|
||||
} PHY_STATUS_TYPE;
|
||||
|
||||
/** \brief PHY update flags */
|
||||
static PHY_STATUS_TYPE physts;
|
||||
|
||||
/** \brief Last PHY update flags, used for determing if something has changed */
|
||||
static PHY_STATUS_TYPE olddphysts;
|
||||
|
||||
/** \brief PHY update counter for state machine */
|
||||
static s32_t phyustate;
|
||||
|
||||
/** \brief Holds the PHY ID */
|
||||
static u32_t phy_id;
|
||||
|
||||
/** \brief Temporary holder of link status for LAN7420 */
|
||||
static u32_t phy_lan7420_sts_tmp;
|
||||
|
||||
/* Write a value via the MII link (non-blocking) */
|
||||
void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
|
||||
{
|
||||
/* Write value at PHY address and register */
|
||||
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
|
||||
LPC_EMAC->MWTD = Value;
|
||||
}
|
||||
|
||||
/* Write a value via the MII link (blocking) */
|
||||
err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
|
||||
{
|
||||
u32_t mst = 250;
|
||||
err_t sts = ERR_OK;
|
||||
|
||||
/* Write value at PHY address and register */
|
||||
lpc_mii_write_noblock(PhyReg, Value);
|
||||
|
||||
/* Wait for unbusy status */
|
||||
while (mst > 0) {
|
||||
sts = LPC_EMAC->MIND;
|
||||
if ((sts & EMAC_MIND_BUSY) == 0)
|
||||
mst = 0;
|
||||
else {
|
||||
mst--;
|
||||
osDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (sts != 0)
|
||||
sts = ERR_TIMEOUT;
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* Reads current MII link busy status */
|
||||
u32_t lpc_mii_is_busy(void)
|
||||
{
|
||||
return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
|
||||
}
|
||||
|
||||
/* Starts a read operation via the MII link (non-blocking) */
|
||||
u32_t lpc_mii_read_data(void)
|
||||
{
|
||||
u32_t data = LPC_EMAC->MRDD;
|
||||
LPC_EMAC->MCMD = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/* Starts a read operation via the MII link (non-blocking) */
|
||||
void lpc_mii_read_noblock(u32_t PhyReg)
|
||||
{
|
||||
/* Read value at PHY address and register */
|
||||
LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
|
||||
LPC_EMAC->MCMD = EMAC_MCMD_READ;
|
||||
}
|
||||
|
||||
/* Read a value via the MII link (blocking) */
|
||||
err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
|
||||
{
|
||||
u32_t mst = 250;
|
||||
err_t sts = ERR_OK;
|
||||
|
||||
/* Read value at PHY address and register */
|
||||
lpc_mii_read_noblock(PhyReg);
|
||||
|
||||
/* Wait for unbusy status */
|
||||
while (mst > 0) {
|
||||
sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
|
||||
if ((sts & EMAC_MIND_BUSY) == 0) {
|
||||
mst = 0;
|
||||
*data = LPC_EMAC->MRDD;
|
||||
} else {
|
||||
mst--;
|
||||
osDelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
LPC_EMAC->MCMD = 0;
|
||||
|
||||
if (sts != 0)
|
||||
sts = ERR_TIMEOUT;
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** \brief Update PHY status from passed value
|
||||
*
|
||||
* This function updates the current PHY status based on the
|
||||
* passed PHY status word. The PHY status indicate if the link
|
||||
* is active, the connection speed, and duplex.
|
||||
*
|
||||
* \param[in] netif NETIF structure
|
||||
* \param[in] linksts Status word from PHY
|
||||
* \return 1 if the status has changed, otherwise 0
|
||||
*/
|
||||
static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
|
||||
{
|
||||
s32_t changed = 0;
|
||||
|
||||
/* Update link active status */
|
||||
if (linksts & LNK_STAT_VALID)
|
||||
physts.phy_link_active = 1;
|
||||
else
|
||||
physts.phy_link_active = 0;
|
||||
|
||||
/* Full or half duplex */
|
||||
if (linksts & LNK_STAT_FULLDUPLEX)
|
||||
physts.phy_full_duplex = 1;
|
||||
else
|
||||
physts.phy_full_duplex = 0;
|
||||
|
||||
/* Configure 100MBit/10MBit mode. */
|
||||
if (linksts & LNK_STAT_SPEED10MPS)
|
||||
physts.phy_speed_100mbs = 0;
|
||||
else
|
||||
physts.phy_speed_100mbs = 1;
|
||||
|
||||
if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
|
||||
changed = 1;
|
||||
if (physts.phy_speed_100mbs) {
|
||||
/* 100MBit mode. */
|
||||
lpc_emac_set_speed(1);
|
||||
|
||||
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
}
|
||||
else {
|
||||
/* 10MBit mode. */
|
||||
lpc_emac_set_speed(0);
|
||||
|
||||
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
|
||||
}
|
||||
|
||||
olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
|
||||
}
|
||||
|
||||
if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
|
||||
changed = 1;
|
||||
if (physts.phy_full_duplex)
|
||||
lpc_emac_set_duplex(1);
|
||||
else
|
||||
lpc_emac_set_duplex(0);
|
||||
|
||||
olddphysts.phy_full_duplex = physts.phy_full_duplex;
|
||||
}
|
||||
|
||||
if (physts.phy_link_active != olddphysts.phy_link_active) {
|
||||
changed = 1;
|
||||
#if NO_SYS == 1
|
||||
if (physts.phy_link_active)
|
||||
netif_set_link_up(netif);
|
||||
else
|
||||
netif_set_link_down(netif);
|
||||
#else
|
||||
if (physts.phy_link_active)
|
||||
tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
|
||||
(void*) netif, 1);
|
||||
else
|
||||
tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
|
||||
(void*) netif, 1);
|
||||
#endif
|
||||
|
||||
olddphysts.phy_link_active = physts.phy_link_active;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/** \brief Initialize the DP83848 PHY.
|
||||
*
|
||||
* This function initializes the DP83848 PHY. It will block until
|
||||
* complete. This function is called as part of the EMAC driver
|
||||
* initialization. Configuration of the PHY at startup is
|
||||
* controlled by setting up configuration defines in lpc_phy.h.
|
||||
*
|
||||
* \param[in] netif NETIF structure
|
||||
* \param[in] rmii If set, configures the PHY for RMII mode
|
||||
* \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
|
||||
*/
|
||||
err_t lpc_phy_init(struct netif *netif, int rmii)
|
||||
{
|
||||
u32_t tmp;
|
||||
s32_t i;
|
||||
|
||||
physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
|
||||
physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
|
||||
physts.phy_link_active = olddphysts.phy_link_active = 0;
|
||||
phyustate = 0;
|
||||
|
||||
/* Only first read and write are checked for failure */
|
||||
/* Put the DP83848C in reset mode and wait for completion */
|
||||
if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
|
||||
return ERR_TIMEOUT;
|
||||
i = 400;
|
||||
while (i > 0) {
|
||||
osDelay(1); /* 1 ms */
|
||||
if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
|
||||
return ERR_TIMEOUT;
|
||||
|
||||
if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
|
||||
i = -1;
|
||||
else
|
||||
i--;
|
||||
}
|
||||
/* Timeout? */
|
||||
if (i == 0)
|
||||
return ERR_TIMEOUT;
|
||||
|
||||
// read PHY ID
|
||||
lpc_mii_read(DP8_IDR1_REG, &tmp);
|
||||
phy_id = (tmp << 16);
|
||||
lpc_mii_read(DP8_IDR2_REG, &tmp);
|
||||
phy_id |= (tmp & 0XFFF0);
|
||||
|
||||
/* Setup link based on configuration options */
|
||||
#if PHY_USE_AUTONEG==1
|
||||
tmp = DP8_AUTONEG;
|
||||
#else
|
||||
tmp = 0;
|
||||
#endif
|
||||
#if PHY_USE_100MBS==1
|
||||
tmp |= DP8_SPEED_SELECT;
|
||||
#endif
|
||||
#if PHY_USE_FULL_DUPLEX==1
|
||||
tmp |= DP8_DUPLEX_MODE;
|
||||
#endif
|
||||
lpc_mii_write(DP8_BMCR_REG, tmp);
|
||||
|
||||
/* Enable RMII mode for PHY */
|
||||
if (rmii)
|
||||
lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
|
||||
|
||||
/* The link is not set active at this point, but will be detected
|
||||
later */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Phy status update state machine */
|
||||
s32_t lpc_phy_sts_sm(struct netif *netif)
|
||||
{
|
||||
s32_t changed = 0;
|
||||
u32_t data = 0;
|
||||
u32_t tmp;
|
||||
|
||||
switch (phyustate) {
|
||||
default:
|
||||
case 0:
|
||||
if (phy_id == DP83848C_ID) {
|
||||
lpc_mii_read_noblock(DP8_PHY_STAT_REG);
|
||||
phyustate = 2;
|
||||
}
|
||||
else if (phy_id == LAN8720_ID) {
|
||||
lpc_mii_read_noblock(DP8_PHY_SCSR_REG);
|
||||
phyustate = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (phy_id == LAN8720_ID) {
|
||||
tmp = lpc_mii_read_data();
|
||||
// we get speed and duplex here.
|
||||
phy_lan7420_sts_tmp = (tmp & PHY_SCSR_DUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
|
||||
phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
|
||||
|
||||
//read the status register to get link status
|
||||
lpc_mii_read_noblock(DP8_BMSR_REG);
|
||||
phyustate = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* Wait for read status state */
|
||||
if (!lpc_mii_is_busy()) {
|
||||
/* Update PHY status */
|
||||
tmp = lpc_mii_read_data();
|
||||
|
||||
if (phy_id == DP83848C_ID) {
|
||||
// STS register contains all needed status bits
|
||||
data = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0;
|
||||
data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
|
||||
data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
|
||||
}
|
||||
else if (phy_id == LAN8720_ID) {
|
||||
// we only get the link status here.
|
||||
phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0;
|
||||
data = phy_lan7420_sts_tmp;
|
||||
}
|
||||
|
||||
changed = lpc_update_phy_sts(netif, data);
|
||||
phyustate = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
|
@ -0,0 +1,30 @@
|
|||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LWIPOPTS_CONF_H
|
||||
#define LWIPOPTS_CONF_H
|
||||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
|
||||
#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
|
||||
#define MEM_SIZE 15360
|
||||
#elif defined(TARGET_LPC1768)
|
||||
#define MEM_SIZE 16362
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (C) 2012 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LWIPOPTS_CONF_H
|
||||
#define LWIPOPTS_CONF_H
|
||||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
|
||||
#define MEM_SIZE (1600 * 16)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,192 @@
|
|||
#include "lwip/opt.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "mbed_interface.h"
|
||||
#include "ethernet_api.h"
|
||||
#include "ethernetext_api.h"
|
||||
|
||||
#define RECV_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_PRI (osPriorityNormal)
|
||||
#define PHY_TASK_WAIT (200)
|
||||
|
||||
/* memory */
|
||||
static sys_sem_t recv_ready_sem; /* receive ready semaphore */
|
||||
|
||||
/* function */
|
||||
static void rza1_recv_task(void *arg);
|
||||
static void rza1_phy_task(void *arg);
|
||||
static err_t rza1_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
|
||||
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p);
|
||||
static void rza1_recv_callback(void);
|
||||
|
||||
static void rza1_recv_task(void *arg) {
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
struct eth_hdr *ethhdr;
|
||||
u16_t recv_size;
|
||||
struct pbuf *p;
|
||||
struct pbuf *q;
|
||||
|
||||
while (1) {
|
||||
sys_arch_sem_wait(&recv_ready_sem, 0);
|
||||
recv_size = ethernet_receive();
|
||||
if (recv_size != 0) {
|
||||
p = pbuf_alloc(PBUF_RAW, recv_size, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
(void)ethernet_read((char *)q->payload, q->len);
|
||||
}
|
||||
ethhdr = p->payload;
|
||||
switch (htons(ethhdr->type)) {
|
||||
case ETHTYPE_IP:
|
||||
case ETHTYPE_ARP:
|
||||
#if PPPOE_SUPPORT
|
||||
case ETHTYPE_PPPOEDISC:
|
||||
case ETHTYPE_PPPOE:
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
/* full packet send to tcpip_thread to process */
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
/* Free buffer */
|
||||
pbuf_free(p);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Return buffer */
|
||||
pbuf_free(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rza1_phy_task(void *arg) {
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
s32_t connect_sts = 0; /* 0: disconnect, 1:connect */
|
||||
s32_t link_sts;
|
||||
s32_t link_mode_new = NEGO_FAIL;
|
||||
s32_t link_mode_old = NEGO_FAIL;
|
||||
|
||||
while (1) {
|
||||
link_sts = ethernet_link();
|
||||
if (link_sts == 1) {
|
||||
link_mode_new = ethernetext_chk_link_mode();
|
||||
if (link_mode_new != link_mode_old) {
|
||||
if (connect_sts == 1) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
}
|
||||
if (link_mode_new != NEGO_FAIL) {
|
||||
ethernetext_set_link_mode(link_mode_new);
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
|
||||
connect_sts = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (connect_sts != 0) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
link_mode_new = NEGO_FAIL;
|
||||
connect_sts = 0;
|
||||
}
|
||||
}
|
||||
link_mode_old = link_mode_new;
|
||||
osDelay(PHY_TASK_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
static err_t rza1_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) {
|
||||
/* Only send packet is link is up */
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
return etharp_output(netif, q, ipaddr);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p) {
|
||||
struct pbuf *q;
|
||||
s32_t cnt;
|
||||
err_t err = ERR_MEM;
|
||||
s32_t write_size = 0;
|
||||
|
||||
if ((p->payload != NULL) && (p->len != 0)) {
|
||||
/* If the first data can't be written, transmit descriptor is full. */
|
||||
for (cnt = 0; cnt < 100; cnt++) {
|
||||
write_size = ethernet_write((char *)p->payload, p->len);
|
||||
if (write_size != 0) {
|
||||
break;
|
||||
}
|
||||
osDelay(1);
|
||||
}
|
||||
if (write_size != 0) {
|
||||
for (q = p->next; q != NULL; q = q->next) {
|
||||
(void)ethernet_write((char *)q->payload, q->len);
|
||||
}
|
||||
if (ethernet_send() == 1) {
|
||||
err = ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rza1_recv_callback(void) {
|
||||
sys_sem_signal(&recv_ready_sem);
|
||||
}
|
||||
|
||||
err_t eth_arch_enetif_init(struct netif *netif)
|
||||
{
|
||||
ethernet_cfg_t ethcfg;
|
||||
|
||||
/* set MAC hardware address */
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
netif->hwaddr[0] = MBED_MAC_ADDR_0;
|
||||
netif->hwaddr[1] = MBED_MAC_ADDR_1;
|
||||
netif->hwaddr[2] = MBED_MAC_ADDR_2;
|
||||
netif->hwaddr[3] = MBED_MAC_ADDR_3;
|
||||
netif->hwaddr[4] = MBED_MAC_ADDR_4;
|
||||
netif->hwaddr[5] = MBED_MAC_ADDR_5;
|
||||
#else
|
||||
mbed_mac_address((char *)netif->hwaddr);
|
||||
#endif
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* device capabilities */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwiprza1";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
|
||||
netif->output = rza1_etharp_output;
|
||||
netif->linkoutput = rza1_low_level_output;
|
||||
|
||||
/* Initialize the hardware */
|
||||
ethcfg.int_priority = 6;
|
||||
ethcfg.recv_cb = &rza1_recv_callback;
|
||||
ethcfg.ether_mac = (char *)netif->hwaddr;
|
||||
ethernetext_init(ðcfg);
|
||||
|
||||
/* semaphore */
|
||||
sys_sem_new(&recv_ready_sem, 0);
|
||||
|
||||
/* task */
|
||||
sys_thread_new("rza1_recv_task", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||||
sys_thread_new("rza1_phy_task", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void eth_arch_enable_interrupts(void) {
|
||||
ethernetext_start_stop(1);
|
||||
}
|
||||
|
||||
void eth_arch_disable_interrupts(void) {
|
||||
ethernetext_start_stop(0);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Copyright (C) 2015 mbed.org, MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LWIPOPTS_CONF_H
|
||||
#define LWIPOPTS_CONF_H
|
||||
|
||||
#define LWIP_TRANSPORT_ETHERNET 1
|
||||
|
||||
#define MEM_SIZE (1600 * 16)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,560 @@
|
|||
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include <string.h>
|
||||
#include "cmsis_os.h"
|
||||
#include "mbed_interface.h"
|
||||
|
||||
/** @defgroup lwipstm32f4xx_emac_DRIVER stm32f4 EMAC driver for LWIP
|
||||
* @ingroup lwip_emac
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define RECV_TASK_PRI (osPriorityHigh)
|
||||
#define PHY_TASK_PRI (osPriorityLow)
|
||||
#define PHY_TASK_WAIT (200)
|
||||
|
||||
|
||||
#if defined (__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; /* Ethernet Rx MA Descriptor */
|
||||
|
||||
#if defined (__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; /* Ethernet Tx DMA Descriptor */
|
||||
|
||||
#if defined (__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */
|
||||
|
||||
#if defined (__ICCARM__) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */
|
||||
|
||||
|
||||
ETH_HandleTypeDef heth;
|
||||
|
||||
static sys_sem_t rx_ready_sem; /* receive ready semaphore */
|
||||
static sys_mutex_t tx_lock_mutex;
|
||||
|
||||
/* function */
|
||||
static void stm32f4_rx_task(void *arg);
|
||||
static void stm32f4_phy_task(void *arg);
|
||||
static err_t stm32f4_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
|
||||
static err_t stm32f4_low_level_output(struct netif *netif, struct pbuf *p);
|
||||
|
||||
/**
|
||||
* Override HAL Eth Init function
|
||||
*/
|
||||
void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
if (heth->Instance == ETH) {
|
||||
/* Peripheral clock enable */
|
||||
__ETH_CLK_ENABLE();
|
||||
|
||||
__GPIOA_CLK_ENABLE();
|
||||
__GPIOB_CLK_ENABLE();
|
||||
__GPIOC_CLK_ENABLE();
|
||||
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB11 ------> ETH_TX_EN
|
||||
PB12 ------> ETH_TXD0
|
||||
PB13 ------> ETH_TXD1
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral interrupt init*/
|
||||
/* Sets the priority grouping field */
|
||||
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
|
||||
HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override HAL Eth DeInit function
|
||||
*/
|
||||
void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
|
||||
{
|
||||
if (heth->Instance == ETH) {
|
||||
/* Peripheral clock disable */
|
||||
__ETH_CLK_DISABLE();
|
||||
|
||||
/**ETH GPIO Configuration
|
||||
PC1 ------> ETH_MDC
|
||||
PA1 ------> ETH_REF_CLK
|
||||
PA2 ------> ETH_MDIO
|
||||
PA7 ------> ETH_CRS_DV
|
||||
PC4 ------> ETH_RXD0
|
||||
PC5 ------> ETH_RXD1
|
||||
PB11 ------> ETH_TX_EN
|
||||
PB12 ------> ETH_TXD0
|
||||
PB13 ------> ETH_TXD1
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13);
|
||||
|
||||
/* Peripheral interrupt Deinit*/
|
||||
HAL_NVIC_DisableIRQ(ETH_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ethernet Rx Transfer completed callback
|
||||
*
|
||||
* @param heth: ETH handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
|
||||
sys_sem_signal(&rx_ready_sem);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ethernet IRQ Handler
|
||||
*
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void ETH_IRQHandler(void)
|
||||
{
|
||||
HAL_ETH_IRQHandler(&heth);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* In this function, the hardware should be initialized.
|
||||
* Called from eth_arch_enetif_init().
|
||||
*
|
||||
* @param netif the already initialized lwip network interface structure
|
||||
* for this ethernetif
|
||||
*/
|
||||
static void stm32f4_low_level_init(struct netif *netif)
|
||||
{
|
||||
uint32_t regvalue = 0;
|
||||
HAL_StatusTypeDef hal_eth_init_status;
|
||||
|
||||
/* Init ETH */
|
||||
uint8_t MACAddr[6];
|
||||
heth.Instance = ETH;
|
||||
heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
|
||||
heth.Init.Speed = ETH_SPEED_10M;
|
||||
heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||
heth.Init.PhyAddress = 1;
|
||||
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||||
MACAddr[0] = MBED_MAC_ADDR_0;
|
||||
MACAddr[1] = MBED_MAC_ADDR_1;
|
||||
MACAddr[2] = MBED_MAC_ADDR_2;
|
||||
MACAddr[3] = MBED_MAC_ADDR_3;
|
||||
MACAddr[4] = MBED_MAC_ADDR_4;
|
||||
MACAddr[5] = MBED_MAC_ADDR_5;
|
||||
#else
|
||||
mbed_mac_address((char *)MACAddr);
|
||||
#endif
|
||||
heth.Init.MACAddr = &MACAddr[0];
|
||||
heth.Init.RxMode = ETH_RXINTERRUPT_MODE;
|
||||
heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
|
||||
heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
|
||||
hal_eth_init_status = HAL_ETH_Init(&heth);
|
||||
|
||||
if (hal_eth_init_status == HAL_OK) {
|
||||
/* Set netif link flag */
|
||||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
}
|
||||
|
||||
/* Initialize Tx Descriptors list: Chain Mode */
|
||||
HAL_ETH_DMATxDescListInit(&heth, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
|
||||
|
||||
/* Initialize Rx Descriptors list: Chain Mode */
|
||||
HAL_ETH_DMARxDescListInit(&heth, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
|
||||
|
||||
#if LWIP_ARP || LWIP_ETHERNET
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr[0] = heth.Init.MACAddr[0];
|
||||
netif->hwaddr[1] = heth.Init.MACAddr[1];
|
||||
netif->hwaddr[2] = heth.Init.MACAddr[2];
|
||||
netif->hwaddr[3] = heth.Init.MACAddr[3];
|
||||
netif->hwaddr[4] = heth.Init.MACAddr[4];
|
||||
netif->hwaddr[5] = heth.Init.MACAddr[5];
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* device capabilities */
|
||||
/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
|
||||
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
|
||||
|
||||
/* Enable MAC and DMA transmission and reception */
|
||||
HAL_ETH_Start(&heth);
|
||||
|
||||
/**** Configure PHY to generate an interrupt when Eth Link state changes ****/
|
||||
/* Read Register Configuration */
|
||||
HAL_ETH_ReadPHYRegister(&heth, PHY_MICR, ®value);
|
||||
|
||||
regvalue |= (PHY_MICR_INT_EN | PHY_MICR_INT_OE);
|
||||
|
||||
/* Enable Interrupts */
|
||||
HAL_ETH_WritePHYRegister(&heth, PHY_MICR, regvalue);
|
||||
|
||||
/* Read Register Configuration */
|
||||
HAL_ETH_ReadPHYRegister(&heth, PHY_MISR, ®value);
|
||||
|
||||
regvalue |= PHY_MISR_LINK_INT_EN;
|
||||
|
||||
/* Enable Interrupt on change of link status */
|
||||
HAL_ETH_WritePHYRegister(&heth, PHY_MISR, regvalue);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should do the actual transmission of the packet. The packet is
|
||||
* contained in the pbuf that is passed to the function. This pbuf
|
||||
* might be chained.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
|
||||
* @return ERR_OK if the packet could be sent
|
||||
* an err_t value if the packet couldn't be sent
|
||||
*
|
||||
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
|
||||
* strange results. You might consider waiting for space in the DMA queue
|
||||
* to become availale since the stack doesn't retry to send a packet
|
||||
* dropped because of memory failure (except for the TCP timers).
|
||||
*/
|
||||
|
||||
static err_t stm32f4_low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
err_t errval;
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer = (uint8_t*)(heth.TxDesc->Buffer1Addr);
|
||||
__IO ETH_DMADescTypeDef *DmaTxDesc;
|
||||
uint32_t framelength = 0;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
DmaTxDesc = heth.TxDesc;
|
||||
bufferoffset = 0;
|
||||
|
||||
|
||||
sys_mutex_lock(&tx_lock_mutex);
|
||||
|
||||
/* copy frame from pbufs to driver buffers */
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
/* Is this buffer available? If not, goto error */
|
||||
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
|
||||
errval = ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get bytes in current lwIP buffer */
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
||||
while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) {
|
||||
/* Copy data to Tx buffer*/
|
||||
memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), (ETH_TX_BUF_SIZE - bufferoffset));
|
||||
|
||||
/* Point to next descriptor */
|
||||
DmaTxDesc = (ETH_DMADescTypeDef*)(DmaTxDesc->Buffer2NextDescAddr);
|
||||
|
||||
/* Check if the buffer is available */
|
||||
if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) {
|
||||
errval = ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
buffer = (uint8_t*)(DmaTxDesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
|
||||
/* Copy the remaining bytes */
|
||||
memcpy((uint8_t*)((uint8_t*)buffer + bufferoffset), (uint8_t*)((uint8_t*)q->payload + payloadoffset), byteslefttocopy);
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
framelength = framelength + byteslefttocopy;
|
||||
}
|
||||
|
||||
/* Prepare transmit descriptors to give to DMA */
|
||||
HAL_ETH_TransmitFrame(&heth, framelength);
|
||||
|
||||
errval = ERR_OK;
|
||||
|
||||
error:
|
||||
|
||||
/* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */
|
||||
if ((heth.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) {
|
||||
/* Clear TUS ETHERNET DMA flag */
|
||||
heth.Instance->DMASR = ETH_DMASR_TUS;
|
||||
|
||||
/* Resume DMA transmission*/
|
||||
heth.Instance->DMATPDR = 0;
|
||||
}
|
||||
|
||||
sys_mutex_unlock(&tx_lock_mutex);
|
||||
|
||||
return errval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
* @param netif the lwip network interface structure for this ethernetif
|
||||
* @return a pbuf filled with the received packet (including MAC header)
|
||||
* NULL on memory error
|
||||
*/
|
||||
static struct pbuf * stm32f4_low_level_input(struct netif *netif)
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
struct pbuf *q;
|
||||
uint16_t len = 0;
|
||||
uint8_t *buffer;
|
||||
__IO ETH_DMADescTypeDef *dmarxdesc;
|
||||
uint32_t bufferoffset = 0;
|
||||
uint32_t payloadoffset = 0;
|
||||
uint32_t byteslefttocopy = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
|
||||
/* get received frame */
|
||||
if (HAL_ETH_GetReceivedFrame(&heth) != HAL_OK)
|
||||
return NULL;
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len" variable. */
|
||||
len = heth.RxFrameInfos.length;
|
||||
buffer = (uint8_t*)heth.RxFrameInfos.buffer;
|
||||
|
||||
if (len > 0) {
|
||||
/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
}
|
||||
|
||||
if (p != NULL) {
|
||||
dmarxdesc = heth.RxFrameInfos.FSRxDesc;
|
||||
bufferoffset = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
byteslefttocopy = q->len;
|
||||
payloadoffset = 0;
|
||||
|
||||
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
|
||||
while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) {
|
||||
/* Copy data to pbuf */
|
||||
memcpy((uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), (ETH_RX_BUF_SIZE - bufferoffset));
|
||||
|
||||
/* Point to next descriptor */
|
||||
dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr);
|
||||
buffer = (uint8_t*)(dmarxdesc->Buffer1Addr);
|
||||
|
||||
byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset);
|
||||
bufferoffset = 0;
|
||||
}
|
||||
/* Copy remaining data in pbuf */
|
||||
memcpy((uint8_t*)((uint8_t*)q->payload + payloadoffset), (uint8_t*)((uint8_t*)buffer + bufferoffset), byteslefttocopy);
|
||||
bufferoffset = bufferoffset + byteslefttocopy;
|
||||
}
|
||||
|
||||
/* Release descriptors to DMA */
|
||||
/* Point to first descriptor */
|
||||
dmarxdesc = heth.RxFrameInfos.FSRxDesc;
|
||||
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
|
||||
for (i = 0; i < heth.RxFrameInfos.SegCount; i++) {
|
||||
dmarxdesc->Status |= ETH_DMARXDESC_OWN;
|
||||
dmarxdesc = (ETH_DMADescTypeDef*)(dmarxdesc->Buffer2NextDescAddr);
|
||||
}
|
||||
|
||||
/* Clear Segment_Count */
|
||||
heth.RxFrameInfos.SegCount = 0;
|
||||
}
|
||||
|
||||
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
|
||||
if ((heth.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) {
|
||||
/* Clear RBUS ETHERNET DMA flag */
|
||||
heth.Instance->DMASR = ETH_DMASR_RBUS;
|
||||
/* Resume DMA reception */
|
||||
heth.Instance->DMARPDR = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* This task receives input data
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure
|
||||
*/
|
||||
static void stm32f4_rx_task(void *arg)
|
||||
{
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
struct pbuf *p;
|
||||
|
||||
while (1) {
|
||||
sys_arch_sem_wait(&rx_ready_sem, 0);
|
||||
p = stm32f4_low_level_input(netif);
|
||||
if (p != NULL) {
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This task checks phy link status and updates net status
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure
|
||||
*/
|
||||
static void stm32f4_phy_task(void *arg)
|
||||
{
|
||||
struct netif *netif = (struct netif*)arg;
|
||||
uint32_t phy_status = 0;
|
||||
|
||||
while (1) {
|
||||
uint32_t status;
|
||||
if (HAL_ETH_ReadPHYRegister(&heth, PHY_SR, &status) == HAL_OK) {
|
||||
if ((status & PHY_LINK_STATUS) && !(phy_status & PHY_LINK_STATUS)) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
|
||||
} else if (!(status & PHY_LINK_STATUS) && (phy_status & PHY_LINK_STATUS)) {
|
||||
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||||
}
|
||||
|
||||
phy_status = status;
|
||||
}
|
||||
|
||||
osDelay(PHY_TASK_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is the ethernet packet send function. It calls
|
||||
* etharp_output after checking link status.
|
||||
*
|
||||
* \param[in] netif the lwip network interface structure for this lpc_enetif
|
||||
* \param[in] q Pointer to pbug to send
|
||||
* \param[in] ipaddr IP address
|
||||
* \return ERR_OK or error code
|
||||
*/
|
||||
static err_t stm32f4_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
|
||||
{
|
||||
/* Only send packet is link is up */
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
return etharp_output(netif, q, ipaddr);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called at the beginning of the program to set up the
|
||||
* network interface.
|
||||
*
|
||||
* This function should be passed as a parameter to netif_add().
|
||||
*
|
||||
* @param[in] netif the lwip network interface structure for this lpc_enetif
|
||||
* @return ERR_OK if the loopif is initialized
|
||||
* ERR_MEM if private data couldn't be allocated
|
||||
* any other err_t on error
|
||||
*/
|
||||
err_t eth_arch_enetif_init(struct netif *netif)
|
||||
{
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* device capabilities */
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
|
||||
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwipstm32f4";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
netif->name[0] = 'e';
|
||||
netif->name[1] = 'n';
|
||||
|
||||
netif->output = stm32f4_etharp_output;
|
||||
netif->linkoutput = stm32f4_low_level_output;
|
||||
|
||||
/* semaphore */
|
||||
sys_sem_new(&rx_ready_sem, 0);
|
||||
|
||||
sys_mutex_new(&tx_lock_mutex);
|
||||
|
||||
/* task */
|
||||
sys_thread_new("stm32f4_recv_task", stm32f4_rx_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||||
sys_thread_new("stm32f4_phy_task", stm32f4_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||||
|
||||
/* initialize the hardware */
|
||||
stm32f4_low_level_init(netif);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void eth_arch_enable_interrupts(void)
|
||||
{
|
||||
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
|
||||
HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(ETH_IRQn);
|
||||
}
|
||||
|
||||
void eth_arch_disable_interrupts(void)
|
||||
{
|
||||
NVIC_DisableIRQ(ETH_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* --------------------------------- End Of File ------------------------------ */
|
Loading…
Add table
Add a link
Reference in a new issue