请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4040|回复: 14
收起左侧

[RL-TCPnet V7.X] 分享个修正版RL-TCPnet V7.X和LwIP的LAN8720驱动,符合CMSIS-Driver驱动规范,适用于所有STM32系列(V1.0)

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105917
QQ
发表于 2020-4-14 11:10:56 | 显示全部楼层 |阅读模式
在CMSIS-Driver提供的原始驱动基础上之加了复位功能,这个复位功能非常重要,否则运行阶段8720容易通信异常。

【非常重要的帖子,必读】
CMSIS-Driver驱动各种以太网PHY芯片,读取ID前建议加上软件复位
http://www.armbbs.cn/forum.php?mod=viewthread&tid=95709



这个驱动是在H7-TOOL的RTX5全家桶版上使用的。

PHY_LAN8720.h
PHY_LAN8720.c


  1. /*
  2. * Copyright (c) 2013-2018 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------
  19. *
  20. * $Date:        25. May 2018
  21. * $Revision:    V6.2
  22. *  
  23. * Driver:       Driver_ETH_PHYn (default: Driver_ETH_PHY0)
  24. * Project:      Ethernet Physical Layer Transceiver (PHY)
  25. *               Driver for LAN8720
  26. * -----------------------------------------------------------------------
  27. * Use the following configuration settings in the middleware component
  28. * to connect to this driver.
  29. *
  30. *   Configuration Setting                     Value
  31. *   ---------------------                     -----
  32. *   Connect to hardware via Driver_ETH_PHY# = n (default: 0)
  33. * -------------------------------------------------------------------- */

  34. /* History:
  35. *  Version 6.2
  36. *    Updated for ARM compiler 6
  37. *  Version 6.1
  38. *    Added driver flow control flags
  39. *  Version 6.00
  40. *    Based on API V2.00
  41. *  Version 5.01
  42. *    Based on API V1.10 (namespace prefix ARM_ added)
  43. *  Version 5.00
  44. *    Initial release
  45. */

  46. #include "PHY_LAN8720.h"

  47. #define ARM_ETH_PHY_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(6,2) /* driver version */


  48. #ifndef ETH_PHY_NUM
  49. #define ETH_PHY_NUM     0        /* Default driver number */
  50. #endif

  51. #ifndef ETH_PHY_ADDR
  52. #define ETH_PHY_ADDR    0x00     /* Default device address */
  53. #endif


  54. /* Driver Version */
  55. static const ARM_DRIVER_VERSION DriverVersion = {
  56.   ARM_ETH_PHY_API_VERSION,
  57.   ARM_ETH_PHY_DRV_VERSION
  58. };

  59. /* Ethernet PHY control structure */
  60. static PHY_CTRL PHY = { NULL, NULL, 0, 0, 0 };


  61. /**
  62.   \fn          ARM_DRIVER_VERSION GetVersion (void)
  63.   \brief       Get driver version.
  64.   \return      \ref ARM_DRIVER_VERSION
  65. */
  66. static ARM_DRIVER_VERSION GetVersion (void) {
  67.   return DriverVersion;
  68. }


  69. /**
  70.   \fn          int32_t Initialize (ARM_ETH_PHY_Read_t  fn_read,
  71.                                    ARM_ETH_PHY_Write_t fn_write)
  72.   \brief       Initialize Ethernet PHY Device.
  73.   \param[in]   fn_read   Pointer to \ref ARM_ETH_MAC_PHY_Read
  74.   \param[in]   fn_write  Pointer to \ref ARM_ETH_MAC_PHY_Write
  75.   \return      \ref execution_status
  76. */
  77. static int32_t Initialize (ARM_ETH_PHY_Read_t fn_read, ARM_ETH_PHY_Write_t fn_write) {

  78.   if ((fn_read == NULL) || (fn_write == NULL)) { return ARM_DRIVER_ERROR_PARAMETER; }

  79.   if ((PHY.flags & PHY_INIT) == 0U) {
  80.     /* Register PHY read/write functions. */
  81.     PHY.reg_rd = fn_read;
  82.     PHY.reg_wr = fn_write;

  83.     PHY.bmcr   = 0U;
  84.     PHY.flags  = PHY_INIT;
  85.   }

  86.   return ARM_DRIVER_OK;
  87. }

  88. /**
  89.   \fn          int32_t Uninitialize (void)
  90.   \brief       De-initialize Ethernet PHY Device.
  91.   \return      \ref execution_status
  92. */
  93. static int32_t Uninitialize (void) {

  94.   PHY.reg_rd = NULL;
  95.   PHY.reg_wr = NULL;
  96.   PHY.bmcr   = 0U;
  97.   PHY.flags  = 0U;

  98.   return ARM_DRIVER_OK;
  99. }

  100. /**
  101.   \fn          int32_t PowerControl (ARM_POWER_STATE state)
  102.   \brief       Control Ethernet PHY Device Power.
  103.   \param[in]   state  Power state
  104.   \return      \ref execution_status
  105. */
  106. static int32_t PowerControl (ARM_POWER_STATE state) {
  107.   uint16_t val;

  108.   switch ((int32_t)state) {
  109.     case ARM_POWER_OFF:
  110.       if ((PHY.flags & PHY_INIT) == 0U) {
  111.         /* Initialize must provide register access function pointers */
  112.         return ARM_DRIVER_ERROR;
  113.       }

  114.       PHY.flags &= ~PHY_POWER;
  115.       PHY.bmcr   =  BMCR_POWER_DOWN;

  116.       return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr));

  117.     case ARM_POWER_FULL:
  118.       if ((PHY.flags & PHY_INIT) == 0U) {
  119.         return ARM_DRIVER_ERROR;
  120.       }
  121.       if (PHY.flags & PHY_POWER) {
  122.         return ARM_DRIVER_OK;
  123.       }
  124.          
  125.           {
  126.                 uint32_t tout;
  127.                  
  128.                 PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, BMCR_RESET);
  129.                 for (tout = 0; tout < 0x10000; tout++)
  130.                 {
  131.                         PHY.reg_rd(ETH_PHY_ADDR, REG_BMCR, &val);
  132.                         if (!(val & 0x8000))
  133.                         {
  134.                                 break;
  135.                         }
  136.                 }
  137.          
  138.           }
  139.          
  140.       /* Check Device Identification. */
  141.       PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR1, &val);

  142.       if (val != PHY_ID1) {
  143.         /* Invalid PHY ID */
  144.         return ARM_DRIVER_ERROR_UNSUPPORTED;
  145.       }

  146.       PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR2, &val);

  147.       if ((val & 0xFFF0) != PHY_ID2) {
  148.         /* Invalid PHY ID */
  149.         return ARM_DRIVER_ERROR_UNSUPPORTED;
  150.       }

  151.       PHY.bmcr = 0U;

  152.       if (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr) != ARM_DRIVER_OK) {
  153.         return ARM_DRIVER_ERROR;
  154.       }

  155.       PHY.flags |=  PHY_POWER;

  156.       return ARM_DRIVER_OK;

  157.     case ARM_POWER_LOW:
  158.     default:
  159.       return ARM_DRIVER_ERROR_UNSUPPORTED;
  160.   }
  161. }

  162. /**
  163.   \fn          int32_t SetInterface (uint32_t interface)
  164.   \brief       Set Ethernet Media Interface.
  165.   \param[in]   interface  Media Interface type
  166.   \return      \ref execution_status
  167. */
  168. static int32_t SetInterface (uint32_t interface) {

  169.   if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }

  170.   switch (interface) {
  171.     case ARM_ETH_INTERFACE_RMII:
  172.       break;
  173.     case ARM_ETH_INTERFACE_MII:
  174.     default:
  175.       return ARM_DRIVER_ERROR_UNSUPPORTED;
  176.   }
  177.   return(0);
  178. }

  179. /**
  180.   \fn          int32_t SetMode (uint32_t mode)
  181.   \brief       Set Ethernet PHY Device Operation mode.
  182.   \param[in]   mode  Operation Mode
  183.   \return      \ref execution_status
  184. */
  185. static int32_t SetMode (uint32_t mode) {
  186.   uint16_t val;

  187.   if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }

  188.   val = PHY.bmcr & BMCR_POWER_DOWN;

  189.   switch (mode & ARM_ETH_PHY_SPEED_Msk) {
  190.     case ARM_ETH_PHY_SPEED_10M:
  191.       break;
  192.     case ARM_ETH_PHY_SPEED_100M:
  193.       val |=  BMCR_SPEED_SEL;
  194.       break;
  195.     default:
  196.       return ARM_DRIVER_ERROR_UNSUPPORTED;
  197.   }

  198.   switch (mode & ARM_ETH_PHY_DUPLEX_Msk) {
  199.     case ARM_ETH_PHY_DUPLEX_HALF:
  200.       break;
  201.     case ARM_ETH_PHY_DUPLEX_FULL:
  202.       val |=  BMCR_DUPLEX;
  203.       break;
  204.   }

  205.   if (mode & ARM_ETH_PHY_AUTO_NEGOTIATE) {
  206.     val |= BMCR_ANEG_EN;
  207.   }

  208.   if (mode & ARM_ETH_PHY_LOOPBACK) {
  209.     val |= BMCR_LOOPBACK;
  210.   }

  211.   if (mode & ARM_ETH_PHY_ISOLATE) {
  212.     val |= BMCR_ISOLATE;
  213.   }

  214.   PHY.bmcr = val;

  215.   return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr));
  216. }

  217. /**
  218.   \fn          ARM_ETH_LINK_STATE GetLinkState (void)
  219.   \brief       Get Ethernet PHY Device Link state.
  220.   \return      current link status \ref ARM_ETH_LINK_STATE
  221. */
  222. static ARM_ETH_LINK_STATE GetLinkState (void) {
  223.   ARM_ETH_LINK_STATE state;
  224.   uint16_t           val = 0U;

  225.   if (PHY.flags & PHY_POWER) {
  226.     PHY.reg_rd(ETH_PHY_ADDR, REG_BMSR, &val);
  227.   }
  228.   state = (val & BMSR_LINK_STAT) ? ARM_ETH_LINK_UP : ARM_ETH_LINK_DOWN;

  229.   return (state);
  230. }

  231. /**
  232.   \fn          ARM_ETH_LINK_INFO GetLinkInfo (void)
  233.   \brief       Get Ethernet PHY Device Link information.
  234.   \return      current link parameters \ref ARM_ETH_LINK_INFO
  235. */
  236. static ARM_ETH_LINK_INFO GetLinkInfo (void) {
  237.   ARM_ETH_LINK_INFO info;
  238.   uint16_t          val = 0U;

  239.   if (PHY.flags & PHY_POWER) {
  240.     PHY.reg_rd(ETH_PHY_ADDR, REG_PSCSR, &val);
  241.   }

  242.   info.speed  = (val & PSCSR_SPEED)  ? ARM_ETH_SPEED_10M   : ARM_ETH_SPEED_100M;
  243.   info.duplex = (val & PSCSR_DUPLEX) ? ARM_ETH_DUPLEX_FULL : ARM_ETH_DUPLEX_HALF;

  244.   return (info);
  245. }


  246. /* PHY Driver Control Block */
  247. extern
  248. ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(ETH_PHY_NUM);
  249. ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(ETH_PHY_NUM) = {
  250.   GetVersion,
  251.   Initialize,
  252.   Uninitialize,
  253.   PowerControl,
  254.   SetInterface,
  255.   SetMode,
  256.   GetLinkState,
  257.   GetLinkInfo
  258. };
复制代码


回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-9-25 10:57:06 | 显示全部楼层
我想问一下硬汉哥,初始化中有硬件复位了,这个软件复位就不需要了吧
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105917
QQ
 楼主| 发表于 2020-9-25 11:02:44 | 显示全部楼层
heluo1985 发表于 2020-9-25 10:57
我想问一下硬汉哥,初始化中有硬件复位了,这个软件复位就不需要了吧

加上,加上更靠谱。
回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-9-25 11:09:12 | 显示全部楼层
硬汉哥。神速回复啊
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
发表于 2020-11-28 18:02:24 | 显示全部楼层
硬汉哥,你好,使用LAN8720A现在能读ID,但使用RL-NETTCP的工程ping不通板子呢?
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
发表于 2020-11-29 14:00:55 | 显示全部楼层
hejiang177 发表于 2020-11-28 18:02
硬汉哥,你好,使用LAN8720A现在能读ID,但使用RL-NETTCP的工程ping不通板子呢?

不好意思,是没注意开了DHCP
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
发表于 2020-11-30 14:05:53 | 显示全部楼层
硬汉哥,你好,用你的例子也改了驱动RTX5+LWIP+LAN8720,LWIP运行几个小时后,ping就会出现几秒钟才通的情况,而且会超时,这种情况是可能会是什么原因呢?
回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-12-3 09:28:25 | 显示全部楼层
近期在用 stm32h743 + lan8720,RTX 系统+RL-TCPNET,长时间运行偶发性 出现 CMSIS-RTOS error: ISR Queue overflow,不知道硬汉哥有没有遇到这样的情况?
回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-12-3 09:31:47 | 显示全部楼层
近期在用stm32H743 + LAN8720,RTX+RL-TCPnet V7.X,长时间运行,有时候跑几天偶发性出现  CMSIS-RTOS error: ISR Queue overflow,不知道硬汉哥有没有见过这个错误?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105917
QQ
 楼主| 发表于 2020-12-3 10:18:25 | 显示全部楼层
