快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADSP-BF561
Visual DSP++ 5.0(update 6)
Bfin-uclinux-2009r1.6
欢迎转载,但请保留作者信息
在内核代码中随处可见EXPORT_SYMBOL,在不启用module的支持时,它们被定义为:
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
#define EXPORT_SYMBOL_GPL_FUTURE(sym)
#define EXPORT_UNUSED_SYMBOL(sym)
#define EXPORT_UNUSED_SYMBOL_GPL(sym)
也就是什么事情也不做,但是当启用MODULE的支持时(CONFIG_MODULES)它们就变成了:
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) /
extern typeof(sym) sym; /
__CRC_SYMBOL(sym, sec) /
static const char __kstrtab_##sym[] /
__attribute__((section("__ksymtab_strings"), aligned(1))) /
= MODULE_SYMBOL_PREFIX #sym; /
static const struct kernel_symbol __ksymtab_##sym /
__used /
__attribute__((section("__ksymtab" sec), unused)) /
= { (unsigned long)&sym, __kstrtab_##sym }
#define EXPORT_SYMBOL(sym) /
__EXPORT_SYMBOL(sym, "")
就这样,对于每个用EXPORT_SYMBOL指定的符号,内核都将用一个kernel_symbol结构体进行描述:
struct kernel_symbol
{
unsigned long value;
const char *name;
};
并且这些描述信息被统一放到__ksymtab这个段中,看看vmlinux.lds.s对这个段的处理:
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { /
VMLINUX_SYMBOL(__start___ksymtab) = .; /
*(__ksymtab) /
VMLINUX_SYMBOL(__stop___ksymtab) = .; /
} /
因此如果我们需要查询一个函数的地址,只要查询__start___ksymtab和__stop___ksymtab之间的空间,让它们进行名称匹配就可以得到函数地址了。当我们在vdsp下查找的时候,需要从system.map中得到__start___ksymtab和__stop___ksymtab这两个地址,当改变内核的编译选项时,需要相应改变这两个地址。
我们尝试查找printk,并在驱动初始化时调用它输出信息:
typedef struct _ksymbol
{
unsigned long value;
const char* name;
} ksymbol;
typedef (*pfcall)();
// 根据system map的值修改而来
#define SYMTAB_START 0x00129190
#define SYMTAB_STOP 0x0012cd18
unsigned long find_symbol(const char* name)
{
ksymbol* p = (ksymbol*)SYMTAB_START;
while(p < SYMTAB_STOP)
{
if(strcmp(p->name, name) == 0)
return p->value;
p++;
}
return 0;
}
// 我们需要的内核函数列表
pfcall my_printk;
void find_my_function()
{
// 查找我们需要的内核函数,注意下划线
my_printk = find_symbol("_printk");
}
static void driver_load()
{
find_my_function();
if(my_printk)
{
my_printk("/nI AM HERE!/n");
}
}
static void driver_exit()
{
}
然后在ldf文件中加上constdata,bsz等各段的定义,下载运行:
哈哈,内核很听话地输出
I AM HERE!
真乖,给你发糖吃!
忙乎了几天,做个初步的总结:
1、完全可以用vdsp控制uclinux内核的运行。
2、vdsp无法读取vmlinux中的详细调试信息,因而无法直接对内核的其它部分做源码级的调试,一个很大的遗憾。
3、在vdsp下开发uclinux驱动是可行的,且开发调试的效率比kgdb的方式要高。
4、在vdsp下使用单步跟踪的时候,偶尔会发生VDSP总处于stepping的情况,但如果是设置断点并直接run则没有任何问题。
5、相比于将整个内核移植到vdsp下,只用vdsp开发驱动的方法要快速、简单得多,也稳定得多。因而也更具实用价值。
6、可以考虑开发一个专用于vdsp开发驱动的辅助驱动,完成内核资源的动态或者静态申请,开发完成之后辅助将之链接到内核中。
7、用VDSP开发uclinux应用程序的方法与此类似,自己改造一个类似于加载flat文件的驱动。
希望以后再有人问:“你这个东西有没有实用?”
可以大声回答:“当然!”
近日,我家6岁的小姑娘参加了第六届POP全国少儿英语风采大赛,拉票进行中(2011-6-15前)。
请帮忙点击新东方网站的链接:
http://popdasai.xdf.cn/toupiao.php?do=space&uid=4237
投她一票,谢谢!
让vdsp与uclinux共舞(7):在内核为驱动预留空间(2009-11-2)
让vdsp与uclinux共舞(6):用vdsp开发驱动的设想(2009-11-2)
让vdsp与uclinux共舞(5):加入dwarf调试信息(2009-11-2)
让vdsp与uclinux共舞(4):加载uclinux(2009-11-2)
让vdsp与uclinux共舞(3):boot kernel(2009-10-31)
让vdsp与uclinux共舞(2):vdsp的影响(2009-10-31)
让VDSP与uclinux共舞(1):开篇(2009-10-30)