OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 12472|回复: 17

STM32F429+LWIP(DP83848)ping不通

[复制链接]

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
发表于 2016-9-7 17:24:21 | 显示全部楼层 |阅读模式
1.使用的芯片是STM32F429、PHY是dp83848.
软件工程使用的是原子大概的F429+UCOSii+LWIP的工程,修改了PhyAddress为0x01,
同时修改了/* Section 4: Extended PHY Registers */
#define PHY_SR                                ((uint16_t)16)                 //DP83848的PHY状态寄存器地址
#define PHY_SPEED_STATUS    ((uint16_t)0x0002)         //DP83848 PHY速度值掩码
#define PHY_DUPLEX_STATUS   ((uint16_t)0x0004) //DP83848 PHY连接状态值掩码
但是连接上网络之后就是ping不通。望各位给点调试思路。
软件运行之后现象:
1.RJ45黄灯常亮,绿灯一直在闪烁;
2.仿真查看lwip_comm_init初始化都是正常的。
3.程序一直在进中断服务函数,UCOSII任务运行都是正常的。
void ETH_IRQHandler(void)
{
    OSIntEnter();
    while(ETH_GetRxPktSize(ETH_Handler.RxDesc))   
    {
        lwip_pkt_handle();//处理以太网数据,即将数据提交给LWIP
    }
    //清除中断标志位
    __HAL_ETH_DMA_CLEAR_IT(&ETH_Handler,ETH_DMA_IT_R);
    __HAL_ETH_DMA_CLEAR_IT(&ETH_Handler,ETH_DMA_IT_NIS);
    OSIntExit();  
}
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-8 08:32:13 | 显示全部楼层
中断函数里面处理太多了吧,建议开个task,然后有中断通知task接收。尽量让中断里面的代码简单
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复 支持 1 反对 0

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-7 17:25:40 | 显示全部楼层
DP83848.c的代码
[mw_shl_code=c,true]#include "DP83848IVV.h"
#include "lwip_comm.h"
#include "delay.h"
#include "malloc.h"
#include "includes.h"


ETH_HandleTypeDef ETH_Handler;      //以太网句柄

ETH_DMADescTypeDef *DMARxDscrTab;        //以太网DMA接收描述符数据结构体指针
ETH_DMADescTypeDef *DMATxDscrTab;        //以太网DMA发送描述符数据结构体指针
uint8_t *Rx_Buff;                                         //以太网底层驱动接收buffers指针
uint8_t *Tx_Buff;                                         //以太网底层驱动发送buffers指针
  
//DP83848初始化
//返回值:0,成功;
//    其他,失败
u8 DP83848_Init(void)
{      
    u8 macaddress[6];

    macaddress[0]        =        lwipdev.mac[0];
        macaddress[1]        =        lwipdev.mac[1];
        macaddress[2]        =        lwipdev.mac[2];
        macaddress[3]        =        lwipdev.mac[3];   
        macaddress[4]        =        lwipdev.mac[4];
        macaddress[5]        =        lwipdev.mac[5];
        
        ETH_Handler.Instance                                =        ETH;
    ETH_Handler.Init.AutoNegotiation        =        ETH_AUTONEGOTIATION_ENABLE;        //使能自协商模式
    ETH_Handler.Init.Speed                                =        ETH_SPEED_100M;                                //速度100M,如果开启了自协商模式,此配置就无效
    ETH_Handler.Init.DuplexMode                        =        ETH_MODE_FULLDUPLEX;                //全双工模式,如果开启了自协商模式,此配置就无效
    ETH_Handler.Init.PhyAddress                        =        DP83848_PHY_ADDRESS;                //DP83848地址  
    ETH_Handler.Init.MACAddr                        =        macaddress;                            //MAC地址  
    ETH_Handler.Init.RxMode                                =        ETH_RXINTERRUPT_MODE;           //轮训接收模式
    ETH_Handler.Init.ChecksumMode                =        ETH_CHECKSUM_BY_HARDWARE;        //硬件帧校验  
    ETH_Handler.Init.MediaInterface                =        ETH_MEDIA_INTERFACE_RMII;        //RMII接口  
    if(HAL_ETH_Init(&ETH_Handler)==HAL_OK)
    {
        return 0;   //成功
    }
    else return 1;  //失败
}

