Chinaunix首页 | 论坛 | 博客
  • 博客访问: 211818
  • 博文数量: 93
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 978
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-10 15:46
个人简介

青春无悔

文章分类

全部博文(93)

文章存档

2015年(16)

2014年(77)

我的朋友

分类: 嵌入式

2014-11-10 16:37:52

系统配置:include/bf518f-ezbrd.h

启动顺序如下:

  • cpu/blackfin/initcode.c (first if booting from LDR, second otherwise)
  • cpu/blackfin/start.S
  • cpu/blackfin/cpu.c
  • lib_blackfin/board.c

LDR

Since the LDR format has the ability to execute small pieces of code (init blocks), as well as load chunks of code into specific memory addresses, the startup sequence process is streamlined nicely. For a general overview of the LDR process, please see .

  1. Boot ROM loads and executes LDR init blocks: cpu/blackfin/initcode.c:initcode()
    1. U-Boot programs clock/memory settings (PLL/EBIU) and interrupt sources (IWR/SIC_IWR)
  2. Boot ROM loads U-Boot LDR into external memory
  3. Boot ROM clears U-Boot BSS section
  4. Boot ROM jumps to start of U-Boot: cpu/blackfin/start.S:_start()
  5. U-Boot starts up like normal

Common

Here we will start at the ELF entry point of U-Boot which is cpu/blackfin/start.S:_start(). When booting in bypass mode (parallel flash), or using the U-Boot gocommand, this is the first thing executed.

  1. U-Boot starts at ELF entry point: cpu/blackfin/start.S:_start()
    1. Initialize stack to L1 scratch space
    2. Initialize hardware watchdog (if enabled)
    3. Disable nested interrupts and enable CYCLES (which the udelay() function needs)
    4. Initialize minimal C runtime environment
    5. Call cpu/blackfin/initcode.c:initcode() (only in bypass mode)
      1. Program clock/memory settings (PLL/EBIU) and interrupt sources (IWR/SIC_IWR)
    6. Relocate U-Boot from point of execution to external memory monitor base
      1. only as needed (according to how U-Boot was started)
      2. only copies U-Boot to monitor base -- does not start executing there
    7. Call memset() to zero BSS
    8. Set stack to configured address (default is external memory)
    9. Lower self to the lowest Interrupt level (IVG15)
      1. this is when U-Boot starts executing at configured memory monitor base
    10. Jump to the next step …
  2. U-Boot initializes the cpu: cpu/blackfin/cpu.c:cpu_init_f()
    1. Relocate L1 functions/data from external memory into L1 memory (only as needed)
    2. Turn on hardware trace buffer (if enabled via debug dumping)
    3. Enable reset on double fault (if panic hang is disabled)
    4. Jump to the next step …
  3. U-Boot initializes important services: arch/blackfin/lib/board.c:board_init_f()
    1. Initialize the Instruction and Data CPLB tables
    2. Initialize exception callbacks
    3. Turn on Instruction and Data caches (if enabled)
    4. Initialize the global and board data structures
    5. Initialize IRQ callbacks
    6. Initialize the default environment
    7. Initialize the console baudrate
    8. Initialize the console
    9. Call board-specific checkboard()
      1. Do whatever board-specific very early things
    10. Initialize the Blackfin on-chip RTC
    11. Initialize the core timers
    12. Jump to the next step …
  4. U-Boot initializes remaining services:arch/blackfin/lib/board.c:board_init_r()
    1. Initialize malloc subsystem
    2. Initialize parallel flash (if enabled)
    3. Initialize SPI flash (if enabled)
    4. Initialize NAND flash (if enabled)
    5. Relocate saved environment from flash (or wherever configured)
    6. Initialize common U-Boot devices
    7. Initialize common U-Boot function jumptable
    8. Call board-specific misc_init_r()
      1. Do whatever board-specific misc/late init things
    9. Initialize the network (if enabled)
    10. Initialize I2C (if enabled)
    11. Jump to the next step …
  5. U-Boot executes common code:common/main.c: main_loop()
    1. See autoboot / U-Boot console / whatever like normal

Debug Options

All of these options are placed into your board configuration file. They require a CONFIG_ prefix to be added (it has been omitted here for readability).

DEBUG_DUMP

When an unhandled exception or interrupt occurs, the state of the processor will be dumped to the console as well as the hardware trace buffer. You can use this information to easily locate the code that triggered the exception.

For more in-depth information for how to use the hardware trace effectively as well as some examples, see the  document.

This option adds little overhead in terms of code size (1 kB) and adds no runtime overhead as it is only executed when an unhandled exception occurs -- which should never happen in at runtime.

DEBUG_DUMP_SYMS

The normal dump output will only include undecoded addresses. You need to translate them by hand to the actual symbols by comparing them to the objdump output of the U-Boot ELF. This can get tedious very quickly while doing development, so this option will embed the symbol table in the U-Boot binary. When a dump occurs, the addresses will be translated automatically so the output will include both the address and the associated symbol.

This option adds quite a bit of overhead in terms of code size (11 kB) but adds no runtime overhead as it is only executed by the dump code mentioned above.

DEBUG_EARLY_SERIAL

This will turn on serial output as early as possible (almost at power on) so that status messages will be constantly written to the UART console. Additional status messages will also be enabled at significant steps in the booting process.

The actual early implementation details can be found in the cpu/blackfin/serial.h and cpu/blackfin/serial.c files.

This option adds little overhead in terms of code size (2 kB) but adds runtime overhead and output that is really only suitable for debugging.

DEBUG_NULL_PTR

If you have code that may be accessing initialized data (or NULL pointers), then you can catch them. This will cover the start of memory (first 1kB) with two CPLB's. That way, any memory access to that region (data or instruction) will cause an exception. Any unhandled exceptions will cause a processor dump (see the DEBUG_DUMPoptions).

Keep in mind that any valid accesses will also be flagged, so this should only be enabled during development. You will be unable to use standard U-Boot commands such as memory display, copy, fill, etc… on the protected memory region.

This option adds little overhead (~70 bytes), but prevents the start of memory from being used.

PANIC_HANG

This option is pretty straight forward. Upon a crash that would automatically reset the board, the board will instead hang and constantly execute the emuexcpt instruction. If a JTAG ICE is hooked up, it will automatically be triggered.

HW_WATCHDOG

While not strictly a debug option, it can be quite useful while debugging remotely. This will enable the on-chip Blackfin hardware watchdog right after power on, and then common pieces of U-Boot will routinely poke it. If some piece of code gets hung up, the watchdog will reset the processor.

HW_WATCHDOG_TIMEOUT_INITCODE

If you're booting an LDR image, you should use a “largish” timeout value here as the processor will not be able to poke the watchdog until the LDR has finished completely loading. When booting over the UART or slow SPI devices, it can take a few seconds before U-Boot can take over. The default timeout is set to 20 seconds.

HW_WATCHDOG_TIMEOUT_START

Once U-Boot has started executing (before initialization/relocation), the watchdog will be programmed with a 5 second timeout. If your initialization process can take a while, increase this timeout as needed.

Troubleshooting

Memory Timings

The most common problem people hit is external memory setup. Either the hardware is not solid and so cannot run at all or at the max theoretical frequency, or the timings are wrong for the specified SCLK and memory part.

This is often observed when enabling early serial debug and then only seeing a string of letters that end in >.

Rather than figure out the timings yourself, read the  page (and in particular, read the spreadsheet at the bottom).

If things still aren't working, slow down the timings from whatever the memory datasheet says. Once you have a known working configuration, you can try speeding things back up until they fail, and then reviewing the hardware signals to fix any problems there.

It might also be helpful to connect a JTAG device and examine external memory to make sure the contents match exactly the u-boot binary that should be there. Failing memory devices/timings will show random bit errors.

JTAG Loading

Sometimes it is useful to load U-Boot directly up into external memory and bypass the flash programming process. Here are a few notes to show you how with GDB and aJTAG connection. By themselves, these commands will not work. You have to connect to a remote jtag target first, so see the  if you need more information.

Initcode

First, since GDB will load things directly into external memory, we need to make sure external memory has been set up properly first. Normally this is handled by the Boot ROM calling our initcode, but since we are bypassing the Boot ROM, we need to load it by hand.

Start with a simple piece of code like so (call it init.S):

#include /blackfin.h> .global __start
__start: sp.l = LO(L1_SRAM_SCRATCH_END - 20); sp.h = HI(L1_SRAM_SCRATCH_END - 20); call _initcode;1: emuexcpt; jump 1b;.size __start, .-__start

Then just link it against the initcode to produce a standalone ELF like so (make sure to replace the -mcpu argument with the appropriate value for your board):

