world leader in high performance signal processing
Trace: » load_application_running_in_bf561_core_b

Run program on BF561 Core B

The BF561 has two identical Blackfin cores, Core A and Core B. There are several ways to run a program on core B.

Load program using GDB

You can build a standalone program using bfin-elf-gcc toolchain. Then load the program to core B via GDB/JTAG. Please refer to example here.

Load standalone program to Core B in uClinux

You can create a ELF program to run on core B using bfin-elf-gcc. When linux booted on core A, you can use the utility corebld to load the binary to memory and start core B for execution.

By default, the linux kernel running on core A manages all HW resources, except L2 memory and L1 memory on core B. Core B can only utilize L2 and its L1 memory. You can change linux kernel setting to give control of some HW resource (like part of SDRAM) to core B of course. But please note core A and core B cannot share the same resource, since there is no synchronization between the two cores.

linker script for BF561

Linker script controls linker to create binary with expected memory layout. bfin-elf-gcc uses some arch specific options to make linker choose special linker script and start file. Here we care about two options: -mmulticore and mcoreb. The detailed meaning can be found in GCC manual . To find out the default linker script used:

host:~> bfin-elf-gcc -Wl,--verbose -mcpu=bf561-0.3 -mmulticore -mcoreb test_c.o -o test_c
GNU ld version 2.17
  Supported emulations:
   elf32bfin
   elf32bfinfd
opened script file /home/adam/workspace/toolchain/0612/bfin-elf/bin/../lib/gcc/bfin-elf/4.1.2/../../../../bfin-elf/lib/bf561b.ld
opened script file /home/adam/workspace/toolchain/0612/bfin-elf/bin/../lib/gcc/bfin-elf/4.1.2/../../../../bfin-elf/lib/bfin-common-mc.ld
using external linker script:
==================================================
/*
 * The common part of the default linker stripts for standalone executables
 * running on single core Blackfin processors.
 *
 * Copyright (C) 2008 Analog Devices, Inc.
 *
 * The authors hereby grant permission to use, copy, modify, distribute,
 * and license this software and its documentation for any purpose, provided
 * that existing copyright notices are retained in all copies and that this
 * notice is included verbatim in any distributions. No written agreement,
 * license, or royalty fee is required for any of the authorized uses.
 * Modifications to this software may be copyrighted by their authors
 * and need not follow the licensing terms described here, provided that
 * the new terms are clearly indicated on the first page of each file where
 * they apply.
 */

/* The default linker script, for single core blackfin standalone executables */
OUTPUT_FORMAT("elf32-bfin", "elf32-bfin",
	      "elf32-bfin")
OUTPUT_ARCH(bfin)
ENTRY(__start)
[snip]

In some case if the default linker script cannot meet your requirement, e.g, you would like core B to use some SDRAM, or L2 memory, you need to customize the linker script yourself.

corebld

we use a linux program corebld (and related driver /dev/coreb) to load a program to core B. corebld will read the program headers of the ELF binary and load related sections into memory, then start Core B.

Configure kernel to enable corebld:

Linux kernel:
BF561 Specific Configuration -->
   --- Core B Support
       Core B Support  --->
            [*] Enable Core B support
            [*] Enable Core B reset support

uClinux-dist:
Blackfin app programs  --->
    [*] BF561 Core B support tools

Here are some examples.

Load a simple C program

file: user/blkfin-apps/corebld/example/test_c.c

scm failed with exit code 1:
file does not exist in git

This can be built using:

bfin-elf-gcc -mcpu=bf561-0.3 -mmulticore -mcoreb -c test.c -o test.o
bfin-elf-gcc -mcpu=bf561-0.3 -mmulticore -mcoreb test_c.o -o  test_c

If we check the prgram headers of the test_c:

host:> bfin-elf-readelf -a
[snip]
Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xff400000 0xff400000 0x00840 0x0089c RW  0x1000
  LOAD           0x002000 0xff600000 0xff600000 0x00e82 0x00e82 R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .rodata .eh_frame .ctors .dtors .jcr .data .bss 
   01     .init .text .fini 

It shows test_c uses L1 Data and L1 instruction memory.

corebld loads test_c to memory according the the program headers:

root:/usr/coreb> corebld test_c                                             
wrote 2204 bytes to 0x0xff400000
wrote 3714 bytes to 0x0xff600000
Starting Core B 

Once Core B starts, it will load the first instruction from 0xff600000 and start execution. Usually, the first thing the program should do is initializing core B. The default initialization code is linked to test_c by bfin-elf-gcc, you may find it in toolchain/binutils-2.17/libgloss/bfin/basiccrt.S.

Load a simple C++ program

If we are to load a C++ program to coreb:

file: user/blkfin-apps/corebld/example/test_cpp.cpp

scm failed with exit code 1:
file does not exist in git

The default linker script puts everything into L1. However, the binary of test.cpp is too big to fit into L1. We have to customize the linker script, to make use of L2.

uclinux-dist/user/blkfin-apps/corebld/coreb.lds:
[snip]
 .text           :
  {
    *(.text .stub .text.* .gnu.linkonce.t.*)
    KEEP (*(.text.*personality*))
    /* .gnu.warning sections are handled specially by elf32.em.  */
    *(.gnu.warning)
  } >MEM_L2 =0

Another trick is we need to initialize core B before doing anything, so the first instruction (at 0xff600000) is to jump to the start code:

file: user/blkfin-apps/corebld/example/coreb_stub.S

scm failed with exit code 1:
file does not exist in git

We put this piece of code to L1:

uclinux-dist/user/blkfin-apps/corebld/coreb.lds:
[snip]
 .text_l1        :
  {
    *(.l1.text)
  } >MEM_L1_CODE =0

Build test.cpp using the customized link script:

bfin-elf-gcc -mcpu=bf561-0.3 -mmulticore -mcoreb -c coreb_stub.S -o coreb_stub.o
bfin-elf-g++ -mcpu=bf561-0.3 -mmulticore -mcoreb -c test.cpp -o test_cpp.o
bfin-elf-g++ -T coreb.lds -mcpu=bf561-0.3 -mmulticore -mcoreb test_cpp.o coreb_stub.o -o test_cpp

Check the program headers:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0xfeb00000 0xfeb00000 0x0bf5c 0x0c810 RWE 0x1000
  LOAD           0x00d000 0xff400000 0xff400000 0x00004 0x00004 RW  0x1000
  LOAD           0x00e000 0xff600000 0xff600000 0x0000a 0x0000a R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .init .text .fini .rodata .eh_frame .gcc_except_table .ctors .dtors .jcr .data .bss 
   01     .data_l1 
   02     .text_l1 

Now we load test_cpp using corebld:

root:/usr/coreb> corebld test_cpp
wrote 51216 bytes to 0x0xfeb00000
wrote 4 bytes to 0x0xff400000
wrote 10 bytes to 0x0xff600000
Starting Core B 

To check the result, we use a simple kernel module to read from L2 where test_cpp write into:

file: user/blkfin-apps/corebld/test_module/dualcore_test.c

scm failed with exit code 1:
file does not exist in git

The module writes “1” to location “0xfeb1fffc”, while test_cpp will change the value to “12”.

root:/usr/coreb> ls                                                             
dualcore_test.ko  test_c            test_cpp                                    
root:/usr/coreb> insmod dualcore_test.ko                                        
dualcore_test: module license 'unspecified' taints kernel.                      
Dual core test module inserted: set testarg = [1]                               
 @ [feb1fffc]                                                                   
root:/usr/coreb> corebld test_cpp                                               
wroteS5t2a6rbttisntg  xCxoer0e 00B                                              
                                                                                
wrote 4 bytes to 0x0xff400000                                                   
wrote 10 bytes to 0x0xff600000                                                  
root:/usr/coreb> cat /proc/coreb_testarg                                        
12

SMP

Complete Table of Contents/Topics