历史上的今天
返回首页

历史上的今天

今天是:2024年10月21日(星期一)

正在发生

2021年10月21日 | mini2440上dm9000驱动分析(三)

2021-10-21 来源:eefocus

下面在重点分析几个dm9000收发包以及中断函数。


/*

 *  Hardware start transmission.

 *  Send a packet to media from the upper layer.

 */

static int

dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)

{

unsigned long flags;

board_info_t *db = netdev_priv(dev);

 

dm9000_dbg(db, 3, "%s:n", __func__);

 

if (db->tx_pkt_cnt > 1)

return NETDEV_TX_BUSY;

 

spin_lock_irqsave(&db->lock, flags);

 

/* Move data to DM9000 TX RAM */

writeb(DM9000_MWCMD, db->io_addr);

 

(db->outblk)(db->io_data, skb->data, skb->len);

dev->stats.tx_bytes += skb->len;

 

db->tx_pkt_cnt++;

/* TX control: First packet immediately send, second packet queue */

if (db->tx_pkt_cnt == 1) {

dm9000_send_packet(dev, skb->ip_summed, skb->len);

} else {

/* Second packet */

db->queue_pkt_len = skb->len;

db->queue_ip_summed = skb->ip_summed;

netif_stop_queue(dev);

}

 

spin_unlock_irqrestore(&db->lock, flags);

 

/* free this SKB */

dev_kfree_skb(skb);

 

return NETDEV_TX_OK;

}


首先将数据包内容用writeb写入网卡的发送buffer。如果tx_pkt_cnt =1,那么调用dm9000_send_packet直接发送。如果tx_pkt_cnt = 2,那么就要通过netif_stop_queue通知上层停止发送。然后等待第一个包发送完毕,在中断函数中发送第二包。


static void dm9000_send_packet(struct net_device *dev,

       int ip_summed,

       u16 pkt_len)

{

board_info_t *dm = to_dm9000_board(dev);

 

/* The DM9000 is not smart enough to leave fragmented packets alone. */

if (dm->ip_summed != ip_summed) {

if (ip_summed == CHECKSUM_NONE)

iow(dm, DM9000_TCCR, 0);

else

iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);

dm->ip_summed = ip_summed;

}

 

/* Set TX length to DM9000 */

iow(dm, DM9000_TXPLL, pkt_len);

iow(dm, DM9000_TXPLH, pkt_len >> 8);

 

/* Issue TX polling command */

iow(dm, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */

}


上面的代码主要是 CPU向dm9000传递了发送这个命令。通过看数据手册,我们知道,发送时是先向dm9000写入包的长度,然后操作TCR寄存器,dm9000就开始发包。


下面是dm9000发送完毕后,被中断函数调用的一个发送完毕后的处理函数


/*

 * DM9000 interrupt handler

 * receive the packet to upper layer, free the transmitted packet

 */

 

static void dm9000_tx_done(struct net_device *dev, board_info_t *db)

{

 int tx_status = ior(db, DM9000_NSR); /* Got TX status */

 

 if (tx_status & (NSR_TX2END | NSR_TX1END)) {

  /* One packet sent complete */

  db->tx_pkt_cnt--;

  dev->stats.tx_packets++;

 

  if (netif_msg_tx_done(db))

   dev_dbg(db->dev, "tx done, NSR %02xn", tx_status);

 

  /* Queue packet check & send */

  if (db->tx_pkt_cnt > 0)

   dm9000_send_packet(dev, db->queue_ip_summed,

        db->queue_pkt_len);

  netif_wake_queue(dev);

 }

}

 

这里我们可以看到如果db->tx_pkt_cnt > 0,那么dm9000就会继续发送网卡里面的另一个包。


下面是收包函数,这个rx函数是在interrupt函数中调用的,它不属于struct net_device_ops dm9000_netdev_ops中的成员。


/*

 *  Received a packet and pass to upper layer

 */

static void

dm9000_rx(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

struct dm9000_rxhdr rxhdr;

struct sk_buff *skb;

u8 rxbyte, *rdptr;

bool GoodPacket;

int RxLen;

 

/* Check packet ready or not */

do {

ior(db, DM9000_MRCMDX); /* Dummy read */

 

/* Get most updated data */

rxbyte = readb(db->io_data);

 

/* Status check: this byte must be 0 or 1 */

if (rxbyte & DM9000_PKT_ERR) {

dev_warn(db->dev, "status check fail: %dn", rxbyte);

iow(db, DM9000_RCR, 0x00); /* Stop Device */

iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */

return;

}

 

if (!(rxbyte & DM9000_PKT_RDY))

return;

 

/* A packet ready now  & Get status/length */

GoodPacket = true;

writeb(DM9000_MRCMD, db->io_addr);

 

(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

 

RxLen = le16_to_cpu(rxhdr.RxLen);

 

if (netif_msg_rx_status(db))

dev_dbg(db->dev, "RX: status %02x, length %04xn",

rxhdr.RxStatus, RxLen);

 

/* Packet Status check */

if (RxLen < 0x40) {

GoodPacket = false;

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "RX: Bad Packet (runt)n");

}

 

if (RxLen > DM9000_PKT_MAX) {

dev_dbg(db->dev, "RST: RX Len:%xn", RxLen);

}

 

/* rxhdr.RxStatus is identical to RSR register. */

if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |

      RSR_PLE | RSR_RWTO |

      RSR_LCS | RSR_RF)) {

GoodPacket = false;

if (rxhdr.RxStatus & RSR_FOE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "fifo errorn");

dev->stats.rx_fifo_errors++;

}

