Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1640873
  • 博文数量: 124
  • 博客积分: 4078
  • 博客等级: 中校
  • 技术积分: 3943
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-21 11:28
个人简介

新博客:http://sparkandshine.net/

文章分类

全部博文(124)

分类: 嵌入式

2012-04-10 17:37:10

摘要:

    本文详细记录了Contiki动态加载模块Loader在IAR下移植遇到的问题,分析及解决。


一、编译错误

1.1 could not open source file

    Contiki是在Linux平台下开发的,其源码引用了Linux库头文件(仅仅引用库文件,自己实现,比如dlfcn.h的dlopen函数),当在IAR编译时提示could not open source file错误,解决方法是将这些头文件从Linux找出来并加到IAR的工程目录,Linux库头文件可能又包含其他库头文件,不过不用担心,会很快收敛的:-)涉及到文件如下:

  1. ./include/malloc.h dlfcn.h features.h unistd.h
  2. ./include/i386-linux-gnu/bits/predefs.h wordsize.h dlfcn.h environments.h esizes.h confname.h types.h posix_opt.h
  3. ./include/i386-linux-gnu/sys/cdefs.h
  4. ./include/i386-linux-gnu/gnu/stubs.h stubs-32.h
  5. ./include/getopt.h

    为了尽量少改动代码,根据源码,用文件目录core/linux_lib组织这些被引用库头文件,记得将相应路径加到IAR的预处理路径中,linux_lib文件压缩包文件 linux_lib.rar   。

1.2 FILE未定义

    编译提示FILE未定义,在malloc.h文件,如下,在Contiki并没有用到这些函数,注释掉。

  1. extern int malloc_info (int __options, FILE *__fp);

1.3 expression must be a pointer to a complete object type

    编译时,提示错误"expression must be a pointer to a complete object type ",定位于Contiki\core\loader\cmod.c 94,如下:

  1. h.bss = h.data + h.datasize;

    h类型是cle_info结构体,bss、data、datasize类型分别为void *、void *、cle_word(实质是u16_t)。理论上是没有错的,但这跟编译器有关(GCC可以,IAR不行),主要问题在于类似的隐式转换,这里将类型转换显式化(假设是32位的处理器),如下:

  1. h.bss = (void *)((u32_t)h.data + h.datasize);

1.4 类型不匹配

    编译时,在文件core\loader\cmod.c提示错误a value of type "void *" cannot be assigned to an entity of type "void (*)(void)" ,提示错误的源代码如下:

  1. cmod_module[imod].fini = cle_lookup(&h, pread, off, "_fini");
  2. init = cle_lookup(&h, pread, off, "_init");

    .init和.fini是程序初始化与终结代码段,这两个段的代码会最终拼成两个函数_init()和_fini()。cle_lookup函数返回void类型的指针,但cmod_module[imod].fini是函数指针。

  1. //filename:cle.c function:cle_lookup()
  2. return (void*)(uintptr_t)(addr + s.st_value);

  3. struct cmod_info cmod_module[CMOD_NMODULES];
  4. struct cmod_info
  5. {
  6.   void *ram;
  7.   void(*fini)(void);
  8. };

问题转化为将指针转换为函数指针(也许在GCC无须修改),修改后代码如下:

  1. cmod_module[imod].fini = (void (*)(void))(cle_lookup(&h, pread, off, "_fini"));

同理,init = cle_lookup(&h, pread, off, "_init")改成:

  1. init = (void (*)(void))(cle_lookup(&h, pread, off, "_init"));

在elfloader_compat.c也有类似的问题,修改后代码如下:

  1. elfloader_fini = (void (*)(void))(cle_lookup(&h, xmem_pread, eepromaddr, "_fini")); 
  2. elfloader_init = (void (*)(void))(cle_lookup(&h, xmem_pread, eepromaddr, "_init"));

关于如何将指针转换为函数指针可参考博文《如何将一个指针强制转换为一个函数指针》。

1.5 off_t和intptr_t重定义

    off_t分别在platform/stm32test/contiki-conf.h、core/linux_lib/sys/unistd.h定义,前者实质是unsigned long,后者实质是long int,这里注释后者的定义。

    intptr_t分别在IAR Systems\Embedded Workbench 5.4\arm\INC\stdint.h、core/linux_lib/sys/unistd.h定义,前者实质是__INTPTR_T_TYPE__,后者实质是int,这里注释后者的定义。

1.6 _etext、_edata、__data_start未定义

    编译时,在elfloader_compat.c提示_etext、_edata、__data_start未定义错误,这些符号(通常称特殊符号)被定义在链接脚本中(ld链接器是这样,IAR也是吗?),程序使用需先声明,链接器会在链接成可执行文件时解析成正确的值。在elfloader_compat.c加入如下代码:

  1. /***added by jelline***/
  2. extern unsigned long _etext; //代码段结束地址 _stext为代码段开始地址
  3. extern unsigned long __data_start; //初始化的数据开始地址
  4. extern unsigned long _edata//初始化的数据结束地址

1.7 ROM_ERASE_UNIT_SIZE未定义

    编译时,在elfloader_compat.c报ROM_ERASE_UNIT_SIZE未定义错误,Contiki是按sector擦除的,这里将ROM_ERASE_UNIT_SIZE定义为COFFEE_SECTOR_SIZE,在elfloader_compat.c加入如下代码:

  1. #include "cfs-coffee-arch.h"

  2. #define ROM_ERASE_UNIT_SIZE COFFEE_SECTOR_SIZE

三、链接错误

3.1 elfloader_arch_allocate_ram等重定义

    链接时,提示elfloader_arch_allocate_ram、elfloader_arch_allocate_ram、elfloader_arch_relocate、elfloader_arch_write_rom重定义,如下:

图1 重定义错误

    elfloader_arch_allocate_ram、elfloader_arch_allocate_ram、elfloader_arch_relocate、elfloader_arch_write_rom分别在文件core/loader/elfloader-stub.c、cpu/arm/stm32f103/elfloader-stm32f10x.c实现。elfloader-stub.c可以理解为elfloader-stub.h实现的模板,我本以为还要自己实现呢(我的MCU是stm32f103),原来Contiki已经有了,这里将elfloader-stub.c从工程目录移除,并添加elfloader-stm32f10x.c

3.2 elfloader_load、elfloader_unknow重定义

    链接时,提示elfloader_load、elfloader_unknow重定义,其分别在文件core/loader/elfloader.c、core/loader/elfloader_compat.c实现。这里将elfloader_compat.c从工程目录移除。


至此,编译链接成功,接下来就是写些测试例子测试下:-)

阅读(7230) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~