$ bfin-elf-gcc -nostartfiles init.S arch/blackfin/cpu/initcode.o -o init.elf -Iinclude -D__ASSEMBLY__ -mcpu=bf547 

GDB Load

Now, armed with these two ELF's (init.elf and u-boot), we can get things running with GDB.

The important commands we run are:

  1. set remotetimeout 300 - do not time out when working with slow JTAG devices
  2. load init.elf - load the initcode into on-chip memory …
  3. continue - … and execute it -- the emuexcpt instruction we used earlier will automatically signal the JTAG when it is done
  4. symbol-file u-boot - you may need this when call memset fails …
  5. load u-boot - load u-boot into the right place …
  6. call memset(&_bss_vma, 0, &_bss_len) - clear the BSS since GDB will not do it for us …
  7. continue - … and start executing U-Boot

Example

Here is a sample run. Note that the addresses and sizes may be significantly different from your setup -- that is perfectly normal!

If you're using this procedure repeatedly, enter this sequence in .gdbinit (working directory)

$ bfin-elf-gdb ./u-boot (gdb) set remotetimeout 300 ... connect to your jtag device ...

(gdb) load init.elf Loading section .text, size 0x32c lma 0xffa00000
Start address 0xffa0031c, load size 812
Transfer rate: 1676 bits/sec, 812 bytes/write.
(gdb) c Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0xffa00328 in ?? ()

(gdb) load u-boot Loading section .text, size 0xa778 lma 0xfeb00000
Loading section .rodata, size 0x31e4 lma 0xfeb0a778
Loading section .data, size 0x2300 lma 0xfeb0d95c
Loading section .u_boot_cmd, size 0x280 lma 0xfeb0fc5c
Loading section .text_l1, size 0x40 lma 0xfeb0fedc
Start address 0xfeb00000, load size 65308
Transfer rate: 7829 bits/sec, 9329 bytes/write.
(gdb) call memset(&_bss_vma, 0, &_bss_len) (note for BF609 board you may skip this)
warning: Unable to restore previously selected frame.
$6 = 0xfeb0ff1c
Current language:  auto; currently asm
(gdb) c Continuing.


Blackfin U-Boot Memory Layout

Here we show a typical system that has 4megs of external memory. The memory regions above the asynchronous memory will differ depending on your Blackfin variant, so consult the appropriate datasheet for exact addresses if you really want to know.

0xffe00000: Blackfin Core MMRs
 ...
0xffc00000: Blackfin System MMRs
 ...
0xef000000: Boot ROM jump table
 ...
0x20000000: Start of asynchronous memory
 ...
0x01000000: CONFIG_SYS_MAX_RAM_SIZE:  End of external memory
0x00f80000: CONFIG_SYS_MONITOR_BASE:  Relocated U-Boot image
0x00f20000: CONFIG_SYS_MALLOC_BASE:   U-Boot's dynamic heap for malloc()
0x00f1ffb0: CONFIG_SYS_GBL_DATA_ADDR: U-Boot's static "global data" region
0x00f1ff70: CONFIG_SYS_BD_INFO_ADDR:  U-Boot's static "board info" region
0x00f1ff6c: CONFIG_STACKBASE:         U-Boot's stack: grows "down"
0x00f1df70: CONFIG_SYS_MEMTEST_END:   End address for U-Boot's memory test code
 ...
0x00000000: CONFIG_SYS_SDRAM_BASE/CONFIG_SYS_MEMTEST_START: Start of external memory

If you only define the relevant size's (CONFIG_SYS_MONITOR_LEN and CONFIG_SYS_MALLOC_LEN), then you will get a memory layout such as this automatically.

If you start relocating pieces though (such as putting the global data or stack into on-chip memory), then you will need to define all of the memory regions accordingly. Otherwise the mismatch of custom addresses and automatic placement will result in an invalid memory layout.

Configuration

Review the common documentation (the top level README file) for more information on these.

CONFIG_SYS_MONITOR_BASE  - Base address where U-Boot executes
CONFIG_SYS_MONITOR_LEN   - Size of the monitor region

CONFIG_SYS_MALLOC_BASE   - Base address of U-Boot's dynamic heap
CONFIG_SYS_MALLOC_LEN    - Size of the heap

CONFIG_SYS_GBL_DATA_ADDR - Base address of U-Boot's global data
GENERATED_BD_INFO_SIZE   - Size of the global data w/padding (calculated automatically)

CONFIG_SYS_BD_INFO_ADDR  - Base address of U-Boot's global data
GENERATED_BD_INFO_SIZE   - Size of the board info w/padding (calculated automatically)

CONFIG_STACKBASE         - Base address of U-Boot's stack (which grows down)

/* These are Blackfin specific */
CONFIG_LINUX_CMDLINE_ADDR - Base address for the Linux kernel command line
CONFIG_LINUX_CMDLINE_SIZE - Largest string that may be passed


1.先看编译后生成的./u-boot.lds文件


1.先看编译后生成的./u-boot.lds文件

01OUTPUT_ARCH(bfin)
02MEMORY
03{
04 ram : ORIGIN = ((16 * 1024 * 1024) - (512 * 1024)), LENGTH = (512 * 1024)
05 l1_code : ORIGIN = 0xFFA00000, LENGTH = (0xFFA07FFF - 0xFFA00000 + 1)
06 l1_data : ORIGIN = 0xFF900000, LENGTH = (0xFF903FFF - 0xFF900000 + 1)
07}
08ENTRY(_start)
09SECTIONS
10{
11 .text.pre :
12 {
13  arch/blackfin/cpu/start.o (.text .text.*)
14 
15 } >ram
16 .text.init :
17 {
18  arch/blackfin/cpu/initcode.o (.text .text.*)
19 } >ram
20 __initcode_lma = LOADADDR(.text.init);
21 __initcode_len = SIZEOF(.text.init);
22 .text :
23 {
24  *(.text .text.*)
25 } >ram
26 .rodata :
27 {
28  . = ALIGN(4);
29  *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*)))
30  . = ALIGN(4);
31 } >ram
32 .data :
33 {
34  . = ALIGN(4);
35  *(.data .data.*)
36  *(.data1)
37  *(.sdata)
38  *(.sdata2)
39  *(.dynamic)
40  CONSTRUCTORS
41 } >ram
42 .u_boot_list : {
43  KEEP(*(SORT(.u_boot_list*)));
44 } >ram
45 .text_l1 :
46 {
47  . = ALIGN(4);
48  __stext_l1 = .;
49  *(.l1.text)
50  . = ALIGN(4);
51  __etext_l1 = .;
52 } >l1_code AT>ram
53 __text_l1_lma = LOADADDR(.text_l1);
54 __text_l1_len = SIZEOF(.text_l1);
55 ASSERT (__text_l1_len <= (0xFFA07FFF - 0xFFA00000 + 1), "L1 text overflow!")
56 .data_l1 :
57 {
58  . = ALIGN(4);
59  __sdata_l1 = .;
60  *(.l1.data)
61  *(.l1.bss)
62  . = ALIGN(4);
63  __edata_l1 = .;
64 } >l1_data AT>ram
65 __data_l1_lma = LOADADDR(.data_l1);
66 __data_l1_len = SIZEOF(.data_l1);
67 ASSERT (__data_l1_len <= (0xFF903FFF - 0xFF900000 + 1), "L1 data overflow!")
68 .bss :
69 {
70  . = ALIGN(4);
71  *(.sbss) *(.scommon)
72  *(.dynbss)
73  *(.bss .bss.*)
74  *(COMMON)
75  . = ALIGN(4);
76 } >ram
77 __bss_vma = ADDR(.bss);
78 __bss_len = SIZEOF(.bss);
79}
1.根目录下的u-boot.lds文件为arch/blackfin/cpu/u-boot.lds文件转换后生成。
2.
1)01说明CPU的体系结构;
2)02~07指定U-Boot的内存环境;在此注意到RAM资源使用的是SDRAM的最高位512 KByte;
3)08指定入口地址;
4)09~79是SECTIONS指定分配;
5)11~15主要是star文件的text文件映射到RAM;
6)16~21主要是对initcode代码的text段分配,并且赋值两个变量
7)22~25其他程序的text段指定映射至RAM;
8)26~31指定只读数据的映射至RAM;
9)32~41只读读写数据的映射至RAM;
10)42~44只读u_boot_list数据映射至RAM;
11)45~54映射text_l1至指定的L1;赋值两个变量;
12)55判断是否L1 Text的溢出;
13)56~66因素data_l1至指定的L1;赋值两个变量;
14)67判断是否L1 Data的溢出;
15)68~78指定bss段映射至RAM区域。

2.arch/blackfin/cpu/start.s的分析

3.arch/blackfin/cpu/initcode.c的分析

阅读(850) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~