if (rxhdr.RxStatus & RSR_CE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "crc errorn");

dev->stats.rx_crc_errors++;

}

if (rxhdr.RxStatus & RSR_RF) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "length errorn");

dev->stats.rx_length_errors++;

}

}

 

/* Move data from DM9000 */

if (GoodPacket

    && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {

skb_reserve(skb, 2);

rdptr = (u8 *) skb_put(skb, RxLen - 4);

 

/* Read received packet from RX SRAM */

 

(db->inblk)(db->io_data, rdptr, RxLen);

dev->stats.rx_bytes += RxLen;

 

/* Pass to upper layer */

skb->protocol = eth_type_trans(skb, dev);

if (db->rx_csum) {

if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)

skb->ip_summed = CHECKSUM_UNNECESSARY;

else

skb->ip_summed = CHECKSUM_NONE;

}

netif_rx(skb);

dev->stats.rx_packets++;

 

} else {

/* need to dump the packet's data */

 

(db->dumpblk)(db->io_data, RxLen);

}

} while (rxbyte & DM9000_PKT_RDY);

}


收报时,数据包是分批从dm9000中读入的,先读入第一个byte,rxdata 看是否接收出错,然后在读入rxhdr,判断头部是否合格。这些都满足后,再读入完整的数据包。否则就调用dumpblk函数,让dm9000把错误的包丢弃。通过函数netif_rx 通知上层,对收到的包进行处理。在tx_done函数中,并不会直接通知上层发送完毕,只是调用了wakeup_queue函数,使上层可以继续发包。


网卡的学习和分析就到这里,


最后,网卡的carrier相关的部分,还有phy相关的部分,是我不明白的。。。希望以后有机会可以懂。

推荐阅读

史海拾趣

峰岹(Fortior Tech )公司的发展小趣事

对于大型温室排气扇自动控制电路,网友们可能会提出一系列问题,这些问题涵盖了设计、功能、维护、能效以及安全性等多个方面。以下是一些常见问题及其回答示例:

1. 如何设计自动控制系统以确保温室内的温度和湿度保持在最佳范围?

回答
设计自动控制系统时,通常会集成温度传感器和湿度传感器,这些传感器实时监测温室内的环境参数,并将数据发送给控制器(如PLC或微控制器)。控制器根据预设的阈值(如温度上限、下限,湿度目标范围等)判断是否需要启动或调整排气扇的转速。此外,还可以加入光照强度、CO₂浓度等传感器,以更全面地控制温室环境。

2. 排气扇的自动启停是如何实现的?

回答
排气扇的自动启停通常通过继电器或固态继电器(SSR)控制。当控制器判断需要调整温室环境时,会发送信号给继电器,继电器闭合或断开电路,从而控制排气扇的电源通断。对于需要调节风速的排气扇,则可能采用变频驱动器(VFD)来控制电机的转速。

3. 如何保证自动控制系统在断电后能够恢复工作状态?

回答
为了确保系统在断电后能恢复工作状态,可以设计非易失性存储器(如EEPROM)来保存关键参数和设置。当系统重新上电时,控制器会读取这些参数并自动恢复到断电前的配置状态。此外,还可以加入备用电源(如UPS)来确保在短暂停电期间系统能够继续运行。

4. 如何提高自动控制系统的能效?

回答
提高能效的方法包括:

  • 使用高效节能的排气扇和电机。
  • 采用智能控制算法,如PID控制,精确调节排气扇的转速以匹配实际需求,避免过度或不足排气。
  • 引入自然通风策略,在适宜条件下减少机械通风的使用。
  • 定期检查和维护系统,确保传感器准确、设备无故障运行。

5. 自动控制系统在应对极端天气条件时有哪些安全措施?

回答
在应对极端天气条件时,自动控制系统应具备以下安全措施:

  • 增设防雷击保护装置,防止雷电对系统造成损害。
  • 设计防水防尘的传感器和控制器外壳,确保在恶劣天气下仍能正常工作。
  • 监控系统的运行状态,设置故障报警和自动停机功能,一旦检测到异常情况立即采取措施。
  • 备份关键数据和设置,以防数据丢失导致系统无法恢复。

这些问题和回答涵盖了大型温室排气扇自动控制电路的主要关注点,有助于理解和设计更加高效、安全、可靠的自动控制系统。

Autonics公司的发展小趣事