//ETH底层驱动,时钟使能,引脚配置
//此函数会被HAL_ETH_Init()调用
//heth:以太网句柄
void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
{
    GPIO_InitTypeDef GPIO_Initure;
   
    __HAL_RCC_ETH_CLK_ENABLE();             //开启ETH时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                        //开启GPIOA时钟
        __HAL_RCC_GPIOB_CLK_ENABLE();                        //开启GPIOB时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();                        //开启GPIOC时钟
    __HAL_RCC_GPIOG_CLK_ENABLE();                        //开启GPIOG时钟
   
    /*网络引脚设置 RMII接口
    ETH_MDIO -------------------------> PA2
    ETH_MDC --------------------------> PC1
    ETH_RMII_REF_CLK------------------> PA1
    ETH_RMII_CRS_DV ------------------> PA7
    ETH_RMII_RXD0 --------------------> PC4
    ETH_RMII_RXD1 --------------------> PC5
    ETH_RMII_TX_EN -------------------> PG11 //DP83848 此引脚使用的PG11
    ETH_RMII_TXD0 --------------------> PG13
    ETH_RMII_TXD1 --------------------> PG14*/
   
    //PA1,2,7
    GPIO_Initure.Pin                =        GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7;
    GPIO_Initure.Mode                =        GPIO_MODE_AF_PP;          //推挽复用
    GPIO_Initure.Pull                =        GPIO_NOPULL;              //不带上下拉
    GPIO_Initure.Speed                =        GPIO_SPEED_HIGH;         //高速
    GPIO_Initure.Alternate        =        GPIO_AF11_ETH;                //复用为ETH功能
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);                          //初始化
   
    //修改为PG11
    GPIO_Initure.Pin        =        GPIO_PIN_11;                       //PG11
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);                         //始化
   
    //PC1,4,5
    GPIO_Initure.Pin        =        GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5; //PC1,4,5
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);                                         //初始化
       
    //PG13,14
    GPIO_Initure.Pin        =        GPIO_PIN_13|GPIO_PIN_14;   //PG13,14
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);                         //初始化
   
    HAL_NVIC_SetPriority(ETH_IRQn,0,0);                                 //网络中断优先级应该高一点
    HAL_NVIC_EnableIRQ(ETH_IRQn);
}
//读取PHY寄存器值
u32 DP83848_ReadPHY(u16 reg)
{
    u32 regval;
    HAL_ETH_ReadPHYRegister(&ETH_Handler,reg,&regval);
    return regval;
}
//向DP83848指定寄存器写入值
//reg:要写入的寄存器
//value:要写入的值
void DP83848_WritePHY(u16 reg,u16 value)
{
    u32 temp=value;
    HAL_ETH_ReadPHYRegister(&ETH_Handler,reg,&temp);
}
//得到DP83848的速度模式
//返回值:
//001:10M半双工
//101:10M全双工
//010:100M半双工
//110:100M全双工
//其他:错误.
u8 DP83848_Get_Speed(void)
{
        u8 speed;
        speed=((DP83848_ReadPHY(16)&0x06)>>1); //从DP83848的16号寄存器中读取网络速度和双工模式
        return speed;
}

extern void lwip_pkt_handle(void);                //在lwip_comm.c里面定义
//中断服务函数
void ETH_IRQHandler(void)
{
    OSIntEnter();
    while(ETH_GetRxPktSize(ETH_Handler.RxDesc))   
    {
        lwip_pkt_handle();//处理以太网数据,即将数据提交给LWIP
    }
    //清除中断标志位
    __HAL_ETH_DMA_CLEAR_IT(&ETH_Handler,ETH_DMA_IT_R);
    __HAL_ETH_DMA_CLEAR_IT(&ETH_Handler,ETH_DMA_IT_NIS);
    OSIntExit();  
}

//获取接收到的帧长度
//DMARxDesc:接收DMA描述符
//返回值:接收到的帧长度
u32  ETH_GetRxPktSize(ETH_DMADescTypeDef *DMARxDesc)
{
    u32 frameLength = 0;
    if(((DMARxDesc->Status&ETH_DMARXDESC_OWN)==(uint32_t)RESET) &&
     ((DMARxDesc->Status&ETH_DMARXDESC_ES)==(uint32_t)RESET) &&
     ((DMARxDesc->Status&ETH_DMARXDESC_LS)!=(uint32_t)RESET))
    {
        frameLength=((DMARxDesc->Status&ETH_DMARXDESC_FL)>>ETH_DMARXDESC_FRAME_LENGTHSHIFT);
    }
    return frameLength;
}

//为ETH底层驱动申请内存
//返回值:0,正常
//    其他,失败
u8 ETH_Mem_Malloc(void)
{
        DMARxDscrTab=mymalloc(SRAMIN,ETH_RXBUFNB*sizeof(ETH_DMADescTypeDef));//申请内存
        DMATxDscrTab=mymalloc(SRAMIN,ETH_TXBUFNB*sizeof(ETH_DMADescTypeDef));//申请内存  
        Rx_Buff=mymalloc(SRAMIN,ETH_RX_BUF_SIZE*ETH_RXBUFNB);        //申请内存
        Tx_Buff=mymalloc(SRAMIN,ETH_TX_BUF_SIZE*ETH_TXBUFNB);        //申请内存
        if(!(u32)&DMARxDscrTab||!(u32)&DMATxDscrTab||!(u32)&Rx_Buff||!(u32)&Tx_Buff)
        {
                ETH_Mem_Free();
                return 1;        //申请失败
        }       
        return 0;                //申请成功
}

//释放ETH 底层驱动申请的内存
void ETH_Mem_Free(void)
{
        myfree(SRAMIN,DMARxDscrTab);//释放内存
        myfree(SRAMIN,DMATxDscrTab);//释放内存
        myfree(SRAMIN,Rx_Buff);                //释放内存
        myfree(SRAMIN,Tx_Buff);                //释放内存  
}


[/mw_shl_code]
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-7 17:27:10 | 显示全部楼层
各位给点调试的思路,目前不知道怎么继续调试下去了
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 08:22:17 | 显示全部楼层
期待回复啊!!!
回复 支持 反对

使用道具 举报

1

主题

140

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
290
金钱
290
注册时间
2016-8-15
在线时间
20 小时
发表于 2016-9-8 08:27:44 | 显示全部楼层

回帖奖励 +1 金钱

不懂,帮顶
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 08:47:46 | 显示全部楼层
ysq7120 发表于 2016-9-8 08:32
中断函数里面处理太多了吧,建议开个task,然后有中断通知task接收。尽量让中断里面的代码简单

这块直接移植的是原子哥的程序,还没动。现在的问题是我移植ping不通,程序仿真过程中程序会不断的进ETH_IRQHandler中断(系统任务运行正常)。
不知道接下来如何调试了
回复 支持 反对

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-8 10:16:55 | 显示全部楼层
LWIP_ICMP 这个宏有打开吗?
既然进入中断,你就接受包看看包的内容是不是ping包。如果宏有打开,跟踪下去是否哪里不对,如果没打开,ping不通是正常的。
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 10:57:21 | 显示全部楼层
ysq7120 发表于 2016-9-8 10:16
LWIP_ICMP 这个宏有打开吗?
既然进入中断,你就接受包看看包的内容是不是ping包。如果宏有打开,跟踪下去 ...

是打开的
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 11:02:44 | 显示全部楼层
ysq7120 发表于 2016-9-8 10:16
LWIP_ICMP 这个宏有打开吗?
既然进入中断,你就接受包看看包的内容是不是ping包。如果宏有打开,跟踪下去 ...

插上网线 LINK LED 不亮。LINK_ACT LED 一直在闪烁
回复 支持 反对

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-8 11:05:06 | 显示全部楼层
那就等ping包来了后单步跟踪,并看包的内容是否正确。不分析你找不出问题的
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 15:04:43 | 显示全部楼层
ysq7120 发表于 2016-9-8 11:05
那就等ping包来了后单步跟踪,并看包的内容是否正确。不分析你找不出问题的

