快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADI bf561 DSP
uclinux-2008r1.5-rc3(smp patch)
Visual DSP++ 5.0(update 5)
欢迎转载,但请保留作者信息
若您对本文有兴趣,可到http://www.bfin-tools.org/bbs/viewthread.php?tid=17&extra=进行讨论。
在A核启动的末期,会创建一个内核线程,此内核线程的入口为kernel_init函数。
static int __init kernel_init(void * unused)
{
………………………
smp_prepare_cpus(max_cpus);
……………………..
}
再看看smp_prepare_cpus函数:
void __init smp_prepare_cpus(unsigned int max_cpus)
{
platform_prepare_cpus(max_cpus);
platform_request_ipi(&ipi_handler);
}
继续看platform_prepare_cpus函数:
void __init platform_prepare_cpus(unsigned int max_cpus)
{
int len;
len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
if (len > COREB_SRAM_SIZE) {
/* Paranoid. */
printk(KERN_ERR "Bootstrap code size (%d) > CoreB SRAM (%d).\n",
len, COREB_SRAM_SIZE);
return;
}
dma_memcpy((void *)COREB_SRAM_BASE, &coreb_trampoline_start, len);
/* Both cores ought to be present on a bf561! */
cpu_set(0, cpu_present_map); /* CoreA */
cpu_set(1, cpu_present_map); /* CoreB */
printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_SRAM_BASE);
}
在这里有两个符号coreb_trampoline_end和coreb_trampoline_start。这两个符号分别指向了B核入口代码的起始位置和结束位置,然后通过DMA将它们复制到COREB_SRAM_BASE,即0xff60 0000,B核启动后将从这里开始执行。
注意此时B核仍然没有启动。真正启动B核要到下面的函数:
int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0)
return -EBUSY; /* CoreB already running?! */
printk(KERN_INFO "Booting Core B.\n");
spin_lock(&boot_lock);
/* Kick CoreB, which should start execution from CORE_SRAM_BASE. */
SSYNC();
bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~COREB_SRAM_INIT);
SSYNC();
timeout = jiffies + 1 * HZ;
while (time_before(jiffies, timeout)) {
if (cpu_isset(cpu, cpu_callin_map))
break;
udelay(100);
barrier();
if (jiffies > (timeout+500)) {
printk(KERN_INFO ".");
timeout = jiffies;
}
}
spin_unlock(&boot_lock);
return cpu_isset(cpu, cpu_callin_map) ? 0 : -ENOSYS;
}
这种方式在vdsp下使用有几个问题需要修改。
首先因为vdsp一启动直接就将B核置于FULLON的状态,所以前面的这个条件检测
if ((bfin_read_SICA_SYSCR() & COREB_SRAM_INIT) == 0)
return -EBUSY; /* CoreB already running?! */
只能略过。
在这里B核的可执行代码是由A核加载的,在vdsp下可以直接将代码放在coreb里面,因此platform_prepare_cpus函数只要留下
/* Both cores ought to be present on a bf561! */
cpu_set(0, cpu_present_map); /* CoreA */
cpu_set(1, cpu_present_map); /* CoreB */
这两行即可。
直接将arch/blackfin/mach-bf561/secondary.S添加到coreb工程中。
在默认情况下,B核入口指向uclinux_basiccrt.S,需要在ldf文件中进行修改:
RESOLVE(coreb_trampoline_start, 0xFF600000)
KEEP(coreb_trampoline_start,_main)
在此之前一直是将所有的代码链接到A核中,在启用了B核之后,这些代码和数据都必须设置为共享,最简单的办法就是将这些dlb和sml3.dlb放在一起,就像这样:
$LIBRARIES_SML3 =
/*$VDSG<insert-user-libraries-shared-memory-L3-beginning> */
/* Text inserted between these $VDSG comments will be preserved */
/*$VDSG<insert-user-libraries-shared-memory-L3-beginning> */
sml3.dlb
,arch-mm.dlb
,arch-kernel.dlb
,arch-lib.dlb
,kernel.dlb
,init.dlb
,mach-common.dlb
,mm.dlb
,fs.dlb
,fs-proc.dlb
,fs-sysfs.dlb
,fs-ramfs.dlb
,fs-patitions.dlb
,lib.dlb
,drivers-char.dlb
,drivers-serial.dlb
,drivers-base.dlb
,drivers-base-power.dlb
,drivers-net.dlb
,mach-bf561.dlb
,security.dlb
,net.dlb
,net-core.dlb
,net-netlink.dlb
,net-sched.dlb
,net-ethernet.dlb
,block.dlb
,$LIBS
然后将各个section的定义由p0转移到COMMON_MEMORY。
当然这样做会引起一些新的链接错误,下面将逐一解决。
uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(61):__builtin_constant_p(2009-2-11)
uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(62):__builtin_return_address(2009-2-11)
uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(63):_NSIG_WORDS_is_unsupported_size(2009-2-11)
uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(64):__ebss_b_l1(2009-02-12)