zhujie
zhujie

注册于 2 years ago

回答
5
文章
0
关注者
0

DP83848

  • 先上原理图

Dp83848原理图.png

  1. 也是用的RMII接口,但是应该注意这个开发板选用的是有源晶振
  2. 开发板上的Reset 引脚是和单片机 复位连接在一起的,不受我控制
  • 配置代码及寄存器设置代码
  1. 配置代码同8720A
  2. 寄存器配置代码这里面需要对照DataSheet看一下

Reg-1.png
Reg-2.png
Reg2-1.png
Reg2-2.png
Reg2-3.1.png
Reg2-3.2.png

  1. 对应修改 Hal 中的寄存器配置位 和 drv_eth.h 中的配置位
/* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS           1U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY                 ((uint32_t)0x00FFFFFFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY                ((uint32_t)0x00000FFFU)

#define PHY_READ_TO                     ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO                    ((uint32_t)0x0000FFFFU)

/* Section 3: Common PHY Registers */

#define PHY_BCR                         ((uint16_t)0x00U)    /*!< Transceiver Basic Control Register   */
#define PHY_BSR                         ((uint16_t)0x01U)    /*!< Transceiver Basic Status Register    */

#define PHY_RESET                       ((uint16_t)0x8000U)  /*!< PHY Reset */
#define PHY_LOOPBACK                    ((uint16_t)0x4000U)  /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M             ((uint16_t)0x2100U)  /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M             ((uint16_t)0x2000U)  /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M              ((uint16_t)0x0100U)  /*!< Set the full-duplex mode at 10 Mb/s  */
#define PHY_HALFDUPLEX_10M              ((uint16_t)0x0000U)  /*!< Set the half-duplex mode at 10 Mb/s  */
#define PHY_AUTONEGOTIATION             ((uint16_t)0x1000U)  /*!< Enable auto-negotiation function     */
#define PHY_RESTART_AUTONEGOTIATION     ((uint16_t)0x0200U)  /*!< Restart auto-negotiation function    */
#define PHY_POWERDOWN                   ((uint16_t)0x0800U)  /*!< Select the power down mode           */
#define PHY_ISOLATE                     ((uint16_t)0x0400U)  /*!< Isolate PHY from MII                 */

#define PHY_AUTONEGO_COMPLETE           ((uint16_t)0x0020U)  /*!< Auto-Negotiation process completed   */
#define PHY_LINKED_STATUS               ((uint16_t)0x0004U)  /*!< Valid link established               */
#define PHY_JABBER_DETECTION            ((uint16_t)0x0002U)  /*!< Jabber condition detected            */

/* Section 4: Extended PHY Registers */
#define PHY_SR                          ((uint16_t)0x10U)    /*!< PHY status register Offset           */

#define PHY_LINK_STATUS                 ((uint16_t)0x0001U)  /*!< PHY Link mask                        */
#define PHY_SPEED_STATUS                ((uint16_t)0x0002U)  /*!< PHY Speed mask                       */
#define PHY_DUPLEX_STATUS               ((uint16_t)0x0004U)  /*!< PHY Duplex mask                      */
// 为了防止寄存器配置错误,我把不使用的配置寄存器都屏蔽了
/* The PHY basic control register */
#define PHY_BASIC_CONTROL_REG       0x00U
#define PHY_RESET_MASK              (1<<15)
#define PHY_AUTO_NEGOTIATION_MASK   (1<<12)

/* The PHY basic status register */
#define PHY_BASIC_STATUS_REG        0x01U
#define PHY_LINKED_STATUS_MASK      (1<<2)
#define PHY_AUTONEGO_COMPLETE_MASK  (1<<5)

/* The PHY ID one register */
#define PHY_ID1_REG                 0x02U

///* The PHY ID two register */
//#define PHY_ID2_REG                 0x03U

///* The PHY auto-negotiate advertise register */
//#define PHY_AUTONEG_ADVERTISE_REG   0x04U


#ifdef PHY_USING_DP83848C
#define PHY_Status_REG              0x10U
#define PHY_10M_MASK                (1<<1)
#define PHY_FULL_DUPLEX_MASK        (1<<2)
#define PHY_Status_SPEED_10M(sr)    ((sr) & PHY_10M_MASK)
#define PHY_Status_SPEED_100M(sr)   (!PHY_Status_SPEED_10M(sr))
#define PHY_Status_FULL_DUPLEX(sr)  ((sr) & PHY_FULL_DUPLEX_MASK)

/*  The PHY interrupt source flag register. */
//#define PHY_INTERRUPT_FLAG_REG      0x12U
//#define PHY_LINK_CHANGE_FLAG        (1<<13)
///*  The PHY interrupt control register. */
//#define PHY_INTERRUPT_CTRL_REG      0x11U
//#define PHY_INTERRUPT_EN            ((1<<0)|(1<<1))
///*  The PHY interrupt mask register. */
//#define PHY_INTERRUPT_MASK_REG      0x12U
//#define PHY_INT_MASK                (1<<5)
#endif /* PHY_USING_DP83848C */
  • 修改 1
  1. 配置代码关闭自适应
    __HAL_RCC_ETH_CLK_ENABLE();

    /* ETHERNET Configuration */
    EthHandle.Instance = ETH;
    EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
    EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;
    EthHandle.Init.Speed = ETH_SPEED_100M;
    EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
    EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
    EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
#ifdef RT_LWIP_USING_HW_CHECKSUM
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
#else
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
#endif
  1. Rtthread 线程中关闭自适应
static void phy_monitor_thread_entry(void *parameter)
{
    uint8_t phy_addr = 0xFF;
    uint8_t detected_count = 0;

    while(phy_addr == 0xFF)
    {
        /* phy search */
        rt_uint32_t i, temp;
        for (i = 0; i <= 0x1F; i++)
        {
            EthHandle.Init.PhyAddress = i;
            HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);

            if (temp != 0xFFFF && temp != 0x00)
            {
                phy_addr = i;
                break;
            }
        }

        detected_count++;
        rt_thread_mdelay(1000);

        if (detected_count > 10)
        {
            LOG_E("No PHY device was detected, please check hardware!");
        }
    }

    LOG_D("Found a phy, address:0x%02X", phy_addr);

//    /* RESET PHY */
//    LOG_D("RESET PHY!");
//    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
//    rt_thread_mdelay(2000);
//    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);

    phy_linkchange();
#ifdef PHY_USING_INTERRUPT_MODE
    /* configuration intterrupt pin */
    rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
    rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);

    /* enable phy interrupt */
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
#if defined(PHY_INTERRUPT_CTRL_REG)
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
#endif
#else /* PHY_USING_INTERRUPT_MODE */
    stm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
                                        NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
    if (!stm32_eth_device.poll_link_timer || rt_timer_start(stm32_eth_device.poll_link_timer) != RT_EOK)
    {
        LOG_E("Start link change detection timer failed");
    }
#endif /* PHY_USING_INTERRUPT_MODE */
}
  • 修改1-实验结果

结果1.png

  1. 此时可以发现 100M 半双工
  2. BSR(01) = 0x786D; PHY_Status_REG(10) = 0
  3. 正常触发中断
  4. 可以ping通
  • 修改 2
  1. 修改配置代码为 自适应
    __HAL_RCC_ETH_CLK_ENABLE();

    /* ETHERNET Configuration */
    EthHandle.Instance = ETH;
    EthHandle.Init.MACAddr = (rt_uint8_t *)&stm32_eth_device.dev_addr[0];
    EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
    EthHandle.Init.Speed = ETH_SPEED_100M;
    EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
    EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
    EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
#ifdef RT_LWIP_USING_HW_CHECKSUM
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
#else
    EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
#endif
  1. 开启 Rtthread 线程中的Reset 和自适应

static void phy_monitor_thread_entry(void *parameter)
{
    uint8_t phy_addr = 0xFF;
    uint8_t detected_count = 0;

    while(phy_addr == 0xFF)
    {
        /* phy search */
        rt_uint32_t i, temp;
        for (i = 0; i <= 0x1F; i++)
        {
            EthHandle.Init.PhyAddress = i;
            HAL_ETH_ReadPHYRegister(&EthHandle, PHY_ID1_REG, (uint32_t *)&temp);

            if (temp != 0xFFFF && temp != 0x00)
            {
                phy_addr = i;
                break;
            }
        }

        detected_count++;
        rt_thread_mdelay(1000);

        if (detected_count > 10)
        {
            LOG_E("No PHY device was detected, please check hardware!");
        }
    }

    LOG_D("Found a phy, address:0x%02X", phy_addr);

    /* RESET PHY */
    LOG_D("RESET PHY!");
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_RESET_MASK);
    rt_thread_mdelay(2000);
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_BASIC_CONTROL_REG, PHY_AUTO_NEGOTIATION_MASK);

    phy_linkchange();
