This commit is contained in:
Richard Barry 2020-02-07 21:49:55 +00:00
parent 589dd9f149
commit 7cf721ccf7
36 changed files with 15170 additions and 15098 deletions

View file

@ -0,0 +1,3 @@
Update pack_struct_start.h and pack_struct_end.h for your architecure.
These files define the specifiers needed by your compiler to properly pack struct data
need by FreeRTOS+TCP.

View file

@ -0,0 +1,32 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
; /* FIX ME. Update for the compiler specifier needed at end of a struct declartion to pack the struct. */

View file

@ -0,0 +1,32 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
/* FIX ME. Update for the compiler specifier needed at the start of a struct declartion to pack the struct. */

View file

@ -1,454 +1,454 @@
/** /**
* \file * \file
* *
* \brief API driver for KSZ8051MNL PHY component. * \brief API driver for KSZ8051MNL PHY component.
* *
* Copyright (c) 2013 Atmel Corporation. All rights reserved. * Copyright (c) 2013 Atmel Corporation. All rights reserved.
* *
* \asf_license_start * \asf_license_start
* *
* \page License * \page License
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* 3. The name of Atmel may not be used to endorse or promote products derived * 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission. * from this software without specific prior written permission.
* *
* 4. This software may only be redistributed and used in connection with an * 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product. * Atmel microcontroller product.
* *
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* \asf_license_stop * \asf_license_stop
* *
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "FreeRTOSIPConfig.h" #include "FreeRTOSIPConfig.h"
#include "ethernet_phy.h" #include "ethernet_phy.h"
#include "instance/gmac.h" #include "instance/gmac.h"
/// @cond 0 /// @cond 0
/**INDENT-OFF**/ /**INDENT-OFF**/
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**INDENT-ON**/ /**INDENT-ON**/
/// @endcond /// @endcond
/** /**
* \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL) * \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
* *
* Driver for the ksz8051mnl component. This driver provides access to the main * Driver for the ksz8051mnl component. This driver provides access to the main
* features of the PHY. * features of the PHY.
* *
* \section dependencies Dependencies * \section dependencies Dependencies
* This driver depends on the following modules: * This driver depends on the following modules:
* - \ref gmac_group Ethernet Media Access Controller (GMAC) module. * - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
* *
* @{ * @{
*/ */
SPhyProps phyProps; SPhyProps phyProps;
/* Max PHY number */ /* Max PHY number */
#define ETH_PHY_MAX_ADDR 31 #define ETH_PHY_MAX_ADDR 31
/* Ethernet PHY operation max retry count */ /* Ethernet PHY operation max retry count */
#define ETH_PHY_RETRY_MAX 1000000 #define ETH_PHY_RETRY_MAX 1000000
/* Ethernet PHY operation timeout */ /* Ethernet PHY operation timeout */
#define ETH_PHY_TIMEOUT 10 #define ETH_PHY_TIMEOUT 10
/** /**
* \brief Find a valid PHY Address ( from addrStart to 31 ). * \brief Find a valid PHY Address ( from addrStart to 31 ).
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* \param uc_start_addr Start address of the PHY to be searched. * \param uc_start_addr Start address of the PHY to be searched.
* *
* \return 0xFF when no valid PHY address is found. * \return 0xFF when no valid PHY address is found.
*/ */
int ethernet_phy_addr = 0; int ethernet_phy_addr = 0;
static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr, static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_start_addr) uint8_t uc_start_addr)
{ {
uint32_t ul_value = 0; uint32_t ul_value = 0;
uint8_t uc_cnt; uint8_t uc_cnt;
uint8_t uc_phy_address = uc_phy_addr; uint8_t uc_phy_address = uc_phy_addr;
gmac_enable_management(p_gmac, true); gmac_enable_management(p_gmac, true);
/* /*
#define GMII_OUI_MSB 0x0022 #define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05 #define GMII_OUI_LSB 0x05
PHYID1 = 0x0022 PHYID1 = 0x0022
PHYID2 = 0x1550 PHYID2 = 0x1550
0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0 0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
*/ */
/* Check the current PHY address */ /* Check the current PHY address */
gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value); gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
/* Find another one */ /* Find another one */
if (ul_value != GMII_OUI_MSB) { if (ul_value != GMII_OUI_MSB) {
ethernet_phy_addr = 0xFF; ethernet_phy_addr = 0xFF;
for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) { for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
uc_phy_address = (uc_phy_address + 1) & 0x1F; uc_phy_address = (uc_phy_address + 1) & 0x1F;
ul_value = 0; ul_value = 0;
gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value); gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
if (ul_value == GMII_OUI_MSB) { if (ul_value == GMII_OUI_MSB) {
ethernet_phy_addr = uc_phy_address; ethernet_phy_addr = uc_phy_address;
break; break;
} }
} }
} }
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
if (ethernet_phy_addr != 0xFF) { if (ethernet_phy_addr != 0xFF) {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value); gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
} }
return ethernet_phy_addr; return ethernet_phy_addr;
} }
/** /**
* \brief Perform a HW initialization to the PHY and set up clocks. * \brief Perform a HW initialization to the PHY and set up clocks.
* *
* This should be called only once to initialize the PHY pre-settings. * This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups). * The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII). * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode). * The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins. * The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done. * The GMAC peripheral pins are configured after the reset is done.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK. * \param ul_mck GMAC MCK.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck) uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
{ {
uint8_t uc_rc = GMAC_TIMEOUT; uint8_t uc_rc = GMAC_TIMEOUT;
uint8_t uc_phy; uint8_t uc_phy;
ethernet_phy_reset(GMAC,uc_phy_addr); ethernet_phy_reset(GMAC,uc_phy_addr);
/* Configure GMAC runtime clock */ /* Configure GMAC runtime clock */
uc_rc = gmac_set_mdc_clock(p_gmac, mck); uc_rc = gmac_set_mdc_clock(p_gmac, mck);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
return 0; return 0;
} }
/* Check PHY Address */ /* Check PHY Address */
uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0); uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
if (uc_phy == 0xFF) { if (uc_phy == 0xFF) {
return 0; return 0;
} }
if (uc_phy != uc_phy_addr) { if (uc_phy != uc_phy_addr) {
ethernet_phy_reset(p_gmac, uc_phy_addr); ethernet_phy_reset(p_gmac, uc_phy_addr);
} }
phy_props.phy_chn = uc_phy; phy_props.phy_chn = uc_phy;
return uc_phy; return uc_phy;
} }
/** /**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the * \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings. * settings.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply. * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr, uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag) uint8_t uc_apply_setting_flag)
{ {
uint32_t ul_stat1; uint32_t ul_stat1;
uint32_t ul_stat2; uint32_t ul_stat2;
uint8_t uc_phy_address, uc_speed = true, uc_fd = true; uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
uint8_t uc_rc = GMAC_TIMEOUT; uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true); gmac_enable_management(p_gmac, true);
uc_phy_address = uc_phy_addr; uc_phy_address = uc_phy_addr;
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1); uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */ /* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
return uc_rc; return uc_rc;
} }
if ((ul_stat1 & GMII_LINK_STATUS) == 0) { if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
/* Disable PHY management and start the GMAC transfer */ /* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
return GMAC_INVALID; return GMAC_INVALID;
} }
if (uc_apply_setting_flag == 0) { if (uc_apply_setting_flag == 0) {
/* Disable PHY management and start the GMAC transfer */ /* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
return uc_rc; return uc_rc;
} }
/* Read advertisement */ /* Read advertisement */
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2); uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
phy_props.phy_stat1 = ul_stat1; phy_props.phy_stat1 = ul_stat1;
phy_props.phy_stat2 = ul_stat2; phy_props.phy_stat2 = ul_stat2;
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */ /* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
return uc_rc; return uc_rc;
} }
if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) { if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
/* Set GMAC for 100BaseTX and Full Duplex */ /* Set GMAC for 100BaseTX and Full Duplex */
uc_speed = true; uc_speed = true;
uc_fd = true; uc_fd = true;
} else } else
if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) { if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
/* Set MII for 100BaseTX and Half Duplex */ /* Set MII for 100BaseTX and Half Duplex */
uc_speed = true; uc_speed = true;
uc_fd = false; uc_fd = false;
} else } else
if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) { if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
/* Set MII for 10BaseT and Full Duplex */ /* Set MII for 10BaseT and Full Duplex */
uc_speed = false; uc_speed = false;
uc_fd = true; uc_fd = true;
} else } else
if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) { if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
/* Set MII for 10BaseT and Half Duplex */ /* Set MII for 10BaseT and Half Duplex */
uc_speed = false; uc_speed = false;
uc_fd = false; uc_fd = false;
} }
gmac_set_speed(p_gmac, uc_speed); gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd); gmac_enable_full_duplex(p_gmac, uc_fd);
/* Start the GMAC transfers */ /* Start the GMAC transfers */
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
return uc_rc; return uc_rc;
} }
PhyProps_t phy_props; PhyProps_t phy_props;
/** /**
* \brief Issue an auto negotiation of the PHY. * \brief Issue an auto negotiation of the PHY.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr) uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
{ {
uint32_t ul_retry_max = ETH_PHY_RETRY_MAX; uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
uint32_t ul_value; uint32_t ul_value;
uint32_t ul_phy_anar; uint32_t ul_phy_anar;
uint32_t ul_retry_count = 0; uint32_t ul_retry_count = 0;
uint8_t uc_speed = 0; uint8_t uc_speed = 0;
uint8_t uc_fd=0; uint8_t uc_fd=0;
uint8_t uc_rc = GMAC_TIMEOUT; uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true); gmac_enable_management(p_gmac, true);
/* Set up control register */ /* Set up control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value); uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -1; phy_props.phy_result = -1;
return uc_rc; return uc_rc;
} }
ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */ ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN); ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */ ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value); uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -2; phy_props.phy_result = -2;
return uc_rc; return uc_rc;
} }
/* /*
* Set the Auto_negotiation Advertisement Register. * Set the Auto_negotiation Advertisement Register.
* MII advertising for Next page. * MII advertising for Next page.
* 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3. * 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
*/ */
ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX | ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
GMII_AN_IEEE_802_3; GMII_AN_IEEE_802_3;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar); uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -3; phy_props.phy_result = -3;
return uc_rc; return uc_rc;
} }
/* Read & modify control register */ /* Read & modify control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value); uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -4; phy_props.phy_result = -4;
return uc_rc; return uc_rc;
} }
ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE; ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value); uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -5; phy_props.phy_result = -5;
return uc_rc; return uc_rc;
} }
/* Restart auto negotiation */ /* Restart auto negotiation */
ul_value |= (uint32_t)GMII_RESTART_AUTONEG; ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
ul_value &= ~(uint32_t)GMII_ISOLATE; ul_value &= ~(uint32_t)GMII_ISOLATE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value); uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -6; phy_props.phy_result = -6;
return uc_rc; return uc_rc;
} }
/* Check if auto negotiation is completed */ /* Check if auto negotiation is completed */
while (1) { while (1) {
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value); uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -7; phy_props.phy_result = -7;
return uc_rc; return uc_rc;
} }
/* Done successfully */ /* Done successfully */
if (ul_value & GMII_AUTONEG_COMP) { if (ul_value & GMII_AUTONEG_COMP) {
break; break;
} }
/* Timeout check */ /* Timeout check */
if (ul_retry_max) { if (ul_retry_max) {
if (++ul_retry_count >= ul_retry_max) { if (++ul_retry_count >= ul_retry_max) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -8; phy_props.phy_result = -8;
return GMAC_TIMEOUT; return GMAC_TIMEOUT;
} }
} }
} }
/* Get the auto negotiate link partner base page */ /* Get the auto negotiate link partner base page */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params); uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
if (uc_rc != GMAC_OK) { if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = -9; phy_props.phy_result = -9;
return uc_rc; return uc_rc;
} }
/* Set up the GMAC link speed */ /* Set up the GMAC link speed */
if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) { if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
/* Set MII for 100BaseTX and Full Duplex */ /* Set MII for 100BaseTX and Full Duplex */
uc_speed = true; uc_speed = true;
uc_fd = true; uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) { } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
/* Set MII for 10BaseT and Full Duplex */ /* Set MII for 10BaseT and Full Duplex */
uc_speed = false; uc_speed = false;
uc_fd = true; uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) { } else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
/* Set MII for 100BaseTX and half Duplex */ /* Set MII for 100BaseTX and half Duplex */
uc_speed = true; uc_speed = true;
uc_fd = false; uc_fd = false;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) { } else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
/* Set MII for 10BaseT and half Duplex */ /* Set MII for 10BaseT and half Duplex */
uc_speed = false; uc_speed = false;
uc_fd = false; uc_fd = false;
} }
gmac_set_speed(p_gmac, uc_speed); gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd); gmac_enable_full_duplex(p_gmac, uc_fd);
/* Select Media Independent Interface type */ /* Select Media Independent Interface type */
gmac_select_mii_mode(p_gmac, ETH_PHY_MODE); gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
gmac_enable_transmit(GMAC, true); gmac_enable_transmit(GMAC, true);
gmac_enable_receive(GMAC, true); gmac_enable_receive(GMAC, true);
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
phy_props.phy_result = 1; phy_props.phy_result = 1;
return uc_rc; return uc_rc;
} }
/** /**
* \brief Issue a SW reset to reset all registers of the PHY. * \brief Issue a SW reset to reset all registers of the PHY.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* *
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr) uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
{ {
uint32_t ul_bmcr = GMII_RESET; uint32_t ul_bmcr = GMII_RESET;
uint8_t uc_phy_address = uc_phy_addr; uint8_t uc_phy_address = uc_phy_addr;
uint32_t ul_timeout = ETH_PHY_TIMEOUT; uint32_t ul_timeout = ETH_PHY_TIMEOUT;
uint8_t uc_rc = GMAC_TIMEOUT; uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true); gmac_enable_management(p_gmac, true);
ul_bmcr = GMII_RESET; ul_bmcr = GMII_RESET;
gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr); gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
do { do {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr); gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
ul_timeout--; ul_timeout--;
} while ((ul_bmcr & GMII_RESET) && ul_timeout); } while ((ul_bmcr & GMII_RESET) && ul_timeout);
gmac_enable_management(p_gmac, false); gmac_enable_management(p_gmac, false);
if (!ul_timeout) { if (!ul_timeout) {
uc_rc = GMAC_OK; uc_rc = GMAC_OK;
} }
return (uc_rc); return (uc_rc);
} }
/// @cond 0 /// @cond 0
/**INDENT-OFF**/ /**INDENT-OFF**/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/**INDENT-ON**/ /**INDENT-ON**/
/// @endcond /// @endcond
/** /**
* \} * \}
*/ */

View file

