STM32H743(M7内核)通过CubeMX搭建工程,移植TreadX和NetXDUO(二)

前言

在前篇移植Threadx的基础上移植NetXDUO网络协议栈

参考安富莱的教程:https://www.armbbs.cn/forum.php?mod=viewthread&tid=104619

1、CubeMx配置

打开上一篇配置好的cubemx工程
在这里插入图片描述
配置ETH为RMII,Rx Buffers Address配置为0x30040200
,具体原因我这边还没研究清楚

在这里插入图片描述
开启中断
在这里插入图片描述
网口所有引脚配置为Very High
在这里插入图片描述
配置网口复位引脚
在这里插入图片描述
点击生成工程代码

2、获取源码,并添加到工程中

1)通过git获取源码:https://github.com/azure-rtos/netxduo
2)移植安富莱的例程:https://www.armbbs.cn/forum.php?mod=viewthread&tid=104619
在这里插入图片描述
源码目录如图,我们只需要common、ports目录下的文件
在这里插入图片描述
在工程目录下创建NetXDUO目录,并将其复制过来
在这里插入图片描述

添加ST提供的nx_stm32_eth_driver、dp83848文件

dp83848phy驱动可从git获取:https://github.com/STMicroelectronics/stm32-dp83848
nx_stm32_eth_driver是在cubemx安装NETXDUO安装包时提供,我这边是复制安富莱的移植文件后进行修改的,源码如下,后面再进行修改分析

/**************************************************************************/
/*                                                                        */
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
/*                                                                        */
/*       This software is licensed under the Microsoft Software License   */
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
/*       and in the root directory of this software.                      */
/*                                                                        */
/**************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** NetX Component                                                        */
/**                                                                       */
/**   Ethernet device driver for STM32H7xx family micro processors        */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

/* Indicate that driver source is being compiled.  */

#define NX_DRIVER_SOURCE


/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area.  Include driver-specific include file here!  */

#ifndef NX_STM32_ETH_DRIVER_H

/* Determine if the driver uses IP deferred processing or direct ISR processing.  */

#define NX_DRIVER_ENABLE_DEFERRED                /* Define this to enable deferred ISR processing.  */


/* Determine if the packet transmit queue logic is required for this driver.   */

/* No, not required for this driver.  #define NX_DRIVER_INTERNAL_TRANSMIT_QUEUE   */

/* Define to enable hardware checksum offload.  */
#define HARDWARE_CHECKSUM_ENABLE

/* Include driver specific include file.  */
#include "nx_stm32_eth_driver.h"

#endif /* NX_STM32_ETH_DRIVER_H */

/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area!  */
#ifndef      __MEMORY_AT
  #if     (defined (__CC_ARM))
    #define  __MEMORY_AT(x)     __attribute__((at(x)))
  #elif   (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
    #define  __MEMORY_AT__(x)   __attribute__((section(".bss.ARM.__at_"#x)))
    #define  __MEMORY_AT(x)     __MEMORY_AT__(x)
  #else
    //#define  __MEMORY_AT(x)
    //#warning Position memory containing __MEMORY_AT macro at absolute address!
  #endif
#endif

/* Define the driver information structure that is only available within this file.  */
/* Place Ethernet BD at uncacheable memory*/
#if defined ( __ICCARM__ )
    #pragma location = 0x30040200
    NX_DRIVER_INFORMATION nx_driver_information;

    /* Ethernet Rx DMA 描述符 */
    #pragma location = 0x30040000
    ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT];

    /* Ethernet Tx DMA 描述符 */
    #pragma location = 0x30040060
    ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; 

#elif defined(__CC_ARM) 

    NX_DRIVER_INFORMATION nx_driver_information __MEMORY_AT(0x30040200);

    /* Ethernet Rx DMA 描述符 */
    ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT] __MEMORY_AT(0x30040000);

    /* Ethernet Tx DMA 描述符 */
    ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT] __MEMORY_AT(0x30040060); 

#elif  (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))

    NX_DRIVER_INFORMATION nx_driver_information __MEMORY_AT(0x30040200);

    /* Ethernet Rx DMA 描述符 */
    ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT] __MEMORY_AT(0x30040000);

    /* Ethernet Tx DMA 描述符 */
    ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT] __MEMORY_AT(0x30040060); 

#elif  defined(__GNUC__)
    /* Ethernet Rx DMA 描述符 */
__attribute__((section (".RAM3"))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; 

    /* Ethernet Tx DMA 描述符 */
__attribute__((section (".RAM3"))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; 

__attribute__((section (".RAM3"))) NX_DRIVER_INFORMATION nx_driver_information;
#endif


ETH_HandleTypeDef heth = {0};
ETH_TxPacketConfig TxPacketCfg = {0};
ETH_MACFilterConfigTypeDef FilterConfig;



/****** DRIVER SPECIFIC ****** Start of part/vendor specific data area.  Include hardware-specific data here!  */

/****** DRIVER SPECIFIC ****** End of part/vendor specific data area!  */


/* Define the routines for processing each driver entry request.  The contents of these routines will change with
   each driver. However, the main driver entry function will not change, except for the entry function name.  */

static VOID         _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr);
#ifdef NX_ENABLE_INTERFACE_CAPABILITY
static VOID         _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr);
static VOID         _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr);
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */

static VOID         _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr);

static VOID         _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE
static VOID         _nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr)
static NX_PACKET    *_nx_driver_transmit_packet_dequeue(VOID)
#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */


/* Define the prototypes for the hardware implementation of this driver. The contents of these routines are
   driver-specific.  */

static UINT         _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr);
static UINT         _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr);
static UINT         _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr);

