【STM32H7】第6章 ThreadX NetXDUO网络协议栈移植到STM32H7

2023-04-23  

6.1 初学者重要提示

1、 网口使用的是DM9161/9162(紧挨着9帧串口座的网口),而不是DM9000。

2、 本章是以MDK AC5移植为例进行说明,如果大家要移植到其它IDE,方法是一样的,本教程就不做说明了,下面的例子移植了各种IDE:

ThreadX全家桶所有组件综合模板发布,史上最强安全认证综合模板,稳如泰山,含AC5,AC6,IAR和GCC:

armbbs.cn/forum.php?

3、 测试例子,务必看本章6.7小节的操作步骤,采用的固定IP。

6.2 第1步,准备一个工程模板

为了方便大家移植,需要大家先对移植好的工程有个整体认识:

6.3 第2步,添加NetXDUO和ETH驱动到工程

大家可以使用ThreadX内核教程配套的例子作为模板使用,在模板的基础上需要添加NetXDUO文件,PHY芯片驱动文件和以太网驱动文件,大家可以直接从本章教程提供的例子里面复制。

PHY芯片DM9162的驱动文件dm9162.c和dm9162.h添加到自己的工程里面,路径不限。配套例子是放在Usernetx文件。

以太网驱动文件stm32h7xx_hal_eth.c,这个是STM32H7的HAL库自带的。

NetXDUO相关源文件。

大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在NetXDUO。


6.4 第3步,初始化文件nx_stm32_eth_driver.c

这个文件比较重要,是NetXDUO的接口文件。这里将关键的几个地方为大家做个说明。


6.4.1 以太网描述符和收发缓冲区定

以太网描述符和收发缓冲区定义如下,定义了MDK AC5,MDK AC6,IAR和GCC:


/* Ethernet Rx DMA 描述符 */

__attribute__((at(0x30040000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; 


/* Ethernet Tx DMA 描述符 */

__attribute__((at(0x30040060))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; 


/* Ethernet 接收缓冲 */

__attribute__((at(0x30040200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE];


#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_TX_DESC_CNT和ETH_RX_DESC_CNT在stm32h7xx_hal_conf.h文件里面:


#define ETH_TX_DESC_CNT 4 /* number of Ethernet Tx DMA descriptors */ #define ETH_RX_DESC_CNT 4 /* number of Ethernet Rx DMA descriptors */

有了这些认识后,还有一个关键点要认识到,H7的以太网收发描述符和收发缓存最好都定义到D2域的SRAM3空间,首地址是0x3004 0000,总大小32KB。


6.4.2 以太网引脚,时钟和中断配置

初始化部分:

void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)

    GPIO_InitTypeDef GPIO_InitStruct;


    /*

        PC1     ------> ETH_MDC

        PA1     ------> ETH_REF_CLK

        PA2     ------> ETH_MDIO

        PA7     ------> ETH_CRS_DV

        PC4     ------> ETH_RXD0

        PC5     ------> ETH_RXD1

        PB13    ------> ETH_TXD1

        PG11    ------> ETH_TX_EN

        PG13    ------> ETH_TXD0 

    */


        /* 使能外设时钟 */

        __HAL_RCC_ETH1MAC_CLK_ENABLE();

        __HAL_RCC_ETH1TX_CLK_ENABLE();

        __HAL_RCC_ETH1RX_CLK_ENABLE();


        /* 使能时钟 */

        __HAL_RCC_GPIOA_CLK_ENABLE();

        __HAL_RCC_GPIOB_CLK_ENABLE();

        __HAL_RCC_GPIOC_CLK_ENABLE();

        __HAL_RCC_GPIOG_CLK_ENABLE();


        

        /* 配置PA1, PA2 , PA7 */

        GPIO_InitStruct.Pin =  GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;

        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

        GPIO_InitStruct.Pull = GPIO_NOPULL ; 

        GPIO_InitStruct.Alternate = GPIO_AF11_ETH;

        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


        /* 配置PB13 */

        GPIO_InitStruct.Pin = GPIO_PIN_13;

        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


        /* 配置PC1, PC4和PC5 */

        GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; 

        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);    


        /* 配置PG11, PG12和PG13 */

        GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_13;

        HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);


        /* 设置中断优先级 */

        HAL_NVIC_SetPriority(ETH_IRQn, 0, 0);

        HAL_NVIC_EnableIRQ(ETH_IRQn);    

}

这里要注意以太网中断优先级的配置,这里是将中断优先级配置为0。


以太网中断服务程序

/*

*********************************************************************************************************

*    函 数 名: ETH_IRQHandler

*    功能说明: 以太网回调函数

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

void ETH_IRQHandler(void)

{

    HAL_ETH_IRQHandler(&heth);

}

中断服务程序里面的这个全局变量heth是在nx_stm32_eth_driver.c文件开头定义的。


6.4.3 PHY芯片DM9162驱动

DM9162的驱动在DM9162.c文件实现,被文件nx_stm32_eth_driver.c中的函数_nx_driver_hardware_initialize调用,用于获取网线接线状态,网速等信息。


  /* Initialize the DM9162 ETH PHY */

    DM9162_Init(&DM9162);


    PHYLinkState = DM9162_GetLinkState(&DM9162);


    while(PHYLinkState <= DM9162_STATUS_LINK_DOWN)

    {

        PHYLinkState = DM9162_GetLinkState(&DM9162);

        tx_thread_sleep(100);

    }

 

    switch (PHYLinkState)

    {

      case DM9162_STATUS_100MBITS_FULLDUPLEX:

        duplex = ETH_FULLDUPLEX_MODE;

        speed = ETH_SPEED_100M;

        break;

      case DM9162_STATUS_100MBITS_HALFDUPLEX:

        duplex = ETH_HALFDUPLEX_MODE;

        speed = ETH_SPEED_100M;

        break;

      case DM9162_STATUS_10MBITS_FULLDUPLEX:

        duplex = ETH_FULLDUPLEX_MODE;

        speed = ETH_SPEED_10M;

        break;

      case DM9162_STATUS_10MBITS_HALFDUPLEX:

        duplex = ETH_HALFDUPLEX_MODE;

        speed = ETH_SPEED_10M;

        break;

      default:

        duplex = ETH_FULLDUPLEX_MODE;

        speed = ETH_SPEED_100M;

        break;

    }

6.5 第4步,MPU配置文件bsp.c

这个bsp.c文件也比较重要,




移植阶段,直接将我们移植好的模板内容复制过去即可。这个里面最重要的就是以太网收发描述符地址区的MPU配置:


/*

*********************************************************************************************************

*    函 数 名: MPU_Config

*    功能说明: 配置MPU

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

static void MPU_Config( void )

{

    MPU_Region_InitTypeDef MPU_InitStruct;


    /* 禁止 MPU */

    HAL_MPU_Disable();

    

    省略未写

    /* 配置以太网收发描述符部分为Strongly Ordered */

    MPU_InitStruct.Enable = MPU_REGION_ENABLE;

    MPU_InitStruct.BaseAddress = 0x30040000;

    MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;

    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);

}



务必要关闭以太网收发描述的Cache。


6.6 第5步,创建应用任务

这里将NetXDUO应用专门整理到了文件demo_dm9162_netx.c。大家可以直接将这个文件添加到自己的工程里面。

6.7 第6步,添加头文件路径

NetXDUO需要添加的头文件如下:

6.8 网络调试助手和板子的调试操作步骤

我们这里使用下面这款调试助手,当然,任何其它网络调试助手均可,不限制:

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。