@ -1,281 +1,281 @@
/** /**
* \file * \file
* *
* \brief KSZ8051MNL (Ethernet PHY) driver for SAM. * \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
* *
* Copyright (c) 2013 Atmel Corporation. All rights reserved. * Copyright (c) 2013 Atmel Corporation. All rights reserved.
* *
* \asf_license_start * \asf_license_start
* *
* \page License * \page License
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* 3. The name of Atmel may not be used to endorse or promote products derived * 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission. * from this software without specific prior written permission.
* *
* 4. This software may only be redistributed and used in connection with an * 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product. * Atmel microcontroller product.
* *
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* \asf_license_stop * \asf_license_stop
* *
*/ */
#ifndef ETHERNET_PHY_H_INCLUDED #ifndef ETHERNET_PHY_H_INCLUDED
#define ETHERNET_PHY_H_INCLUDED #define ETHERNET_PHY_H_INCLUDED
#include "compiler.h" #include "compiler.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
// IEEE defined Registers // IEEE defined Registers
#define GMII_BMCR 0x00 // Basic Control #define GMII_BMCR 0x00 // Basic Control
#define GMII_BMSR 0x01 // Basic Status #define GMII_BMSR 0x01 // Basic Status
#define GMII_PHYID1 0x02 // PHY Idendifier 1 #define GMII_PHYID1 0x02 // PHY Idendifier 1
#define GMII_PHYID2 0x03 // PHY Idendifier 2 #define GMII_PHYID2 0x03 // PHY Idendifier 2
#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement #define GMII_ANAR 0x04 // Auto_Negotiation Advertisement
#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability #define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability
#define GMII_ANER 0x06 // Auto-negotiation Expansion #define GMII_ANER 0x06 // Auto-negotiation Expansion
#define GMII_ANNPR 0x07 // Auto-negotiation Next Page #define GMII_ANNPR 0x07 // Auto-negotiation Next Page
#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability #define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability
//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved //#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved
//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved //#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved
#define GMII_AFECR1 0x11 // AFE Control 1 #define GMII_AFECR1 0x11 // AFE Control 1
//#define GMII_ERDWR 12 // Extend Register - Data Write Register //#define GMII_ERDWR 12 // Extend Register - Data Write Register
//#define GMII_ERDRR 13 // Extend Register - Data Read Register //#define GMII_ERDRR 13 // Extend Register - Data Read Register
//14 reserved //14 reserved
#define GMII_RXERCR 0x15 // RXER Counter #define GMII_RXERCR 0x15 // RXER Counter
#define PHY_REG_01_BMSR 0x01 // Basic mode status register #define PHY_REG_01_BMSR 0x01 // Basic mode status register
#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1 #define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2 #define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg #define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
#define PHY_REG_05_LPA 0x05 // Link partner ability reg #define PHY_REG_05_LPA 0x05 // Link partner ability reg
#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register #define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX #define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED #define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
#define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register #define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register
#define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register #define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register
#define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register #define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register
#define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED #define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED
#define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register #define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register
#define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register #define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register
#define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register #define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register
#define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register #define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register
#define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register #define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register
#define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register #define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register
#define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register #define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register
#define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register #define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register
#define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control #define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control
#define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED #define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED
#define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register #define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register
#define PHY_REG_1E_RESERVED3 0x1E // #define PHY_REG_1E_RESERVED3 0x1E //
#define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED #define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED
#define PHY_REG_1E_PHYCR_1 0x1E // #define PHY_REG_1E_PHYCR_1 0x1E //
#define PHY_REG_1F_PHYCR_2 0x1F // #define PHY_REG_1F_PHYCR_2 0x1F //
#define PHY_SPEED_10 1 #define PHY_SPEED_10 1
#define PHY_SPEED_100 2 #define PHY_SPEED_100 2
#define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100) #define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)
#define PHY_MDIX_DIRECT 1 #define PHY_MDIX_DIRECT 1
#define PHY_MDIX_CROSSED 2 #define PHY_MDIX_CROSSED 2
#define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT) #define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
#define PHY_DUPLEX_HALF 1 #define PHY_DUPLEX_HALF 1
#define PHY_DUPLEX_FULL 2 #define PHY_DUPLEX_FULL 2
#define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF) #define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
typedef struct _SPhyProps { typedef struct _SPhyProps {
unsigned char speed; unsigned char speed;
unsigned char mdix; unsigned char mdix;
unsigned char duplex; unsigned char duplex;
unsigned char spare; unsigned char spare;
} SPhyProps; } SPhyProps;
const char *phyPrintable (const SPhyProps *apProps); const char *phyPrintable (const SPhyProps *apProps);
extern SPhyProps phyProps; extern SPhyProps phyProps;
#define GMII_OMSOR 0x16 // Operation Mode Strap Override #define GMII_OMSOR 0x16 // Operation Mode Strap Override
#define GMII_OMSSR 0x17 // Operation Mode Strap Status #define GMII_OMSSR 0x17 // Operation Mode Strap Status
#define GMII_ECR 0x18 // Expanded Control #define GMII_ECR 0x18 // Expanded Control
//#define GMII_DPPSR 19 // Digital PMA/PCS Status //#define GMII_DPPSR 19 // Digital PMA/PCS Status
//20 reserved //20 reserved
//#define GMII_RXERCR 21 // RXER Counter Register //#define GMII_RXERCR 21 // RXER Counter Register
//22-26 reserved //22-26 reserved
#define GMII_ICSR 0x1B // Interrupt Control/Status #define GMII_ICSR 0x1B // Interrupt Control/Status
//#define GMII_DDC1R 28 // Digital Debug Control 1 Register //#define GMII_DDC1R 28 // Digital Debug Control 1 Register
#define GMII_LCSR 0x1D // LinkMD Control/Status #define GMII_LCSR 0x1D // LinkMD Control/Status
//29-30 reserved //29-30 reserved
#define GMII_PCR1 0x1E // PHY Control 1 #define GMII_PCR1 0x1E // PHY Control 1
#define GMII_PCR2 0x1F // PHY Control 2 #define GMII_PCR2 0x1F // PHY Control 2
/* /*
//Extend Registers //Extend Registers
#define GMII_CCR 256 // Common Control Register #define GMII_CCR 256 // Common Control Register
#define GMII_SSR 257 // Strap Status Register #define GMII_SSR 257 // Strap Status Register
#define GMII_OMSOR 258 // Operation Mode Strap Override Register #define GMII_OMSOR 258 // Operation Mode Strap Override Register
#define GMII_OMSSR 259 // Operation Mode Strap Status Register #define GMII_OMSSR 259 // Operation Mode Strap Status Register
#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register #define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register
#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register #define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register
#define GMII_ATR 263 // Analog Test Register #define GMII_ATR 263 // Analog Test Register
*/ */
// Bit definitions: GMII_BMCR 0x00 Basic Control // Bit definitions: GMII_BMCR 0x00 Basic Control
#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation #define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation #define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps #define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps
#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable #define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation #define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation #define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation #define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation #define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test #define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test
//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved //#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved
// Reserved 6 to 0 // Read as 0, ignore on write // Reserved 6 to 0 // Read as 0, ignore on write
// Bit definitions: GMII_BMSR 0x01 Basic Status // Bit definitions: GMII_BMSR 0x01 Basic Status
#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable #define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable #define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable #define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable #define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable #define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
// Reserved 10 to79 // Read as 0, ignore on write // Reserved 10 to79 // Read as 0, ignore on write
//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15 //#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
// Reserved 7 // Reserved 7
#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression #define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete #define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault #define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability #define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
#define GMII_LINK_STATUS (1 << 2) // Link Status #define GMII_LINK_STATUS (1 << 2) // Link Status
#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect #define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability #define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1 // Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2 // Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
#define GMII_LSB_MASK 0x3F #define GMII_LSB_MASK 0x3F
#define GMII_OUI_MSB 0x0022 #define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05 #define GMII_OUI_LSB 0x05
// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement // Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement
// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability // Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
#define GMII_NP (1 << 15) // Next page Indication #define GMII_NP (1 << 15) // Next page Indication
// Reserved 7 // Reserved 7
#define GMII_RF (1 << 13) // Remote Fault #define GMII_RF (1 << 13) // Remote Fault
// Reserved 12 // Write as 0, ignore on read // Reserved 12 // Write as 0, ignore on read
#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner) #define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
// 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device) // 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
#define GMII_100T4 (1 << 9) // 100BASE-T4 Support #define GMII_100T4 (1 << 9) // 100BASE-T4 Support
#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support #define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support #define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support
#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support #define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
#define GMII_10_HDX (1 << 5) // 10BASE-T Support #define GMII_10_HDX (1 << 5) // 10BASE-T Support
// Selector 4 to 0 // Protocol Selection Bits // Selector 4 to 0 // Protocol Selection Bits
#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3 #define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3
// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion // Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
// Reserved 15 to 5 // Read as 0, ignore on write // Reserved 15 to 5 // Read as 0, ignore on write
#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault #define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault
#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able #define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able
#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able #define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able
#define GMII_PAGE_RX (1 << 1) // New Page Received #define GMII_PAGE_RX (1 << 1) // New Page Received
#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able #define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able
/** /**
* \brief Perform a HW initialization to the PHY and set up clocks. * \brief Perform a HW initialization to the PHY and set up clocks.
* *
* This should be called only once to initialize the PHY pre-settings. * This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups). * The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII). * The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode). * The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins. * The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done. * The GMAC peripheral pins are configured after the reset is done.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK. * \param ul_mck GMAC MCK.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck); uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
/** /**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the * \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings. * settings.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply. * \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr, uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag); uint8_t uc_apply_setting_flag);
/** /**
* \brief Issue an auto negotiation of the PHY. * \brief Issue an auto negotiation of the PHY.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* *
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr); uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
/** /**
* \brief Issue a SW reset to reset all registers of the PHY. * \brief Issue a SW reset to reset all registers of the PHY.
* *
* \param p_gmac Pointer to the GMAC instance. * \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address. * \param uc_phy_addr PHY address.
* *
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout. * \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/ */
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr); uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
typedef struct xPHY_PROPS { typedef struct xPHY_PROPS {
signed char phy_result; signed char phy_result;
uint32_t phy_params; uint32_t phy_params;
uint32_t phy_stat1; uint32_t phy_stat1;
uint32_t phy_stat2; uint32_t phy_stat2;
unsigned char phy_chn; unsigned char phy_chn;
} PhyProps_t; } PhyProps_t;
extern PhyProps_t phy_props; extern PhyProps_t phy_props;
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */ #endif /* #ifndef ETHERNET_PHY_H_INCLUDED */

View file