static VOID         _nx_driver_hardware_packet_received(VOID);
#ifdef NX_ENABLE_INTERFACE_CAPABILITY
static UINT         _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr);
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    nx_driver_stm32h7xx                               STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This is the entry point of the NetX Ethernet Driver. This driver    */
/*    function is responsible for initializing the Ethernet controller,   */
/*    enabling or disabling the controller as need, preparing             */
/*    a packet for transmission, and getting status information.          */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        The driver request from the   */
/*                                            IP layer.                   */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_interface_attach           Process attach request        */
/*    _nx_driver_initialize                 Process initialize request    */
/*    _nx_driver_enable                     Process link enable request   */
/*    _nx_driver_disable                    Process link disable request  */
/*    _nx_driver_packet_send                Process send packet requests  */
/*    _nx_driver_multicast_join             Process multicast join request*/
/*    _nx_driver_multicast_leave            Process multicast leave req   */
/*    _nx_driver_get_status                 Process get status request    */
/*    _nx_driver_deferred_processing        Drive deferred processing     */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    IP layer                                                            */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
/****** DRIVER SPECIFIC ****** Start of part/vendor specific global driver entry function name.  */
VOID  nx_driver_stm32h7xx(NX_IP_DRIVER *driver_req_ptr)
/****** DRIVER SPECIFIC ****** End of part/vendor specific global driver entry function name.  */
{

    /* Default to successful return.  */
    driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

    /* Process according to the driver request type in the IP control
       block.  */
    switch (driver_req_ptr -> nx_ip_driver_command)
    {

    case NX_LINK_INTERFACE_ATTACH:

        /* Process link interface attach requests.  */
        _nx_driver_interface_attach(driver_req_ptr);
        break;

    case NX_LINK_INITIALIZE:
    {

        /* Process link initialize requests.  */
        _nx_driver_initialize(driver_req_ptr);
        break;
    }

    case NX_LINK_ENABLE:
    {

        /* Process link enable requests.  */
        _nx_driver_enable(driver_req_ptr);
        break;
    }

    case NX_LINK_DISABLE:
    {

        /* Process link disable requests.  */
        _nx_driver_disable(driver_req_ptr);
        break;
    }


    case NX_LINK_ARP_SEND:
    case NX_LINK_ARP_RESPONSE_SEND:
    case NX_LINK_PACKET_BROADCAST:
    case NX_LINK_RARP_SEND:
    case NX_LINK_PACKET_SEND:
    {

        /* Process packet send requests.  */
        _nx_driver_packet_send(driver_req_ptr);
        break;
    }


    case NX_LINK_MULTICAST_JOIN:
    {

        /* Process multicast join requests.  */
        _nx_driver_multicast_join(driver_req_ptr);
        break;
    }


    case NX_LINK_MULTICAST_LEAVE:
    {

        /* Process multicast leave requests.  */
        _nx_driver_multicast_leave(driver_req_ptr);
        break;
    }

    case NX_LINK_GET_STATUS:
    {

        /* Process get status requests.  */
        _nx_driver_get_status(driver_req_ptr);
        break;
    }

    case NX_LINK_DEFERRED_PROCESSING:
    {

        /* Process driver deferred requests.  */

        /* Process a device driver function on behave of the IP thread. */
        _nx_driver_deferred_processing(driver_req_ptr);

        break;
    }


#ifdef NX_ENABLE_INTERFACE_CAPABILITY
    case NX_INTERFACE_CAPABILITY_GET:
    {

        /* Process get capability requests.  */
        _nx_driver_capability_get(driver_req_ptr);
        break;
    }

    case NX_INTERFACE_CAPABILITY_SET:
    {

        /* Process set capability requests.  */
        _nx_driver_capability_set(driver_req_ptr);
        break;
    }
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */

    default:


        /* Invalid driver request.  */

        /* Return the unhandled command status.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_UNHANDLED_COMMAND;

        /* Default to successful return.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_interface_attach                       STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the interface attach request.              */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_interface_attach(NX_IP_DRIVER *driver_req_ptr)
{
    /* Setup the driver's interface.  This example is for a simple one-interface
       Ethernet driver. Additional logic is necessary for multiple port devices.  */
    nx_driver_information.nx_driver_information_interface =  driver_req_ptr -> nx_ip_driver_interface;

#ifdef NX_ENABLE_INTERFACE_CAPABILITY
    driver_req_ptr -> nx_ip_driver_interface -> nx_interface_capability_flag = NX_DRIVER_CAPABILITY;
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */

    /* Return successful status.  */
    driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_initialize                             STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the initialize request.  The processing    */
/*    in this function is generic. All ethernet controller logic is to    */
/*    be placed in _nx_driver_hardware_initialize.                        */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_initialize        Process initialize request    */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_initialize(NX_IP_DRIVER *driver_req_ptr)
{

NX_IP           *ip_ptr;
NX_INTERFACE    *interface_ptr;
UINT            status;


    /* Setup the IP pointer from the driver request.  */
    ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

    /* Setup interface pointer.  */
    interface_ptr = driver_req_ptr -> nx_ip_driver_interface;

    /* Initialize the driver's information structure.  */

    /* Default IP pointer to NULL.  */
    nx_driver_information.nx_driver_information_ip_ptr =               NX_NULL;

    /* Setup the driver state to not initialized.  */
    nx_driver_information.nx_driver_information_state =                NX_DRIVER_STATE_NOT_INITIALIZED;

    /* Setup the default packet pool for the driver's received packets.  */
    nx_driver_information.nx_driver_information_packet_pool_ptr = ip_ptr -> nx_ip_default_packet_pool;

    /* Clear the deferred events for the driver.  */
    nx_driver_information.nx_driver_information_deferred_events =       0;

#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE

    /* Clear the transmit queue count and head pointer.  */
    nx_driver_information.nx_driver_transmit_packets_queued =  0;
    nx_driver_information.nx_driver_transmit_queue_head =      NX_NULL;
    nx_driver_information.nx_driver_transmit_queue_tail =      NX_NULL;
#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */

    /* Call the hardware-specific ethernet controller initialization.  */
    status =  _nx_driver_hardware_initialize(driver_req_ptr);

    /* Determine if the request was successful.  */
    if (status == NX_SUCCESS)
    {

        /* Successful hardware initialization.  */

        /* Setup driver information to point to IP pointer.  */
        nx_driver_information.nx_driver_information_ip_ptr = driver_req_ptr -> nx_ip_driver_ptr;

        /* Setup the link maximum transfer unit. */
        interface_ptr -> nx_interface_ip_mtu_size =  NX_DRIVER_ETHERNET_MTU - NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Setup the physical address of this IP instance.  Increment the
           physical address lsw to simulate multiple nodes hanging on the
           ethernet.  */
        interface_ptr -> nx_interface_physical_address_msw =
                (ULONG)(( heth.Init.MACAddr[0] << 8) | ( heth.Init.MACAddr[1]));
        interface_ptr -> nx_interface_physical_address_lsw =
                (ULONG)(( heth.Init.MACAddr[2] << 24) | ( heth.Init.MACAddr[3] << 16) |
                        ( heth.Init.MACAddr[4] << 8) | ( heth.Init.MACAddr[5]));

        /* Indicate to the IP software that IP to physical mapping
           is required.  */
        interface_ptr -> nx_interface_address_mapping_needed =  NX_TRUE;

        /* Move the driver's state to initialized.  */
        nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_INITIALIZED;

        /* Indicate successful initialize.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
    else
    {

        /* Initialization failed.  Indicate that the request failed.  */
        driver_req_ptr -> nx_ip_driver_status =   NX_DRIVER_ERROR;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_enable                                 STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the initialize request. The processing     */
/*    in this function is generic. All ethernet controller logic is to    */
/*    be placed in _nx_driver_hardware_enable.                            */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_enable            Process enable request        */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_enable(NX_IP_DRIVER *driver_req_ptr)
{

NX_IP           *ip_ptr;
UINT            status;


    /* Setup the IP pointer from the driver request.  */
    ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

    /* See if we can honor the NX_LINK_ENABLE request.  */
    if (nx_driver_information.nx_driver_information_state < NX_DRIVER_STATE_INITIALIZED)
    {

        /* Mark the request as not successful.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
        return;
    }

    /* Check if it is enabled by someone already */
    if (nx_driver_information.nx_driver_information_state >=  NX_DRIVER_STATE_LINK_ENABLED)
    {

        /* Yes, the request has already been made.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_ALREADY_ENABLED;
        return;
    }

    /* Call hardware specific enable.  */
    status =  _nx_driver_hardware_enable(driver_req_ptr);

    /* Was the hardware enable successful?  */
    if (status == NX_SUCCESS)
    {

        /* Update the driver state to link enabled.  */
        nx_driver_information.nx_driver_information_state = NX_DRIVER_STATE_LINK_ENABLED;

        /* Mark request as successful.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

        /* Mark the IP instance as link up.  */
        ip_ptr -> nx_ip_driver_link_up =  NX_TRUE;
    }
    else
    {

        /* Enable failed.  Indicate that the request failed.  */
        driver_req_ptr -> nx_ip_driver_status =   NX_DRIVER_ERROR;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_disable                                STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the disable request. The processing        */
/*    in this function is generic. All ethernet controller logic is to    */
/*    be placed in _nx_driver_hardware_disable.                           */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_disable           Process disable request       */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_disable(NX_IP_DRIVER *driver_req_ptr)
{

NX_IP           *ip_ptr;
UINT            status;


    /* Setup the IP pointer from the driver request.  */
    ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

    /* Check if the link is enabled.  */
    if (nx_driver_information.nx_driver_information_state !=  NX_DRIVER_STATE_LINK_ENABLED)
    {

        /* The link is not enabled, so just return an error.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
        return;
    }

    /* Call hardware specific disable.  */
    status =  _nx_driver_hardware_disable(driver_req_ptr);

    /* Was the hardware disable successful?  */
    if (status == NX_SUCCESS)
    {

        /* Mark the IP instance as link down.  */
        ip_ptr -> nx_ip_driver_link_up =  NX_FALSE;

        /* Update the driver state back to initialized.  */
        nx_driver_information.nx_driver_information_state =  NX_DRIVER_STATE_INITIALIZED;

        /* Mark request as successful.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
    else
    {

        /* Disable failed, return an error.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_packet_send                            STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the packet send request. The processing    */
/*    in this function is generic. All ethernet controller packet send    */
/*    logic is to be placed in _nx_driver_hardware_packet_send.           */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_packet_send       Process packet send request   */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_packet_send(NX_IP_DRIVER *driver_req_ptr)
{

NX_IP           *ip_ptr;
NX_PACKET       *packet_ptr;
ULONG           *ethernet_frame_ptr;
UINT            status;


    /* Setup the IP pointer from the driver request.  */
    ip_ptr =  driver_req_ptr -> nx_ip_driver_ptr;

    /* Check to make sure the link is up.  */
    if (nx_driver_information.nx_driver_information_state != NX_DRIVER_STATE_LINK_ENABLED)
    {

        /* Inidate an unsuccessful packet send.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

        /* Link is not up, simply free the packet.  */
        nx_packet_transmit_release(driver_req_ptr -> nx_ip_driver_packet);
        return;
    }

    /* Process driver send packet.  */

    /* Place the ethernet frame at the front of the packet.  */
    packet_ptr =  driver_req_ptr -> nx_ip_driver_packet;

    /* Adjust the prepend pointer.  */
    packet_ptr -> nx_packet_prepend_ptr =
            packet_ptr -> nx_packet_prepend_ptr - NX_DRIVER_ETHERNET_FRAME_SIZE;

    /* Adjust the packet length.  */
    packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_DRIVER_ETHERNET_FRAME_SIZE;

    /* Setup the ethernet frame pointer to build the ethernet frame.  Backup another 2
      * bytes to get 32-bit word alignment.  */
    ethernet_frame_ptr =  (ULONG *) (packet_ptr -> nx_packet_prepend_ptr - 2);

    /* Set up the hardware addresses in the Ethernet header. */
    *ethernet_frame_ptr       =  driver_req_ptr -> nx_ip_driver_physical_address_msw;
    *(ethernet_frame_ptr + 1) =  driver_req_ptr -> nx_ip_driver_physical_address_lsw;

    *(ethernet_frame_ptr + 2) =  (ip_ptr -> nx_ip_arp_physical_address_msw << 16) |
        (ip_ptr -> nx_ip_arp_physical_address_lsw >> 16);
    *(ethernet_frame_ptr + 3) =  (ip_ptr -> nx_ip_arp_physical_address_lsw << 16);

    /* Set up the frame type field in the Ethernet harder. */
    if ((driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_SEND)||
        (driver_req_ptr -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND))
    {

        *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_ARP;
    }
    else if(driver_req_ptr -> nx_ip_driver_command == NX_LINK_RARP_SEND)
    {

        *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_RARP;
    }

#ifdef FEATURE_NX_IPV6
    else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
    {

        *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IPV6;
    }
#endif /* FEATURE_NX_IPV6 */

    else
    {

        *(ethernet_frame_ptr + 3) |= NX_DRIVER_ETHERNET_IP;
    }

    /* Endian swapping if NX_LITTLE_ENDIAN is defined.  */
    NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr));
    NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 1));
    NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 2));
    NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr + 3));

    /* Determine if the packet exceeds the driver's MTU.  */
    if (packet_ptr -> nx_packet_length > NX_DRIVER_ETHERNET_MTU)
    {

        /* This packet exceeds the size of the driver's MTU. Simply throw it away! */

        /* Remove the Ethernet header.  */
        NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

        /* Indicate an unsuccessful packet send.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

        /* Link is not up, simply free the packet.  */
        nx_packet_transmit_release(packet_ptr);
        return;
    }

    /* Transmit the packet through the Ethernet controller low level access routine. */
    status = _nx_driver_hardware_packet_send(packet_ptr);

    /* Determine if there was an error.  */
    if (status != NX_SUCCESS)
    {

        /* Driver's hardware send packet routine failed to send the packet.  */

        /* Remove the Ethernet header.  */
        NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

        /* Indicate an unsuccessful packet send.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;

        /* Link is not up, simply free the packet.  */
        nx_packet_transmit_release(packet_ptr);
    }
    else
    {

        /* Set the status of the request.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_multicast_join                         STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the multicast join request. The processing */
/*    in this function is generic. All ethernet controller multicast join */
/*    logic is to be placed in _nx_driver_hardware_multicast_join.        */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_multicast_join    Process multicast join request*/
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_multicast_join(NX_IP_DRIVER *driver_req_ptr)
{

UINT        status;


    /* Call hardware specific multicast join function. */
    status =  _nx_driver_hardware_multicast_join(driver_req_ptr);

    /* Determine if there was an error.  */
    if (status != NX_SUCCESS)
    {

        /* Indicate an unsuccessful request.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
    else
    {

        /* Indicate the request was successful.   */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_multicast_leave                        STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the multicast leave request. The           */
/*    processing in this function is generic. All ethernet controller     */
/*    multicast leave logic is to be placed in                            */
/*    _nx_driver_hardware_multicast_leave.                                */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_multicast_leave   Process multicast leave req   */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_multicast_leave(NX_IP_DRIVER *driver_req_ptr)
{

UINT        status;


    /* Call hardware specific multicast leave function. */
    status =  _nx_driver_hardware_multicast_leave(driver_req_ptr);

    /* Determine if there was an error.  */
    if (status != NX_SUCCESS)
    {

        /* Indicate an unsuccessful request.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
    else
    {

        /* Indicate the request was successful.   */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_get_status                             STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the get status request. The processing     */
/*    in this function is generic. All ethernet controller get status     */
/*    logic is to be placed in _nx_driver_hardware_get_status.            */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_hardware_get_status        Process get status request    */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_get_status(NX_IP_DRIVER *driver_req_ptr)
{

UINT        status;


    /* Call hardware specific get status function. */
    status =  _nx_driver_hardware_get_status(driver_req_ptr);

    /* Determine if there was an error.  */
    if (status != NX_SUCCESS)
    {

        /* Indicate an unsuccessful request.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
    else
    {

        /* Indicate the request was successful.   */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
}


#ifdef NX_ENABLE_INTERFACE_CAPABILITY
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_capability_get                         STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the get capability request.                */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_capability_get(NX_IP_DRIVER *driver_req_ptr)
{

    /* Return the capability of the Ethernet controller.  */
    *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_DRIVER_CAPABILITY;

    /* Return the success status.  */
    driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_capability_set                         STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the set capability request.                */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_capability_set(NX_IP_DRIVER *driver_req_ptr)
{

UINT        status;


    /* Call hardware specific get status function. */
    status =  _nx_driver_hardware_capability_set(driver_req_ptr);

    /* Determine if there was an error.  */
    if (status != NX_SUCCESS)
    {

        /* Indicate an unsuccessful request.  */
        driver_req_ptr -> nx_ip_driver_status =  NX_DRIVER_ERROR;
    }
    else
    {

        /* Indicate the request was successful.   */
        driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;
    }
}
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_deferred_processing                    STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    XC, Microsoft Corporation                                           */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing the deferred ISR action within the context */
/*    of the IP thread.                                                   */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver command from the IP    */
/*                                            thread                      */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_packet_transmitted        Clean up after transmission    */
/*    _nx_driver_packet_received           Process a received packet      */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    Driver entry function                                               */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_deferred_processing(NX_IP_DRIVER *driver_req_ptr)
{

TX_INTERRUPT_SAVE_AREA

ULONG       deferred_events;


    /* Disable interrupts.  */
    TX_DISABLE

    /* Pickup deferred events.  */
    deferred_events =  nx_driver_information.nx_driver_information_deferred_events;
    nx_driver_information.nx_driver_information_deferred_events =  0;

    /* Restore interrupts.  */
    TX_RESTORE

    /* Check for received packet.  */
    if(deferred_events & NX_DRIVER_DEFERRED_PACKET_RECEIVED)
    {

        /* Process received packet(s).  */
        _nx_driver_hardware_packet_received();
    }

    /* Mark request as successful.  */
    driver_req_ptr->nx_ip_driver_status =  NX_SUCCESS;
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_transfer_to_netx                       STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processing incoming packets.  This routine would      */
/*    be called from the driver-specific receive packet processing        */
/*    function _nx_driver_hardware.                              */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    ip_ptr                                Pointer to IP protocol block  */
/*    packet_ptr                            Packet pointer                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    Error indication                                                    */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_ip_packet_receive                 NetX IP packet receive        */
/*    _nx_ip_packet_deferred_receive        NetX IP packet receive        */
/*    _nx_arp_packet_deferred_receive       NetX ARP packet receive       */
/*    _nx_rarp_packet_deferred_receive      NetX RARP packet receive      */
/*    _nx_packet_release                    Release packet                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_hardware_packet_received   Driver packet receive function*/
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID _nx_driver_transfer_to_netx(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
{

USHORT    packet_type;


    /* Set the interface for the incoming packet.  */
    packet_ptr -> nx_packet_ip_interface = nx_driver_information.nx_driver_information_interface;

    /* Pickup the packet header to determine where the packet needs to be
       sent.  */
    packet_type =  (USHORT)(((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+12))) << 8) |
        ((UINT) (*(packet_ptr -> nx_packet_prepend_ptr+13)));

    /* Route the incoming packet according to its ethernet type.  */
    if (packet_type == NX_DRIVER_ETHERNET_IP || packet_type == NX_DRIVER_ETHERNET_IPV6)
    {
        /* Note:  The length reported by some Ethernet hardware includes
           bytes after the packet as well as the Ethernet header.  In some
           cases, the actual packet length after the Ethernet header should
           be derived from the length in the IP header (lower 16 bits of
           the first 32-bit word).  */

        /* Clean off the Ethernet header.  */
        packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Adjust the packet length.  */
        packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Route to the ip receive function.  */
        _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr);
    }
    else if (packet_type == NX_DRIVER_ETHERNET_ARP)
    {

        /* Clean off the Ethernet header.  */
        packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Adjust the packet length.  */
        packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Route to the ARP receive function.  */
        _nx_arp_packet_deferred_receive(ip_ptr, packet_ptr);
    }
    else if (packet_type == NX_DRIVER_ETHERNET_RARP)
    {

        /* Clean off the Ethernet header.  */
        packet_ptr -> nx_packet_prepend_ptr += NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Adjust the packet length.  */
        packet_ptr -> nx_packet_length -= NX_DRIVER_ETHERNET_FRAME_SIZE;

        /* Route to the RARP receive function.  */
        _nx_rarp_packet_deferred_receive(ip_ptr, packet_ptr);
    }
    else
    {
        /* Invalid ethernet header... release the packet.  */
        nx_packet_release(packet_ptr);
    }
}


#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_transmit_packet_enqueue                STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function queues a transmit packet when the hardware transmit   */
/*    queue does not have the resources (buffer descriptors, etc.) to     */
/*    send the packet.  The queue is maintained as a singularly linked-   */
/*    list with head and tail pointers. The maximum number of packets on  */
/*    the transmit queue is regulated by the constant                     */
/*    NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH. When this number is exceeded,   */
/*    the oldest packet is discarded after the new packet is queued.      */
/*                                                                        */
/*    Note: that it is assumed further driver interrupts are locked out   */
/*    during the call to this driver utility.                             */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    packet_ptr                            Packet pointer                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_packet_transmit_release           Release packet                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_hardware_packet_send       Driver packet send function   */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID _nx_driver_transmit_packet_enqueue(NX_PACKET *packet_ptr)
{

    /* Determine if there is anything on the queue.  */
    if (nx_driver_information.nx_driver_transmit_queue_tail)
    {

        /* Yes, something is on the transmit queue. Simply add the new packet to the
           tail.  */
        nx_driver_information.nx_driver_transmit_queue_tail -> nx_packet_queue_next  =  packet_ptr;

        /* Update the tail pointer.  */
        nx_driver_information.nx_driver_transmit_queue_tail =  packet_ptr;
    }
    else
    {

        /* First packet on the transmit queue.  */

        /* Setup head pointers.  */
        nx_driver_information.nx_driver_transmit_queue_head =  packet_ptr;
        nx_driver_information.nx_driver_transmit_queue_tail =  packet_ptr;

        /* Set the packet's next pointer to NULL.  */
        packet_ptr -> nx_packet_queue_next =  NX_NULL;
    }

    /* Increment the total packets queued.  */
    nx_driver_information.nx_driver_transmit_packets_queued++;

    /* Determine if the total packet queued exceeds the driver's maximum transmit
       queue depth.  */
    if (nx_driver_information.nx_driver_transmit_packets_queued > NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH)
    {

        /* Yes, remove the head packet (oldest) packet in the transmit queue and release it.  */
        packet_ptr =  nx_driver_information.nx_driver_transmit_queue_head;

        /* Adjust the head pointer to the next packet.  */
        nx_driver_information.nx_driver_transmit_queue_head =  packet_ptr -> nx_packet_queue_next;

        /* Decrement the transmit packet queued count.  */
        nx_driver_information.nx_driver_transmit_packets_queued--;

        /* Remove the ethernet header.  */
        NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

        /* Release the packet.  */
        nx_packet_transmit_release(packet_ptr);
    }
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_transmit_packet_dequeue                STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function removes the oldest transmit packet when the hardware  */
/*    transmit queue has new resources (usually after a transmit complete */
/*    interrupt) to send the packet. If there are no packets in the       */
/*    transmit queue, a NULL is returned.                                 */
/*                                                                        */
/*    Note: that it is assumed further driver interrupts are locked out   */
/*    during the call to this driver utility.                             */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    packet_ptr                            Packet pointer                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_hardware_packet_send       Driver packet send function   */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static NX_PACKET *_nx_driver_transmit_packet_dequeue(VOID)
{

NX_PACKET   *packet_ptr;


    /* Pickup the head pointer of the tranmit packet queue.  */
    packet_ptr =  nx_driver_information.nx_driver_transmit_queue_head;

    /* Determine if there is anything on the queue.  */
    if (packet_ptr)
    {

        /* Yes, something is on the transmit queue. Simply the packet from the head of the queue.  */

        /* Update the head pointer.  */
        nx_driver_information.nx_driver_transmit_queue_head =  packet_ptr -> nx_packet_queue_next;

        /* Clear the next pointer in the packet.  */
        packet_ptr -> nx_packet_queue_next =  NX_NULL;

        /* Decrement the transmit packet queued count.  */
        nx_driver_information.nx_driver_transmit_packets_queued--;
    }

    /* Return the packet pointer - NULL if there are no packets queued.  */
    return(packet_ptr);
}

#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */



/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions.  */

/*******************************************************************************
                       PHI IO Functions
*******************************************************************************/
/**
  * @brief  Initializes the MDIO interface GPIO and clocks.
  * @param  None
  * @retval 0 if OK, -1 if ERROR
  */
int32_t ETH_PHY_IO_Init(void)
{
  /* We assume that MDIO GPIO configuration is already done
     in the ETH_MspInit() else it should be done here
  */

  /* Configure the MDIO Clock */
  HAL_ETH_SetMDIOClockRange(&heth);

  return 0;
}

/**
  * @brief  De-Initializes the MDIO interface .
  * @param  None
  * @retval 0 if OK, -1 if ERROR
  */
int32_t ETH_PHY_IO_DeInit (void)
{
  return 0;
}

/**
  * @brief  Read a PHY register through the MDIO interface.
  * @param  DevAddr: PHY port address
  * @param  RegAddr: PHY register address
  * @param  pRegVal: pointer to hold the register value
  * @retval 0 if OK -1 if Error
  */
int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
  if(HAL_ETH_ReadPHYRegister(&heth, DevAddr, RegAddr, pRegVal) != HAL_OK)
  {
    return -1;
  }

  return 0;
}

/**
  * @brief  Write a value to a PHY register through the MDIO interface.
  * @param  DevAddr: PHY port address
  * @param  RegAddr: PHY register address
  * @param  RegVal: Value to be written
  * @retval 0 if OK -1 if Error
  */
int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
  if(HAL_ETH_WritePHYRegister(&heth, DevAddr, RegAddr, RegVal) != HAL_OK)
  {
    return -1;
  }

  return 0;
}

/**
  * @brief  Get the time in millisecons used for internal PHY driver process.
  * @retval Time value
  */
int32_t ETH_PHY_IO_GetTick(void)
{
  return HAL_GetTick();
}



/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_initialize                    STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific initialization.           */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]  */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    ETH_BSP_Config                        Configure Ethernet            */
/*    ETH_MACAddressConfig                  Setup MAC address             */
/*    ETH_DMARxDescReceiveITConfig          Enable receive descriptors    */
/*    nx_packet_allocate                    Allocate receive packet(s)    */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_initialize                 Driver initialize processing  */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/

/* 配置PHY驱动适配 */
//根据安富莱驱动修改、使用cube mx配置eth并把io全部更改为告诉引脚,
//配置网口复位引脚,并在eth引脚初始化前复位网口
//添加网口MPU配置
//更改_nx_driver_hardware_initialize函数中dm9162为lan8724
//lan8724为在cube mx配置lwip时的驱动,更改了LAN8742_SMR、LAN8742_PHYSCSR寄存器值
//使其驱动成DP83848网口芯片
//最后添加netxDUO线程,创建tcp客户端,成功通信
//获取官方dp83848驱动
//修改MPU的配置为安富莱的配置后,网口收发测试正常,不会死机
#include "dp83848.h"

ETH_TxPacketConfig TxConfig;

dp83848_Object_t LAN8742;
TX_THREAD *netx_thread_ptr;

static UINT  _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr)
{
NX_PACKET           *packet_ptr;
UINT                i;
ETH_MACConfigTypeDef MACConf;
INT PHYLinkState;
UINT duplex, speed = 0;
dp83848_IOCtx_t  LAN8742_IOCtx = {ETH_PHY_IO_Init,
                                  ETH_PHY_IO_DeInit,
                                  ETH_PHY_IO_WriteReg,
                                  ETH_PHY_IO_ReadReg,
                                  ETH_PHY_IO_GetTick};

    netx_thread_ptr = tx_thread_identify();
                              
    /* Default to successful return.  */
    driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

    /* Setup indices.  */
    nx_driver_information.nx_driver_information_receive_current_index = 0;
    nx_driver_information.nx_driver_information_transmit_current_index = 0;
    nx_driver_information.nx_driver_information_transmit_release_index = 0;

    /* Clear the number of buffers in use counter.  */
    nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0;

    /* Make sure there are receive packets... otherwise, return an error.  */
    if (nx_driver_information.nx_driver_information_packet_pool_ptr == NULL)
    {

        /* There must be receive packets. If not, return an error!  */
        return(NX_DRIVER_ERROR);
    }
    
    {
      
	   static uint8_t MACAddr[6];

	  /* USER CODE BEGIN ETH_Init 1 */

	  /* USER CODE END ETH_Init 1 */
	  heth.Instance = ETH;
	  MACAddr[0] = 0x00;
	  MACAddr[1] = 0x80;
	  MACAddr[2] = 0xE1;
	  MACAddr[3] = 0x00;
	  MACAddr[4] = 0x00;
	  MACAddr[5] = 0x00;
	  heth.Init.MACAddr = &MACAddr[0];
	  heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
	  heth.Init.TxDesc = DMATxDscrTab;
	  heth.Init.RxDesc = DMARxDscrTab;
	  heth.Init.RxBuffLen = 1524;

	  /* USER CODE BEGIN MACADDRESS */

	  /* USER CODE END MACADDRESS */

	  if (HAL_ETH_Init(&heth) != HAL_OK)
	  {
		
	  }

	  memset(&TxPacketCfg, 0 , sizeof(ETH_TxPacketConfig));
	  TxPacketCfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
	  TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
	  TxPacketCfg.CRCPadCtrl = ETH_CRC_PAD_INSERT;
    }

    ETH_DMAConfigTypeDef dmaDefaultConf = {0};
    dmaDefaultConf.AddressAlignedBeats = ENABLE;
    dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED;
    dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1;
    dmaDefaultConf.FlushRxPacket = DISABLE;
    dmaDefaultConf.PBLx8Mode = DISABLE;
    dmaDefaultConf.RebuildINCRxBurst = DISABLE;
    dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
    dmaDefaultConf.SecondPacketOperate = ENABLE;
    dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
    dmaDefaultConf.TCPSegmentation = DISABLE;
    dmaDefaultConf.MaximumSegmentSize = 536;
    /* enable OSF bit to enhance throughput */
    HAL_ETH_SetDMAConfig(&heth, &dmaDefaultConf);

    FilterConfig.PromiscuousMode = DISABLE;
    FilterConfig.HashUnicast = DISABLE;
    FilterConfig.HashMulticast = DISABLE;
    FilterConfig.DestAddrInverseFiltering = DISABLE;
    FilterConfig.PassAllMulticast = DISABLE;
    FilterConfig.BroadcastFilter = ENABLE;
    FilterConfig.SrcAddrInverseFiltering = DISABLE;
    FilterConfig.SrcAddrFiltering = DISABLE;
    FilterConfig.HachOrPerfectFilter = DISABLE;
    FilterConfig.ReceiveAllMode = DISABLE;
    FilterConfig.ControlPacketsFilter = 0x00;

    /* Set Tx packet config common parameters */
    memset(&TxPacketCfg, 0, sizeof(ETH_TxPacketConfig));
    TxPacketCfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM ;
    TxPacketCfg.CRCPadCtrl = ETH_CRC_PAD_DISABLE;

	/* Set PHY IO functions */
	  DP83848_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

	  /* Initialize the LAN8742 ETH PHY */
	  DP83848_Init(&LAN8742);

    PHYLinkState = DP83848_GetLinkState(&LAN8742);

    while(PHYLinkState <= DP83848_STATUS_LINK_DOWN)
    {
        PHYLinkState = DP83848_GetLinkState(&LAN8742);
        tx_thread_sleep(100);
    }
 
	switch (PHYLinkState)
    {
    case DP83848_STATUS_100MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case DP83848_STATUS_100MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case DP83848_STATUS_10MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    case DP83848_STATUS_10MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    default:
      break;
    }

    /* Get MAC Config MAC */
    HAL_ETH_GetMACConfig(&heth, &MACConf);
    MACConf.DuplexMode = duplex;
    MACConf.Speed = speed;
    HAL_ETH_SetMACConfig(&heth, &MACConf);

    for(i = 0; i < ETH_TX_DESC_CNT; i++)
    {
        DMARxDscrTab[i].DESC0 = 0;
        DMARxDscrTab[i].DESC1 = 0;
        DMATxDscrTab[i].DESC2 = (uint32_t)1<<31;
        DMATxDscrTab[i].DESC3 = 0;
    }

    for(i = 0; i < ETH_RX_DESC_CNT; i++)
    {

        /* Allocate a packet for the receive buffers.  */
        if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr,
                               NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS)
        {

            /* Adjust the packet.  */
            packet_ptr -> nx_packet_prepend_ptr += 2;
            DMARxDscrTab[i].DESC0 = (uint32_t) packet_ptr -> nx_packet_prepend_ptr;
            DMARxDscrTab[i].BackupAddr0 = (uint32_t) packet_ptr -> nx_packet_prepend_ptr;

            /* Remember the receive packet poitner.  */
            nx_driver_information.nx_driver_information_receive_packets[i] =  packet_ptr;

            DMARxDscrTab[i].DESC3 = ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V|ETH_DMARXNDESCRF_IOC;

        }
        else
        {
            /* Cannot allocate packets from the packet pool. */
            return(NX_DRIVER_ERROR);
        }
    }

      /* Save the size of one rx buffer.  */
    nx_driver_information.nx_driver_information_rx_buffer_size = packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start;

    /* Clear the number of buffers in use counter.  */
    nx_driver_information.nx_driver_information_multicast_count = 0;

    /* Return success!  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_enable                        STM32H7xx/IAR     */
/*                                                            6.1         */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                     */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific link enable requests.     */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]  */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    ETH_Start                             Start Ethernet operation      */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_enable                     Driver link enable processing */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_enable(NX_IP_DRIVER *driver_req_ptr)
{

    /* Call STM32 library to start Ethernet operation.  */
    HAL_ETH_Start_IT(&heth);

    /* Return success!  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_disable                       STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific link disable requests.    */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]  */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    ETH_MACTransmissionCmd                Disable transmit              */
/*    ETH_FlushTransmitFIFO                 Flush transmit FIFO           */
/*    ETH_MACReceptionCmd                   Disable receive               */
/*    ETH_DMATransmissionCmd                Stop DMA transmission         */
/*    ETH_DMAReceptionCmd                   Stop DMA reception            */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_disable                    Driver link disable processing*/
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_disable(NX_IP_DRIVER *driver_req_ptr)
{

    HAL_ETH_Stop(&heth);

    /* Return success!  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_packet_send                   STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific packet send requests.     */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    packet_ptr                            Pointer to packet to send     */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]  */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    [_nx_driver_transmit_packet_enqueue]  Optional internal transmit    */
/*                                            packet queue routine        */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_packet_send                Driver packet send processing */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_packet_send(NX_PACKET *packet_ptr)
{

NX_PACKET       *pktIdx;
UINT            buffLen = 0;

ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));


int i = 0;

    for (pktIdx = packet_ptr;pktIdx != NX_NULL ; pktIdx = pktIdx -> nx_packet_next)
    {
        if (i >= ETH_TX_DESC_CNT)
        {
            return NX_DRIVER_ERROR;
    }

        Txbuffer[i].buffer = pktIdx->nx_packet_prepend_ptr;
        Txbuffer[i].len = (pktIdx -> nx_packet_append_ptr - pktIdx->nx_packet_prepend_ptr);
        buffLen += (pktIdx -> nx_packet_append_ptr - pktIdx->nx_packet_prepend_ptr);

        if(i>0)
        {
          Txbuffer[i-1].next = &Txbuffer[i];
        }

        if (pktIdx-> nx_packet_next ==NULL)
        {
          Txbuffer[i].next = NULL;
        }

        i++;
        SCB_CleanDCache_by_Addr((uint32_t*)(pktIdx -> nx_packet_data_start), pktIdx -> nx_packet_data_end - pktIdx -> nx_packet_data_start);
    }

#ifdef NX_ENABLE_INTERFACE_CAPABILITY
    if (packet_ptr -> nx_packet_interface_capability_flag & (NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM |
                                                             NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM |
                                                             NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM |
                                                             NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM))
    {
        TxPacketCfg.ChecksumCtrl = ETH_DMATXNDESCRF_CIC_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
    }
    else if (packet_ptr -> nx_packet_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM)
        {

        TxPacketCfg.ChecksumCtrl = ETH_DMATXNDESCRF_CIC_IPHDR_INSERT;
        }
#else
        TxPacketCfg.ChecksumCtrl = ETH_DMATXNDESCRF_CIC_DISABLE;
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */

    TxPacketCfg.Length = buffLen;
    TxPacketCfg.TxBuffer = Txbuffer;
 
    /* transmit the packet */
    if(HAL_ETH_Transmit(&heth, &TxPacketCfg, 2000))
    {
        /* Return error.  */
        return(NX_DRIVER_ERROR);
    }

      /* Remove the Ethernet header.  */
    NX_DRIVER_ETHERNET_HEADER_REMOVE(packet_ptr);

    /* Free the packet.  */
    nx_packet_transmit_release(packet_ptr);

    return(NX_SUCCESS);
}

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_multicast_join                STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific multicast join requests.  */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]*/
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_multicast_join             Driver multicast join         */
/*                                            processing                  */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_multicast_join(NX_IP_DRIVER *driver_req_ptr)
{


    /* Increase the multicast count.  */
    nx_driver_information.nx_driver_information_multicast_count++;

    /* Enable multicast frame reception.  */
    FilterConfig.PassAllMulticast = ENABLE;
    HAL_ETH_SetMACFilterConfig(&heth, &FilterConfig);

    /* Return success.  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_multicast_leave               STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific multicast leave requests. */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]*/
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_multicast_leave            Driver multicast leave        */
/*                                            processing                  */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_multicast_leave(NX_IP_DRIVER *driver_req_ptr)
{

    /* Decrease the multicast count.  */
    nx_driver_information.nx_driver_information_multicast_count--;

    /* If multicast count reachs zero, disable multicast frame reception.  */
   if (nx_driver_information.nx_driver_information_multicast_count == 0)
    {

        /* Disable multicast frame reception.  */
        FilterConfig.PassAllMulticast = DISABLE;
        HAL_ETH_SetMACFilterConfig(&heth, &FilterConfig);
    }

    /* Return success.  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_get_status                    STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific get status requests.      */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                        Driver request pointer        */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]*/
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_get_status                 Driver get status processing  */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT  _nx_driver_hardware_get_status(NX_IP_DRIVER *driver_req_ptr)
{

    /* Return success.  */
    return(NX_SUCCESS);
}


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_packet_received               STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes packets received by the ethernet            */
/*    controller. This driver assumes NX_PACKET to be MTU size            */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_driver_transfer_to_netx           Transfer packet to NetX       */
/*    nx_packet_allocate                    Allocate receive packets      */
/*    _nx_packet_release                    Release receive packets       */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_deferred_processing        Deferred driver processing    */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static VOID  _nx_driver_hardware_packet_received(VOID)
{

    NX_PACKET     *packet_ptr;
    NX_PACKET  *received_packet_ptr;
    INT            i;
    uint32_t framelength = 0;
    static ETH_BufferTypeDef RxBuff[NX_DRIVER_RX_DESCRIPTORS];
    
    memset(RxBuff, 0 , NX_DRIVER_RX_DESCRIPTORS*sizeof(ETH_BufferTypeDef));
    
    for(i = 0; i < NX_DRIVER_RX_DESCRIPTORS -1; i++)
    {
        RxBuff[i].next=&RxBuff[i+1];
    }
           
    while (HAL_ETH_GetRxDataBuffer(&heth, RxBuff) == HAL_OK)
    {
        HAL_ETH_GetRxDataLength(&heth, &framelength);
        
        ETH_RxDescListTypeDef *dmarxdesclist = &heth.RxDescList;
        uint32_t FirstAppDesc = dmarxdesclist->FirstAppDesc;

        /* This driver assumes the recieved packet size is 1536 bytes */
        received_packet_ptr = nx_driver_information.nx_driver_information_receive_packets[FirstAppDesc];
        received_packet_ptr->nx_packet_append_ptr = received_packet_ptr->nx_packet_prepend_ptr + framelength;
        received_packet_ptr->nx_packet_length = framelength;
        received_packet_ptr->nx_packet_next = NULL;
        
        if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr,
                                NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS)
        {
            /* Adjust the packet.  */
            packet_ptr -> nx_packet_prepend_ptr += 2;
            SCB_InvalidateDCache_by_Addr((uint32_t*)packet_ptr -> nx_packet_data_start, packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start);
            HAL_ETH_DescAssignMemory(&heth, FirstAppDesc, packet_ptr -> nx_packet_prepend_ptr, NULL);
            nx_driver_information.nx_driver_information_receive_packets[FirstAppDesc] = packet_ptr;

            /* Build Rx descriptor to be ready for next data reception */
            HAL_ETH_BuildRxDescriptors(&heth);

            /* Transfer the packet to NetX.  */
            _nx_driver_transfer_to_netx(nx_driver_information.nx_driver_information_ip_ptr, received_packet_ptr);
        }
        else
        {
            HAL_ETH_BuildRxDescriptors(&heth);
        }
    }
}


#ifdef NX_ENABLE_INTERFACE_CAPABILITY
/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_driver_hardware_capability_set                STM32H7xx/IAR     */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Yuxin Zhou, Microsoft Corporation                                   */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function processes hardware-specific capability set requests.  */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    driver_req_ptr                         Driver request pointer       */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                [NX_SUCCESS|NX_DRIVER_ERROR]  */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_driver_capability_set             Capability set processing     */
/*                                                                        */
/*  RELEASE HISTORY                                                       */
/*                                                                        */
/*    DATE              NAME                      DESCRIPTION             */
/*                                                                        */
/*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
/*  xx-xx-xxxx     Yuxin Zhou               Modified comment(s),          */
/*                                            resulting in version 6.1    */
/*                                                                        */
/**************************************************************************/
static UINT _nx_driver_hardware_capability_set(NX_IP_DRIVER *driver_req_ptr)
{

    return NX_SUCCESS;
}
#endif /* NX_ENABLE_INTERFACE_CAPABILITY */


void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{

  ULONG deffered_events;
  deffered_events = nx_driver_information.nx_driver_information_deferred_events;

  nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_RECEIVED;

  if (!deffered_events)
  {
    /* Call NetX deferred driver processing.  */
    _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr);
  }
}

void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
{
  ULONG deffered_events;
  deffered_events = nx_driver_information.nx_driver_information_deferred_events;


  nx_driver_information.nx_driver_information_deferred_events |= NX_DRIVER_DEFERRED_PACKET_TRANSMITTED;

  if (!deffered_events)
  {
    /* Call NetX deferred driver processing.  */
    _nx_ip_driver_deferred_processing(nx_driver_information.nx_driver_information_ip_ptr);
  }
}

/****** DRIVER SPECIFIC ****** Start of part/vendor specific internal driver functions.  */


/**************************************************************************/
/*                                                                        */
/*            Copyright (c) 1996-2017 by Express Logic Inc.               */
/*                                                                        */
/*  This software is copyrighted by and is the sole property of Express   */
/*  Logic, Inc.  All rights, title, ownership, or other interests         */
/*  in the software remain the property of Express Logic, Inc.  This      */
/*  software may only be used in accordance with the corresponding        */
/*  license agreement.  Any unauthorized use, duplication, transmission,  */
/*  distribution, or disclosure of this software is expressly forbidden.  */
/*                                                                        */
/*  This Copyright notice may not be removed or modified without prior    */
/*  written consent of Express Logic, Inc.                                */
/*                                                                        */
/*  Express Logic, Inc. reserves the right to modify this software        */
/*  without notice.                                                       */
/*                                                                        */
/*  Express Logic, Inc.                     info@expresslogic.com         */
/*  11423 West Bernardo Court               http://www.expresslogic.com   */
/*  San Diego, CA  92127                                                  */
/*                                                                        */
/**************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** NetX Component                                                        */
/**                                                                       */
/**   Ethernet driver for STM32H7xx family of microprocessors             */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

#ifndef NX_STM32_ETH_DRIVER_H
#define NX_STM32_ETH_DRIVER_H


#ifdef   __cplusplus

/* Yes, C++ compiler is present.  Use standard C.  */
extern   "C" {
#endif


/* Include ThreadX header file, if not already.  */  
  
#ifndef TX_API_H
#include "tx_api.h"
#endif


/* Include NetX header file, if not already.  */

#ifndef NX_API_H
#include "nx_api.h"
#endif


/* Determine if the driver's source file is being compiled. The constants and typdefs are only valid within
   the driver's source file compilation.  */

#ifdef NX_DRIVER_SOURCE


/****** DRIVER SPECIFIC ****** Start of part/vendor specific include area.  Include any such files here!  */
//#include "nx_stm32_eth_config.h"

#include "stm32h7xx.h"
#include "stm32h7xx_hal.h"
#include "stm32h7xx_hal_eth.h"


/****** DRIVER SPECIFIC ****** End of part/vendor specific include file area!  */


/* Define generic constants and macros for all NetX Ethernet drivers.  */

#define NX_DRIVER_ETHERNET_IP                   0x0800
#define NX_DRIVER_ETHERNET_IPV6                 0x86dd
#define NX_DRIVER_ETHERNET_ARP                  0x0806
#define NX_DRIVER_ETHERNET_RARP                 0x8035

#define NX_DRIVER_ETHERNET_MTU                  1514
#define NX_DRIVER_ETHERNET_FRAME_SIZE           14

#define NX_DRIVER_DEFERRED_PACKET_RECEIVED      1
#define NX_DRIVER_DEFERRED_DEVICE_RESET         2
#define NX_DRIVER_DEFERRED_PACKET_TRANSMITTED   4

#define NX_DRIVER_STATE_NOT_INITIALIZED         1
#define NX_DRIVER_STATE_INITIALIZE_FAILED       2
#define NX_DRIVER_STATE_INITIALIZED             3    
#define NX_DRIVER_STATE_LINK_ENABLED            4    

#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE
#define NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH      10
#endif

#define NX_DRIVER_ERROR                         90


#define NX_DRIVER_ETHERNET_HEADER_REMOVE(p)   \
{   \
    p -> nx_packet_prepend_ptr =  p -> nx_packet_prepend_ptr + NX_DRIVER_ETHERNET_FRAME_SIZE;  \
    p -> nx_packet_length =  p -> nx_packet_length - NX_DRIVER_ETHERNET_FRAME_SIZE;    \
}    


/****** DRIVER SPECIFIC ****** Start of part/vendor specific constants area.  Include any such constants here!  */

/* Define the number of descriptors and attached packets for transmit and receive operations. */

#ifndef NX_DRIVER_TX_DESCRIPTORS   
#define NX_DRIVER_TX_DESCRIPTORS   ETH_TX_DESC_CNT   
#endif

#ifndef NX_DRIVER_RX_DESCRIPTORS
#define NX_DRIVER_RX_DESCRIPTORS   ETH_RX_DESC_CNT
#endif

/****** DRIVER SPECIFIC ****** End of part/vendor specific constant area!  */

#define NX_DRIVER_CAPABILITY ( NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM   | \
                               NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM   | \
                               NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM    | \
                               NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM    | \
                               NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM    | \
                               NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM    | \
                               NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM   | \
                               NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM   | \
                               NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM | \
                               NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM )   


/* Define basic Ethernet driver information typedef. Note that this typedefs is designed to be used only
   in the driver's C file. */

typedef struct NX_DRIVER_INFORMATION_STRUCT
{
    /* NetX IP instance that this driver is attached to.  */
    NX_IP               *nx_driver_information_ip_ptr;            

    /* Driver's current state.  */
    ULONG               nx_driver_information_state ;  

    /* Packet pool used for receiving packets. */
    NX_PACKET_POOL      *nx_driver_information_packet_pool_ptr;        

    /* Define the driver interface association.  */
    NX_INTERFACE        *nx_driver_information_interface;

    /* Define the deferred event field. This will contain bits representing events 
       deferred from the ISR for processing in the thread context.  */
    ULONG               nx_driver_information_deferred_events;


    /****** DRIVER SPECIFIC ****** Start of part/vendor specific driver information area.  Include any such constants here!  */

    /* Indices to current receive/transmit descriptors.  */
    UINT                nx_driver_information_receive_current_index;          
    UINT                nx_driver_information_transmit_current_index; 
    
    /* Transmit release index.  */
    UINT                nx_driver_information_transmit_release_index;
    
    /* Define the number of transmit buffers in use.  */
    UINT                nx_driver_information_number_of_transmit_buffers_in_use;

    /* Define the association between buffer descriptors and NetX packets.  */
    NX_PACKET           *nx_driver_information_transmit_packets[NX_DRIVER_TX_DESCRIPTORS];
    NX_PACKET           *nx_driver_information_receive_packets[NX_DRIVER_RX_DESCRIPTORS];
    
    /* Define the size of a rx buffer size.  */
    ULONG               nx_driver_information_rx_buffer_size;

    ULONG               nx_driver_information_multicast_count;
    
#ifdef NX_DRIVER_INTERNAL_TRANSMIT_QUEUE

    /* Define the parameters in the internal driver transmit queue.  The queue is maintained as a singularly
       linked-list with head and tail pointers.  The maximum number of packets on the queue is regulated by 
       the constant NX_DRIVER_MAX_TRANSMIT_QUEUE_DEPTH, which is defined above. When this number is reached,
       the oldest packet is discarded after the new packet is queued.  */
    ULONG               nx_driver_transmit_packets_queued;
    NX_PACKET           nx_driver_transmit_queue_head;
    NX_PACKET           nx_driver_transmit_queue_tail;
#endif /* NX_DRIVER_INTERNAL_TRANSMIT_QUEUE */

    /****** DRIVER SPECIFIC ****** End of part/vendor specific driver information area.  */

}   NX_DRIVER_INFORMATION;

#endif


/****** DRIVER SPECIFIC ****** Start of part/vendor specific external function prototypes.  A typical NetX Ethernet driver
                               should expose its entry function as well as its interrupt handling function(s) here. All other
                               functions in the driver should have local scope, i.e., defined as static.  */
    
/* Define global driver entry function. */

VOID  nx_driver_stm32h7xx(NX_IP_DRIVER *driver_req_ptr);

/* Define global driver interrupt dispatch function.  */

//VOID  nx_driver_stm32h7xx_ethernet_isr(void);

/****** DRIVER SPECIFIC ****** End of part/vendor specific external function prototypes.  */


#ifdef   __cplusplus
/* Yes, C++ compiler is present.  Use standard C.  */
    }
#endif
#endif /* NX_STM32_ETH_DRIVER_H */


在这里插入图片描述
打开工程创建对应目录
在这里插入图片描述
添加common中src全部源码
在这里插入图片描述
添加接口文件及PHY驱动
在这里插入图片描述
添加头文件路径

3、工程配置及网络接口配置

在这里插入图片描述
配置只使用IRAM2
在这里插入图片描述
配置MPU,通过配置MPU使网口使用的内存能够正常读写,保证网口通信正常

在这里插入图片描述CUBEMX重新生成的工程,中断需要重新注释掉

在这里插入图片描述
在这里插入图片描述
在网口初始化前,复位网口

	tx_thread_sleep(500);
	HAL_GPIO_WritePin(EHT_RST_GPIO_Port, EHT_RST_Pin, GPIO_PIN_RESET);
	tx_thread_sleep(500);
	HAL_GPIO_WritePin(EHT_RST_GPIO_Port, EHT_RST_Pin, GPIO_PIN_SET);

在这里插入图片描述
在这里插入图片描述
注释掉MAC的配置,因为该配置会在nx_stm32_eth_driver中实现
在这里插入图片描述
在这里插入图片描述
定义DMA描述符地址及相应变量句柄

重点在_nx_driver_hardware_initialize函数的配置,需要和我们所用的PHY芯片进行接口配置

#include "dp83848.h"

ETH_TxPacketConfig TxConfig;

dp83848_Object_t LAN8742;
TX_THREAD *netx_thread_ptr;

static UINT  _nx_driver_hardware_initialize(NX_IP_DRIVER *driver_req_ptr)
{
NX_PACKET           *packet_ptr;
UINT                i;
ETH_MACConfigTypeDef MACConf;
INT PHYLinkState;
UINT duplex, speed = 0;
dp83848_IOCtx_t  LAN8742_IOCtx = {ETH_PHY_IO_Init,
                                  ETH_PHY_IO_DeInit,
                                  ETH_PHY_IO_WriteReg,
                                  ETH_PHY_IO_ReadReg,
                                  ETH_PHY_IO_GetTick};

    netx_thread_ptr = tx_thread_identify();
                              
    /* Default to successful return.  */
    driver_req_ptr -> nx_ip_driver_status =  NX_SUCCESS;

    /* Setup indices.  */
    nx_driver_information.nx_driver_information_receive_current_index = 0;
    nx_driver_information.nx_driver_information_transmit_current_index = 0;
    nx_driver_information.nx_driver_information_transmit_release_index = 0;

    /* Clear the number of buffers in use counter.  */
    nx_driver_information.nx_driver_information_number_of_transmit_buffers_in_use = 0;

    /* Make sure there are receive packets... otherwise, return an error.  */
    if (nx_driver_information.nx_driver_information_packet_pool_ptr == NULL)
    {

        /* There must be receive packets. If not, return an error!  */
        return(NX_DRIVER_ERROR);
    }
    
    {
      
	   static uint8_t MACAddr[6];

	  /* USER CODE BEGIN ETH_Init 1 */

	  /* USER CODE END ETH_Init 1 */
	  heth.Instance = ETH;
	  MACAddr[0] = 0x00;
	  MACAddr[1] = 0x80;
	  MACAddr[2] = 0xE1;
	  MACAddr[3] = 0x00;
	  MACAddr[4] = 0x00;
	  MACAddr[5] = 0x00;
	  heth.Init.MACAddr = &MACAddr[0];
	  heth.Init.MediaInterface = HAL_ETH_RMII_MODE;
	  heth.Init.TxDesc = DMATxDscrTab;
	  heth.Init.RxDesc = DMARxDscrTab;
	  heth.Init.RxBuffLen = 1524;

	  /* USER CODE BEGIN MACADDRESS */

	  /* USER CODE END MACADDRESS */

	  if (HAL_ETH_Init(&heth) != HAL_OK)
	  {
		
	  }

	  memset(&TxPacketCfg, 0 , sizeof(ETH_TxPacketConfig));
	  TxPacketCfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
	  TxPacketCfg.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
	  TxPacketCfg.CRCPadCtrl = ETH_CRC_PAD_INSERT;
    }

    ETH_DMAConfigTypeDef dmaDefaultConf = {0};
    dmaDefaultConf.AddressAlignedBeats = ENABLE;
    dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED;
    dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1;
    dmaDefaultConf.FlushRxPacket = DISABLE;
    dmaDefaultConf.PBLx8Mode = DISABLE;
    dmaDefaultConf.RebuildINCRxBurst = DISABLE;
    dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
    dmaDefaultConf.SecondPacketOperate = ENABLE;
    dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
    dmaDefaultConf.TCPSegmentation = DISABLE;
    dmaDefaultConf.MaximumSegmentSize = 536;
    /* enable OSF bit to enhance throughput */
    HAL_ETH_SetDMAConfig(&heth, &dmaDefaultConf);

    FilterConfig.PromiscuousMode = DISABLE;
    FilterConfig.HashUnicast = DISABLE;
    FilterConfig.HashMulticast = DISABLE;
    FilterConfig.DestAddrInverseFiltering = DISABLE;
    FilterConfig.PassAllMulticast = DISABLE;
    FilterConfig.BroadcastFilter = ENABLE;
    FilterConfig.SrcAddrInverseFiltering = DISABLE;
    FilterConfig.SrcAddrFiltering = DISABLE;
    FilterConfig.HachOrPerfectFilter = DISABLE;
    FilterConfig.ReceiveAllMode = DISABLE;
    FilterConfig.ControlPacketsFilter = 0x00;

    /* Set Tx packet config common parameters */
    memset(&TxPacketCfg, 0, sizeof(ETH_TxPacketConfig));
    TxPacketCfg.Attributes = ETH_TX_PACKETS_FEATURES_CSUM ;
    TxPacketCfg.CRCPadCtrl = ETH_CRC_PAD_DISABLE;

	/* Set PHY IO functions */
	  DP83848_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

	  /* Initialize the LAN8742 ETH PHY */
	  DP83848_Init(&LAN8742);

    PHYLinkState = DP83848_GetLinkState(&LAN8742);

    while(PHYLinkState <= DP83848_STATUS_LINK_DOWN)
    {
        PHYLinkState = DP83848_GetLinkState(&LAN8742);
        tx_thread_sleep(100);
    }
 
	switch (PHYLinkState)
    {
    case DP83848_STATUS_100MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case DP83848_STATUS_100MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case DP83848_STATUS_10MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    case DP83848_STATUS_10MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    default:
      break;
    }

    /* Get MAC Config MAC */
    HAL_ETH_GetMACConfig(&heth, &MACConf);
    MACConf.DuplexMode = duplex;
    MACConf.Speed = speed;
    HAL_ETH_SetMACConfig(&heth, &MACConf);

    for(i = 0; i < ETH_TX_DESC_CNT; i++)
    {
        DMARxDscrTab[i].DESC0 = 0;
        DMARxDscrTab[i].DESC1 = 0;
        DMATxDscrTab[i].DESC2 = (uint32_t)1<<31;
        DMATxDscrTab[i].DESC3 = 0;
    }

    for(i = 0; i < ETH_RX_DESC_CNT; i++)
    {

        /* Allocate a packet for the receive buffers.  */
        if (nx_packet_allocate(nx_driver_information.nx_driver_information_packet_pool_ptr, &packet_ptr,
                               NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS)
        {

            /* Adjust the packet.  */
            packet_ptr -> nx_packet_prepend_ptr += 2;
            DMARxDscrTab[i].DESC0 = (uint32_t) packet_ptr -> nx_packet_prepend_ptr;
            DMARxDscrTab[i].BackupAddr0 = (uint32_t) packet_ptr -> nx_packet_prepend_ptr;

            /* Remember the receive packet poitner.  */
            nx_driver_information.nx_driver_information_receive_packets[i] =  packet_ptr;

            DMARxDscrTab[i].DESC3 = ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V|ETH_DMARXNDESCRF_IOC;

        }
        else
        {
            /* Cannot allocate packets from the packet pool. */
            return(NX_DRIVER_ERROR);
        }
    }

      /* Save the size of one rx buffer.  */
    nx_driver_information.nx_driver_information_rx_buffer_size = packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_data_start;

    /* Clear the number of buffers in use counter.  */
    nx_driver_information.nx_driver_information_multicast_count = 0;

    /* Return success!  */
    return(NX_SUCCESS);
}

我们可以根据自己板卡所使用的PHY芯片去替换不同的驱动即可,我这边使用的使dp83848,驱动在git中ST官方有提供源码,其他驱动应该也有

4、创建网络应用线程及应用

在这里插入图片描述
新建APP目录,添加tcp客户端应用
在这里插入图片描述
在这里插入图片描述


#include "app_netx_tcp_client.h"
#include "main.h"
#include "nx_api.h"

/*
*********************************************************************************************************
*	                                    IP相关
*********************************************************************************************************
*/
/* 远程服务器端口和IP */
#define TCP_SERVER_PORT                 1001
#define TCP_SERVER_ADDRESS              IP_ADDRESS(192, 168, 1, 11)

/* 本地IP地址 */
#define IP_ADDR0                        192
#define IP_ADDR1                        168
#define IP_ADDR2                        1
#define IP_ADDR3                        10

/* 本地端口号 */
#define DEFAULT_PORT                    1000

/*
*********************************************************************************************************
*	                                    NetX任务和通信组件
*********************************************************************************************************
*/
UCHAR data_buffer[4096];

NX_PACKET_POOL    pool_0;
NX_IP             ip_0;  

/* 数据包内存池 */
#define PACKET_SIZE          1536
#define NX_PACKET_POOL_SIZE  ((PACKET_SIZE + sizeof(NX_PACKET)) * 20)
	
ULONG  packet_pool_area[NX_PACKET_POOL_SIZE/4 + 4];

/* ARP缓存 */
ULONG    arp_space_area[512 / sizeof(ULONG)];                                                      
ULONG    error_counter;

#define PRINT_DATA(addr, port, data)        do {                                            \
                                                  printf("[%lu.%lu.%lu.%lu:%u] -> '%s' \r\n", \
                                                  (addr >> 24) & 0xff,                      \
                                                  (addr >> 16) & 0xff,                      \
                                                  (addr >> 8) & 0xff,                       \
                                                  (addr & 0xff), port, data);               \
                                               } while(0)

extern TX_THREAD   AppTaskNetXProTCB;
extern TX_THREAD   *netx_thread_ptr;                                               
extern VOID  nx_driver_stm32h7xx(NX_IP_DRIVER *driver_req_ptr);
                                              
/*
*********************************************************************************************************
*	                                    NetX任务和通信组件
*********************************************************************************************************
*/
/* 上电先将其设置到低优先级,待网线插入后提升优先级到3 */
#define  APP_CFG_TASK_NETX_PRIO                           28u    
#define  APP_CFG_TASK_NETX_STK_SIZE                     4096u
static   uint64_t  AppTaskNetXStk[APP_CFG_TASK_NETX_STK_SIZE/8];

/* 提升NetX处理任务优先级到3 */
#define  APP_CFG_TASK_NETX_PRIO1                           3u 

/* 提升NetX应用任务优先级到6 */
#define  APP_CFG_TASK_NetXPro_PRIO1                        6u

NX_TCP_SOCKET TCPSocket;

void  AppNetxDuoTcpClient(void)
{
	UINT status;
    UINT ret;
    ULONG socket_state;
    UINT old_priority;

    NX_PACKET *RecPacket;
    NX_PACKET *TraPacket;

    ULONG bytes_read;
	
	ULONG peer_ip_address;
	ULONG peer_port;
    
    uint8_t sendbuf[20];
    uint32_t count = 0;
    
	tx_thread_sleep(1000);
	
    /* 初始化NetX */
    nx_system_initialize();

    /* 创建内存池 */
    status =  nx_packet_pool_create(&pool_0,                                       /* 内存池控制块 */
                                     "NetX Main Packet Pool",                      /* 内存池名 */
                                     1536,                                         /* 内存池每个数据包大小,单位字节
                                                                                      此值必须至少为 40 个字节,并且还必须可以被 4 整除 */
									 (ULONG*)(((int)packet_pool_area + 15) & ~15) ,/* 内存池地址,此地址必须ULONG对齐 */
                                     NX_PACKET_POOL_SIZE);                         /* 内存池大小 */                  
          
    /* 检测创建是否失败 */
    if (status) error_counter++;

    /* 例化IP */
    status = nx_ip_create(&ip_0,                                                   /* IP实例控制块 */                                    
                            "NetX IP Instance 0",                                  /* IP实例名 */     
                            IP_ADDRESS(IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3),    /* IP地址 */
                            0xFFFFFF00UL,                                          /* 子网掩码 */
                            &pool_0,                                               /* 内存池 */
							nx_driver_stm32h7xx,                                   /* 网卡驱动 */
                            (UCHAR*)AppTaskNetXStk,                                /* IP任务栈地址 */
                            sizeof(AppTaskNetXStk),                                /* IP任务栈大小,单位字节 */
                            APP_CFG_TASK_NETX_PRIO);                               /* IP任务优先级 */
                            
							
    /* 检测创建是否失败 */
    if (status) error_counter++;

    /* 使能ARP,并提供ARP缓存 */
    status =  nx_arp_enable(&ip_0,                     /* IP实例控制块 */
							(void *)arp_space_area,    /* ARP缓存地址 */
							sizeof(arp_space_area));   /* 每个 ARP 条目均为 52 个字节,因此,ARP 条目总数是52字节整数倍 */

    /* 使能fragment */    
    status = nx_ip_fragment_enable(&ip_0);

    /* 检测使能成功 */
    if (status) error_counter++;

    /* 使能TCP */
    status =  nx_tcp_enable(&ip_0);

    /* 检测使能成功 */
    if (status) error_counter++;

    /* 使能UDP  */
    status =  nx_udp_enable(&ip_0);

    /* 检测使能成功 */
    if (status) error_counter++;

    /* 使能ICMP */
    status =  nx_icmp_enable(&ip_0);

    /* 检测使能成功 */
    if (status) error_counter++;   
    
	if(error_counter)
    {
        printf("error_counter \r\n"); 
    }

    tx_thread_priority_change(netx_thread_ptr, APP_CFG_TASK_NETX_PRIO1, &old_priority);

    
    /* 创建TCP Socket */
    ret = nx_tcp_socket_create(&ip_0,                 /* IP实例控制块 */    
                               &TCPSocket,            /* TCP控制块 */ 
                               "TCP Server Socket",   /* TCP Socket名 */ 
                               NX_IP_NORMAL,          /* IP服务类型 */ 
                               NX_FRAGMENT_OKAY,      /* 使能IP分段 */ 
                               NX_IP_TIME_TO_LIVE,    /* 指定一个 8 位的值,用于定义此数据包在被丢弃之前可通过的路由器数目 */ 
                               4320,                  /* TCP Socket接收队列中允许的最大字节数 */ 
                               NX_NULL,               /* 用于在接收流中检测到紧急数据时调用的回调函数 */
                               NX_NULL);              /* TCP Socket另一端发出断开连接时调用的回调函数 */
    if (ret)
    {
        printf("nx_tcp_socket_create file\r\n");   
    }


			
    while (1)
	{  
		TX_MEMSET(data_buffer, '\0', sizeof(data_buffer));

        /* 获取socket状态 */
        nx_tcp_socket_info_get(&TCPSocket,     /* TCP Socket控制块 */
		                       NULL,           /* 发送的TCP数据包总数目 */
		                       NULL,           /* 发送的TCP总字节数 */
		                       NULL,           /* 接收TCP数据包总数目 */
		                       NULL,           /* 接收的TCP总字节数 */
		                       NULL,           /* 重新传输的TCP数据包总数目 */
		                       NULL,           /* Socket上TCP排队的TCP数据包总数 */
		                       NULL,           /* Socket上有校验和错误的TCP数据包总数 */
		                       &socket_state,  /* Socket当前状态 */
		                       NULL,           /* 仍在排队等待ACK的发送数据包总数 */
		                       NULL,           /* 当前发送窗口大小 */
		                       NULL);          /* 当前接收窗口大小 */

        /* 如果连接还没有建立,继续接受新连接,成功的话开启接收数据 */
        if(socket_state != NX_TCP_ESTABLISHED)
        {
			tx_thread_sleep(1000);

				
			/* 绑定端口 */
			ret =  nx_tcp_client_socket_bind(&TCPSocket, DEFAULT_PORT, NX_WAIT_FOREVER);

			if (ret != NX_SUCCESS)
			{
				printf("nx_tcp_client_socket_bind file\r\n");  
			}
			else 
			{
				printf("nx_tcp_client_socket_bind = %d\r\n", DEFAULT_PORT);
			}
			
            /* 连接远程服务器 */
            ret = nx_tcp_client_socket_connect(&TCPSocket, TCP_SERVER_ADDRESS, TCP_SERVER_PORT, NX_WAIT_FOREVER);

            if (ret != NX_SUCCESS)
            {
                printf("nx_tcp_client_socket_connect file\r\n");  
            }
            else
            {
                printf("nx_tcp_client_socket_connect success\r\n"); 
            }
        }
        
        if((socket_state == NX_TCP_ESTABLISHED)&&(ret == NX_SUCCESS))
        {
                
            /* 接收TCP客户端发的TCP数据包 */
            ret = nx_tcp_socket_receive(&TCPSocket,        /* TCP Socket控制块 */
			                            &RecPacket,      /* 接收到的数据包 */
			                            NX_WAIT_FOREVER);  /* 永久等待 */

            if (ret == NX_SUCCESS)
            {
                
				/* 获取客户端的IP地址和端口 */
				nx_tcp_socket_peer_info_get(&TCPSocket,       /* TCP Socket控制块 */ 
											&peer_ip_address, /* 远程IP地址 */ 
											&peer_port);      /* 远程端口号 */

                /* 获取客户端发来的数据 */
                nx_packet_data_retrieve(RecPacket,    /* 接收到的数据包 */
				                        data_buffer,    /* 解析出数据 */
				                        &bytes_read);   /* 数据大小 */

                /* 打印接收到数据 */
//                PRINT_DATA(peer_ip_address, (unsigned int)peer_port, data_buffer);

                nx_packet_release(RecPacket);
                
               /* 申请发送数据包 */
               ret = nx_packet_allocate(&pool_0, &TraPacket, NX_TCP_PACKET, TX_WAIT_FOREVER);

               if (ret)
               {
                   printf("nx_packet_allocate file\r\n");  
               }

               sprintf((char *)sendbuf, "sendbuf = %d\r\n", count++);
               
               /*将要发送的数据附加到TraPacket */
               ret = nx_packet_data_append(TraPacket, (VOID *)sendbuf, strlen((char *)sendbuf), &pool_0, TX_WAIT_FOREVER);

               if (ret)
               {
                   printf("nx_packet_data_append file\r\n");  
               }
   
               /* 发送数据,注意发送后,此函数会释放数据包 */
               ret =  nx_tcp_socket_send(&TCPSocket,   
                                          TraPacket,       
                                           NX_WAIT_FOREVER); 
               
               
               if (ret)
               {
                   printf("nx_tcp_socket_send file\r\n");  
               }
                
            }
            else
            {
                /* 释放数据包 */
                nx_packet_release(RecPacket);
                
                /* 断开连接 */
                nx_tcp_socket_disconnect(&TCPSocket, 
				                         NX_WAIT_FOREVER);
				
				/* disconnect the socket */
                nx_tcp_client_socket_unbind(&TCPSocket);
            }
        }
	}  	
    
}








#ifndef  __APP_NETX_TCP_CLIENT_H__
#define  __APP_NETX_TCP_CLIENT_H__

void  AppNetxDuoTcpClient(void);

#endif


在thread.c文件中添加创建网络通信线程代码


#include "main.h"
#include "thread.h"

/*
*********************************************************************************************************
*                                 任务优先级,数值越小优先级越高
*********************************************************************************************************
*/
#define  APP_CFG_TASK_START_PRIO                          2u


/*
*********************************************************************************************************
*                                    任务栈大小,单位字节
*********************************************************************************************************
*/
#define  APP_CFG_TASK_START_STK_SIZE                    4096u

/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/                                                        
static  TX_THREAD   AppTaskStartTCB;
static  uint64_t    AppTaskStartStk[APP_CFG_TASK_START_STK_SIZE/8];



/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static  void  AppTaskStart          (ULONG thread_input);
static  void  AppTaskCreate         (void);

/*
*********************************************************************************************************
*	函 数 名: tx_application_define
*	功能说明: ThreadX专用的任务创建,通信组件创建函数
*	形    参: first_unused_memory  未使用的地址空间
*	返 回 值: 无
*********************************************************************************************************
*/
void  tx_application_define(void *first_unused_memory)
{
	/*
	   此函数仅用于实现启动任务,其它任务在函数AppTaskCreate里面创建。
	*/
	/**************创建启动任务*********************/
    tx_thread_create(&AppTaskStartTCB,              /* 任务控制块地址 */   
                       "App Task Start",              /* 任务名 */
                       AppTaskStart,                  /* 启动任务函数地址 */
                       0,                             /* 传递给任务的参数 */
                       &AppTaskStartStk[0],            /* 堆栈基地址 */
                       APP_CFG_TASK_START_STK_SIZE,    /* 堆栈空间大小 */  
                       APP_CFG_TASK_START_PRIO,        /* 任务优先级*/
                       APP_CFG_TASK_START_PRIO,        /* 任务抢占阀值 */
                       TX_NO_TIME_SLICE,               /* 不开启时间片 */
                       TX_AUTO_START);                 /* 创建后立即启动 */   
			   
}


/*
*********************************************************************************************************
*	函 数 名: AppTaskStart
*	功能说明: 启动任务。

*	形    参: thread_input 是在创建该任务时传递的形参
*	返 回 值: 无
	优 先 级: 2
*********************************************************************************************************
*/
static  void  AppTaskStart (ULONG thread_input)
{
	(void)thread_input;

	/* 内核开启后,恢复HAL里的时间基准 */
    HAL_ResumeTick();
	AppTaskCreate();

    while (1)
	{  
		
		printf("AppTaskStart RUN");
		tx_thread_sleep(1000);
    }
}



/*
*********************************************************************************************************
*	函 数 名: AppTaskNetXPro
*	功能说明: 消息处理,这里用作NetX网络任务处理
*	形    参: thread_input 是在创建该任务时传递的形参
*	返 回 值: 无
	优 先 级: 
*********************************************************************************************************
*/
extern void AppNetxDuoTcpClient(void);
static void AppTaskNetXPro(ULONG thread_input)
{
    (void)thread_input;
    
    tx_thread_sleep(1000); 
	while(1)
	{
        AppNetxDuoTcpClient();
	}   
}


/*
*********************************************************************************************************
*	函 数 名: AppTaskCreate
*	功能说明: 创建应用任务
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
#define  APP_CFG_TASK_NetXPro_PRIO                        3u 

#define  APP_CFG_TASK_NETXPRO_STK_SIZE                  4096u

TX_THREAD   AppTaskNetXProTCB;
static  uint64_t    AppTaskNetXProStk[APP_CFG_TASK_NETXPRO_STK_SIZE/8];

static  void  AppTaskCreate (void)
{
	/**************创建NetX处理任务*********************/
    tx_thread_create(&AppTaskNetXProTCB,               /* 任务控制块地址 */    
                      "App NETX Pro",                   /* 任务名 */
                       AppTaskNetXPro,                  /* 启动任务函数地址 */
                       0,                           /* 传递给任务的参数 */
                       &AppTaskNetXProStk[0],           /* 堆栈基地址 */
                       APP_CFG_TASK_NETXPRO_STK_SIZE,    /* 堆栈空间大小 */  
                       APP_CFG_TASK_NetXPro_PRIO,    /* 任务优先级*/
                       APP_CFG_TASK_NetXPro_PRIO,    /* 任务抢占阀值 */
                       TX_NO_TIME_SLICE,             /* 不开启时间片 */
                       TX_AUTO_START);               /* 创建后立即启动 */
}


在这里插入图片描述
在main.c文件中重定义HAL_GetTick,因为滴答定时器被内核占用,导致该函数运行异常,需重定义一下,在网口驱动时会调用到该函数

#include "tx_initialize.h"

extern  volatile ULONG      _tx_thread_system_state;

uint32_t HAL_GetTick (void)
{
    static uint32_t ticks = 0U;
    uint32_t i;

    if (_tx_thread_system_state == TX_INITIALIZE_IS_FINISHED)
    {
            return ((uint32_t)_tx_time_get());
    }

    for (i = (SystemCoreClock >> 14U); i > 0U; i--)
    {
            __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
            __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
    }
   
    return ++ticks;
}

编译代码,无错误,点击烧录进行测试

5、网口通信测试

在这里插入图片描述
网口的配置如图

MPU配置的更改

上面的移植过程,发现网络通信异常,调试发现
在这里插入图片描述
网口无法分配到内存池,经过排查,需修改MPU的配置
在这里插入图片描述
将以太网描述符修改为256B,不知到为啥,我另外移植的工程按照前面的配置可以正常网络通信,后面在学习一下MPU的内容,有知道的朋友可以讨论一下

void MPU_Config(void)
{
		MPU_Region_InitTypeDef MPU_InitStruct;

	/* 禁止 MPU */
	HAL_MPU_Disable();

    /* 最高性能,读Cache和写Cache都开启 */	
#if 0
   	/* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
	MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress      = 0x24000000;
	MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
	MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
	MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
	MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
	MPU_InitStruct.SubRegionDisable = 0x00;
	MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

	HAL_MPU_ConfigRegion(&MPU_InitStruct);

    /* 最低性能,读Cache和写Cache都关闭 */
 #else
	/* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
	MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress      = 0x24000000;
	MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
	MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
	MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
	MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
	MPU_InitStruct.SubRegionDisable = 0x00;
	MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;

	HAL_MPU_ConfigRegion(&MPU_InitStruct);
#endif
	
    
    /* 配置以太网收发描述符部分为Strongly Ordered */
	MPU_InitStruct.Enable = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress = 0x30040000;
	MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
	MPU_InitStruct.IsCacheable  = MPU_ACCESS_NOT_CACHEABLE;
	MPU_InitStruct.IsShareable  = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number = MPU_REGION_NUMBER2;
	MPU_InitStruct.SubRegionDisable = 0x0;
	MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
	MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

	HAL_MPU_ConfigRegion(&MPU_InitStruct);

	/*使能 MPU */
	HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

网络通信再测试

在这里插入图片描述
设置本地网络ip地址,根据自己软件设置
在这里插入图片描述
打开TCPServer,选择本地的网络ip,端口号并进行侦听
如图通信正常
在这里插入图片描述
可以正常ping通网络,自此ThreadX+NetXDUO移植完成,具体使用请参考其他教程

DP83848驱动源码

/**
  ******************************************************************************
  * @file    dp83848.c
  * @author  MCD Application Team
  * @brief   This file provides a set of functions needed to manage the DP83848
  *          PHY devices.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "dp83848.h"

/** @addtogroup BSP
  * @{
  */

/** @addtogroup Component
  * @{
  */

/** @defgroup DP83848 DP83848
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup DP83848_Private_Defines DP83848 Private Defines
  * @{
  */
#define DP83848_SW_RESET_TO    ((uint32_t)500U)
#define DP83848_INIT_TO        ((uint32_t)2000U)
#define DP83848_MAX_DEV_ADDR   ((uint32_t)31U)
/**
  * @}
  */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup DP83848_Private_Functions DP83848 Private Functions
  * @{
  */

/**
  * @brief  Register IO functions to component object
  * @param  pObj: device object  of DP83848_Object_t.
  * @param  ioctx: holds device IO functions.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_ERROR if missing mandatory function
  */
int32_t  DP83848_RegisterBusIO(dp83848_Object_t *pObj, dp83848_IOCtx_t *ioctx)
{
  if(!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
  {
    return DP83848_STATUS_ERROR;
  }

  pObj->IO.Init = ioctx->Init;
  pObj->IO.DeInit = ioctx->DeInit;
  pObj->IO.ReadReg = ioctx->ReadReg;
  pObj->IO.WriteReg = ioctx->WriteReg;
  pObj->IO.GetTick = ioctx->GetTick;

  return DP83848_STATUS_OK;
}

/**
  * @brief  Initialize the DP83848 and configure the needed hardware resources
  * @param  pObj: device object DP83848_Object_t.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_ADDRESS_ERROR if cannot find device address
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  *         DP83848_STATUS_RESET_TIMEOUT if cannot perform a software reset
  */
 int32_t DP83848_Init(dp83848_Object_t *pObj)
 {
   uint32_t tickstart = 0, regvalue = 0, addr = 0;
   int32_t status = DP83848_STATUS_OK;

   if(pObj->Is_Initialized == 0)
   {
     if(pObj->IO.Init != 0)
     {
       /* GPIO and Clocks initialization */
       pObj->IO.Init();
     }

     /* for later check */
     pObj->DevAddr = DP83848_MAX_DEV_ADDR + 1;

     /* Get the device address from special mode register */
     for(addr = 0; addr <= DP83848_MAX_DEV_ADDR; addr ++)
     {
       if(pObj->IO.ReadReg(addr, DP83848_SMR, &regvalue) < 0)
       {
         status = DP83848_STATUS_READ_ERROR;
         /* Can't read from this device address
            continue with next address */
         continue;
       }

       if((regvalue & DP83848_SMR_PHY_ADDR) == addr)
       {
         pObj->DevAddr = addr;
         status = DP83848_STATUS_OK;
         break;
       }
     }

     if(pObj->DevAddr > DP83848_MAX_DEV_ADDR)
     {
       status = DP83848_STATUS_ADDRESS_ERROR;
     }

     /* if device address is matched */
     if(status == DP83848_STATUS_OK)
     {
       /* set a software reset  */
       if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, DP83848_BCR_SOFT_RESET) >= 0)
       {
         /* get software reset status */
         if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &regvalue) >= 0)
         {
           tickstart = pObj->IO.GetTick();

           /* wait until software reset is done or timeout occured  */
           while(regvalue & DP83848_BCR_SOFT_RESET)
           {
             if((pObj->IO.GetTick() - tickstart) <= DP83848_SW_RESET_TO)
             {
               if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &regvalue) < 0)
               {
                 status = DP83848_STATUS_READ_ERROR;
                 break;
               }
             }
             else
             {
               status = DP83848_STATUS_RESET_TIMEOUT;
               break;
             }
           }
         }
         else
         {
           status = DP83848_STATUS_READ_ERROR;
         }
       }
       else
       {
         status = DP83848_STATUS_WRITE_ERROR;
       }
     }
   }

   if(status == DP83848_STATUS_OK)
   {
     tickstart =  pObj->IO.GetTick();

     /* Wait for 2s to perform initialization */
     while((pObj->IO.GetTick() - tickstart) <= DP83848_INIT_TO)
     {
     }
     pObj->Is_Initialized = 1;
   }

   return status;
 }

