快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADI bf561 DSP
uclinux-2008r1.5-rc3 (移植到vdsp5)
Visual DSP++ 5.0(update 5)
欢迎转载,但请保留作者信息
/* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */
call _bf53x_relocate_l1_mem;
#if CONFIG_BFIN_KERNEL_CLOCK
call _start_dma_code;
#endif
这里调用了两个函数,第一个函数bf53x_relocate_l1_mem的实现在linux-2.6.x\arch\blackfin\kernel\setup.c中,其用意是将定义在l1 cache里的代码和数据由SDRAM复制到l1 cache,但是当在vdsp下编译时直接通过LDF的控制将这些内容放在了l1 cache里面,因此第一个函数可跳过。
第二个函数start_dma_code的实现也在head.s中,用于设置PLL和SDRAM的参数,下面主要看看这个函数:
#if CONFIG_BFIN_KERNEL_CLOCK
ENTRY(_start_dma_code)
p0.h = hi(SICA_IWR0);
p0.l = lo(SICA_IWR0);
r0.l = 0x1;
[p0] = r0;
SSYNC;
/*
* Set PLL_CTL
* - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors
* - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK
* - [7] = output delay (add 200ps of delay to mem signals)
* - [6] = input delay (add 200ps of input delay to mem signals)
* - [5] = PDWN : 1=All Clocks off
* - [3] = STOPCK : 1=Core Clock off
* - [1] = PLL_OFF : 1=Disable Power to PLL
* - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL
* all other bits set to zero
*/
p0.h = hi(PLL_LOCKCNT);
p0.l = lo(PLL_LOCKCNT);
r0 = 0x300(Z);
w[p0] = r0.l;
ssync;
P2.H = hi(EBIU_SDGCTL);
P2.L = lo(EBIU_SDGCTL);
R0 = [P2];
BITSET (R0, 24);
[P2] = R0;
SSYNC;
r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */
r0 = r0 << 9; /* Shift it over, */
r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/
r0 = r1 | r0;
r1 = PLL_BYPASS; /* Bypass the PLL? */
r1 = r1 << 8; /* Shift it over */
r0 = r1 | r0; /* add them all together */
p0.h = hi(PLL_CTL);
p0.l = lo(PLL_CTL); /* Load the address */
cli r2; /* Disable interrupts */
ssync;
w[p0] = r0.l; /* Set the value */
idle; /* Wait for the PLL to stablize */
sti r2; /* Enable interrupts */
.Lcheck_again:
p0.h = hi(PLL_STAT);
p0.l = lo(PLL_STAT);
R0 = W[P0](Z);
CC = BITTST(R0,5);
if ! CC jump .Lcheck_again;
/* Configure SCLK & CCLK Dividers */
r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV);
p0.h = hi(PLL_DIV);
p0.l = lo(PLL_DIV);
w[p0] = r0.l;
ssync;
p0.l = lo(EBIU_SDRRC);
p0.h = hi(EBIU_SDRRC);
r0 = mem_SDRRC;
w[p0] = r0.l;
ssync;
p0.l = LO(EBIU_SDBCTL);
p0.h = HI(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */
r0 = mem_SDBCTL;
w[p0] = r0.l;
ssync;
P2.H = hi(EBIU_SDGCTL);
P2.L = lo(EBIU_SDGCTL);
R0 = [P2];
BITCLR (R0, 24);
p0.h = hi(EBIU_SDSTAT);
p0.l = lo(EBIU_SDSTAT);
r2.l = w[p0];
cc = bittst(r2,3);
if !cc jump .Lskip;
NOP;
BITSET (R0, 23);
.Lskip:
[P2] = R0;
SSYNC;
R0.L = lo(mem_SDGCTL);
R0.H = hi(mem_SDGCTL);
R1 = [p2];
R1 = R1 | R0;
[P2] = R1;
SSYNC;
RTS;
ENDPROC(_start_dma_code)
#endif /* CONFIG_BFIN_KERNEL_CLOCK */
这段代码的注释已经相当清晰了,当在vdsp下调试的时候,在运行到
w[p0] = r0.l; /* Set the value */
idle; /* Wait for the PLL to stablize */
sti r2; /* Enable interrupts */
中的idle的时候,dsp进入idle状态,vdsp仍然显示a核在running,中断下来后pc将停在sti r2语句上,此时可以继续往下执行,但是PLL的配置并不会生效,除非此时B核处于idle状态。
head.s分析(1):保存u-boot传递过来的指针(2009-1-19)
head.s分析(2):SYSCFG配置(2009-1-19)
head.s分析(3):数据及指针寄存器清0(2009-1-19)
head.s分析(4):关闭CACHE(2009-01-19)
head.s分析(5):关闭串口(2009-01-19)
head.s分析(6):栈指针初始化(2009-01-19)
head.s分析(7):init_early_exception_vectors(2009-1-19)