快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADSP-BF561
Visual DSP++ 5.0(update 6)
Bfin-uclinux-2009r1.6
欢迎转载,但请保留作者信息
做好前面的准备工作,我们就可以用vdsp进行驱动的开发了。在开发的时候必须注意,虽然我们完全可以在驱动中使用vdsp库,但是如果希望驱动开发完成后能转入GCC编译,那就不要使用任何vdsp特有的东西!
为了尽快验证驱动可行性,在此采用了已经完全移植到vdsp下的内核的头文件,当然对于原始的头文件也不需要太大的改动。
在vdsp下新建一个工程,我们就叫它dummy_io吧,为了最后便于转到gcc下编译,我们把它放在linux-2.6.x/drivers/char目录下。
添加一个c文件,内容如下:
/*
简单驱动测试
*/
#ifdef __VISUALDSPVERSION__
#include <config.h>
#endif
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/raw.h>
#include <linux/tty.h>
#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/device.h>
#include <linux/highmem.h>
#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
#include <linux/bootmem.h>
#include <linux/splice.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
static void driver_load();
static void driver_exit();
typedef struct _vdsp_comm
{
int driver_loaded;
void (*driver_load)();
int driver_exited;
void (*driver_exit)();
}vdsp_comm;
#pragma section(".vdsp_comm")
static vdsp_comm comm_param =
{
.driver_loaded = 1,
.driver_load = driver_load,
.driver_exited = 0,
.driver_exit = driver_exit
};
static void driver_load()
{
}
static void driver_exit()
{
}
再添加一个ldf文件,内容如下:
ARCHITECTURE(ADSP-BF561)
SEARCH_DIR($ADI_DSP/Blackfin/lib)
// Workarounds are enabled, exceptions are disabled.
#define RT_LIB_NAME(x) lib ## x ## y.dlb
#define RT_LIB_NAME_EH(x) lib ## x ## y.dlb
#define RT_LIB_NAME_MT(x) lib ## x ## mty.dlb
#define RT_LIB_NAME_EH_MT(x) lib ## x ## mty.dlb
#define RT_OBJ_NAME(x) x ## y.doj
#define RT_OBJ_NAME_MT(x) x ## mty.doj
#define LIBS /
RT_LIB_NAME(mc561) /
,RT_LIB_NAME(small561) /
,RT_LIB_NAME_MT(io561) /
,RT_LIB_NAME_MT(c561) /
,RT_LIB_NAME_MT(event561) /
,RT_LIB_NAME_MT(x561) /
,RT_LIB_NAME_EH_MT(cpp561) /
,RT_LIB_NAME_EH_MT(cpprt561) /
,RT_LIB_NAME(f64ieee561) /
,RT_LIB_NAME(dsp561) /
,RT_LIB_NAME(sftflt561) /
,RT_LIB_NAME(etsi561) /
,RT_LIB_NAME(ssl561) /
,RT_LIB_NAME(drv561) /
,RT_LIB_NAME(usb561) /
,RT_LIB_NAME(rt_fileio561) /
$LIBS = LIBS;
$LIBRARIES_CORE_A =
RT_LIB_NAME_MT(io561)
, RT_LIB_NAME(profile561)
, RT_OBJ_NAME(crtn561)
, dummy_io.doj
;
#define VDSP_COMM_BEGIN 0x0019a000
#define VDSP_COMM_END 0x0019a03f
#define VDSP_DRIVER_CODE_BEGIN 0x001a0000
#define VDSP_DRIVER_CODE_END 0x001affff
#define VDSP_DRIVER_DATA_BEGIN 0x001b0000
#define VDSP_DRIVER_DATA_END 0x001bffff
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))
} > MEM_DRIVER_CODE
} /* SECTIONS */
} /* p0 */
假如我们改便了内核的编译选项,需要根据map重新定义下面这几个地址的值。
#define VDSP_COMM_BEGIN 0x0019a000
#define VDSP_COMM_END 0x0019a03f
#define VDSP_DRIVER_CODE_BEGIN 0x001a0000
#define VDSP_DRIVER_CODE_END 0x001affff
#define VDSP_DRIVER_DATA_BEGIN 0x001b0000
#define VDSP_DRIVER_DATA_END 0x001bffff
接着我们按f7编译链接,链接完成后自动提示是否下载,同意它下载,观察PC指针,在下载完成后并不会改变程序的状态。
在driver_load函数上设置一个断点,让a核继续运行,此时内核将自动检测到数据改变,输出以下信息:
driver loaded detect!prepare to init driver
而后vdsp将在我们的断点处中断下来:
这说明,我们的这一步已经成功,我们现在可以实现在vdsp下修改程序并让vdsp自动加载我们的驱动,哈哈!这一切只要按一下F7就OK了,是不是比kgdb简单多了?
下面我们将查找内核的函数并调用它。
让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)
关于uClinux-2.6(bf561) for VDSP的移植(2008/3/11)