快樂蝦
http://blog.csdn.net/lights_joy/
lights@hb165.com
本文適用于
ADSP-BF561
uclinux-2008r1.5-rc3 (smp patch, 移植到 vdsp5)
Visual DSP++ 5.0(update 5)
歡迎轉(zhuǎn)載 , 但請保留作者信息
本文討論鏈接: http://www.bfin-tools.org/bbs/viewthread.php?tid=23&extra =
cplb 表的生成由 generate_cpl_tables 函數(shù)完成:
void __init generate_cpl_tables( void )
{
unsigned int cpu;
/* Generate per-CPU I&D CPLB tables */
for (cpu = 0; cpu < NR_CPUS; ++cpu)
generate_cpltab_cpu(cpu);
}
由于 ab 兩個核都需要 cpl 表,因此實際工作將由 generate_cpltab_cpu 函數(shù)完成。它的主體結(jié)構(gòu)如下:
void __init generate_cpltab_cpu( unsigned int cpu)
{
u16 i, j, process;
u32 a_start, a_end, as, ae, as_1m;
struct cplb_tab *t_i = NULL;
struct cplb_tab *t_d = NULL;
struct s_cplb cplb;
printk(KERN_INFO "NOMPU: setting up cplb tables for global access\n" );
cplb.init_i.size = CPLB_TBL_ENTRIES;
cplb.init_d.size = CPLB_TBL_ENTRIES;
cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
cplb.init_i.pos = 0;
cplb.init_d.pos = 0;
cplb.switch_i.pos = 0;
cplb.switch_d.pos = 0;
cplb.init_i.tab = icplb_tables[cpu];
cplb.init_d.tab = dcplb_tables[cpu];
cplb.switch_i.tab = ipdt_tables[cpu];
cplb.switch_d.tab = dpdt_tables[cpu];
…………………………
for (i = ZERO_P; i < ARRAY_SIZE(cplb_data); ++i) {
if (!cplb_data[i].valid)
continue ;
………………………… ..
for (j = INITIAL_T; j <= SWITCH_T; j++) {
switch (j) {
case INITIAL_T:
if (cplb_data[i].attr & INITIAL_T) {
t_i = &cplb.init_i;
t_d = &cplb.init_d;
process = 1;
} else
process = 0;
break ;
case SWITCH_T:
if (cplb_data[i].attr & SWITCH_T) {
t_i = &cplb.switch_i;
t_d = &cplb.switch_d;
process = 1;
} else
process = 0;
break ;
default :
process = 0;
break ;
}
if (!process)
continue ;
if (cplb_data[i].attr & I_CPLB)
__fill_code_cplbtab(t_i, i, a_start, a_end);
if (cplb_data[i].attr & D_CPLB)
__fill_data_cplbtab(t_d, i, a_start, a_end);
}
}
/* close tables */
close_cplbtab(&cplb.init_i);
close_cplbtab(&cplb.init_d);
cplb.init_i.tab[cplb.init_i.pos] = -1;
cplb.init_d.tab[cplb.init_d.pos] = -1;
cplb.switch_i.tab[cplb.switch_i.pos] = -1;
cplb.switch_d.tab[cplb.switch_d.pos] = -1;
}
整個流程挺簡單的,用兩重循環(huán)來配置 icplb_tables 、 dcplb_talbes 、 ipdt_tables 和 dpdt_tables 這四個全局的表。關(guān)鍵的表項生成由 __fill_code_cplbtab 和 __fill_data_cplbtab 兩個函數(shù)完成。
1.1 fill_cplbtab
這個是生成一個或者 CPLB 表項的最底層函數(shù), __fill_code_cplbtab 和 __fill_data_cplbtab 均調(diào)用此函數(shù)來生成 CPLB 表項。其實現(xiàn)為:
static unsigned short __init
fill_cplbtab( struct cplb_tab *table,
unsigned long start, unsigned long end,
unsigned long block_size, unsigned long cplb_data)
{
int i;
switch (block_size) {
case SIZE_4M:
i = 3;
break ;
case SIZE_1M:
i = 2;
break ;
case SIZE_4K:
i = 1;
break ;
case SIZE_1K:
default :
i = 0;
break ;
}
cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
while ((start < end) && (table->pos < table->size)) {
table->tab[table->pos++] = start;
if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
table->tab[table->pos++] =
cplb_data | CPLB_LOCK | CPLB_DIRTY;
else
table->tab[table->pos++] = cplb_data;
start += block_size;
}
return 0;
}
static u16 __init lock_kernel_check(u32 start, u32 end)
{
if ((end <= (u32) _end && end >= (u32)_stext) ||
(start <= (u32) _end && start >= (u32)_stext))
return IN_KERNEL;
return 0;
}
也就是說,當這個區(qū)域中含有內(nèi)核的代碼或者數(shù)據(jù)時,將會自動加上 CPLB_LOCK 和 CPLB_DIRTY 兩個屬性,即這個頁將不允許進行切換。
1.2 __fill_code_cplbtab
這個函數(shù)將生成一個或者多個的 icplb 表項。其實現(xiàn)為:
/* helper function */
static void __fill_code_cplbtab( struct cplb_tab *t, int i, u32 a_start, u32 a_end)
{
if (cplb_data[i].psize) {
fill_cplbtab(t,
cplb_data[i].start,
cplb_data[i].end,
cplb_data[i].psize,
cplb_data[i].i_conf);
#if defined (CONFIG_BFIN_ICACHE)
if (ANOMALY_05000263 && i == SDRAM_KERN) {
fill_cplbtab(t,
cplb_data[i].start,
cplb_data[i].end,
SIZE_4M,
cplb_data[i].i_conf);
} else
#endif
} else {
fill_cplbtab(t,
cplb_data[i].start,
a_start,
SIZE_1M,
cplb_data[i].i_conf);
fill_cplbtab(t,
a_start,
a_end,
SIZE_4M,
cplb_data[i].i_conf);
fill_cplbtab(t, a_end,
cplb_data[i].end,
SIZE_1M,
cplb_data[i].i_conf);
}
}
下圖給出了初始化完成后的寄存器配置:
1.2.1 L1 指令區(qū)域
當
{
.start = 0, /* dyanmic */
.end = 0, /* dynamic */
.psize = SIZE_4M,
.attr = INITIAL_T | SWITCH_T | I_CPLB,
.i_conf = L1_IMEMORY,
.d_conf = 0,
.valid = 1,
.name = "L1 I-Memory" ,
},
這個塊傳遞進來時, ICPLB_ADDR 的值對于 A 核為 0xffa0 0000 ,對于 B 核則為 0xff60 0000 。而 ICPLB_DATA 的值將為 0x0003 0007 ,這個值的意義是:
數(shù)據(jù)位 |
位 |
值 |
意義 |
CPLB_VALID |
0 |
1 |
Valid(enabled) CPLB entry |
CPLB_LOCK |
1 |
1 |
Locked, CPLB entry should not be replaced |
CPLB_USER_RD |
2 |
1 |
User mode read access permitted |
CPLB_LRUPRIO |
8 |
0 |
Low importance |
CPLB_MEM_LEV |
9 |
0 |
無效 |
CPLB_L1_CHBL |
12 |
0 |
Non cacheable in L1 |
PAGE_SIZE |
17-16 |
11 |
4M Page size |
1.2.2 內(nèi)核區(qū)域
當
{
.start = 0,
.end = 0, /* dynamic */
.psize = 0,
.attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
.i_conf = SDRAM_IGENERIC,
.d_conf = SDRAM_DGENERIC,
.valid = 1,
.name = "Kernel Memory" ,
},
這個塊傳遞進來時,如果設(shè)置的內(nèi)存大小為 64M ,它將連續(xù)創(chuàng)建 15 個入口項,其地址從 0 開始,按 4M 大小向上遞增,且每個入口項的 ICPLB_DATA 的值都為 0x0003 1205 ,這個值的意義是:
數(shù)據(jù)位 |
位 |
值 |
意義 |
CPLB_VALID |
0 |
1 |
Valid(enabled) CPLB entry |
CPLB_LOCK |
1 |
0 |
Unlocked, CPLB entry can be replaced |
CPLB_USER_RD |
2 |
1 |
User mode read access permitted |
CPLB_LRUPRIO |
8 |
0 |
Low importance |
CPLB_MEM_LEV |
9 |
padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-
發(fā)表評論
最新評論
|
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

評論