一、写在前面
上一节已经把所需要的工程源码全部准备好了,前面做的只是基础工作,现在去编译工程会出现非常多的错误以及警告,这一节就是去解决这些错误和警告。
二、修改报错文件
因为是源码是基于FREERTOS的,所以错误的代码不是找不到头文件,就是找不到API,按照这两个思路去解决这些错误就行了。
1、修改头文件报错
删除FREERTOS
相关头文件,比如“FreeRTOS.h” “task.h”
,调用这些头文件出现在源码的很多地方,只要替换为RT-Thread
相关即可。
2、修改LWIP依赖的OS内核函数
修改sys_arch.c
中关于OS内核函数
例如源码
1err_t sys_sem_new(sys_sem_t *sem, u8_t count)
2{
3 osSemaphoreDef(SEM);
4
5 *sem = osSemaphoreCreate (osSemaphore(SEM), 1);
6
7 if(*sem == NULL)
8 {
9#if SYS_STATS
10 ++lwip_stats.sys.sem.err;
11#endif /* SYS_STATS */
12 return ERR_MEM;
13 }
14
15 if(count == 0) // Means it can't be taken
16 {
17 osSemaphoreWait(*sem,0);
18 }
19
20#if SYS_STATS
21 ++lwip_stats.sys.sem.used;
22 if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
23 lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
24 }
25#endif /* SYS_STATS */
26
27 return ERR_OK;
28}
修改为
1err_t sys_sem_new( sys_sem_t *sem, u8_t count )
2{
3 static unsigned short counter = 0;
4 char tname[RT_NAME_MAX];
5 sys_sem_t tmpsem;
6
7 RT_DEBUG_NOT_IN_INTERRUPT;
8
9 rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter);
10 counter ++;
11
12 tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO);
13 if (tmpsem == RT_NULL)
14 return ERR_MEM;
15 else
16 {
17 *sem = tmpsem;
18
19 return ERR_OK;
20 }
21}
替换请参考RT-Thread的LWIP软件包
链接:https://github.com/RT-Thread/rt-thread/tree/master/components/net/lwip-2.1.0(喜欢RT-Thread不要忘了在GitHub上留下你的星哦)
完成修改操作
三、工程和LWIP关联起来
1、启动LWIP
在 main 调用tcpip_init(NULL, NULL)
来完成LWIP的初始化
2、配置LWIP
调用Netif_Config();
完成对LWIP的配置
1static void Netif_Config(void)
2{
3 ip_addr_t ipaddr;
4 ip_addr_t netmask;
5 ip_addr_t gw;
6
7 IP_ADDR4(&ipaddr,192,168,1,30);
8 IP_ADDR4(&netmask,255,255,255,0);
9 IP_ADDR4(&gw,192,168,1,1);
10
11 /* add the network interface */
12 netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &tcpip_input);
13
14 /* Registers the default network interface. */
15 netif_set_default(&gnetif);
16
17 netif_set_link_callback(&gnetif, eth_link_callback);
18
19
20#if LWIP_DHCP
21 /* Start DHCPClient */
22 tid = rt_thread_create("eth_dhcp", DHCP_Thread, &gnetif, 1024, 30, 20);
23 rt_thread_startup(tid);
24#endif
25}
3、修改low_level_init
在配置ETH之前增加PHY硬复位
1phy_reset();
把FREERTOS创建任务函数替换为RT-Thread
1 /* create the task that handles the ETH_MAC */
2 xTaskCreate( ethernetif_input, "eth_if", INTERFACE_THREAD_STACK_SIZE, netif, INTERFACE_TASK_PRIORITY,NULL);
3
4 /* create the task that handles the eth_link */
5 xTaskCreate( ethernet_link_thread, "eth_link", INTERFACE_THREAD_STACK_SIZE, netif, INTERFACE_TASK_PRIORITY,NULL);
查看剩余代码部分请向?滑动屏幕
1 rt_thread_t tid = rt_thread_create("eth_rx", ethernetif_input, netif, 2048, 2, 10);
2 rt_thread_startup(tid);
3 rt_thread_t tid = rt_thread_create("eth_link", ethernet_link_thread, &gnetif, 1024, 20, 10);
4 rt_thread_startup(tid);
4、修改low_level_output
在发送函数前要增加一句 SCB_CleanInvalidateDCache();
1 TxConfig.Length = framelen;
2 TxConfig.TxBuffer = Txbuffer;
3
4 SCB_CleanInvalidateDCache();
5 HAL_ETH_Transmit(&EthHandle, &TxConfig, 0);
5、修改信号量收发API
原来的API都是基于FREERTOS的,修改为RT-Thread
如:
1 if (osSemaphoreWait( RxPktSemaphore, TIME_WAITING_FOR_INPUT)==osOK)
修改为:
1 if(rt_sem_take(ð_rxin, RT_WAITING_FOREVER) == RT_EOK)
6、把开发板和电脑连接起来
能看到开发板和电脑的已经通讯了。至此移植全部完成。
四、我移植过程中遇到的问题
1、发送函数增加SCB_CleanInvalidateDCache();
这个和cache策略配置有关,这个CACHE还需要多少研究。不加这一句会导致发送失败。
2、PHY硬复位
如果不复位可能导致ETH
配置失败。
3、lwipopts.h
修改
这里使用LWIP的动态内存,所以要把这个宏定义为1。
1#define MEMP_MEM_MALLOC 1
4、LWIP的RAM设置
这里的设置一定要是
1#define LWIP_RAM_HEAP_POINTER (0x30044000)
5、设置pbuf_size
1#define PBUF_POOL_BUFSIZE 1536
6、注意2个宏定义
1#define ETH_RX_BUFFER_SIZE (1536UL)
2#define ETH_MAX_PACKET_SIZE ((uint32_t)1528)
这两个宏定义只能使用其中一个,因为大小不一样,会导致内存出现问题。
五、我参考GITHUB上的代码中存在的问题
1、发送函数没有增加SCB_CleanInvalidateDCache()
;
2、在配置PHY之前没有给一个硬复位;
3、LWIP提供了3中内存分配机制,但是全部定义为0,既都没使用;
4、pbuf_size
通过宏定义来实现,我直接手动到设置为1536
;
六、参考链接
1、言简意赅的介绍M7内核的Cache工作流程,摸爬滚打半年的经验总结
http://forum.armfly.com/forum.php?mod=viewthread&tid=90066&highlight=%C3%FE%C5%C0%B9%F6%B4%F2
2、stm32h7_freertos
https://github.com/suoZhangEmbedded/stm32h7_freertos
3、终于搞定STM32H743网络了,分享调试经验及注意事项
http://www.stmcu.org.cn/module/forum/thread-615089-1-3.html