world leader in high performance signal processing
Trace: » example_on-chip_sram

Example Driver using On-Chip SRAM

We offer two methods to load driver module into L1 and L2 SRAM.

Attributes

Specify the proper function and variable attributes; here is a complete example:

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
 
int a __attribute__((l1_data)) = 1; /* Specify the global initialized variable 'a' saved in the L1 data bank A memory */
int b __attribute__((l1_data)); /* Specify the global uninitialized variable 'b' saved in L1 data bank A memory */
 
int c __attribute__((l1_data_B)) = 2; /* Specify the global initialized variable 'c' saved in L1 data bank B memory */
int d __attribute__((l1_data_B)); /* Specify the global uninitialized variable 'd' saved in L1 data bank B memory */
 
 
void l1_code_test(void)__attribute__((l1_text)); /* Sepcify the function 'l1_code_test' saved in L1 instruction memory */
 
int e __attribute__((l2_data)) = 3; /* Specify the global initialized variable 'e' saved in the L2  memory */
int f __attribute__((l2_bss)); /* Specify the global uninitialized variable 'f' saved in L2 memory */
 
void l2_code_test(void)__attribute__((l2)); /* Sepcify the function 'l2_code_test' saved in L2 memory */
 
 
void l1_code_test(void)
{
        printk(KERN_ALERT "L1 Code test: code function addr = 0x%p\n", l1_code_test);
}
 
void l1_data_a_test(void)
{
        printk(KERN_ALERT "L1 Data bank A test: data variable addr = 0x%p, data value is %d\n", &a, a);
}
 
void l1_bss_a_test(void)
{
        printk(KERN_ALERT "L1 BSS  bank A test: bss  variable addr = 0x%p, bss value is %d\n", &b, b);
}
 
void l1_data_b_test(void)
{
        printk(KERN_ALERT "L1 Data bank B test: data variable addr = 0x%p, data value is %d\n", &c, c);
}
 
void l1_bss_b_test(void)
{
        printk(KERN_ALERT "L1 BSS  bank B test: bss  variable addr = 0x%p, bss value is %d\n", &d, d);
}
 
void l2_code_test(void)
{
        printk(KERN_ALERT "L2 Code test: code function addr = 0x%p\n", l2_code_test);
}
 
void l2_data_test(void)
{
        printk(KERN_ALERT "L2 data test: data variable addr = 0x%p, data value is %d\n", &e, e);
}
 
void l2_bss_test(void)
{
        printk(KERN_ALERT "L2 BSS test: bss  variable addr = 0x%p, bss value is %d\n", &f, f);
}
 
static int hello_init(void)
{
        printk(KERN_ALERT "========Load module into L1 and L2 memory========\n");
        l1_code_test();
        l1_data_a_test();
        l1_bss_a_test();
        l1_data_b_test();
        l1_bss_b_test();
        l2_code_test();
        l2_data_test();
        l2_bss_test();
        return 0;
}
 
static void hello_exit(void)
{
        printk(KERN_ALERT "Goodbye, cruel world\n");
}
 
module_init(hello_init);
module_exit(hello_exit);

The running result is as follows:

root:~> insmod hello.ko
========Load module into L1 and L2 memory========
L1 Code test: code function addr = 0xffa00378
L1 Data bank A test: data variable addr = 0xff803e58, data value is 1
L1 BSS  bank A test: bss  variable addr = 0xff803e5c, bss value is 0
L1 Data bank B test: data variable addr = 0xff902580, data value is 2
L1 BSS  bank B test: bss  variable addr = 0xff902584, bss value is 0
L2 Code test: code function addr = 0xfeb00000
L2 Data test: data variable addr = 0xfeb03e58, data value is 3
L2 BSS  test: bss  variable addr = 0xfeb03e5c, bss value is 0

Linker Flags

You can use the following options with the linker command. Nothing needs to be changed in the driver. The following flags work:

  • --code-in-l1: put .text section into L1 instruction memory
  • --data-in-l1: put .data and .bss section into L1 data bank A memory

Here is the program “hello.c”

#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
 
int a=1;
int b;
 
void sram_code_test(void);
 
void sram_code_test(void)
{
        printk(KERN_ALERT "Code test: code function addr = 0x%p\n", sram_code_test);
}
 
void sram_data_test(void)
{
        printk(KERN_ALERT "Data test: data variable addr = 0x%p, data value is %d\n", &a, a);
}
 
void sram_bss_test(void)
{
        printk(KERN_ALERT "BSS  test: bss  variable addr = 0x%p, bss value is %d\n", &b, b);
}
 
static int hello_init(void)
{
        printk(KERN_ALERT "========Load module into L1 or L2 memory========\n");
        sram_code_test();
        sram_data_test();
        sram_bss_test();
        return 0;
}
 
static void hello_exit(void)
{
        printk(KERN_ALERT "Goodbye, cruel world\n");
}
 
module_init(hello_init);
module_exit(hello_exit);

The Makefile is simple, one line is enough:

obj-m += hello.o

The following instruction tell you how to generate 'hello.ko':

$ make -C /home/aubrey/cvs/kernel/new/uClinux-dist/linux-2.6.x SUBDIRS=$PWD modules
make: Entering directory `/home/aubrey/cvs/kernel/new/uClinux-dist/linux-2.6.x'
  CC [M]  /tftpboot/module-example/hello.o
  Building modules, stage 2.
  MODPOST
  CC      /tftpboot/module-example/hello.mod.o
  LD [M]  /tftpboot/module-example/hello.ko
make: Leaving directory `/home/aubrey/cvs/kernel/new/uClinux-dist/linux-2.6.x'

Here we get the hello.ko, now we re-link the object file to add the specific flags to the driver module:

$ bfin-uclinux-ld --code-in-l1 --data-in-l1 -r -o hello.ko hello.o hello.mod.o

Make sure the flags have been added

$ bfin-uclinux-readelf -h hello.ko
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Analog Devices Blackfin
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          1004 (bytes into file)
  Flags:                             0x30, code in L1, data in L1 <===================== Here, make sure the flags are set
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         13
  Section header string table index: 10

The running result is as follows:

root:~> insmod hello.ko
========Load module into L1 or L2 memory========
Code test: code function addr = 0xffa003cc
Data test: data variable addr = 0xff803e58, data value is 1
BSS  test: bss  variable addr = 0xff803e5c, bss value is 0