FreeRTOS+LWIP(3)

2019-08-20 19:34

2、将源码包FreeRTOS\\Source下的include文件复制到KEIL的工程目录下,再此之前要将portmacro.hFreeRTOSConfig.h复制到该文件(include)下。 portmacro.h在FreeRTOS\\Source\\portable\\RVDS\\ARM_CM3下

FreeRTOSConfig.h在FreeRTOSV7.2.0\\FreeRTOS\\Demo\\CORTEX_STM32F103_Keil下 FreeRTOSConfig.h是一个STM32对应的DEMO已经配置好了,如需修改请参照《配置FreeRTOS》,《配置FreeRTOS》详细的说明了FreeRTOSConfig.h里每个宏定义的意义,根据自己需要进行配置。

找到Project->options for target->C/C++->Include Paths

将头文件文件include包含到工程里面去。

3、修改启动文件startup_stm32f10x_hd.s(32内核中)

在050行在__heap_limit 下面添加: PRESERVE8 THUMB

IMPORT xPortPendSVHandler IMPORT xPortSysTickHandler IMPORT vPortSVCHandler

跳到 076 行 DCD SVC_Handler 改成 DCD vPortSVCHandler 跳到079行 DCD PendSV_Handler成 DCD xPortPendSVHandler 跳到080行

DCD SysTick_Handler 成 DCD xPortSysTickHandler

4、在main.c的头部里#include一下头文件:FreeRTOS.h task.h queue.h 这样就移植完毕了。移植过程参考《在STM32中移植FreeRTOS》文档。

7 LWIP的移植

LWIP是TCP/IP协议栈的一个开放源代码实现,它由瑞士计算机科学院的Adam Dunkels等开发,目的是减少内存使用率和代码空间大小,因此LWIP适用于运行在资源受限的嵌入式系统环境中。LWIP可以在几百字节或几十KB的RAM空间运行。LWIP既可以移植到操作系统上运行,也可以在无操作系统下独立运行。 LWIP具有如下特性:

LWIP在STM32上的底层驱动的移植

LWIP在STM32上的底层驱动的移植主要包括两方面:一、修改文件ethernetif.c,该文件

是连接LWIP协议栈和STM32网络驱动程序的桥梁,LWIP协议栈为开发者提供了ethernetif.c的程序模板;二、编写STM32的网络驱动程序,实现网络底层的初始化、收发报文功能。

1、 ethernetif.c文件的移植

ethernetif.c是LWIP协议栈和STM32网络驱动程序之间的接口,它主要包含ethernetif_init、ethernetif_input、low_level_init、low_level_input、low_level_output等函数。

1.1 ethernetif_init函数

该函数是LWIP底层网络接口的初始化函数,指定了网络接口netif对应的主机名及网卡的描述,并指定了网卡的mac地址。同时,该函数还指定了netif的发送数据报文函数,并调用了网络底层驱动初始化函数low_level_init对网络底层进行初始化。(要根据自己选用的网卡调用网卡驱动)

1.2 low_level_init函数

这个函数是网卡的初始化函数。虽然该函数代码量不大,但是它完成的工作量却不少。代码如下:

low_level_init(struct netif *netif) {

// struct ethernetif *ethernetif = netif->state; /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ netif->hwaddr[0] = mymac[0]; netif->hwaddr[1] = mymac[1]; netif->hwaddr[2] = mymac[2]; netif->hwaddr[3] = mymac[3]; netif->hwaddr[4] = mymac[4]; netif->hwaddr[5] = mymac[5]; /* maximum transfer unit */ netif->mtu = MAX_FRAMELEN;

if(ENC28J60_Init((u8*)mymac)) //初始化ENC28J60 {

return ERR_IF; //底层网络接口错误 }

//指示灯状态:0x476 is PHLCON LEDA(绿)=links status, LEDB(红)=receive/transmit //PHLCON:PHY 模块LED 控制寄存器 ENC28J60_PHY_Write(PHLCON,0x0476); /* device capabilities */

/* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */

netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; return ERR_OK;

/* Do whatever else is needed to initialize interface. */ }

Low_level_init函数设定了网卡的物理地址和每帧最大传输数据字节数。

1.3 ethernetif_input函数

该函数用于从底层物理网卡读取报文,并将该报文向上传递给LWIP协议栈函数ethernet_input进行处理。源代码如下:

void ethernetif_input(struct netif *netif) {

// struct ethernetif *ethernetif; struct eth_hdr *ethhdr; struct pbuf *p;

// ethernetif = netif->state;

/* move received packet into a new pbuf */ p = low_level_input(netif);

/* no packet could be read, silently ignore this */ if (p == NULL) return;

/* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload;

switch (htons(ethhdr->type)) { /* IP or ARP packet? */ case ETHTYPE_IP: case ETHTYPE_ARP: #if PPPOE_SUPPORT /* PPPoE packet? */ case ETHTYPE_PPPOEDISC: case ETHTYPE_PPPOE:

#endif /* PPPOE_SUPPORT */

/* full packet send to tcpip_thread to process */ if (netif->input(p, netif)!=ERR_OK)

{ LWIP_DEBUGF(NETIF_DEBUG, (\ pbuf_free(p); p = NULL; } break; default:

pbuf_free(p); p = NULL; break; }

}

1.4 low_level_input函数

该函数用于从内存中申请一个新的pbuf,并把接收到的数据报文内容拷贝至该pbuf中。源代码如下:

static struct pbuf *

low_level_input(struct netif *netif) {

// struct ethernetif *ethernetif = netif->state; struct pbuf *p, *q; u16_t len; int rev_len=0;

/* Obtain the size of the packet and put it into the \variable. */

len = ENC28J60_Packet_Receive(MAX_FRAMELEN,lwip_buf); #if ETH_PAD_SIZE

len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ #endif

/* We allocate a pbuf chain of pbufs from the pool. */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != NULL) { #if ETH_PAD_SIZE

pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif

/* We iterate over the pbuf chain until we have read the entire * packet into the pbuf. */ for(q = p; q != NULL; q = q->next) {

/* Read enough bytes to fill this pbuf in the chain. The * available data in the pbuf is given by the q->len * variable.

* This does not necessarily have to be a memcpy, you can also preallocate * pbufs for a DMA-enabled MAC and after receiving truncate it to the * actually received size. In this case, ensure the tot_len member of the * pbuf is the sum of the chained pbuf len members. */

//read data into(q->payload, q->len); memcpy((u8_t*)q->payload, (u8_t*)&lwip_buf[rev_len],q->len); rev_len +=q->len; }

// acknowledge that packet has been read();

#if ETH_PAD_SIZE


FreeRTOS+LWIP(3).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:中国公务员制度第2阶段测试题

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: