快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADSP-BF561
Visual DSP++ 5.0(update 6)
Bfin-uclinux-2009r1.6
欢迎转载,但请保留作者信息
下面我们尝试在vdsp下开发uclinux应用程序。
与驱动的开发类似,我们在内核代码之前挪用一段空间来使用。这样我们就可以在vdsp下使用固定地址的方式进行开发。
我们需要在应用程序中使用uclinux内核提供的服务,因此,uclibc就是必不可少的内容,我们将之移植到vdsp下编译。需要注意的是我们仅移植其中的libc。至于libdsp之类的我们直接可以使用vdsp的库,嘿嘿。
在开发的时候,我们使用vdsp进行编译并下载,然后使用一个stub程序接受命令行输入,并跳转到我们指定的位置开始执行。
开发完成后,我们通过stub程序加载dxe文件并跳转到正确的位置运行。
在vdsp下开发时,我们仅需要使用单核方式进行开发,当然,在实际运行时,我们的程序可能会在两个核之间进行切换,我们需要在下载完成后为ab核重新加载一次符号信息。
根据这种方式,写一个简单的ldf文件:
ARCHITECTURE(ADSP-BF561)
SEARCH_DIR($ADI_DSP/Blackfin/lib)
$LIBRARIES_CORE_A =
libc.dlb
, libdsp561.dlb
, libf64ieee561.dlb
, librt561.dlb
, libevent561.dlb
, libmc561.dlb
, libx561.dlb
, libsmall561.dlb
, libdrv561.dlb
, main.doj
;
#define VDSP_COMM_BEGIN 0x00010000
#define VDSP_COMM_END 0x00010039
#define VDSP_DRIVER_CODE_BEGIN 0x00010040
#define VDSP_DRIVER_CODE_END 0x0001ffff
#define VDSP_DRIVER_DATA_BEGIN 0x00020000
#define VDSP_DRIVER_DATA_END 0x0002ffff
PROCESSOR p0
{
MEMORY
{
MEM_VDSP_COMM { TYPE(RAM) START(VDSP_COMM_BEGIN) END(VDSP_COMM_END) WIDTH(8) }
MEM_DRIVER_CODE { TYPE(RAM) START(VDSP_DRIVER_CODE_BEGIN) END(VDSP_DRIVER_CODE_END) WIDTH(8) }
MEM_DRIVER_DATA { TYPE(RAM) START(VDSP_DRIVER_DATA_BEGIN) END(VDSP_DRIVER_DATA_END) WIDTH(8) }
} /* MEMORY */
OUTPUT($COMMAND_LINE_OUTPUT_DIRECTORY/p0.dxe)
SECTIONS
{
.vdsp_comm
{
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS($LIBRARIES_CORE_A(.vdsp_comm))
} > MEM_VDSP_COMM
.code
{
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS($LIBRARIES_CORE_A(program))
} > MEM_DRIVER_CODE
.data
{
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS($LIBRARIES_CORE_A(data1))
INPUT_SECTIONS($LIBRARIES_CORE_A(constdata))
INPUT_SECTIONS( $LIBRARIES_CORE_A(voldata))
INPUT_SECTIONS( $LIBRARIES_CORE_A(primio_atomic_lock))
} > MEM_DRIVER_DATA
bsz ZERO_INIT
{
INPUT_SECTION_ALIGN(4)
_bsz_begin = .;
INPUT_SECTIONS($LIBRARIES_CORE_A(bsz))
_bsz_end = .;
} > MEM_DRIVER_DATA
} /* SECTIONS */
} /* p0 */
这里最重要的是要保证我们移植的libc在vdsp库之前,这样才能正确使用uclinux内核提供的功能。
我们自己写一个appstub程序,辅助完成程序的调试,这个程序使用gcc编译,目前尚未实现dxe文件加载:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/watchdog.h>
#include <signal.h>
#include <paths.h>
#include <sched.h>
/*
* The main program.
*/
typedef int (*pfcall)(int argc, char *argv[]);
int main(int argc, char *argv[])
{
unsigned int addr = 0;
unsigned int *p;
if(argc < 2)
{
printf("not enough param.");
return 1;
}
addr = strtoul(argv[1], NULL, 16);
p = (unsigned int*)addr;
if(p[0])
{
printf("detect new app at %08x/n", p);
p[0] = 0;
if(p[1])
{
printf("prepare call %08x/n", p[1]);
argv[1] = argv[0];
((pfcall)p[1])(argc-1, argv+1);
printf("function call over./n");
}
else
printf("no function entry found./n");
}
else
printf("old app exist.");
return 0;
}
这段代码功能和简单,就是检测指定位置的内存,如果发现变化就跳转到指定位置继续运行,同时传递argc和argv参数。
我们的目标是在vdsp下开发uclinux应用程序,下面是一段很简单的代码:
#include <stdio.h>
static int app_main(int argc, char** argv);
typedef struct _vdsp_comm
{
int app_loaded;
void (*app_load)();
}vdsp_comm;
#pragma section(".vdsp_comm")
static vdsp_comm comm_param =
{
.app_loaded = 1,
.app_load = app_main,
};
static int main(int argc, char** argv, char** envp)
{
FILE* f = fdopen(1, "wt");
fprintf(f, "hello world!/n");
return 0;
}
extern void __uClibc_main(int (*main)(int, char **, char **), int argc,
char **argv, void (*app_init)(void), void (*app_fini)(void),
void (*rtld_fini)(void), void *stack_end) attribute_noreturn;
extern char bsz_begin[], bsz_end[];
static int app_main(int argc, char** argv)
{
memset(bsz_begin, 0, bsz_end - bsz_begin);
__uClibc_main(main, argc, argv, NULL, NULL, NULL, NULL);
return 0;
}
这段代码指定了程序入口是app_main,因为我们略过了uclibc的crt代码,因此在此函数的入口直接调用了uClibc_main对uclibc进行初始化。
这里需要注意的是bss段,在uclinux的flat格式的文件中,bss段是由加载器读取flat文件时清零的。对于我们这种情况就只能自己动手了,因此在uclibc_main调用之前插入了一个memset。
可以在console里看到程序的运行结果:
root:/> appstub 10000
detect new app at 00010000
prepare call 0001480e
hello world!
root:/>
下面是vdsp调试的截图:
我们可以像不带系统样的进行各种调试工作!
让vdsp与uclinux共舞(11):方案改进(2009-11-6)
让vdsp与uclinux共舞(10):加载SMP内核(2009-11-4)
让vdsp与uclinux共舞(9):查找内核函数(2009-11-3)
让vdsp与uclinux共舞(8):vdsp驱动框架(2009-11-3)
让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)
近日,我家6岁的小姑娘参加了第六届POP全国少儿英语风采大赛,拉票进行中(2011-6-15前)。
请帮忙点击新东方网站的链接:
http://popdasai.xdf.cn/toupiao.php?do=space&uid=4237
投她一票,谢谢!