heluo1985 发表于 2020-12-3 09:28
近期在用 stm32h743 + lan8720,RTX 系统+RL-TCPNET,长时间运行偶发性 出现 CMSIS-RTOS error: ISR Queue  ...

弹出这个是中断消息已经满,而你没有及时处理。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105917
QQ
 楼主| 发表于 2020-12-3 10:19:15 | 显示全部楼层
hejiang177 发表于 2020-11-30 14:05
硬汉哥,你好,用你的例子也改了驱动RTX5+LWIP+LAN8720,LWIP运行几个小时后,ping就会出现几秒钟才通的情 ...

这个问题,我升级过,你可以参考下

LwIP网络教程开始更新,使用MDK的RTE环境开发,配套RTX5和FreeRTOS两个版本,更新至第7章(2020-05-03)
http://www.armbbs.cn/forum.php?m ... 5874&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-12-3 12:01:45 | 显示全部楼层
eric2013 发表于 2020-12-3 10:18
弹出这个是中断消息已经满,而你没有及时处理。

我也监控过这个FIFO,一般情况下都是及时处理了,但是就是长时间运行偶发性这个故障,这个是ISR中断太快,任务没有处理导致,我怀疑是ISR中中断标志清不掉了导致的
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
105917
QQ
 楼主| 发表于 2020-12-3 12:07:17 | 显示全部楼层
heluo1985 发表于 2020-12-3 12:01
我也监控过这个FIFO,一般情况下都是及时处理了,但是就是长时间运行偶发性这个故障,这个是ISR中断太快 ...

不清楚了,没遇到这种情况。
回复

使用道具 举报

5

主题

109

回帖

124

积分

初级会员

积分
124
发表于 2020-12-6 10:47:03 | 显示全部楼层
eric2013 发表于 2020-12-3 10:19
这个问题,我升级过,你可以参考下

LwIP网络教程开始更新,使用MDK的RTE环境开发,配套RTX5和FreeRTOS ...

好的,我看一下
谢谢
回复

使用道具 举报

2

主题

60

回帖

66

积分

初级会员

积分
66
发表于 2020-12-9 10:02:14 | 显示全部楼层
eric2013 发表于 2020-12-3 12:07
不清楚了,没遇到这种情况。

EventRecord调试监控,显示的时间应该都不对了,系统进入了ISR FIFO 溢出了,我倒是觉得有可能CPU挂掉,大约持续了40us,EventRecord回复正常时间,初步怀疑电源不稳定造成的。。。。。。。。

EventRecord调试监控

EventRecord调试监控
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-3-29 08:57 , Processed in 0.290017 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表