[应用相关]

TI Cortex M3串口转以太网例程分析3-----lwIP1.3.2移植

[复制链接]
645|3
手机看帖
扫描二维码
随时随地手机跟帖
renzheshengui|  楼主 | 2018-9-15 21:52 | 显示全部楼层 |阅读模式
原文网址:https://blog.csdn.net/zhzht19861011/article/details/6742016

TI Cortex M3串口转以太网例程上层应用的基础是lwIP,版本是V1.3.2 。对于lwIP,陌生的同学可以到网上查查,它是是瑞士的Adam编写的一个开源TCP/IP协议。既然串口转以太网例程的基础是lwIP,那么还是看看lwIp是如何移植到TI的Cortex M3硬件中的吧。此为分割线-------

         移植概述可以参看博客的这篇**,以下基本按照这个格式来看看具体的移植代码。http://blog.csdn.net/zhzht19861011/article/details/6615965

1.cc.h文件

         这个文件主要设置lwIP内部使用的数据类型,比如u8_t、u32_t等。lwIP可以移植到32位、16位甚至是8位构架的微控制器,由于移植的硬件平台以及编译器的不同,这些数据类型是要移植者根据自己的硬件和编译器特性来自行设置的。比如int类型变量,在8位和16位控制器中多表示2字节,但在32位微处理器中却表示4个字节,若是连这些基本数据类型都没有设置正确的话,就谈不上移植了。下面看cc.h的源代码:




  • #ifndef __CC_H__



  • #define __CC_H__







  • typedef unsigned    char    u8_t;     //基本数据类型设置



  • typedef signed      char    s8_t;



  • typedef unsigned    short   u16_t;



  • typedef signed      short   s16_t;



  • typedef unsigned    long    u32_t;



  • typedef signed      long    s32_t;



  • typedef u32_t               mem_ptr_t;







  • #ifndef BYTE_ORDER



  • #define BYTE_ORDER LITTLE_ENDIAN



  • #endif







  • #if defined(__arm__) && defined(__ARMCC_VERSION)         //以下主要设置不同编译器的结构体数据的对齐,lwIP需要



  •     //



  •     // Setup PACKing macros for KEIL/RVMDK Tools



  •     //



  •     #define PACK_STRUCT_BEGIN __packed



  •     #define PACK_STRUCT_STRUCT



  •     #define PACK_STRUCT_END



  •     #define PACK_STRUCT_FIELD(x) x



  • #elif defined (__IAR_SYSTEMS_ICC__)



  •     //



  •     // Setup PACKing macros for IAR Tools



  •     //



  •     #define PACK_STRUCT_BEGIN



  •     #define PACK_STRUCT_STRUCT



  •     #define PACK_STRUCT_END



  •     #define PACK_STRUCT_FIELD(x) x



  •     #define PACK_STRUCT_USE_INCLUDES



  • #else



  •     //



  •     // Setup PACKing macros for GCC Tools



  •     //



  •     #define PACK_STRUCT_BEGIN



  •     #define PACK_STRUCT_STRUCT __attribute__ ((__packed__))



  •     #define PACK_STRUCT_END



  •     #define PACK_STRUCT_FIELD(x) x



  • #endif







  • #ifdef DEBUG



  • extern void __error__(char *pcFilename, unsigned long ulLine);



  • #define LWIP_PLATFORM_ASSERT(expr)      \



  • {                                       \



  •     if(!(expr))                         \



  •     {                                   \



  •         __error__(__FILE__, __LINE__);  \



  •     }                                   \



  • }



  • #else



  • #define LWIP_PLATFORM_ASSERT(expr)



  • #endif







  • #endif /* __CC_H__ */



renzheshengui|  楼主 | 2018-9-15 21:53 | 显示全部楼层
2.2 Stellaris以太网硬件底层数据发送函数
        上面也已经讲到了,ARP模块发送数据到网络接口会调用netif->linkoutput函数;IP层发送数据到网络接口会调用netif->output函数,但IP层实际的数据发送函数任然是netif->linkoutput,在以太网初始化中,已经为linkoutput指针赋值:netif->linkoutput=stellarisif_output;因此,移植lwIP时程序员需要编写的Stellaris以太网硬件底层数据发送函数正是stellarisif_output()函数。先来看以下它的源码:



  • /**



  • * This function with either place the packet into the Stellaris transmit fifo,



  • * or will place the packet in the interface PBUF Queue for subsequent



  • * transmission when the transmitter becomes idle.



  • * 这个函数要么将数据包放到Stellaris发送缓存FIFO中,要么把数据包放到PBUF队列,等待



  • * 发送器变空之后载发送。



  • *



  • * @param netif the lwip network interface structure for this ethernetif



  • * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)



  • * @return ERR_OK if the packet could be sent



  • *         an err_t value if the packet couldn't be sent



  • *



  • */



  • static err_t



  • stellarisif_output(struct netif *netif, struct pbuf *p)



  • {



  •   struct stellarisif *stellarisif = netif->state;



  •   SYS_ARCH_DECL_PROTECT(lev);







  •   /**



  •    * This entire function must run within a "critical section" to preserve



  •    * the integrity of the transmit pbuf queue.



  •    *



  •    */



  •   SYS_ARCH_PROTECT(lev);







  •   /**



  •    * Bump the reference count on the pbuf to prevent it from being



  •    * freed till we are done with it.



  •    *



  •    */



  •   pbuf_ref(p);







  •   /**



  •    * If the transmitter is idle, and there is nothing on the queue,



  •    * send the pbuf now.



  •    *



  •    */



  •   if(PBUF_QUEUE_EMPTY(&stellarisif->txq) &&



  •     ((HWREG(ETH_BASE + MAC_O_TR) & MAC_TR_NEWTX) == 0)) {



  •     stellarisif_transmit(netif, p);



  •   }







  •   /* Otherwise place the pbuf on the transmit queue. */



  •   else {



  •     /* Add to transmit packet queue */



  •     if(!enqueue_packet(p, &(stellarisif->txq))) {



  •       /* if no room on the queue, free the pbuf reference and return error. */



  •       pbuf_free(p);



  •       SYS_ARCH_UNPROTECT(lev);



  •       return (ERR_MEM);



  •     }



  •   }







  •   /* Return to prior interrupt state and return. */



  •   SYS_ARCH_UNPROTECT(lev);



  •   return ERR_OK;



  • }



1. SYS_ARCH_DECL_PROTECT(lev);、SYS_ARCH_PROTECT(lev);、SYS_ARCH_UNPROTECT(lev);由于Stellaris以太网在发送数据的时候必须处在临界区,既不能被中断打扰,因此,上面几个宏是用来关闭和打开总中断的。SYS_ARCH_DECL_PROTECT(lev)用来定义一个32位变量lev,这个变量用来保存当前中断使能信息;SYS_ARCH_PROTECT(lev)用来关闭中断;SYS_ARCH_UNPROTECT(lev)用来打开中断。

2. pbuf_ref(p);将参数结构体pbuf的ref域加一。这个域统计有多少个指针指向这个pbuf,这些指针可能是应用程序的指针、协议栈的指针或者数据链中的pbuf->next指针,只有ref为0时,才可以释放这个pbuf。关于结构体pbuf的详细介绍参见博客:http://blog.csdn.net/zhzht19861011/article/details/6591252

3. stellarisif_transmit(netif, p):发送数据。


使用特权

评论回复
renzheshengui|  楼主 | 2018-9-15 21:53 | 显示全部楼层

2.3  Stellaris以太网硬件底层数据过程
当网络上一包数据到达以太网控制器后,以太网控制器会置为接收中断,在中断服务函数中,调用

stellarisif_receive函数(需程序员根据具体硬件自行编写)来接收一个数据包,再通过

ethernet_input函数分析接收到的数据包的类型,比如类型为0x8000,则为IP帧,会调用ip_input

函数来将收到的这个IP数据包送往lwIP协议栈的高层。Stellaris以太网硬件具体中断函数分析见博客

:http://blog.csdn.net/zhzht19861011/article/details/6221699


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

3808

帖子

2

粉丝