2 几个头文件的定义
数据类型定义
在LwIP的头文件/src/arch/include/arch目录下cc.h、cpu.h、perf.h文件中有一些与CPU或编译器相关的数据定义(如数据长度,字的高低位顺序等)。这应该与FREERTOS定义的数据长度等参数是一致的。 将cpu.h中的宏定义BYTE_ORDER修改为:
#define BYTE_ORDER LITTLE_ENDIAN即AT32UC3A默认为小端存储系统。 修改cc.h中数据类型长度的定义: typedefunsigned charu8_t; typedef signed char s8_t; typedef unsigned short ul6_t; typedef signed short s16_t; typedef unsigned int u32_t; typedef signed int s32_t; 修改cc.h中宏定义:
一般情况下C语言的结构体struct是4字节对齐的,但是在处理数据包的时候,LwIP使用的是通过结构体中不同数据的长度来读取相应的数据的,所以在定义struct的时候使用_packed关键字,让编译器放弃struct的字节对齐。LwIP在它的结构体定义中有几个PACKED_FIELD_xxx宏,默认的时候这几个宏都是空的,在移植的时候要添加不同的编译器所对应的_packed关键字。 #define PACK_STRUCT_FIELD(x) x
#define PACK_STRUCT_STRUCT _packed #definePACK_STRUCT_BEGIN #definePACK_STRUCT_END
8联合测试
测试程序:
//LWIP查询
void LWIP_Polling(void){
if(timer_expired(&input_time,5)) //接收包,周期处理函数 {
ethernetif_input(&enc28j60_netif); }
if(timer_expired(&last_tcp_time,TCP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//TCP处理定时
器处理函数 { tcp_tmr(); }
if(timer_expired(&last_arp_time,ARP_TMR_INTERVAL/CLOCKTICKS_PER_MS))//ARP处理定时器 { etharp_tmr(); }
if(timer_expired(&last_ipreass_time,IP_TMR_INTERVAL/CLOCKTICKS_PER_MS)){ //IP重新组装定时器 ip_reass_tmr(); }
#if LWIP_DHCP>0
if(timer_expired(&last_dhcp_fine_time,DHCP_FINE_TIMER_MSECS/CLOCKTICKS_PER_MS)) { dhcp_fine_tmr(); }
if(timer_expired(&last_dhcp_coarse_time,DHCP_COARSE_TIMER_MSECS/CLOCKTICKS_PER_MS)) { dhcp_coarse_tmr(); } #endif }
int main(void) {
// u16 tcnt=0; // u8 key;
delay_init(); //延时函数初始化 NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为9600 // LED_Init(); //LED端口初始化 //RTC_Init(); //初始化RTC //Adc_Init(); //初始化ADC #if LWIP_DHCP>0 //若使用DHCP协议 ipaddr.addr = 0; netmask.addr = 0; gw.addr = 0; #else // IP4_ADDR(&ipaddr, 172, 16, 0, 16); //设置本地ip地址
IP4_ADDR(&gw, 172, 16, 0, 1); //网关 IP4_ADDR(&netmask, 255, 255, 255, 0); //子网掩码 #endif
init_lwip_timer(); //初始化LWIP定时器 //初始化LWIP协议栈,执行检查用户所有可配置的值,初始化所有的模块 lwip_init();
// printf(\初始化LWIP协议栈\\r\\n\ //添加网络接口 while((netif_add(&enc28j60_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input)==NULL)) { // u8 i; delay_ms(200); // printf(\网络接口添加失败\\r\\n\// for(i=0;i<6;i++) // { // printf(\// // } } //注册默认的网络接口 netif_set_default(&enc28j60_netif); //建立网络接口用于处理通信 netif_set_up(&enc28j60_netif); /*
Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at the predefined regular intervals after starting the client.
You can peek in the netif->dhcp struct for the actual DHCP status. ip_addr_t offered_ip_addr; ip_addr_t offered_sn_mask; ip_addr_t offered_gw_addr; dhcp_ip = enc28j60_netif.dhcp->offered_ip_addr.addr; printf(\地址:%ld,%ld,%ld,%ld\\t\\n\0)>>16,(dhcp_ip&0xff000000)>>24); */
#if LWIP_DHCP>0 //若使用DHCP协议 dhcp_start(&enc28j60_netif); //为网卡创建一个新的DHCP客户端 #endif xTaskCreate(ping_task, \创建任务 vTaskStartScheduler();
for(;;); }
void ping_task(void *pvParam) { lwip_demo_init(); //初始化lwip_demo while (1) { }
LWIP_Polling(); vTaskDelay( 500 ); }
//LWIP查询
我这里就简单的做了一个环回测试。程序编译完并烧到开发板,注意:设置网卡的IP必须是和电脑的是同网段的。然后ENC28J60网卡模块插上网线,在这之前必须先确定我们设定的IP没有人使用,所以要在上电前先ping一下我们设定的IP,方法如下: 打开电脑的DOS界面,输入:ping 172.16.0.16。
如果在上电之前没有ping通,而上电后ping通则说明移植成功了。
参考文献
《STM32嵌入式系统开发实战指南 FreeRTOS与LwIP联合移植》[李志明等编著][机械工业
出版社][2013.05][322页]
《嵌入式网络那些事(完整中文版)》
《配置FreeRTOS》
《在STM32中移植FreeRTOS》