一般采用的步骤:
1.深入了解所采用的系统核心
2.分析所采用的C语言开发工具的特点.
3.编写移植代码.
4.进行移植的测试
5.针对项目的开发平台,封装服务函数.
首先,是芯片的中断处理机制,如何开启,屏蔽中断,可否保存前一次中断状态,芯片是否有软中断或陷阱指令
已经将图片移植成功,是一件很快乐的事情.
现在要将网络也加进去,看一看,想什么办法能够办到.
将lwip组织起来:
lwipopts.h
cc.h
timer.h
Timer0_Init(void)
Timer1_Init(void)
Delay10ms(unsigned short T) ;
Undefine_Init(void) ;
volatile 跟const 相反,可能在外界的影响下改变.编译器不再对其进行优化.
关于时钟中断,可有对应的例子,没有什么关系,如果想把这两个合并在一起不太可能,
因为硬件不同罢了.
Timer0
Timer1 所有的都为了ucos-ii //time tick时钟激发.
SYSTEM CLOCK CONTROL ;
Main.c只是测试一个移植了,只能在串行口里输出测试结果,但并不能表示它已经完成了,对lwip移植任务.
/******************************************************************************/
/--------------------------------/
/最后发现这只是一个应用程序嘛:
/还没有到初始化硬件的地步吧.
/--------------------------------/
lwip_Main.c 其中只有一个函数,这个函数就可以完成你所要的lwip?
看看这个lwip_Main做了那些事情:
1.定义ip结构体 struct ip_addr,netmask ,gw ;
2.定义信号量:sys_sem_t sem ;
3. 初始化一些东西.
初始化 TCP/IP 之前为何还需要实始化系统?
IP4_ADDR(&gw,0,0,0,0) ;
IP4_ADDR(&ipaddr,0,0,0,0) ;
IP4_ADDR(&netmask,0,0,0,0) ;
netif = netif_add(&ipaddr,&netmask,&gw,ethernetif_init,tcpip_input) ;
netif_set_default(netit) ;
dhcp_start(netif) ;
或者形如如此的形式,其的IP地址可以设定的.
udpecho_init() ;
但是这里跟本就没有任务,
是否要把此lwip添加到任务里去?
this is for web page ;in httpd file
httpd.h:
httpd_init() ;
httpd_thread() ;
这里的函数很简洁,但是何时使用httpd_init(void) ;
到现在还没有发现,有那些东西需要做的,
没有步骤
App:应用程序没有必要在这里看,
因为其中一些东西,跟本就不必要的
而需要理解其中的实质,怎么把lwip移植成功?
另外可以借助原先一个例子,可以比较读取,看是否已经到了熟习,或者可以用上派场上.
如果说lwip里没有牵涉到硬件问题,那么我们可以把它当一个库来看待
现在要怎么去使用它的函数,
另一方面,怎么样来初始化其对应的网络接口:8019
问题关键不再放在这个上面,应该更有意义的是看LPC2284.h里是怎么去实现的,
然后我们再把它的实现过程移植s3c2440上去,可以看到结果的时候,就是照搬就快成功了.
而在lwip文件夹下的所有文件已经实现了
这里的代码一定是很比较稳定的,已经实现得比较好的.现在是实现它看看怎么样让调用起它来.
**************************************
如果目标板的初始化,
一:在main里可能就只用到那一个函数:
TargetInit() ---在图片例子里也已经完成了.不是必须的.
二:RTL8019
这个是网卡驱动:
要知道网卡的指针是怎么回事:
网卡的地址:
timer0_init()初始是什么事情?
现在关键问题在:s3c2440代替LPC2294
可不可以把这个封装更简单一些,以便使用更方便?
搞清里面的差别,另外看看,为什么要在LPC2294要用到Timer
原来有网卡驱动需要:
处理计时器:
timeout()函数按受两个参数:
第一指向变量的指针,存储了开始时间,
第二:保存了以秒计数的超时时间.当超过超时间时,该项函数触发一个事件,
开始时间中重新写入当前时间并返
并返回一个非0值.
------------------------------------
应该封闭起lwip,它已经跟其它任何初始硬件无,
只要保证调用它的函数能够起作用,正确使用它即可.
没有必要去读它里的任何一个文件,因为它是协议.
如果不对硬件初始化,那是不可能调用到lwip里的函数的.
注意:
1.可能要使用lwIP时,会做成一个任务,
还要给它分配优先级.Task.h
2.Target.c里去初始化网卡. 找出config.h,因为Target.c里只引用了它.但是好像在config.h里并不怎么实现它.
3.虽然Timer很重要,但是我想没有必要把它也拿出来细究,因为不涉及到lwip
4.
没有看到有那个函数调用汉字打点函数,
为何当你调用Lcd_printf()时也可以出现汉字?
Uart_SendString(pUartMsg) ;
lcd.c:一个向lcd里发送,
printf.c一个向串行端口发送.
Nand.c没有被使用到.
最好想法把所有无关的都剥离出来,然后把相关的分成块.
可以像其它一样:
1.初始化 :像 lcd,printf-Uart,[xxx_init()]
2.将那些相应的函数放到任务里.不停执行.
3.将在单独文件里实现函数.
4.函数里去调用lwip协议函数.
-----------------------------------------------------
分作两部分了.一部分是RTL8019,另一部分:lwip
-----------------------------------------------------
5.RTL8019对网卡的实现函数.
6.lwip实现栈,调用其中的函数实现--栈.
------------------------------------
dm9000已经在RTL8019实现,UBOOT已经有对dm9000实现,可以包装一下,
rtl8019_netif
最好就与主板上分离开,
只要网卡对应地址是
权衡那一种更容易达到效果:
rtl8019一般不是在ARM上,没有办法知道其驱动,
而dm9000是驱动,却又没有与lwip建立关系.
包装dm9000一下,
lwip需要的网络接口,初始化接口:
ethernetif_init()
low_level_output()
ethernetif_input()
ethernetif_init()负责网络的接口初始化.底层收发包函数,MAC地址和硬件初始化等.
low_level_output()负责将上层传来的网络包通过DM9000发送出去.
重新包装DM9000驱动
在UBoot 里有DM9000驱动即可用到.
需要以下几个函数:
int dm9000_eth_init(struct netif*db) ;
void dm9000_eth_send(volatile void *,int) ;
int dm9000_eth_send_done(int) ;
int dm9000_eth_rxlen(void);
int dm9000_eth_rx(U8*rdptr,U16 RxLen) ;
int dm9000_drop_frame(U16 RxLen) ;
其中,只有发送和接收两个函数需要改动,
LWIP上层传给low_level_output()的数据包,
将根据MSS和MTU等值切割成一个个的小包,分别填充到链表pbuf里。
**************************************
struct netif{
struct netif *next ;
struct ip_addr ip_addr ;
struct ip_addr netmask ;
struct ip_addr gw ;
err_t(*input)(struct pbuf *p , struct netif *inp) ;
err_t(*output)struct netif*netif,struct pbuf *p,struct ip_addr *ipaddr) ;
err_t(*linkoutput)(struct netif*netif,struct pbuf *p) ;
#if LWIP_DHCP
struct dhcp *dhcp;
#endif
/** number of bytes used in hwaddr */
unsigned char hwaddr_len;
/** link level hardware address of this interface */
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
/** maximum transfer unit (in bytes) */
U16 mtu;
/** flags (see NETIF_FLAG_ above) */
U8 flags;
/** link type */
U8 link_type;
/** descriptive abbreviation */
char name[2];
/** number of this interface */
U8 num;
};
//alt_lwip_dev结构体描述了符合LWIP规范的网络端口设备
struct alt_lwip_dev
{
/* The netif pointer MUST be the first element in the structure */
struct netif* netif;
const char* name;
err_t (*init_routine)(struct netif*); //初始化函数
void (*rx_routine)(); //数据接收函数
};
//alt_lwip_dev_list:设备链表
typedef struct
{
alt_llist llist; /* for internal use */
alt_lwip_dev dev;
}alt_lwip_dev_list;
typedef struct alt_llist_s alt_llist;
struct alt_llist_s {
alt_llist* next; /* Pointer to the next element in the list. */
alt_llist* previous; /* Pointer to the previous element in the list. */
};
//在LWIP定义的这些结构体类型的基础上,DE2_WEB_SERVER定义了针对DM9000网络接口的一个结构体
typedef struct
{
alt_lwip_dev_list lwip_dev_list; //与之关联的设备链表
int base_addr; //寄存器的基地址
int irq; //中断编号
u_char hwaddr[6]; //MAC地址
int index_offset;
int data_offset;
int dm9k_tx_space;
int dm9k_linked;
sys_sem_t arp_semaphore;
sys_sem_t tx_semaphore;
} alt_avalon_dm9k_if;
先让驱动起来,移植s3c2440加到其它程序一起.
焦海波那个有可能考虑.因为那一些写的比较完整,但总是低估了它的难度.
果然,焦已经形成文档了
下载下来看看,或许有解的机会.
移植被LwIP到一个新的目标系统时,只需要修改这个接口艰险可,那个接口? sys_arch
操作系统模拟层(sys_arch) 它在底层操作系统和LwIP之间提供了一个接口?
sys_arch需要为LwIP提供信号量(sem)和邮箱(mailboxes)
信号量是可以计数信号量,也可以二值信号量,---LwIP都可以正常工作,
邮箱用于消息传递.
int sys_init()
sys_sem_t sys_sem_new() ;
sys_sem_freem() ;
sys_sem_signal()
sys_arch_sem_wait() ;
sys_mbox_t sys_mbox_new() ;
sys_mbox_free(sys_mbox_t mbox) ;
void sys_mbox_post(sys_mbox_t mbox,void *msg)
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox,void **msg,u32_t timeout)
struct sys_timeouts *sys_arch_timeouts(void)
如果底层操作系统支持多线程并且LwIP中需要这样的功能,则一定要实现这个函数.
sys_thread_t sys_thread_new(void(*thread)(void*arg),void *arg,int prio) ;
sys_prot_t sys_arch_protect(void)
void sys_arch_unprotect(sys_prot_t pval) ;
以上是Lwip与操作系统关系.
----------------------------------------------------------------------------
OS支持的模拟层需要添加的头文件:
cc.h 与硬件平台以及编译器相关的环境变量及数据类型声明文件.或者一些移到sys_arch.h中.
与编译器相关的LwIP结构体
PACK_STRUCT_FILED(x)
PACK_STRUCT_STRUCT
PACK_STRUCT_BEGIN
PACK_STRUCT_END
与平台相关
LWIP_PLATFORM_DIAG(X)
memset() 如果编译器不提供,这个文件一定要包含它的定义,即memset()
perf.h
sys_arch.h sys_arch.c的头文件
整个移植所依赖的操作系统平台.
OK 文件夹和文件指定的路建立后,
先去定数据类型定义.
cc.h:
typedef unsigned char u8_t
typedef signed char s8_t
typedef unsigned short u16_t ;
.......
允许它们定义,没关系,跟系统内其它的定义不相冲突,如果全部换成一致也不见得好使用.
因为分为不同的分块移植的.
信号量操作函数
邮箱操作函数:
特别注意:投递到邮箱中的消息只能是一个指针.
一:邮箱一次能够接收多条消息比仅接收一条消息更加有效.
二:邮箱中的消息是一个指针.
__ilvSetLwIP()
实现网络驱动与LwIP的接口,是网络系统得以顺利运转的源动力,它会告诉LwIP网络数据的发送出口,建立网络数据的接收入口并实现
接收入口与LwIP处理入口的对接.
当底层网络收发设备进入正常工作状态,网络数据能够正常流入流出LwIP后,这个函数进行的工作会结束.
我需要一款纯的Lwip源代码,可能都是别人移植了后,影响到我的思路.
下载一个原版的后,不用再去查看别人移植的,现在的工作是怎样先把这个lwip先移植到uCos-ii里去,
暂时还不让它跑起来,按照常规的想法是把其思路先移植上去再说.看看有什么效果.再实现驱动.
采用一个干净的lwip源码是很有用处的.
一:可以就此完全不用顾及别人的移植思路,
二:自己移植出错容易找出来,
三:用时会快一些.
实际上这些都是在这里操作.
LwIPEntry.c这个文件也像LwIP_main.c文件一样.是重中之重.
没有把硬件东西提取来,有点过失,
如果再把其中的东西提取来,就有点更直接的效果.
ethernetif_init()初始化底层接口:
Lwip作者已经帮我们完成大部分工作,我们只要把框架内完成与底层硬件相关的部分即可.
ethernetif 是一个结构体:用来描述网络硬件设备(通常说的网卡)
它唯一不可缺少的是网卡的MAC地址.
ethernetif->ethaddr ====指针指向netif中保存的网卡MAC地址.
low_level_output()
与硬件联系的函数,
指定任务优先级,最好定为最高优先级,如果确定存在更高优先级,一定要让更高优先级任务占用CPU使用权时间不能太长,
否则将严重影响网络性能.
ethernetif.c是硬件的抽象层.
实现了它,不一定可以,还需要硬件驱动.
lib_emac.c专门用来建立驱动函数:
硬件驱动:它不仅包括EMACInit()
EMACReadPacket() EMACSendPacket() 分别负责网络数据包的接收和发送.
这个已经在处理硬件了.
怎样使用硬件工人和顺利就得有这么一种慢慢使用的过程了.
所以网卡的实现也只有三个函数吗?
EMACInit()
EMACReadPacket()
EMACSendPacket()
怎样把问题简化:
1.lwip
2.dm9000
3.lwip->ucosii 这个可以暂时搞定: ---------------------返正先把这个搞定再说.-------------------
4.lwip->dm9000
lwip->dm9000详细问题,要解决几个问题:
1.EMAC发送和接收中断处理函数 --dm9000看看中断处理函数.
2.EMACSendPacket 发送
找来找去没有发现什么新的东西可以模仿,不如自己写一个.
首先把LwIP移植之后再说,其它的就不必太在意.
先把一步做完,
然后再考虑网络驱动的问题.
文件结构也很重要,不然可能有一些会搞混乱.
在此中间,焦海波采用了链表来构建邮箱,
而我将采用另一种方式:队列,让队列给uCOS-II去处理更好一些.
这样把LwIP实现了后,再就是硬件网卡驱动.
首先添加LwIPEntry.c文件,
看来我在dm9000 花费了太多心血,倒头来还只是一个linux版的,而且一点进展都没有,
怎么办?
我想把它搞掉.
算是移植完成了,但是没有调试,因为可能还有许多错误,要清除这些错误,得一段时间.
怎么把平台里的网络相关函数抽象出来?
直接用到一些函数,可以用来发送Ping Webpage 之类,看看,可不可以脱离硬件函数.
怎么办,ADS不可以直接加工程.
是否需要有更多了解.
我是怎么样把我所做的添加上去呢?
难道像昨晚那样一个一个添加?
其实文件夹跟本就不存于mcp工程里.
编译已经成功,但是一些应该使用的功能可能还没有达到你的要求,
现在的工作是怎样把相应的功能加进去,即是怎样把Lwip 栈协议加进去,
实现通信.
出现的另外一个问题,为何在外部的驱动,没法在lwip里调用,是否是因把dw9000加到了外面?
现在的问题只是:驱动出现了问题,如果把驱动处理好
可能一切都好办了.
但驱动如何才能添加上去.
因为其它的驱动看似很容易得到,但是不符乎我的芯片上的意思,
我决问自己写dm9000的驱动.
有文档,也有别人的例子,应该比较容易一些.
编写驱动程序:
注意处理器所用的C编译器使用"大端格式","小端格式"
只有两个可以直接被除数处理器访问的寄存器,
CMD 端口和DATA端口,
(DM9000中有许多控制和状态寄存器) 访问这些控制,状态寄存器的方法:
1.将寄存器的地址写到CMD端口
2.从DATA端口读写寄存器中的数据.
1-3
新建一个试一试:
全部用新的就可以了,自己新建一个即立成功.没有什么完成不了,
可能还是因为宏的问题,
所以从dm9000x.h里把不必要的东西都裁减掉.
高位片选地址:
DM9000地址端口= 高位片选地址+300H+0H
DM9000数据端口= 高位片选地址+300H+4H
DM9000的高位片选地址将是多少?
0x90000A46
现在已经编译通过,
基本的修改已经完成,怎么让OS启动
虽然已经移植完成了,但没有调试,没有看出来是否已经成功还没有定论
肯定还会有问题:
1.驱动dm9000虽然完成了,但没有测试,是否完备
2.LwIP栈协议还不一定移植成功,因为申请的空间还不明确.
3.添加的应用程序可能存在一定的问题,如果没有其它问题,应用程序都可以顺利执行.
4.是否还需要添加httpd.c文件,让其当服务,用来访问,如果可以,则应该一试,以防备其它的不成功,采取这个可以能过,
5.也算是网络通顺的一个实例.(但是有一个问题即是,这个是里面是否)
移植的方式很多,但要想成,得有一个章程.
如下是linux里的移植过程:
sys_arch.c里有另一种操作:
把有一些东西分开了,
初始化网卡与网卡数据接收中断:
extern void eth_init(void) ;
extern void eth_rx(int irq,void*devid) ;
而我自己移植里没有看到有那里初始化硬件,也没有看到那里调用其中的网卡接收中断数据函数
网卡初始化.
有low_level_init()是网卡初始化?不是,而网卡初始化是硬件文件里定义.
实际上都写到这个文件里了,sys_arch.c
1.初始化网卡和网络接口:
err_t init_ethernetif(struct netif*netif)
{
//初始化网卡
eth_init() ; //当然在硬件文件里实现
ethernetif_init(netif); //初始化网络接口,当然也会在硬件文件里实现,
return ERR_OK ;
}
2.初始化lwip
void sys_init(void)
{ //这里所做的一切都是一样的.没什么可以大作文件,看看即可.
netif_init() ;
mem_init() ;
memp_init() ;
pbuf_init() ;
.....
//这里把接收网卡数据的线程,创建起来.这里使用单独的线程执行ethernetif_input() ;
sys_thread_new(ethernet_rev,(void*)0,TCPIP_THREAD_PRIO) ;
}
//那我看看我的移植,没有初始化硬件.
我认为焦海波之做法不可靠,他把邮箱分成多个邮箱,再用链表链起来,
而其实可以采有和OS系统里创建队列,只建起队列即可,操作也在对队列实行
没有必要再去创建多个邮箱链表.
总感到别扭,为什么采用那种方式?
是否可以改革,把之前的所想的都改掉呢?
如果可以通了,就好.但关键是不知道是否能通啊.
dm9000.c里实际上也只是有三个函数:
重要的三个函数:
DM9000_init()
eth_rx()
eth_send()
而给出定义为外部变量时也采用了同样的方式:
extern DM9000_init()
extern eth_rx()
extern eth_send
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//一直没有bootloader ,所以重新找了一个.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
虽然移植完成了,但是测试时候,连lcd,com都没有成功,怎么办?
是否因为调用了OS里的sys_thread_new 之后,也把其中的任务破坏了?
是否还有一种可能是因为双重使用了ethernet.c而另一个只是用了一个名字为:
ethernetif.c
所以要么就此脱离移植笔录,
要么全部按移植笔录来操作,而不另外添加任务新东西.
怎样保持一个干净的东西,需要对此做一些修整.
可以把DM9000里的驱动先加进去,而不使用LwIP看结果如何.
在DM9000.c里设一些可以返回值Uart_printf() ; 这样的函数,让其运行过来,看看结果如何?
即调试一样的.如果DM9000驱动成功,再把LwIP加进去.
先让这个跑起来:myucos.rar
是否思路不清晰,造成了多加了一些任务?
只专门研究-lwip1.1.3
要不把驱动放到里去让其运行,看看结果,把它的每个函数都加进去试.
ADS1.2是否可以不需要平台调试呢?
先来看看模拟平台.模拟平台没办法测试丢弃.
再把LwIP移植工作做成功,做到最简单.
我让他全部是光光的,什么都没有,也不另添加什么新文件进去.
两个工程都基本完成,再烧到板子里试,看能不能跑起来,如果能,说明是两者都没破坏,
上一篇:拥抱ARM妹纸第二季 之 第二次 约会需要浪漫,这么大灯泡怎么弄?
下一篇:JLINK+ADS+mini2440配置
推荐阅读最新更新时间:2024-03-16 15:28