您的位置:首页 > 其它

再读内核存储管理(8):片内SRAM的使用

2008-06-17 14:24 405 查看
快乐虾
http://blog.csdn.net/lights_joy/
lights@hb165.com
本文适用于
ADI bf561 DSP
uclinux-2008r1-rc8 (移植到vdsp5)
Visual DSP++ 5.0


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

1.1 片内SRAM的使用
BF561内部带有高达328K的片内SRAM,那么在内核中是如何使用这些东西的呢?
1.1.1 SRAM信息描述
BF561的片内SRAM由好几个不连续的块组成,内核使用了l1_sram_piece这个结构体进行描述:
/* the data structure for L1 scratchpad and DATA SRAM */
struct l1_sram_piece {
void *paddr;
int size;
int flag;
pid_t pid;
};
其中的flag可以取以下几个值:
#define SRAM_SLT_NULL 0
#define SRAM_SLT_FREE 1
#define SRAM_SLT_ALLOCATED 2
此外还有一个相关的宏定义:
#define CONFIG_L1_MAX_PIECE 16 // L1 SRAM分为个小块
1.1.2 scratch pad SRAM
1.1.2.1 初始化:l1sram_init
在mem_init函数中(arch/blackfin/mm/init.c)有这样的调用:
l1sram_init();
此函数位于arch/blackfin/mm/blackfin_sram.c中:
static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];

/* L1 Scratchpad SRAM initialization function */
void __init l1sram_init(void)
{
printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB/n",
L1_SCRATCH_LENGTH >> 10);

memset(&l1_ssram, 0x00, sizeof(l1_ssram));
l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
l1_ssram[0].size = L1_SCRATCH_LENGTH;
l1_ssram[0].flag = SRAM_SLT_FREE;

/* mutex initialize */
spin_lock_init(&l1sram_lock);
}
在这里有以下定义:
#define L1_SCRATCH_START 0xFFB00000
#define L1_SCRATCH_LENGTH 0x1000
实际上这个函数就是记录了scratch pad SRAM这4K片内SRAM的信息。
1.1.2.2 内存分配:l1sram_alloc
这个函数的实现如下:
/* L1 Scratchpad memory allocate function */
void *l1sram_alloc(size_t size)
{
unsigned flags;
void *addr;

/* add mutex operation */
spin_lock_irqsave(&l1sram_lock, flags);

addr = _l1_sram_alloc(size, l1_ssram, ARRAY_SIZE(l1_ssram));

/* add mutex operation */
spin_unlock_irqrestore(&l1sram_lock, flags);

return addr;
}
跟踪_l1_sram_alloc:
/* L1 memory allocate function */
static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
{
int i, index = 0;
void *addr = NULL;

if (size <= 0)
return NULL;

/* Align the size */
size = (size + 3) & ~3;

/* not use the good method to match the best slot !!! */
/* search an available memory slot */
for (i = 0; i < count; i++) {
if ((pfree[i].flag == SRAM_SLT_FREE)
&& (pfree[i].size >= size)) {
addr = pfree[i].paddr;
pfree[i].flag = SRAM_SLT_ALLOCATED;
pfree[i].pid = current->pid;
index = i;
break;
}
}
if (i >= count)
return NULL;

/* updated the NULL memory slot !!! */
if (pfree[i].size > size) {
for (i = 0; i < count; i++) {
if (pfree[i].flag == SRAM_SLT_NULL) {
pfree[i].pid = 0;
pfree[i].flag = SRAM_SLT_FREE;
pfree[i].paddr = addr + size;
pfree[i].size = pfree[index].size - size;
pfree[index].size = size;
break;
}
}
}

return addr;
}
从上述函数可以看出,它的分配策略很简单,就是从下往上搜索,找到第一个足够大的块,从这个块内取出指定大小的空间,然后将剩余的空间用一个空闲的描述结构体来表示。由于CONFIG_L1_MAX_PIECE这个宏定义的关系,这个空间可以分配的块数是有限制的。当然在内核中实际也不会将它分成这么多块,毕竟总共才4K的空间。
在mem_init函数中,有这样一个调用:
/* Allocate this once; never free it. We assume this gives us a
pointer to the start of L1 scratchpad memory; panic if it
doesn't. */
tmp = (unsigned long)l1sram_alloc(sizeof(struct l1_scratch_task_info));
这是第一个使用l1sram_alloc的地方,因此在Scratchpad SRAM的最开始就是一个l1_scratch_task_info结构体,通过访问指定的地址(L1_SCRATCH_START)就可以访问这个全局变量。

1.1.3 l1_data_sram_init
在mem_init函数中(arch/blackfin/mm/init.c)有这样的调用:
l1_data_sram_init();
此函数位于arch/blackfin/mm/blackfin_sram.c中:
static struct l1_sram_piece l1_data_A_sram[CONFIG_L1_MAX_PIECE];
static struct l1_sram_piece l1_data_B_sram[CONFIG_L1_MAX_PIECE];
void __init l1_data_sram_init(void)
{
memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
l1_data_A_sram[0].paddr = (void *)L1_DATA_A_START +
(_ebss_l1 - _sdata_l1);
l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
l1_data_A_sram[0].flag = SRAM_SLT_FREE;

printk(KERN_INFO "Blackfin Data A SRAM: %d KB (%d KB free)/n",
L1_DATA_A_LENGTH >> 10, l1_data_A_sram[0].size >> 10);

memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
l1_data_B_sram[0].paddr = (void *)L1_DATA_B_START +
(_ebss_b_l1 - _sdata_b_l1);
l1_data_B_sram[0].size = L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
l1_data_B_sram[0].flag = SRAM_SLT_FREE;

printk(KERN_INFO "Blackfin Data B SRAM: %d KB (%d KB free)/n",
L1_DATA_B_LENGTH >> 10, l1_data_B_sram[0].size >> 10);

/* mutex initialize */
spin_lock_init(&l1_data_sram_lock);
}
在这里有:
#define L1_DATA_A_START 0xFF800000
#define L1_DATA_B_START 0xFF900000
#define L1_DATA_A_LENGTH (0x8000 - 0x4000)
#define L1_DATA_B_LENGTH (0x8000 - 0x4000)
由于启用了cache,因此可用的L1_DATA_A和L1_DATA_B都只有16K可用。
这个函数也只是简单记录了这两个SRAM块的信息。

1.1.4 l1_inst_sram_init
在mem_init函数中(arch/blackfin/mm/init.c)有这样的调用:
l1_inst_sram_init();
此函数位于arch/blackfin/mm/blackfin_sram.c中:
static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
void __init l1_inst_sram_init(void)
{
memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
l1_inst_sram[0].paddr = (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
l1_inst_sram[0].flag = SRAM_SLT_FREE;

printk(KERN_INFO "Blackfin Instruction SRAM: %d KB (%d KB free)/n",
L1_CODE_LENGTH >> 10, l1_inst_sram[0].size >> 10);

/* mutex initialize */
spin_lock_init(&l1_inst_sram_lock);
}
在这里有:
#define L1_CODE_START 0xFFA00000
#define L1_CODE_LENGTH 0x4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: