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
  • 相关阅读:
    设计模式总结——程序猿的武功秘籍(上)
    php获取分类以下的全部子类方法
    TypeError: Cannot read property &#39;style&#39; of null 错误解决
    Java抽象类
    PHP_SELF、 SCRIPT_NAME、 REQUEST_URI差别
    [WPF]使用Pack URI路径訪问二进制资源
    Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组
    Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组
    Android JNI编程(三)——C语言指针的初步认识、指针变量、互换两个数、函数返回多个值
    Android JNI编程(二)——C语言的基本数据类型,输出函数,输入函数
  • 原文地址:https://www.cnblogs.com/armfly/p/14667667.html
Copyright © 2011-2022 走看看