/**
  * @brief  De-Initialize the dp83848 and it's hardware resources
  * @param  pObj: device object DP83848_Object_t.
  * @retval None
  */
int32_t DP83848_DeInit(dp83848_Object_t *pObj)
{
  if(pObj->Is_Initialized)
  {
    if(pObj->IO.DeInit != 0)
    {
      if(pObj->IO.DeInit() < 0)
      {
        return DP83848_STATUS_ERROR;
      }
    }

    pObj->Is_Initialized = 0;
  }

  return DP83848_STATUS_OK;
}

/**
  * @brief  Disable the DP83848 power down mode.
  * @param  pObj: device object DP83848_Object_t.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_DisablePowerDownMode(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0)
  {
    readval &= ~DP83848_BCR_POWER_DOWN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0)
    {
      status =  DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Enable the DP83848 power down mode.
  * @param  pObj: device object DP83848_Object_t.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_EnablePowerDownMode(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0)
  {
    readval |= DP83848_BCR_POWER_DOWN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0)
    {
      status =  DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Start the auto negotiation process.
  * @param  pObj: device object DP83848_Object_t.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_StartAutoNego(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0)
  {
    readval |= DP83848_BCR_AUTONEGO_EN;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0)
    {
      status =  DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Get the link state of DP83848 device.
  * @param  pObj: Pointer to device object.
  * @param  pLinkState: Pointer to link state
  * @retval DP83848_STATUS_LINK_DOWN  if link is down
  *         DP83848_STATUS_AUTONEGO_NOTDONE if Auto nego not completed
  *         DP83848_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
  *         DP83848_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
  *         DP83848_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
  *         DP83848_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_GetLinkState(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;

  /* Read Status register  */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BSR, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }

  /* Read Status register again */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BSR, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }

  if((readval & DP83848_BSR_LINK_STATUS) == 0)
  {
    /* Return Link Down status */
    return DP83848_STATUS_LINK_DOWN;
  }

  /* Check Auto negotiaition */
  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) < 0)
  {
    return DP83848_STATUS_READ_ERROR;
  }

  if((readval & DP83848_BCR_AUTONEGO_EN) != DP83848_BCR_AUTONEGO_EN)
  {
    if(((readval & DP83848_BCR_SPEED_SELECT) == DP83848_BCR_SPEED_SELECT) && ((readval & DP83848_BCR_DUPLEX_MODE) == DP83848_BCR_DUPLEX_MODE))
    {
      return DP83848_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & DP83848_BCR_SPEED_SELECT) == DP83848_BCR_SPEED_SELECT)
    {
      return DP83848_STATUS_100MBITS_HALFDUPLEX;
    }
    else if ((readval & DP83848_BCR_DUPLEX_MODE) == DP83848_BCR_DUPLEX_MODE)
    {
      return DP83848_STATUS_10MBITS_FULLDUPLEX;
    }
    else
    {
      return DP83848_STATUS_10MBITS_HALFDUPLEX;
    }
  }
  else /* Auto Nego enabled */
  {
    if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_PHYSCSR, &readval) < 0)
    {
      return DP83848_STATUS_READ_ERROR;
    }

    /* Check if auto nego not done */
    if((readval & DP83848_PHYSCSR_AUTONEGO_DONE) == 0)
    {
      return DP83848_STATUS_AUTONEGO_NOTDONE;
    }

    if((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_100BTX_FD)
    {
      return DP83848_STATUS_100MBITS_FULLDUPLEX;
    }
    else if ((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_100BTX_HD)
    {
      return DP83848_STATUS_100MBITS_HALFDUPLEX;
    }
    else if ((readval & DP83848_PHYSCSR_HCDSPEEDMASK) == DP83848_PHYSCSR_10BT_FD)
    {
      return DP83848_STATUS_10MBITS_FULLDUPLEX;
    }
    else
    {
      return DP83848_STATUS_10MBITS_HALFDUPLEX;
    }
  }
}

/**
  * @brief  Set the link state of DP83848 device.
  * @param  pObj: Pointer to device object.
  * @param  pLinkState: link state can be one of the following
  *         DP83848_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD
  *         DP83848_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD
  *         DP83848_STATUS_10MBITS_FULLDUPLEX  if 10Mb/s FD
  *         DP83848_STATUS_10MBITS_HALFDUPLEX  if 10Mb/s HD
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_ERROR  if parameter error
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_SetLinkState(dp83848_Object_t *pObj, uint32_t LinkState)
{
  uint32_t bcrvalue = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &bcrvalue) >= 0)
  {
    /* Disable link config (Auto nego, speed and duplex) */
    bcrvalue &= ~(DP83848_BCR_AUTONEGO_EN | DP83848_BCR_SPEED_SELECT | DP83848_BCR_DUPLEX_MODE);

    if(LinkState == DP83848_STATUS_100MBITS_FULLDUPLEX)
    {
      bcrvalue |= (DP83848_BCR_SPEED_SELECT | DP83848_BCR_DUPLEX_MODE);
    }
    else if (LinkState == DP83848_STATUS_100MBITS_HALFDUPLEX)
    {
      bcrvalue |= DP83848_BCR_SPEED_SELECT;
    }
    else if (LinkState == DP83848_STATUS_10MBITS_FULLDUPLEX)
    {
      bcrvalue |= DP83848_BCR_DUPLEX_MODE;
    }
    else
    {
      /* Wrong link status parameter */
      status = DP83848_STATUS_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  if(status == DP83848_STATUS_OK)
  {
    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, bcrvalue) < 0)
    {
      status = DP83848_STATUS_WRITE_ERROR;
    }
  }

  return status;
}