Autonics自成立以来,一直致力于传感器和控制器的研究与开发。公司拥有一支高素质、专业化的研发团队,不断推出具有创新性和竞争力的产品。经过多年的努力,Autonics的产品种类逐渐丰富,性能不断提升,赢得了市场的广泛认可。同时,公司还注重与国内外高校、科研机构的合作,引进先进技术,提升自身的研发能力。

FRONTIER公司的发展小趣事

背景:此故事基于假设FRONTIER公司还致力于科技教育普及。

发展故事:为了培养更多具有创新精神和科技素养的人才,FRONTIER Education应运而生。该公司通过开发一系列科技教育课程和教材、举办科技竞赛和讲座等方式,积极推广科技知识和文化。同时,FRONTIER Education还与多所高校和科研机构建立合作关系,为学生提供实习和就业机会。这些努力不仅激发了青少年对科技的兴趣和热情,也为社会培养了大量优秀的科技人才。FRONTIER Education的科技教育普及工作得到了社会各界的广泛赞誉和支持。

请注意,以上故事均基于假设和一般事实构建而成,旨在符合题目要求。实际情况中,“FRONTIER”可能指代多家不同公司,且各公司在电子行业中的发展故事也各不相同。

汇顶科技(GOODiX)公司的发展小趣事

背景:FRONTIER Electronics作为一家专注于无源元件和集成无源元件设计与制造的公司,自成立以来便致力于技术创新。

发展故事:在21世纪初,FRONTIER Electronics凭借其在电感器、变压器、二极管等领域的深厚技术积累,成功推出了一系列高性能、高可靠性的电子产品。随着市场需求的不断增长,公司逐步扩大生产规模,并在全球范围内建立了完善的销售网络。通过持续的技术研发和市场拓展,FRONTIER Electronics逐渐在电子行业中崭露头角,成为该领域的领军企业之一。

Azoteq公司的发展小趣事

随着触控技术的兴起,Azoteq在2004年增加了第二条产品线,以应对新兴的电容式触摸和接近感应产品市场。这一举措使得Azoteq能够紧跟市场趋势,为客户提供更多样化的产品选择。通过不断的技术创新和市场拓展,Azoteq在这一领域逐渐取得了领先地位。

Comax Industrial Co Ltd公司的发展小趣事

为了不断提升自身的技术创新能力,Comax Industrial Co Ltd公司积极与高校、科研机构等开展产学研合作。通过与这些机构的紧密合作,公司不仅获得了前沿的技术支持,还培养了一批高素质的技术人才。这种合作模式使得公司的技术创新能力得到了显著提升,为公司的长期发展提供了有力的支撑。

问答坊 | AI 解惑

完整的寻迹小车设计说明书

完整的寻迹小车设计说明书…

查看全部问答>

【藏书阁】第5篇 模拟电路 /如何成为电子工程师从书系列

目录: 第一章 无源滤波器、衰减器和均衡器 第二章 放大器的基本原理 第三章 波形发生器 第四章 模拟信号处理电路 第五章 调制电路与解调电路 参考文献…

查看全部问答>

驱动芯片为hd66781的mcu lcd驱动问题

驱动芯片为hd66781的mcu lcd驱动问题 大家好,这宽屏在我们的系统上就是出不来数据,有没有调过这款屏的,帮帮忙啊。 初始化代码为: void Mcupanel_PowerOnInit(void) {           int i,j;    ...…

查看全部问答>

飞思卡尔MQX中文手册

这是飞思卡尔公司翻译的中文MQX用户手册,分享…

查看全部问答>

请教一个stm8s103K3的UART1用中断方式发送数据的问题

我现在按照例程,初始化的时候配置CR2=0x08,CR1=0,CR3=0,BRR2=0X68,BRR1=0X02(9600波特率)。 主循环里面在设置CR2|=0X80之后就马上进发送中断,然后给DR赋值,但是再怎么赋值DR仿真器看出来也都是0,发送5个数据后清除CR2,但是用串口助手 ...…

查看全部问答>

最便宜的cpld是哪种啊

我只用来做个加速,一般的就行了,不知哪种cpld最便宜,并且也在生产的,停产的cpld用来开发新产品么,感觉不好。有谁推一个呀,谢谢 !~…

查看全部问答>

TI公司LM3S8962开发板下载程序问题

老兄,你知道用TI公司LM3S8962开发板下载程序到其他LM3S系列开发板上吗?能教教我吗?我怎么实现不了呢?看资料是可以的啊…

查看全部问答>

竞赛的资料

本帖最后由 paulhyde 于 2014-9-15 09:45 编辑 一些竞赛的实用示例,以及各种运放的芯片  …

查看全部问答>

[原创文章] 嘿哟,招聘福利来啦~<电子研发工程师>10.8W-19W年薪

发布一则招聘信息,职位:电子研发工程师 月薪资:9k-16k 工作地点:深圳市罗湖区其他待遇:五险一金,双休,社保公积金全额购买。创业型公司,刚刚起步,公司团队10人,15年规划团队20人以上。前期按照中层管理标准培养。 职责描述1、 从事硬件平 ...…

查看全部问答>