tag 标签: 松江嵌入式

相关博文
  • 热度 28
    2012-4-4 12:26
    2111 次阅读|
    0 个评论
    作者,下家山 9.1需要改动的地方 :        ①c/src/lib/libcpu/arm/s3c2410/include/s3c2400.h相应register的修改.        ②因为要使用串口功能,所以需要在应用程序中添加端口初始化函数,来初始化各端口,主要初始化Port F,H,端口F为LED显示功能所用,端口H为串口打印功能所用.            (可以直接复制s3c2410开发板套件资料的armsys_2410/hardware_test_pro中的Port_Init函数)        ③在c/src/lib/libbsp/arm/gp32/startup/Bspstart.c,bsp_start_default函数中添加bank0-bank7的相关register的设置        ④在start.S(见c/src/lib/libbsp/arm/gp32/start)中添加LED显示子程序.    9.2需要确认的地方:        ①在c/src/lib/libbsp/arm/gp32/console/Uart.c中对照s3c2410 datasheet确信各register地址是否正确.        ②确信baudrate是否与PC机上的串口baudrate一致.        ③Fclk,Pclk,Hclk的值为多少,相关函数参照c/src/lib/libcpu/arm/s3c2400/clock/Support.c c/src/lib/libbsp/arm/gp32/include/Bsp.h  c/src/lib/libbsp/arm/gp32/startup/Bspstart.c 知道baudrate,Fclk,Pclk,Hclk是怎么计算的,并对照s3c2410 datasheet确信计算结果是否准确.     9.3调试方法 :            LED跟踪(并借助ads)             所以需要写一个LED显示程序,最好用汇编写,并在ads上验证该程序能正常调用. 10:调试hello world时碰到的问题          我用LED一直跟踪到boot_card函数都很顺利,但到执行 BSP_RTEMS_Configuration = *Configuration.RTEMS_api_configuration;这条语句时程序跳飞。显然,这条跳飞的原因大半是指针造成的,Configuration.RTEMS_api_configuration是一个指针,使用指针的大忌是不初始化就使用,因为没有初始化,所指向的地址未知,因此程序跑飞.所以,我定义了一个rtems_api_configuration_table     结构体,并把其地址赋给Configuration.RTEMS_api_configuration,果然BSP_RTEMS_Configuration = *Configuration.RTEMS_api_configuration;执行过去了.我开始接着往下调,但一个OS往往是牵一发而动全身,改动了Configuration.RTEMS_api_configuration,接下来很多地方都要改动,所以要找到根源.           BSP_RTEMS_Configuration是Configuration的一个复制体,而Configuration是在confdefs.h中定义的,是一个已初始化的全局变量,所以我怀疑是不是全局变量初始化不成功?初始化的全局变量是放在.data区域的,而这一区域是定位在sdram中的.那么怎样才能看到这一区域的内容呢?最后想到了ads,我通过ftp把编译好的bin文件下载到板子后,再通过AXD调试软件查看sdram中的内容.这里,可以定义些一眼就能看出来的特征值,比如定义两个全局变量int a=0xaaaaaaaa;int b=0xbbbbbbbb;.但是,64M的sdram怎么查呢!用过ads的人应该知道,编译后的执行文件(.o)对每个函数,全局变量都已分配好了地址,这些地址在编译完成时在Section Cross References中会列出来.那么,在gcc中编译后怎么查看其中的函数,变量的地址呢?找相关资料,发现readelf就是干这个事的,所以readelf -a helloworld.exe map得到map文件,用UltraEdit -32打开查看,记下全局变量a,b的地址(map中你还可以看到各函数的具体位置及占用空间的大小。要知道自己添加的文件是否编译进去,这是个很好的方法,我在编译network时,就如此).然后,在axd中定位到刚才记下的地址,发现AXD中a,b的地址与刚记下的地址(map)相差0x100偏移量.后面,我还做了大量的实验,比如定义结构体.都证明gcc编译后的全局变量的地址与AXD中查到的地址相差0x100,AXD查到的地址应该是sdram中的实际反映.因此我马上想到了linkcmds文件的.base段,其定义的就是sdram起始的0x100个字节,果然,当我把.base段去掉后原来跑飞的地方通过了.但去掉.base也不是办法,之后把它移到.bss段。但后来想来想去还是不妥,既然系统把它定义到前面一定不会错,我把它改动了,还不知有什么后患呢?那还有什么办法呢?后来突然想到,我通过uboot下载bin文件到sdram时,load地址是0x30000000,我把load地址改为0x30000100后,也一样解决了问题.         在调试hello world例程时碰到的主要是这个问题.其他地方只要调试时细心应该不会有什么问题. 11:调试网络时碰到的问题            在testsuites/samples中找到loopback例程,发现要用到clock驱动. 而专门测试clock的例程是testsuites/samples下的ticker.clock是通过中断来实现的,所以接下来要添加中断.            首先,弄清楚RTEMS内核,中断的实现机制.rtems-4.6.99.3关于中断的函数调用流程如下:    rtems_exception_init_mngt安装六类异常向量地址到rtems_vector_table(在linkcmds中定义,实际地址为0x30000020)开始的地方,rtems_irq_mngt_init以实际的irq句柄初始化异常向量表,并以default_int_handler地址初始化32个rtems bsp       irq中断向量地址.当发生irq中断时,系统跳到0x00000018地址执行,0x00000018地址处装载的就是rtems_irq_mngt_init安装的实际的irq句柄,通过这个句柄就可以找到相应的32个rtems bsp irq中断向量的哪个发生了中断,从而跳到对应isr服务程序执行.            系统是怎么找到clock中断isr服务地址的,rtems-4.6.99.3关于clock中断的函数调用流程如下       到现在虽然中断句柄已经安装好了,但还没有做映射,系统怎么访问0x00000018地址呢? 11.1   MMU          记得,在start.S中我屏蔽了          ldr     r0, =mem_map/*装载映射表*/          bl      mmu_init   /*初始化mmu*/          现在要打开          程序的调试工作有回到了汇编阶段,所以,我又用LED跟踪.          一直跟踪到函数mmu_init中的 mmu_set_ctrl函数         前都没事,但调用这个函数时程序跑飞了.         我开始怀疑是C内嵌汇编出了问题,所以我把mmu_set_ctrl换成了纯汇编程序放到了start.S中,同样跟踪到了我转换后的汇编函数中。但,就在执行使能mmu这条语句时飞掉了.把这条语句屏蔽了就没事.说明不是内嵌汇编的问题.那么在执行这条语句时,cpu到底做了些什么呢?要擦看汇编及pc指针最好的办法莫过于用ads了,用AXD调试程序运行到使能mmu这条语句时也跑飞了.做了改动的地方只有       mem_map,gp32中的映射表为   我改动后为   我开始以为映射属性的问题,但怎么换都不行,后来,发现问题出在映射size上,64M的sdram只映射了9M,暂且不说,因为我程序加各堆栈再怎么样也不会超过9M,没有映射完64M也不会出什么问题.但是,Internals Regs如果没有映射完就有问题了,我对照s3c2410.h,发现,从48000000-4a000000,50000000-5a0000000而我只映射了16M也就是只映射了48000000-49000000,50000000-510000000,这么多register没有映射,当要访问没有映射的register时肯定会因找不到地址而跑飞.所以,映射所有的bank0-bank7     mmu_sect_map_t mem_map[] = { /*    */     {0x30000000, 0x00000000,   1, MMU_CACHE_NONE},     /* SDRAM for vectors */     {0x30000000, 0x30000000,   32, MMU_CACHE_WTHROUGH}, /* SDRAM W cache */     {0x32000000, 0x32000000,   32, MMU_CACHE_NONE},     /* SDRAM W/O cache */     {0x48000000, 0x48000000,   256, MMU_CACHE_NONE},    /* Internals Regs - */     {0x50000000,  0x50000000,   256, MMU_CACHE_NONE},    /* Internal Regs - */     {0x00000000, 0x00000000,   0,    0}                /* The end */ }; 这样,运行ticker例程时,看到了正确结果. 11.2 照葫芦画瓢      由于rtems-4.6.99.3源码自带的gp32-bsp中并没有网络驱动,所幸的是edp7312中有cs8900的驱动,因此可以copy edp7312目录下的整个network目录到c/src/lib/libbsp/arm/gp32下,并修改相关makefike文件,这里我把要注意的地方列出来:      ①在configure rtems-4.6.99.3时去掉disable-networking disable-posix; ②对bank3 bus设置:   /*==========Bank 3 parameter==========*/ #define B3_Tacs        0x0  /*0clk*/ #define B3_Tcos        0x3  /*0clk*/ #define B3_Tacc        0x7  /*14clk*/ #define B3_Tcoh        0x1  /*0clk*/ #define B3_Tah         0x0  /*0clk*/ #define B3_Tacp        0x3  #define B3_PMC         0x0  /*normal*/ rBANKCON3= ((B3_Tacs13)+(B3_Tcos11)+(B3_Tacc8)+(B3_Tcoh6)+(B3_Tah4)+(B3_Tacp2)+(B3_PMC)); 不然,连cs8900 ID号都读不出来. 要成功编译需要花点时间。但这不是难点!只要细心,应该没有问题。 转载:请注明,作者,下家山   请尊重原创!    
  • 热度 20
    2012-4-4 12:24
    2076 次阅读|
    0 个评论
    作者,下家山   11.3 需要添加的东东      参考c/src/lib/libbsp/arm/edb7312/include/bsp.h,在c/src/lib/libbsp/arm/gp32/include/bsp.h中添加cs8900相关的东东;                                     针对s3c2410修改或添加c/src/lib/libbsp/arm/gp32/network/network.c,有下列内容要添加或修改: ① 定义 cs8900 基址 , 即#define CS8900_BASE 0x19000300 ② 中断号 , 查看原理图,cs8900用的是EINT9号中断,所以cs8900_isr_data数组要改为rtems_irq_connect_data cs8900_isr_data = {BSP_EINT8_23,                                          (rtems_irq_hdl)cs8900_isr,                                          cs8900_isr_on,cs8900_isr_off, cs8900_isr_is_on,                                          3,     /* unused for ARM cpus */                                          0 };   /* unused for ARM cpus */            ③ EINT9 中断初始化 , 我把EINT9的中断初始化放在 cs8900_isr_on中,这样可以在安装isr_handler时  初始化static void cs8900_isr_on(const rtems_irq_connect_data *unused) {          rGPGCON = (rGPGCON 0xfffffff3)|(13);        /*PG1/9 = EINT9*/              rGPGUP  = 0xffff;          rEXTINT1 = (rEXTINT1 ~(74)) | 0x44; /*EINT9=high level triggered*/          rEINTPEND=(19);              /*rSRCPND = BIT_EINT8_23; *//*to clear the previous pending states*/              /*rINTPND = BIT_EINT8_23;*/              rEINTMASK = ~(19|0xf);/*enable EINT9*/          rINTMSK = ~BIT_EINT8_23;/*enable EINT8_23*/                  return; } ④中断复位 ,即中断发生后要清中断,如: rtems_isr cs8900_isr(rtems_vector_number v) {     rEINTPEND=(19);         ClearPending(BIT_EINT8_23);     cs8900_interrupt(v, g_cs);    }  针对s3c2410修改或添加c/src/libchip/network/cs8900.c,有下列内容要添加或修改:        ⑤ 声明 cs8900_device 结构体 ,如static cs8900_device cs8900;        ⑥ attach cs8900_device 结构体 , 即在函数cs8900_driver_attach的if语句前添加config-drv_ctrl=cs8900;语句,这条语句必须添加,不然出现Driver eth0 already in use.的错误,即        ⑦ 应用程序需要添加的东西 , 我开始调试的是rtems-4.6.99.3/testsuites/samples/loopback,但后来想到要从PC端PING 2410,就直接换成了调试netlink例程(rtems-4.6.99.3没有network例程,需要下载其他版本的例程),但调试了几天也没调试成功,后来看rtems-4.6.99.3下面的doc文档networking.pdf介绍了netdemo例程,又改成调netdemo。例程netdemo中需要添加networkconfig.h文件,并修改其中的rtems_bsdnet_ifconfig,rtems_bsdnet_config两个结构体.修改后的内容如下: static char ethernet_address = { 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }; static struct rtems_bsdnet_ifconfig netdriver_config = {          RTEMS_BSP_NETWORK_DRIVER_NAME,                 /* name */          RTEMS_BSP_NETWORK_DRIVER_ATTACH,    /* attach function */          NULL,                                   /* link to next interface */          "192.168.13.88",          /* IP address */          "255.255.255.0",          /* IP net mask */          ethernet_address,               /* Ethernet hardware address */          0                                   /* Use default driver parameters */ };      struct rtems_bsdnet_config rtems_bsdnet_config = {                  netdriver_config,                  NULL,                   0,                          /* Default network task priority */                   0,                          /* Default mbuf capacity */                   0,                          /* Default mbuf cluster capacity */                   "rtems_host",                /* Host name */                   "nodomain.com",          /* Domain name */                   "192.168.13.1",   /* Gateway */                   "192.168.13.11", /* Log host */                   {"192.168.13.88" },      /* Name server(s) */ }; 11.4  ping      开始ping板子,什么反应都没有,所以找了个抓包程序,发现PC端收到的包格式有错误,收到内容如下:ff ff ff ff ff ff 33 44 55 66 77 88 08 06 00 00 00 01 08 00 06 04 00 01 33 44 55 66 77 88 c0 a8 0d 58 00 00 00 00 00 00 c0 a8 0d 0b 0b 0b 0b 0b 0b 0b…分析后发现在08 06 后面多了两个字节00 00,分析原代码(花了很长时间)发现sizeof (struct ether_header)=16(应用到此结构的代码在cpukit/libnetworking/net/if_ethersubr.c),ether_header定义如下: struct ether_header {          u_char        ether_dhost ;/* ETHER_ADDR_LEN =6*/          u_char        ether_shost ;/**/          u_short       ether_type; };/*见cpukit/libnetworking/net/Ethernet.h*/ 按理所sizeof (struct ether_header)应为14但是我printf后的结构却为16,显然多出的两个字节在此,后来问同事说是字节对齐问题,果然在ether_header结构体后加__packed __attribute__((packed))属性后 struct ether_header {          u_char        ether_dhost ;/* ETHER_ADDR_LEN =6*/          u_char        ether_shost ;/**/          u_short       ether_type; }__packed __attribute__((packed)); 果然ping通了。 转载:请注明,作者,下家山   请尊重原创!