@ -1,267 +1,267 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
#include "semphr.h" #include "semphr.h"
/* Hardware abstraction. */ /* Hardware abstraction. */
#include "FreeRTOS_IO.h" #include "FreeRTOS_IO.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
/* Driver includes. */ /* Driver includes. */
#include "lpc17xx_emac.h" #include "lpc17xx_emac.h"
#include "lpc17xx_pinsel.h" #include "lpc17xx_pinsel.h"
/* Demo includes. */ /* Demo includes. */
#include "NetworkInterface.h" #include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1 #if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else #else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif #endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the /* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */ up. */
#define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) ) #define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) )
#define niMAX_TX_ATTEMPTS ( 5 ) #define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the /* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */ interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 ) #define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* A deferred interrupt handler task that processes * A deferred interrupt handler task that processes
*/ */
static void prvEMACHandlerTask( void *pvParameters ); static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */ /* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue; extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx /* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */ interrupt is received. */
static SemaphoreHandle_t xEMACRxEventSemaphore = NULL; static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
EMAC_CFG_Type Emac_Config; EMAC_CFG_Type Emac_Config;
PINSEL_CFG_Type xPinConfig; PINSEL_CFG_Type xPinConfig;
BaseType_t xStatus, xReturn; BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ]; extern uint8_t ucMACAddress[ 6 ];
/* Enable Ethernet Pins */ /* Enable Ethernet Pins */
boardCONFIGURE_ENET_PINS( xPinConfig ); boardCONFIGURE_ENET_PINS( xPinConfig );
Emac_Config.Mode = EMAC_MODE_AUTO; Emac_Config.Mode = EMAC_MODE_AUTO;
Emac_Config.pbEMAC_Addr = ucMACAddress; Emac_Config.pbEMAC_Addr = ucMACAddress;
xStatus = EMAC_Init( &Emac_Config ); xStatus = EMAC_Init( &Emac_Config );
LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE ); LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
if( xStatus != ERROR ) if( xStatus != ERROR )
{ {
vSemaphoreCreateBinary( xEMACRxEventSemaphore ); vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore ); configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to /* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */ ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL ); xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
/* Enable the interrupt and set its priority to the minimum /* Enable the interrupt and set its priority to the minimum
interrupt priority. */ interrupt priority. */
NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ENET_IRQn ); NVIC_EnableIRQ( ENET_IRQn );
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
xReturn = pdFAIL; xReturn = pdFAIL;
} }
configASSERT( xStatus != ERROR ); configASSERT( xStatus != ERROR );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{ {
BaseType_t xReturn = pdFAIL; BaseType_t xReturn = pdFAIL;
int32_t x; int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength ); extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer ); extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
/* Attempt to obtain access to a Tx buffer. */ /* Attempt to obtain access to a Tx buffer. */
for( x = 0; x < niMAX_TX_ATTEMPTS; x++ ) for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
{ {
if( EMAC_CheckTransmitIndex() == TRUE ) if( EMAC_CheckTransmitIndex() == TRUE )
{ {
/* Will the data fit in the Tx buffer? */ /* Will the data fit in the Tx buffer? */
if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */ if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
{ {
/* Assign the buffer to the Tx descriptor that is now known to /* Assign the buffer to the Tx descriptor that is now known to
be free. */ be free. */
EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer ); EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
/* The EMAC now owns the buffer. */ /* The EMAC now owns the buffer. */
pxNetworkBuffer->pucBuffer = NULL; pxNetworkBuffer->pucBuffer = NULL;
/* Initiate the Tx. */ /* Initiate the Tx. */
EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength ); EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
iptraceNETWORK_INTERFACE_TRANSMIT(); iptraceNETWORK_INTERFACE_TRANSMIT();
/* The Tx has been initiated. */ /* The Tx has been initiated. */
xReturn = pdPASS; xReturn = pdPASS;
} }
break; break;
} }
else else
{ {
vTaskDelay( niTX_BUFFER_FREE_WAIT ); vTaskDelay( niTX_BUFFER_FREE_WAIT );
} }
} }
/* Finished with the network buffer. */ /* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void ENET_IRQHandler( void ) void ENET_IRQHandler( void )
{ {
uint32_t ulInterruptCause; uint32_t ulInterruptCause;
while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 ) while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
{ {
/* Clear the interrupt. */ /* Clear the interrupt. */
LPC_EMAC->IntClear = ulInterruptCause; LPC_EMAC->IntClear = ulInterruptCause;
/* Clear fatal error conditions. NOTE: The driver does not clear all /* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */ errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U ) if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
{ {
LPC_EMAC->Command |= EMAC_CR_TX_RES; LPC_EMAC->Command |= EMAC_CR_TX_RES;
} }
/* Unblock the deferred interrupt handler task if the event was an /* Unblock the deferred interrupt handler task if the event was an
Rx. */ Rx. */
if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL ) if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
{ {
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL ); xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
} }
} }
/* ulInterruptCause is used for convenience here. A context switch is /* ulInterruptCause is used for convenience here. A context switch is
wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
compiler warning. */ compiler warning. */
portEND_SWITCHING_ISR( ulInterruptCause ); portEND_SWITCHING_ISR( ulInterruptCause );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters ) static void prvEMACHandlerTask( void *pvParameters )
{ {
size_t xDataLength; size_t xDataLength;
const uint16_t usCRCLength = 4; const uint16_t usCRCLength = 4;
NetworkBufferDescriptor_t *pxNetworkBuffer; NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
/* This is not included in the header file for some reason. */ /* This is not included in the header file for some reason. */
extern uint8_t *EMAC_NextPacketToRead( void ); extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters; ( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore ); configASSERT( xEMACRxEventSemaphore );
for( ;; ) for( ;; )
{ {
/* Wait for the EMAC interrupt to indicate that another packet has been /* Wait for the EMAC interrupt to indicate that another packet has been
received. The while() loop is only needed if INCLUDE_vTaskSuspend is received. The while() loop is only needed if INCLUDE_vTaskSuspend is
set to 0 in FreeRTOSConfig.h. */ set to 0 in FreeRTOSConfig.h. */
while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE ); while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
/* At least one packet has been received. */ /* At least one packet has been received. */
while( EMAC_CheckReceiveIndex() != FALSE ) while( EMAC_CheckReceiveIndex() != FALSE )
{ {
/* Obtain the length, minus the CRC. The CRC is four bytes /* Obtain the length, minus the CRC. The CRC is four bytes
but the length is already minus 1. */ but the length is already minus 1. */
xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U ); xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
if( xDataLength > 0U ) if( xDataLength > 0U )
{ {
/* Obtain a network buffer to pass this data into the /* Obtain a network buffer to pass this data into the
stack. No storage is required as the network buffer stack. No storage is required as the network buffer
will point directly to the buffer that already holds will point directly to the buffer that already holds
the received data. */ the received data. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 ); pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );
if( pxNetworkBuffer != NULL ) if( pxNetworkBuffer != NULL )
{ {
pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead(); pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
pxNetworkBuffer->xDataLength = xDataLength; pxNetworkBuffer->xDataLength = xDataLength;
xRxEvent.pvData = ( void * ) pxNetworkBuffer; xRxEvent.pvData = ( void * ) pxNetworkBuffer;
/* Data was received and stored. Send a message to the IP /* Data was received and stored. Send a message to the IP
task to let it know. */ task to let it know. */
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{ {
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
} }
} }
else else
{ {
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
} }
iptraceNETWORK_INTERFACE_RECEIVE(); iptraceNETWORK_INTERFACE_RECEIVE();
} }
/* Release the frame. */ /* Release the frame. */
EMAC_UpdateRxConsumeIndex(); EMAC_UpdateRxConsumeIndex();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,331 +1,331 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "list.h" #include "list.h"
#include "queue.h" #include "queue.h"
#include "semphr.h" #include "semphr.h"
#include "task.h" #include "task.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "m480_eth.h" #include "m480_eth.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it driver will filter incoming packets and only pass the stack those packets it
considers need processing. */ considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else #else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif #endif
/* Default the size of the stack used by the EMAC deferred handler task to twice /* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE #ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE ) #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif #endif
static SemaphoreHandle_t xTXMutex = NULL; static SemaphoreHandle_t xTXMutex = NULL;
/* The handle of the task that processes Rx packets. The handle is required so /* The handle of the task that processes Rx packets. The handle is required so
the task can be notified when new packets arrive. */ the task can be notified when new packets arrive. */
static TaskHandle_t xRxHanderTask = NULL; static TaskHandle_t xRxHanderTask = NULL;
static TimerHandle_t xPhyHandlerTask = NULL; static TimerHandle_t xPhyHandlerTask = NULL;
/* /*
* A task that processes received frames. * A task that processes received frames.
*/ */
static void prvEMACHandlerTask( void *pvParameters ); static void prvEMACHandlerTask( void *pvParameters );
static void prvPhyTmrCallback( TimerHandle_t xTimer ); static void prvPhyTmrCallback( TimerHandle_t xTimer );
/* The size of each buffer when BufferAllocation_1 is used: /* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */ http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536 #define niBUFFER_1_PACKET_SIZE 1536
#ifdef __ICCARM__ #ifdef __ICCARM__
#pragma data_alignment=4 #pragma data_alignment=4
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
#else #else
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4))); static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
#endif #endif
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
uint8_t hwaddr[6]; uint8_t hwaddr[6];
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
/* Init ETH */ /* Init ETH */
numaker_mac_address(hwaddr); numaker_mac_address(hwaddr);
FreeRTOS_UpdateMACAddress(hwaddr); FreeRTOS_UpdateMACAddress(hwaddr);
FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) ); FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
/* Enable clock & set EMAC configuration */ /* Enable clock & set EMAC configuration */
/* Enable MAC and DMA transmission and reception */ /* Enable MAC and DMA transmission and reception */
if( numaker_eth_init(hwaddr) < 0) if( numaker_eth_init(hwaddr) < 0)
{ {
xReturn = pdFAIL; xReturn = pdFAIL;
} else { } else {
xReturn = pdPASS; xReturn = pdPASS;
/* Guard against the task being created more than once and the /* Guard against the task being created more than once and the
descriptors being initialized more than once. */ descriptors being initialized more than once. */
/* Timer task to monitor PHY Link status */ /* Timer task to monitor PHY Link status */
if( xPhyHandlerTask == NULL ) if( xPhyHandlerTask == NULL )
{ {
xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback ); xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
configASSERT(xPhyHandlerTask); configASSERT(xPhyHandlerTask);
xReturn = xTimerStart( xPhyHandlerTask, 0 ) ; xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
configASSERT( xReturn ); configASSERT( xReturn );
} }
/* Rx task */ /* Rx task */
if( xRxHanderTask == NULL ) if( xRxHanderTask == NULL )
{ {
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask ); xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
configASSERT( xReturn ); configASSERT( xReturn );
} }
if( xTXMutex == NULL ) if( xTXMutex == NULL )
{ {
xTXMutex = xSemaphoreCreateMutex(); xTXMutex = xSemaphoreCreateMutex();
configASSERT( xTXMutex ); configASSERT( xTXMutex );
} }
} }
NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
numaker_eth_enable_interrupts(); numaker_eth_enable_interrupts();
FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) ); FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
return xReturn; return xReturn;
} }
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
{ {
uint8_t *buffer=NULL; uint8_t *buffer=NULL;
// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength)); // FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE ) if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
{ {
FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE)); FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
return pdFALSE; return pdFALSE;
} }
buffer = numaker_eth_get_tx_buf(); buffer = numaker_eth_get_tx_buf();
if( buffer == NULL ) if( buffer == NULL )
{ {
NU_DEBUGF(("Eth TX slots are busy\n")); NU_DEBUGF(("Eth TX slots are busy\n"));
return pdFALSE; return pdFALSE;
} }
/* Get exclusive access */ /* Get exclusive access */
xSemaphoreTake(xTXMutex, portMAX_DELAY); xSemaphoreTake(xTXMutex, portMAX_DELAY);
NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer)); NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
//SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength //SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength); memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL); numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
/* Call the standard trace macro to log the send event. */ /* Call the standard trace macro to log the send event. */
iptraceNETWORK_INTERFACE_TRANSMIT(); iptraceNETWORK_INTERFACE_TRANSMIT();
if( xReleaseAfterSend != pdFALSE ) if( xReleaseAfterSend != pdFALSE )
{ {
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
buffer. The Ethernet buffer is therefore no longer needed, and must be buffer. The Ethernet buffer is therefore no longer needed, and must be
freed for re-use. */ freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor ); vReleaseNetworkBufferAndDescriptor( pxDescriptor );
} }
xSemaphoreGive(xTXMutex); xSemaphoreGive(xTXMutex);
return pdTRUE; return pdTRUE;
} }
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{ {
uint8_t *ucRAMBuffer = ucNetworkPackets; uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul; uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{ {
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE; ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
} }
} }
BaseType_t xGetPhyLinkStatus( void ) BaseType_t xGetPhyLinkStatus( void )
{ {
BaseType_t xReturn; BaseType_t xReturn;
if( numaker_eth_link_ok() ) if( numaker_eth_link_ok() )
{ {
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
xReturn = pdFAIL; xReturn = pdFAIL;
} }
return xReturn; return xReturn;
} }
static void prvPhyTmrCallback( TimerHandle_t xTimer ) static void prvPhyTmrCallback( TimerHandle_t xTimer )
{ {
IPStackEvent_t xRxEvent; IPStackEvent_t xRxEvent;
static BaseType_t lastLink = pdFAIL; static BaseType_t lastLink = pdFAIL;
BaseType_t currLink = xGetPhyLinkStatus(); BaseType_t currLink = xGetPhyLinkStatus();
if( currLink != lastLink ) if( currLink != lastLink )
{ {
FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down")); FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
if( !currLink ) if( !currLink )
{ {
xRxEvent.eEventType = eNetworkDownEvent; xRxEvent.eEventType = eNetworkDownEvent;
xSendEventStructToIPTask( &xRxEvent, 0 ); xSendEventStructToIPTask( &xRxEvent, 0 );
} }
lastLink = currLink; lastLink = currLink;
} }
} }
static void prvEMACHandlerTask( void *pvParameters ) static void prvEMACHandlerTask( void *pvParameters )
{ {
TimeOut_t xPhyTime; TimeOut_t xPhyTime;
TickType_t xPhyRemTime; TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0; UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount; UBaseType_t uxCurrentCount;
BaseType_t xResult = 0; BaseType_t xResult = 0;
uint32_t ulStatus; uint32_t ulStatus;
uint16_t dataLength = 0; uint16_t dataLength = 0;
uint8_t *buffer = NULL; uint8_t *buffer = NULL;
NetworkBufferDescriptor_t *pxBufferDescriptor = NULL; NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
IPStackEvent_t xRxEvent; IPStackEvent_t xRxEvent;
const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul ); const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
/* Remove compiler warnings about unused parameters. */ /* Remove compiler warnings about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
/* A possibility to set some additional task properties. */ /* A possibility to set some additional task properties. */
for( ;; ) for( ;; )
{ {
uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentCount ) if( uxLastMinBufferCount != uxCurrentCount )
{ {
/* The logging produced below may be helpful /* The logging produced below may be helpful
while tuning +TCP: see how many buffers are in use. */ while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentCount; uxLastMinBufferCount = uxCurrentCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
} }
/* No events to process now, wait for the next. */ /* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
while(1) while(1)
{ {
/* get received frame */ /* get received frame */
if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) { if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
/* The event was lost because a network buffer was not available. /* The event was lost because a network buffer was not available.
Call the standard trace macro to log the occurrence. */ Call the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
break; break;
} }
/* Allocate a network buffer descriptor that points to a buffer /* Allocate a network buffer descriptor that points to a buffer
large enough to hold the received frame. As this is the simple large enough to hold the received frame. As this is the simple
rather than efficient example the received data will just be copied rather than efficient example the received data will just be copied
into this buffer. */ into this buffer. */
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 ); pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( PACKET_BUFFER_SIZE, 0 );
if( pxBufferDescriptor != NULL ) if( pxBufferDescriptor != NULL )
{ {
memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength ); memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
// FreeRTOS_printf(("--> dataLength=%d\n",dataLength)); // FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
pxBufferDescriptor->xDataLength = dataLength; pxBufferDescriptor->xDataLength = dataLength;
} else { } else {
numaker_eth_rx_next(); numaker_eth_rx_next();
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
break; break;
} }
/* The event about to be sent to the TCP/IP is an Rx event. */ /* The event about to be sent to the TCP/IP is an Rx event. */
xRxEvent.eEventType = eNetworkRxEvent; xRxEvent.eEventType = eNetworkRxEvent;
/* pvData is used to point to the network buffer descriptor that /* pvData is used to point to the network buffer descriptor that
now references the received data. */ now references the received data. */
xRxEvent.pvData = ( void * ) pxBufferDescriptor; xRxEvent.pvData = ( void * ) pxBufferDescriptor;
/* Send the data to the TCP/IP stack. */ /* Send the data to the TCP/IP stack. */
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{ {
/* The buffer could not be sent to the IP task so the buffer /* The buffer could not be sent to the IP task so the buffer
must be released. */ must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor ); vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
/* Make a call to the standard trace macro to log the /* Make a call to the standard trace macro to log the
occurrence. */ occurrence. */
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
} else } else
{ {
/* The message was successfully sent to the TCP/IP stack. /* The message was successfully sent to the TCP/IP stack.
Call the standard trace macro to log the occurrence. */ Call the standard trace macro to log the occurrence. */
iptraceNETWORK_INTERFACE_RECEIVE(); iptraceNETWORK_INTERFACE_RECEIVE();
} }
numaker_eth_rx_next(); numaker_eth_rx_next();
} }
numaker_eth_trigger_rx(); numaker_eth_trigger_rx();
} }
} }
void xNetworkCallback(char event) void xNetworkCallback(char event)
{ {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
switch (event) switch (event)
{ {
case 'R': //For RX event case 'R': //For RX event
/* Wakeup the prvEMACHandlerTask. */ /* Wakeup the prvEMACHandlerTask. */
if( xRxHanderTask != NULL ) if( xRxHanderTask != NULL )
{ {
vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken ); vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} }
break; break;
case 'T': //For TX event case 'T': //For TX event
// ack of tx done, no-op in this stage // ack of tx done, no-op in this stage
break; break;
default: default:
break; break;
} }
} }

View file

