嵌入式网络那些事例程移植到stm32f103c8
以太网IP,UDP协议传输的数据是逐级包含的关系如下图,
以太网帧:
以太网帧头+以太网数据
IP帧头+IP数据 ARP数据包
ICMP帧头+ICMP数据 / UDP帧头+UDP数据
用户数据
UDP数据如何被接收的:
网口芯片有以太网数据后,发出中断给stm32。
stm32在中断调用ethernet.c中的ethernetif_input(),也传入了当前的netif结构;
ethernetif_input调用了同一个文件下的low_level_input();
low_level_output调用了同一个文件下的PacketReceive();
PacketReceive调用网口芯片接口,读取网口芯片中暂存的1500个数据;申请一个pbuf,将1500个数据存入pbuf,返回该pbuf指针。
根据返回pbuf指针的payload(帧头:有目的地址,源地址,帧类型),判断帧类型:是IP?ARP?ETHTYPE_PPPOEDISC?还是ETHTYPE_PPPOE?
判断之后就调用netif->input(),它在初始化时已经注册为etharp.c中的ethernet_input()
ethernet_input去掉以太帧首部,调用ip.c中的ip_input();
ip_input调用udp.c中的udp_input();
udp_input去掉IP首部,调用pcb->recv(),并将以太帧中的用户数据递交,而pcb->recv在初始化时注册为:udp_demo_callback();这样用户程序udp_demo_callback就能获得用户数据。
UDP数据如何发送的:
用户程序分配tansport类型的pbuf,pbuf中有预留的ethhdr,iphdr,和udphdr,同样也包含了用户数据。调用udp_sendto();
udp_sendto调用udp.c中的udp_sendto_if(),
udp_sendto_if填充udp的首部,计算校验和后,调用ip.c中的ip_output_if()
ip_output_if填充ip的首部,计算校验和,调用netif->output(),而它在ethernetif_init()时,已经注册为etharp.c中的etharp_output();
etharp_output调用同一文件下的etharp_send_ip()
etharp_send_ip填充ethhdr后,调用netif->linkoutput(),而它在ethernetif.c的ethernetif_init()时,已经注册为ethernetif.c下的low_level_output()
low_level_output调用同一文件下的PacketSend();
PacketSend通过spi接口把数据发送给外部网口。
例程是基于stm32f103ze的,资源充足是c8的3倍;移植到c8上需要做如下工作:
1、更改spi文件,spi的接口,其中spi总线用到spi1是PA5,PA6,PA7,rst管脚不需要接,针对我的板子,更换cs引脚为PA9
注意更改spi速率SPI_BaudRatePrescaler。实测256无法连接,改为4就能连接了,这个卡了好久;
2、main,NVIC中的中断使能很多例程都是关断的,作者用的都是查询方式处理,这里可以更改为中断处理,但是要注意while(1)中的处理屏蔽掉
更改为EXTI_Line1,source更改为A 1,IRQChannnel跟改为EXTI1_IRQn,总之都更改到相应的通道就行。共5个地方
_IT.c文件中的EXTI_IRQ也更改为相应的名字,还有清楚标志位的语句;共3个地方
3、GPIO初始化函数,A0改为输入,它和NVIC函数共同作用,作为中断
4、更改lwip_init_task中的网关,子网掩码,I;
5、更改lwipopts.h中的选项,MEM_SIZE更改成2*1024,debugprintf选项,opts.h中PBUF_POOL_SIZE改为8
6、lwip,主机ping通板卡,但是板卡ping不到主机,原因很可能是主机防火墙打开了,关闭既能双向ping通