I've been having some issues debugging U-Boot. I believe it is due to a RAM configuration error, but I would like to get some clarity on it.
My methodology for testing is below, and is based on these instructions for the BeagleBone Black
Load board with no memory/image
load u-boot-spl.bin to the SRAM memory via JTAG at the proper address specified in processor manual (TI AM5728, so address 0x40300000) and load u-boot-spl ELF symbols
Set PC register to the start address of U-Boot-SPL (0x40300000)
Run SPL, and pause after I receive a message such as this one:
At this point I know that U-Boot has relocated from the SRAM to the DDR3 RAM due to spl_relocate_stack_gd() being already called.
Load U-Boot via JTAG, the PC automatically changes to address 0x80800000 due to having the context of the relocation.
From here I would resume the application to get to the U-Boot console and get the gd->relocaddr from bdinfo, but even single stepping into the program results in U-Boot becoming unresponsive, and the PC moving to address 0x0000000C.
My guess is that this is because the SDRAM was not configured correctly, resulting in an erroneous read, considering that the first instruction is a branch, which could result in the erroneous PC value.
The trouble is that when I try this with a TI AM5728 EVM, with the known-correct RAM configs, the same thing happens. But when I start the EVM with a SD card that only has u-boot.img and MLO, I reach the U-Boot command line.
Am I going crazy with the notion that this could be the RAM? Since I have evidence of a working RAM configuration for the same SoC doing the same behaviour, or is there something else that I am missing? printf()'s don't seem to work, and enabling the DEBUG macro does not print anything to console, either.
Related
I am trying to link my project for a custom embedded system where a RAM chip
is mounted at address 0x20000000.
I am changed my linker file to point data to this area and it compiles and maps the data properly as verified in map file.
But when I connect gdb to QEMU and try to load the executable it gives an error.
It seems as if, QEMU is protecting area below 0x40000000 as it is thinking area below this maybe used by some kernel?
If I change the address above 0x4XXX_XXXX for my RAM things work.
How to go about it?
It seems as if, QEMU is protecting area below 0x40000000 as it is
thinking area below this maybe used by some kernel?
Initial machine state in softmmu QEMU normally does not depend on the guest code. But the machine model that you use may not have physical memory at 0x20000000.
You can check that using gdb monitor info mtree command.
How to go about it?
You can add a model of your custom embedded system to QEMU and place physical memory at 0x20000000.
I'm trying to boot a kernel (extracted from a firmware) using QEMU.
Qemu emulation seems to start at 0x0.
The problem is that the memory from 0x0 to 0x04000000 is only filled with 0.
How can i debug the bootloader?
You don't say what your command line is. The address where QEMU starts execution depends on many things:
the guest CPU architecture
which board model you are emulating
whether you passed QEMU a BIOS image file
the file format of any file passed to -kernel (ELF, plain kernel image, uImage, etc)
In general, though, you should not expect to be able to pull a random kernel image out of a firmware dump for a piece of Arm hardware and run it under QEMU. This is because every Arm board or machine is different -- RAM may be in different places, the devices such as the serial port are at different addresses, and so on -- and the kernel will only boot on systems which it has been compiled to support. The chances are very high that (a) QEMU does not have a specific emulation of the bit of hardware that the firmware dump is for and (b) the kernel from the firmware has not been built to also run on any of the board types that QEMU does support. So it will almost certainly simply crash very early on in bootup without producing any output.
If you want to debug what's going on in early bootup, the best approach is probably to use QEMU's built in gdbstub, and attach a guest-architecture-aware gdb to it. You may also find QEMU's internal logging via the '-d' option useful, though it requires some familiarity with how QEMU works to make sense of the output.
On AMVv7, I use U-boot as my bootloader.
Question
Once it has initialized my board, and put itself in the ram, can my code overwrite it?
(I will provide my vector table, my TLB logic and so on).
I read that a cpu reset won't need the full initialization u-Boot does.
The plan is to use U-boot and to ditch it completely once it has done its work (saving me to do it in the first place) and take full control of the board, without sacrificing any bit of ram.
What is the problem with that approach (if there is one)?
What you want to do is fine. This is for example how the Linux kernel operates as (generally speaking) nothing of U-Boot is around after U-Boot starts execution of whatever it has been told to load and execute.
If your application capable of handling your board functionality,then no need of worrying about u-boot, because once it execute load and execute, this RAM location is usable memory.
If you run your standalone program under u-boot program space, it cannot be overwrite by your program. if you try to overwrite, the board will reboot.
I'm working on a custom Cortex-M3-based device and I need to implement in-application programming (IAP) mechanism so that it will be possible to update the device firmware without JTAG (we'll use TFTP or HTTP instead). While the IAP-related code examples available from ST Microelectronics are clear enough to me, I don't really understand how the re-flashing works.
As far as I understand, the instructions are fetched by the CPU from the Flash through the ICode bus (and the prefetch block, of course). So, here's my pretty silly question: why doesn't the running program get corrupted while it re-flashes itself (i.e. changes the Flash memory from which it is being run)?
A common solution is to have a small reserved area in the flash, where the actual flashing program is stored. When new firmware has been downloaded just make a jump to the code in this area.
Of course, this small area is not overwritten when flashing firmware, it can only be done by other means (like JTAG). So make sure this flashing-program works good to start with. :)
I'm not familiar with STM implementation, but in NXP chips the IAP routines are stored in a separate, reserved ROM area which can't be erased by user code.
If you're implementing the flash writing code yourself by using HW registers directly, you need to either make sure that it doesn't touch the sectors it's running from, or runs from the RAM.
Now a days many micro-controllers supporting IAP, that it is possible to program its flash memory while program execution in the same flash.
For IAP, program memory in the flash may be divided into 2 parts, one executable & other backup parts.
Generally we program the flash memory at a location (say, part-1) through JTAG, whose firmware version is 0.01. For IAP, i.e, program the flash in another part (part-2) while code is executing, corresponding API's should be provide in firmware version 0.01, which helps to program the flash part-2, After completion of programming successfully firmware version will be updated as 0.02. Upon processor restarts, program execution jumps to latest firmware by checking firmware version at initialization.
The part where the firmware is executing is called executable part, and other is back-up. why it is called back-up mean, suppose if there exists any firmware corruption while programming, firmware version will not update & upon restart, program control will automatically jumps back to back-up firmware after checking version number.
Another good way to do it is using custom made bootloader. However STM IAP is not stored in Flash so it can not be overwritten by it self. What generally people do is to spilt the flash in two parts , one is reserved for Custom made Bootloader and Another is for application. Bootloader makes sure that it does not write to its own assigned area. Bootloader can be programmed through JTAG and later application can utilize bootloader to program itself.
As far as I understand, the instructions are fetched by the CPU from the Flash through the ICode bus (and the prefetch block, of course). So, here's my pretty silly question: why doesn't the running program get corrupted while it re-flashes itself (i.e. changes the Flash memory from which it is being run)?
This is because, in general case writing/programming to flash memory is not allowed while you are reading from it(i.e executing code).
Have a look at this for some ideas on implementing IAP.
s3c44b0x does not support flash breakpoint(unlike other processors such as lpc1758 which has on-chip flash), then how to debug bootloader when it still runs in the flash?
Logic analyzer, printf, ICE, and EPROM / Flash memory emulator would be the old-school ways.
The Samsung S3C44b0x (ARM7TDMI) claims to have an on-chip ICE breaker debug support, so getting a In-Circuit Emulator might be what you want to do.
Added:
If you have enough RAM, during the booting from Flash you could print log messages to an in-memory buffer in RAM, and then output this buffer, using printf to serial later once the UART is initialized.
2nd addition:
To isolate which portion of the bootstrap process, you could replace modules or steps with empty stubs, with the sole intent to isolate crashing. The approach is to narrow the possibilities of failure. Make an firmware image that initializes only the first basic step e.g. the system's memory, if that works add your task or process housekeeper module / step, later including initializing the UART, etc.
If you have the output pins, add some LEDs to count the sections in binary, allowing your to see which section of code is currently running.
Check out the book Debugging Rules and print off your own copy of the free Rules of Debugging poster. It's a short book, and while nothing revolutionary it solidifies the debugging process, and helps most people be more organized and methodical in their debugging.
References:
The ten secrets of embedded debugging
SO: What simple method can I use to debug an embedded processor without serial port or video?
Softpanorama Debugging Links