forked from xuos/xiuos
				
			
						commit
						a03b4bd13d
					
				| 
						 | 
					@ -70,6 +70,13 @@ int MountSDCard(void)
 | 
				
			||||||
#include <connect_sdio.h>
 | 
					#include <connect_sdio.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BSP_USING_SEMC
 | 
				
			||||||
 | 
					extern status_t BOARD_InitSEMC(void);
 | 
				
			||||||
 | 
					#ifdef BSP_USING_EXTSRAM
 | 
				
			||||||
 | 
					extern int ExtSramInit(void);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void BOARD_SD_Pin_Config(uint32_t speed, uint32_t strength)
 | 
					void BOARD_SD_Pin_Config(uint32_t speed, uint32_t strength)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD,
 | 
					    IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B0_00_USDHC1_CMD,
 | 
				
			||||||
| 
						 | 
					@ -302,6 +309,22 @@ void InitBoardHardware()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    InitBoardMemory((void *)HEAP_BEGIN, (void *)HEAP_END);
 | 
					    InitBoardMemory((void *)HEAP_BEGIN, (void *)HEAP_END);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BSP_USING_SEMC
 | 
				
			||||||
 | 
					    CLOCK_InitSysPfd(kCLOCK_Pfd2, 29);
 | 
				
			||||||
 | 
					    /* Set semc clock to 163.86 MHz */
 | 
				
			||||||
 | 
					    CLOCK_SetMux(kCLOCK_SemcMux, 1);
 | 
				
			||||||
 | 
					    CLOCK_SetDiv(kCLOCK_SemcDiv, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (BOARD_InitSEMC() != kStatus_Success) {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC Init Failed\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#ifdef MEM_EXTERN_SRAM
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        ExtSramInit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef BSP_USING_LPUART
 | 
					#ifdef BSP_USING_LPUART
 | 
				
			||||||
    Imxrt1052HwUartInit();
 | 
					    Imxrt1052HwUartInit();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,18 @@ menuconfig BSP_USING_GPIO
 | 
				
			||||||
        source "$BSP_DIR/third_party_driver/gpio/Kconfig"
 | 
					        source "$BSP_DIR/third_party_driver/gpio/Kconfig"
 | 
				
			||||||
    endif
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					menuconfig BSP_USING_LWIP
 | 
				
			||||||
 | 
					    bool "Using LwIP device"
 | 
				
			||||||
 | 
					    default n
 | 
				
			||||||
 | 
					    select RESOURCES_LWIP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					menuconfig BSP_USING_SEMC
 | 
				
			||||||
 | 
					    bool "Using SEMC device"
 | 
				
			||||||
 | 
					    default n
 | 
				
			||||||
 | 
					    if BSP_USING_SEMC
 | 
				
			||||||
 | 
					        source "$BSP_DIR/third_party_driver/semc/Kconfig"
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
menuconfig BSP_USING_SDIO
 | 
					menuconfig BSP_USING_SDIO
 | 
				
			||||||
    bool "Using SD card device"
 | 
					    bool "Using SD card device"
 | 
				
			||||||
    default n
 | 
					    default n
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,13 @@
 | 
				
			||||||
SRC_DIR := common gpio
 | 
					SRC_DIR := common gpio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_BSP_USING_LWIP),y)
 | 
				
			||||||
 | 
					  SRC_DIR += ethernet
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_BSP_USING_SEMC),y)
 | 
				
			||||||
 | 
					  SRC_DIR += semc
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(CONFIG_BSP_USING_LPUART),y)
 | 
					ifeq ($(CONFIG_BSP_USING_LPUART),y)
 | 
				
			||||||
  SRC_DIR += uart
 | 
					  SRC_DIR += uart
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c
 | 
				
			||||||
 | 
					SRC_DIR := lan8720
 | 
				
			||||||
 | 
					include $(KERNEL_ROOT)/compiler.mk
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,313 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					 *    and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. The name of the author may not be used to endorse or promote products
 | 
				
			||||||
 | 
					 *    derived from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 | 
				
			||||||
 | 
					 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
				
			||||||
 | 
					 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 | 
				
			||||||
 | 
					 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 | 
				
			||||||
 | 
					 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 | 
				
			||||||
 | 
					 * OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of the lwIP TCP/IP stack.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Adam Dunkels <adam@sics.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2019 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file enet_ethernetif.c
 | 
				
			||||||
 | 
					 * @brief ethernet drivers
 | 
				
			||||||
 | 
					 * @version 1.0
 | 
				
			||||||
 | 
					 * @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					 * @date 2021.11.11
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lwip/opt.h"
 | 
				
			||||||
 | 
					#include "lwip/def.h"
 | 
				
			||||||
 | 
					#include "lwip/mem.h"
 | 
				
			||||||
 | 
					#include "lwip/pbuf.h"
 | 
				
			||||||
 | 
					#include "lwip/stats.h"
 | 
				
			||||||
 | 
					#include "lwip/snmp.h"
 | 
				
			||||||
 | 
					#include "lwip/ethip6.h"
 | 
				
			||||||
 | 
					#include "netif/etharp.h"
 | 
				
			||||||
 | 
					#include "netif/ppp/pppoe.h"
 | 
				
			||||||
 | 
					#include "lwip/igmp.h"
 | 
				
			||||||
 | 
					#include "lwip/mld6.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					//#include "FreeRTOS.h"
 | 
				
			||||||
 | 
					//#include "event_groups.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "netif/ethernet.h"
 | 
				
			||||||
 | 
					#include "enet_ethernetif.h"
 | 
				
			||||||
 | 
					#include "enet_ethernetif_priv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_enet.h"
 | 
				
			||||||
 | 
					#include "fsl_phy.h"
 | 
				
			||||||
 | 
					#include "fsl_gpio.h"
 | 
				
			||||||
 | 
					#include "fsl_iomuxc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sys_arch.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Code
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void enet_delay(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    volatile uint32_t i = 0;
 | 
				
			||||||
 | 
					    for (i = 0; i < 1000000; ++i)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        __asm("NOP"); /* delay */
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Time_Update_LwIP(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_clk_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const clock_enet_pll_config_t config = {.enableClkOutput = true, .enableClkOutput25M = false, .loopDivider = 1};
 | 
				
			||||||
 | 
					    CLOCK_InitEnetPll(&config);
 | 
				
			||||||
 | 
					    SysTick_Config(USEC_TO_COUNT(1000U, CLOCK_GetFreq(kCLOCK_CoreSysClk)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_gpio_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GPIO_PinInit(GPIO1, 3, &gpio_config);
 | 
				
			||||||
 | 
					    GPIO_PinInit(GPIO1, 10, &gpio_config);
 | 
				
			||||||
 | 
					    /* pull up the ENET_INT before RESET. */
 | 
				
			||||||
 | 
					    GPIO_WritePinOutput(GPIO1, 10, 1);
 | 
				
			||||||
 | 
					    GPIO_WritePinOutput(GPIO1, 3, 0);
 | 
				
			||||||
 | 
					    enet_delay();
 | 
				
			||||||
 | 
					    GPIO_WritePinOutput(GPIO1, 3, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ETH_BSP_Config(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static int flag = 0;
 | 
				
			||||||
 | 
					    if(flag == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ethernetif_clk_init();
 | 
				
			||||||
 | 
					        ethernetif_gpio_init();
 | 
				
			||||||
 | 
					        flag = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_phy_init(struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                         const ethernetif_config_t *ethernetifConfig,
 | 
				
			||||||
 | 
					                         enet_config_t *config)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t sysClock;
 | 
				
			||||||
 | 
					    status_t status;
 | 
				
			||||||
 | 
					    bool link = false;
 | 
				
			||||||
 | 
					    uint32_t count = 0;
 | 
				
			||||||
 | 
					    phy_speed_t speed;
 | 
				
			||||||
 | 
					    phy_duplex_t duplex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_PLATFORM_DIAG(("Initializing PHY...\r\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((count < ENET_ATONEGOTIATION_TIMEOUT) && (!link))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        status = PHY_Init(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, sysClock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (kStatus_Success == status)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            PHY_GetLinkStatus(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, &link);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (kStatus_PHY_AutoNegotiateFail == status)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LWIP_PLATFORM_DIAG(("PHY Auto-negotiation failed. Please check the ENET cable connection and link partner setting."));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LWIP_ASSERT("\r\nCannot initialize PHY.\r\n", 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        count++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (link)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Get the actual PHY link speed. */
 | 
				
			||||||
 | 
					        PHY_GetLinkSpeedDuplex(*ethernetif_enet_ptr(ethernetif), ethernetifConfig->phyAddress, &speed, &duplex);
 | 
				
			||||||
 | 
					        /* Change the MII speed and duplex for actual link status. */
 | 
				
			||||||
 | 
					        config->miiSpeed = (enet_mii_speed_t)speed;
 | 
				
			||||||
 | 
					        config->miiDuplex = (enet_mii_duplex_t)duplex;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#if 0 /* Disable assert. If initial auto-negation is timeout, \ \
 | 
				
			||||||
 | 
					         the ENET is set to default (100Mbs and full-duplex). */
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        LWIP_ASSERT("\r\nGiving up PHY initialization. Please check the ENET cable connection and link partner setting and reset the board.\r\n", 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This function should be called when a packet is ready to be read
 | 
				
			||||||
 | 
					 * from the interface. It uses the function ethernetif_linkinput() that
 | 
				
			||||||
 | 
					 * should handle the actual reception of bytes from the network
 | 
				
			||||||
 | 
					 * interface. Then the type of the received packet is determined and
 | 
				
			||||||
 | 
					 * the appropriate input function is called.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_input(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct pbuf *p;
 | 
				
			||||||
 | 
					    err_t ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("netif != NULL", (netif != NULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* move received packet into a new pbuf */
 | 
				
			||||||
 | 
					    while ((p = ethernetif_linkinput(netif)) != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* pass all packets to ethernet_input, which decides what packets it supports */
 | 
				
			||||||
 | 
					        if ((ret = netif->input(p, netif)) != ERR_OK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
 | 
				
			||||||
 | 
					            lw_print("lw: [%s] ret %d p %p\n", __func__, ret, p);
 | 
				
			||||||
 | 
					            pbuf_free(p);
 | 
				
			||||||
 | 
					            p = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ENET_Type *ethernetif_get_enet_base(const uint8_t enetIdx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ENET_Type* enets[] = ENET_BASE_PTRS;
 | 
				
			||||||
 | 
					    int arrayIdx;
 | 
				
			||||||
 | 
					    int enetCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (arrayIdx = 0, enetCount = 0; arrayIdx < ARRAY_SIZE(enets); arrayIdx++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (enets[arrayIdx] != 0U)    /* process only defined positions */
 | 
				
			||||||
 | 
					        {                             /* (some SOC headers count ENETs from 1 instead of 0) */
 | 
				
			||||||
 | 
					            if (enetCount == enetIdx)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return enets[arrayIdx];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            enetCount++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                      const uint8_t enetIdx,
 | 
				
			||||||
 | 
					                      const ethernetif_config_t *ethernetifConfig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    LWIP_ASSERT("netif != NULL", (netif != NULL));
 | 
				
			||||||
 | 
					    LWIP_ASSERT("ethernetifConfig != NULL", (ethernetifConfig != NULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_NETIF_HOSTNAME
 | 
				
			||||||
 | 
					    /* Initialize interface hostname */
 | 
				
			||||||
 | 
					    netif->hostname = "lwip";
 | 
				
			||||||
 | 
					#endif /* LWIP_NETIF_HOSTNAME */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Initialize the snmp variables and counters inside the struct netif.
 | 
				
			||||||
 | 
					     * The last argument should be replaced with your link speed, in units
 | 
				
			||||||
 | 
					     * of bits per second.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    netif->state = ethernetif;
 | 
				
			||||||
 | 
					    netif->name[0] = IFNAME0;
 | 
				
			||||||
 | 
					    netif->name[1] = IFNAME1;
 | 
				
			||||||
 | 
					/* We directly use etharp_output() here to save a function call.
 | 
				
			||||||
 | 
					 * You can instead declare your own function an call etharp_output()
 | 
				
			||||||
 | 
					 * from it if you have to do some checks before sending (e.g. if link
 | 
				
			||||||
 | 
					 * is available...) */
 | 
				
			||||||
 | 
					#if LWIP_IPV4
 | 
				
			||||||
 | 
					    netif->output = etharp_output;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if LWIP_IPV6
 | 
				
			||||||
 | 
					    netif->output_ip6 = ethip6_output;
 | 
				
			||||||
 | 
					#endif /* LWIP_IPV6 */
 | 
				
			||||||
 | 
					    netif->linkoutput = ethernetif_linkoutput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV4 && LWIP_IGMP
 | 
				
			||||||
 | 
					    netif_set_igmp_mac_filter(netif, ethernetif_igmp_mac_filter);
 | 
				
			||||||
 | 
					    netif->flags |= NETIF_FLAG_IGMP;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV6_MLD
 | 
				
			||||||
 | 
					    netif_set_mld_mac_filter(netif, ethernetif_mld_mac_filter);
 | 
				
			||||||
 | 
					    netif->flags |= NETIF_FLAG_MLD6;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Init ethernetif parameters.*/
 | 
				
			||||||
 | 
					    *ethernetif_enet_ptr(ethernetif) = ethernetif_get_enet_base(enetIdx);
 | 
				
			||||||
 | 
					    LWIP_ASSERT("*ethernetif_enet_ptr(ethernetif) != NULL", (*ethernetif_enet_ptr(ethernetif) != NULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* set MAC hardware address length */
 | 
				
			||||||
 | 
					    netif->hwaddr_len = ETH_HWADDR_LEN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* set MAC hardware address */
 | 
				
			||||||
 | 
					    memcpy(netif->hwaddr, ethernetifConfig->macAddress, NETIF_MAX_HWADDR_LEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* maximum transfer unit */
 | 
				
			||||||
 | 
					    netif->mtu = 1500; /* TODO: define a config */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* device capabilities */
 | 
				
			||||||
 | 
					    /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
 | 
				
			||||||
 | 
					    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* ENET driver initialization.*/
 | 
				
			||||||
 | 
					    ethernetif_enet_init(netif, ethernetif, ethernetifConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV6_MLD
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * For hardware/netifs that implement MAC filtering.
 | 
				
			||||||
 | 
					     * All-nodes link-local is handled by default, so we must let the hardware know
 | 
				
			||||||
 | 
					     * to allow multicast packets in.
 | 
				
			||||||
 | 
					     * Should set mld_mac_filter previously. */
 | 
				
			||||||
 | 
					    if (netif->mld_mac_filter != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ip6_addr_t ip6_allnodes_ll;
 | 
				
			||||||
 | 
					        ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
 | 
				
			||||||
 | 
					        netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ERR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,674 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					 *    and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. The name of the author may not be used to endorse or promote products
 | 
				
			||||||
 | 
					 *    derived from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 | 
				
			||||||
 | 
					 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
				
			||||||
 | 
					 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 | 
				
			||||||
 | 
					 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 | 
				
			||||||
 | 
					 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 | 
				
			||||||
 | 
					 * OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of the lwIP TCP/IP stack.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Adam Dunkels <adam@sics.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2019 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file enet_ethernetif_kinetis.c
 | 
				
			||||||
 | 
					 * @brief ethernet drivers
 | 
				
			||||||
 | 
					 * @version 1.0
 | 
				
			||||||
 | 
					 * @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					 * @date 2021.11.11
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sys_arch.h"
 | 
				
			||||||
 | 
					#include "lwip/opt.h"
 | 
				
			||||||
 | 
					#include "lwip/def.h"
 | 
				
			||||||
 | 
					#include "lwip/mem.h"
 | 
				
			||||||
 | 
					#include "lwip/pbuf.h"
 | 
				
			||||||
 | 
					#include "lwip/stats.h"
 | 
				
			||||||
 | 
					#include "lwip/snmp.h"
 | 
				
			||||||
 | 
					#include "lwip/ethip6.h"
 | 
				
			||||||
 | 
					#include "netif/etharp.h"
 | 
				
			||||||
 | 
					#include "netif/ppp/pppoe.h"
 | 
				
			||||||
 | 
					#include "lwip/igmp.h"
 | 
				
			||||||
 | 
					#include "lwip/mld6.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					#define USE_RTOS 1
 | 
				
			||||||
 | 
					#define FSL_RTOS_FREE_RTOS
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					#include "xs_sem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#include "FreeRTOS.h"
 | 
				
			||||||
 | 
					#include "event_groups.h"
 | 
				
			||||||
 | 
					#include "list.h"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef uint32_t     TickType_t;
 | 
				
			||||||
 | 
					#define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef TickType_t       EventBits_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef long             BaseType_t;
 | 
				
			||||||
 | 
					typedef unsigned long    UBaseType_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define portBASE_TYPE    long
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define pdFALSE          ( ( BaseType_t ) 0 )
 | 
				
			||||||
 | 
					#define pdTRUE           ( ( BaseType_t ) 1 )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define pdPASS           ( pdTRUE )
 | 
				
			||||||
 | 
					#define pdFAIL           ( pdFALSE )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					typedef struct EventGroupDef_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    EventBits_t uxEventBits;
 | 
				
			||||||
 | 
					    List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #if ( configUSE_TRACE_FACILITY == 1 )
 | 
				
			||||||
 | 
					        UBaseType_t uxEventGroupNumber;
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
 | 
				
			||||||
 | 
					        uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
 | 
					} EventGroup_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct EventGroupDef_t;
 | 
				
			||||||
 | 
					typedef struct EventGroupDef_t   * EventGroupHandle_t;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "enet_ethernetif.h"
 | 
				
			||||||
 | 
					#include "enet_ethernetif_priv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_enet.h"
 | 
				
			||||||
 | 
					#include "fsl_phy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sys_arch.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Helper struct to hold private data used to operate your ethernet interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ethernetif
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ENET_Type *base;
 | 
				
			||||||
 | 
					#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0)) || \
 | 
				
			||||||
 | 
					    (USE_RTOS && defined(FSL_RTOS_FREE_RTOS))
 | 
				
			||||||
 | 
					    enet_handle_t handle;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					    int enetSemaphore;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    EventGroupHandle_t enetTransmitAccessEvent;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    EventBits_t txFlag;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t *RxBuffDescrip;
 | 
				
			||||||
 | 
					    enet_tx_bd_struct_t *TxBuffDescrip;
 | 
				
			||||||
 | 
					    rx_buffer_t *RxDataBuff;
 | 
				
			||||||
 | 
					    tx_buffer_t *TxDataBuff;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Code
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32 lwip_obtain_semaphore(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    return (KSemaphoreObtain(ethernetif->enetSemaphore, WAITING_FOREVER) == EOK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if FSL_FEATURE_ENET_QUEUE > 1
 | 
				
			||||||
 | 
					static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, uint32_t ringId, enet_event_t event, void *param)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param)
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_ENET_QUEUE */
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct netif *netif = (struct netif *)param;
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    BaseType_t xResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (event)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case kENET_RxEvent:
 | 
				
			||||||
 | 
					            ethernetif_input(netif);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case kENET_TxEvent:
 | 
				
			||||||
 | 
					#ifndef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            portBASE_TYPE taskToWake = pdFALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __CA7_REV
 | 
				
			||||||
 | 
					            if (SystemGetIRQNestingLevel())
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            if (__get_IPSR())
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                xResult = xEventGroupSetBitsFromISR(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, &taskToWake);
 | 
				
			||||||
 | 
					                if ((pdPASS == xResult) && (pdTRUE == taskToWake))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    portYIELD_FROM_ISR(taskToWake);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                xEventGroupSetBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KSemaphoreAbandon(ethernetif->enetSemaphore);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV4 && LWIP_IGMP
 | 
				
			||||||
 | 
					err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
 | 
				
			||||||
 | 
					                                 enum netif_mac_filter_action action)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    uint8_t multicastMacAddr[6];
 | 
				
			||||||
 | 
					    err_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    multicastMacAddr[0] = 0x01U;
 | 
				
			||||||
 | 
					    multicastMacAddr[1] = 0x00U;
 | 
				
			||||||
 | 
					    multicastMacAddr[2] = 0x5EU;
 | 
				
			||||||
 | 
					    multicastMacAddr[3] = (group->addr >> 8) & 0x7FU;
 | 
				
			||||||
 | 
					    multicastMacAddr[4] = (group->addr >> 16) & 0xFFU;
 | 
				
			||||||
 | 
					    multicastMacAddr[5] = (group->addr >> 24) & 0xFFU;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (action)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case IGMP_ADD_MAC_FILTER:
 | 
				
			||||||
 | 
					            /* Adds the ENET device to a multicast group.*/
 | 
				
			||||||
 | 
					            ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case IGMP_DEL_MAC_FILTER:
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * Moves the ENET device from a multicast group.
 | 
				
			||||||
 | 
					             * Since the ENET_LeaveMulticastGroup() could filter out also other
 | 
				
			||||||
 | 
					             * group addresses having the same hash, the call is commented out.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            result = ERR_IF;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV6_MLD
 | 
				
			||||||
 | 
					err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
 | 
				
			||||||
 | 
					                                enum netif_mac_filter_action action)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    uint8_t multicastMacAddr[6];
 | 
				
			||||||
 | 
					    err_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    multicastMacAddr[0] = 0x33U;
 | 
				
			||||||
 | 
					    multicastMacAddr[1] = 0x33U;
 | 
				
			||||||
 | 
					    multicastMacAddr[2] = (group->addr[3]) & 0xFFU;
 | 
				
			||||||
 | 
					    multicastMacAddr[3] = (group->addr[3] >> 8) & 0xFFU;
 | 
				
			||||||
 | 
					    multicastMacAddr[4] = (group->addr[3] >> 16) & 0xFFU;
 | 
				
			||||||
 | 
					    multicastMacAddr[5] = (group->addr[3] >> 24) & 0xFFU;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (action)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case NETIF_ADD_MAC_FILTER:
 | 
				
			||||||
 | 
					            /* Adds the ENET device to a multicast group.*/
 | 
				
			||||||
 | 
					            ENET_AddMulticastGroup(ethernetif->base, multicastMacAddr);
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case NETIF_DEL_MAC_FILTER:
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * Moves the ENET device from a multicast group.
 | 
				
			||||||
 | 
					             * Since the ENET_LeaveMulticastGroup() could filter out also other
 | 
				
			||||||
 | 
					             * group addresses having the same hash, the call is commented out.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            /* ENET_LeaveMulticastGroup(ethernetif->base, multicastMacAddr); */
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            result = ERR_IF;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Initializes ENET driver.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                          const ethernetif_config_t *ethernetifConfig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    enet_config_t config;
 | 
				
			||||||
 | 
					    uint32_t sysClock;
 | 
				
			||||||
 | 
					    enet_buffer_config_t buffCfg[ENET_RING_NUM];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* prepare the buffer configuration. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBdNumber = ENET_RXBD_NUM;                      /* Receive buffer descriptor number. */
 | 
				
			||||||
 | 
					    buffCfg[0].txBdNumber = ENET_TXBD_NUM;                      /* Transmit buffer descriptor number. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t);           /* Aligned receive data buffer size. */
 | 
				
			||||||
 | 
					    buffCfg[0].txBuffSizeAlign = sizeof(tx_buffer_t);           /* Aligned transmit data buffer size. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBdStartAddrAlign = &(ethernetif->RxBuffDescrip[0]); /* Aligned receive buffer descriptor start address. */
 | 
				
			||||||
 | 
					    buffCfg[0].txBdStartAddrAlign = &(ethernetif->TxBuffDescrip[0]); /* Aligned transmit buffer descriptor start address. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBufferAlign = &(ethernetif->RxDataBuff[0][0]); /* Receive data buffer start address. */
 | 
				
			||||||
 | 
					    buffCfg[0].txBufferAlign = &(ethernetif->TxDataBuff[0][0]); /* Transmit data buffer start address. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_GetDefaultConfig(&config);
 | 
				
			||||||
 | 
					    config.ringNum = ENET_RING_NUM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_phy_init(ethernetif, ethernetifConfig, &config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					    uint32_t instance;
 | 
				
			||||||
 | 
					    static ENET_Type *const enetBases[] = ENET_BASE_PTRS;
 | 
				
			||||||
 | 
					    static const IRQn_Type enetTxIrqId[] = ENET_Transmit_IRQS;
 | 
				
			||||||
 | 
					    /*! @brief Pointers to enet receive IRQ number for each instance. */
 | 
				
			||||||
 | 
					    static const IRQn_Type enetRxIrqId[] = ENET_Receive_IRQS;
 | 
				
			||||||
 | 
					#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
 | 
				
			||||||
 | 
					    /*! @brief Pointers to enet timestamp IRQ number for each instance. */
 | 
				
			||||||
 | 
					    static const IRQn_Type enetTsIrqId[] = ENET_1588_Timer_IRQS;
 | 
				
			||||||
 | 
					#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Create the Event for transmit busy release trigger. */
 | 
				
			||||||
 | 
					#ifdef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					    if(ethernetif->enetSemaphore < 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ethernetif->enetSemaphore = KSemaphoreCreate(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    ethernetif->txFlag = 0x1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    config.interrupt |= kENET_RxFrameInterrupt | kENET_TxFrameInterrupt | kENET_TxBufferInterrupt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (instance = 0; instance < ARRAY_SIZE(enetBases); instance++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (enetBases[instance] == ethernetif->base)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					#ifdef __CA7_REV
 | 
				
			||||||
 | 
					            GIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY);
 | 
				
			||||||
 | 
					            GIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY);
 | 
				
			||||||
 | 
					#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
 | 
				
			||||||
 | 
					            GIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY);
 | 
				
			||||||
 | 
					#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            NVIC_SetPriority(enetRxIrqId[instance], ENET_PRIORITY);
 | 
				
			||||||
 | 
					            NVIC_SetPriority(enetTxIrqId[instance], ENET_PRIORITY);
 | 
				
			||||||
 | 
					#if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE
 | 
				
			||||||
 | 
					            NVIC_SetPriority(enetTsIrqId[instance], ENET_1588_PRIORITY);
 | 
				
			||||||
 | 
					#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */
 | 
				
			||||||
 | 
					#endif /* __CA7_REV */
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("Input Ethernet base error!", (instance != ARRAY_SIZE(enetBases)));
 | 
				
			||||||
 | 
					#endif /* USE_RTOS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initialize the ENET module.*/
 | 
				
			||||||
 | 
					    ENET_Init(ethernetif->base, ðernetif->handle, &config, &buffCfg[0], netif->hwaddr, sysClock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					    ENET_SetCallback(ðernetif->handle, ethernet_callback, netif);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_ActiveRead(ethernetif->base);
 | 
				
			||||||
 | 
					//    low_level_init();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return &(ethernetif->base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns next buffer for TX.
 | 
				
			||||||
 | 
					 * Can wait if no buffer available.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static unsigned char *enet_get_tx_buffer(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static unsigned char ucBuffer[ENET_FRAME_MAX_FRAMELEN];
 | 
				
			||||||
 | 
					    return ucBuffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Sends frame via ENET.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static err_t enet_send_frame(struct ethernetif *ethernetif, unsigned char *data, const uint32_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if USE_RTOS && defined(FSL_RTOS_FREE_RTOS)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        status_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        lw_print("lw: [%s] len %d\n", __func__, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (result == kStatus_ENET_TxFrameBusy)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					#ifdef FSL_RTOS_XIUOS
 | 
				
			||||||
 | 
					                KSemaphoreObtain(ethernetif->enetSemaphore, portMAX_DELAY);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					                xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent, ethernetif->txFlag, pdTRUE, (BaseType_t) false,
 | 
				
			||||||
 | 
					                                    portMAX_DELAY);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } while (result == kStatus_ENET_TxFrameBusy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ERR_OK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint32_t counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (counter = ENET_TIMEOUT; counter != 0U; counter--)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (ENET_SendFrame(ethernetif->base, ðernetif->handle, data, length) != kStatus_ENET_TxFrameBusy)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ERR_OK;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return ERR_TIMEOUT;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct pbuf *ethernetif_linkinput(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    struct pbuf *p = NULL;
 | 
				
			||||||
 | 
					    struct pbuf *q;
 | 
				
			||||||
 | 
					    uint32_t len;
 | 
				
			||||||
 | 
					    status_t status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Obtain the size of the packet and put it into the "len"
 | 
				
			||||||
 | 
					       variable. */
 | 
				
			||||||
 | 
					    status = ENET_GetRxFrameSize(ðernetif->handle, &len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (kStatus_ENET_RxFrameEmpty != status)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Call ENET_ReadFrame when there is a received frame. */
 | 
				
			||||||
 | 
					        if (len != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					            len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* We allocate a pbuf chain of pbufs from the pool. */
 | 
				
			||||||
 | 
					            p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (p != NULL)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					                pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                if (p->next == 0) /* One-chain buffer.*/
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ENET_ReadFrame(ethernetif->base, ðernetif->handle, p->payload, p->len);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else    /* Multi-chain buffer.*/
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    uint8_t data_tmp[ENET_FRAME_MAX_FRAMELEN];
 | 
				
			||||||
 | 
					                    uint32_t data_tmp_len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    ENET_ReadFrame(ethernetif->base, ðernetif->handle, data_tmp, p->tot_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    /* We iterate over the pbuf chain until we have read the entire
 | 
				
			||||||
 | 
					                    * packet into the pbuf. */
 | 
				
			||||||
 | 
					                    for (q = p; (q != NULL) && ((data_tmp_len + q->len) <= sizeof(data_tmp)); q = q->next)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        /* Read enough bytes to fill this pbuf in the chain. The
 | 
				
			||||||
 | 
					                        * available data in the pbuf is given by the q->len
 | 
				
			||||||
 | 
					                        * variable. */
 | 
				
			||||||
 | 
					                        memcpy(q->payload,  &data_tmp[data_tmp_len], q->len);
 | 
				
			||||||
 | 
					                        data_tmp_len += q->len;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
 | 
				
			||||||
 | 
					                if (((u8_t *)p->payload)[0] & 1)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    /* broadcast or multicast packet*/
 | 
				
			||||||
 | 
					                    MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    /* unicast packet*/
 | 
				
			||||||
 | 
					                    MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					                pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LINK_STATS_INC(link.recv);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                /* drop packet*/
 | 
				
			||||||
 | 
					                ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: Fail to allocate new memory space\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LINK_STATS_INC(link.memerr);
 | 
				
			||||||
 | 
					                LINK_STATS_INC(link.drop);
 | 
				
			||||||
 | 
					                MIB2_STATS_NETIF_INC(netif, ifindiscards);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* Update the received buffer when error happened. */
 | 
				
			||||||
 | 
					            if (status == kStatus_ENET_RxFrameError)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					#if 0 && defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 0) /* Error statisctics */
 | 
				
			||||||
 | 
					                enet_data_error_stats_t eErrStatic;
 | 
				
			||||||
 | 
					                /* Get the error information of the received g_frame. */
 | 
				
			||||||
 | 
					                ENET_GetRxErrBeforeReadFrame(ðernetif->handle, &eErrStatic);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					                /* Update the receive buffer. */
 | 
				
			||||||
 | 
					                ENET_ReadFrame(ethernetif->base, ðernetif->handle, NULL, 0U);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                LINK_STATS_INC(link.drop);
 | 
				
			||||||
 | 
					                MIB2_STATS_NETIF_INC(netif, ifindiscards);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    err_t result;
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    struct pbuf *q;
 | 
				
			||||||
 | 
					    unsigned char *pucBuffer;
 | 
				
			||||||
 | 
					    unsigned char *pucChar;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("Output packet buffer empty", p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pucBuffer = enet_get_tx_buffer(ethernetif);
 | 
				
			||||||
 | 
					    if (pucBuffer == NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ERR_BUF;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Initiate transfer. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					    pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (p->len == p->tot_len)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* No pbuf chain, don't have to copy -> faster. */
 | 
				
			||||||
 | 
					        pucBuffer = (unsigned char *)p->payload;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* pbuf chain, copy into contiguous ucBuffer. */
 | 
				
			||||||
 | 
					        if (p->tot_len > ENET_FRAME_MAX_FRAMELEN)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ERR_BUF;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            pucChar = pucBuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (q = p; q != NULL; q = q->next)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                /* Send the data from the pbuf to the interface, one pbuf at a
 | 
				
			||||||
 | 
					                time. The size of the data in each pbuf is kept in the ->len
 | 
				
			||||||
 | 
					                variable. */
 | 
				
			||||||
 | 
					                /* send data from(q->payload, q->len); */
 | 
				
			||||||
 | 
					                memcpy(pucChar, q->payload, q->len);
 | 
				
			||||||
 | 
					                pucChar += q->len;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Send frame. */
 | 
				
			||||||
 | 
					    result = enet_send_frame(ethernetif, pucBuffer, p->tot_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
 | 
				
			||||||
 | 
					    if (((u8_t *)p->payload)[0] & 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* broadcast or multicast packet*/
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* unicast packet */
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					/* increase ifoutdiscards or ifouterrors on error */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					    pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LINK_STATS_INC(link.xmit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Should be called at the beginning of the program to set up the
 | 
				
			||||||
 | 
					 * first network interface. It calls the function ethernetif_init() to do the
 | 
				
			||||||
 | 
					 * actual setup of the hardware.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @return ERR_OK if the loopif is initialized
 | 
				
			||||||
 | 
					 *         ERR_MEM if private data couldn't be allocated
 | 
				
			||||||
 | 
					 *         any other err_t on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif0_init(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static struct ethernetif ethernetif_0;
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static tx_buffer_t txDataBuff_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]);
 | 
				
			||||||
 | 
					    ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]);
 | 
				
			||||||
 | 
					    ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]);
 | 
				
			||||||
 | 
					    ethernetif_0.TxDataBuff = &(txDataBuff_0[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1)
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Should be called at the beginning of the program to set up the
 | 
				
			||||||
 | 
					 * second network interface. It calls the function ethernetif_init() to do the
 | 
				
			||||||
 | 
					 * actual setup of the hardware.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @return ERR_OK if the loopif is initialized
 | 
				
			||||||
 | 
					 *         ERR_MEM if private data couldn't be allocated
 | 
				
			||||||
 | 
					 *         any other err_t on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif1_init(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static struct ethernetif ethernetif_1;
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static tx_buffer_t txDataBuff_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]);
 | 
				
			||||||
 | 
					    ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]);
 | 
				
			||||||
 | 
					    ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]);
 | 
				
			||||||
 | 
					    ethernetif_1.TxDataBuff = &(txDataBuff_1[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
 | 
				
			||||||
							
								
								
									
										960
									
								
								Ubiquitous/XiZi/board/xidatong/third_party_driver/ethernet/enet_ethernetif_lpc.c
								
								
								
								
									Executable file
								
							
							
						
						
									
										960
									
								
								Ubiquitous/XiZi/board/xidatong/third_party_driver/ethernet/enet_ethernetif_lpc.c
								
								
								
								
									Executable file
								
							| 
						 | 
					@ -0,0 +1,960 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					 *    and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. The name of the author may not be used to endorse or promote products
 | 
				
			||||||
 | 
					 *    derived from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 | 
				
			||||||
 | 
					 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
				
			||||||
 | 
					 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 | 
				
			||||||
 | 
					 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 | 
				
			||||||
 | 
					 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 | 
				
			||||||
 | 
					 * OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of the lwIP TCP/IP stack.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Adam Dunkels <adam@sics.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2019 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file enet_ethernetif_lpc.c
 | 
				
			||||||
 | 
					 * @brief ethernet drivers
 | 
				
			||||||
 | 
					 * @version 1.0
 | 
				
			||||||
 | 
					 * @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					 * @date 2021.11.11
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lwip/opt.h"
 | 
				
			||||||
 | 
					#include "lwip/def.h"
 | 
				
			||||||
 | 
					#include "lwip/mem.h"
 | 
				
			||||||
 | 
					#include "lwip/pbuf.h"
 | 
				
			||||||
 | 
					#include "lwip/stats.h"
 | 
				
			||||||
 | 
					#include "lwip/snmp.h"
 | 
				
			||||||
 | 
					#include "lwip/sys.h"
 | 
				
			||||||
 | 
					#include "lwip/ethip6.h"
 | 
				
			||||||
 | 
					#include "netif/etharp.h"
 | 
				
			||||||
 | 
					#include "netif/ppp/pppoe.h"
 | 
				
			||||||
 | 
					#include "lwip/igmp.h"
 | 
				
			||||||
 | 
					#include "lwip/mld6.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#if !NO_SYS
 | 
				
			||||||
 | 
					//#include "FreeRTOS.h"
 | 
				
			||||||
 | 
					//#include "event_groups.h"
 | 
				
			||||||
 | 
					//#include "lwip/tcpip.h"
 | 
				
			||||||
 | 
					//#endif /* !NO_SYS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "enet_ethernetif.h"
 | 
				
			||||||
 | 
					#include "enet_ethernetif_priv.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_enet.h"
 | 
				
			||||||
 | 
					#include "fsl_phy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//#if MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT
 | 
				
			||||||
 | 
					///* These two has to match for zero-copy functionality */
 | 
				
			||||||
 | 
					//#error "MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT"
 | 
				
			||||||
 | 
					//#endif /* MEM_ALIGNMENT != FSL_ENET_BUFF_ALIGNMENT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Used to wrap received data in a pbuf to be passed into lwIP
 | 
				
			||||||
 | 
					 *        without copying.
 | 
				
			||||||
 | 
					 * Once last reference is released, RX descriptor will be returned to DMA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct rx_pbuf_wrapper
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct pbuf_custom p;           /*!< Pbuf wrapper. Has to be first. */
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t* rxDesc;    /*!< Descriptor holding the data. */
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif;  /*!< Ethernet interface context data. */
 | 
				
			||||||
 | 
					    volatile bool ownedByLwip;      /*!< If true, descriptor cannot be reused by DMA yet. */
 | 
				
			||||||
 | 
					} rx_pbuf_wrapper_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Helper struct to hold private data used to operate
 | 
				
			||||||
 | 
					 *        your ethernet interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct ethernetif
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ENET_Type *base;
 | 
				
			||||||
 | 
					    enet_handle_t handle;
 | 
				
			||||||
 | 
					#if !NO_SYS
 | 
				
			||||||
 | 
					    EventGroupHandle_t enetTransmitAccessEvent;
 | 
				
			||||||
 | 
					    EventBits_t txFlag;
 | 
				
			||||||
 | 
					#endif /* !NO_SYS */
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t *RxBuffDescrip;
 | 
				
			||||||
 | 
					    enet_tx_bd_struct_t *TxBuffDescrip;
 | 
				
			||||||
 | 
					    rx_buffer_t *RxDataBuff;
 | 
				
			||||||
 | 
					    volatile struct pbuf *txPbufs[ENET_TXBD_NUM];
 | 
				
			||||||
 | 
					    volatile uint8_t txIdx;
 | 
				
			||||||
 | 
					    volatile uint8_t txReleaseIdx;
 | 
				
			||||||
 | 
					    rx_pbuf_wrapper_t rxPbufs[ENET_RXBD_NUM];
 | 
				
			||||||
 | 
					    uint8_t rxIdx;
 | 
				
			||||||
 | 
					    const mem_range_t *non_dma_memory;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ethernetif_tx_release(struct ethernetif *ethernetif);
 | 
				
			||||||
 | 
					static void ethernetif_rx_release(struct pbuf *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Code
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Called from ENET ISR.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void ethernet_callback(ENET_Type *base, enet_handle_t *handle,
 | 
				
			||||||
 | 
					                              enet_event_t event, uint8_t channel, void *param)
 | 
				
			||||||
 | 
					#if NO_SYS
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct netif *netif = (struct netif *)param;
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (event == kENET_TxIntEvent)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ethernetif_tx_release(ethernetif);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct netif *netif = (struct netif *)param;
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    BaseType_t xResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (event)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case kENET_RxIntEvent:
 | 
				
			||||||
 | 
					            ethernetif_input(netif);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case kENET_TxIntEvent:
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            portBASE_TYPE taskToWake = pdFALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ethernetif_tx_release(ethernetif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __CA7_REV
 | 
				
			||||||
 | 
					            if (SystemGetIRQNestingLevel())
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            if (__get_IPSR())
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                xResult = xEventGroupSetBitsFromISR(
 | 
				
			||||||
 | 
					                                            ethernetif->enetTransmitAccessEvent,
 | 
				
			||||||
 | 
					                                            ethernetif->txFlag, &taskToWake);
 | 
				
			||||||
 | 
					                if ((pdPASS == xResult) && (pdTRUE == taskToWake))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    portYIELD_FROM_ISR(taskToWake);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                xEventGroupSetBits(ethernetif->enetTransmitAccessEvent,
 | 
				
			||||||
 | 
					                                   ethernetif->txFlag);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* NO_SYS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV4 && LWIP_IGMP
 | 
				
			||||||
 | 
					err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
 | 
				
			||||||
 | 
					                                 enum netif_mac_filter_action action)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    err_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (action)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case IGMP_ADD_MAC_FILTER:
 | 
				
			||||||
 | 
					            /* LPC ENET does not accept multicast selectively,
 | 
				
			||||||
 | 
					             * so all multicast has to be passed through. */
 | 
				
			||||||
 | 
					            ENET_AcceptAllMulticast(ethernetif->base);
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case IGMP_DEL_MAC_FILTER:
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * Moves the ENET device from a multicast group.
 | 
				
			||||||
 | 
					             * Since we don't keep track of which multicast groups
 | 
				
			||||||
 | 
					             * are still to enabled, the call is commented out.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            /* ENET_RejectAllMulticast(ethernetif->base); */
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            result = ERR_IF;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV6_MLD
 | 
				
			||||||
 | 
					err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
 | 
				
			||||||
 | 
					                                enum netif_mac_filter_action action)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    err_t result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (action)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        case NETIF_ADD_MAC_FILTER:
 | 
				
			||||||
 | 
					            /* LPC ENET does not accept multicast selectively,
 | 
				
			||||||
 | 
					             * so all multicast has to be passed through. */
 | 
				
			||||||
 | 
					            ENET_AcceptAllMulticast(ethernetif->base);
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case NETIF_DEL_MAC_FILTER:
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * Moves the ENET device from a multicast group.
 | 
				
			||||||
 | 
					             * Since we don't keep track of which multicast groups
 | 
				
			||||||
 | 
					             * are still to enabled, the call is commented out.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            /* ENET_RejectAllMulticast(ethernetif->base); */
 | 
				
			||||||
 | 
					            result = ERR_OK;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            result = ERR_IF;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets the RX descriptor by its index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline enet_rx_bd_struct_t *ethernetif_get_rx_desc(
 | 
				
			||||||
 | 
					                                                  struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                                                  uint32_t index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return &(ethernetif->RxBuffDescrip[index]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets the TX descriptor by its index.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline enet_tx_bd_struct_t *ethernetif_get_tx_desc(
 | 
				
			||||||
 | 
					                                                  struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                                                  uint32_t index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return &(ethernetif->TxBuffDescrip[index]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Initializes ENET driver.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                          const ethernetif_config_t *ethernetifConfig)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    enet_config_t config;
 | 
				
			||||||
 | 
					    uint32_t sysClock;
 | 
				
			||||||
 | 
					    enet_buffer_config_t buffCfg[ENET_RING_NUM];
 | 
				
			||||||
 | 
					    uint32_t rxBufferStartAddr[ENET_RXBD_NUM];
 | 
				
			||||||
 | 
					    uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* calculate start addresses of all rx buffers */
 | 
				
			||||||
 | 
					    for (i = 0; i < ENET_RXBD_NUM; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        rxBufferStartAddr[i] = (uint32_t)&(ethernetif->RxDataBuff[i][ETH_PAD_SIZE]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* prepare the buffer configuration. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxRingLen = ENET_RXBD_NUM;                          /* The length of receive buffer descriptor ring. */
 | 
				
			||||||
 | 
					    buffCfg[0].txRingLen = ENET_TXBD_NUM;                          /* The length of transmit buffer descriptor ring. */
 | 
				
			||||||
 | 
					    buffCfg[0].txDescStartAddrAlign = ethernetif_get_tx_desc(ethernetif, 0U); /* Aligned transmit descriptor start address. */
 | 
				
			||||||
 | 
					    buffCfg[0].txDescTailAddrAlign = ethernetif_get_tx_desc(ethernetif, 0U);  /* Aligned transmit descriptor tail address. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxDescStartAddrAlign = ethernetif_get_rx_desc(ethernetif, 0U); /* Aligned receive descriptor start address. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxDescTailAddrAlign = ethernetif_get_rx_desc(ethernetif, ENET_RXBD_NUM); /* Aligned receive descriptor tail address. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBufferStartAddr = rxBufferStartAddr;              /* Start addresses of the rx buffers. */
 | 
				
			||||||
 | 
					    buffCfg[0].rxBuffSizeAlign = sizeof(rx_buffer_t);              /* Aligned receive data buffer size. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sysClock = CLOCK_GetFreq(ethernetifConfig->clockName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("ethernetifConfig->non_dma_memory == NULL", (ethernetifConfig->non_dma_memory != NULL));
 | 
				
			||||||
 | 
					    ethernetif->non_dma_memory = ethernetifConfig->non_dma_memory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_GetDefaultConfig(&config);
 | 
				
			||||||
 | 
					    config.multiqueueCfg = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_phy_init(ethernetif, ethernetifConfig, &config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !NO_SYS
 | 
				
			||||||
 | 
					    /* Create the Event for transmit busy release trigger. */
 | 
				
			||||||
 | 
					    ethernetif->enetTransmitAccessEvent = xEventGroupCreate();
 | 
				
			||||||
 | 
					    ethernetif->txFlag = 0x1;
 | 
				
			||||||
 | 
					#endif /* !NO_SYS */
 | 
				
			||||||
 | 
					    NVIC_SetPriority(ETHERNET_IRQn, ENET_PRIORITY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif->txIdx = 0U;
 | 
				
			||||||
 | 
					    ethernetif->rxIdx = 0U;
 | 
				
			||||||
 | 
					    ethernetif->txReleaseIdx = 0U;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < ENET_RXBD_NUM; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ethernetif->rxPbufs[i].p.custom_free_function = ethernetif_rx_release;
 | 
				
			||||||
 | 
					        ethernetif->rxPbufs[i].rxDesc = ðernetif->RxBuffDescrip[i];
 | 
				
			||||||
 | 
					        ethernetif->rxPbufs[i].ethernetif = ethernetif;
 | 
				
			||||||
 | 
					        ethernetif->rxPbufs[i].ownedByLwip = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_Init(ethernetif->base, &config, netif->hwaddr, sysClock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(LPC54018_SERIES)
 | 
				
			||||||
 | 
					    /* Workaround for receive issue on lpc54018 */
 | 
				
			||||||
 | 
					    ethernetif->base->MAC_FRAME_FILTER |= ENET_MAC_FRAME_FILTER_RA_MASK;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Create the handler. */
 | 
				
			||||||
 | 
					#if NO_SYS
 | 
				
			||||||
 | 
					    ENET_EnableInterrupts(ethernetif->base, kENET_DmaTx);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    ENET_EnableInterrupts(ethernetif->base, kENET_DmaTx | kENET_DmaRx);
 | 
				
			||||||
 | 
					#endif /* NO_SYS */
 | 
				
			||||||
 | 
					    ENET_CreateHandler(ethernetif->base, ðernetif->handle, &config,
 | 
				
			||||||
 | 
					                       &buffCfg[0], ethernet_callback, netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_DescriptorInit(ethernetif->base, &config, &buffCfg[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Active TX/RX. */
 | 
				
			||||||
 | 
					    ENET_StartRxTx(ethernetif->base, 1, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return &(ethernetif->base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Find the ENET instance index from its base address.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static uint32_t ethernetif_get_enet_idx(ENET_Type *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS;
 | 
				
			||||||
 | 
					    uint32_t instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (instance = 0; instance < FSL_FEATURE_SOC_LPC_ENET_COUNT; instance++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (s_enetBases[instance] == base)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("Cannot find ENET instance index from its base address.",
 | 
				
			||||||
 | 
					                instance < FSL_FEATURE_SOC_LPC_ENET_COUNT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Sends (part of) a frame via ENET.
 | 
				
			||||||
 | 
					 * TODO: Since ENET_SendFrame() could not be used, some functionality it does
 | 
				
			||||||
 | 
					 * is missing here for now (channel selection depending on AVB content,
 | 
				
			||||||
 | 
					 * timestamping.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void ethernetif_send_buffer(struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                                   unsigned char *data,
 | 
				
			||||||
 | 
					                                   const uint32_t length,
 | 
				
			||||||
 | 
					                                   struct pbuf *p_to_release,
 | 
				
			||||||
 | 
					                                   enet_desc_flag flag)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static const IRQn_Type s_enetIrqId[] = ENET_IRQS;
 | 
				
			||||||
 | 
					    enet_tx_bd_struct_t *txDesc = ethernetif_get_tx_desc(ethernetif,
 | 
				
			||||||
 | 
					                                                         ethernetif->txIdx);
 | 
				
			||||||
 | 
					    ethernetif->txPbufs[ethernetif->txIdx] = p_to_release;
 | 
				
			||||||
 | 
					    ethernetif->txIdx = (ethernetif->txIdx + 1) % ENET_TXBD_NUM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Prepare the descriptor for transmit. */
 | 
				
			||||||
 | 
					    txDesc->buff1Addr = (uint32_t)data;
 | 
				
			||||||
 | 
					    txDesc->buff2Addr = (uint32_t)NULL;
 | 
				
			||||||
 | 
					    txDesc->buffLen =
 | 
				
			||||||
 | 
					                     ENET_TXDESCRIP_RD_BL1(length) | ENET_TXDESCRIP_RD_IOC_MASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    txDesc->controlStat =
 | 
				
			||||||
 | 
					                    ENET_TXDESCRIP_RD_FL(length) | ENET_TXDESCRIP_RD_LDFD(flag);
 | 
				
			||||||
 | 
					    if ((flag & kENET_FirstFlagOnly) == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * Submit to DMA if not the first descriptor in chain.
 | 
				
			||||||
 | 
					         * All the descriptors have to be prepared before the first one
 | 
				
			||||||
 | 
					         * is flagged for DMA and transfer starts. ENET could output invalid
 | 
				
			||||||
 | 
					         * frames otherwise (the exception is Store and Forward mode, where
 | 
				
			||||||
 | 
					         * delays between preparing of descriptors does not matter).
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        txDesc->controlStat |= ENET_TXDESCRIP_RD_OWN_MASK;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)
 | 
				
			||||||
 | 
					                                                ðernetif->handle.txBdRing[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Increment txDescUsed.
 | 
				
			||||||
 | 
					     * Without this, callback would not fire from ENET ISR on finished TX.
 | 
				
			||||||
 | 
					     * This is kind of a hack. Alternative could be to define
 | 
				
			||||||
 | 
					     * void ETHERNET_DriverIRQHandler(void) and handle IRQs completely
 | 
				
			||||||
 | 
					     * in this file.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    DisableIRQ(s_enetIrqId[ethernetif_get_enet_idx(ethernetif->base)]);
 | 
				
			||||||
 | 
					    txBdRing->txDescUsed++;
 | 
				
			||||||
 | 
					    EnableIRQ(s_enetIrqId[ethernetif_get_enet_idx(ethernetif->base)]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reclaims exactly one TX descriptor after its data has been sent out.
 | 
				
			||||||
 | 
					 * Then the descriptor can be used by application to prepare next data to send.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void ethernetif_tx_release(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    LWIP_ASSERT("Attempt to release more TX buffers than acquired.",
 | 
				
			||||||
 | 
					                ethernetif->txIdx != ethernetif->txReleaseIdx);
 | 
				
			||||||
 | 
					    enet_tx_bd_struct_t *txDesc
 | 
				
			||||||
 | 
					                         = ðernetif->TxBuffDescrip[ethernetif->txReleaseIdx];
 | 
				
			||||||
 | 
					    LWIP_ASSERT("TX buffer still owned by DMA.",
 | 
				
			||||||
 | 
					                !ENET_IsTxDescriptorDmaOwn(txDesc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct pbuf *p = (struct pbuf *)
 | 
				
			||||||
 | 
					                                  ethernetif->txPbufs[ethernetif->txReleaseIdx];
 | 
				
			||||||
 | 
					    if (p != NULL)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					        /* Reclaim the padding, force because it may be REF pbuf. */
 | 
				
			||||||
 | 
					        pbuf_header_force(p, ETH_PAD_SIZE);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if NO_SYS
 | 
				
			||||||
 | 
					#if defined(LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT) && LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
 | 
				
			||||||
 | 
					        pbuf_free(p);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        #error "Bare metal requires LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT=1 because pbuf_free() is being called from an ISR"
 | 
				
			||||||
 | 
					#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					        if (pbuf_free_callback(p) != ERR_OK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					#if defined(LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT) && LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
 | 
				
			||||||
 | 
					            pbuf_free(p);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					            LWIP_ASSERT("Failed to enqueue pbuf deallocation on tcpip_thread",
 | 
				
			||||||
 | 
					                        0);
 | 
				
			||||||
 | 
					#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					#endif /* NO_SYS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ethernetif->txPbufs[ethernetif->txReleaseIdx] = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif->txReleaseIdx = (ethernetif->txReleaseIdx + 1) % ENET_TXBD_NUM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reclaims RX descriptor which holds the p's buffer after p is no longer used
 | 
				
			||||||
 | 
					 * by the application / lwIP. The DMA can receive new data into
 | 
				
			||||||
 | 
					 * the descriptor's buffer then.
 | 
				
			||||||
 | 
					 * Note that RX buffers may be freed by lwIP out of the order in which they were
 | 
				
			||||||
 | 
					 * passed to lwIP. Therefore there may be spaces between the RX descriptors
 | 
				
			||||||
 | 
					 * flagged as owned by DMA and DMA could still wait until it's actual position
 | 
				
			||||||
 | 
					 * is released.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void ethernetif_rx_release(struct pbuf *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SYS_ARCH_DECL_PROTECT(old_level);
 | 
				
			||||||
 | 
					    rx_pbuf_wrapper_t *wrapper = (rx_pbuf_wrapper_t *)p;
 | 
				
			||||||
 | 
					#if NO_SYS
 | 
				
			||||||
 | 
					    bool intEnable = false;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    bool intEnable = true;
 | 
				
			||||||
 | 
					#endif /* NO_SYS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SYS_ARCH_PROTECT(old_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wrapper->ownedByLwip = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Update the receive buffer descriptor. */
 | 
				
			||||||
 | 
					    ENET_UpdateRxDescriptor(wrapper->rxDesc, NULL, NULL, intEnable, false);
 | 
				
			||||||
 | 
					    ENET_UpdateRxDescriptorTail(wrapper->ethernetif->base, 0U,
 | 
				
			||||||
 | 
					          (uint32_t)ethernetif_get_rx_desc(wrapper->ethernetif, ENET_RXBD_NUM));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SYS_ARCH_UNPROTECT(old_level);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Gets the length of a received frame (if there is some).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static status_t ethernetif_get_rx_frame_size(struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                                             uint32_t *length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t index = ethernetif->rxIdx;
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t *rxDesc;
 | 
				
			||||||
 | 
					    uint32_t rxControl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Reset the length to zero. */
 | 
				
			||||||
 | 
					    *length = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        rxDesc = ethernetif_get_rx_desc(ethernetif, index);
 | 
				
			||||||
 | 
					        rxControl = ENET_GetRxDescriptor(rxDesc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((rxControl & ENET_RXDESCRIP_WR_OWN_MASK)
 | 
				
			||||||
 | 
					            || (ethernetif->rxPbufs[index].ownedByLwip))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * Buffer descriptor is owned by DMA or lwIP.
 | 
				
			||||||
 | 
					             * We haven't received any complete frame yet.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            return kStatus_ENET_RxFrameEmpty;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Application owns the buffer descriptor. */
 | 
				
			||||||
 | 
					        if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* It's last descriptor of a frame, get its status or length. */
 | 
				
			||||||
 | 
					            if (rxControl & ENET_RXDESCRIP_WR_ERRSUM_MASK)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return kStatus_ENET_RxFrameError;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                *length = rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK;
 | 
				
			||||||
 | 
					                return kStatus_Success;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        index = (index + 1U) % ENET_RXBD_NUM;
 | 
				
			||||||
 | 
					    } while (index != ethernetif->rxIdx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * All descriptors have data but the end of the frame not detected.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    return kStatus_ENET_RxFrameError;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Drops (releases) receive descriptors until the last one of a frame is reached
 | 
				
			||||||
 | 
					 * or drops entire descriptor ring when all descriptors have data but end
 | 
				
			||||||
 | 
					 * of the frame not detected among them.
 | 
				
			||||||
 | 
					 * Function can be called only after ethernetif_get_rx_frame_size() indicates
 | 
				
			||||||
 | 
					 * that there actually is a frame error or a received frame.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void ethernetif_drop_frame(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if NO_SYS
 | 
				
			||||||
 | 
					    bool intEnable = false;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    bool intEnable = true;
 | 
				
			||||||
 | 
					#endif /* NO_SYS */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t *rxDesc;
 | 
				
			||||||
 | 
					    uint8_t index = ethernetif->rxIdx;
 | 
				
			||||||
 | 
					    uint32_t rxControl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        rxDesc = ethernetif_get_rx_desc(ethernetif, ethernetif->rxIdx);
 | 
				
			||||||
 | 
					        ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
 | 
				
			||||||
 | 
					        rxControl = ENET_GetRxDescriptor(rxDesc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Update the receive buffer descriptor. */
 | 
				
			||||||
 | 
					        ENET_UpdateRxDescriptor(rxDesc, NULL, NULL, intEnable, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Find the last buffer descriptor for the frame. */
 | 
				
			||||||
 | 
					        if (rxControl & ENET_RXDESCRIP_WR_LD_MASK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while (ethernetif->rxIdx != index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ENET_UpdateRxDescriptorTail(ethernetif->base, 0U,
 | 
				
			||||||
 | 
					                   (uint32_t)ethernetif_get_rx_desc(ethernetif, ENET_RXBD_NUM));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reads a received frame - wraps its descriptor buffer(s) into a pbuf
 | 
				
			||||||
 | 
					 * or a pbuf chain, flag descriptors as owned by lwIP and returns the pbuf.
 | 
				
			||||||
 | 
					 * The descriptors are returned to DMA only after the returned pbuf is released.
 | 
				
			||||||
 | 
					 * Function can be called only after ethernetif_get_rx_frame_size() indicates
 | 
				
			||||||
 | 
					 * that there actually is a received frame.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct pbuf *ethernetif_read_frame(struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                                          uint32_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rx_pbuf_wrapper_t *wrapper;
 | 
				
			||||||
 | 
					    enet_rx_bd_struct_t *rxDesc;
 | 
				
			||||||
 | 
					    uint32_t rxControl;
 | 
				
			||||||
 | 
					    uint32_t len = 0;
 | 
				
			||||||
 | 
					    struct pbuf *p = NULL;
 | 
				
			||||||
 | 
					    struct pbuf *q = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        wrapper = ðernetif->rxPbufs[ethernetif->rxIdx];
 | 
				
			||||||
 | 
					        wrapper->ownedByLwip = true;
 | 
				
			||||||
 | 
					        ethernetif->rxIdx = (ethernetif->rxIdx + 1U) % ENET_RXBD_NUM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rxDesc = wrapper->rxDesc;
 | 
				
			||||||
 | 
					        rxControl = ENET_GetRxDescriptor(rxDesc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        len = (rxControl & ENET_RXDESCRIP_WR_PACKETLEN_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Wrap the receive buffer in pbuf. */
 | 
				
			||||||
 | 
					        if (p == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            p = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &wrapper->p,
 | 
				
			||||||
 | 
					                                    (void *)rxDesc->buff1Addr, len);
 | 
				
			||||||
 | 
					            LWIP_ASSERT("pbuf_alloced_custom() failed", p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					            /* Add the padding header, force because it is a REF type buffer. */
 | 
				
			||||||
 | 
					            pbuf_header_force(p, ETH_PAD_SIZE);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            q = pbuf_alloced_custom(PBUF_RAW, len, PBUF_REF, &wrapper->p,
 | 
				
			||||||
 | 
					                                    (void *)rxDesc->buff1Addr, len);
 | 
				
			||||||
 | 
					            LWIP_ASSERT("pbuf_alloced_custom() failed", q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pbuf_cat(p, q);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } while (((rxControl & ENET_RXDESCRIP_WR_LD_MASK) == 0U)
 | 
				
			||||||
 | 
					             && (p->tot_len < length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
 | 
				
			||||||
 | 
					    if (((u8_t *)p->payload)[0] & 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* broadcast or multicast packet */
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* unicast packet */
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LINK_STATS_INC(link.recv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Attempts to read a frame from ENET and returns it wrapped in a pbuf
 | 
				
			||||||
 | 
					 * or returns NULL when no frame is received. Discards invalid frames.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct pbuf *ethernetif_linkinput(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    struct pbuf *p = NULL;
 | 
				
			||||||
 | 
					    uint32_t len;
 | 
				
			||||||
 | 
					    status_t status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Obtain the size of the packet and put it into the "len" variable. */
 | 
				
			||||||
 | 
					    status = ethernetif_get_rx_frame_size(ethernetif, &len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (status == kStatus_Success)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        p = ethernetif_read_frame(ethernetif, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (p == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* Could not initialise wrapper pbuf(s) - drop the frame. */
 | 
				
			||||||
 | 
					            ethernetif_drop_frame(ethernetif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            LWIP_DEBUGF(NETIF_DEBUG,
 | 
				
			||||||
 | 
					                 ("ethernetif_linkinput: Fail to allocate new memory space\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            LINK_STATS_INC(link.memerr);
 | 
				
			||||||
 | 
					            LINK_STATS_INC(link.drop);
 | 
				
			||||||
 | 
					            MIB2_STATS_NETIF_INC(netif, ifindiscards);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (status == kStatus_ENET_RxFrameError)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Update the received buffer when error happened. */
 | 
				
			||||||
 | 
					        ethernetif_drop_frame(ethernetif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_linkinput: RxFrameError\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        LINK_STATS_INC(link.drop);
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifindiscards);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns the number of TX descriptors which could be used by lwIP/application
 | 
				
			||||||
 | 
					 * to put new TX data into.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The max number of free descriptors is (ENET_TXBD_NUM - 1), that is when
 | 
				
			||||||
 | 
					 * ethernetif->txReleaseIdx == ethernetif->txIdx. Having the capacity decreased
 | 
				
			||||||
 | 
					 * by one allows to avoid locking: txReleaseIdx is advanced only from ISR
 | 
				
			||||||
 | 
					 * and txIdx from tcpip_thread/main loop. Should we use full capacity and have
 | 
				
			||||||
 | 
					 * some variable to indicate between the "all buffers are free" vs. "all buffers
 | 
				
			||||||
 | 
					 * are used" situation, it would be manipulated from two contexts hence locking
 | 
				
			||||||
 | 
					 * would be needed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline int ethernetif_avail_tx_descs(struct ethernetif *ethernetif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (ethernetif->txReleaseIdx + ENET_TXBD_NUM - 1 - ethernetif->txIdx)
 | 
				
			||||||
 | 
					                                                                % ENET_TXBD_NUM;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Attempts to output a frame from ENET. The function avoids copying of
 | 
				
			||||||
 | 
					 * p's payload when possible. In such situation it increases p's reference count
 | 
				
			||||||
 | 
					 * and decreases it (and possibly releases p) after the payload is sent.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    struct ethernetif *ethernetif = netif->state;
 | 
				
			||||||
 | 
					    struct pbuf *q;
 | 
				
			||||||
 | 
					    struct pbuf *pbuf_to_free = NULL;
 | 
				
			||||||
 | 
					    struct pbuf *p_copy;
 | 
				
			||||||
 | 
					    uint16_t clen;
 | 
				
			||||||
 | 
					    bool copy = false;
 | 
				
			||||||
 | 
					    const mem_range_t *non_dma_memory;
 | 
				
			||||||
 | 
					    uint8_t *dst;
 | 
				
			||||||
 | 
					    uint32_t cnt = 0;
 | 
				
			||||||
 | 
					    uint8_t first_idx;
 | 
				
			||||||
 | 
					    uint32_t tail_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LWIP_ASSERT("Output packet buffer empty", p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((p->tot_len - ETH_PAD_SIZE) > ENET_FRAME_MAX_FRAMELEN)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return ERR_BUF;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    clen = pbuf_clen(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check if relocation is needed */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (clen > (ENET_TXBD_NUM - 1))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Pbuf chain is too long to be prepared for DMA at once. */
 | 
				
			||||||
 | 
					        copy = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (q = p; (q != NULL) && !copy; q = q->next)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * Check if payload is aligned is not desired: lwIP creates RAM pbufs
 | 
				
			||||||
 | 
					         * in a way that the data coming after the headers are aligned, but not
 | 
				
			||||||
 | 
					         * the beginning of the ethernet header. LPC ENET DMA will read from
 | 
				
			||||||
 | 
					         * the aligned address, which is ok, because there is additional space
 | 
				
			||||||
 | 
					         * before the headers to make up for alignment - so DMA will not read
 | 
				
			||||||
 | 
					         * from invalid address or unrelated data.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Check payload address is usable by ENET DMA */
 | 
				
			||||||
 | 
					        for (non_dma_memory = ethernetif->non_dma_memory;
 | 
				
			||||||
 | 
					             (non_dma_memory->start != 0U)
 | 
				
			||||||
 | 
					             || (non_dma_memory->end != 0U); non_dma_memory++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((q->payload >= (void *) non_dma_memory->start)
 | 
				
			||||||
 | 
					                && (q->payload < (void *) non_dma_memory->end))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                copy = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (copy)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Pbuf needs to be copied. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        p_copy = pbuf_alloc(PBUF_RAW, (uint16_t) p->tot_len, PBUF_POOL);
 | 
				
			||||||
 | 
					        if (p_copy == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ERR_MEM;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dst = (uint8_t *) p_copy->payload;
 | 
				
			||||||
 | 
					        for (q = p; q != NULL; q = q->next)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            LWIP_ASSERT("Copied bytes would exceed p->tot_len",
 | 
				
			||||||
 | 
					                    (q->len + dst - (uint8_t *) p_copy->payload) <= p->tot_len);
 | 
				
			||||||
 | 
					            memcpy(dst, (uint8_t *)q->payload, q->len);
 | 
				
			||||||
 | 
					            dst += q->len;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        LWIP_ASSERT("Copied bytes != p->tot_len",
 | 
				
			||||||
 | 
					                    (dst - (uint8_t *) p_copy->payload) == p->tot_len);
 | 
				
			||||||
 | 
					        p_copy->len = p_copy->tot_len = p->tot_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        p = p_copy;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					         * Increase reference count so p is released only after it is sent.
 | 
				
			||||||
 | 
					         * For copied pbuf, ref is already 1 after pbuf_alloc().
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        pbuf_ref(p);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * Wait until the sufficient number of descriptors are available,
 | 
				
			||||||
 | 
					     * as we have to start the transfer of the first buffer only
 | 
				
			||||||
 | 
					     * after all buffers in chain are prepared.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    while (ethernetif_avail_tx_descs(ethernetif) < clen)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					#if !NO_SYS
 | 
				
			||||||
 | 
					        xEventGroupWaitBits(ethernetif->enetTransmitAccessEvent,
 | 
				
			||||||
 | 
					                            ethernetif->txFlag, pdTRUE, (BaseType_t) false,
 | 
				
			||||||
 | 
					                            portMAX_DELAY);
 | 
				
			||||||
 | 
					#endif /* !NO_SYS */
 | 
				
			||||||
 | 
					        cnt++;
 | 
				
			||||||
 | 
					        if (cnt >= ENET_TIMEOUT)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ERR_TIMEOUT;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if ETH_PAD_SIZE
 | 
				
			||||||
 | 
					    /* Drop the padding. */
 | 
				
			||||||
 | 
					    pbuf_header(p, -ETH_PAD_SIZE);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initiate transfer. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    first_idx = ethernetif->txIdx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (q = p; q != NULL; q = q->next)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        enet_desc_flag flag = kENET_MiddleFlag;
 | 
				
			||||||
 | 
					        pbuf_to_free = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (q == p)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            flag |= kENET_FirstFlagOnly;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (q->next == NULL)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            flag |= kENET_LastFlagOnly;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* On last TX interrupt, free pbuf chain. */
 | 
				
			||||||
 | 
					            pbuf_to_free = p;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ethernetif_send_buffer(ethernetif, q->payload, q->len, pbuf_to_free,
 | 
				
			||||||
 | 
					                               flag);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* All pbufs from chain are prepared, allow DMA to access the first one. */
 | 
				
			||||||
 | 
					    ethernetif_get_tx_desc(ethernetif, first_idx)->controlStat |=
 | 
				
			||||||
 | 
					                                                     ENET_TXDESCRIP_RD_OWN_MASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Update the transmit tail address. */
 | 
				
			||||||
 | 
					    if (ethernetif->txIdx == 0U)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        tail_address = (uint32_t)ethernetif_get_tx_desc(ethernetif,
 | 
				
			||||||
 | 
					                                                        ENET_TXBD_NUM);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        tail_address = (uint32_t)ethernetif_get_tx_desc(ethernetif,
 | 
				
			||||||
 | 
					                                                        ethernetif->txIdx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ENET_UpdateTxDescriptorTail(ethernetif->base, 0, tail_address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
 | 
				
			||||||
 | 
					    if (((uint8_t *)p->payload)[0] & 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* broadcast or multicast packet */
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* unicast packet */
 | 
				
			||||||
 | 
					        MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    LINK_STATS_INC(link.xmit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ERR_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Should be called at the beginning of the program to set up the
 | 
				
			||||||
 | 
					 * first network interface. It calls the function ethernetif_init() to do the
 | 
				
			||||||
 | 
					 * actual setup of the hardware.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @return ERR_OK if the loopif is initialized
 | 
				
			||||||
 | 
					 *         ERR_MEM if private data couldn't be allocated
 | 
				
			||||||
 | 
					 *         any other err_t on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif0_init(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static struct ethernetif ethernetif_0;
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_0[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static rx_buffer_t rxDataBuff_0[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_0.RxBuffDescrip = &(rxBuffDescrip_0[0]);
 | 
				
			||||||
 | 
					    ethernetif_0.TxBuffDescrip = &(txBuffDescrip_0[0]);
 | 
				
			||||||
 | 
					    ethernetif_0.RxDataBuff = &(rxDataBuff_0[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ethernetif_init(netif, ðernetif_0, 0U, (ethernetif_config_t *)netif->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 1)
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Should be called at the beginning of the program to set up the
 | 
				
			||||||
 | 
					 * second network interface. It calls the function ethernetif_init() to do the
 | 
				
			||||||
 | 
					 * actual setup of the hardware.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add().
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @return ERR_OK if the loopif is initialized
 | 
				
			||||||
 | 
					 *         ERR_MEM if private data couldn't be allocated
 | 
				
			||||||
 | 
					 *         any other err_t on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif1_init(struct netif *netif)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static struct ethernetif ethernetif_1;
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rxBuffDescrip_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t txBuffDescrip_1[ENET_TXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					    SDK_ALIGN(static rx_buffer_t rxDataBuff_1[ENET_RXBD_NUM], FSL_ENET_BUFF_ALIGNMENT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ethernetif_1.RxBuffDescrip = &(rxBuffDescrip_1[0]);
 | 
				
			||||||
 | 
					    ethernetif_1.TxBuffDescrip = &(txBuffDescrip_1[0]);
 | 
				
			||||||
 | 
					    ethernetif_1.RxDataBuff = &(rxDataBuff_1[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ethernetif_init(netif, ðernetif_1, 1U, (ethernetif_config_t *)netif->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					SRC_FILES := fsl_phy.c
 | 
				
			||||||
 | 
					include $(KERNEL_ROOT)/compiler.mk
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,324 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The Clear BSD License
 | 
				
			||||||
 | 
					 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2017 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted (subject to the limitations in the disclaimer below) provided
 | 
				
			||||||
 | 
					 *  that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Redistributions of source code must retain the above copyright notice, this list
 | 
				
			||||||
 | 
					 *   of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Redistributions in binary form must reproduce the above copyright notice, this
 | 
				
			||||||
 | 
					 *   list of conditions and the following disclaimer in the documentation and/or
 | 
				
			||||||
 | 
					 *   other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Neither the name of the copyright holder nor the names of its
 | 
				
			||||||
 | 
					 *   contributors may be used to endorse or promote products derived from this
 | 
				
			||||||
 | 
					 *   software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
				
			||||||
 | 
					 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
				
			||||||
 | 
					 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
				
			||||||
 | 
					 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 | 
				
			||||||
 | 
					 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
				
			||||||
 | 
					 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_phy.h"
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the timeout macro. */
 | 
				
			||||||
 | 
					#define PHY_TIMEOUT_COUNT 0x3FFFFFFU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Prototypes
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Get the ENET instance from peripheral base address.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @return ENET instance.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					extern uint32_t ENET_GetInstance(ENET_Type *base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Variables
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
 | 
				
			||||||
 | 
					/*! @brief Pointers to enet clocks for each instance. */
 | 
				
			||||||
 | 
					extern clock_ip_name_t s_enetClock[FSL_FEATURE_SOC_ENET_COUNT];
 | 
				
			||||||
 | 
					#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Code
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t bssReg;
 | 
				
			||||||
 | 
					    uint32_t counter = PHY_TIMEOUT_COUNT;
 | 
				
			||||||
 | 
					    uint32_t idReg = 0;
 | 
				
			||||||
 | 
					    status_t result = kStatus_Success;
 | 
				
			||||||
 | 
					    uint32_t instance = ENET_GetInstance(base);
 | 
				
			||||||
 | 
					    uint32_t timeDelay;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
 | 
				
			||||||
 | 
					    /* Set SMI first. */
 | 
				
			||||||
 | 
					    CLOCK_EnableClock(s_enetClock[instance]);
 | 
				
			||||||
 | 
					#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
 | 
				
			||||||
 | 
					    ENET_SetSMI(base, srcClock_Hz, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initialization after PHY stars to work. */
 | 
				
			||||||
 | 
					    while ((idReg != PHY_CONTROL_ID1) && (counter != 0))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        PHY_Read(base, phyAddr, PHY_ID1_REG, &idReg);
 | 
				
			||||||
 | 
					        counter --;       
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!counter)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return kStatus_Fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Reset PHY. */
 | 
				
			||||||
 | 
					    counter = PHY_TIMEOUT_COUNT;
 | 
				
			||||||
 | 
					    result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
 | 
				
			||||||
 | 
					    if (result == kStatus_Success)
 | 
				
			||||||
 | 
					    {  
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /* Set the negotiation. */
 | 
				
			||||||
 | 
					        result = PHY_Write(base, phyAddr, PHY_AUTONEG_ADVERTISE_REG,
 | 
				
			||||||
 | 
					                           (PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK |
 | 
				
			||||||
 | 
					                            PHY_10BASETX_FULLDUPLEX_MASK | PHY_10BASETX_HALFDUPLEX_MASK | 0x1U));
 | 
				
			||||||
 | 
					        if (result == kStatus_Success)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG,
 | 
				
			||||||
 | 
					                               (PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
 | 
				
			||||||
 | 
					            if (result == kStatus_Success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                /* Check auto negotiation complete. */
 | 
				
			||||||
 | 
					                while (counter --)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &bssReg);
 | 
				
			||||||
 | 
					                    if ( result == kStatus_Success)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if ((bssReg & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            /* Wait a moment for Phy status stable. */
 | 
				
			||||||
 | 
					                            for (timeDelay = 0; timeDelay < PHY_TIMEOUT_COUNT; timeDelay ++)
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                __ASM("nop");
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!counter)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return kStatus_PHY_AutoNegotiateFail;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear the SMI interrupt event. */
 | 
				
			||||||
 | 
					    ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Starts a SMI write command. */
 | 
				
			||||||
 | 
					    ENET_StartSMIWrite(base, phyAddr, phyReg, kENET_MiiWriteValidFrame, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Wait for SMI complete. */
 | 
				
			||||||
 | 
					    for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check for timeout. */
 | 
				
			||||||
 | 
					    if (!counter)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return kStatus_PHY_SMIVisitTimeout;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear MII interrupt event. */
 | 
				
			||||||
 | 
					    ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return kStatus_Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert(dataPtr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t counter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear the MII interrupt event. */
 | 
				
			||||||
 | 
					    ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Starts a SMI read command operation. */
 | 
				
			||||||
 | 
					    ENET_StartSMIRead(base, phyAddr, phyReg, kENET_MiiReadValidFrame);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Wait for MII complete. */
 | 
				
			||||||
 | 
					    for (counter = PHY_TIMEOUT_COUNT; counter > 0; counter--)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check for timeout. */
 | 
				
			||||||
 | 
					    if (!counter)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return kStatus_PHY_SMIVisitTimeout;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Get data from MII register. */
 | 
				
			||||||
 | 
					    *dataPtr = ENET_ReadSMIData(base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Clear MII interrupt event. */
 | 
				
			||||||
 | 
					    ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return kStatus_Success;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    status_t result;
 | 
				
			||||||
 | 
					    uint32_t data = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Set the loop mode. */
 | 
				
			||||||
 | 
					    if (enable)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (mode == kPHY_LocalLoop)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (speed == kPHY_Speed100M)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                data = PHY_BCTL_SPEED_100M_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                data = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;                
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					           return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* First read the current status in control register. */
 | 
				
			||||||
 | 
					            result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &data);
 | 
				
			||||||
 | 
					            if (result == kStatus_Success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return PHY_Write(base, phyAddr, PHY_CONTROL1_REG, (data | PHY_CTL1_REMOTELOOP_MASK));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /* Disable the loop mode. */
 | 
				
			||||||
 | 
					        if (mode == kPHY_LocalLoop)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* First read the current status in control register. */
 | 
				
			||||||
 | 
					            result = PHY_Read(base, phyAddr, PHY_BASICCONTROL_REG, &data);
 | 
				
			||||||
 | 
					            if (result == kStatus_Success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                data &= ~PHY_BCTL_LOOP_MASK;
 | 
				
			||||||
 | 
					                return PHY_Write(base, phyAddr, PHY_BASICCONTROL_REG, (data | PHY_BCTL_RESTART_AUTONEG_MASK));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* First read the current status in control one register. */
 | 
				
			||||||
 | 
					            result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &data);
 | 
				
			||||||
 | 
					            if (result == kStatus_Success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return PHY_Write(base, phyAddr, PHY_CONTROL1_REG, (data & ~PHY_CTL1_REMOTELOOP_MASK));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert(status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    status_t result = kStatus_Success;
 | 
				
			||||||
 | 
					    uint32_t data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Read the basic status register. */
 | 
				
			||||||
 | 
					    result = PHY_Read(base, phyAddr, PHY_BASICSTATUS_REG, &data);
 | 
				
			||||||
 | 
					    if (result == kStatus_Success)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!(PHY_BSTATUS_LINKSTATUS_MASK & data))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* link down. */
 | 
				
			||||||
 | 
					            *status = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* link up. */
 | 
				
			||||||
 | 
					            *status = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    assert(duplex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    status_t result = kStatus_Success;
 | 
				
			||||||
 | 
					    uint32_t data, ctlReg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Read the control two register. */
 | 
				
			||||||
 | 
					    result = PHY_Read(base, phyAddr, PHY_CONTROL1_REG, &ctlReg);
 | 
				
			||||||
 | 
					    if (result == kStatus_Success)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
 | 
				
			||||||
 | 
					        if ((PHY_CTL1_10FULLDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* Full duplex. */
 | 
				
			||||||
 | 
					            *duplex = kPHY_FullDuplex;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* Half duplex. */
 | 
				
			||||||
 | 
					            *duplex = kPHY_HalfDuplex;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = ctlReg & PHY_CTL1_SPEEDUPLX_MASK;
 | 
				
			||||||
 | 
					        if ((PHY_CTL1_100HALFDUPLEX_MASK == data) || (PHY_CTL1_100FULLDUPLEX_MASK == data))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            /* 100M speed. */
 | 
				
			||||||
 | 
					            *speed = kPHY_Speed100M;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        { /* 10M speed. */
 | 
				
			||||||
 | 
					            *speed = kPHY_Speed10M;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,225 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The Clear BSD License
 | 
				
			||||||
 | 
					 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2017 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted (subject to the limitations in the disclaimer below) provided
 | 
				
			||||||
 | 
					 *  that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Redistributions of source code must retain the above copyright notice, this list
 | 
				
			||||||
 | 
					 *   of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Redistributions in binary form must reproduce the above copyright notice, this
 | 
				
			||||||
 | 
					 *   list of conditions and the following disclaimer in the documentation and/or
 | 
				
			||||||
 | 
					 *   other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * o Neither the name of the copyright holder nor the names of its
 | 
				
			||||||
 | 
					 *   contributors may be used to endorse or promote products derived from this
 | 
				
			||||||
 | 
					 *   software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
				
			||||||
 | 
					 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
				
			||||||
 | 
					 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 | 
				
			||||||
 | 
					 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
				
			||||||
 | 
					 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
				
			||||||
 | 
					 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 | 
				
			||||||
 | 
					 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
				
			||||||
 | 
					 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _FSL_PHY_H_
 | 
				
			||||||
 | 
					#define _FSL_PHY_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_enet.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @addtogroup phy_driver
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief PHY driver version */
 | 
				
			||||||
 | 
					#define FSL_PHY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) /*!< Version 2.0.0. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the PHY registers. */
 | 
				
			||||||
 | 
					#define PHY_BASICCONTROL_REG 0x00U      /*!< The PHY basic control register. */
 | 
				
			||||||
 | 
					#define PHY_BASICSTATUS_REG 0x01U       /*!< The PHY basic status register. */
 | 
				
			||||||
 | 
					#define PHY_ID1_REG 0x02U               /*!< The PHY ID one register. */
 | 
				
			||||||
 | 
					#define PHY_ID2_REG 0x03U               /*!< The PHY ID two register. */
 | 
				
			||||||
 | 
					#define PHY_AUTONEG_ADVERTISE_REG 0x04U /*!< The PHY auto-negotiate advertise register. */
 | 
				
			||||||
 | 
					#define PHY_CONTROL1_REG 0x1FU          /*!< The PHY control one register. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PHY_CONTROL_ID1 0x07U /*!< The PHY ID1*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the mask flag in basic control register. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_DUPLEX_MASK 0x0100U          /*!< The PHY duplex bit mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_RESTART_AUTONEG_MASK 0x0200U /*!< The PHY restart auto negotiation mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_AUTONEG_MASK 0x1000U         /*!< The PHY auto negotiation bit mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_SPEED_MASK 0x2000U           /*!< The PHY speed bit mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_LOOP_MASK 0x4000U            /*!< The PHY loop bit mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_RESET_MASK 0x8000U           /*!< The PHY reset bit mask. */
 | 
				
			||||||
 | 
					#define PHY_BCTL_SPEED_100M_MASK  0x2000U     /*!< The PHY 100M speed mask. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!@brief Defines the mask flag of operation mode in control two register*/
 | 
				
			||||||
 | 
					#define PHY_CTL1_REMOTELOOP_MASK 0x0004U    /*!< The PHY remote loopback mask. */
 | 
				
			||||||
 | 
					//#define PHY_CTL2_REFCLK_SELECT_MASK 0x0080U /*!< The PHY RMII reference clock select. */ 
 | 
				
			||||||
 | 
					#define PHY_CTL1_10HALFDUPLEX_MASK 0x0004U  /*!< The PHY 10M half duplex mask. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_100HALFDUPLEX_MASK 0x0008U /*!< The PHY 100M half duplex mask. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_10FULLDUPLEX_MASK 0x0014U  /*!< The PHY 10M full duplex mask. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_100FULLDUPLEX_MASK 0x0018U /*!< The PHY 100M full duplex mask. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_SPEEDUPLX_MASK 0x001CU     /*!< The PHY speed and duplex mask. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_ENERGYDETECT_MASK 0x10U    /*!< The PHY signal present on rx differential pair. */
 | 
				
			||||||
 | 
					#define PHY_CTL1_LINKUP_MASK 0x100U         /*!< The PHY link up. */        
 | 
				
			||||||
 | 
					#define PHY_LINK_READY_MASK (PHY_CTL1_ENERGYDETECT_MASK | PHY_CTL1_LINKUP_MASK)
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
 | 
					/*! @brief Defines the mask flag in basic status register. */
 | 
				
			||||||
 | 
					#define PHY_BSTATUS_LINKSTATUS_MASK 0x0004U  /*!< The PHY link status mask. */
 | 
				
			||||||
 | 
					#define PHY_BSTATUS_AUTONEGABLE_MASK 0x0008U /*!< The PHY auto-negotiation ability mask. */
 | 
				
			||||||
 | 
					#define PHY_BSTATUS_AUTONEGCOMP_MASK 0x0020U /*!< The PHY auto-negotiation complete mask. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the mask flag in PHY auto-negotiation advertise register. */
 | 
				
			||||||
 | 
					#define PHY_100BaseT4_ABILITY_MASK 0x200U    /*!< The PHY have the T4 ability. */
 | 
				
			||||||
 | 
					#define PHY_100BASETX_FULLDUPLEX_MASK 0x100U /*!< The PHY has the 100M full duplex ability.*/
 | 
				
			||||||
 | 
					#define PHY_100BASETX_HALFDUPLEX_MASK 0x080U /*!< The PHY has the 100M full duplex ability.*/
 | 
				
			||||||
 | 
					#define PHY_10BASETX_FULLDUPLEX_MASK 0x040U  /*!< The PHY has the 10M full duplex ability.*/
 | 
				
			||||||
 | 
					#define PHY_10BASETX_HALFDUPLEX_MASK 0x020U  /*!< The PHY has the 10M full duplex ability.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the PHY status. */
 | 
				
			||||||
 | 
					enum _phy_status
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kStatus_PHY_SMIVisitTimeout = MAKE_STATUS(kStatusGroup_PHY, 1),  /*!< ENET PHY SMI visit timeout. */
 | 
				
			||||||
 | 
					    kStatus_PHY_AutoNegotiateFail = MAKE_STATUS(kStatusGroup_PHY, 2) /*!< ENET PHY AutoNegotiate Fail. */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the PHY link speed. This is align with the speed for ENET MAC. */
 | 
				
			||||||
 | 
					typedef enum _phy_speed
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kPHY_Speed10M = 0U, /*!< ENET PHY 10M speed. */
 | 
				
			||||||
 | 
					    kPHY_Speed100M      /*!< ENET PHY 100M speed. */
 | 
				
			||||||
 | 
					} phy_speed_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the PHY link duplex. */
 | 
				
			||||||
 | 
					typedef enum _phy_duplex
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kPHY_HalfDuplex = 0U, /*!< ENET PHY half duplex. */
 | 
				
			||||||
 | 
					    kPHY_FullDuplex       /*!< ENET PHY full duplex. */
 | 
				
			||||||
 | 
					} phy_duplex_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief Defines the PHY loopback mode. */
 | 
				
			||||||
 | 
					typedef enum _phy_loop
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kPHY_LocalLoop = 0U, /*!< ENET PHY local loopback. */
 | 
				
			||||||
 | 
					    kPHY_RemoteLoop      /*!< ENET PHY remote loopback. */
 | 
				
			||||||
 | 
					} phy_loop_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * API
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					  * @name PHY Driver
 | 
				
			||||||
 | 
					  * @{
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Initializes PHY.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  This function initialize the SMI interface and initialize PHY.
 | 
				
			||||||
 | 
					 *  The SMI is the MII management interface between PHY and MAC, which should be
 | 
				
			||||||
 | 
					 *  firstly initialized before any other operation for PHY. The PHY initialize with auto-negotiation. 
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base       ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr    The PHY address.
 | 
				
			||||||
 | 
					 * @param srcClock_Hz  The module clock frequency - system clock for MII management interface - SMI.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success  PHY initialize success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_AutoNegotiateFail  PHY auto negotiate fail
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_Init(ENET_Type *base, uint32_t phyAddr, uint32_t srcClock_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief PHY Write function. This function write data over the SMI to
 | 
				
			||||||
 | 
					 * the specified PHY register. This function is called by all PHY interfaces.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base    ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr The PHY address.
 | 
				
			||||||
 | 
					 * @param phyReg  The PHY register.
 | 
				
			||||||
 | 
					 * @param data    The data written to the PHY register.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success     PHY write success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_Write(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief PHY Read function. This interface read data over the SMI from the
 | 
				
			||||||
 | 
					 * specified PHY register. This function is called by all PHY interfaces.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base     ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr  The PHY address.
 | 
				
			||||||
 | 
					 * @param phyReg   The PHY register.
 | 
				
			||||||
 | 
					 * @param dataPtr  The address to store the data read from the PHY register.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success  PHY read success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_Read(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, uint32_t *dataPtr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Enables/disables PHY loopback.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base     ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr  The PHY address.
 | 
				
			||||||
 | 
					 * @param mode     The loopback mode to be enabled, please see "phy_loop_t".
 | 
				
			||||||
 | 
					 * the two loopback mode should not be both set. when one loopback mode is set
 | 
				
			||||||
 | 
					 * the other one should be disabled.
 | 
				
			||||||
 | 
					 * @param speed    PHY speed for loopback mode.
 | 
				
			||||||
 | 
					 * @param enable   True to enable, false to disable.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success  PHY loopback success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_EnableLoopback(ENET_Type *base, uint32_t phyAddr, phy_loop_t mode, phy_speed_t speed, bool enable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Gets the PHY link status.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base     ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr  The PHY address.
 | 
				
			||||||
 | 
					 * @param status   The link up or down status of the PHY.
 | 
				
			||||||
 | 
					 *         - true the link is up.
 | 
				
			||||||
 | 
					 *         - false the link is down.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success   PHY get link status success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_GetLinkStatus(ENET_Type *base, uint32_t phyAddr, bool *status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Gets the PHY link speed and duplex.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base     ENET peripheral base address.
 | 
				
			||||||
 | 
					 * @param phyAddr  The PHY address.
 | 
				
			||||||
 | 
					 * @param speed    The address of PHY link speed.
 | 
				
			||||||
 | 
					 * @param duplex   The link duplex of PHY.
 | 
				
			||||||
 | 
					 * @retval kStatus_Success   PHY get link speed and duplex success
 | 
				
			||||||
 | 
					 * @retval kStatus_PHY_SMIVisitTimeout  PHY SMI visit time out
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t PHY_GetLinkSpeedDuplex(ENET_Type *base, uint32_t phyAddr, phy_speed_t *speed, phy_duplex_t *duplex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _FSL_PHY_H_ */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,39 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					* Copyright (c) 2021 AIIT XUOS Lab
 | 
				
			||||||
 | 
					* XiUOS is licensed under Mulan PSL v2.
 | 
				
			||||||
 | 
					* You can use this software according to the terms and conditions of the Mulan PSL v2.
 | 
				
			||||||
 | 
					* You may obtain a copy of Mulan PSL v2 at:
 | 
				
			||||||
 | 
					*        http://license.coscl.org.cn/MulanPSL2
 | 
				
			||||||
 | 
					* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
				
			||||||
 | 
					* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
				
			||||||
 | 
					* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
				
			||||||
 | 
					* See the Mulan PSL v2 for more details.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					* @file connect_ethernet.h
 | 
				
			||||||
 | 
					* @brief Adapted network software protocol stack and hardware operation functions
 | 
				
			||||||
 | 
					* @version 1.0
 | 
				
			||||||
 | 
					* @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					* @date 2021-12-7
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __CONNECT_ETHERNET_H_
 | 
				
			||||||
 | 
					#define __CONNECT_ETHERNET_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					 extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef sourceClock
 | 
				
			||||||
 | 
					#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,192 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without modification,
 | 
				
			||||||
 | 
					 * are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					 *    and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 * 3. The name of the author may not be used to endorse or promote products
 | 
				
			||||||
 | 
					 *    derived from this software without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | 
				
			||||||
 | 
					 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 | 
				
			||||||
 | 
					 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
				
			||||||
 | 
					 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 | 
				
			||||||
 | 
					 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 | 
				
			||||||
 | 
					 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 | 
				
			||||||
 | 
					 * OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of the lwIP TCP/IP stack.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Author: Adam Dunkels <adam@sics.se>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2013-2016, Freescale Semiconductor, Inc.
 | 
				
			||||||
 | 
					 * Copyright 2016-2019 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file enet_ethernetif.h
 | 
				
			||||||
 | 
					 * @brief ethernet drivers
 | 
				
			||||||
 | 
					 * @version 1.0
 | 
				
			||||||
 | 
					 * @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					 * @date 2021.11.11
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENET_ETHERNETIF_H
 | 
				
			||||||
 | 
					#define ENET_ETHERNETIF_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lwip/err.h"
 | 
				
			||||||
 | 
					#include "lwip/netif.h"
 | 
				
			||||||
 | 
					#include "fsl_enet.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					#ifndef ENET_RXBD_NUM
 | 
				
			||||||
 | 
					    #define ENET_RXBD_NUM (5)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ENET_TXBD_NUM
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
 | 
				
			||||||
 | 
					    #define ENET_TXBD_NUM (5)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    #define ENET_TXBD_NUM (3)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ENET_RXBUFF_SIZE
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0)
 | 
				
			||||||
 | 
					    #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN + ETH_PAD_SIZE)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    #define ENET_RXBUFF_SIZE ENET_FRAME_MAX_FRAMELEN
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENET_TXBUFF_SIZE
 | 
				
			||||||
 | 
					    #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENET_TIMEOUT        (0xFFFU)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ENET IRQ priority. Used in FreeRTOS. */
 | 
				
			||||||
 | 
					/* Interrupt priorities. */
 | 
				
			||||||
 | 
					#ifdef __CA7_REV
 | 
				
			||||||
 | 
					#ifndef ENET_PRIORITY
 | 
				
			||||||
 | 
					    #define ENET_PRIORITY       (21U)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ENET_1588_PRIORITY
 | 
				
			||||||
 | 
					    #define ENET_1588_PRIORITY  (20U)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#ifndef ENET_PRIORITY
 | 
				
			||||||
 | 
					    #define ENET_PRIORITY       (15U)//(6U)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef ENET_1588_PRIORITY
 | 
				
			||||||
 | 
					    #define ENET_1588_PRIORITY  (5U)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*  Defines Ethernet Autonegotiation Timeout during initialization.
 | 
				
			||||||
 | 
					 *  Set it to 0 to disable the waiting. */
 | 
				
			||||||
 | 
					#ifndef ENET_ATONEGOTIATION_TIMEOUT
 | 
				
			||||||
 | 
					    #define ENET_ATONEGOTIATION_TIMEOUT     (0xFFFU)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Define those to better describe your network interface. */
 | 
				
			||||||
 | 
					#define IFNAME0 'e'
 | 
				
			||||||
 | 
					#define IFNAME1 'n'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
 | 
				
			||||||
 | 
					    #if defined(FSL_FEATURE_L2CACHE_LINESIZE_BYTE) \
 | 
				
			||||||
 | 
					        && ((!defined(FSL_SDK_DISBLE_L2CACHE_PRESENT)) || (FSL_SDK_DISBLE_L2CACHE_PRESENT == 0))
 | 
				
			||||||
 | 
					        #if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
 | 
				
			||||||
 | 
					            #define FSL_CACHE_LINESIZE_MAX MAX(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
 | 
				
			||||||
 | 
					            #define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_CACHE_LINESIZE_MAX)
 | 
				
			||||||
 | 
					        #else
 | 
				
			||||||
 | 
					            #define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_FEATURE_L2CACHE_LINESIZE_BYTE)
 | 
				
			||||||
 | 
					        #endif
 | 
				
			||||||
 | 
					    #elif defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
 | 
				
			||||||
 | 
					        #define FSL_ENET_BUFF_ALIGNMENT MAX(ENET_BUFF_ALIGNMENT, FSL_FEATURE_L1DCACHE_LINESIZE_BYTE)
 | 
				
			||||||
 | 
					    #else
 | 
				
			||||||
 | 
					        #define FSL_ENET_BUFF_ALIGNMENT ENET_BUFF_ALIGNMENT
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    #define FSL_ENET_BUFF_ALIGNMENT ENET_BUFF_ALIGNMENT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ENET_RING_NUM 1U
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef uint8_t rx_buffer_t[SDK_SIZEALIGN(ENET_RXBUFF_SIZE, FSL_ENET_BUFF_ALIGNMENT)];
 | 
				
			||||||
 | 
					typedef uint8_t tx_buffer_t[SDK_SIZEALIGN(ENET_TXBUFF_SIZE, FSL_ENET_BUFF_ALIGNMENT)];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0))
 | 
				
			||||||
 | 
					typedef struct mem_range
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t start;
 | 
				
			||||||
 | 
					    uint32_t end;
 | 
				
			||||||
 | 
					} mem_range_t;
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Helper struct to hold data for configuration of ethernet interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct ethernetif_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t phyAddress;
 | 
				
			||||||
 | 
					    clock_name_t clockName;
 | 
				
			||||||
 | 
					    uint8_t macAddress[NETIF_MAX_HWADDR_LEN];
 | 
				
			||||||
 | 
					#if (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 0))
 | 
				
			||||||
 | 
					    const mem_range_t *non_dma_memory;
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_SOC_LPC_ENET_COUNT */
 | 
				
			||||||
 | 
					} ethernetif_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif /* __cplusplus */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add()
 | 
				
			||||||
 | 
					 * if you initialize the first ENET interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif0_init(struct netif *netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if (defined(FSL_FEATURE_SOC_ENET_COUNT) && (FSL_FEATURE_SOC_ENET_COUNT > 1)) \
 | 
				
			||||||
 | 
					 || (defined(FSL_FEATURE_SOC_LPC_ENET_COUNT) && (FSL_FEATURE_SOC_LPC_ENET_COUNT > 1))
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This function should be passed as a parameter to netif_add()
 | 
				
			||||||
 | 
					 * if you initialize the second ENET interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif1_init(struct netif *netif);
 | 
				
			||||||
 | 
					#endif /* FSL_FEATURE_SOC_*_ENET_COUNT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This function should be called when a packet is ready to be read
 | 
				
			||||||
 | 
					 * from the interface.
 | 
				
			||||||
 | 
					 * It is used by bare-metal applications.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void ethernetif_input( struct netif *netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ETH_BSP_Config(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int32 lwip_obtain_semaphore(struct netif *netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* __cplusplus */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* ENET_ETHERNETIF_H */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,82 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2019 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file enet_ethernetif_priv.h
 | 
				
			||||||
 | 
					 * @brief ethernet drivers
 | 
				
			||||||
 | 
					 * @version 1.0
 | 
				
			||||||
 | 
					 * @author AIIT XUOS Lab
 | 
				
			||||||
 | 
					 * @date 2021.11.11
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef ENET_ETHERNETIF_PRIV_H
 | 
				
			||||||
 | 
					#define ENET_ETHERNETIF_PRIV_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "lwip/err.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ethernetif;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif /* __cplusplus */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                      const uint8_t enetIdx,
 | 
				
			||||||
 | 
					                      const ethernetif_config_t *ethernetifConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_enet_init(struct netif *netif, struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                          const ethernetif_config_t *ethernetifConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ethernetif_phy_init(struct ethernetif *ethernetif,
 | 
				
			||||||
 | 
					                         const ethernetif_config_t *ethernetifConfig,
 | 
				
			||||||
 | 
					                         enet_config_t *config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENET_Type **ethernetif_enet_ptr(struct ethernetif *ethernetif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV4 && LWIP_IGMP
 | 
				
			||||||
 | 
					err_t ethernetif_igmp_mac_filter(struct netif *netif, const ip4_addr_t *group,
 | 
				
			||||||
 | 
					                                 enum netif_mac_filter_action action);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LWIP_IPV6 && LWIP_IPV6_MLD
 | 
				
			||||||
 | 
					err_t ethernetif_mld_mac_filter(struct netif *netif, const ip6_addr_t *group,
 | 
				
			||||||
 | 
					                                enum netif_mac_filter_action action);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Should allocate a pbuf and transfer the bytes of the incoming
 | 
				
			||||||
 | 
					 * packet from the interface into the pbuf.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @return a pbuf filled with the received packet (including MAC header)
 | 
				
			||||||
 | 
					 *         NULL on memory error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct pbuf *ethernetif_linkinput(struct netif *netif);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This function should do the actual transmission of the packet. The packet is
 | 
				
			||||||
 | 
					 * contained in the pbuf that is passed to the function. This pbuf
 | 
				
			||||||
 | 
					 * might be chained.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param netif the lwip network interface structure for this ethernetif
 | 
				
			||||||
 | 
					 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 | 
				
			||||||
 | 
					 * @return ERR_OK if the packet could be sent
 | 
				
			||||||
 | 
					 *         an err_t value if the packet couldn't be sent
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 | 
				
			||||||
 | 
					 *       strange results. You might consider waiting for space in the DMA queue
 | 
				
			||||||
 | 
					 *       to become available since the stack doesn't retry to send a packet
 | 
				
			||||||
 | 
					 *       dropped because of memory failure (except for the TCP timers).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* __cplusplus */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* ENET_ETHERNETIF_PRIV_H */
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,830 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017-2018 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _FSL_SEMC_H_
 | 
				
			||||||
 | 
					#define _FSL_SEMC_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "fsl_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @addtogroup semc
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @name Driver version */
 | 
				
			||||||
 | 
					/*@{*/
 | 
				
			||||||
 | 
					/*! @brief SEMC driver version 2.0.4. */
 | 
				
			||||||
 | 
					#define FSL_SEMC_DRIVER_VERSION (MAKE_VERSION(2, 0, 4))
 | 
				
			||||||
 | 
					/*@}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC status. */
 | 
				
			||||||
 | 
					enum _semc_status
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidDeviceType            = MAKE_STATUS(kStatusGroup_SEMC, 0),
 | 
				
			||||||
 | 
					    kStatus_SEMC_IpCommandExecutionError      = MAKE_STATUS(kStatusGroup_SEMC, 1),
 | 
				
			||||||
 | 
					    kStatus_SEMC_AxiCommandExecutionError     = MAKE_STATUS(kStatusGroup_SEMC, 2),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidMemorySize            = MAKE_STATUS(kStatusGroup_SEMC, 3),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidIpcmdDataSize         = MAKE_STATUS(kStatusGroup_SEMC, 4),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidAddressPortWidth      = MAKE_STATUS(kStatusGroup_SEMC, 5),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidDataPortWidth         = MAKE_STATUS(kStatusGroup_SEMC, 6),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidSwPinmuxSelection     = MAKE_STATUS(kStatusGroup_SEMC, 7),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidBurstLength           = MAKE_STATUS(kStatusGroup_SEMC, 8),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidColumnAddressBitWidth = MAKE_STATUS(kStatusGroup_SEMC, 9),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidBaseAddress           = MAKE_STATUS(kStatusGroup_SEMC, 10),
 | 
				
			||||||
 | 
					    kStatus_SEMC_InvalidTimerSetting          = MAKE_STATUS(kStatusGroup_SEMC, 11),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC memory device type. */
 | 
				
			||||||
 | 
					typedef enum _semc_mem_type
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_MemType_SDRAM = 0, /*!< SDRAM */
 | 
				
			||||||
 | 
					    kSEMC_MemType_SRAM,      /*!< SRAM */
 | 
				
			||||||
 | 
					    kSEMC_MemType_NOR,       /*!< NOR */
 | 
				
			||||||
 | 
					    kSEMC_MemType_NAND,      /*!< NAND */
 | 
				
			||||||
 | 
					    kSEMC_MemType_8080       /*!< 8080. */
 | 
				
			||||||
 | 
					} semc_mem_type_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC WAIT/RDY polarity. */
 | 
				
			||||||
 | 
					typedef enum _semc_waitready_polarity
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_LowActive = 0, /*!< Low active. */
 | 
				
			||||||
 | 
					    kSEMC_HighActive,    /*!< High active. */
 | 
				
			||||||
 | 
					} semc_waitready_polarity_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC SDRAM Chip selection . */
 | 
				
			||||||
 | 
					typedef enum _semc_sdram_cs
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_SDRAM_CS0 = 0, /*!< SEMC SDRAM CS0. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAM_CS1,     /*!< SEMC SDRAM CS1. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAM_CS2,     /*!< SEMC SDRAM CS2. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAM_CS3      /*!< SEMC SDRAM CS3. */
 | 
				
			||||||
 | 
					} semc_sdram_cs_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NAND device type. */
 | 
				
			||||||
 | 
					typedef enum _semc_nand_access_type
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NAND_ACCESS_BY_AXI = 0,
 | 
				
			||||||
 | 
					    kSEMC_NAND_ACCESS_BY_IPCMD,
 | 
				
			||||||
 | 
					} semc_nand_access_type_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC interrupts . */
 | 
				
			||||||
 | 
					typedef enum _semc_interrupt_enable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_IPCmdDoneInterrupt = SEMC_INTEN_IPCMDDONEEN_MASK, /*!< Ip command done interrupt. */
 | 
				
			||||||
 | 
					    kSEMC_IPCmdErrInterrupt  = SEMC_INTEN_IPCMDERREN_MASK,  /*!< Ip command error interrupt. */
 | 
				
			||||||
 | 
					    kSEMC_AXICmdErrInterrupt = SEMC_INTEN_AXICMDERREN_MASK, /*!< AXI command error interrupt. */
 | 
				
			||||||
 | 
					    kSEMC_AXIBusErrInterrupt = SEMC_INTEN_AXIBUSERREN_MASK  /*!< AXI bus error interrupt. */
 | 
				
			||||||
 | 
					} semc_interrupt_enable_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command data size in bytes. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_datasize
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_IPcmdDataSize_1bytes = 1, /*!< The IP command data size 1 byte. */
 | 
				
			||||||
 | 
					    kSEMC_IPcmdDataSize_2bytes,     /*!< The IP command data size 2 byte. */
 | 
				
			||||||
 | 
					    kSEMC_IPcmdDataSize_3bytes,     /*!< The IP command data size 3 byte. */
 | 
				
			||||||
 | 
					    kSEMC_IPcmdDataSize_4bytes      /*!< The IP command data size 4 byte. */
 | 
				
			||||||
 | 
					} semc_ipcmd_datasize_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC auto-refresh timing. */
 | 
				
			||||||
 | 
					typedef enum _semc_refresh_time
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_RefreshThreeClocks = 0x0U, /*!< The refresh timing with three bus clocks. */
 | 
				
			||||||
 | 
					    kSEMC_RefreshSixClocks,          /*!< The refresh timing with six bus clocks. */
 | 
				
			||||||
 | 
					    kSEMC_RefreshNineClocks          /*!< The refresh timing with nine bus clocks. */
 | 
				
			||||||
 | 
					} semc_refresh_time_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief CAS latency */
 | 
				
			||||||
 | 
					typedef enum _semc_caslatency
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_LatencyOne = 1, /*!< Latency  1. */
 | 
				
			||||||
 | 
					    kSEMC_LatencyTwo,     /*!< Latency  2. */
 | 
				
			||||||
 | 
					    kSEMC_LatencyThree,   /*!< Latency  3. */
 | 
				
			||||||
 | 
					} semc_caslatency_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC sdram column address bit number. */
 | 
				
			||||||
 | 
					typedef enum _semc_sdram_column_bit_num
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_SdramColunm_12bit = 0x0U, /*!< 12 bit. */
 | 
				
			||||||
 | 
					    kSEMC_SdramColunm_11bit,        /*!< 11 bit. */
 | 
				
			||||||
 | 
					    kSEMC_SdramColunm_10bit,        /*!< 10 bit. */
 | 
				
			||||||
 | 
					    kSEMC_SdramColunm_9bit,         /*!< 9 bit. */
 | 
				
			||||||
 | 
					} semc_sdram_column_bit_num_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC sdram burst length. */
 | 
				
			||||||
 | 
					typedef enum _semc_sdram_burst_len
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Sdram_BurstLen1 = 0, /*!< Burst length 1*/
 | 
				
			||||||
 | 
					    kSEMC_Sdram_BurstLen2,     /*!< Burst length 2*/
 | 
				
			||||||
 | 
					    kSEMC_Sdram_BurstLen4,     /*!< Burst length 4*/
 | 
				
			||||||
 | 
					    kSEMC_Sdram_BurstLen8      /*!< Burst length 8*/
 | 
				
			||||||
 | 
					} sem_sdram_burst_len_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC nand column address bit number. */
 | 
				
			||||||
 | 
					typedef enum _semc_nand_column_bit_num
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NandColum_16bit = 0x0U, /*!< 16 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_15bit,        /*!< 15 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_14bit,        /*!< 14 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_13bit,        /*!< 13 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_12bit,        /*!< 12 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_11bit,        /*!< 11 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_10bit,        /*!< 10 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NandColum_9bit,         /*!< 9 bit. */
 | 
				
			||||||
 | 
					} semc_nand_column_bit_num_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC nand burst length. */
 | 
				
			||||||
 | 
					typedef enum _semc_nand_burst_len
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen1 = 0, /*!< Burst length 1*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen2,     /*!< Burst length 2*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen4,     /*!< Burst length 4*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen8,     /*!< Burst length 8*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen16,    /*!< Burst length 16*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen32,    /*!< Burst length 32*/
 | 
				
			||||||
 | 
					    kSEMC_Nand_BurstLen64     /*!< Burst length 64*/
 | 
				
			||||||
 | 
					} sem_nand_burst_len_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC nor/sram column address bit number. */
 | 
				
			||||||
 | 
					typedef enum _semc_norsram_column_bit_num
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NorColum_12bit = 0x0U, /*!< 12 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_11bit,        /*!< 11 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_10bit,        /*!< 10 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_9bit,         /*!< 9 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_8bit,         /*!< 8 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_7bit,         /*!< 7 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_6bit,         /*!< 6 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_5bit,         /*!< 5 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_4bit,         /*!< 4 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_3bit,         /*!< 3 bit. */
 | 
				
			||||||
 | 
					    kSEMC_NorColum_2bit          /*!< 2 bit. */
 | 
				
			||||||
 | 
					} semc_norsram_column_bit_num_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC nor/sram burst length. */
 | 
				
			||||||
 | 
					typedef enum _semc_norsram_burst_len
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen1 = 0, /*!< Burst length 1*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen2,     /*!< Burst length 2*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen4,     /*!< Burst length 4*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen8,     /*!< Burst length 8*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen16,    /*!< Burst length 16*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen32,    /*!< Burst length 32*/
 | 
				
			||||||
 | 
					    kSEMC_Nor_BurstLen64     /*!< Burst length 64*/
 | 
				
			||||||
 | 
					} sem_norsram_burst_len_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC dbi column address bit number. */
 | 
				
			||||||
 | 
					typedef enum _semc_dbi_column_bit_num
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_12bit = 0x0U, /*!< 12 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_11bit,        /*!< 11 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_10bit,        /*!< 10 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_9bit,         /*!< 9 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_8bit,         /*!< 8 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_7bit,         /*!< 7 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_6bit,         /*!< 6 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_5bit,         /*!< 5 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_4bit,         /*!< 4 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_3bit,         /*!< 3 bit. */
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Colum_2bit          /*!< 2 bit. */
 | 
				
			||||||
 | 
					} semc_dbi_column_bit_num_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC dbi burst length. */
 | 
				
			||||||
 | 
					typedef enum _semc_dbi_burst_len
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen1 = 0, /*!< Burst length 1*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen2,     /*!< Burst length 2*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_Dbi_BurstLen4, /*!< Burst length 4*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen8,     /*!< Burst length 8*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen16,    /*!< Burst length 16*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen32,    /*!< Burst length 32*/
 | 
				
			||||||
 | 
					    kSEMC_Dbi_BurstLen64     /*!< Burst length 64*/
 | 
				
			||||||
 | 
					} sem_dbi_burst_len_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IOMUXC. */
 | 
				
			||||||
 | 
					typedef enum _semc_iomux_pin
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_MUXA8   = SEMC_IOCR_MUX_A8_SHIFT,   /*!< MUX A8 pin. */
 | 
				
			||||||
 | 
					    kSEMC_MUXCSX0 = SEMC_IOCR_MUX_CSX0_SHIFT, /*!< MUX CSX0 pin */
 | 
				
			||||||
 | 
					    kSEMC_MUXCSX1 = SEMC_IOCR_MUX_CSX1_SHIFT, /*!< MUX CSX1 Pin.*/
 | 
				
			||||||
 | 
					    kSEMC_MUXCSX2 = SEMC_IOCR_MUX_CSX2_SHIFT, /*!< MUX CSX2 Pin. */
 | 
				
			||||||
 | 
					    kSEMC_MUXCSX3 = SEMC_IOCR_MUX_CSX3_SHIFT, /*!< MUX CSX3 Pin. */
 | 
				
			||||||
 | 
					    kSEMC_MUXRDY  = SEMC_IOCR_MUX_RDY_SHIFT   /*!< MUX RDY pin. */
 | 
				
			||||||
 | 
					} semc_iomux_pin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NOR/PSRAM Address bit 27 A27. */
 | 
				
			||||||
 | 
					typedef enum _semc_iomux_nora27_pin
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_MORA27_NONE    = 0,                        /*!< No NOR/SRAM A27 pin. */
 | 
				
			||||||
 | 
					    kSEMC_NORA27_MUXCSX3 = SEMC_IOCR_MUX_CSX3_SHIFT, /*!< MUX CSX3 Pin. */
 | 
				
			||||||
 | 
					    kSEMC_NORA27_MUXRDY  = SEMC_IOCR_MUX_RDY_SHIFT   /*!< MUX RDY pin. */
 | 
				
			||||||
 | 
					} semc_iomux_nora27_pin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC port size. */
 | 
				
			||||||
 | 
					typedef enum _semc_port_size
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_PortSize8Bit = 0, /*!< 8-Bit port size. */
 | 
				
			||||||
 | 
					    kSEMC_PortSize16Bit     /*!< 16-Bit port size. */
 | 
				
			||||||
 | 
					} smec_port_size_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC address mode. */
 | 
				
			||||||
 | 
					typedef enum _semc_addr_mode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_AddrDataMux = 0, /*!< SEMC address/data mux mode. */
 | 
				
			||||||
 | 
					    kSEMC_AdvAddrdataMux,  /*!< Advanced address/data mux mode. */
 | 
				
			||||||
 | 
					    kSEMC_AddrDataNonMux   /*!< Address/data non-mux mode. */
 | 
				
			||||||
 | 
					} semc_addr_mode_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC DQS read strobe mode. */
 | 
				
			||||||
 | 
					typedef enum _semc_dqs_mode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_Loopbackinternal = 0, /*!< Dummy read strobe loopbacked internally. */
 | 
				
			||||||
 | 
					    kSEMC_Loopbackdqspad,       /*!< Dummy read strobe loopbacked from DQS pad. */
 | 
				
			||||||
 | 
					} semc_dqs_mode_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC ADV signal active polarity. */
 | 
				
			||||||
 | 
					typedef enum _semc_adv_polarity
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_AdvActiveLow = 0, /*!< Adv active low. */
 | 
				
			||||||
 | 
					    kSEMC_AdvActivehigh,    /*!< Adv active low. */
 | 
				
			||||||
 | 
					} semc_adv_polarity_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC RDY signal active polarity. */
 | 
				
			||||||
 | 
					typedef enum _semc_rdy_polarity
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_RdyActiveLow = 0, /*!< Adv active low. */
 | 
				
			||||||
 | 
					    kSEMC_RdyActivehigh,    /*!< Adv active low. */
 | 
				
			||||||
 | 
					} semc_rdy_polarity_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command for NAND: address mode. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_nand_addrmode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_ColumnRow = 0x0U, /*!< Address mode: column and row address(5Byte-CA0/CA1/RA0/RA1/RA2). */
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_ColumnCA0,        /*!< Address mode: column address only(1 Byte-CA0).  */
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_ColumnCA0CA1,     /*!< Address mode: column address only(2 Byte-CA0/CA1). */
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_RawRA0,           /*!< Address mode: row address only(1 Byte-RA0). */
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_RawRA0RA1,        /*!< Address mode: row address only(2 Byte-RA0/RA1). */
 | 
				
			||||||
 | 
					    kSEMC_NANDAM_RawRA0RA1RA2      /*!< Address mode: row address only(3 Byte-RA0).  */
 | 
				
			||||||
 | 
					} semc_ipcmd_nand_addrmode_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command for NAND: command mode. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_nand_cmdmode
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_Command = 0x2U,      /*!< command. */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandHold,         /*!< Command hold. */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandAddress,      /*!< Command address. */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandAddressHold,  /*!< Command address hold.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandAddressRead,  /*!< Command address read.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandAddressWrite, /*!< Command address write.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandRead,         /*!< Command read.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_CommandWrite,        /*!< Command write.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_Read,                /*!< Read.  */
 | 
				
			||||||
 | 
					    kSEMC_NANDCM_Write                /*!< Write.  */
 | 
				
			||||||
 | 
					} semc_ipcmd_nand_cmdmode_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NAND address option. */
 | 
				
			||||||
 | 
					typedef enum _semc_nand_address_option
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_5byte_CA2RA3 = 0U, /*!< CA0+CA1+RA0+RA1+RA2 */
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_4byte_CA2RA2 = 2U, /*!< CA0+CA1+RA0+RA1 */
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_3byte_CA2RA1 = 4U, /*!< CA0+CA1+RA0 */
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_4byte_CA1RA3 = 1U, /*!< CA0+RA0+RA1+RA2 */
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_3byte_CA1RA2 = 3U, /*!< CA0+RA0+RA1 */
 | 
				
			||||||
 | 
					    kSEMC_NandAddrOption_2byte_CA1RA1 = 7U, /*!< CA0+RA0 */
 | 
				
			||||||
 | 
					} semc_nand_address_option_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command for NOR. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_nor_dbi
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_NORDBICM_Read = 0x2U, /*!< NOR read. */
 | 
				
			||||||
 | 
					    kSEMC_NORDBICM_Write        /*!< NOR write.  */
 | 
				
			||||||
 | 
					} semc_ipcmd_nor_dbi_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command for SRAM. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_sram
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_SRAMCM_ArrayRead = 0x2U, /*!< SRAM memory array read. */
 | 
				
			||||||
 | 
					    kSEMC_SRAMCM_ArrayWrite,       /*!< SRAM memory array write. */
 | 
				
			||||||
 | 
					    kSEMC_SRAMCM_RegRead,          /*!< SRAM memory register read. */
 | 
				
			||||||
 | 
					    kSEMC_SRAMCM_RegWrite          /*!< SRAM memory register write. */
 | 
				
			||||||
 | 
					} semc_ipcmd_sram_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC IP command for SDARM. */
 | 
				
			||||||
 | 
					typedef enum _semc_ipcmd_sdram
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Read = 0x8U, /*!< SDRAM memory read. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Write,       /*!< SDRAM memory write. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Modeset,     /*!< SDRAM MODE SET. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Active,      /*!< SDRAM active. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_AutoRefresh, /*!< SDRAM auto-refresh. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_SelfRefresh, /*!< SDRAM self-refresh. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Precharge,   /*!< SDRAM precharge. */
 | 
				
			||||||
 | 
					    kSEMC_SDRAMCM_Prechargeall /*!< SDRAM precharge all. */
 | 
				
			||||||
 | 
					} semc_ipcmd_sdram_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC SDRAM configuration structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. The memory size in the configuration is in the unit of KB. So memsize_kbytes
 | 
				
			||||||
 | 
					 * should be set as 2^2, 2^3, 2^4 .etc which is base 2KB exponential function.
 | 
				
			||||||
 | 
					 * Take refer to BR0~BR3 register in RM for details.
 | 
				
			||||||
 | 
					 * 2. The prescalePeriod_N16Cycle is in unit of 16 clock cycle. It is a exception for prescaleTimer_n16cycle = 0,
 | 
				
			||||||
 | 
					 * it means the prescaler timer period is 256 * 16 clock cycles. For precalerIf precalerTimer_n16cycle not equal to 0,
 | 
				
			||||||
 | 
					 * The  prescaler timer period is prescalePeriod_N16Cycle * 16 clock cycles.
 | 
				
			||||||
 | 
					 * idleTimeout_NprescalePeriod,  refreshUrgThreshold_NprescalePeriod, refreshPeriod_NprescalePeriod are
 | 
				
			||||||
 | 
					 * similar to prescalePeriod_N16Cycle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct _semc_sdram_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_iomux_pin csxPinMux;       /*!< CS pin mux. The kSEMC_MUXA8 is not valid in sdram pin mux setting. */
 | 
				
			||||||
 | 
					    uint32_t address;               /*!< The base address. */
 | 
				
			||||||
 | 
					    uint32_t memsize_kbytes;        /*!< The memory size in unit of kbytes. */
 | 
				
			||||||
 | 
					    smec_port_size_t portSize;      /*!< Port size. */
 | 
				
			||||||
 | 
					    sem_sdram_burst_len_t burstLen; /*!< Burst length. */
 | 
				
			||||||
 | 
					    semc_sdram_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
 | 
				
			||||||
 | 
					    semc_caslatency_t casLatency;                 /*!< CAS latency. */
 | 
				
			||||||
 | 
					    uint8_t tPrecharge2Act_Ns;                    /*!< Precharge to active wait time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tAct2ReadWrite_Ns;                    /*!< Act to read/write wait time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tRefreshRecovery_Ns;                  /*!< Refresh recovery time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tWriteRecovery_Ns;                    /*!< write recovery time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tCkeOff_Ns;                           /*!< CKE off minimum time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tAct2Prechage_Ns;                     /*!< Active to precharge in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tSelfRefRecovery_Ns;                  /*!< Self refresh recovery time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tRefresh2Refresh_Ns;                  /*!< Refresh to refresh wait time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint8_t tAct2Act_Ns;                          /*!< Active to active wait time in unit of nanosecond. */
 | 
				
			||||||
 | 
					    uint32_t tPrescalePeriod_Ns;     /*!< Prescaler timer period should not be larger than 256 * 16 * clock cycle. */
 | 
				
			||||||
 | 
					    uint32_t tIdleTimeout_Ns;        /*!< Idle timeout in unit of prescale time period. */
 | 
				
			||||||
 | 
					    uint32_t refreshPeriod_nsPerRow; /*!< Refresh timer period like 64ms * 1000000/8192 . */
 | 
				
			||||||
 | 
					    uint32_t refreshUrgThreshold;    /*!< Refresh urgent threshold. */
 | 
				
			||||||
 | 
					    uint8_t refreshBurstLen;         /*!< Refresh burst length. */
 | 
				
			||||||
 | 
					} semc_sdram_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NAND device timing configuration structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_nand_timing_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t tCeSetup_Ns;        /*!< CE setup time: tCS. */
 | 
				
			||||||
 | 
					    uint8_t tCeHold_Ns;         /*!< CE hold time: tCH. */
 | 
				
			||||||
 | 
					    uint8_t tCeInterval_Ns;     /*!< CE interval time:tCEITV. */
 | 
				
			||||||
 | 
					    uint8_t tWeLow_Ns;          /*!< WE low time: tWP. */
 | 
				
			||||||
 | 
					    uint8_t tWeHigh_Ns;         /*!< WE high time: tWH. */
 | 
				
			||||||
 | 
					    uint8_t tReLow_Ns;          /*!< RE low time: tRP. */
 | 
				
			||||||
 | 
					    uint8_t tReHigh_Ns;         /*!< RE high time: tREH. */
 | 
				
			||||||
 | 
					    uint8_t tTurnAround_Ns;     /*!< Turnaround time for async mode: tTA. */
 | 
				
			||||||
 | 
					    uint8_t tWehigh2Relow_Ns;   /*!< WE# high to RE# wait time: tWHR. */
 | 
				
			||||||
 | 
					    uint8_t tRehigh2Welow_Ns;   /*!< RE# high to WE# low wait time: tRHW. */
 | 
				
			||||||
 | 
					    uint8_t tAle2WriteStart_Ns; /*!< ALE to write start wait time: tADL. */
 | 
				
			||||||
 | 
					    uint8_t tReady2Relow_Ns;    /*!< Ready to RE# low min wait time: tRR. */
 | 
				
			||||||
 | 
					    uint8_t tWehigh2Busy_Ns;    /*!< WE# high to busy wait time: tWB. */
 | 
				
			||||||
 | 
					} semc_nand_timing_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NAND configuration structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_nand_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_iomux_pin cePinMux;    /*!< The CE pin mux setting. The kSEMC_MUXRDY is not valid for CE pin setting. */
 | 
				
			||||||
 | 
					    uint32_t axiAddress;        /*!< The base address for AXI nand. */
 | 
				
			||||||
 | 
					    uint32_t axiMemsize_kbytes; /*!< The memory size in unit of kbytes for AXI nand. */
 | 
				
			||||||
 | 
					    uint32_t ipgAddress;        /*!< The base address for IPG nand . */
 | 
				
			||||||
 | 
					    uint32_t ipgMemsize_kbytes; /*!< The memory size in unit of kbytes for IPG nand. */
 | 
				
			||||||
 | 
					    semc_rdy_polarity_t rdyactivePolarity;       /*!< Wait ready polarity. */
 | 
				
			||||||
 | 
					    bool edoModeEnabled;                         /*!< EDO mode enabled. */
 | 
				
			||||||
 | 
					    semc_nand_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
 | 
				
			||||||
 | 
					    semc_nand_address_option_t arrayAddrOption;  /*!< Address option. */
 | 
				
			||||||
 | 
					    sem_nand_burst_len_t burstLen;               /*!< Burst length. */
 | 
				
			||||||
 | 
					    smec_port_size_t portSize;                   /*!< Port size. */
 | 
				
			||||||
 | 
					    semc_nand_timing_config_t *timingConfig;     /*!< SEMC nand timing configuration. */
 | 
				
			||||||
 | 
					} semc_nand_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC NOR configuration structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_nor_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_iomux_pin cePinMux;                        /*!< The CE# pin mux setting. */
 | 
				
			||||||
 | 
					    semc_iomux_nora27_pin addr27;                   /*!< The Addr bit 27 pin mux setting. */
 | 
				
			||||||
 | 
					    uint32_t address;                               /*!< The base address. */
 | 
				
			||||||
 | 
					    uint32_t memsize_kbytes;                        /*!< The memory size in unit of kbytes. */
 | 
				
			||||||
 | 
					    uint8_t addrPortWidth;                          /*!< The address port width. */
 | 
				
			||||||
 | 
					    semc_rdy_polarity_t rdyactivePolarity;          /*!< Wait ready polarity. */
 | 
				
			||||||
 | 
					    semc_adv_polarity_t advActivePolarity;          /*!< ADV# polarity. */
 | 
				
			||||||
 | 
					    semc_norsram_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
 | 
				
			||||||
 | 
					    semc_addr_mode_t addrMode;                      /*!< Address mode. */
 | 
				
			||||||
 | 
					    sem_norsram_burst_len_t burstLen;               /*!< Burst length. */
 | 
				
			||||||
 | 
					    smec_port_size_t portSize;                      /*!< Port size. */
 | 
				
			||||||
 | 
					    uint8_t tCeSetup_Ns;                            /*!< The CE setup time. */
 | 
				
			||||||
 | 
					    uint8_t tCeHold_Ns;                             /*!< The CE hold time. */
 | 
				
			||||||
 | 
					    uint8_t tCeInterval_Ns;                         /*!< CE interval minimum time. */
 | 
				
			||||||
 | 
					    uint8_t tAddrSetup_Ns;                          /*!< The address setup time. */
 | 
				
			||||||
 | 
					    uint8_t tAddrHold_Ns;                           /*!< The address hold time. */
 | 
				
			||||||
 | 
					    uint8_t tWeLow_Ns;                              /*!< WE low time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tWeHigh_Ns;                             /*!< WE high time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tReLow_Ns;                              /*!< RE low time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tReHigh_Ns;                             /*!< RE high time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tTurnAround_Ns;                         /*!< Turnaround time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tAddr2WriteHold_Ns;                     /*!< Address to write data hold time for async mode. */
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDS_TIME)
 | 
				
			||||||
 | 
					    uint8_t tWriteSetup_Ns; /*!< Write data setup time for sync mode.*/
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if defined(FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME) && (FSL_FEATURE_SEMC_HAS_NOR_WDH_TIME)
 | 
				
			||||||
 | 
					    uint8_t tWriteHold_Ns; /*!< Write hold time for sync mode. */
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    uint8_t latencyCount; /*!< Latency count for sync mode. */
 | 
				
			||||||
 | 
					    uint8_t readCycle;    /*!< Read cycle time for sync mode. */
 | 
				
			||||||
 | 
					} semc_nor_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC SRAM  configuration structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_sram_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_iomux_pin cePinMux;               /*!< The CE# pin mux setting. */
 | 
				
			||||||
 | 
					    semc_iomux_nora27_pin addr27;          /*!< The Addr bit 27 pin mux setting. */
 | 
				
			||||||
 | 
					    uint32_t address;                      /*!< The base address. */
 | 
				
			||||||
 | 
					    uint32_t memsize_kbytes;               /*!< The memory size in unit of kbytes. */
 | 
				
			||||||
 | 
					    uint8_t addrPortWidth;                 /*!< The address port width. */
 | 
				
			||||||
 | 
					    semc_adv_polarity_t advActivePolarity; /*!< ADV# polarity 1: active high, 0: active low. */
 | 
				
			||||||
 | 
					    semc_addr_mode_t addrMode;             /*!< Address mode. */
 | 
				
			||||||
 | 
					    sem_norsram_burst_len_t burstLen;      /*!< Burst length. */
 | 
				
			||||||
 | 
					    smec_port_size_t portSize;             /*!< Port size. */
 | 
				
			||||||
 | 
					    uint8_t tCeSetup_Ns;                   /*!< The CE setup time. */
 | 
				
			||||||
 | 
					    uint8_t tCeHold_Ns;                    /*!< The CE hold time. */
 | 
				
			||||||
 | 
					    uint8_t tCeInterval_Ns;                /*!< CE interval minimum time. */
 | 
				
			||||||
 | 
					    uint8_t tAddrSetup_Ns;                 /*!< The address setup time. */
 | 
				
			||||||
 | 
					    uint8_t tAddrHold_Ns;                  /*!< The address hold time. */
 | 
				
			||||||
 | 
					    uint8_t tWeLow_Ns;                     /*!< WE low time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tWeHigh_Ns;                    /*!< WE high time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tReLow_Ns;                     /*!< RE low time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tReHigh_Ns;                    /*!< RE high time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tTurnAround_Ns;                /*!< Turnaround time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tAddr2WriteHold_Ns;            /*!< Address to write data hold time for async mode. */
 | 
				
			||||||
 | 
					    uint8_t tWriteSetup_Ns;                /*!< Write data setup time for sync mode.*/
 | 
				
			||||||
 | 
					    uint8_t tWriteHold_Ns;                 /*!< Write hold time for sync mode. */
 | 
				
			||||||
 | 
					    uint8_t latencyCount;                  /*!< Latency count for sync mode. */
 | 
				
			||||||
 | 
					    uint8_t readCycle;                     /*!< Read cycle time for sync mode. */
 | 
				
			||||||
 | 
					} semc_sram_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC DBI configuration structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_dbi_config
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_iomux_pin csxPinMux;                   /*!< The CE# pin mux. */
 | 
				
			||||||
 | 
					    uint32_t address;                           /*!< The base address. */
 | 
				
			||||||
 | 
					    uint32_t memsize_kbytes;                    /*!< The memory size in unit of 4kbytes. */
 | 
				
			||||||
 | 
					    semc_dbi_column_bit_num_t columnAddrBitNum; /*!< Column address bit number. */
 | 
				
			||||||
 | 
					    sem_dbi_burst_len_t burstLen;               /*!< Burst length. */
 | 
				
			||||||
 | 
					    smec_port_size_t portSize;                  /*!< Port size. */
 | 
				
			||||||
 | 
					    uint8_t tCsxSetup_Ns;                       /*!< The CSX setup time. */
 | 
				
			||||||
 | 
					    uint8_t tCsxHold_Ns;                        /*!< The CSX hold time. */
 | 
				
			||||||
 | 
					    uint8_t tWexLow_Ns;                         /*!< WEX low time. */
 | 
				
			||||||
 | 
					    uint8_t tWexHigh_Ns;                        /*!< WEX high time. */
 | 
				
			||||||
 | 
					    uint8_t tRdxLow_Ns;                         /*!< RDX low time. */
 | 
				
			||||||
 | 
					    uint8_t tRdxHigh_Ns;                        /*!< RDX high time. */
 | 
				
			||||||
 | 
					    uint8_t tCsxInterval_Ns;                    /*!< Write data setup time.*/
 | 
				
			||||||
 | 
					} semc_dbi_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC AXI queue a weight setting structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_queuea_weight_struct
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t qos : 4;              /*!< weight of qos for queue 0 . */
 | 
				
			||||||
 | 
					    uint32_t aging : 4;            /*!< weight of aging for queue 0.*/
 | 
				
			||||||
 | 
					    uint32_t slaveHitSwith : 8;    /*!< weight of read/write switch for queue 0.*/
 | 
				
			||||||
 | 
					    uint32_t slaveHitNoswitch : 8; /*!< weight of read/write no switch for queue 0  .*/
 | 
				
			||||||
 | 
					} semc_queuea_weight_struct_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC AXI queue a weight setting union. */
 | 
				
			||||||
 | 
					typedef union _semc_queuea_weight
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_queuea_weight_struct_t queueaConfig; /*!< Structure configuration for queueA. */
 | 
				
			||||||
 | 
					    uint32_t queueaValue; /*!< Configuration value for queueA which could directly write to the reg. */
 | 
				
			||||||
 | 
					} semc_queuea_weight_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC AXI queue b weight setting structure. */
 | 
				
			||||||
 | 
					typedef struct _semc_queueb_weight_struct
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t qos : 4;           /*!< weight of qos for queue 1. */
 | 
				
			||||||
 | 
					    uint32_t aging : 4;         /*!< weight of aging for queue 1.*/
 | 
				
			||||||
 | 
					    uint32_t slaveHitSwith : 8; /*!< weight of read/write switch for queue 1.*/
 | 
				
			||||||
 | 
					    uint32_t weightPagehit : 8; /*!< weight of page hit for queue 1 only .*/
 | 
				
			||||||
 | 
					    uint32_t bankRotation : 8;  /*!< weight of bank rotation for queue 1 only .*/
 | 
				
			||||||
 | 
					} semc_queueb_weight_struct_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC AXI queue b weight setting union. */
 | 
				
			||||||
 | 
					typedef union _semc_queueb_weight
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_queueb_weight_struct_t queuebConfig; /*!< Structure configuration for queueB. */
 | 
				
			||||||
 | 
					    uint32_t queuebValue; /*!< Configuration value for queueB which could directly write to the reg. */
 | 
				
			||||||
 | 
					} semc_queueb_weight_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @brief SEMC AXI queue weight setting. */
 | 
				
			||||||
 | 
					typedef struct _semc_axi_queueweight
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_queuea_weight_t queueaWeight; /*!< Weight settings for queue a. */
 | 
				
			||||||
 | 
					    semc_queueb_weight_t queuebWeight; /*!< Weight settings for queue b. */
 | 
				
			||||||
 | 
					} semc_axi_queueweight_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC configuration structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * busTimeoutCycles: when busTimeoutCycles is zero, the bus timeout cycle is
 | 
				
			||||||
 | 
					 * 255*1024. otherwise the bus timeout cycles is busTimeoutCycles*1024.
 | 
				
			||||||
 | 
					 * cmdTimeoutCycles: is used for command execution timeout cycles. it's
 | 
				
			||||||
 | 
					 * similar to the busTimeoutCycles.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct _semc_config_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_dqs_mode_t dqsMode;            /*!< Dummy read strobe mode: use enum in "semc_dqs_mode_t". */
 | 
				
			||||||
 | 
					    uint8_t cmdTimeoutCycles;           /*!< Command execution timeout cycles. */
 | 
				
			||||||
 | 
					    uint8_t busTimeoutCycles;           /*!< Bus timeout cycles. */
 | 
				
			||||||
 | 
					    semc_axi_queueweight_t queueWeight; /*!< AXI queue weight. */
 | 
				
			||||||
 | 
					} semc_config_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * API
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @name SEMC Initialization and De-initialization
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Gets the SEMC default basic configuration structure.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The purpose of this API is to get the default SEMC
 | 
				
			||||||
 | 
					 * configure structure for SEMC_Init(). User may use the initialized
 | 
				
			||||||
 | 
					 * structure unchanged in SEMC_Init(), or modify some fields of the
 | 
				
			||||||
 | 
					 * structure before calling SEMC_Init().
 | 
				
			||||||
 | 
					 * Example:
 | 
				
			||||||
 | 
					   @code
 | 
				
			||||||
 | 
					   semc_config_t config;
 | 
				
			||||||
 | 
					   SEMC_GetDefaultConfig(&config);
 | 
				
			||||||
 | 
					   @endcode
 | 
				
			||||||
 | 
					 * @param config The SEMC configuration structure pointer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void SEMC_GetDefaultConfig(semc_config_t *config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Initializes SEMC.
 | 
				
			||||||
 | 
					 * This function ungates the SEMC clock and initializes SEMC.
 | 
				
			||||||
 | 
					 * This function must be called before calling any other SEMC driver functions.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param configure The SEMC configuration structure pointer.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void SEMC_Init(SEMC_Type *base, semc_config_t *configure);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Deinitializes the SEMC module and gates the clock.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function gates the SEMC clock. As a result, the SEMC module doesn't work after
 | 
				
			||||||
 | 
					 * calling this function, for some IDE, calling this API may cause the next downloading
 | 
				
			||||||
 | 
					 * operation failed. so, please call this API cautiously. Additional, users can
 | 
				
			||||||
 | 
					 * using "#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL (1)" to disable the clock control
 | 
				
			||||||
 | 
					 * operation in drivers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void SEMC_Deinit(SEMC_Type *base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @name SEMC Configuration Operation For Each Memory Type
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Configures SDRAM controller in SEMC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param cs The chip selection.
 | 
				
			||||||
 | 
					 * @param config The sdram configuration.
 | 
				
			||||||
 | 
					 * @param clkSrc_Hz The SEMC clock frequency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Configures NAND controller in SEMC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param config The nand configuration.
 | 
				
			||||||
 | 
					 * @param clkSrc_Hz The SEMC clock frequency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_ConfigureNAND(SEMC_Type *base, semc_nand_config_t *config, uint32_t clkSrc_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Configures NOR controller in SEMC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param config The nor configuration.
 | 
				
			||||||
 | 
					 * @param clkSrc_Hz The SEMC clock frequency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_ConfigureNOR(SEMC_Type *base, semc_nor_config_t *config, uint32_t clkSrc_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Configures SRAM controller in SEMC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param config The sram configuration.
 | 
				
			||||||
 | 
					 * @param clkSrc_Hz The SEMC clock frequency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_ConfigureSRAM(SEMC_Type *base, semc_sram_config_t *config, uint32_t clkSrc_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Configures DBI controller in SEMC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param config The dbi configuration.
 | 
				
			||||||
 | 
					 * @param clkSrc_Hz The SEMC clock frequency.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_ConfigureDBI(SEMC_Type *base, semc_dbi_config_t *config, uint32_t clkSrc_Hz);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @name SEMC Interrupt Operation
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Enables the SEMC interrupt.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function enables the SEMC interrupts according to the provided mask. The mask
 | 
				
			||||||
 | 
					 * is a logical OR of enumeration members. See @ref semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 * For example, to enable the IP command done and error interrupt, do the following.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *     SEMC_EnableInterrupts(ENET, kSEMC_IPCmdDoneInterrupt | kSEMC_IPCmdErrInterrupt);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param mask  SEMC interrupts to enable. This is a logical OR of the
 | 
				
			||||||
 | 
					 *             enumeration :: semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void SEMC_EnableInterrupts(SEMC_Type *base, uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    base->INTEN |= mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Disables the SEMC interrupt.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function disables the SEMC interrupts according to the provided mask. The mask
 | 
				
			||||||
 | 
					 * is a logical OR of enumeration members. See @ref semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 * For example, to disable the IP command done and error interrupt, do the following.
 | 
				
			||||||
 | 
					 * @code
 | 
				
			||||||
 | 
					 *     SEMC_DisableInterrupts(ENET, kSEMC_IPCmdDoneInterrupt | kSEMC_IPCmdErrInterrupt);
 | 
				
			||||||
 | 
					 * @endcode
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param mask  SEMC interrupts to disable. This is a logical OR of the
 | 
				
			||||||
 | 
					 *             enumeration :: semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void SEMC_DisableInterrupts(SEMC_Type *base, uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    base->INTEN &= ~mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Gets the SEMC status.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function gets the SEMC interrupts event status.
 | 
				
			||||||
 | 
					 * User can use the a logical OR of enumeration member as a mask.
 | 
				
			||||||
 | 
					 * See @ref semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @return status flag, use status flag in semc_interrupt_enable_t to get the related status.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline bool SEMC_GetStatusFlag(SEMC_Type *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return base->INTR;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Clears the SEMC status flag state.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The following status register flags can be cleared SEMC interrupt status.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base SEMC base pointer
 | 
				
			||||||
 | 
					 * @param mask The status flag mask, a logical OR of enumeration member @ref semc_interrupt_enable_t.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void SEMC_ClearStatusFlags(SEMC_Type *base, uint32_t mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    base->INTR |= mask;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @name SEMC Memory Access Operation
 | 
				
			||||||
 | 
					 * @{
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Check if SEMC is in idle.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @return  True SEMC is in idle, false is not in idle.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline bool SEMC_IsInIdle(SEMC_Type *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (base->STS0 & SEMC_STS0_IDLE_MASK) ? true : false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC IP command access.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param type  SEMC memory type. refer to "semc_mem_type_t"
 | 
				
			||||||
 | 
					 * @param address  SEMC device address.
 | 
				
			||||||
 | 
					 * @param command  SEMC IP command.
 | 
				
			||||||
 | 
					 * For NAND device, we should use the SEMC_BuildNandIPCommand to get the right nand command.
 | 
				
			||||||
 | 
					 * For NOR/DBI device, take refer to "semc_ipcmd_nor_dbi_t".
 | 
				
			||||||
 | 
					 * For SRAM device, take refer to "semc_ipcmd_sram_t".
 | 
				
			||||||
 | 
					 * For SDRAM device, take refer to "semc_ipcmd_sdram_t".
 | 
				
			||||||
 | 
					 * @param write  Data for write access.
 | 
				
			||||||
 | 
					 * @param read   Data pointer for read data out.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_SendIPCommand(
 | 
				
			||||||
 | 
					    SEMC_Type *base, semc_mem_type_t type, uint32_t address, uint16_t command, uint32_t write, uint32_t *read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Build SEMC IP command for NAND.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function build SEMC NAND IP command. The command is build of user command code,
 | 
				
			||||||
 | 
					 * SEMC address mode and SEMC command mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param userCommand  NAND device normal command.
 | 
				
			||||||
 | 
					 * @param addrMode  NAND address mode. Refer to "semc_ipcmd_nand_addrmode_t".
 | 
				
			||||||
 | 
					 * @param cmdMode   NAND command mode. Refer to "semc_ipcmd_nand_cmdmode_t".
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint16_t SEMC_BuildNandIPCommand(uint8_t userCommand,
 | 
				
			||||||
 | 
					                                               semc_ipcmd_nand_addrmode_t addrMode,
 | 
				
			||||||
 | 
					                                               semc_ipcmd_nand_cmdmode_t cmdMode)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (uint16_t)((uint16_t)userCommand << 8) | (uint16_t)(addrMode << 4) | ((uint8_t)cmdMode & 0x0Fu);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Check if the NAND device is ready.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @return  True NAND is ready, false NAND is not ready.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline bool SEMC_IsNandReady(SEMC_Type *base)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (base->STS0 & SEMC_STS0_NARDY_MASK) ? true : false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC NAND device memory write through IP command.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param address  SEMC NAND device address.
 | 
				
			||||||
 | 
					 * @param data  Data for write access.
 | 
				
			||||||
 | 
					 * @param size_bytes   Data length.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_IPCommandNandWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC NAND device memory read through IP command.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param address  SEMC NAND device address.
 | 
				
			||||||
 | 
					 * @param data  Data pointer for data read out.
 | 
				
			||||||
 | 
					 * @param size_bytes   Data length.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_IPCommandNandRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC NOR device memory write through IP command.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param address  SEMC NOR device address.
 | 
				
			||||||
 | 
					 * @param data  Data for write access.
 | 
				
			||||||
 | 
					 * @param size_bytes   Data length.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_IPCommandNorWrite(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief SEMC NOR device memory read through IP command.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param base  SEMC peripheral base address.
 | 
				
			||||||
 | 
					 * @param address  SEMC NOR device address.
 | 
				
			||||||
 | 
					 * @param data  Data pointer for data read out.
 | 
				
			||||||
 | 
					 * @param size_bytes   Data length.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					status_t SEMC_IPCommandNorRead(SEMC_Type *base, uint32_t address, uint8_t *data, uint32_t size_bytes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* @} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(__cplusplus)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*! @}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _FSL_SEMC_H_*/
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,9 @@
 | 
				
			||||||
 | 
					config BSP_USING_EXTSRAM
 | 
				
			||||||
 | 
					    bool "config semc extern sram"
 | 
				
			||||||
 | 
					    default n
 | 
				
			||||||
 | 
					    select MEM_EXTERN_SRAM
 | 
				
			||||||
 | 
					    if BSP_USING_EXTSRAM
 | 
				
			||||||
 | 
					        config EXTSRAM_MAX_NUM
 | 
				
			||||||
 | 
					            int "config extsram chip num"
 | 
				
			||||||
 | 
					            default 4
 | 
				
			||||||
 | 
					    endif
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					SRC_FILES := connect_semc.c fsl_semc.c semc_externsdram_test.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(KERNEL_ROOT)/compiler.mk
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					#include "fsl_semc.h"
 | 
				
			||||||
 | 
					#include "clock_config.h"
 | 
				
			||||||
 | 
					#include <xs_base.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXAMPLE_SEMC SEMC
 | 
				
			||||||
 | 
					#define EXAMPLE_SEMC_START_ADDRESS (0x80000000U)
 | 
				
			||||||
 | 
					#define EXAMPLE_SEMC_CLK_FREQ CLOCK_GetFreq(kCLOCK_SemcClk)
 | 
				
			||||||
 | 
					#define SEMC_SRAM_SIZE (32 * 1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					status_t BOARD_InitSEMC(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    semc_config_t config;
 | 
				
			||||||
 | 
					    semc_sdram_config_t sdramconfig;
 | 
				
			||||||
 | 
					    uint32_t clockFrq = EXAMPLE_SEMC_CLK_FREQ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initializes the MAC configure structure to zero. */
 | 
				
			||||||
 | 
					    memset(&config, 0, sizeof(semc_config_t));
 | 
				
			||||||
 | 
					    memset(&sdramconfig, 0, sizeof(semc_sdram_config_t));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Initialize SEMC. */
 | 
				
			||||||
 | 
					    SEMC_GetDefaultConfig(&config);
 | 
				
			||||||
 | 
					    config.dqsMode = kSEMC_Loopbackdqspad; /* For more accurate timing. */
 | 
				
			||||||
 | 
					    SEMC_Init(SEMC, &config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Configure SDRAM. */
 | 
				
			||||||
 | 
					    sdramconfig.csxPinMux           = kSEMC_MUXCSX0;
 | 
				
			||||||
 | 
					    sdramconfig.address             = 0x80000000;
 | 
				
			||||||
 | 
					    sdramconfig.memsize_kbytes      = 32 * 1024; /* 32MB = 32*1024*1KBytes*/
 | 
				
			||||||
 | 
					    sdramconfig.portSize            = kSEMC_PortSize16Bit;
 | 
				
			||||||
 | 
					    sdramconfig.burstLen            = kSEMC_Sdram_BurstLen8;
 | 
				
			||||||
 | 
					    sdramconfig.columnAddrBitNum    = kSEMC_SdramColunm_9bit;
 | 
				
			||||||
 | 
					    sdramconfig.casLatency          = kSEMC_LatencyThree;
 | 
				
			||||||
 | 
					    sdramconfig.tPrecharge2Act_Ns   = 18; /* Trp 18ns */
 | 
				
			||||||
 | 
					    sdramconfig.tAct2ReadWrite_Ns   = 18; /* Trcd 18ns */
 | 
				
			||||||
 | 
					    sdramconfig.tRefreshRecovery_Ns = 67; /* Use the maximum of the (Trfc , Txsr). */
 | 
				
			||||||
 | 
					    sdramconfig.tWriteRecovery_Ns   = 12; /* 12ns */
 | 
				
			||||||
 | 
					    sdramconfig.tCkeOff_Ns =
 | 
				
			||||||
 | 
					        42; /* The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.*/
 | 
				
			||||||
 | 
					    sdramconfig.tAct2Prechage_Ns       = 42; /* Tras 42ns */
 | 
				
			||||||
 | 
					    sdramconfig.tSelfRefRecovery_Ns    = 67;
 | 
				
			||||||
 | 
					    sdramconfig.tRefresh2Refresh_Ns    = 60;
 | 
				
			||||||
 | 
					    sdramconfig.tAct2Act_Ns            = 60;
 | 
				
			||||||
 | 
					    sdramconfig.tPrescalePeriod_Ns     = 160 * (1000000000 / clockFrq);
 | 
				
			||||||
 | 
					    sdramconfig.refreshPeriod_nsPerRow = 64 * 1000000 / 8192; /* 64ms/8192 */
 | 
				
			||||||
 | 
					    sdramconfig.refreshUrgThreshold    = sdramconfig.refreshPeriod_nsPerRow;
 | 
				
			||||||
 | 
					    sdramconfig.refreshBurstLen        = 1;
 | 
				
			||||||
 | 
					    return SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef BSP_USING_EXTSRAM
 | 
				
			||||||
 | 
					int ExtSramInit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    extern void ExtSramInitBoardMemory(void *start_phy_address, void *end_phy_address, uint8 extsram_idx);
 | 
				
			||||||
 | 
					    ExtSramInitBoardMemory((void*)(EXAMPLE_SEMC_START_ADDRESS), (void*)((EXAMPLE_SEMC_START_ADDRESS + SEMC_SRAM_SIZE)), kSEMC_SDRAM_CS0);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -0,0 +1,180 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2017 NXP
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "board.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EXAMPLE_SEMC_START_ADDRESS (0x80000000U)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SEMC_EXAMPLE_DATALEN (0x1000U)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Prototypes
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					static void SEMC_SDRAMReadWrite32Bit(void);
 | 
				
			||||||
 | 
					static void SEMC_SDRAMReadWrite16Bit(void);
 | 
				
			||||||
 | 
					static void SEMC_SDRAMReadWrite8Bit(void);
 | 
				
			||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Variables
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t sdram_writeBuffer[SEMC_EXAMPLE_DATALEN];
 | 
				
			||||||
 | 
					uint32_t sdram_readBuffer[SEMC_EXAMPLE_DATALEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * @brief Main function
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int semc_externsram_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Example Start!\r\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* 32Bit data read and write. */
 | 
				
			||||||
 | 
					    SEMC_SDRAMReadWrite32Bit();
 | 
				
			||||||
 | 
					    /* 16Bit data read and write. */
 | 
				
			||||||
 | 
					    SEMC_SDRAMReadWrite16Bit();
 | 
				
			||||||
 | 
					    /* 8Bit data read and write. */
 | 
				
			||||||
 | 
					    SEMC_SDRAMReadWrite8Bit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Example End.\r\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),semc_externsram_test, semc_externsram_test,  semc_externsram_test );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SEMC_SDRAMReadWrite32Bit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t index;
 | 
				
			||||||
 | 
					    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
 | 
				
			||||||
 | 
					    uint32_t *sdram  = (uint32_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
 | 
				
			||||||
 | 
					    int result      = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Memory 32 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					    /* Prepare data and write to SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_writeBuffer[index] = index;
 | 
				
			||||||
 | 
					        sdram[index]             = sdram_writeBuffer[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Read 32 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					    /* Read data from the SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_readBuffer[index] = sdram[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Start!\r\n");
 | 
				
			||||||
 | 
					    /* Compare the two buffers. */
 | 
				
			||||||
 | 
					    while (datalen--)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = -1;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result < 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Failed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 32 bit Data Write and Read Compare Succeed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void SEMC_SDRAMReadWrite16Bit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t index;
 | 
				
			||||||
 | 
					    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
 | 
				
			||||||
 | 
					    uint16_t *sdram  = (uint16_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
 | 
				
			||||||
 | 
					    int result      = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Memory 16 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
 | 
				
			||||||
 | 
					    memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Prepare data and write to SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_writeBuffer[index] = index % 0xFFFF;
 | 
				
			||||||
 | 
					        sdram[index]             = sdram_writeBuffer[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Read 16 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					    /* Read data from the SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_readBuffer[index] = sdram[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Start!\r\n");
 | 
				
			||||||
 | 
					    /* Compare the two buffers. */
 | 
				
			||||||
 | 
					    while (datalen--)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = -1;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result < 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Failed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 16 bit Data Write and Read Compare Succeed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void SEMC_SDRAMReadWrite8Bit(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t index;
 | 
				
			||||||
 | 
					    uint32_t datalen = SEMC_EXAMPLE_DATALEN;
 | 
				
			||||||
 | 
					    uint8_t *sdram   = (uint8_t *)EXAMPLE_SEMC_START_ADDRESS; /* SDRAM start address. */
 | 
				
			||||||
 | 
					    int result      = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Memory 8 bit Write Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(sdram_writeBuffer, 0, sizeof(sdram_writeBuffer));
 | 
				
			||||||
 | 
					    memset(sdram_readBuffer, 0, sizeof(sdram_readBuffer));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Prepare data and write to SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_writeBuffer[index] = index % 0x100;
 | 
				
			||||||
 | 
					        sdram[index]             = sdram_writeBuffer[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM Read 8 bit Data Start, Start Address 0x%x, Data Length %d !\r\n", sdram, datalen);
 | 
				
			||||||
 | 
					    /* Read data from the SDRAM. */
 | 
				
			||||||
 | 
					    for (index = 0; index < datalen; index++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        sdram_readBuffer[index] = sdram[index];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Start!\r\n");
 | 
				
			||||||
 | 
					    /* Compare the two buffers. */
 | 
				
			||||||
 | 
					    while (datalen--)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (sdram_writeBuffer[datalen] != sdram_readBuffer[datalen])
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            result = -1;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (result < 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Failed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        KPrintf("\r\n SEMC SDRAM 8 bit Data Write and Read Compare Succeed!\r\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -13,10 +13,21 @@ KERNELPATHS :=-I$(BSP_ROOT) \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/include \
 | 
						-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/include \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/osa \
 | 
						-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/osa \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/phy \
 | 
						-I$(BSP_ROOT)/third_party_driver/usb/nxp_usb_driver/phy \
 | 
				
			||||||
 | 
						-I$(BSP_ROOT)/third_party_driver/ethernet \
 | 
				
			||||||
 | 
						-I$(BSP_ROOT)/third_party_driver/ethernet/lan8720 \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/MIMXRT1052 \
 | 
						-I$(BSP_ROOT)/third_party_driver/MIMXRT1052 \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/MIMXRT1052/drivers \
 | 
						-I$(BSP_ROOT)/third_party_driver/MIMXRT1052/drivers \
 | 
				
			||||||
	-I$(BSP_ROOT)/third_party_driver/CMSIS/Include \
 | 
						-I$(BSP_ROOT)/third_party_driver/CMSIS/Include \
 | 
				
			||||||
	-I$(KERNEL_ROOT)/include \
 | 
						-I$(KERNEL_ROOT)/include \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/compat \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/netif \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/apps \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
 | 
				
			||||||
 | 
						-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch \
 | 
				
			||||||
	-I$(KERNEL_ROOT)/resources/include \
 | 
						-I$(KERNEL_ROOT)/resources/include \
 | 
				
			||||||
	-I$(BSP_ROOT)/include \
 | 
						-I$(BSP_ROOT)/include \
 | 
				
			||||||
	-I$(BSP_ROOT)/xip #
 | 
						-I$(BSP_ROOT)/xip #
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue