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

对于没有内置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
	}
}

 

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

你可能感兴趣的:(linux)