/**
  * @brief  Enable loopback mode.
  * @param  pObj: Pointer to device object.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_EnableLoopbackMode(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0)
  {
    readval |= DP83848_BCR_LOOPBACK;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0)
    {
      status = DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Disable loopback mode.
  * @param  pObj: Pointer to device object.
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_DisableLoopbackMode(dp83848_Object_t *pObj)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_BCR, &readval) >= 0)
  {
    readval &= ~DP83848_BCR_LOOPBACK;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_BCR, readval) < 0)
    {
      status =  DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Enable IT source.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT source to be enabled
  *         should be a value or a combination of the following:
  *         DP83848_WOL_IT
  *         DP83848_ENERGYON_IT
  *         DP83848_AUTONEGO_COMPLETE_IT
  *         DP83848_REMOTE_FAULT_IT
  *         DP83848_LINK_DOWN_IT
  *         DP83848_AUTONEGO_LP_ACK_IT
  *         DP83848_PARALLEL_DETECTION_FAULT_IT
  *         DP83848_AUTONEGO_PAGE_RECEIVED_IT
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_EnableIT(dp83848_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_IMR, &readval) >= 0)
  {
    readval |= Interrupt;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_IMR, readval) < 0)
    {
      status =  DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Disable IT source.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT source to be disabled
  *         should be a value or a combination of the following:
  *         DP83848_WOL_IT
  *         DP83848_ENERGYON_IT
  *         DP83848_AUTONEGO_COMPLETE_IT
  *         DP83848_REMOTE_FAULT_IT
  *         DP83848_LINK_DOWN_IT
  *         DP83848_AUTONEGO_LP_ACK_IT
  *         DP83848_PARALLEL_DETECTION_FAULT_IT
  *         DP83848_AUTONEGO_PAGE_RECEIVED_IT
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  *         DP83848_STATUS_WRITE_ERROR if connot write to register
  */
