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

 
快乐虾
http://blog.csdn.net/lights_joy/
lights@hb165.com
  
 
本文适用于
ADI bf561 DSP
uclinux-2008r1-rc8 (移植到vdsp5)
Visual DSP++ 5.0
  
 
欢迎转载,但请保留作者信息
 
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 分为个小块
在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的信息。
这个函数的实现如下:
/* 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)就可以访问这个全局变量。
 
在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块的信息。
 
在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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值