@ -1,448 +1,448 @@
/**************************************************************************//** /**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 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 * 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. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "list.h" #include "list.h"
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "m480_eth.h" #include "m480_eth.h"
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) #define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) #define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) #define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0) #define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) #define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0) #define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
#ifdef __ICCARM__ #ifdef __ICCARM__
#pragma data_alignment=4 #pragma data_alignment=4
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
#else #else
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4))); struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4))); uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4))); uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
#endif #endif
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns // PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
// Assume we want to set each tick to 100ns. // Assume we want to set each tick to 100ns.
// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 // Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz // Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 // From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)
{ {
EMAC->MIIMDAT = val; EMAC->MIIMDAT = val;
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
} }
static uint16_t mdio_read(uint8_t addr, uint8_t reg) static uint16_t mdio_read(uint8_t addr, uint8_t reg)
{ {
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
return(EMAC->MIIMDAT); return(EMAC->MIIMDAT);
} }
static int reset_phy(void) static int reset_phy(void)
{ {
uint16_t reg; uint16_t reg;
uint32_t delayCnt; uint32_t delayCnt;
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
delayCnt = 2000; delayCnt = 2000;
while(delayCnt-- > 0) { while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
break; break;
} }
if(delayCnt == 0) { if(delayCnt == 0) {
NU_DEBUGF(("Reset phy failed\n")); NU_DEBUGF(("Reset phy failed\n"));
return(-1); return(-1);
} }
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
ADVERTISE_10HALF | ADVERTISE_10HALF |
ADVERTISE_10FULL | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100HALF |
ADVERTISE_100FULL); ADVERTISE_100FULL);
reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
delayCnt = 200000; delayCnt = 200000;
while(delayCnt-- > 0) { while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
break; break;
} }
if(delayCnt == 0) { if(delayCnt == 0) {
NU_DEBUGF(("AN failed. Set to 100 FULL\n")); NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
return(-1); return(-1);
} else { } else {
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
if(reg & ADVERTISE_100FULL) { if(reg & ADVERTISE_100FULL) {
NU_DEBUGF(("100 full\n")); NU_DEBUGF(("100 full\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
} else if(reg & ADVERTISE_100HALF) { } else if(reg & ADVERTISE_100HALF) {
NU_DEBUGF(("100 half\n")); NU_DEBUGF(("100 half\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
} else if(reg & ADVERTISE_10FULL) { } else if(reg & ADVERTISE_10FULL) {
NU_DEBUGF(("10 full\n")); NU_DEBUGF(("10 full\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
} else { } else {
NU_DEBUGF(("10 half\n")); NU_DEBUGF(("10 half\n"));
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
} }
} }
FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1))); FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));
FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2))); FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));
return(0); return(0);
} }
static void init_tx_desc(void) static void init_tx_desc(void)
{ {
uint32_t i; uint32_t i;
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) { for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
tx_desc[i].buf = &tx_buf[i][0]; tx_desc[i].buf = &tx_buf[i][0];
tx_desc[i].status2 = 0; tx_desc[i].status2 = 0;
tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
} }
EMAC->TXDSA = (unsigned int)&tx_desc[0]; EMAC->TXDSA = (unsigned int)&tx_desc[0];
return; return;
} }
static void init_rx_desc(void) static void init_rx_desc(void)
{ {
uint32_t i; uint32_t i;
cur_rx_desc_ptr = &rx_desc[0]; cur_rx_desc_ptr = &rx_desc[0];
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) { for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
rx_desc[i].status1 = OWNERSHIP_EMAC; rx_desc[i].status1 = OWNERSHIP_EMAC;
rx_desc[i].buf = &rx_buf[i][0]; rx_desc[i].buf = &rx_buf[i][0];
rx_desc[i].status2 = 0; rx_desc[i].status2 = 0;
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
} }
EMAC->RXDSA = (unsigned int)&rx_desc[0]; EMAC->RXDSA = (unsigned int)&rx_desc[0];
return; return;
} }
void numaker_set_mac_addr(uint8_t *addr) void numaker_set_mac_addr(uint8_t *addr)
{ {
EMAC->CAM0M = (addr[0] << 24) | EMAC->CAM0M = (addr[0] << 24) |
(addr[1] << 16) | (addr[1] << 16) |
(addr[2] << 8) | (addr[2] << 8) |
addr[3]; addr[3];
EMAC->CAM0L = (addr[4] << 24) | EMAC->CAM0L = (addr[4] << 24) |
(addr[5] << 16); (addr[5] << 16);
} }
static void __eth_clk_pin_init() static void __eth_clk_pin_init()
{ {
/* Unlock protected registers */ /* Unlock protected registers */
SYS_UnlockReg(); SYS_UnlockReg();
/* Enable IP clock */ /* Enable IP clock */
CLK_EnableModuleClock(EMAC_MODULE); CLK_EnableModuleClock(EMAC_MODULE);
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
/* Update System Core Clock */ /* Update System Core Clock */
SystemCoreClockUpdate(); SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */ /* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------*/
// Configure RMII pins // Configure RMII pins
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV; SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0; SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK; SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk | SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk); SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC | SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO | SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 | SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 | SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN; SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
// Enable high slew rate on all RMII TX output pins // Enable high slew rate on all RMII TX output pins
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) | PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) | (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos); (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
/* Lock protected registers */ /* Lock protected registers */
SYS_LockReg(); SYS_LockReg();
} }
int numaker_eth_init(uint8_t *mac_addr) int numaker_eth_init(uint8_t *mac_addr)
{ {
int ret = 0; int ret = 0;
// init CLK & pins // init CLK & pins
__eth_clk_pin_init(); __eth_clk_pin_init();
// Reset MAC // Reset MAC
EMAC->CTL = EMAC_CTL_RST_Msk; EMAC->CTL = EMAC_CTL_RST_Msk;
while(EMAC->CTL & EMAC_CTL_RST_Msk) {} while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
init_tx_desc(); init_tx_desc();
init_rx_desc(); init_rx_desc();
numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
/* Configure the MAC interrupt enable register. */ /* Configure the MAC interrupt enable register. */
EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk | EMAC_INTEN_TXIEN_Msk |
EMAC_INTEN_RXGDIEN_Msk | EMAC_INTEN_RXGDIEN_Msk |
EMAC_INTEN_TXCPIEN_Msk | EMAC_INTEN_TXCPIEN_Msk |
EMAC_INTEN_RXBEIEN_Msk | EMAC_INTEN_RXBEIEN_Msk |
EMAC_INTEN_TXBEIEN_Msk | EMAC_INTEN_TXBEIEN_Msk |
EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RDUIEN_Msk |
EMAC_INTEN_TSALMIEN_Msk | EMAC_INTEN_TSALMIEN_Msk |
EMAC_INTEN_WOLIEN_Msk; EMAC_INTEN_WOLIEN_Msk;
/* Configure the MAC control register. */ /* Configure the MAC control register. */
EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk; EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
/* Accept packets for us and all broadcast and multicast packets */ /* Accept packets for us and all broadcast and multicast packets */
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
EMAC_CAMCTL_AMP_Msk | EMAC_CAMCTL_AMP_Msk |
EMAC_CAMCTL_ABP_Msk; EMAC_CAMCTL_ABP_Msk;
EMAC->CAMEN = 1; // Enable CAM entry 0 EMAC->CAMEN = 1; // Enable CAM entry 0
ret= reset_phy(); ret= reset_phy();
EMAC_ENABLE_RX(); EMAC_ENABLE_RX();
EMAC_ENABLE_TX(); EMAC_ENABLE_TX();
return ret; return ret;
} }
void ETH_halt(void) void ETH_halt(void)
{ {
EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
} }
unsigned int m_status; unsigned int m_status;
void EMAC_RX_IRQHandler(void) void EMAC_RX_IRQHandler(void)
{ {
// NU_DEBUGF(("%s ... \r\n", __FUNCTION__)); // NU_DEBUGF(("%s ... \r\n", __FUNCTION__));
m_status = EMAC->INTSTS & 0xFFFF; m_status = EMAC->INTSTS & 0xFFFF;
EMAC->INTSTS = m_status; EMAC->INTSTS = m_status;
if (m_status & EMAC_INTSTS_RXBEIF_Msk) { if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted // Shouldn't goes here, unless descriptor corrupted
NU_DEBUGF(("RX descriptor corrupted \r\n")); NU_DEBUGF(("RX descriptor corrupted \r\n"));
//return; //return;
} }
// FIX ME: for rx-event, to ack rx_isr into event queue // FIX ME: for rx-event, to ack rx_isr into event queue
xNetworkCallback('R'); xNetworkCallback('R');
} }
void numaker_eth_trigger_rx(void) void numaker_eth_trigger_rx(void)
{ {
ETH_TRIGGER_RX(); ETH_TRIGGER_RX();
} }
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
{ {
unsigned int cur_entry, status; unsigned int cur_entry, status;
cur_entry = EMAC->CRXDSA; cur_entry = EMAC->CRXDSA;
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
return -1; return -1;
status = cur_rx_desc_ptr->status1; status = cur_rx_desc_ptr->status1;
if(status & OWNERSHIP_EMAC) if(status & OWNERSHIP_EMAC)
return -1; return -1;
if (status & RXFD_RXGD) { if (status & RXFD_RXGD) {
*buf = cur_rx_desc_ptr->buf; *buf = cur_rx_desc_ptr->buf;
*len = status & 0xFFFF; *len = status & 0xFFFF;
} }
return 0; return 0;
} }
void numaker_eth_rx_next(void) void numaker_eth_rx_next(void)
{ {
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
cur_rx_desc_ptr = cur_rx_desc_ptr->next; cur_rx_desc_ptr = cur_rx_desc_ptr->next;
} }
void EMAC_TX_IRQHandler(void) void EMAC_TX_IRQHandler(void)
{ {
unsigned int cur_entry, status; unsigned int cur_entry, status;
status = EMAC->INTSTS & 0xFFFF0000; status = EMAC->INTSTS & 0xFFFF0000;
EMAC->INTSTS = status; EMAC->INTSTS = status;
if(status & EMAC_INTSTS_TXBEIF_Msk) { if(status & EMAC_INTSTS_TXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted // Shouldn't goes here, unless descriptor corrupted
return; return;
} }
cur_entry = EMAC->CTXDSA; cur_entry = EMAC->CTXDSA;
while (cur_entry != (uint32_t)fin_tx_desc_ptr) { while (cur_entry != (uint32_t)fin_tx_desc_ptr) {
fin_tx_desc_ptr = fin_tx_desc_ptr->next; fin_tx_desc_ptr = fin_tx_desc_ptr->next;
} }
// FIX ME: for tx-event, no-op at this stage // FIX ME: for tx-event, no-op at this stage
xNetworkCallback('T'); xNetworkCallback('T');
} }
uint8_t *numaker_eth_get_tx_buf(void) uint8_t *numaker_eth_get_tx_buf(void)
{ {
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
return(NULL); return(NULL);
else else
return(cur_tx_desc_ptr->buf); return(cur_tx_desc_ptr->buf);
} }
void numaker_eth_trigger_tx(uint16_t length, void *p) void numaker_eth_trigger_tx(uint16_t length, void *p)
{ {
struct eth_descriptor volatile *desc; struct eth_descriptor volatile *desc;
cur_tx_desc_ptr->status2 = (unsigned int)length; cur_tx_desc_ptr->status2 = (unsigned int)length;
desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
cur_tx_desc_ptr = desc; cur_tx_desc_ptr = desc;
ETH_TRIGGER_TX(); ETH_TRIGGER_TX();
} }
int numaker_eth_link_ok(void) int numaker_eth_link_ok(void)
{ {
/* first, a dummy read to latch */ /* first, a dummy read to latch */
mdio_read(CONFIG_PHY_ADDR, MII_BMSR); mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
return 1; return 1;
return 0; return 0;
} }
//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) //void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
//{ //{
// nu_eth_txrx_cb = eth_cb; // nu_eth_txrx_cb = eth_cb;
// nu_userData = userData; // nu_userData = userData;
//} //}
// Provide ethernet devices with a semi-unique MAC address // Provide ethernet devices with a semi-unique MAC address
void numaker_mac_address(uint8_t *mac) void numaker_mac_address(uint8_t *mac)
{ {
uint32_t uID1; uint32_t uID1;
// Fetch word 0 // Fetch word 0
uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
// Fetch word 1 // Fetch word 1
// we only want bottom 16 bits of word1 (MAC bits 32-47) // we only want bottom 16 bits of word1 (MAC bits 32-47)
// and bit 9 forced to 1, bit 8 forced to 0 // and bit 9 forced to 1, bit 8 forced to 0
// Locally administered MAC, reduced conflicts // Locally administered MAC, reduced conflicts
// http://en.wikipedia.org/wiki/MAC_address // http://en.wikipedia.org/wiki/MAC_address
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
{ {
// with a semi-unique MAC address from the UUID // with a semi-unique MAC address from the UUID
/* Enable FMC ISP function */ /* Enable FMC ISP function */
SYS_UnlockReg(); SYS_UnlockReg();
FMC_Open(); FMC_Open();
// = FMC_ReadUID(0); // = FMC_ReadUID(0);
uID1 = FMC_ReadUID(1); uID1 = FMC_ReadUID(1);
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF); word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
/* Disable FMC ISP function */ /* Disable FMC ISP function */
FMC_Close(); FMC_Close();
/* Lock protected registers */ /* Lock protected registers */
SYS_LockReg(); SYS_LockReg();
} }
word1 |= 0x00000200; word1 |= 0x00000200;
word1 &= 0x0000FEFF; word1 &= 0x0000FEFF;
mac[0] = (word1 & 0x0000ff00) >> 8; mac[0] = (word1 & 0x0000ff00) >> 8;
mac[1] = (word1 & 0x000000ff); mac[1] = (word1 & 0x000000ff);
mac[2] = (word0 & 0xff000000) >> 24; mac[2] = (word0 & 0xff000000) >> 24;
mac[3] = (word0 & 0x00ff0000) >> 16; mac[3] = (word0 & 0x00ff0000) >> 16;
mac[4] = (word0 & 0x0000ff00) >> 8; mac[4] = (word0 & 0x0000ff00) >> 8;
mac[5] = (word0 & 0x000000ff); mac[5] = (word0 & 0x000000ff);
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5])); NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
} }
void numaker_eth_enable_interrupts(void) { void numaker_eth_enable_interrupts(void) {
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk ; EMAC_INTEN_TXIEN_Msk ;
NVIC_EnableIRQ(EMAC_RX_IRQn); NVIC_EnableIRQ(EMAC_RX_IRQn);
NVIC_EnableIRQ(EMAC_TX_IRQn); NVIC_EnableIRQ(EMAC_TX_IRQn);
} }
void numaker_eth_disable_interrupts(void) { void numaker_eth_disable_interrupts(void) {
NVIC_DisableIRQ(EMAC_RX_IRQn); NVIC_DisableIRQ(EMAC_RX_IRQn);
NVIC_DisableIRQ(EMAC_TX_IRQn); NVIC_DisableIRQ(EMAC_TX_IRQn);
} }

View file

@ -1,164 +1,164 @@
/**************************************************************************//** /**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved. * @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors * 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * 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 * 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. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include "M480.h" #include "M480.h"
#ifndef _M480_ETH_ #ifndef _M480_ETH_
#define _M480_ETH_ #define _M480_ETH_
/* Generic MII registers. */ /* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */ #define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */ #define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */ #define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */ #define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */ #define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */ #define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */ #define MII_EXPANSION 0x06 /* Expansion register */
#define MII_DCOUNTER 0x12 /* Disconnect counter */ #define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */ #define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ #define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */ #define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */ #define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */ #define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ #define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */ #define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */ #define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ #define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */ #define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */ /* Basic mode control register. */
#define BMCR_RESV 0x007f /* Unused... */ #define BMCR_RESV 0x007f /* Unused... */
#define BMCR_CTST 0x0080 /* Collision test */ #define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */ #define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ #define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ #define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ #define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ #define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ #define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ #define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */ #define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */ /* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ #define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */ #define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */ #define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ #define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */ #define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ #define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x07c0 /* Unused... */ #define BMSR_RESV 0x07c0 /* Unused... */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ #define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ #define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ #define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ #define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ #define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */ /* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */ #define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ #define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ #define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ #define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ #define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ #define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ #define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_RESV 0x1c00 /* Unused... */ #define ADVERTISE_RESV 0x1c00 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ #define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ #define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ #define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors #define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors
#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors #define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors
#define PACKET_BUFFER_SIZE 1520 #define PACKET_BUFFER_SIZE 1520
#define CONFIG_PHY_ADDR 1 #define CONFIG_PHY_ADDR 1
// Frame Descriptor's Owner bit // Frame Descriptor's Owner bit
#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC #define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU //#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
// Rx Frame Descriptor Status // Rx Frame Descriptor Status
#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received #define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available #define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
// Tx Frame Descriptor's Control bits // Tx Frame Descriptor's Control bits
#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable #define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
#define TXFD_INTEN 0x04 // Interrupt Enable #define TXFD_INTEN 0x04 // Interrupt Enable
#define TXFD_CRCAPP 0x02 // Append CRC #define TXFD_CRCAPP 0x02 // Append CRC
#define TXFD_PADEN 0x01 // Padding Enable #define TXFD_PADEN 0x01 // Padding Enable
// Tx Frame Descriptor Status // Tx Frame Descriptor Status
#define TXFD_TXCP 0x00080000 // Transmission Completion #define TXFD_TXCP 0x00080000 // Transmission Completion
#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available #define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
// Tx/Rx buffer descriptor structure // Tx/Rx buffer descriptor structure
struct eth_descriptor; struct eth_descriptor;
struct eth_descriptor { struct eth_descriptor {
uint32_t status1; uint32_t status1;
uint8_t *buf; uint8_t *buf;
uint32_t status2; uint32_t status2;
struct eth_descriptor *next; struct eth_descriptor *next;
#ifdef TIME_STAMPING #ifdef TIME_STAMPING
uint32_t backup1; uint32_t backup1;
uint32_t backup2; uint32_t backup2;
uint32_t reserved1; uint32_t reserved1;
uint32_t reserved2; uint32_t reserved2;
#endif #endif
}; };
#ifdef TIME_STAMPING #ifdef TIME_STAMPING
#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) #define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) #define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
s32_t ETH_settime(u32_t sec, u32_t nsec); s32_t ETH_settime(u32_t sec, u32_t nsec);
s32_t ETH_gettime(u32_t *sec, u32_t *nsec); s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
s32_t ETH_adjtimex(int ppm); s32_t ETH_adjtimex(int ppm);
void ETH_setinc(void); void ETH_setinc(void);
#endif #endif
#ifdef NU_TRACE #ifdef NU_TRACE
#define NU_DEBUGF(x) { printf x; } #define NU_DEBUGF(x) { printf x; }
#else #else
#define NU_DEBUGF(x) #define NU_DEBUGF(x)
#endif #endif
void numaker_set_mac_addr(uint8_t *addr); void numaker_set_mac_addr(uint8_t *addr);
int numaker_eth_init(uint8_t *mac_addr); int numaker_eth_init(uint8_t *mac_addr);
uint8_t *numaker_eth_get_tx_buf(void); uint8_t *numaker_eth_get_tx_buf(void);
void numaker_eth_trigger_tx(uint16_t length, void *p); void numaker_eth_trigger_tx(uint16_t length, void *p);
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf); int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);
void numaker_eth_rx_next(void); void numaker_eth_rx_next(void);
void numaker_eth_trigger_rx(void); void numaker_eth_trigger_rx(void);
int numaker_eth_link_ok(void); int numaker_eth_link_ok(void);
void numaker_mac_address(uint8_t *mac); void numaker_mac_address(uint8_t *mac);
void numaker_eth_enable_interrupts(void); void numaker_eth_enable_interrupts(void);
void numaker_eth_disable_interrupts(void); void numaker_eth_disable_interrupts(void);
#endif /* _M480_ETH_ */ #endif /* _M480_ETH_ */

View file

@ -1,177 +1,177 @@
/*********************************************************************************************************************** /***********************************************************************************************************************
* DISCLAIMER * DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all * other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws. * applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES * EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS * SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the * this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link: * following link:
* http://www.renesas.com/disclaimer * http://www.renesas.com/disclaimer
* *
* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/ ***********************************************************************************************************************/
/*********************************************************************************************************************** /***********************************************************************************************************************
* File Name : ether_callback.c * File Name : ether_callback.c
* Version : ---- * Version : ----
* Description : This module solves all the world's problems * Description : This module solves all the world's problems
***********************************************************************************************************************/ ***********************************************************************************************************************/
/********************************************************************************************************************** /**********************************************************************************************************************
* History : DD.MM.YYYY Version Description * History : DD.MM.YYYY Version Description
* : 05.01.2015 ---- Clean up source code. * : 05.01.2015 ---- Clean up source code.
***********************************************************************************************************************/ ***********************************************************************************************************************/
/*********************************************************************************************************************** /***********************************************************************************************************************
Includes <System Includes> , "Project Includes" Includes <System Includes> , "Project Includes"
***********************************************************************************************************************/ ***********************************************************************************************************************/
#include "r_ether_rx_if.h" #include "r_ether_rx_if.h"
/*********************************************************************************************************************** /***********************************************************************************************************************
Private global variables and functions Private global variables and functions
***********************************************************************************************************************/ ***********************************************************************************************************************/
int32_t callback_ether_regist(void); int32_t callback_ether_regist(void);
void callback_ether(void * pparam); void callback_ether(void * pparam);
static void callback_wakeon_lan(uint32_t channel); static void callback_wakeon_lan(uint32_t channel);
static void callback_link_on(uint32_t channel); static void callback_link_on(uint32_t channel);
static void callback_link_off(uint32_t channel); static void callback_link_off(uint32_t channel);
volatile uint8_t pause_enable = ETHER_FLAG_OFF; volatile uint8_t pause_enable = ETHER_FLAG_OFF;
volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX]; volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX];
volatile uint8_t link_detect[ETHER_CHANNEL_MAX]; volatile uint8_t link_detect[ETHER_CHANNEL_MAX];
void EINT_Trig_isr(void *); void EINT_Trig_isr(void *);
/* /*
* When that Link Status changes, the following function will be called: * When that Link Status changes, the following function will be called:
*/ */
void prvLinkStatusChange( BaseType_t xStatus ); void prvLinkStatusChange( BaseType_t xStatus );
/*********************************************************************************************************************** /***********************************************************************************************************************
* Function Name: callback_ether * Function Name: callback_ether
* Description : Regist of callback function * Description : Regist of callback function
* Arguments : - * Arguments : -
* Return Value : 0: success, -1:failed * Return Value : 0: success, -1:failed
***********************************************************************************************************************/ ***********************************************************************************************************************/
int32_t callback_ether_regist(void) int32_t callback_ether_regist(void)
{ {
ether_param_t param; ether_param_t param;
ether_cb_t cb_func; ether_cb_t cb_func;
int32_t ret; int32_t ret;
/* Set the callback function (LAN cable connect/disconnect event) */ /* Set the callback function (LAN cable connect/disconnect event) */
cb_func.pcb_func = &callback_ether; cb_func.pcb_func = &callback_ether;
param.ether_callback = cb_func; param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param); ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);
if (ETHER_SUCCESS != ret) if (ETHER_SUCCESS != ret)
{ {
return -1; return -1;
} }
/* Set the callback function (Ether interrupt event) */ /* Set the callback function (Ether interrupt event) */
cb_func.pcb_int_hnd = &EINT_Trig_isr; cb_func.pcb_int_hnd = &EINT_Trig_isr;
param.ether_callback = cb_func; param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param); ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);
if (ETHER_SUCCESS != ret) if (ETHER_SUCCESS != ret)
{ {
return -1; return -1;
} }
return 0; return 0;
} /* End of function callback_ether_regist() */ } /* End of function callback_ether_regist() */
/*********************************************************************************************************************** /***********************************************************************************************************************
* Function Name: callback_ether * Function Name: callback_ether
* Description : Sample of the callback function * Description : Sample of the callback function
* Arguments : pparam - * Arguments : pparam -
* *
* Return Value : none * Return Value : none
***********************************************************************************************************************/ ***********************************************************************************************************************/
void callback_ether(void * pparam) void callback_ether(void * pparam)
{ {
ether_cb_arg_t * pdecode; ether_cb_arg_t * pdecode;
uint32_t channel; uint32_t channel;
pdecode = (ether_cb_arg_t *)pparam; pdecode = (ether_cb_arg_t *)pparam;
channel = pdecode->channel; /* Get Ethernet channel number */ channel = pdecode->channel; /* Get Ethernet channel number */
switch (pdecode->event_id) switch (pdecode->event_id)
{ {
/* Callback function that notifies user to have detected magic packet. */ /* Callback function that notifies user to have detected magic packet. */
case ETHER_CB_EVENT_ID_WAKEON_LAN: case ETHER_CB_EVENT_ID_WAKEON_LAN:
callback_wakeon_lan(channel); callback_wakeon_lan(channel);
break; break;
/* Callback function that notifies user to have become Link up. */ /* Callback function that notifies user to have become Link up. */
case ETHER_CB_EVENT_ID_LINK_ON: case ETHER_CB_EVENT_ID_LINK_ON:
callback_link_on(channel); callback_link_on(channel);
break; break;
/* Callback function that notifies user to have become Link down. */ /* Callback function that notifies user to have become Link down. */
case ETHER_CB_EVENT_ID_LINK_OFF: case ETHER_CB_EVENT_ID_LINK_OFF:
callback_link_off(channel); callback_link_off(channel);
break; break;
default: default:
break; break;
} }
} /* End of function callback_ether() */ } /* End of function callback_ether() */
/*********************************************************************************************************************** /***********************************************************************************************************************
* Function Name: callback_wakeon_lan * Function Name: callback_wakeon_lan
* Description : * Description :
* Arguments : channel - * Arguments : channel -
* Ethernet channel number * Ethernet channel number
* Return Value : none * Return Value : none
***********************************************************************************************************************/ ***********************************************************************************************************************/
static void callback_wakeon_lan(uint32_t channel) static void callback_wakeon_lan(uint32_t channel)
{ {
if (ETHER_CHANNEL_MAX > channel) if (ETHER_CHANNEL_MAX > channel)
{ {
magic_packet_detect[channel] = 1; magic_packet_detect[channel] = 1;
/* Please add necessary processing when magic packet is detected. */ /* Please add necessary processing when magic packet is detected. */
} }
} /* End of function callback_wakeon_lan() */ } /* End of function callback_wakeon_lan() */
/*********************************************************************************************************************** /***********************************************************************************************************************
* Function Name: callback_link_on * Function Name: callback_link_on
* Description : * Description :
* Arguments : channel - * Arguments : channel -
* Ethernet channel number * Ethernet channel number
* Return Value : none * Return Value : none
***********************************************************************************************************************/ ***********************************************************************************************************************/
static void callback_link_on(uint32_t channel) static void callback_link_on(uint32_t channel)
{ {
if (ETHER_CHANNEL_MAX > channel) if (ETHER_CHANNEL_MAX > channel)
{ {
link_detect[channel] = ETHER_FLAG_ON_LINK_ON; link_detect[channel] = ETHER_FLAG_ON_LINK_ON;
/* Please add necessary processing when becoming Link up. */ /* Please add necessary processing when becoming Link up. */
prvLinkStatusChange( 1 ); prvLinkStatusChange( 1 );
} }
} /* End of function callback_link_on() */ } /* End of function callback_link_on() */
/*********************************************************************************************************************** /***********************************************************************************************************************
* Function Name: callback_link_off * Function Name: callback_link_off
* Description : * Description :
* Arguments : channel - * Arguments : channel -
* Ethernet channel number * Ethernet channel number
* Return Value : none * Return Value : none
***********************************************************************************************************************/ ***********************************************************************************************************************/
static void callback_link_off(uint32_t channel) static void callback_link_off(uint32_t channel)
{ {
if (ETHER_CHANNEL_MAX > channel) if (ETHER_CHANNEL_MAX > channel)
{ {
link_detect[channel] = ETHER_FLAG_ON_LINK_OFF; link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;
/* Please add necessary processing when becoming Link down. */ /* Please add necessary processing when becoming Link down. */
prvLinkStatusChange( 0 ); prvLinkStatusChange( 0 );
} }
} /* End of function ether_cb_link_off() */ } /* End of function ether_cb_link_off() */
/* End of File */ /* End of File */

View file

@ -1,118 +1,118 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
#include "semphr.h" #include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
/* Hardware includes. */ /* Hardware includes. */
#include "hwEthernet.h" #include "hwEthernet.h"
/* Demo includes. */ /* Demo includes. */
#include "NetworkInterface.h" #include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1 #if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else #else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif #endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the /* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */ up. */
#define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS ) #define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )
#define niMAX_TX_ATTEMPTS ( 5 ) #define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the /* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */ interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 ) #define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* A deferred interrupt handler task that processes * A deferred interrupt handler task that processes
*/ */
extern void vEMACHandlerTask( void *pvParameters ); extern void vEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */ /* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue; extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx /* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */ interrupt is received. */
SemaphoreHandle_t xEMACRxEventSemaphore = NULL; SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
BaseType_t xStatus, xReturn; BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ]; extern uint8_t ucMACAddress[ 6 ];
/* Initialise the MAC. */ /* Initialise the MAC. */
vInitEmac(); vInitEmac();
while( lEMACWaitForLink() != pdPASS ) while( lEMACWaitForLink() != pdPASS )
{ {
vTaskDelay( 20 ); vTaskDelay( 20 );
} }
vSemaphoreCreateBinary( xEMACRxEventSemaphore ); vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore ); configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to /* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */ ensure the interrupt handler can return directly to it. */
xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL ); xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
xReturn = pdPASS; xReturn = pdPASS;
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{ {
extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength ); extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength ); vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
/* Finished with the network buffer. */ /* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return pdTRUE; return pdTRUE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,175 +1,175 @@
#define xBUFFER_CACHE_SIZE 10 #define xBUFFER_CACHE_SIZE 10
#define xMAX_FAULT_INJECTION_RATE 15 #define xMAX_FAULT_INJECTION_RATE 15
#define xMIN_FAULT_INJECTION_RATE 3 #define xMIN_FAULT_INJECTION_RATE 3
#define xNUM_FAULT_TYPES 1 #define xNUM_FAULT_TYPES 1
static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 }; static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
#define xFAULT_LOG_SIZE 2048 #define xFAULT_LOG_SIZE 2048
uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ]; uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
uint32_t ulFaultLogIndex = 0; uint32_t ulFaultLogIndex = 0;
static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn ) static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
{ {
BaseType_t x, xReturn = pdFALSE; BaseType_t x, xReturn = pdFALSE;
for( x = 0; x < xBUFFER_CACHE_SIZE; x++ ) for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
{ {
if( xNetworkBufferCache[ x ] == NULL ) if( xNetworkBufferCache[ x ] == NULL )
{ {
xNetworkBufferCache[ x ] = pxNetworkBufferIn; xNetworkBufferCache[ x ] = pxNetworkBufferIn;
xReturn = pdTRUE; xReturn = pdTRUE;
break; break;
} }
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvGetCachedPacket( void ) static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
{ {
BaseType_t x; BaseType_t x;
NetworkBufferDescriptor_t *pxReturn = NULL; NetworkBufferDescriptor_t *pxReturn = NULL;
for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- ) for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
{ {
if( xNetworkBufferCache[ x ] != NULL ) if( xNetworkBufferCache[ x ] != NULL )
{ {
pxReturn = xNetworkBufferCache[ x ]; pxReturn = xNetworkBufferCache[ x ];
xNetworkBufferCache[ x ] = NULL; xNetworkBufferCache[ x ] = NULL;
break; break;
} }
} }
return pxReturn; return pxReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData ) static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
{ {
NetworkBufferDescriptor_t *pxReturn; NetworkBufferDescriptor_t *pxReturn;
/* Obtain a new descriptor. */ /* Obtain a new descriptor. */
pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 ); pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
if( pxReturn != NULL ) if( pxReturn != NULL )
{ {
/* Copy in the packet data. */ /* Copy in the packet data. */
pxReturn->xDataLength = pxOriginalPacket->xDataLength; pxReturn->xDataLength = pxOriginalPacket->xDataLength;
memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength ); memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
} }
return pxReturn; return pxReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData ) static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
{ {
static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0; static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn; NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
uint32_t ulFault; uint32_t ulFault;
return pxNetworkBufferIn; return pxNetworkBufferIn;
ulCallCount++; ulCallCount++;
if( ulCallCount > ulNextFaultCallCount ) if( ulCallCount > ulNextFaultCallCount )
{ {
xApplicationGetRandomNumber( &( ulNextFaultCallCount ) ); xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );
ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE; ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE ) if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
{ {
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE; ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
} }
ulCallCount = 0; ulCallCount = 0;
xApplicationGetRandomNumber( &( ulFault ) ); xApplicationGetRandomNumber( &( ulFault ) );
ulFault = ulFault % xNUM_FAULT_TYPES; ulFault = ulFault % xNUM_FAULT_TYPES;
if( ulFaultLogIndex < xFAULT_LOG_SIZE ) if( ulFaultLogIndex < xFAULT_LOG_SIZE )
{ {
ulInjectedFault[ ulFaultLogIndex ] = ulFault; ulInjectedFault[ ulFaultLogIndex ] = ulFault;
ulFaultLogIndex++; ulFaultLogIndex++;
} }
switch( ulFault ) switch( ulFault )
{ {
case 0: case 0:
/* Just drop the packet. */ /* Just drop the packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn ); vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
pxReturn = NULL; pxReturn = NULL;
break; break;
case 1: case 1:
/* Store the packet in the cache for later. */ /* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE ) if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{ {
/* The packet may get sent later, it is not being sent /* The packet may get sent later, it is not being sent
now. */ now. */
pxReturn = NULL; pxReturn = NULL;
} }
break; break;
case 2: case 2:
/* Send a cached packet. */ /* Send a cached packet. */
pxReturn = prvGetCachedPacket(); pxReturn = prvGetCachedPacket();
if( pxReturn != NULL ) if( pxReturn != NULL )
{ {
/* A cached packet was obtained so drop the original /* A cached packet was obtained so drop the original
packet. */ packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn ); vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
} }
else else
{ {
/* Could not obtain a packet from the cache so just return /* Could not obtain a packet from the cache so just return
the packet that was passed in. */ the packet that was passed in. */
pxReturn = pxNetworkBufferIn; pxReturn = pxNetworkBufferIn;
} }
break; break;
case 4: case 4:
/* Send a duplicate of the packet right away. */ /* Send a duplicate of the packet right away. */
pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData ); pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
/* Send the original packet to the stack. */ /* Send the original packet to the stack. */
xRxEvent.pvData = ( void * ) pxNetworkBufferIn; xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{ {
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn ); vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
} }
break; break;
case 5: case 5:
/* Send both a cached packet and the current packet. */ /* Send both a cached packet and the current packet. */
xRxEvent.pvData = ( void * ) prvGetCachedPacket(); xRxEvent.pvData = ( void * ) prvGetCachedPacket();
if( xRxEvent.pvData != NULL ) if( xRxEvent.pvData != NULL )
{ {
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL ) if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{ {
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn ); vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
} }
} }
break; break;
case 6: case 6:
case 7: case 7:
case 8: case 8:
/* Store the packet in the cache for later. */ /* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE ) if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{ {
/* The packet may get sent later, it is not being sent /* The packet may get sent later, it is not being sent
now. */ now. */
pxReturn = NULL; pxReturn = NULL;
} }
break; break;
} }
} }
return pxReturn; return pxReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,398 +1,398 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
#include "semphr.h" #include "semphr.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
/* Xilinx library files. */ /* Xilinx library files. */
#include <xemacps.h> #include <xemacps.h>
#include "Zynq/x_topology.h" #include "Zynq/x_topology.h"
#include "Zynq/x_emacpsif.h" #include "Zynq/x_emacpsif.h"
#include "Zynq/x_emacpsif_hw.h" #include "Zynq/x_emacpsif_hw.h"
/* Provided memory configured as uncached. */ /* Provided memory configured as uncached. */
#include "uncached_memory.h" #include "uncached_memory.h"
#ifndef BMSR_LINK_STATUS #ifndef BMSR_LINK_STATUS
#define BMSR_LINK_STATUS 0x0004UL #define BMSR_LINK_STATUS 0x0004UL
#endif #endif
#ifndef PHY_LS_HIGH_CHECK_TIME_MS #ifndef PHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not /* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
receiving packets. */ receiving packets. */
#define PHY_LS_HIGH_CHECK_TIME_MS 15000 #define PHY_LS_HIGH_CHECK_TIME_MS 15000
#endif #endif
#ifndef PHY_LS_LOW_CHECK_TIME_MS #ifndef PHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still low every second. */ /* Check if the LinkSStatus in the PHY is still low every second. */
#define PHY_LS_LOW_CHECK_TIME_MS 1000 #define PHY_LS_LOW_CHECK_TIME_MS 1000
#endif #endif
/* The size of each buffer when BufferAllocation_1 is used: /* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */ http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536 #define niBUFFER_1_PACKET_SIZE 1536
/* Naming and numbering of PHY registers. */ /* Naming and numbering of PHY registers. */
#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */ #define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
#ifndef iptraceEMAC_TASK_STARTING #ifndef iptraceEMAC_TASK_STARTING
#define iptraceEMAC_TASK_STARTING() do { } while( 0 ) #define iptraceEMAC_TASK_STARTING() do { } while( 0 )
#endif #endif
/* Default the size of the stack used by the EMAC deferred handler task to twice /* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE #ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE ) #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Look for the link to be up every few milliseconds until either xMaxTime time * Look for the link to be up every few milliseconds until either xMaxTime time
* has passed or a link is found. * has passed or a link is found.
*/ */
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime ); static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
/* /*
* A deferred interrupt handler for all MAC/DMA interrupt sources. * A deferred interrupt handler for all MAC/DMA interrupt sources.
*/ */
static void prvEMACHandlerTask( void *pvParameters ); static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* EMAC data/descriptions. */ /* EMAC data/descriptions. */
static xemacpsif_s xEMACpsif; static xemacpsif_s xEMACpsif;
struct xtopology_t xXTopology = struct xtopology_t xXTopology =
{ {
.emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR, .emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
.emac_type = xemac_type_emacps, .emac_type = xemac_type_emacps,
.intc_baseaddr = 0x0, .intc_baseaddr = 0x0,
.intc_emac_intr = 0x0, .intc_emac_intr = 0x0,
.scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR, .scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
.scugic_emac_intr = 0x36, .scugic_emac_intr = 0x36,
}; };
XEmacPs_Config mac_config = XEmacPs_Config mac_config =
{ {
.DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */ .DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
.BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */ .BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
}; };
extern int phy_detected; extern int phy_detected;
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */ /* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
static uint32_t ulPHYLinkStatus = 0; static uint32_t ulPHYLinkStatus = 0;
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
#endif #endif
/* ucMACAddress as it appears in main.c */ /* ucMACAddress as it appears in main.c */
extern const uint8_t ucMACAddress[ 6 ]; extern const uint8_t ucMACAddress[ 6 ];
/* Holds the handle of the task used as a deferred interrupt processor. The /* Holds the handle of the task used as a deferred interrupt processor. The
handle is used so direct notifications can be sent to the task for all EMAC/DMA handle is used so direct notifications can be sent to the task for all EMAC/DMA
related interrupts. */ related interrupts. */
TaskHandle_t xEMACTaskHandle = NULL; TaskHandle_t xEMACTaskHandle = NULL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
uint32_t ulLinkSpeed, ulDMAReg; uint32_t ulLinkSpeed, ulDMAReg;
BaseType_t xStatus, xLinkStatus; BaseType_t xStatus, xLinkStatus;
XEmacPs *pxEMAC_PS; XEmacPs *pxEMAC_PS;
const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL ); const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
/* Guard against the init function being called more than once. */ /* Guard against the init function being called more than once. */
if( xEMACTaskHandle == NULL ) if( xEMACTaskHandle == NULL )
{ {
pxEMAC_PS = &( xEMACpsif.emacps ); pxEMAC_PS = &( xEMACpsif.emacps );
memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) ); memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress); xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
if( xStatus != XST_SUCCESS ) if( xStatus != XST_SUCCESS )
{ {
FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) ); FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
} }
/* Initialize the mac and set the MAC address. */ /* Initialize the mac and set the MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 ); XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
#if( ipconfigUSE_LLMNR == 1 ) #if( ipconfigUSE_LLMNR == 1 )
{ {
/* Also add LLMNR multicast MAC address. */ /* Also add LLMNR multicast MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 ); XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
} }
#endif /* ipconfigUSE_LLMNR == 1 */ #endif /* ipconfigUSE_LLMNR == 1 */
XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 ); XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
ulLinkSpeed = Phy_Setup( pxEMAC_PS ); ulLinkSpeed = Phy_Setup( pxEMAC_PS );
XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed); XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
/* Setting the operating speed of the MAC needs a delay. */ /* Setting the operating speed of the MAC needs a delay. */
vTaskDelay( pdMS_TO_TICKS( 25UL ) ); vTaskDelay( pdMS_TO_TICKS( 25UL ) );
ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET); ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
/* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive /* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
packets from the receiver packet buffer memory when no AHB resource is available. */ packets from the receiver packet buffer memory when no AHB resource is available. */
XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET, XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK); ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
setup_isr( &xEMACpsif ); setup_isr( &xEMACpsif );
init_dma( &xEMACpsif ); init_dma( &xEMACpsif );
start_emacps( &xEMACpsif ); start_emacps( &xEMACpsif );
prvGMACWaitLS( xWaitLinkDelay ); prvGMACWaitLS( xWaitLinkDelay );
/* The deferred interrupt handler task is created at the highest /* The deferred interrupt handler task is created at the highest
possible priority to ensure the interrupt handler can return directly possible priority to ensure the interrupt handler can return directly
to it. The task's handle is stored in xEMACTaskHandle so interrupts can to it. The task's handle is stored in xEMACTaskHandle so interrupts can
notify the task when there is something to process. */ notify the task when there is something to process. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle ); xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
} }
else else
{ {
/* Initialisation was already performed, just wait for the link. */ /* Initialisation was already performed, just wait for the link. */
prvGMACWaitLS( xWaitRelinkDelay ); prvGMACWaitLS( xWaitRelinkDelay );
} }
/* Only return pdTRUE when the Link Status of the PHY is high, otherwise the /* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
DHCP process and all other communication will fail. */ DHCP process and all other communication will fail. */
xLinkStatus = xGetPhyLinkStatus(); xLinkStatus = xGetPhyLinkStatus();
return ( xLinkStatus != pdFALSE ); return ( xLinkStatus != pdFALSE );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
{ {
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{ {
iptraceNETWORK_INTERFACE_TRANSMIT(); iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend ); emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
} }
else if( bReleaseAfterSend != pdFALSE ) else if( bReleaseAfterSend != pdFALSE )
{ {
/* No link. */ /* No link. */
vReleaseNetworkBufferAndDescriptor( pxBuffer ); vReleaseNetworkBufferAndDescriptor( pxBuffer );
} }
return pdTRUE; return pdTRUE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static inline unsigned long ulReadMDIO( unsigned ulRegister ) static inline unsigned long ulReadMDIO( unsigned ulRegister )
{ {
uint16_t usValue; uint16_t usValue;
XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue ); XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
return usValue; return usValue;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime ) static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
{ {
TickType_t xStartTime, xEndTime; TickType_t xStartTime, xEndTime;
const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL ); const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
BaseType_t xReturn; BaseType_t xReturn;
xStartTime = xTaskGetTickCount(); xStartTime = xTaskGetTickCount();
for( ;; ) for( ;; )
{ {
xEndTime = xTaskGetTickCount(); xEndTime = xTaskGetTickCount();
if( xEndTime - xStartTime > xMaxTime ) if( xEndTime - xStartTime > xMaxTime )
{ {
xReturn = pdFALSE; xReturn = pdFALSE;
break; break;
} }
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
break; break;
} }
vTaskDelay( xShortDelay ); vTaskDelay( xShortDelay );
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{ {
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) ); static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
uint8_t *ucRAMBuffer = ucNetworkPackets; uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul; uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{ {
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE; ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xGetPhyLinkStatus( void ) BaseType_t xGetPhyLinkStatus( void )
{ {
BaseType_t xReturn; BaseType_t xReturn;
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 ) if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
{ {
xReturn = pdFALSE; xReturn = pdFALSE;
} }
else else
{ {
xReturn = pdTRUE; xReturn = pdTRUE;
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters ) static void prvEMACHandlerTask( void *pvParameters )
{ {
TimeOut_t xPhyTime; TimeOut_t xPhyTime;
TickType_t xPhyRemTime; TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0; UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount; UBaseType_t uxCurrentCount;
BaseType_t xResult = 0; BaseType_t xResult = 0;
uint32_t xStatus; uint32_t xStatus;
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
/* Remove compiler warnings about unused parameters. */ /* Remove compiler warnings about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
/* A possibility to set some additional task properties like calling /* A possibility to set some additional task properties like calling
portTASK_USES_FLOATING_POINT() */ portTASK_USES_FLOATING_POINT() */
iptraceEMAC_TASK_STARTING(); iptraceEMAC_TASK_STARTING();
vTaskSetTimeOutState( &xPhyTime ); vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
for( ;; ) for( ;; )
{ {
uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentCount ) if( uxLastMinBufferCount != uxCurrentCount )
{ {
/* The logging produced below may be helpful /* The logging produced below may be helpful
while tuning +TCP: see how many buffers are in use. */ while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentCount; uxLastMinBufferCount = uxCurrentCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
} }
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{ {
static UBaseType_t uxLastMinQueueSpace = 0; static UBaseType_t uxLastMinQueueSpace = 0;
uxCurrentCount = uxGetMinimumIPQueueSpace(); uxCurrentCount = uxGetMinimumIPQueueSpace();
if( uxLastMinQueueSpace != uxCurrentCount ) if( uxLastMinQueueSpace != uxCurrentCount )
{ {
/* The logging produced below may be helpful /* The logging produced below may be helpful
while tuning +TCP: see how many buffers are in use. */ while tuning +TCP: see how many buffers are in use. */
uxLastMinQueueSpace = uxCurrentCount; uxLastMinQueueSpace = uxCurrentCount;
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
} }
} }
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */ #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 ) if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
{ {
/* No events to process now, wait for the next. */ /* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
} }
if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 ) if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
{ {
xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT; xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
xResult = emacps_check_rx( &xEMACpsif ); xResult = emacps_check_rx( &xEMACpsif );
} }
if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 ) if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
{ {
xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT; xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
emacps_check_tx( &xEMACpsif ); emacps_check_tx( &xEMACpsif );
} }
if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 ) if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
{ {
xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT; xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
emacps_check_errors( &xEMACpsif ); emacps_check_errors( &xEMACpsif );
} }
if( xResult > 0 ) if( xResult > 0 )
{ {
/* A packet was received. No need to check for the PHY status now, /* A packet was received. No need to check for the PHY status now,
but set a timer to check it later on. */ but set a timer to check it later on. */
vTaskSetTimeOutState( &xPhyTime ); vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
xResult = 0; xResult = 0;
} }
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
{ {
xStatus = ulReadMDIO( PHY_REG_01_BMSR ); xStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) ) if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
{ {
ulPHYLinkStatus = xStatus; ulPHYLinkStatus = xStatus;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) ); FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
} }
vTaskSetTimeOutState( &xPhyTime ); vTaskSetTimeOutState( &xPhyTime );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{ {
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
} }
else else
{ {
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
} }
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,144 +1,144 @@
/* /*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
* *
* Xilinx, Inc. * Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. * AND FITNESS FOR A PARTICULAR PURPOSE.
* *
*/ */
#ifndef __NETIF_XEMACPSIF_H__ #ifndef __NETIF_XEMACPSIF_H__
#define __NETIF_XEMACPSIF_H__ #define __NETIF_XEMACPSIF_H__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
#include "xstatus.h" #include "xstatus.h"
#include "sleep.h" #include "sleep.h"
#include "xparameters.h" #include "xparameters.h"
#include "xparameters_ps.h" /* defines XPAR values */ #include "xparameters_ps.h" /* defines XPAR values */
#include "xil_types.h" #include "xil_types.h"
#include "xil_assert.h" #include "xil_assert.h"
#include "xil_io.h" #include "xil_io.h"
#include "xil_exception.h" #include "xil_exception.h"
#include "xpseudo_asm.h" #include "xpseudo_asm.h"
#include "xil_cache.h" #include "xil_cache.h"
#include "xil_printf.h" #include "xil_printf.h"
#include "xuartps.h" #include "xuartps.h"
#include "xscugic.h" #include "xscugic.h"
#include "xemacps.h" /* defines XEmacPs API */ #include "xemacps.h" /* defines XEmacPs API */
//#include "netif/xpqueue.h" //#include "netif/xpqueue.h"
//#include "xlwipconfig.h" //#include "xlwipconfig.h"
void xemacpsif_setmac(uint32_t index, uint8_t *addr); void xemacpsif_setmac(uint32_t index, uint8_t *addr);
uint8_t* xemacpsif_getmac(uint32_t index); uint8_t* xemacpsif_getmac(uint32_t index);
//int xemacpsif_init(struct netif *netif); //int xemacpsif_init(struct netif *netif);
//int xemacpsif_input(struct netif *netif); //int xemacpsif_input(struct netif *netif);
#ifdef NOTNOW_BHILL #ifdef NOTNOW_BHILL
unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp); unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
#endif #endif
/* xaxiemacif_hw.c */ /* xaxiemacif_hw.c */
void xemacps_error_handler(XEmacPs * Temac); void xemacps_error_handler(XEmacPs * Temac);
struct xBD_TYPE { struct xBD_TYPE {
uint32_t address; uint32_t address;
uint32_t flags; uint32_t flags;
}; };
/* /*
* Missing declaration in 'src/xemacps_hw.h' : * Missing declaration in 'src/xemacps_hw.h' :
* When set, the GEM DMA will automatically * When set, the GEM DMA will automatically
* discard receive packets from the receiver packet * discard receive packets from the receiver packet
* buffer memory when no AHB resource is * buffer memory when no AHB resource is
* available. * available.
* When low, then received packets will remain to be * When low, then received packets will remain to be
* stored in the SRAM based packet buffer until * stored in the SRAM based packet buffer until
* AHB buffer resource next becomes available. * AHB buffer resource next becomes available.
*/ */
#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000 #define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
#define EMAC_IF_RX_EVENT 1 #define EMAC_IF_RX_EVENT 1
#define EMAC_IF_TX_EVENT 2 #define EMAC_IF_TX_EVENT 2
#define EMAC_IF_ERR_EVENT 4 #define EMAC_IF_ERR_EVENT 4
#define EMAC_IF_ALL_EVENT 7 #define EMAC_IF_ALL_EVENT 7
/* structure within each netif, encapsulating all information required for /* structure within each netif, encapsulating all information required for
* using a particular temac instance * using a particular temac instance
*/ */
typedef struct { typedef struct {
XEmacPs emacps; XEmacPs emacps;
/* pointers to memory holding buffer descriptors (used only with SDMA) */ /* pointers to memory holding buffer descriptors (used only with SDMA) */
struct xBD_TYPE *rxSegments; struct xBD_TYPE *rxSegments;
struct xBD_TYPE *txSegments; struct xBD_TYPE *txSegments;
unsigned char *tx_space; unsigned char *tx_space;
unsigned uTxUnitSize; unsigned uTxUnitSize;
char *remain_mem; char *remain_mem;
unsigned remain_siz; unsigned remain_siz;
volatile int rxHead, rxTail; volatile int rxHead, rxTail;
volatile int txHead, txTail; volatile int txHead, txTail;
volatile int txBusy; volatile int txBusy;
volatile uint32_t isr_events; volatile uint32_t isr_events;
unsigned int last_rx_frms_cntr; unsigned int last_rx_frms_cntr;
} xemacpsif_s; } xemacpsif_s;
//extern xemacpsif_s xemacpsif; //extern xemacpsif_s xemacpsif;
int is_tx_space_available(xemacpsif_s *emac); int is_tx_space_available(xemacpsif_s *emac);
/* xaxiemacif_dma.c */ /* xaxiemacif_dma.c */
struct xNETWORK_BUFFER; struct xNETWORK_BUFFER;
int emacps_check_rx( xemacpsif_s *xemacpsif ); int emacps_check_rx( xemacpsif_s *xemacpsif );
void emacps_check_tx( xemacpsif_s *xemacpsif ); void emacps_check_tx( xemacpsif_s *xemacpsif );
int emacps_check_errors( xemacpsif_s *xemacps ); int emacps_check_errors( xemacpsif_s *xemacps );
void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount ); void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend ); extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
extern unsigned Phy_Setup( XEmacPs *xemacpsp ); extern unsigned Phy_Setup( XEmacPs *xemacpsp );
extern void setup_isr( xemacpsif_s *xemacpsif ); extern void setup_isr( xemacpsif_s *xemacpsif );
extern XStatus init_dma( xemacpsif_s *xemacpsif ); extern XStatus init_dma( xemacpsif_s *xemacpsif );
extern void start_emacps( xemacpsif_s *xemacpsif ); extern void start_emacps( xemacpsif_s *xemacpsif );
void EmacEnableIntr(void); void EmacEnableIntr(void);
void EmacDisableIntr(void); void EmacDisableIntr(void);
XStatus init_axi_dma(xemacpsif_s *xemacpsif); XStatus init_axi_dma(xemacpsif_s *xemacpsif);
void process_sent_bds( xemacpsif_s *xemacpsif ); void process_sent_bds( xemacpsif_s *xemacpsif );
void emacps_send_handler(void *arg); void emacps_send_handler(void *arg);
void emacps_recv_handler(void *arg); void emacps_recv_handler(void *arg);
void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord); void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
void HandleTxErrors(xemacpsif_s *xemacpsif); void HandleTxErrors(xemacpsif_s *xemacpsif);
XEmacPs_Config *xemacps_lookup_config(unsigned mac_base); XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
void clean_dma_txdescs(xemacpsif_s *xemacpsif); void clean_dma_txdescs(xemacpsif_s *xemacpsif);
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif); void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* __NETIF_XAXIEMACIF_H__ */ #endif /* __NETIF_XAXIEMACIF_H__ */

View file

@ -1,243 +1,243 @@
/* /*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
* *
* Xilinx, Inc. * Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. * AND FITNESS FOR A PARTICULAR PURPOSE.
* *
*/ */
/* Standard includes. */ /* Standard includes. */
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "Zynq/x_emacpsif.h" #include "Zynq/x_emacpsif.h"
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "queue.h" #include "queue.h"
///* FreeRTOS+TCP includes. */ ///* FreeRTOS+TCP includes. */
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
extern TaskHandle_t xEMACTaskHandle; extern TaskHandle_t xEMACTaskHandle;
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c /*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
*** to run it on a PEEP board *** to run it on a PEEP board
***/ ***/
unsigned int link_speed = 100; unsigned int link_speed = 100;
void setup_isr( xemacpsif_s *xemacpsif ) void setup_isr( xemacpsif_s *xemacpsif )
{ {
/* /*
* Setup callbacks * Setup callbacks
*/ */
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND, XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
(void *) emacps_send_handler, (void *) emacps_send_handler,
(void *) xemacpsif); (void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV, XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
(void *) emacps_recv_handler, (void *) emacps_recv_handler,
(void *) xemacpsif); (void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR, XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
(void *) emacps_error_handler, (void *) emacps_error_handler,
(void *) xemacpsif); (void *) xemacpsif);
} }
void start_emacps (xemacpsif_s *xemacps) void start_emacps (xemacpsif_s *xemacps)
{ {
/* start the temac */ /* start the temac */
XEmacPs_Start(&xemacps->emacps); XEmacPs_Start(&xemacps->emacps);
} }
extern struct xtopology_t xXTopology; extern struct xtopology_t xXTopology;
volatile int error_msg_count = 0; volatile int error_msg_count = 0;
volatile const char *last_err_msg = ""; volatile const char *last_err_msg = "";
struct xERROR_MSG { struct xERROR_MSG {
void *arg; void *arg;
u8 Direction; u8 Direction;
u32 ErrorWord; u32 ErrorWord;
}; };
static struct xERROR_MSG xErrorList[ 8 ]; static struct xERROR_MSG xErrorList[ 8 ];
static BaseType_t xErrorHead, xErrorTail; static BaseType_t xErrorHead, xErrorTail;
void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord) void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
{ {
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xemacpsif_s *xemacpsif; xemacpsif_s *xemacpsif;
BaseType_t xNextHead = xErrorHead; BaseType_t xNextHead = xErrorHead;
xemacpsif = (xemacpsif_s *)(arg); xemacpsif = (xemacpsif_s *)(arg);
if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) ) if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
{ {
if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) ) if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
xNextHead = 0; xNextHead = 0;
if( xNextHead != xErrorTail ) if( xNextHead != xErrorTail )
{ {
xErrorList[ xErrorHead ].arg = arg; xErrorList[ xErrorHead ].arg = arg;
xErrorList[ xErrorHead ].Direction = Direction; xErrorList[ xErrorHead ].Direction = Direction;
xErrorList[ xErrorHead ].ErrorWord = ErrorWord; xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
xErrorHead = xNextHead; xErrorHead = xNextHead;
xemacpsif = (xemacpsif_s *)(arg); xemacpsif = (xemacpsif_s *)(arg);
xemacpsif->isr_events |= EMAC_IF_ERR_EVENT; xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
} }
if( xEMACTaskHandle != NULL ) if( xEMACTaskHandle != NULL )
{ {
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken ); vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
} }
} }
portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
} }
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord); static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
int emacps_check_errors( xemacpsif_s *xemacps ) int emacps_check_errors( xemacpsif_s *xemacps )
{ {
int xResult; int xResult;
( void ) xemacps; ( void ) xemacps;
if( xErrorHead == xErrorTail ) if( xErrorHead == xErrorTail )
{ {
xResult = 0; xResult = 0;
} }
else else
{ {
xResult = 1; xResult = 1;
emacps_handle_error( emacps_handle_error(
xErrorList[ xErrorTail ].arg, xErrorList[ xErrorTail ].arg,
xErrorList[ xErrorTail ].Direction, xErrorList[ xErrorTail ].Direction,
xErrorList[ xErrorTail ].ErrorWord ); xErrorList[ xErrorTail ].ErrorWord );
} }
return xResult; return xResult;
} }
BaseType_t xNetworkInterfaceInitialise( void ); BaseType_t xNetworkInterfaceInitialise( void );
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
{ {
xemacpsif_s *xemacpsif; xemacpsif_s *xemacpsif;
struct xtopology_t *xtopologyp; struct xtopology_t *xtopologyp;
XEmacPs *xemacps; XEmacPs *xemacps;
xemacpsif = (xemacpsif_s *)(arg); xemacpsif = (xemacpsif_s *)(arg);
xtopologyp = &xXTopology; xtopologyp = &xXTopology;
xemacps = &xemacpsif->emacps; xemacps = &xemacpsif->emacps;
/* Do not appear to be used. */ /* Do not appear to be used. */
( void ) xemacps; ( void ) xemacps;
( void ) xtopologyp; ( void ) xtopologyp;
last_err_msg = NULL; last_err_msg = NULL;
if( ErrorWord != 0 ) if( ErrorWord != 0 )
{ {
switch (Direction) { switch (Direction) {
case XEMACPS_RECV: case XEMACPS_RECV:
if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
{ {
last_err_msg = "Receive DMA error"; last_err_msg = "Receive DMA error";
xNetworkInterfaceInitialise( ); xNetworkInterfaceInitialise( );
} }
if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
{ {
last_err_msg = "Receive over run"; last_err_msg = "Receive over run";
emacps_recv_handler(arg); emacps_recv_handler(arg);
} }
if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
{ {
last_err_msg = "Receive buffer not available"; last_err_msg = "Receive buffer not available";
emacps_recv_handler(arg); emacps_recv_handler(arg);
} }
break; break;
case XEMACPS_SEND: case XEMACPS_SEND:
if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
{ {
last_err_msg = "Transmit DMA error"; last_err_msg = "Transmit DMA error";
xNetworkInterfaceInitialise( ); xNetworkInterfaceInitialise( );
} }
if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
{ {
last_err_msg = "Transmit under run"; last_err_msg = "Transmit under run";
HandleTxErrors( xemacpsif ); HandleTxErrors( xemacpsif );
} }
if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
{ {
last_err_msg = "Transmit buffer exhausted"; last_err_msg = "Transmit buffer exhausted";
HandleTxErrors( xemacpsif ); HandleTxErrors( xemacpsif );
} }
if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
{ {
last_err_msg = "Transmit retry excessed limits"; last_err_msg = "Transmit retry excessed limits";
HandleTxErrors( xemacpsif ); HandleTxErrors( xemacpsif );
} }
if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 ) if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
{ {
last_err_msg = "Transmit collision"; last_err_msg = "Transmit collision";
emacps_check_tx( xemacpsif ); emacps_check_tx( xemacpsif );
} }
break; break;
} }
} }
// Break on this statement and inspect error_msg if you like // Break on this statement and inspect error_msg if you like
if( last_err_msg != NULL ) if( last_err_msg != NULL )
{ {
error_msg_count++; error_msg_count++;
FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) ); FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
} }
} }
extern XEmacPs_Config mac_config; extern XEmacPs_Config mac_config;
void HandleTxErrors(xemacpsif_s *xemacpsif) void HandleTxErrors(xemacpsif_s *xemacpsif)
{ {
u32 netctrlreg; u32 netctrlreg;
//taskENTER_CRITICAL() //taskENTER_CRITICAL()
{ {
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET); XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK); netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg); XEMACPS_NWCTRL_OFFSET, netctrlreg);
clean_dma_txdescs( xemacpsif ); clean_dma_txdescs( xemacpsif );
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress, netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET); XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK); netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress, XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg); XEMACPS_NWCTRL_OFFSET, netctrlreg);
} }
//taskEXIT_CRITICAL( ); //taskEXIT_CRITICAL( );
} }

View file

@ -1,39 +1,39 @@
/* /*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved. * Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
* *
* Xilinx, Inc. * Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. * AND FITNESS FOR A PARTICULAR PURPOSE.
* *
*/ */
#ifndef __XEMACPSIF_HW_H_ #ifndef __XEMACPSIF_HW_H_
#define __XEMACPSIF_HW_H_ #define __XEMACPSIF_HW_H_
#include "Zynq/x_emacpsif.h" #include "Zynq/x_emacpsif.h"
//#include "lwip/netif.h" //#include "lwip/netif.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
XEmacPs_Config * lookup_config(unsigned mac_base); XEmacPs_Config * lookup_config(unsigned mac_base);
//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif); //void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
int emacps_check_errors( xemacpsif_s *xemacps ); int emacps_check_errors( xemacpsif_s *xemacps );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View file

@ -1,46 +1,46 @@
/* /*
* Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved. * Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
* *
* Xilinx, Inc. * Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. * AND FITNESS FOR A PARTICULAR PURPOSE.
* *
*/ */
#ifndef __XTOPOLOGY_H_ #ifndef __XTOPOLOGY_H_
#define __XTOPOLOGY_H_ #define __XTOPOLOGY_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps }; enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
struct xtopology_t { struct xtopology_t {
unsigned emac_baseaddr; unsigned emac_baseaddr;
enum xemac_types emac_type; enum xemac_types emac_type;
unsigned intc_baseaddr; unsigned intc_baseaddr;
unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */ unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
unsigned scugic_baseaddr; /* valid only for Zynq */ unsigned scugic_baseaddr; /* valid only for Zynq */
unsigned scugic_emac_intr; /* valid only for GEM */ unsigned scugic_emac_intr; /* valid only for GEM */
}; };
extern int x_topology_n_emacs; extern int x_topology_n_emacs;
extern struct xtopology_t x_topology[]; extern struct xtopology_t x_topology[];
int x_topology_find_index(unsigned base); int x_topology_find_index(unsigned base);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View file

@ -1,63 +1,63 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "list.h" #include "list.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it driver will filter incoming packets and only pass the stack those packets it
considers need processing. */ considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else #else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif #endif
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
/* FIX ME. */ /* FIX ME. */
return pdFALSE; return pdFALSE;
} }
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{ {
/* FIX ME. */ /* FIX ME. */
return pdFALSE; return pdFALSE;
} }
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{ {
/* FIX ME. */ /* FIX ME. */
} }
BaseType_t xGetPhyLinkStatus( void ) BaseType_t xGetPhyLinkStatus( void )
{ {
/* FIX ME. */ /* FIX ME. */
return pdFALSE; return pdFALSE;
} }