int32_t DP83848_DisableIT(dp83848_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_IMR, &readval) >= 0)
  {
    readval &= ~Interrupt;

    /* Apply configuration */
    if(pObj->IO.WriteReg(pObj->DevAddr, DP83848_IMR, readval) < 0)
    {
      status = DP83848_STATUS_WRITE_ERROR;
    }
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Clear IT flag.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT flag to be cleared
  *         should be a value or a combination of the following:
  *         DP83848_WOL_IT
  *         DP83848_ENERGYON_IT
  *         DP83848_AUTONEGO_COMPLETE_IT
  *         DP83848_REMOTE_FAULT_IT
  *         DP83848_LINK_DOWN_IT
  *         DP83848_AUTONEGO_LP_ACK_IT
  *         DP83848_PARALLEL_DETECTION_FAULT_IT
  *         DP83848_AUTONEGO_PAGE_RECEIVED_IT
  * @retval DP83848_STATUS_OK  if OK
  *         DP83848_STATUS_READ_ERROR if connot read register
  */
int32_t  DP83848_ClearIT(dp83848_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = DP83848_STATUS_OK;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_ISFR, &readval) < 0)
  {
    status =  DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @brief  Get IT Flag status.
  * @param  pObj: Pointer to device object.
  * @param  Interrupt: IT Flag to be checked,
  *         should be a value or a combination of the following:
  *         DP83848_WOL_IT
  *         DP83848_ENERGYON_IT
  *         DP83848_AUTONEGO_COMPLETE_IT
  *         DP83848_REMOTE_FAULT_IT
  *         DP83848_LINK_DOWN_IT
  *         DP83848_AUTONEGO_LP_ACK_IT
  *         DP83848_PARALLEL_DETECTION_FAULT_IT
  *         DP83848_AUTONEGO_PAGE_RECEIVED_IT
  * @retval 1 IT flag is SET
  *         0 IT flag is RESET
  *         DP83848_STATUS_READ_ERROR if connot read register
  */
int32_t DP83848_GetITStatus(dp83848_Object_t *pObj, uint32_t Interrupt)
{
  uint32_t readval = 0;
  int32_t status = 0;

  if(pObj->IO.ReadReg(pObj->DevAddr, DP83848_ISFR, &readval) >= 0)
  {
    status = ((readval & Interrupt) == Interrupt);
  }
  else
  {
    status = DP83848_STATUS_READ_ERROR;
  }

  return status;
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */


/**
  ******************************************************************************
  * @file    dp83848.h
  * @author  MCD Application Team
  * @brief   This file contains all the functions prototypes for the
  *          dp83848.c PHY driver.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DP83848_H
#define DP83848_H

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>

/** @addtogroup BSP
  * @{
  */

/** @addtogroup Component
  * @{
  */

/** @defgroup DP83848
  * @{
  */
/* Exported constants --------------------------------------------------------*/
/** @defgroup DP83848_Exported_Constants DP83848 Exported Constants
  * @{
  */

/** @defgroup DP83848_Registers_Mapping DP83848 Registers Mapping
  * @{
  */
#define DP83848_BCR      ((uint16_t)0x0000U)
#define DP83848_BSR      ((uint16_t)0x0001U)
#define DP83848_PHYI1R   ((uint16_t)0x0002U)
#define DP83848_PHYI2R   ((uint16_t)0x0003U)
#define DP83848_ANAR     ((uint16_t)0x0004U)
#define DP83848_ANLPAR   ((uint16_t)0x0005U)
#define DP83848_ANER     ((uint16_t)0x0006U)
#define DP83848_ANNPTR   ((uint16_t)0x0007U)
#define DP83848_SMR      ((uint16_t)0x0019U)
#define DP83848_ISFR     ((uint16_t)0x0012U)
#define DP83848_IMR      ((uint16_t)0x0011U)
#define DP83848_PHYSCSR  ((uint16_t)0x0010U)
/**
  * @}
  */

/** @defgroup DP83848_BCR_Bit_Definition DP83848 BCR Bit Definition
  * @{
  */
#define DP83848_BCR_SOFT_RESET         ((uint16_t)0x8000U)
#define DP83848_BCR_LOOPBACK           ((uint16_t)0x4000U)
#define DP83848_BCR_SPEED_SELECT       ((uint16_t)0x2000U)
#define DP83848_BCR_AUTONEGO_EN        ((uint16_t)0x1000U)
#define DP83848_BCR_POWER_DOWN         ((uint16_t)0x0800U)
#define DP83848_BCR_ISOLATE            ((uint16_t)0x0400U)
#define DP83848_BCR_RESTART_AUTONEGO   ((uint16_t)0x0200U)
#define DP83848_BCR_DUPLEX_MODE        ((uint16_t)0x0100U)
/**
  * @}
  */

/** @defgroup DP83848_BSR_Bit_Definition DP83848 BSR Bit Definition
  * @{
  */
#define DP83848_BSR_100BASE_T4       ((uint16_t)0x8000U)
#define DP83848_BSR_100BASE_TX_FD    ((uint16_t)0x4000U)
#define DP83848_BSR_100BASE_TX_HD    ((uint16_t)0x2000U)
#define DP83848_BSR_10BASE_T_FD      ((uint16_t)0x1000U)
#define DP83848_BSR_10BASE_T_HD      ((uint16_t)0x0800U)
#define DP83848_BSR_MF_PREAMBLE      ((uint16_t)0x0040U)
#define DP83848_BSR_AUTONEGO_CPLT    ((uint16_t)0x0020U)
#define DP83848_BSR_REMOTE_FAULT     ((uint16_t)0x0010U)
#define DP83848_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U)
#define DP83848_BSR_LINK_STATUS      ((uint16_t)0x0004U)
#define DP83848_BSR_JABBER_DETECT    ((uint16_t)0x0002U)
#define DP83848_BSR_EXTENDED_CAP     ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup DP83848_PHYI1R_Bit_Definition DP83848 PHYI1R Bit Definition
  * @{
  */
#define DP83848_PHYI1R_OUI_3_18           ((uint16_t)0xFFFFU)
/**
  * @}
  */

/** @defgroup DP83848_PHYI2R_Bit_Definition DP83848 PHYI2R Bit Definition
  * @{
  */
#define DP83848_PHYI2R_OUI_19_24          ((uint16_t)0xFC00U)
#define DP83848_PHYI2R_MODEL_NBR          ((uint16_t)0x03F0U)
#define DP83848_PHYI2R_REVISION_NBR       ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup DP83848_ANAR_Bit_Definition DP83848 ANAR Bit Definition
  * @{
  */
#define DP83848_ANAR_NEXT_PAGE               ((uint16_t)0x8000U)
#define DP83848_ANAR_REMOTE_FAULT            ((uint16_t)0x2000U)
#define DP83848_ANAR_PAUSE_OPERATION         ((uint16_t)0x0C00U)
#define DP83848_ANAR_PO_NOPAUSE              ((uint16_t)0x0000U)
#define DP83848_ANAR_PO_SYMMETRIC_PAUSE      ((uint16_t)0x0400U)
#define DP83848_ANAR_PO_ASYMMETRIC_PAUSE     ((uint16_t)0x0800U)
#define DP83848_ANAR_PO_ADVERTISE_SUPPORT    ((uint16_t)0x0C00U)
#define DP83848_ANAR_100BASE_TX_FD           ((uint16_t)0x0100U)
#define DP83848_ANAR_100BASE_TX              ((uint16_t)0x0080U)
#define DP83848_ANAR_10BASE_T_FD             ((uint16_t)0x0040U)
#define DP83848_ANAR_10BASE_T                ((uint16_t)0x0020U)
#define DP83848_ANAR_SELECTOR_FIELD          ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup DP83848_ANLPAR_Bit_Definition DP83848 ANLPAR Bit Definition
  * @{
  */
#define DP83848_ANLPAR_NEXT_PAGE            ((uint16_t)0x8000U)
#define DP83848_ANLPAR_REMOTE_FAULT         ((uint16_t)0x2000U)
#define DP83848_ANLPAR_PAUSE_OPERATION      ((uint16_t)0x0C00U)
#define DP83848_ANLPAR_PO_NOPAUSE           ((uint16_t)0x0000U)
#define DP83848_ANLPAR_PO_SYMMETRIC_PAUSE   ((uint16_t)0x0400U)
#define DP83848_ANLPAR_PO_ASYMMETRIC_PAUSE  ((uint16_t)0x0800U)
#define DP83848_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U)
#define DP83848_ANLPAR_100BASE_TX_FD        ((uint16_t)0x0100U)
#define DP83848_ANLPAR_100BASE_TX           ((uint16_t)0x0080U)
#define DP83848_ANLPAR_10BASE_T_FD          ((uint16_t)0x0040U)
#define DP83848_ANLPAR_10BASE_T             ((uint16_t)0x0020U)
#define DP83848_ANLPAR_SELECTOR_FIELD       ((uint16_t)0x000FU)
/**
  * @}
  */

/** @defgroup DP83848_ANER_Bit_Definition DP83848 ANER Bit Definition
  * @{
  */
#define DP83848_ANER_RX_NP_LOCATION_ABLE    ((uint16_t)0x0040U)
#define DP83848_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U)
#define DP83848_ANER_PARALLEL_DETECT_FAULT  ((uint16_t)0x0010U)
#define DP83848_ANER_LP_NP_ABLE             ((uint16_t)0x0008U)
#define DP83848_ANER_NP_ABLE                ((uint16_t)0x0004U)
#define DP83848_ANER_PAGE_RECEIVED          ((uint16_t)0x0002U)
#define DP83848_ANER_LP_AUTONEG_ABLE        ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup DP83848_ANNPTR_Bit_Definition DP83848 ANNPTR Bit Definition
  * @{
  */
#define DP83848_ANNPTR_NEXT_PAGE         ((uint16_t)0x8000U)
#define DP83848_ANNPTR_MESSAGE_PAGE      ((uint16_t)0x2000U)
#define DP83848_ANNPTR_ACK2              ((uint16_t)0x1000U)
#define DP83848_ANNPTR_TOGGLE            ((uint16_t)0x0800U)
#define DP83848_ANNPTR_MESSAGE_CODE      ((uint16_t)0x07FFU)
/**
  * @}
  */

/** @defgroup DP83848_ANNPRR_Bit_Definition DP83848 ANNPRR Bit Definition
  * @{
  */
#define DP83848_ANNPRR_NEXT_PAGE         ((uint16_t)0x8000U)
#define DP83848_ANNPRR_ACK               ((uint16_t)0x4000U)
#define DP83848_ANNPRR_MESSAGE_PAGE      ((uint16_t)0x2000U)
#define DP83848_ANNPRR_ACK2              ((uint16_t)0x1000U)
#define DP83848_ANNPRR_TOGGLE            ((uint16_t)0x0800U)
#define DP83848_ANNPRR_MESSAGE_CODE      ((uint16_t)0x07FFU)
/**
  * @}
  */

/** @defgroup DP83848_MMDACR_Bit_Definition DP83848 MMDACR Bit Definition
  * @{
  */
#define DP83848_MMDACR_MMD_FUNCTION       ((uint16_t)0xC000U)
#define DP83848_MMDACR_MMD_FUNCTION_ADDR  ((uint16_t)0x0000U)
#define DP83848_MMDACR_MMD_FUNCTION_DATA  ((uint16_t)0x4000U)
#define DP83848_MMDACR_MMD_DEV_ADDR       ((uint16_t)0x001FU)
/**
  * @}
  */

/** @defgroup DP83848_ENCTR_Bit_Definition DP83848 ENCTR Bit Definition
  * @{
  */
#define DP83848_ENCTR_TX_ENABLE             ((uint16_t)0x8000U)
#define DP83848_ENCTR_TX_TIMER              ((uint16_t)0x6000U)
#define DP83848_ENCTR_TX_TIMER_1S           ((uint16_t)0x0000U)
#define DP83848_ENCTR_TX_TIMER_768MS        ((uint16_t)0x2000U)
#define DP83848_ENCTR_TX_TIMER_512MS        ((uint16_t)0x4000U)
#define DP83848_ENCTR_TX_TIMER_265MS        ((uint16_t)0x6000U)
#define DP83848_ENCTR_RX_ENABLE             ((uint16_t)0x1000U)
#define DP83848_ENCTR_RX_MAX_INTERVAL       ((uint16_t)0x0C00U)
#define DP83848_ENCTR_RX_MAX_INTERVAL_64MS  ((uint16_t)0x0000U)
#define DP83848_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U)
#define DP83848_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U)
#define DP83848_ENCTR_RX_MAX_INTERVAL_1S    ((uint16_t)0x0C00U)
#define DP83848_ENCTR_EX_CROSS_OVER         ((uint16_t)0x0002U)
#define DP83848_ENCTR_EX_MANUAL_CROSS_OVER  ((uint16_t)0x0001U)
/**
  * @}
  */

/** @defgroup DP83848_MCSR_Bit_Definition DP83848 MCSR Bit Definition
  * @{
  */
#define DP83848_MCSR_EDPWRDOWN        ((uint16_t)0x2000U)
#define DP83848_MCSR_FARLOOPBACK      ((uint16_t)0x0200U)
#define DP83848_MCSR_ALTINT           ((uint16_t)0x0040U)
#define DP83848_MCSR_ENERGYON         ((uint16_t)0x0002U)
/**
  * @}
  */

/** @defgroup DP83848_SMR_Bit_Definition DP83848 SMR Bit Definition
  * @{
  */
#define DP83848_SMR_MODE       ((uint16_t)0x00E0U)
#define DP83848_SMR_PHY_ADDR   ((uint16_t)0x001FU)
/**
  * @}
  */

/** @defgroup DP83848_TPDCR_Bit_Definition DP83848 TPDCR Bit Definition
  * @{
  */
#define DP83848_TPDCR_DELAY_IN                 ((uint16_t)0x8000U)
#define DP83848_TPDCR_LINE_BREAK_COUNTER       ((uint16_t)0x7000U)
#define DP83848_TPDCR_PATTERN_HIGH             ((uint16_t)0x0FC0U)
#define DP83848_TPDCR_PATTERN_LOW              ((uint16_t)0x003FU)
/**
  * @}
  */

/** @defgroup DP83848_TCSR_Bit_Definition DP83848 TCSR Bit Definition
  * @{
  */
#define DP83848_TCSR_TDR_ENABLE           ((uint16_t)0x8000U)
#define DP83848_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U)
#define DP83848_TCSR_TDR_CH_CABLE_TYPE    ((uint16_t)0x0600U)
#define DP83848_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U)
#define DP83848_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U)
#define DP83848_TCSR_TDR_CH_CABLE_OPEN    ((uint16_t)0x0400U)
#define DP83848_TCSR_TDR_CH_CABLE_MATCH   ((uint16_t)0x0600U)
#define DP83848_TCSR_TDR_CH_STATUS        ((uint16_t)0x0100U)
#define DP83848_TCSR_TDR_CH_LENGTH        ((uint16_t)0x00FFU)
/**
  * @}
  */

/** @defgroup DP83848_SCSIR_Bit_Definition DP83848 SCSIR Bit Definition
  * @{
  */
#define DP83848_SCSIR_AUTO_MDIX_ENABLE    ((uint16_t)0x8000U)
#define DP83848_SCSIR_CHANNEL_SELECT      ((uint16_t)0x2000U)
#define DP83848_SCSIR_SQE_DISABLE         ((uint16_t)0x0800U)
#define DP83848_SCSIR_XPOLALITY           ((uint16_t)0x0010U)
/**
  * @}
  */

/** @defgroup DP83848_CLR_Bit_Definition DP83848 CLR Bit Definition
  * @{
  */
#define DP83848_CLR_CABLE_LENGTH       ((uint16_t)0xF000U)
/**
  * @}
  */

/** @defgroup DP83848_IMR_ISFR_Bit_Definition DP83848 IMR ISFR Bit Definition
  * @{
  */
#define DP83848_INT_8       ((uint16_t)0x0100U)
#define DP83848_INT_7       ((uint16_t)0x0080U)
#define DP83848_INT_6       ((uint16_t)0x0040U)
#define DP83848_INT_5       ((uint16_t)0x0020U)
#define DP83848_INT_4       ((uint16_t)0x0010U)
#define DP83848_INT_3       ((uint16_t)0x0008U)
#define DP83848_INT_2       ((uint16_t)0x0004U)
#define DP83848_INT_1       ((uint16_t)0x0002U)
/**
  * @}
  */

/** @defgroup DP83848_PHYSCSR_Bit_Definition DP83848 PHYSCSR Bit Definition
  * @{
  */
#define DP83848_PHYSCSR_AUTONEGO_DONE   ((uint16_t)0x100U)
#define DP83848_PHYSCSR_HCDSPEEDMASK    ((uint16_t)0x006U)
#define DP83848_PHYSCSR_10BT_HD         ((uint16_t)0x002U)
#define DP83848_PHYSCSR_10BT_FD         ((uint16_t)0x006U)
#define DP83848_PHYSCSR_100BTX_HD       ((uint16_t)0x000U)
#define DP83848_PHYSCSR_100BTX_FD       ((uint16_t)0x004U)
/**
  * @}
  */

/** @defgroup DP83848_Status DP83848 Status
  * @{
  */

#define  DP83848_STATUS_READ_ERROR            ((int32_t)-5)
#define  DP83848_STATUS_WRITE_ERROR           ((int32_t)-4)
#define  DP83848_STATUS_ADDRESS_ERROR         ((int32_t)-3)
#define  DP83848_STATUS_RESET_TIMEOUT         ((int32_t)-2)
#define  DP83848_STATUS_ERROR                 ((int32_t)-1)
#define  DP83848_STATUS_OK                    ((int32_t) 0)
#define  DP83848_STATUS_LINK_DOWN             ((int32_t) 1)
#define  DP83848_STATUS_100MBITS_FULLDUPLEX   ((int32_t) 2)
#define  DP83848_STATUS_100MBITS_HALFDUPLEX   ((int32_t) 3)
#define  DP83848_STATUS_10MBITS_FULLDUPLEX    ((int32_t) 4)
#define  DP83848_STATUS_10MBITS_HALFDUPLEX    ((int32_t) 5)
#define  DP83848_STATUS_AUTONEGO_NOTDONE      ((int32_t) 6)
/**
  * @}
  */

/** @defgroup DP83848_IT_Flags DP83848 IT Flags
  * @{
  */
#define  DP83848_WOL_IT                        DP83848_INT_8
#define  DP83848_ENERGYON_IT                   DP83848_INT_7
#define  DP83848_AUTONEGO_COMPLETE_IT          DP83848_INT_6
#define  DP83848_REMOTE_FAULT_IT               DP83848_INT_5
#define  DP83848_LINK_DOWN_IT                  DP83848_INT_4
#define  DP83848_AUTONEGO_LP_ACK_IT            DP83848_INT_3
#define  DP83848_PARALLEL_DETECTION_FAULT_IT   DP83848_INT_2
#define  DP83848_AUTONEGO_PAGE_RECEIVED_IT     DP83848_INT_1
/**
  * @}
  */

/**
  * @}
  */

/* Exported types ------------------------------------------------------------*/
/** @defgroup DP83848_Exported_Types DP83848 Exported Types
  * @{
  */
typedef int32_t  (*dp83848_Init_Func) (void);
typedef int32_t  (*dp83848_DeInit_Func) (void);
typedef int32_t  (*dp83848_ReadReg_Func)   (uint32_t, uint32_t, uint32_t *);
typedef int32_t  (*dp83848_WriteReg_Func)  (uint32_t, uint32_t, uint32_t);
typedef int32_t  (*dp83848_GetTick_Func)  (void);

typedef struct
{
  dp83848_Init_Func      Init;
  dp83848_DeInit_Func    DeInit;
  dp83848_WriteReg_Func  WriteReg;
  dp83848_ReadReg_Func   ReadReg;
  dp83848_GetTick_Func   GetTick;
} dp83848_IOCtx_t;


typedef struct
{
  uint32_t            DevAddr;
  uint32_t            Is_Initialized;
  dp83848_IOCtx_t     IO;
  void               *pData;
}dp83848_Object_t;
/**
  * @}
  */

/* Exported macro ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup DP83848_Exported_Functions DP83848 Exported Functions
  * @{
  */
int32_t DP83848_RegisterBusIO(dp83848_Object_t *pObj, dp83848_IOCtx_t *ioctx);
int32_t DP83848_Init(dp83848_Object_t *pObj);
int32_t DP83848_DeInit(dp83848_Object_t *pObj);
int32_t DP83848_DisablePowerDownMode(dp83848_Object_t *pObj);
int32_t DP83848_EnablePowerDownMode(dp83848_Object_t *pObj);
int32_t DP83848_StartAutoNego(dp83848_Object_t *pObj);
int32_t DP83848_GetLinkState(dp83848_Object_t *pObj);
int32_t DP83848_SetLinkState(dp83848_Object_t *pObj, uint32_t LinkState);
int32_t DP83848_EnableLoopbackMode(dp83848_Object_t *pObj);
int32_t DP83848_DisableLoopbackMode(dp83848_Object_t *pObj);
int32_t DP83848_EnableIT(dp83848_Object_t *pObj, uint32_t Interrupt);
int32_t DP83848_DisableIT(dp83848_Object_t *pObj, uint32_t Interrupt);
int32_t DP83848_ClearIT(dp83848_Object_t *pObj, uint32_t Interrupt);
int32_t DP83848_GetITStatus(dp83848_Object_t *pObj, uint32_t Interrupt);
/**
  * @}
  */

#ifdef __cplusplus
}
#endif
#endif /* DP83848_H */


/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值