一,写在前面
上一节已经把所需要的工程源码全部准备好了,前面做的只是基础工作,现在去编译工程会出现非常多的错误以及警告,这一节就是去解决这些错误和警告。
二,修改报错文件
因为是源码是基于FREERTOS的,所以错误的代码不是找不到头文件,就是找不到API,按照这两个思路去解决这些错误就行了。
-
修改头文件报错
删除FREERTOS相关头文件,比如 “FreeRTOS.h” “task.h”,调用这些头文件出现在源码的很多地方,只要替换为RT-Thread相关即可。 -
修改LWIP依赖的OS内核函数
修改sys_arch.c 中关于OS内核函数
例如源码
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
{
osSemaphoreDef(SEM);
*sem = osSemaphoreCreate (osSemaphore(SEM), 1);
if(*sem == NULL)
{
#if SYS_STATS
++lwip_stats.sys.sem.err;
#endif /* SYS_STATS */
return ERR_MEM;
}
if(count == 0) // Means it can't be taken
{
osSemaphoreWait(*sem,0);
}
#if SYS_STATS
++lwip_stats.sys.sem.used;
if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
}
#endif /* SYS_STATS */
return ERR_OK;
}
替换成
err_t sys_sem_new( sys_sem_t *sem, u8_t count )
{
static unsigned short counter = 0;
char tname[RT_NAME_MAX];
sys_sem_t tmpsem;
RT_DEBUG_NOT_IN_INTERRUPT;
rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
counter ++;
tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
if (tmpsem == RT_NULL)
return ERR_MEM;
else
{
*sem = tmpsem;
return ERR_OK;
}
}
完成修改操作
三,工程和LWIP关联起来
-
启动LWIP
在main 调用tcpip_init(NULL, NULL) 来完成LWIP的初始化 -
配置LWIP
调用Netif_Config();完成对LWIP的配置
static void Netif_Config(void)
{
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gw;
IP_ADDR4(&ipaddr,192,168,1,30);
IP_ADDR4(&netmask,255,255,255,0);
IP_ADDR4(&gw,192,168,1,1);
/* add the network interface */
netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
/* Registers the default network interface. */
netif_set_default(&gnetif);
netif_set_link_callback(&gnetif, eth_link_callback);
#if LWIP_DHCP
/* Start DHCPClient */
tid = rt_thread_create("eth_dhcp", DHCP_Thread, &gnetif, 1024, 30, 20);
rt_thread_startup(tid);
#endif
}
- 修改low_level_init
在配置ETH之前增加PHY硬复位
phy_reset();
把FREERTOS创建任务函数替换为RT-Thread
/* create the task that handles the ETH_MAC */
xTaskCreate( ethernetif_input, "eth_if",
INTERFACE_THREAD_STACK_SIZE, netif, INTERFACE_TASK_PRIORITY,NULL);
/* create the task that handles the eth_link */
xTaskCreate( ethernet_link_thread, "eth_link",
INTERFACE_THREAD_STACK_SIZE, netif,INTERFACE_TASK_PRIORITY,NULL);
rt_thread_t tid = rt_thread_create("eth_rx", ethernetif_input, netif, 2048, 2, 10);
rt_thread_startup(tid);
rt_thread_t tid = rt_thread_create("eth_link", ethernet_link_thread, &gnetif, 1024, 20, 10);
rt_thread_startup(tid);
- 修改low_level_output
在发送函数前要增加一句SCB_CleanInvalidateDCache();
TxConfig.Length = framelen;
TxConfig.TxBuffer = Txbuffer;
SCB_CleanInvalidateDCache();
HAL_ETH_Transmit(&EthHandle, &TxConfig, 0);
- 修改收发函数的信号量API
原来的API都是基于FREERTOS的,修改为RT-Thread
如:
if (osSemaphoreWait( RxPktSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
修改为:
if(rt_sem_take(ð_rxin, RT_WAITING_FOREVER) == RT_EOK)
- 把开发板和电脑连接起来
能看到开发板和电脑的已经通讯了。至此移植全部完成。
四,我移植过程中遇到的问题
-
发送函数增加SCB_CleanInvalidateDCache();
这个和cache策略配置有关,这个CACHE还需要多少研究。不加这一句会导致发送失败。 -
PHY硬复位
如果不复位可能导致ETH配置失败。 -
lwipopts.h修改
这里使用LWIP的动态内存,所以要把这个宏定义为1。
#define MEMP_MEM_MALLOC 1
- LWIP的RAM设置
这里的设置一定要是
#define LWIP_RAM_HEAP_POINTER (0x30044000)
- 设置pbuf_size
#define PBUF_POOL_BUFSIZE 1536
- 注意2个宏定义
#define ETH_RX_BUFFER_SIZE (1536UL)
#define ETH_MAX_PACKET_SIZE ((uint32_t)1528)
这两个宏定义只能使用其中一个,因为大小不一样,会导致内存出现问题。
五,我参考GITHUB上的代码中存在的问题
- 发送函数没有增加SCB_CleanInvalidateDCache();
- 在配置PHY之前没有给一个硬复位;
- LWIP提供了3中内存分配机制,但是全部定义为0,既都没使用;
- pbuf_size通过宏定义来实现,我直接手动到设置为1536;