移植 NetXDuo 到 STM32F4 芯片

news2024/11/24 19:26:41

移植 NetXDuo 到 STM32F4 芯片

  • 1. NetXDuo 和 ThreadX 源码获取
  • 2. 准备工作
    • 2.1 基本工程模板获取 —— CubeMx
  • 3.ThreadX 移植
    • 3.1 添加到工程
    • 3.2 文件修改
    • 3.3 补充完成回调函数
  • 4. NetXDuo 移植
    • 4.1 将 NetXDuo 添加到工程
    • 4.2 驱动层实现
    • 4.3 测试

1. NetXDuo 和 ThreadX 源码获取

首先 NetxDuo 和 ThreadX 的源码位于 GitHub 上的连接位置:
ThreadX 源码
NetxDuo 源码

2. 准备工作

2.1 基本工程模板获取 —— CubeMx

略,请确保程序能够正常运行

3.ThreadX 移植

ThreadX 的移植不是本篇的重点,这里只是简要说明大致流程,详细请参考其它资料。

3.1 添加到工程

threadx 支持多核异构的 CPU, 其中单核 CPU 相关的源码位于 common 目录下,src 是源文件,inc 的头文件
将 ThreadX 添加到使用 CubeMx 生成的基本工程中:
common 目录下是 src 文件添加到了 ThreadX 目录下
在这里插入图片描述
port 文件是芯片相关的文件,导入threadx/ports/cortex-m4/ac6/src下的所有 *.s 文件,除了 tx_misra.S 不需要导入。
在这里插入图片描述
上方还有一个 tx_initialize_low_level.s 文件,这个是 threadx 需要的用于获取堆栈指针和中断向量表的实现函数,这个文件可以使用 threadx\ports\cortex_m4\ac6\example_build\sample_threadx 里的那个:
在这里插入图片描述

3.2 文件修改

tx_initialize_low_level.s 修改后的内容如下:

@/**************************************************************************/
@/*                                                                        */
@/*       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.                      */
@/*                                                                        */
@/**************************************************************************/
@
@
@/**************************************************************************/
@/**************************************************************************/
@/**                                                                       */
@/** ThreadX Component                                                     */
@/**                                                                       */
@/**   Initialize                                                          */
@/**                                                                       */
@/**************************************************************************/
@/**************************************************************************/
@
@
   .global     _tx_thread_system_stack_ptr
   .global     _tx_initialize_unused_memory
   .global     _tx_timer_interrupt
   .global     __main
   .global     __tx_SVCallHandler
   .global     __tx_PendSVHandler
   .global     __tx_NMIHandler                     @ NMI
   .global     __tx_BadHandler                     @ HardFault
   .global     __tx_SVCallHandler                  @ SVCall
   .global     __tx_DBGHandler                     @ Monitor
   .global     __tx_PendSVHandler                  @ PendSV
   .global     __tx_SysTickHandler                 @ SysTick
   .global     __tx_IntHandler                     @ Int 0
   .global     __Vectors						   @ 引入启动文件的中断量表标号
   .global     __initial_sp						   @ 引入启动文件的栈地址指针标号
@
@
SYSTEM_CLOCK      =   6000000
SYSTICK_CYCLES    =   ((SYSTEM_CLOCK / 100) -1)

   .text 32
   .align 4
   .syntax unified
@/**************************************************************************/
@/*                                                                        */
@/*  FUNCTION                                               RELEASE        */
@/*                                                                        */
@/*    _tx_initialize_low_level                          Cortex-M4/AC6     */
@/*                                                           6.1          */
@/*  AUTHOR                                                                */
@/*                                                                        */
@/*    William E. Lamie, Microsoft Corporation                             */
@/*                                                                        */
@/*  DESCRIPTION                                                           */
@/*                                                                        */
@/*    This function is responsible for any low-level processor            */
@/*    initialization, including setting up interrupt vectors, setting     */
@/*    up a periodic timer interrupt source, saving the system stack       */
@/*    pointer for use in ISR processing later, and finding the first      */
@/*    available RAM memory address for tx_application_define.             */
@/*                                                                        */
@/*  INPUT                                                                 */
@/*                                                                        */
@/*    None                                                                */
@/*                                                                        */
@/*  OUTPUT                                                                */
@/*                                                                        */
@/*    None                                                                */
@/*                                                                        */
@/*  CALLS                                                                 */
@/*                                                                        */
@/*    None                                                                */
@/*                                                                        */
@/*  CALLED BY                                                             */
@/*                                                                        */
@/*    _tx_initialize_kernel_enter           ThreadX entry function        */
@/*                                                                        */
@/*  RELEASE HISTORY                                                       */
@/*                                                                        */
@/*    DATE              NAME                      DESCRIPTION             */
@/*                                                                        */
@/*  09-30-2020     William E. Lamie         Initial Version 6.1           */
@/*                                                                        */
@/**************************************************************************/
@VOID   _tx_initialize_low_level(VOID)
@{
   .global  _tx_initialize_low_level
   .thumb_func
_tx_initialize_low_level:
@
@    /* Disable interrupts during ThreadX initialization.  */
@
   CPSID   i
@
@    /* Set base of available memory to end of non-initialised RAM area.  */
@
   LDR     r0, =_tx_initialize_unused_memory       @ Build address of unused memory pointer
   LDR     r1, =__initial_sp                       @ 修改为启动文件的栈指针(位于中断向量表前面)
   ADD     r1, r1, #4                              @
   STR     r1, [r0]                                @ Setup first unused memory pointer
@
@    /* Setup Vector Table Offset Register.  */
@
   MOV     r0, #0xE000E000                         @ Build address of NVIC registers
   LDR     r1, =__Vectors                          @ Pickup address of vector table 指向中断向量表
   STR     r1, [r0, #0xD08]                        @ Set vector table address
@
@    /* Set system stack pointer from vector value.  */
@
   LDR     r0, =_tx_thread_system_stack_ptr        @ Build address of system stack pointer
   LDR     r1, =__Vectors                          @ Pickup address of vector table 指向中断向量表
   LDR     r1, [r1]                                @ Pickup reset stack pointer
   STR     r1, [r0]                                @ Save system stack pointer
@
@    /* Enable the cycle count register.  */
@
   LDR     r0, =0xE0001000                         @ Build address of DWT register
   LDR     r1, [r0]                                @ Pickup the current value
   ORR     r1, r1, #1                              @ Set the CYCCNTENA bit
   STR     r1, [r0]                                @ Enable the cycle count register
@
@    /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference.  */
@
   MOV     r0, #0xE000E000                         @ Build address of NVIC registers
   LDR     r1, =SYSTICK_CYCLES
   STR     r1, [r0, #0x14]                         @ Setup SysTick Reload Value
   MOV     r1, #0x7                                @ Build SysTick Control Enable Value
   STR     r1, [r0, #0x10]                         @ Setup SysTick Control
@
@    /* Configure handler priorities.  */
@
   LDR     r1, =0x00000000                         @ Rsrv, UsgF, BusF, MemM
   STR     r1, [r0, #0xD18]                        @ Setup System Handlers 4-7 Priority Registers

   LDR     r1, =0xFF000000                         @ SVCl, Rsrv, Rsrv, Rsrv
   STR     r1, [r0, #0xD1C]                        @ Setup System Handlers 8-11 Priority Registers
                                                   @ Note: SVC must be lowest priority, which is 0xFF

   LDR     r1, =0x40FF0000                         @ SysT, PnSV, Rsrv, DbgM
   STR     r1, [r0, #0xD20]                        @ Setup System Handlers 12-15 Priority Registers
                                                   @ Note: PnSV must be lowest priority, which is 0xFF

@
@    /* Return to caller.  */
@
   BX      lr
@}
@

@/* Define shells for each of the unused vectors.  */
@
   .global  __tx_BadHandler
   .thumb_func
__tx_BadHandler:
   B       __tx_BadHandler

@ /* added to catch the hardfault */

   .global  __tx_HardfaultHandler
   .thumb_func
__tx_HardfaultHandler:
   B       __tx_HardfaultHandler


@ /* added to catch the SVC */

   .global  __tx_SVCallHandler
   .thumb_func
__tx_SVCallHandler:
   B       __tx_SVCallHandler


@ /* Generic interrupt handler template */
   .global  __tx_IntHandler
   .thumb_func
__tx_IntHandler:
@ VOID InterruptHandler (VOID)
@ {
   PUSH    {r0, lr}
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
   BL      _tx_execution_isr_enter             @ Call the ISR enter function
#endif

@    /* Do interrupt handler work here */
@    /* BL <your C Function>.... */

#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
   BL      _tx_execution_isr_exit              @ Call the ISR exit function
#endif
   POP     {r0, lr}
   BX      LR
@ }

@ /* System Tick timer interrupt handler */
@ 这里去除了 SysTick_Handler 的标号
   .global  __tx_SysTickHandler
   .thumb_func
__tx_SysTickHandler:
   .thumb_func
@ VOID TimerInterruptHandler (VOID)
@ {
@
   PUSH    {r0, lr}
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
   BL      _tx_execution_isr_enter             @ Call the ISR enter function
#endif
   BL      _tx_timer_interrupt
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
   BL      _tx_execution_isr_exit              @ Call the ISR exit function
#endif
   POP     {r0, lr}
   BX      LR
@ }


@ /* NMI, DBG handlers */
   .global  __tx_NMIHandler
   .thumb_func
__tx_NMIHandler:
   B       __tx_NMIHandler

   .global  __tx_DBGHandler
   .thumb_func
__tx_DBGHandler:
   B       __tx_DBGHandler

上面主要修改了3个点:

  • 中断向量表,采用了启动文件中的中断向量表
  • 栈指针,使用在启动文件中设置的栈指针
  • 去除了 SysTick_Handler 的标号,这样中断触发时,会进入到 CubeMx 生成的 SysTick_Handler 里面执行,在此我们同时可以递增 HAL 库的基准时间,具体修改如下:
/**
 * @brief This function handles System tick timer.
 */
void SysTick_Handler(void)
{
 /* USER CODE BEGIN SysTick_IRQn 0 */
 extern void __tx_SysTickHandler(void);
 __tx_SysTickHandler();
 /* USER CODE END SysTick_IRQn 0 */
 HAL_IncTick();
 /* USER CODE BEGIN SysTick_IRQn 1 */

 /* USER CODE END SysTick_IRQn 1 */
}

同理修改 tx_thread_schedule.s 文件,主要是去掉 PendSV_Handler,由 HAL 库的中断来调用 _tx_PendSVHandler
在这里插入图片描述
在这里插入图片描述

3.3 补充完成回调函数

补充完成 tx_application_define 回调函数
在这里插入图片描述
用户通过 tx_kernel_enter 将程序控制权交由 threadx 进行控制:
在这里插入图片描述
在主循环中要记得添加 tx_thread_sleep 函数,以便进行线程调度。

4. NetXDuo 移植

4.1 将 NetXDuo 添加到工程

同样位于 netxdou\common 目录下的 src 添加到工程里面,ports/cortex_m4/ac6/src 添加到 port 目录下:
(但其实 port 目录下并没有 src 文件,原因是这需要我们自己实现)
在这里插入图片描述
ST 提供了一套 Azrtos 的软件包,里面切好有基于 ST 芯片以太网的 netxduo 驱动实现,软件包位于 GitHub 或者在 ST 的官网搜索 Cube Azrtos f4 找到软件包 软件包的下载页面
在这里插入图片描述
下载后从 en.x-cube-azrtos-f4\Middlewares\ST\netxduo\common\drivers 目录下获取我们需要的驱动:
由于本篇使用的是以太网,因此拷贝以太网的代码
在这里插入图片描述

4.2 驱动层实现

以太网的 PHY 芯片驱动需要我们根据 datasheet 自己实现,这里实现了 lan8720a 芯片的驱动,附上源码:
lan8720.h

#ifndef __LAN8720_H__
#define __LAN8720_H__

#include <stdint.h>

#define LAN8720_PHY_ADDR	0x00
 
#define LAN8720_BCR		0x00
	#define LAN8720_BCR_SOFT_RESET           ((uint16_t)0x8000U)
	#define LAN8720_BCR_LOOPBACK             ((uint16_t)0x4000U)
	#define LAN8720_BCR_SPEED_SELECT         ((uint16_t)0x2000U)
	#define LAN8720_BCR_AUTONEGO_EN          ((uint16_t)0x1000U)
	#define LAN8720_BCR_POWER_DOWN           ((uint16_t)0x0800U)
	#define LAN8720_BCR_ISOLATE              ((uint16_t)0x0400U)
	#define LAN8720_BCR_RESTART_AUTONEGO     ((uint16_t)0x0200U)
	#define LAN8720_BCR_DUPLEX_MODE          ((uint16_t)0x0100U) 
	
#define LAN8720_BSR		                    ((uint16_t)0x01) 				/* PHY status register Offset */ 
	#define LAN8720_BSR_100BASE_T4           ((uint16_t)0x8000U)
	#define LAN8720_BSR_100BASE_TX_FD        ((uint16_t)0x4000U)
	#define LAN8720_BSR_100BASE_TX_HD        ((uint16_t)0x2000U)
	#define LAN8720_BSR_10BASE_T_FD          ((uint16_t)0x1000U)
	#define LAN8720_BSR_10BASE_T_HD          ((uint16_t)0x0800U)
	#define LAN8720_BSR_100BASE_T2_FD        ((uint16_t)0x0400U)
	#define LAN8720_BSR_100BASE_T2_HD        ((uint16_t)0x0200U)
	#define LAN8720_BSR_EXTENDED_STATUS      ((uint16_t)0x0100U)
	#define LAN8720_BSR_AUTONEGO_CPLT        ((uint16_t)0x0020U)
	#define LAN8720_BSR_REMOTE_FAULT         ((uint16_t)0x0010U)
	#define LAN8720_BSR_AUTONEGO_ABILITY     ((uint16_t)0x0008U)
	#define LAN8720_BSR_LINK_STATUS          ((uint16_t)0x0004U)
	#define LAN8720_BSR_JABBER_DETECT        ((uint16_t)0x0002U)
	#define LAN8720_BSR_EXTENDED_CAP         ((uint16_t)0x0001U)

#define LAN8720_PHYSMR  				     ((uint16_t)17)
	#define LAN8720_PHYSMR_AUTONEGO_MASK    ((uint16_t)0x000F)
	#define LAN8720_PHYSMR_AUTONEGO_DONE    ((uint16_t)0x0008U)
	
	#define LAN8720_PHYSMR_HCDSPEEDMASK     ((uint16_t)0x00E0)
	#define LAN8720_PHYSMR_10BT_HD          ((uint16_t)0x0040)
	#define LAN8720_PHYSMR_10BT_FD          ((uint16_t)0x0060)
	#define LAN8720_PHYSMR_100BTX_HD        ((uint16_t)0x0080)
	#define LAN8720_PHYSMR_100BTX_FD        ((uint16_t)0x00c0) 

#endif // End of __LAN8720_H__

lan8720.c

#include "lan8720.h"
#include "nx_api.h"
#include "nx_stm32_phy_driver.h"

#define LAN8720_SW_RESET_TO ((uint32_t)500U)
#define LAN8720_INIT_TO ((uint32_t)2000U)

int32_t Phy_RegisterBusIO(nx_eth_phy_object_t *pObj, nx_eth_phy_ioctx_t *ioctx)
{
    if (!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick)
    {
        return ETH_PHY_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 ETH_PHY_STATUS_OK;
}

int32_t Phy_Init(nx_eth_phy_object_t *pObj)
{
    uint32_t tickstart = 0, regvalue = 0;
    int32_t status = ETH_PHY_STATUS_OK;

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

        /* for later check */
        pObj->DevAddr = LAN8720_PHY_ADDR;

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

                    /* wait until software reset is done or timeout occured  */
                    while (regvalue & LAN8720_BCR_SOFT_RESET)
                    {
                        if ((pObj->IO.GetTick() - tickstart) <= LAN8720_SW_RESET_TO)
                        {
                            if (pObj->IO.ReadReg(pObj->DevAddr, LAN8720_BCR, &regvalue) < 0)
                            {
                                status = ETH_PHY_STATUS_ERROR;
                                break;
                            }
                        }
                        else
                        {
                            status = ETH_PHY_STATUS_RESET_TIMEOUT;
                        }
                    }
                }
                else
                {
                    status = ETH_PHY_STATUS_READ_ERROR;
                }
            }
            else
            {
                status = ETH_PHY_STATUS_WRITE_ERROR;
            }
        }
    }

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

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

    return status;
}

int32_t Phy_SetLinkState(nx_eth_phy_object_t *pObj, int32_t LinkState)
{
    return ETH_PHY_STATUS_OK;
}

int32_t Phy_GetLinkState(nx_eth_phy_object_t *pObj)
{
    uint32_t readval = 0;

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

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

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

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

    if ((readval & LAN8720_BCR_AUTONEGO_EN) != LAN8720_BCR_AUTONEGO_EN)
    {
        if (((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT) && ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE))
        {
            return ETH_PHY_STATUS_100MBITS_FULLDUPLEX;
        }
        else if ((readval & LAN8720_BCR_SPEED_SELECT) == LAN8720_BCR_SPEED_SELECT)
        {
            return ETH_PHY_STATUS_100MBITS_HALFDUPLEX;
        }
        else if ((readval & LAN8720_BCR_DUPLEX_MODE) == LAN8720_BCR_DUPLEX_MODE)
        {
            return ETH_PHY_STATUS_10MBITS_FULLDUPLEX;
        }
        else
        {
            return ETH_PHY_STATUS_10MBITS_HALFDUPLEX;
        }
    }
    else /* Auto Nego enabled */
    {
        if ((readval & LAN8720_PHYSMR_HCDSPEEDMASK) == LAN8720_PHYSMR_100BTX_FD)
        {
            return ETH_PHY_STATUS_100MBITS_FULLDUPLEX;
        }
        else if ((readval & LAN8720_PHYSMR_HCDSPEEDMASK) == LAN8720_PHYSMR_100BTX_HD)
        {
            return ETH_PHY_STATUS_100MBITS_HALFDUPLEX;
        }
        else if ((readval & LAN8720_PHYSMR_HCDSPEEDMASK) == LAN8720_PHYSMR_10BT_FD)
        {
            return ETH_PHY_STATUS_10MBITS_FULLDUPLEX;
        }
        else
        {
            return ETH_PHY_STATUS_10MBITS_HALFDUPLEX;
        }
    }
}

此处对 nx_stm32_phy_driver.c 文件进行了修改,两个文件修改后如下:
nx_stm32_phy_driver.h


/**************************************************************************/
/*                                                                        */
/*       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.                      */
/*                                                                        */
/**************************************************************************/


#ifndef NX_STM32_PHY_DRIVER_H
#define NX_STM32_PHY_DRIVER_H

#ifdef   __cplusplus
extern   "C" {
#endif
#include <stdint.h>

#define  ETH_PHY_STATUS_READ_ERROR               ((int32_t)-5)
#define  ETH_PHY_STATUS_WRITE_ERROR              ((int32_t)-4)
#define  ETH_PHY_STATUS_ADDRESS_ERROR            ((int32_t)-3)
#define  ETH_PHY_STATUS_RESET_TIMEOUT            ((int32_t)-2)
#define  ETH_PHY_STATUS_ERROR                    ((int32_t)-1)
#define  ETH_PHY_STATUS_OK                       ((int32_t) 0)

#define  ETH_PHY_STATUS_LINK_ERROR               ((int32_t) 0)
#define  ETH_PHY_STATUS_LINK_DOWN                ((int32_t) 1)
#define  ETH_PHY_STATUS_100MBITS_FULLDUPLEX      ((int32_t) 2)
#define  ETH_PHY_STATUS_100MBITS_HALFDUPLEX      ((int32_t) 3)
#define  ETH_PHY_STATUS_10MBITS_FULLDUPLEX       ((int32_t) 4)
#define  ETH_PHY_STATUS_10MBITS_HALFDUPLEX       ((int32_t) 5)
#define  ETH_PHY_STATUS_AUTONEGO_NOT_DONE        ((int32_t) 6)

#if defined(ETH_PHY_1000MBITS_SUPPORTED)
#define  ETH_PHY_STATUS_1000MBITS_FULLDUPLEX  ((int32_t) 7)
#define  ETH_PHY_STATUS_1000MBITS_HALFDUPLEX  ((int32_t) 8)
#endif

typedef int32_t  (*nx_eth_phy_init_func)(void);
typedef int32_t  (*nx_eth_phy_deinit_func)(void);
typedef int32_t  (*nx_eth_phy_read_reg_func)(uint32_t, uint32_t, uint32_t *);
typedef int32_t  (*nx_eth_phy_write_reg_func)(uint32_t, uint32_t, uint32_t);
typedef uint32_t  (*nx_eth_phy_get_tick_func)(void);

typedef struct
{
    nx_eth_phy_init_func        Init;
    nx_eth_phy_deinit_func      DeInit;
    nx_eth_phy_write_reg_func   WriteReg;
    nx_eth_phy_read_reg_func    ReadReg;
    nx_eth_phy_get_tick_func    GetTick;
} nx_eth_phy_ioctx_t;

typedef struct 
{
  uint32_t              DevAddr;
  uint32_t              Is_Initialized;
  nx_eth_phy_ioctx_t    IO;
  void                  *pData;
} nx_eth_phy_object_t;

typedef void * 	nx_eth_phy_handle_t;

int32_t nx_eth_phy_init(void);

int32_t nx_eth_phy_get_link_state(void);

int32_t nx_eth_phy_set_link_state(int32_t linkstate);

nx_eth_phy_handle_t nx_eth_phy_get_handle(void);

#ifdef   __cplusplus
}
#endif
#endif

nx_stm32_phy_driver.c


/**************************************************************************/
/*                                                                        */
/*       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.                      */
/*                                                                        */
/**************************************************************************/
#include "tx_api.h"
#include "nx_stm32_phy_driver.h"
#include "nx_stm32_eth_config.h"

int32_t nx_eth_phy_io_init(void);
int32_t nx_eth_phy_io_deinit(void);
int32_t nx_eth_phy_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal);
int32_t nx_eth_phy_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal);
uint32_t nx_eth_phy_io_get_tick(void);

extern int32_t Phy_RegisterBusIO(nx_eth_phy_object_t *pObj, nx_eth_phy_ioctx_t *ioctx);
extern int32_t Phy_Init(nx_eth_phy_object_t *pObj);
extern int32_t Phy_SetLinkState(nx_eth_phy_object_t *pObj, int32_t LinkState);
extern int32_t Phy_GetLinkState(nx_eth_phy_object_t *pObj);

/* eth_phy_chip IO context object */
static nx_eth_phy_ioctx_t ETH_PHY_IOCtx =
{
    .Init     = nx_eth_phy_io_init,
    .DeInit   = nx_eth_phy_io_deinit,
    .WriteReg = nx_eth_phy_io_write_reg,
    .ReadReg  = nx_eth_phy_io_read_reg,
    .GetTick  = nx_eth_phy_io_get_tick
};
/* eth_phy_chip main object */
static nx_eth_phy_object_t eth_phy_chip;

/**
 * @brief  Initialize the PHY interface
 * @param  none
 * @retval ETH_PHY_STATUS_OK on success, ETH_PHY_STATUS_ERROR otherwise
 */

int32_t nx_eth_phy_init(void)
{
    int32_t ret = ETH_PHY_STATUS_ERROR;
    /* Set PHY IO functions */

    Phy_RegisterBusIO(&eth_phy_chip, &ETH_PHY_IOCtx);
    /* Initialize the eth_phy_chip ETH PHY */

    if (Phy_Init(&eth_phy_chip) == ETH_PHY_STATUS_OK)
    {
        ret = ETH_PHY_STATUS_OK;
    }

    return ret;
}

/**
 * @brief  set the Phy link state.
 * @param  LinkState
 * @retval the link status.
 */

int32_t nx_eth_phy_set_link_state(int32_t LinkState)
{
    return (Phy_SetLinkState(&eth_phy_chip, LinkState));
}

/**
 * @brief  get the Phy link state.
 * @param  none
 * @retval the link status.
 */

int32_t nx_eth_phy_get_link_state(void)
{
    int32_t linkstate = Phy_GetLinkState(&eth_phy_chip);

    return linkstate;
}

/**
 * @brief  get the driver object handle
 * @param  none
 * @retval pointer to the eth_phy_chip main object
 */

nx_eth_phy_handle_t nx_eth_phy_get_handle(void)
{
    return (nx_eth_phy_handle_t)&eth_phy_chip;
}

/**
 * @brief  Initialize the PHY MDIO interface
 * @param  None
 * @retval 0 if OK, -1 if ERROR
 */

int32_t nx_eth_phy_io_init(void)
{
    return ETH_PHY_STATUS_OK;
}

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

/**
 * @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 nx_eth_phy_io_read_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal)
{
    if (HAL_ETH_ReadPHYRegister(&eth_handle, DevAddr, RegAddr, pRegVal) != HAL_OK)
    {
        return ETH_PHY_STATUS_ERROR;
    }

    return ETH_PHY_STATUS_OK;
}

int32_t nx_eth_phy_io_write_reg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal)
{
    if (HAL_ETH_WritePHYRegister(&eth_handle, DevAddr, RegAddr, RegVal) != HAL_OK)
    {
        return ETH_PHY_STATUS_ERROR;
    }

    return ETH_PHY_STATUS_OK;
}

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

自此驱动层就移植完毕了。

4.3 测试

实测了大概 一个小时,都没有出现问题~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1071321.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RT-Thread 中断管理(学习二)

中断的底半处理 RT-Thread不对中断服务程序所需要的处理时间做任何假设、限制&#xff0c;但如同其它实时操作系统或非实时操作系统一样&#xff0c;用户需要保证所有的中断服务程序在尽可能短的时间内完成。这样在发生中断嵌套&#xff0c;或屏蔽了相应中断源的过程中&#x…

小黑开始了拉歌训练,第一次进入部室馆,被通知要去当主持人心里有些紧张的leetcode之旅:337. 打家劫舍 III

小黑代码&#xff08;小黑卡在了bug中&#xff0c;上午一步步探索做出&#xff0c;非常NB!!!&#xff09; # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left lef…

Hive窗口函数回顾

1.语法 1.1 基于行的窗口函数 Hive的窗口函数分为两种类型&#xff0c;一种是基于行的窗口函数&#xff0c;即将某个字段的多行限定为一个范围&#xff0c;对范围内的字段值进行计算&#xff0c;最后将形成的字段拼接在该表上。 注意&#xff1a;在进行窗口函数计算之前&#…

X86指令基本格式

X86指令基本格式 1 什么是机器码2 X86指令基本格式3 指令前缀3.1 第一组&#xff1a;封锁和重复执行前缀3.2 第二组&#xff1a;段前缀3.3 第三组&#xff1a;修改操作数默认长度3.4 第四组&#xff1a;修改默认地址长度 4 操作码5 ModR/M与SIB5.1 ModR/M字节5.2 SIB字节 6 地址…

uCharts常用图表组件demo

带渐变阴影的曲线图 <view class"charts-box"><qiun-data-charts type"area" :opts"opts" :chartData"chartData" :ontouch"true":background"rgba(256,256,256,0)" /> </view>data(){return{…

嵌入式学习(1)HAL库

文章目录 1.HAL库文件介绍2.HAL库编程目录结构3.使用cubemx生成HAL库编程目录结构 1.HAL库文件介绍 2.HAL库编程目录结构 3.使用cubemx生成HAL库编程目录结构

【JavaEE重点知识归纳】第7节:类和对象

目录 一&#xff1a;了解面向对象 1.什么是面向对象 2.面向对象和面向过程区分 二&#xff1a;类定义和使用 1.什么是类 2.练习&#xff1a;定义一个学生类 三&#xff1a;类的实例化 1.什么是实例化 2.类和对象的说明 四&#xff1a;认识this 1.为什么要有this引用…

rails 常量自动加载和重新加载机制

在Rails中&#xff0c;有一个称为"常量自动加载和重新加载机制"的功能&#xff0c;它使得在开发和生产环境中能够自动加载和重新加载类和模块。这个机制允许您不必手动管理类的加载&#xff0c;使得开发更加方便。 快乐学习&#xff1a; 自动加载、重新加载 自动加…

Yii2全拦截路由catchAll的使用

定义&#xff1a;catchAll 路由&#xff08;全拦截路由&#xff09; 应用场景&#xff1a;网站维护的时候需要向用户抛出一个维护的页面&#xff0c;方便提醒用户 使用方法&#xff1a; 1、在应用配置中设置 yii\web\Application::catchAll 属性 2、新增对应的控制器方法 3、…

【Putty】win10 / win 11:SSH 远程连接工具 Putty 下载、安装

目录 一、Jmerter 连接 SSH 隧道的 mysql&#xff08;不可行&#xff09; 二、Putty 介绍 三、Putty 的下载 四、Putty 无需安装直接使用 五、Putty 使用 &#xff08;1&#xff09;我需要连接 ssh 隧道的 MySQL 参数如下 &#xff08;2&#xff09;Putty 使用教程 一、…

MA-SAM:模态不可知的三维医学图像分割SAM自适应

论文&#xff1a;MA-SAM: Modality-agnostic SAM Adaptation for 3D Medical Image Segmentation | Papers With Code 代码&#xff1a;GitHub - cchen-cc/MA-SAM: PyTorch implementation for MA-SAM 机构&#xff1a;a)高级医疗计算和分析中心&#xff0c;麻省总医院和哈佛…

华为云开源低代码引擎 TinyEngine 正式发布

随着企业对于低代码开发平台的需求日益增长,急需一个通用的解决方案来满足各种低代码平台的开发需求。正是在这种情况下,低代码引擎应运而生。它是一种通用的开发框架,通过对低代码平台系统常用的功能进行解构,将其划分为多个功能模块,并为每个模块定义了相应的协议和开发…

Go 语言中 panic 和 recover 搭配使用

本次主要聊聊 Go 语言中关于 panic 和 recover 搭配使用 &#xff0c;以及 panic 的基本原理 最近工作中审查代码的时候发现一段代码&#xff0c;类似于如下这样&#xff0c;将 recover 放到一个子协程里面&#xff0c;期望去捕获主协程的程序异常 看到此处&#xff0c;是否会…

传输层TCP协议

前言 传输层的历史渊源可以追溯到计算机网络的早期阶段。在20世纪60年代和70年代&#xff0c;计算机网络主要是由一些简单的点对点连接组成的。这些连接通常使用专用的硬件和协议&#xff0c;例如串行线路和电话线路。在这种情况下&#xff0c;传输层的功能是由这些协议本身来提…

【SpringCloud】认识微服务

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 Redis 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 认识微服务 一、 服务架构演变1.1 单体架构…

Qt之进程通信-QProcess(含源码+注释)

文章目录 一、QProcess进程通信示例二、QProcess通信个人理解三、源码MainWindowProcessSenderMainWindowProcessSender.hMainWindowProcessSender.cppMainWindowProcessSender.ui MainWindowProcessRecvMainWindowProcessRecv.hMainWindowProcessRecv.cppMainWindowProcessRec…

【算法——双指针】LeetCode 18 四数之和

题目描述&#xff1a; 解题思路&#xff1a;双指针 四数之和与前面三数之和思路一样&#xff0c;排序后&#xff0c;枚举 nums[a]作为第一个数&#xff0c;枚举 nums[b]作为第二个数&#xff0c;那么问题变成找到另外两个数&#xff0c;使得这四个数的和等于 target&#xff0c…

吃鸡玩家必备神器!一站式提升战斗力、分享干货!

大家好&#xff0c;我是吃鸡玩家。在这个视频中&#xff0c;我要分享一个让你瞬间提高战斗力的神器&#xff0c;同时让你享受到顶级游戏作战干货的盛宴&#xff01;让我们一起来了解吧&#xff01; 首先&#xff0c;我们推荐绝地求生作图工具。通过这款工具&#xff0c;你可以轻…

用这些IDEA插件,让你早下班两小时

GenerateAllSetter:一键调用一个对象的所有setter方法 RestfulTool:自动显示所有URL接口&#xff0c;快速检索接口 SequenceDiagram:以图形界面形式显示方法调用链&#xff0c;方便阅读源码、梳理代码 CamelCase:变量下划线转驼峰命名 Rainbow Brackets:帮助程序员识别代码中括…

十五、异常(5)

本章概要 异常限制构造器 异常限制 当覆盖方法的时候&#xff0c;只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用&#xff0c;因为这意味着与基类一起工作的代码&#xff0c;也能和导出类一起正常工作&#xff08;这是面向对象的基本概念&#xff09;&#…