View file

@ -1,217 +1,217 @@
/* /*
FreeRTOS+TCP V2.0.11 FreeRTOS+TCP V2.0.11
Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 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, the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 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 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 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. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos http://aws.amazon.com/freertos
http://www.FreeRTOS.org http://www.FreeRTOS.org
*/ */
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "list.h" #include "list.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
/* FreeRTOS+TCP includes. */ /* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h" #include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "wifi-decl.h" #include "wifi-decl.h"
#include "wmerrno.h" #include "wmerrno.h"
#include "wifi.h" #include "wifi.h"
#include <wmlog.h> #include <wmlog.h>
#define net_e(...) \ #define net_e(...) \
wmlog_e("freertos_tcp", ##__VA_ARGS__) wmlog_e("freertos_tcp", ##__VA_ARGS__)
#define net_w(...) \ #define net_w(...) \
wmlog_w("freertos_tcp", ##__VA_ARGS__) wmlog_w("freertos_tcp", ##__VA_ARGS__)
#define net_d(...) \ #define net_d(...) \
wmlog("freertos_tcp", ##__VA_ARGS__) wmlog("freertos_tcp", ##__VA_ARGS__)
#if 0 //this is lwip structure. #if 0 //this is lwip structure.
#define MAX_INTERFACES_SUPPORTED 3 #define MAX_INTERFACES_SUPPORTED 3
static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED]; static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];
#endif #endif
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it driver will filter incoming packets and only pass the stack those packets it
considers need processing. */ considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) #if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else #else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif #endif
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any) #define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast) #define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_NONE ((u32_t)0xffffffffUL) #define IPADDR_NONE ((u32_t)0xffffffffUL)
/** 127.0.0.1 */ /** 127.0.0.1 */
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) #define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
/** 0.0.0.0 */ /** 0.0.0.0 */
#define IPADDR_ANY ((u32_t)0x00000000UL) #define IPADDR_ANY ((u32_t)0x00000000UL)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) #define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
/** 255.255.255.255 */ /** 255.255.255.255 */
#define INADDR_NONE IPADDR_NONE #define INADDR_NONE IPADDR_NONE
/** 127.0.0.1 */ /** 127.0.0.1 */
#define INADDR_LOOPBACK IPADDR_LOOPBACK #define INADDR_LOOPBACK IPADDR_LOOPBACK
/** 0.0.0.0 */ /** 0.0.0.0 */
#define INADDR_ANY IPADDR_ANY #define INADDR_ANY IPADDR_ANY
/** 255.255.255.255 */ /** 255.255.255.255 */
#define INADDR_BROADCAST IPADDR_BROADCAST #define INADDR_BROADCAST IPADDR_BROADCAST
enum if_state_t { enum if_state_t {
INTERFACE_DOWN = 0, INTERFACE_DOWN = 0,
INTERFACE_UP, INTERFACE_UP,
}; };
struct ip_addr { struct ip_addr {
u32_t addr; u32_t addr;
}; };
#define MLAN_BSS_TYPE_STA 0 #define MLAN_BSS_TYPE_STA 0
extern uint8_t outbuf[2048]; extern uint8_t outbuf[2048];
extern bool mlan_is_amsdu(const t_u8 *rcvdata); extern bool mlan_is_amsdu(const t_u8 *rcvdata);
extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface); extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);
extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen); extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);
extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer); extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer);
static volatile uint32_t xInterfaceState = INTERFACE_DOWN; static volatile uint32_t xInterfaceState = INTERFACE_DOWN;
static int process_data_packet(const t_u8 *databuf, const t_u16 datalen) static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)
{ {
int interface = BSS_TYPE_STA; int interface = BSS_TYPE_STA;
t_u8 *payload = NULL; t_u8 *payload = NULL;
t_u16 payload_len = 0; t_u16 payload_len = 0;
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 ); const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
NetworkBufferDescriptor_t *pxNetworkBuffer; NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface); payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);
if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) { if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {
net_d("Dropping packet\r\n"); net_d("Dropping packet\r\n");
return WM_SUCCESS; return WM_SUCCESS;
} }
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime); pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) { if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */ /* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = payload_len; pxNetworkBuffer->xDataLength = payload_len;
/* Copy the packet data. */ /* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len); memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);
xRxEvent.pvData = (void *) pxNetworkBuffer; xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) { if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len); wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return WM_FAIL; return WM_FAIL;
} }
} }
return WM_SUCCESS; return WM_SUCCESS;
} }
/* Callback function called from the wifi module */ /* Callback function called from the wifi module */
void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata, void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,
const t_u16 datalen) const t_u16 datalen)
{ {
if (interface == BSS_TYPE_STA) if (interface == BSS_TYPE_STA)
process_data_packet(rcvdata, datalen); process_data_packet(rcvdata, datalen);
} }
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
uint8_t ret; uint8_t ret;
mac_addr_t mac_addr; mac_addr_t mac_addr;
ret = wifi_get_device_mac_addr(&mac_addr); ret = wifi_get_device_mac_addr(&mac_addr);
if (ret != WM_SUCCESS) { if (ret != WM_SUCCESS) {
net_d("Failed to get mac address"); net_d("Failed to get mac address");
} }
FreeRTOS_UpdateMACAddress(mac_addr.mac); FreeRTOS_UpdateMACAddress(mac_addr.mac);
return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE; return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;
} }
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{ {
/* FIX ME. */ /* FIX ME. */
} }
BaseType_t xGetPhyLinkStatus( void ) BaseType_t xGetPhyLinkStatus( void )
{ {
/* FIX ME. */ /* FIX ME. */
return pdFALSE; return pdFALSE;
} }
void vNetworkNotifyIFDown() void vNetworkNotifyIFDown()
{ {
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL }; IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
xInterfaceState = INTERFACE_DOWN; xInterfaceState = INTERFACE_DOWN;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) { if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {
/* Could not send the message, so it is still pending. */ /* Could not send the message, so it is still pending. */
net_e("Could not send network down event"); net_e("Could not send network down event");
} }
else { else {
/* Message was sent so it is not pending. */ /* Message was sent so it is not pending. */
net_d("Sent network down event"); net_d("Sent network down event");
} }
} }
void vNetworkNotifyIFUp() void vNetworkNotifyIFUp()
{ {
xInterfaceState = INTERFACE_UP; xInterfaceState = INTERFACE_UP;
} }
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend ) BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{ {
uint8_t pkt_len; uint8_t pkt_len;
if (pxNetworkBuffer == NULL || if (pxNetworkBuffer == NULL ||
pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL ||
pxNetworkBuffer->xDataLength == 0) { pxNetworkBuffer->xDataLength == 0) {
net_d("Incorrect params"); net_d("Incorrect params");
return pdFALSE; return pdFALSE;
} }
memset(outbuf, 0x00, sizeof(outbuf)); memset(outbuf, 0x00, sizeof(outbuf));
pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */ pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */
memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer, memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,
pxNetworkBuffer->xDataLength); pxNetworkBuffer->xDataLength);
int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength); int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);
if (ret != WM_SUCCESS) { if (ret != WM_SUCCESS) {
net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret); net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
} }
if (xReleaseAfterSend != pdFALSE) { if (xReleaseAfterSend != pdFALSE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer); vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
} }
return ret == WM_SUCCESS ? pdTRUE : pdFALSE; return ret == WM_SUCCESS ? pdTRUE : pdFALSE;
} }

View file

@ -1,192 +1,192 @@
/******************************************************************************* /*******************************************************************************
* Network Interface file * Network Interface file
* *
* Summary: * Summary:
* Network Interface file for FreeRTOS-Plus-TCP stack * Network Interface file for FreeRTOS-Plus-TCP stack
* *
* Description: * Description:
* - Interfaces PIC32 to the FreeRTOS TCP/IP stack * - Interfaces PIC32 to the FreeRTOS TCP/IP stack
*******************************************************************************/ *******************************************************************************/
/******************************************************************************* /*******************************************************************************
* File Name: pic32_NetworkInterface.c * File Name: pic32_NetworkInterface.c
* Copyright 2017 Microchip Technology Incorporated and its subsidiaries. * Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * 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 * this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to * the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * 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 * of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions: * so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all * The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. * copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE * SOFTWARE
*******************************************************************************/ *******************************************************************************/
#ifndef PIC32_USE_ETHERNET #ifndef PIC32_USE_ETHERNET
#include <sys/kmem.h> #include <sys/kmem.h>
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "semphr.h" #include "semphr.h"
#include "event_groups.h" #include "event_groups.h"
#include "FreeRTOS_IP.h" #include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h" #include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h" #include "NetworkInterface.h"
#include "NetworkBufferManagement.h" #include "NetworkBufferManagement.h"
#include "peripheral/eth/plib_eth.h" #include "peripheral/eth/plib_eth.h"
#include "system_config.h" #include "system_config.h"
#include "system/console/sys_console.h" #include "system/console/sys_console.h"
#include "system/debug/sys_debug.h" #include "system/debug/sys_debug.h"
#include "system/command/sys_command.h" #include "system/command/sys_command.h"
#include "driver/ethmac/drv_ethmac.h" #include "driver/ethmac/drv_ethmac.h"
#include "driver/miim/drv_miim.h" #include "driver/miim/drv_miim.h"
#include "m2m_types.h" #include "m2m_types.h"
#include "tcpip/tcpip.h" #include "tcpip/tcpip.h"
#include "tcpip/src/tcpip_private.h" #include "tcpip/src/tcpip_private.h"
#include "tcpip/src/link_list.h" #include "tcpip/src/link_list.h"
#include "wilc1000_task.h" #include "wilc1000_task.h"
#include "NetworkConfig.h" #include "NetworkConfig.h"
#include "iot_wifi.h" #include "iot_wifi.h"
/* local definitions and data */ /* local definitions and data */
/* FreeRTOS implementation functions */ /* FreeRTOS implementation functions */
BaseType_t xNetworkInterfaceInitialise( void ) BaseType_t xNetworkInterfaceInitialise( void )
{ {
WIFINetworkParams_t xNetworkParams; WIFINetworkParams_t xNetworkParams;
xNetworkParams.pcSSID = clientcredentialWIFI_SSID; xNetworkParams.pcSSID = clientcredentialWIFI_SSID;
xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID ); xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );
xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD; xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;
xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD ); xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );
xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY; xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;
xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */ xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */
/*Turn WiFi ON */ /*Turn WiFi ON */
if( WIFI_On() != eWiFiSuccess ) if( WIFI_On() != eWiFiSuccess )
{ {
return pdFAIL; return pdFAIL;
} }
/* Connect to the AP */ /* Connect to the AP */
if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess ) if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )
{ {
return pdFAIL; return pdFAIL;
} }
return pdPASS; return pdPASS;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend ) BaseType_t xReleaseAfterSend )
{ {
BaseType_t retRes = pdFALSE; BaseType_t retRes = pdFALSE;
if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) ) if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
{ {
/* There you go */ /* There you go */
if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 ) if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )
{ {
retRes = pdTRUE; retRes = pdTRUE;
} }
/* The buffer has been sent so can be released. */ /* The buffer has been sent so can be released. */
if( xReleaseAfterSend != pdFALSE ) if( xReleaseAfterSend != pdFALSE )
{ {
vReleaseNetworkBufferAndDescriptor( pxDescriptor ); vReleaseNetworkBufferAndDescriptor( pxDescriptor );
} }
} }
return retRes; return retRes;
} }
/************************************* Section: helper functions ************************************************** */ /************************************* Section: helper functions ************************************************** */
/* */ /* */
/************************************* Section: worker code ************************************************** */ /************************************* Section: worker code ************************************************** */
/* */ /* */
void xNetworkFrameReceived( uint32_t len, void xNetworkFrameReceived( uint32_t len,
uint8_t const * const frame ) uint8_t const * const frame )
{ {
bool pktSuccess, pktLost; bool pktSuccess, pktLost;
NetworkBufferDescriptor_t * pxNetworkBuffer = NULL; NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
pktSuccess = pktLost = false; pktSuccess = pktLost = false;
while( true ) while( true )
{ {
if( eConsiderFrameForProcessing( frame ) != eProcessBuffer ) if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )
{ {
break; break;
} }
/* get the network descriptor (no data buffer) to hold this packet */ /* get the network descriptor (no data buffer) to hold this packet */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 ); pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );
if( pxNetworkBuffer == NULL ) if( pxNetworkBuffer == NULL )
{ {
pktLost = true; pktLost = true;
break; break;
} }
/* Set the actual packet length, in case a larger buffer was /* Set the actual packet length, in case a larger buffer was
returned. */ returned. */
pxNetworkBuffer->xDataLength = len; pxNetworkBuffer->xDataLength = len;
/* Copy the packet. */ /* Copy the packet. */
memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len ); memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );
/* Send the data to the TCP/IP stack. */ /* Send the data to the TCP/IP stack. */
xRxEvent.pvData = ( void * ) pxNetworkBuffer; xRxEvent.pvData = ( void * ) pxNetworkBuffer;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{ /* failed */ { /* failed */
pktLost = true; pktLost = true;
} }
else else
{ /* success */ { /* success */
pktSuccess = true; pktSuccess = true;
iptraceNETWORK_INTERFACE_RECEIVE(); iptraceNETWORK_INTERFACE_RECEIVE();
} }
break; break;
} }
if( !pktSuccess ) if( !pktSuccess )
{ /* smth went wrong; nothing sent to the */ { /* smth went wrong; nothing sent to the */
if( pxNetworkBuffer != NULL ) if( pxNetworkBuffer != NULL )
{ {
pxNetworkBuffer->pucEthernetBuffer = 0; pxNetworkBuffer->pucEthernetBuffer = 0;
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
} }
if( pktLost ) if( pktLost )
{ {
iptraceETHERNET_RX_EVENT_LOST(); iptraceETHERNET_RX_EVENT_LOST();
} }
} }
} }
#endif /* #ifndef PIC32_USE_ETHERNET */ #endif /* #ifndef PIC32_USE_ETHERNET */

View file

@ -1,6 +1,6 @@
Documentation and download available at http://www.FreeRTOS.org/ Documentation and download available at http://www.FreeRTOS.org/
Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released TBD Changes between FreeRTOS V10.2.1 and FreeRTOS V10.3.0 released February 7 2020
See http://www.FreeRTOS.org/FreeRTOS-V10.3.x.html See http://www.FreeRTOS.org/FreeRTOS-V10.3.x.html

View file

@ -43,10 +43,10 @@ extern "C" {
* MACROS AND DEFINITIONS * MACROS AND DEFINITIONS
*----------------------------------------------------------*/ *----------------------------------------------------------*/
#define tskKERNEL_VERSION_NUMBER "V10.2.1" #define tskKERNEL_VERSION_NUMBER "V10.3.0"
#define tskKERNEL_VERSION_MAJOR 10 #define tskKERNEL_VERSION_MAJOR 10
#define tskKERNEL_VERSION_MINOR 2 #define tskKERNEL_VERSION_MINOR 3
#define tskKERNEL_VERSION_BUILD 1 #define tskKERNEL_VERSION_BUILD 0
/* MPU region parameters passed in ulParameters /* MPU region parameters passed in ulParameters
* of MemoryRegion_t struct. */ * of MemoryRegion_t struct. */

View file

@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://www.freertos.org/FreeRTOS-V10.3.x.html