打印

用二行语句解决未插网线时HAL库环境下LwIP初始化的问题

[复制链接]
632|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
追光少年|  楼主 | 2018-7-6 12:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本人正进行LwIP的编程学习,发现在探索者开发板用STM32CubeMX完成STM32F407和LAN8720的配置设计十分便利,先利用网上他人分享的配置步骤生成的程序框架,经Keil编译后下载到开发板,一连上网线就可以ping通。和所有经历过的人一样都会遇到两个现实问题:一个是初始化时忘记插网线,会导致初始化失败,后续的TCP服务无法进行;二是连接中出现断线的情况,也会导致连接失败,即使再次连好网线也会造成后续通信故障。本帖重点分享本人通过试验、调试的初始化时未联网线的软件处理方法,连线后的断线处理网上已有有效地解决方法,本帖不赘述。
初始化时未联网线的处理方法网上实例不多,而且本人也未遇到他人介绍HAL库环境下的处理方法,因此,本人只能通过读代码和调试跟踪的方式来寻求解决方法。
由于未联网线就进行初始化会导致后续服务无法正常进行,一般情况都是必须等待网线连接正常后再次初始化ETH及LwIP才能解决。本人解决的方法是在ETH初始化程序中插入自己的代码,在检测到网线未连接时,循环进行ETH初始化,直到网线联通位置。代码的插入位置也必须有讲究,首先必须位于用户安全区,否则再次用STM32CubeMX生成代码的时候会被系统覆盖;另外就是不能影响系统程序分配的内存,否则可能引起重复申请内存,导致内存溢出。本人修改源码插入自己代码的文件选择由MX_LWIP_Init()调用的ethernetif.c文件包含负责ETH的初始化工作函数low_level_init(),其原始代码为:
static void low_level_init(struct netif *netif)
{
    HAL_StatusTypeDef hal_eth_init_status;

    /* Init ETH */

    uint8_t MACAddr[6] ;
    heth.Instance = ETH;
    heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
    heth.Init.PhyAddress = LAN8720A_PHY_ADDRESS;
    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.RxMode = ETH_RXINTERRUPT_MODE;
    heth.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
    heth.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;

    /* USER CODE BEGIN MACADDRESS */

    /* USER CODE END MACADDRESS */

    hal_eth_init_status = HAL_ETH_Init(&heth);

    if (hal_eth_init_status == HAL_OK)
    {
        /* Set netif link flag */
        netif->flags |= NETIF_FLAG_LINK_UP;
    }

其中,函数内的 hal_eth_init_status = HAL_ETH_Init(&heth);负责检测网线的连接及自动协商功能,只影响部分寄存器,不牵涉内存分配的问题。该函数HAL_ETH_Init在连线正常的情况下返回值为HAL_OK,其他情况下当然是非HAL_OK啦。本人插入的二行语句位于/* USER CODE BEGIN MACADDRESS */和/* USER CODE END MACADDRESS */之间,可以不被STM32CubeM再次生成新文件是清除掉。插入的二行代码是hal_eth_init_status = HAL_ERROR;while(hal_eth_init_status != HAL_OK),这样一来新代码和源程序合称为
    /* USER CODE BEGIN MACADDRESS */
    hal_eth_init_status = HAL_ERROR;                  // 使hal_eth_init_status为非HAL_OK,使得至少运行一次HAL_ETH_Init。Keil4.74可以不省略这行代码,hal_eth_init_status初值为0x9D,不影响循环。而Keil5缺了这行会发出警告,本人未在Keil5下具体调试,不能确定缺少这一行的后果。
    while(hal_eth_init_status != HAL_OK)              //利用此行循环语句使的下一条hal_eth_init_status = HAL_ETH_Init(&heth);成为循环体
        /* USER CODE END MACADDRESS */
    hal_eth_init_status = HAL_ETH_Init(&heth);    // 这条语句被循环执行,直到网线连线正常

使得如果HAL_ETH_Init函数的返回值不为HAL_OK的话,hal_eth_init_status = HAL_ETH_Init(&heth)语句成为循环体被有条件循环执行,直到网线正常连上hal_eth_init_status == HAL_OK为止,程序正常完成初始化工作。
还应注意一点,在无系统的环境下,该循环可能导致总程序无法继续,而有系统的情况下,执行MX_LWIP_Init()的任务优先级必须设为较低,才能让其他任务正常运行。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

379

主题

379

帖子

0

粉丝