uclinux内核中CPLB表项的生成

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

本文适用于

ADSP-BF561

优视BF561EVB开发板

uclinux-2008r1.5-rc3 (smp patch, 移植到vdsp5)

Visual DSP++ 5.0(update 5)

欢迎转载但请保留作者信息

本文讨论链接:http://www.bfin-tools.org/bbs/viewthread.php?tid=23&extra=

cplb表的生成由generate_cpl_tables函数完成:

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函数完成。它的主体结构如下:

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;

}

整个流程挺简单的,用两重循环来配置icplb_tablesdcplb_talbesipdt_tablesdpdt_tables这四个全局的表。关键的表项生成由__fill_code_cplbtab__fill_data_cplbtab两个函数完成。

1.1 fill_cplbtab

这个是生成一个或者CPLB表项的最底层函数,__fill_code_cplbtab__fill_data_cplbtab均调用此函数来生成CPLB表项。其实现为:

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;

}

也就是说,当这个区域中含有内核的代码或者数据时,将会自动加上CPLB_LOCKCPLB_DIRTY两个属性,即这个页将不允许进行切换。

1.2 __fill_code_cplbtab

这个函数将生成一个或者多个的icplb表项。其实现为:

/* 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指令区域

{

.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,这个值的意义是:

数据位

意义

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 内核区域

{

.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",

},

这个块传递进来时,如果设置的内存大小为64M,它将连续创建15个入口项,其地址从0开始,按4M大小向上递增,且每个入口项的ICPLB_DATA的值都为0x0003 1205,这个值的意义是:

数据位

意义

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-
分享到:
评论
xiaoer_1982
  • 浏览: 782189 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

你可能感兴趣的:(数据结构,PHP,J#,Access,bbs)