#ifdef PHY_USING_INTERRUPT_MODE
    /* configuration intterrupt pin */
    rt_pin_mode(PHY_INT_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(PHY_INT_PIN, PIN_IRQ_MODE_FALLING, eth_phy_isr, (void *)"callbackargs");
    rt_pin_irq_enable(PHY_INT_PIN, PIN_IRQ_ENABLE);

    /* enable phy interrupt */
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_MASK_REG, PHY_INT_MASK);
#if defined(PHY_INTERRUPT_CTRL_REG)
    HAL_ETH_WritePHYRegister(&EthHandle, PHY_INTERRUPT_CTRL_REG, PHY_INTERRUPT_EN);
#endif
#else /* PHY_USING_INTERRUPT_MODE */
    stm32_eth_device.poll_link_timer = rt_timer_create("phylnk", (void (*)(void*))phy_linkchange,
                                        NULL, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC);
    if (!stm32_eth_device.poll_link_timer || rt_timer_start(stm32_eth_device.poll_link_timer) != RT_EOK)
    {
        LOG_E("Start link change detection timer failed");
    }
#endif /* PHY_USING_INTERRUPT_MODE */
}
  • 修改2 实验结果

结果2.png

  1. 此时可以发现 100M 半双工
  2. BSR(01) = 0x786D; PHY_Status_REG(10) = 0
  3. 这个时候 无法触发中断
  4. 这个时候 不可以ping通
  • 后期修改
  1. 我思考了一下,在配置中我已经开启了自适应,后面应该就不需要了呀,我修改了,将Rtthread 线程中,的芯片复位和开启 自适应,可惜实验结果同上,不触发中断无法ping通。
  2. 后面我发现只要将配置代码中的
 EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;

修改为

 EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_DISABLE;

就可以正常触发中断,正常ping通,无论Rtthread线程中的 phy 寄存器是否配置位自适应。

疑问

  1. 无论是 8720A 还是 83848,我再读取 PHY_Status_REG() 时为啥都是0;当然8720 寄存器地址是1F;83848 是 10;
  2. 8720 无论是否开启自适应都能ping通,正常触发中断,即使是100M,可能是硬件没达标等。
  3. 为啥 我的83848 配置中是否开启自适应,会影响最终的联网成功失败。

恳请 各位大佬 各位大神指点。。。。

测试环境

  1. 计算机发送数据帧,MCU电路板回应,查看发送数与接收数看是否丢包
  2. 从左至右分别是 83848 启明开发板;8720A自己画的电路板;8720A EC20Plus 开发板;
  3. 测试结果表现为,83848 老是掉线;两块8720A 不掉线,不丢包

恳请 大神 大佬们指点,项目比较急,万分感谢!!!

发布答案

无标题.png

所以说,不用在cubeMX中打开!!!!

发布问题答案。。。
微信截图_20201020102944.png
将QS2 修改为 QS1 正常使用

我知道问题所在了,记录下来,避免大家烦我这种低级错误。

Env中配置的Env Start Addr 应该设置成为 “0”
Env.png
也就是代码中这个宏定义
daima.png

是相对于 fal 分区 EasyFlashEnv 的起始地址,而不是相对于chip Flash 的起始地址。
fal_cfg.png

低级错误,不好意思!

开启PKG_EASYFLASH_LOG

接下来 开启PKG_EASYFLASH_LOG,注意分配空间大小,对应的修改Fal_cfg.h 文件配置大小,如下图所示
Log.png
fal_cfg2.png
至此,设备初始化成功,测试一下看看,测试代码直接参考RTthread官方demo,如下
Test.png
测试结果,再用fal看一下
TestShell.png,对于这些“EF40”、“KV40”字段,我也不知道什么意思。。。
printenv看一下,
printenv.png
看着结果正常,先这样吧,

这些“EF40”、“KV40”字段,有大神知道什么原因,请指点。。。

下面是 EasyLogger 组件添加啦!

图片大小被限制,只能添加附件了。。。。







微信图片_20191018160642.jpg
微信图片_20191018160649.jpg
微信图片_20191018160750.jpg

发布
问题