官方例程NET_MAC.C中,定时执行ARP发送,当发送完成触发中断后,查看中断状态字ISR的低八位,printf出来总是显示0x18,也就是说发送完成后ISR的bit3和bit4均为1。
官方手册定义:bit4=1时,表示发送完成。bit3=1时,表示发送缓冲区无效。
为何这里始终出现这个异常?发送缓冲区无效?如何消除掉发送缓冲区无效异常?
官方例程NET_MAC.C中,定时执行ARP发送,当发送完成触发中断后,查看中断状态字ISR的低八位,printf出来总是显示0x18,也就是说发送完成后ISR的bit3和bit4均为1。
官方手册定义:bit4=1时,表示发送完成。bit3=1时,表示发送缓冲区无效。
为何这里始终出现这个异常?发送缓冲区无效?如何消除掉发送缓冲区无效异常?
主要是我自己的写的程序里,总是有这个异常,不管怎样都消不掉,后来用官方例程试试,结果发现也是一样。。。
我怀疑,这个bit3的定义是不是搞错了?比如bit3的实际定义,其实是数据已写入TXFIFO的标记位?
做了一波新的测试:
1、将R32_ETHE_IMR设置为0x02FF,即启用所有的以太网中断事件。
2、在数据发送函数中,临发送前将发送缓冲区的地址(TX描述符的DES2)清0。
3、手动发送数据。
保存、编译、下载后,运行结果很诡异。
第一次手动(按钮)执行发送后,片子竟然没有进入中断。。。
然后第二次手动(按钮)执行发送,程序走死了。
分析:
因为我的数据发送函数中,一进入函数首先查询是否有现存发送任务:
while(mac_cotrl.txdes_cur->txdes0 & 0x80000000); //如有现存发送任务,就死等
所以,在第一次执行发送时,因为找不到发送缓冲区,所以发送动作一直没有完成,描述符的OWN位始终为1,同时因为没有进入中断,描述符也没有切换到另一个,所以在第二次发送时,程序就卡在这里过不去了。
令人惊奇的是,为什么发送缓冲区无效时,没有触发中断??数据手册说R32_ETHE_ISR的bit3标记发送缓冲区无效事件。可实际运作中,这个bit3却失效了。反而在正常发送成功时,bit3又总会被置1??
不知道官方大神们有没有遇到这种状况??期待交流!
进一步测试,R32_ETHE_ISR寄存器中,关于发送的4个标记位,测试结果如下:
RB_XPKT_OK(bit5):
手册描述该位标记因冲突过多导致的数据发送失败事件。
测试中在没有插网线的情况下,执行发送动作,无法激活这个标记。至于线路冲突,因无法模拟,所以无法验证。
RB_XPKT_OK(bit4):
手册描述该位标记数据发送成功事件。
测试中证明该位有效,不论是不是插网线,这个位都会作出响应。
RB_NOTXBUF(bit3):
手册描述该位负责标记发送缓冲区无效事件。1=发送缓冲区无效;0=正常。
测试过程中,当发送缓冲区无效时,该bit无响应,也无法触发中断。当发送缓冲区有效时,该bit会误动作置1。详细描述见楼上。。。
RB_XPKT_FINISH(bit2):
手册描述该位负责标记发送数据写入TXFIFO事件。1=发送数据已写入TXFIFO。0=无
测试发现,启用该事件中断后,执行数据发送动作,无法触发该中断。该标记位对相关事件无响应,就没见它动过,永远都是0。
综上,在ISR寄存器中,只有数据发送成功(bit4)事件可以非常可靠的响应事件触发中断。bit5可能有用,值得保留。bit3和bit2属于神经刀,目前我还没有找到办法用起来。。。
算不上大神,我也斗胆回复下。
ummm,你居然这么仔细,把所有的状态位都打印出来了……很佩服你这样的钻研精神。其实我昨晚在你发帖后十五分钟就看到了,然后我复现出来后也挺迷惑的。今天你又发帖了,我会先回复下,权当抛砖。这个RB_NOTXBUF置位是什么意思我也不清楚。我猜测这个RB_NOTXBUF置位可能是以下几种情况之一引起的:
1,发送缓冲区不是正确的SRAM地址。也就是你在三楼提出来的。这个情况几率较小,按你的操作把DES2清零,CH563零地址是flash啊,umm,这不是让DMA去读flash的数据了么。这个操作的后果确实可能会直接死机额。
2,发送缓冲区被DMA使用结束了。这个位可能置位并不是表示异常的、不好的现象,也可能是表示当前发送成功了,刚使用的发送缓冲和发送FIFO 也都空出了。用户可以对空出来的发送缓冲区进行操作了。
3,这个发送缓冲区挂靠的发送描述符当前由CPU(软件)占用,DMA无权使用,或者仅仅是这个发送缓冲区正在被CPU访问,DMA的操作被拒绝了。
以上三个猜想我都觉得不是很靠谱,毕竟发送缓冲区实际上是个SRAM,谁都能读写,被同时要求访问的概率太小。
我个人觉得学习以太网收发器的重点在于理解以太网上的数据和描述符在FIFO,收发缓冲区和自己设的缓冲区之间的流转过程,以及搞清楚CPU和DMA在这些过程中需要做的事情。以太网中断有许多中断源,也不是所有中断源都要使能的,毕竟让不重要的中断打断程序运转挺浪费时间的,CH563是百兆的,如果加上协议栈再把速度跑满时,所有以太网中断都要响应会让处理速度大打折扣,是可惜的。CH563有个特点,即使不使能某个中断源让其产生中断,你去读中断标志位还是能读到这个中断的,这点需要注意。
还有就是我会继续去搞清楚RB_NOTXBUF位的具体含义,也欢迎你接着探讨。CH563的MAC收发源码我觉得管理描述符不是很高效,有写得更简洁的空间。以后我再写一个MAC收发的示例,请沁恒的前辈和你指点,我也是学物联网的,大家共勉吧。
感谢5楼的兄弟,有人一起讨论真的好开心!
关于你的三个猜测:
关于猜测1:
我在把发送缓冲区地址清0之后,并没有死机,因为我在主程序写了一个闪烁灯,每0.5秒翻转LED状态,所以可以很负责任的说,发送无效缓冲区并没有造成死机,闪烁灯一直在闪,而且还可以执行第二次发送。只是第二次发送会因为我三楼说的原因卡死。
关于猜测2:
首先要说你的描述有问题。数据发送激活TXDMA后,将数据从缓冲区读取到TXFIFO的动作,并不会删掉缓冲区里的数据。缓冲区不是FIFO,它是内存。所以取完数据之后,缓冲区不会被清空。
然后,按你的描述,这个bit3的功能将和发送完成标记位的功能重叠。不过从事实来看,确实有这个可能。但从设计的角度,这就是个bug了。没理由同一种状态要关联2个标记位啊。
关于猜测3:
个人认为不可能。因为这个标记位即使为1,也不影响下一次发送,所以不存在你说的DMA或者缓冲区被占用之类的问题。
关于CH563的MAC收发源码效率问题,唉。。。不说了,说了都是泪
目前我的程序禁用了所有MAC发送相关的中断,就在主程序中完成发送和发完之后的相关重置。
同时在主程序中监控ISR中的2个标记位:发送完成标记位(bit4)和发送失败标记位(bit5)。
当这两个bit任意一个位被置1,就算是发完了。剩下2个神经刀bit,因为搞不懂,所以不敢用。。。
今天咨询了负责单片机方面的工程师,他说RB_NOTXBUF被置位是由于在发送完成读状态描述符的时候,DMA还没有放开对发送缓冲区的控制。所以还是别纠结这方面了……那么请问你是在写什么功能的代码呢?就是自己写一个以太网底层的驱动吗?
既然已经被强奸,所以也就只能把眼睛闭上了。。。
这款芯片的最大特点就是集成以太网,所以把这块搞明白很重要。你的这个解释很牵强,首先是DMA把缓冲区里的数据写入TXFIFO,然后PHY把TXFIFO中的数据发出去。按道理数据都发完了,DMA没理由还在取数据。还是希望能有个更合理的解释。
至于未来的方向,可能还是会以工控居多吧,应该不会往娱乐方向发展。
改了一下代码,验证一下8楼说的可能,发现不是那个状况。
在发送完成后,我增加了一行代码:while(own),确保DMA已经释放了缓冲区权限,然后再打印,仍然是0x18。。。
算了,不纠结了。正在琢磨接收,等把接收搞透了,就可以让CH563带我装逼带我飞了。。。