【F769IDISCOVERY评测】UCSOIII+LwIP 移植
前段时间论坛搞网络的培训移植过LwIP到STM32F769-DISCO,当时的移植并没有添加RTOS,在ST的开发包里面有几个lwip + freertos 的例子,下面分享一个LwIP+UCOSIII 移植的例子,需要的同学可以测试下。1、硬件初始化的部分
和不带RTOS 相比较,添加了RTOS之后,LAN8742A的接收模式从之前的轮询模式修改为中断接收模式。
<font face="微软雅黑" size="3">EthHandle.Instance = ETH;
EthHandle.Init.MACAddr = macaddress;
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
EthHandle.Init.Speed = ETH_SPEED_100M;
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; //中断接收模式
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS;
/* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
if(HAL_ETH_Init(&EthHandle) == HAL_OK)
{
/* Set netif link flag */
netif->flags |= NETIF_FLAG_LINK_UP;
}</font>
相应的网卡的接收数据也使用一个任务来处理,在这个任务里面我们pend一个任务信号量来处理接收的数据,
<font face="微软雅黑" size="3">void ethernetif_input(void* p_arg)
{
OS_ERR err;
struct pbuf *p;
struct netif *netif = (struct netif *) p_arg;
for(;;)
{
OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err);
do
{
p = low_level_input(netif);
if(p != NULL)
{
if(netif->input(p, netif) != ERR_OK)
{
pbuf_free(p);
}
}
}
while(p != NULL);
}
}</font>然后在网卡接收中断中post这个任务信号量,这样能高效实时的处理接收的网络数据,这也是RTOS的优势所在。
<font face="微软雅黑" size="3">void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
OS_ERR err;
OSTaskSemPost(ÐRXTASKTCB,OS_OPT_POST_NONE,&err);
}</font>2、软件的移植
带RTOS 的LWIP 使用的时候要移植一个sys_arch.c 文件中几个函数,这个主要是用于lwip 的信号量转化为ucosiii的信号量。还有一个是用于创建lwip的主线程使用,这里调用的sys_thread_new需要在sys_arch.c中实现。
<font face="微软雅黑" size="3">/**
* @ingroup lwip_os
* Initialize this module:
* - initialize all sub modules
* - start the tcpip_thread
*
* @param initfunc a function to call when tcpip_thread is running and finished initializing
* @param arg argument to pass to initfunc
*/
void
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
{
lwip_init();
tcpip_init_done = initfunc;
tcpip_init_done_arg = arg;
if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
}
#if LWIP_TCPIP_CORE_LOCKING
if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
}
#endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
}</font>
总的来说也就是必须创建2个任务 一个网卡的接收任务,一个是lwip内核的处理任务。
3、添加几个测试任务
为了测试移植的效果我添加4个通信任务:
1) TCP任务:电脑作为服务器,开发板作为客户端。开发板连上服务器后主动循环发送测试数据。
2)UDP任务: 开发板连上电脑后,将电脑通过UDP发送给开发板的数据原封不动的返回给电脑。
3)开发板高速虚拟串口:连上电脑后主动发送数据数据到电脑
4)stlink虚拟串口:将开发板的串口通过stlink发送数据给电脑
几个任务代码:
<font face="微软雅黑" size="3">//USB_VCP
OSTaskCreate((OS_TCB * )&USBVCPTASKTCB,
(CPU_CHAR * )"USB_VCP_task",
(OS_TASK_PTR )USB_VCP_Test,
(void * )0,
(OS_PRIO )USB_VCP_TASK_PRIO,
(CPU_STK * )&USB_VCP_TASK_STK,
(CPU_STK_SIZE)USB_VCP_STK_SIZE/10,
(CPU_STK_SIZE)USB_VCP_STK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
//eth_rx
OSTaskCreate((OS_TCB * )ÐRXTASKTCB,
(CPU_CHAR * )"ETH_RX_task",
(OS_TASK_PTR )ethernetif_input,
(void * )&gnetif,
(OS_PRIO )ETH_RX_TASK_PRIO,
(CPU_STK * )Ð_RX_TASK_STK,
(CPU_STK_SIZE)ETH_RX_STK_SIZE/10,
(CPU_STK_SIZE)ETH_RX_STK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
tcpip_init(NULL, NULL);
OSTaskCreate((OS_TCB * )&TCPCLIENTTASKTCB,
(CPU_CHAR * )"tcp_client_task",
(OS_TASK_PTR )tcp_client_thread,
(void * )0,
(OS_PRIO )TCP_CLIENT_TASK_PRIO,
(CPU_STK * )&TCP_CLIENT_TASK_STK,
(CPU_STK_SIZE)TCP_CLIENT_STK_SIZE/10,
(CPU_STK_SIZE)TCP_CLIENT_STK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
//´
OSTaskCreate((OS_TCB * )&UDPSERVERASKTCB,
(CPU_CHAR * )"udp_server_task",
(OS_TASK_PTR )udp_server_thread,
(void * )0,
(OS_PRIO )UDP_SERVER_TASK_PRIO,
(CPU_STK * )&UDP_SERVER_TASK_STK,
(CPU_STK_SIZE)UDP_SERVER_STK_SIZE/10,
(CPU_STK_SIZE)UDP_SERVER_STK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);</font>运行是下面的这样子:
4个通信任务动态运行如下:
关于UCOSIII的移植和LwIP的详细使用可以参考之前的帖子。测试代码非常简陋,不合理的地方在所难免,实际使用时请完善。
测试代码:
推荐阅读:
【F769IDISCOVERY评测】LwIP Echo 及数据传输测试
【F769IDISCOVERY评测】LwIP之以太网固件升级
【NUCLEO-L496ZG评测】+ UCOSIII:内存管理和消息队列
【NUCLEO-L496ZG评测】+ UCOSIII:软件定时器和信号量
【NUCLEO-L496ZG评测】+ UCOSIII简单移植
【NUCLEO-L496ZG评测】+ UCOSIII:事件标志组
:loveliness:学习了。。。。顶起 学习了。。。。顶起 谢谢支持,加到汇总贴了https://www.stmcu.org.cn/module/forum/thread-609491-1-1.html zero99 发表于 2017-8-21 08:51
谢谢支持,加到汇总贴了https://www.stmcu.org.cn/module/forum/thread-609491-1-1.html
:handshake 大神的帖子含精量妥妥的 谢谢分享 风子 发表于 2017-8-21 09:44
大神的帖子含精量妥妥的
难得冒个泡啊 好贴,赞一个 谢谢分享!!
页:
[1]