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 (GNU Debugger)/JTAG (Joint Test Action Group - low level interface to cpu). Please refer to example here. Load standalone program to Core B in uClinux You can create a ELF (Executable and Linking Format) 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 (synchronous dynamic random access memory (system memory))) 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 (synchronous dynamic random access memory (system memory)), 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 (Executable and Linking Format) 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 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: 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/ [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: We put this piece of code to L1: uclinux-dist/user/blkfin-apps/corebld/ [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 -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: 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