zoukankan      html  css  js  c++  java
  • 【STM32H7】第6章 ThreadX NetXDUO网络协议栈移植到STM32H7

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=104619

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

    本章教程为大家讲解NetXDUO的移植。

    6.1 初学者重要提示

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

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

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

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

    6.6 第5步,创建应用任务

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

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

    6.9 总结

    6.1   初学者重要提示

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

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

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

    http://www.armbbs.cn/forum.php?mod=viewthread&tid=103554

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

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

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

     

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

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

    •   PHY芯片DM9162的驱动文件dm9162.c和dm9162.h添加到自己的工程里面,路径不限。配套例子是放在User etx文件。
    •   以太网驱动文件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   网络调试助手和板子的调试操作步骤

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

     http://www.armbbs.cn/forum.php?mod=viewthread&tid=1568

    6.8.1      测试使用的DM916X网口并注意跳线帽

    测试时,网线要插到DM916X网口上:

     

    特别注意此处跳线帽的位置,要短接PG11:

     

    6.8.2      RJ45网络变压器插座上绿灯和黄灯现象

    各种网卡、交换机等网络设备都不一样,一般来讲:绿灯分为亮或不亮(代表网络速度),黄灯分为闪烁或不闪烁(代表是否有数据收发)。

    绿灯:长亮代表100M; 不亮代表10M。

    黄灯:长亮代表无数据收发; 闪烁代表有数据收发。

    也有些千兆网卡的灯以颜色区分,不亮代表10M / 绿色代表100M / 黄色代表1000M。现在10M的网络基本看不到了,如果一个灯长亮,基本可以说明100M网络或更高,而另一个灯时而闪烁,那代表有数据收发,具体要看网络设备了。甚至有些低等网卡如TP-LINK,只有一个灯,亮代表连通,闪烁代表数据收发。

    对于开发板上面的RJ45网络变压器插座上面的灯而言,绿灯代表数据收发,长亮的话表示无数据收发,闪烁代表有数据收发。黄灯代表网络速度,长亮代表100M,不亮代表10M。

    6.8.3      第1步,设置板子IP地址

    我们这里使用使用固定IP(或者说静态IP一个意思),设置也比较省事。我们这里以开发板和电脑直连的方式进行说明,即通过一根网线直接将开发板的网口和电脑端的网口连接起来即可。如果大家使用的是笔记本,强烈推荐测试期间将笔记本的WIFI网络禁止,各种代理软件和虚拟网卡也暂时关闭。等测试完毕了再逐一打开,查看是否有问题。

    对于固定IP方式,也可以接到路由器或者交换机上面测试,特别注意板子设置的IP地址不要跟路由器或者交换机上其它设备的IP冲突了,测试阶段还是建议采用电脑直连方式,跑通了再跑其它方式。

    在文件demo_dm9162_netx.h中设置IP地址,具体配置如下(大家更新自己的情况修改):

    /*
    *********************************************************************************************************
    *                                        IP相关
    *********************************************************************************************************
    */
    #define DEFAULT_PORT                    1001    /* TCP服务器监听端口号 */
    
    #define IP_ADDR0                        192
    #define IP_ADDR1                        168
    #define IP_ADDR2                        28
    #define IP_ADDR3                        245     

    6.8.4      第2步,设置电脑IP地址

    一定要将电脑端的IP地址设置到跟开发板在一个IP段,即都是192.168.28.X。第2步中已经将开发板的IP设置为192.168.28.245,我们这里就将电脑的IP设置为192.168.28.221。我这里是WIN7 64bit系统。

    (1)右击桌面上的“网络”图标,选择属性。

     

    (2)弹出的界面中选项“本地连接”

     

    (3)选择“属性(P)”

     

    (4)双击“Internet协议版本4(TCP/Ipv4)”选项。

     

    (5)配置IP地址、子网掩码和默认网关,DNS无需配置。

     

    (6)点击了“确定”按钮后,退回到之前的界面,这里的“确定”按钮不要忘了点击:

     

    6.8.5      第3步,测试ping是否成功

    下载例程到开发板,然后ping 192.168.28.245,查看是否连接上。

    (1)WIN+R组合键打开“运行”窗口,输入cmd。

     

    (2)输入ping 192.168.28.245后,回车,也是可以的。

     

    收发相同,没有数据丢失,说明ping命令也是成功的。

    6.8.6      第3步,网络调试助手创建TCP客户端

    •   打开调试助手,点击左上角创建连接:

     

    •   弹出如下界面,类型选择TCP,目标IP设置为192.168.28.245端口号1001,最后点击创建:

     

    •   创建后的界面效果如下:

     

    •   点击连接,连接后的界面效果如下:

     

    6.8.7      第5步,TCP服务器回环测试

    板子和网络调试助手建立连接后就可以相互收发数据了。

     

    发送和接收一致,说明移植是没问题的。

    6.9   总结

    本章节为大家讲解了NetXDUO移植方法,初学的话,建议实际动手操作一遍。

    微信公众号:armfly_com 安富莱论坛:www.armbbs.cn 安富莱淘宝:https://armfly.taobao.com
  • 相关阅读:
    tyvj 1031 热浪 最短路
    【bzoj2005】 [Noi2010]能量采集 数学结论(gcd)
    hdu 1394 Minimum Inversion Number 逆序数/树状数组
    HDU 1698 just a hook 线段树,区间定值,求和
    ZeptoLab Code Rush 2015 C. Om Nom and Candies 暴力
    ZeptoLab Code Rush 2015 B. Om Nom and Dark Park DFS
    ZeptoLab Code Rush 2015 A. King of Thieves 暴力
    hdoj 5199 Gunner map
    hdoj 5198 Strange Class 水题
    vijos 1659 河蟹王国 线段树区间加、区间查询最大值
  • 原文地址:https://www.cnblogs.com/armfly/p/14667667.html
Copyright © 2011-2022 走看看