RTEMS 移植 CS8900网卡成功

经过好久的折腾,大致是成功了,但是还剩下对齐问题没有解决,先记录


基础:
原始基础代码在 \rtems-4.10.2\c\src\libchip\network 下的 cs8900.c
默认已经是编译进系统的,但我们需要手动修改


在以下的bsp中有 cs8900 的bsp实现代码,基本上就是按照他来做,然后修改点点
满足自己的要求。
\rtems-4.10.2\c\src\lib\libbsp\arm\edb7312\network


在 config 的时候需要 --enable-networking 来启用网络协议栈


保证系统已经正常跑起来了,能正常打印hello world。


搭建好环境,我的环境是  virtualbox 里面按照centos5.8 ,用来做编译,编译出 xxx.exe
文件(其实就是 elf 文件,包含了调试信息的),在window下按照 eclipse,按照 zylin 插件
开发板,用JLINK GDBServer,写好 gdbinit 脚本,让rtems可以直接加载到 SDRAM 中进行调试。
这个环境还是挺不错的,至少能单步调试,断点等。比printf更加好用


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1,在 sbc2440 目录添加 network 目录,添加 network.c ,基本就是 edb7312\network 的复制过来用。
2,修改 上一个目录的 sbc2440\Makefile.am 注意修改
noinst_PROGRAMS =
if HAS_NETWORKING
network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
noinst_PROGRAMS += network.rel
network_rel_SOURCES = network/network.c
network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif


if HAS_NETWORKING
libbsp_a_LIBADD += network.rel
endif
添加好了之后需要重新config 和重新make,确保没错,被编译进去内核了。


3,MemoryControl 的BSWCON 和 BANK3 相关的寄存器必须设置,否则无法访问网卡的,至少应该能读到ID
我是在gdb脚本中设置的,具体数值如下,我的系统时钟为 200MHZ : 100MHZ : 50MHZ
monitor memU32 0x48000000 = 0x2201D110      #BWSCON
monitor memU32 0x48000010 = 0x00001F44      #bank3 cs8900
monitor memU32 0x48000024 = 0x008C04F5      #REFRESH 2^11 + 1 - HCLK* 7.8 = 1269 = 4F5


4,修改刚添加的network.c 先修改网卡的基地址,其他还要修改,这里按照思路来。直接使用IO访问
#define CS8900_BASE 0x19000300


5,修改 \libchip\network\cs8900.C 
在 cs8900_driver_attach 函数,注意在attach 的时候其实是需要器件本身的结构体 cs8900_device的
通过 config->drv_ctrl 传入,这个在头文件里面有说明用法,但是其实这样是不好的,这个内部的结构体不应该
由客户自己去构造,所以我放在了里面,驱动直接做。
添加一个全局变量
static cs8900_device cs8900;
在 cs8900_driver_attach 中
  // setup Memory control bank3
  {
    cs8900_device *cs = &cs8900;
    
    memset (cs, 0, sizeof (cs8900_device));
    cs->dev = 0;
    cs->io_base   = 0x19000300;
    cs->mem_base  = 0;
    cs->irq_level = 0;
    cs->rx_queue_size = 30;
    config->drv_ctrl = &cs8900;
  }
  // end
  // 原来的代码
  cs      = config->drv_ctrl;
  cs->dev = unit;
  ifp     = &cs->arpcom.ac_if;


表示自己直接指定一个器件结构


6,编译安装,然后编译 \network-demos-4.10.2\netdemo 这个是network-demos是另外下载的,和rtems源代码
一起下载的。其头文件 networkconfig.h 其实不需要添加什么,只需要指定网络地址,掩码就行了。
不适用 bootp


7,编译netdemo代码。运行,确保能读到网卡的ID号,这过程却是比较繁琐,如果有错误,就要重来,编译安装
内核,再编译 netdemo,再尝试运行,不断的重来,反正我在这里就折腾了好几天。确保能读到网卡ID号为止。


++++++++++++++++++++++


8,开始折腾第二阶段,修改 cs8900.c 使用固定的mac地址,不要读了。这个地址会在初始化时被写入网卡,所以
在这里设置就行了。
void cs8900_get_mac_addr (cs8900_device *cs, unsigned char *mac_address)
{
  // user static config
  mac_address[0] = 0x00;
  mac_address[1] = 0x04;
  mac_address[2] = 0x9f;
  mac_address[3] = 0x00;
  mac_address[4] = 0x5b;
  mac_address[5] = 0x21;
}


9,修改sbc2440/network/network.c 主要是修改中断,原来使用的,主要是使用了新的安装中断句柄函数
rtems_interrupt_handler_install,原来的bsp安装已经不用了。EINT9/GPG1 是网卡的中断引脚,设置外部
中断,中断触发为 上升弦,注意了。其实这里的丁点代码折腾了我好久,要翻越 s3c2440 的datasheet,要做
实验,要读懂网卡的资料,最后才实验成功 ...


rtems_isr BSP_EINT8_23_handler (rtems_vector_number vector)
{
unsigned long oft = rINTOFFSET;
unsigned long val = rEINTPEND;


    if (val & (1<<9))
    {
    cs8900_interrupt(BSP_EINT8_23, g_cs);
   
rEINTPEND = (1<<9);
}
    rSRCPND = 1<<oft;
    rINTPND = 1<<oft;
}


void cs8900_attach_interrupt (cs8900_device *cs)
{
rtems_status_code status;

    g_cs = cs;
    
      // setup interrupt 
  status = rtems_interrupt_handler_install(
        BSP_EINT8_23,
        "EINT8_23",
        RTEMS_INTERRUPT_UNIQUE,
        (rtems_interrupt_handler) BSP_EINT8_23_handler,
        NULL
  );


  // caution, should install handler first
  // EINT9/GPG1
  rGPGCON &= ~(0x03<<(1*2));
  rGPGCON |= 0x02<<(1*2);  //gpg1


  rEINTMASK &= ~(1<<9); // eint9
  rEXTINT1 &= ~(7<<4);
  rEXTINT1 |= 4<<4;   // high level int


  rINTMSK &= ~(1<<BSP_EINT8_23); // EINT8_23
}


void cs8900_detach_interrupt (cs8900_device *cs)
{
rINTMSK |= (1<<BSP_EINT8_23); // EINT8_23

    rtems_interrupt_handler_remove(
        BSP_EINT8_23,
        (rtems_interrupt_handler) BSP_EINT8_23_handler,
        NULL);
}


10,其实理论上以上的修改是已经足够的,但是我调试的过程中发现一直都失败,最后用wireshark 抓包发现
协议栈发送的 ARP 包是错的,以太网头应该是 14个字节的,但是这里的包却是 16个字节,调试了一段时间发现
貌似没啥错,就是 sizeof(ether_header) 居然返回 16个字节,本来应该是14的,思考了半天,突然想起了以前
看过下家山的文章,说是对齐的问题,只需要添加 __attribute__((packed)) 就可以了,我添加了,以太网头是
正常发送了,但是一收到数据就发生了异常 data abort 异常,查找了很久发现应该是内存对齐问题的引起的。
折腾了好久实在没有办法了,就下载了雪松的mini2440的包,对比了一下发现他修改了多处结构体的对齐问题,具体
如下


必须要改的:
E:\Project\rtems\rtems-4.9.5-emboslab\cpukit\libnetworking\net\ethernet.h
struct ether_header {
} __attribute__((packed));


E:\Project\rtems\rtems-4.9.5-emboslab\cpukit\libnetworking\netinet\ip.h
struct ip {
} __packed __aligned(1);


E:\Project\rtems\rtems-4.9.5-emboslab\cpukit\libnetworking\netinet\ip_var.h
struct ipovly {
} __attribute__ ((packed));




E:\Project\rtems\rtems-4.9.5-emboslab\cpukit\libnetworking\netinet\tcpip.h
struct tcpiphdr {
} __attribute__ ((packed));


struct full_tcpiphdr {
} __attribute__ ((packed));


E:\Project\rtems\rtems-4.9.5-emboslab\cpukit\include\rtems\bsd\sys\queue.h
struct quehead {
    struct quehead *qh_link;
    struct quehead *qh_rlink;
} __attribute__((packed));


最后在 sbc2440/make/sbc2440.cfg 中
-mstructure-size-boundary=32 改为 -mstructure-size-boundary=8 表示字节对齐


当所有这些都修改完之后,协议栈就正常了,能ping了,netdemo的整个都跑通了,网卡终于正常。


但是这里就留下了最大的问题,为什么BSD协议栈没有处理?没有意识到吗?我感觉不多可能,ARM平台的对齐问题确实
会带来这些问题,但是问题是 RTEMS 为什么没有修改?还是说不需要这里修改,有其他办法吗?看来一时半刻是搞不懂
的了,慢慢来,慢慢看协议栈吧。


11,说说怎么调试网络
第一,需要学习基本的数据包,ARP, ICMP , IP 这几个包的格式是必须学习的,其他可以慢慢学,不影响调试。
第二,必须学会抓包工具,我用的是 wireshark,开源的,挺好用,公司也在用它。要学会用基本的过滤条件捕捉到自己
想看的包,分析包的内容。定位问题
调试网卡驱动时
1,先关掉广播功能,我的办法是 在 cs8900.c 中修改 
  mem_pp_set_reg (cs, CS8900_PP_RxCTL,
                  CS8900_RX_CTRL_RX_OK |
                  CS8900_RX_CTRL_INDIVIDUAL);
表示只允许接收成功,而且是匹配自己本身MAC地址的包,简单点说只要点对点通过MAC地址发送的包才允许接收,不接收广播
这样对调试网卡是很有好处的,因为基本上不会有谁发给你,只有我自己ping的时候才收到包,非常适合调试。
2,window的命令行,先删除 arp 表
arp -d *
然后手动添加一条 
arp -s 192.168.0.191 00-aa-bb-cc-dd-ee  (目标板的ip和MAC)
这样,当ping的时候,因为目标的MAC地址已经存在在 ARP表中,所以不需要发起广播,是直接发送一个 ICMP(也就是IP包)
网卡驱动立刻就收到这个包,然后就可以分析发送的包,和网卡接收的是否正常,然后协议栈分析是否正常等等。


3,以上调试好了再打开广播功能调试 ARP 是否正常。
基本上ping通了之后都不会有问题的,bsd协议栈是出名稳定的。我是因为暂时没有理解对齐问题而已。


以上都是要点记录,做个笔记,本来应该是一年前做的,但是一直没有成功,当然了,知识是需要积累的,在这一年中我学了其他
学习协议栈,会抓包了,都为这个做了准备,最近的2个星期应该相关刚完成,新的项目还没有启动,抓住这个空档,一口气
把这个心愿给了解了,网络通了,可以用来学习 bsd的协议栈,写得很好,又有书说明。(TCPIP协议第二卷)


fin

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值