原子大哥的ETH_TX_EN接的PB11,我使用的PG11引脚。单片机MAC是如何识别使用的是哪个引脚呢?现在是可以接收到数据接收到数据之后不会响应!

仿真根据调试发现,可以接收到ping的数据包!但是程序接收到数据是怎么处理的不是很明白。
接收函数运行到这里就不知道跑哪去了!
[mw_shl_code=c,true]err_t ethernetif_input(struct netif *netif)
{
        err_t err;
        struct pbuf *p;
        p=low_level_input(netif);   //调用low_level_input函数接收数据
        if(p==NULL) return ERR_MEM;
        err=netif->input(p, netif); //调用netif结构体中的input字段(一个函数)来处理数据包
        if(err!=ERR_OK)
        {
                LWIP_DEBUGF(NETIF_DEBUG,("ethernetif_input: IP input error\n"));
                pbuf_free(p);
                p = NULL;
        }
        return err;
}[/mw_shl_code]
回复 支持 反对

使用道具 举报

19

主题

430

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
金钱
1341
注册时间
2016-4-22
在线时间
187 小时
发表于 2016-9-8 17:22:03 | 显示全部楼层
硬件是否有问题我就不清楚了,软件的你可以从input跟踪下去,或者找到icmp相关处理代码,直接设置断点在里面调试就知道了。
你如果不是ping,收发都正常吗?
伤情最是晚凉天,憔悴斯人不堪怜。
邀酒摧肠三杯醉,寻香惊梦五更寒。
钗头凤斜卿有泪,荼蘼花了我无缘。
小楼寂寞新雨月,也难如钩也难圆。
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2016-9-8 17:30:55 | 显示全部楼层
ysq7120 发表于 2016-9-8 17:22
硬件是否有问题我就不清楚了,软件的你可以从input跟踪下去,或者找到icmp相关处理代码,直接设置断点在里 ...

问题解决了,之前一直是可以接收,但是发送不了。还是引脚配置的问题。我使用Cube重新生成的引脚配置搞定了!
回复 支持 反对

使用道具 举报

5

主题

26

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
373
金钱
373
注册时间
2016-8-2
在线时间
106 小时
发表于 2017-1-21 11:12:27 | 显示全部楼层
shaozp 发表于 2016-9-8 17:30
问题解决了,之前一直是可以接收,但是发送不了。还是引脚配置的问题。我使用Cube重新生成的引脚配置搞定 ...

请问引脚配置什么问题呢?
回复 支持 反对

使用道具 举报

11

主题

80

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4493
金钱
4493
注册时间
2016-8-2
在线时间
51 小时
 楼主| 发表于 2017-2-8 10:58:26 | 显示全部楼层
491603829 发表于 2017-1-21 11:12
请问引脚配置什么问题呢?

记忆中是以太网TX的引脚配置错了,主要是还是检查移植之后的对应的引脚是否都正确,如果不确定可以使用cube进行引脚配置在对比查看
回复 支持 反对

使用道具 举报

6

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2018-12-7
在线时间
45 小时
发表于 2019-1-30 16:49:20 | 显示全部楼层
shaozp 发表于 2016-9-7 17:25
DP83848.c的代码
[mw_shl_code=c,true]#include "DP83848IVV.h"
#include "lwip_comm.h"

你好,我用原子的例程修改DP83848调试也遇到了和你相同的问题,能不能帮我指导下
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2018-12-10
在线时间
2 小时
发表于 2019-2-19 14:08:20 | 显示全部楼层

在stm32f4xx_hal_eth.c中的HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)函数中添加
/*   添加的代码行   */之间的DP83848的驱动代码即可。我也是从改正点原子的代码上改的,亲测可以使用

HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)
{
  uint32_t tmpreg1 = 0, phyreg = 0;
  uint32_t hclk = 60000000;
  uint32_t tickstart = 0;
  uint32_t err = ETH_SUCCESS;
  
  /* Check the ETH peripheral state */
  if(heth == NULL)
  {
    return HAL_ERROR;
  }
  
  /* Check parameters */
  assert_param(IS_ETH_AUTONEGOTIATION(heth->Init.AutoNegotiation));
  assert_param(IS_ETH_RX_MODE(heth->Init.RxMode));
  assert_param(IS_ETH_CHECKSUM_MODE(heth->Init.ChecksumMode));
  assert_param(IS_ETH_MEDIA_INTERFACE(heth->Init.MediaInterface));  
  
  if(heth->State == HAL_ETH_STATE_RESET)
  {
    /* Allocate lock resource and initialize it */
    heth->Lock = HAL_UNLOCKED;
    /* Init the low level hardware : GPIO, CLOCK, NVIC. */
    HAL_ETH_MspInit(heth);
  }
  
  /* Enable SYSCFG Clock */
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  
  /* Select MII or RMII Mode*/
  SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL);
  SYSCFG->PMC |= (uint32_t)heth->Init.MediaInterface;
  
  /* Ethernet Software reset */
  /* Set the SWR bit: resets all MAC subsystem internal registers and logic */
  /* After reset all the registers holds their respective reset values */
  (heth->Instance)->DMABMR |= ETH_DMABMR_SR;
  /*   添加的代码行   */       
          /* Get tick */
  tickstart = HAL_GetTick();
  /*   添加的代码行   */          
  /* Wait for software reset */
  while (((heth->Instance)->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET)
  {
/*   添加的代码行   */               
    /* Check for the Timeout */
    if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_SWRESET)
    {     
      heth->State= HAL_ETH_STATE_TIMEOUT;
  
      /* Process Unlocked */
      __HAL_UNLOCK(heth);
   
      /* Note: The SWR is not performed if the ETH_RX_CLK or the ETH_TX_CLK are  
         not available, please check your external PHY or the IO configuration */
      return HAL_TIMEOUT;
                }
               
/*   添加的代码行   */                       
  }
  
  /*-------------------------------- MAC Initialization ----------------------*/
  /* Get the ETHERNET MACMIIAR value */
  tmpreg1 = (heth->Instance)->MACMIIAR;
  /* Clear CSR Clock Range CR[2:0] bits */
  tmpreg1 &= ETH_MACMIIAR_CR_MASK;
  
  /* Get hclk frequency value */
  hclk = HAL_RCC_GetHCLKFreq();
  
  /* Set CR bits depending on hclk value */
  if((hclk >= 20000000)&&(hclk < 35000000))
  {
    /* CSR Clock Range between 20-35 MHz */
    tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div16;
  }
  else if((hclk >= 35000000)&&(hclk < 60000000))
  {
    /* CSR Clock Range between 35-60 MHz */
    tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div26;
  }  
  else if((hclk >= 60000000)&&(hclk < 100000000))
  {
    /* CSR Clock Range between 60-100 MHz */
    tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div42;
  }  
  else if((hclk >= 100000000)&&(hclk < 150000000))
  {
    /* CSR Clock Range between 100-150 MHz */
    tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div62;
  }
  else /* ((hclk >= 150000000)&&(hclk <= 168000000)) */
  {
    /* CSR Clock Range between 150-168 MHz */
    tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div102;   
  }
  
  /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */
  (heth->Instance)->MACMIIAR = (uint32_t)tmpreg1;
  
  /*-------------------- PHY initialization and configuration ----------------*/
/*   添加的代码行   */                       
  /* Put the PHY in reset mode */
  if((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_RESET)) != HAL_OK)
  {
    /* In case of write timeout */
    err = ETH_ERROR;
   
    /* Config MAC and DMA */
    ETH_MACDMAConfig(heth, err);
   
    /* Set the ETH peripheral state to READY */
    heth->State = HAL_ETH_STATE_READY;
   
    /* Return HAL_ERROR */
    return HAL_ERROR;
  }
  
  /* Delay to assure PHY reset */
  HAL_Delay(PHY_RESET_DELAY);
/*   添加的代码行   */                  
  if((heth->Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
  {
    /* Get tick */
    tickstart = HAL_GetTick();
   
    /* We wait for linked status */
    do
    {
      HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
      
      /* Check for the Timeout */
//      if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_LINKED_STATE)
      if((HAL_GetTick() - tickstart ) > LINKED_STATE_TIMEOUT_VALUE)
      {
        /* In case of write timeout */
        err = ETH_ERROR;
      
        /* Config MAC and DMA */
        ETH_MACDMAConfig(heth, err);
        
        heth->State= HAL_ETH_STATE_READY;
  
        /* Process Unlocked */
        __HAL_UNLOCK(heth);
   
        return HAL_TIMEOUT;
      }
    } while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));

   
    /* Enable Auto-Negotiation */
    if((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_AUTONEGOTIATION)) != HAL_OK)
    {
      /* In case of write timeout */
      err = ETH_ERROR;
      
      /* Config MAC and DMA */
      ETH_MACDMAConfig(heth, err);
      
      /* Set the ETH peripheral state to READY */
      heth->State = HAL_ETH_STATE_READY;
      
      /* Return HAL_ERROR */
      return HAL_ERROR;   
    }
   
    /* Get tick */
    tickstart = HAL_GetTick();
   
    /* Wait until the auto-negotiation will be completed */
    do
    {
      HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
      
      /* Check for the Timeout */
//      if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_AUTONEGO_COMPLETED)
      if((HAL_GetTick() - tickstart ) > AUTONEGO_COMPLETED_TIMEOUT_VALUE)
      {
        /* In case of write timeout */
        err = ETH_ERROR;
      
        /* Config MAC and DMA */
        ETH_MACDMAConfig(heth, err);
        
        heth->State= HAL_ETH_STATE_READY;
  
        /* Process Unlocked */
        __HAL_UNLOCK(heth);
   
        return HAL_TIMEOUT;
      }
      
    } while (((phyreg & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
   
    /* Read the result of the auto-negotiation */
    if((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK)
    {
      /* In case of write timeout */
      err = ETH_ERROR;
      
      /* Config MAC and DMA */
      ETH_MACDMAConfig(heth, err);
      
      /* Set the ETH peripheral state to READY */
      heth->State = HAL_ETH_STATE_READY;
      
      /* Return HAL_ERROR */
      return HAL_ERROR;   
    }
   
    /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
    if((phyreg & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
    {
      /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
      (heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;  
    }
    else
    {
      /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
      (heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX;           
    }
    /* Configure the MAC with the speed fixed by the auto-negotiation process */
    if((phyreg & PHY_SPEED_STATUS) == PHY_SPEED_STATUS)
    {  
      /* Set Ethernet speed to 10M following the auto-negotiation */
      (heth->Init).Speed = ETH_SPEED_10M;
    }
    else
    {   
      /* Set Ethernet speed to 100M following the auto-negotiation */
      (heth->Init).Speed = ETH_SPEED_100M;
    }
  }
  else /* AutoNegotiation Disable */
  {
    /* Check parameters */
    assert_param(IS_ETH_SPEED(heth->Init.Speed));
    assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode));
   
    /* Set MAC Speed and Duplex Mode */
    if(HAL_ETH_WritePHYRegister(heth, PHY_BCR, ((uint16_t)((heth->Init).DuplexMode >> 3) |
                                                (uint16_t)((heth->Init).Speed >> 1))) != HAL_OK)
    {
      /* In case of write timeout */
      err = ETH_ERROR;
      
      /* Config MAC and DMA */
      ETH_MACDMAConfig(heth, err);
      
      /* Set the ETH peripheral state to READY */
      heth->State = HAL_ETH_STATE_READY;
      
      /* Return HAL_ERROR */
      return HAL_ERROR;
    }  
   
    /* Delay to assure PHY configuration */
    HAL_Delay(PHY_CONFIG_DELAY);
  }
  
  /* Config MAC and DMA */
  ETH_MACDMAConfig(heth, err);
  
  /* Set ETH HAL State to Ready */
  heth->State= HAL_ETH_STATE_READY;
  
  /* Return function status */
  return HAL_OK;
}
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 18:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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