【Linux驱动开发】DM9051NP的linux版本驱动

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 16:16   1881   0

对于没有内置EMAC的处理器,如全志F1C100S等,如果需要连接有线网,一般只有2种办法:SPI接口扩展(DM9051NP)和USB接口扩展。本文提供SPI接口的DM9051的驱动,以及官方的驱动问题修正。

环境:

处理器:F1C100S

软件环境:Linux-4.15

DM9051驱动,一般提供轮询(Poll)方式和中断(Interrupt)方式,对于现在网上能下载到的驱动,如1.69.3等,如果使用轮询方式,也可以工作,但CPU占用率非常高,很不实际。因此中断方式是首选。然而对于中断方式,1.69版本驱动及可收集到的驱动,要注意以下情况:

1、对于IRQ引脚中断,原本驱动中设置成IRQF_TRIG_NONE。如果DTS设备树中未指定该引脚的中断方式,需要在驱动中进行指定。要注意的是,因为spi通讯不支持并发,因此必须带有IRQF_ONESHOT,以保证不会嵌套触发中断。同时,如果配置为下降沿触发(IRQF_TRIG_FALLING),当中断程序中处理较大数据帧较耗时的情况下,极有可能出现无法触发下一次中断,导致无法进行接收数据包。

因此,中断方式驱动时,设置为电平触发是稳妥的。我的配置是低电平触发,即 IRQF_TRIG_LOW | IRQF_ONESHOT 。

ret = request_threaded_irq(spi->irq, NULL, dm951_irq,
         IRQF_TRIGGER_LOW | IRQF_ONESHOT,
         ndev->name, db);

2、官方驱动中存在bug,导致的现象是 Ping延迟从100ms渐渐降低到1ms,然后再次循环。原因在于官方驱动在函数dm9051_start_xmit 中,虽然正确启动了任务 dm9051_tx_work ,但在函数dm9051_tx_work 中错误的使用了rx_work结构来获取当前db结构数据,导致dm9051_tx函数中判断db->bt.prob_cntStopped为0。

而官方驱动还是能工作的原因在于,在中断服务程序中,判断了是否需要发送数据,如果需要发送,则进行发送。因此导致了Ping的延迟不稳定。

/* 系统发送数据包函数 */
static netdev_tx_t 
dm9051_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
 board_info_t *db = netdev_priv(dev);

 spin_lock(&db->statelock);//mutex_lock(&db->addr_lock);

 toend_stop_queue1(dev, db->bt.prob_cntStopped++ );
 skb_queue_tail(&db->txq, skb); // JJ: a skb add to the tail of the list '&db->txq'
 driver_dtxt_step(db, '0'); //driver_dtxt_step(db, 'q'); // Normal
 spin_unlock(&db->statelock);//mutex_unlock(&db->addr_lock);

 schedule_work(&db->tx_work);

 return NETDEV_TX_OK;
}
/* 实际向DM9051发送数据包函数 */
static void dm9051_tx_work(struct work_struct *work)
{
 board_info_t *db = container_of(work, board_info_t, rxctrl_work); /* 这里不应该使用rxctrl_work,而应该是tx_work */
 dm9051_tx(db);
}

static void dm9051_tx(board_info_t *db)
{
 struct net_device *dev = db->ndev;
 if (db->bt.prob_cntStopped)  // This is more exactly right!!
 {
    #if LOOP_XMIT
      mutex_lock(&db->addr_lock);
      dm9051_continue_xmit_inRX(db); //=dm9051_continue_poll_xmit
      opening_wake_queue1(dev); 
      mutex_unlock(&db->addr_lock);
    #endif //LOOP_XMIT
 }
}

修正了这两个之后,驱动即可以正常工作。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP