I am trying to get Uboot running on a Freescale mx28evk board. It compiles fine and gives me an image, that I can dd copy to a SD-card.
When I turn on the board I get no output from the serial debug console, not even an error message. I can confirm though that the board works fine with another working image on the card.
What would be the appropriate next step to find out what causes the problem? Are there any patterns or magic numbers on the uBoot partition that I can look for to confirm it is a valid uBoot?
Assuming that you have configured a U-Boot version such as u-boot-2013.07
with the mx28evk_config
configuration and built the u-boot.sb
Makefile target using a toolchain such as arm-2009q1-203-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
, and converted the target to an .sd
file using ./tools/mxsboot sd u-boot.sb u-boot.sd
, then the most likely problem is that you have a mistake in your PMU or SDRAM configuration. A mistake in these configurations is likely to cause a reset loop where the reset occurs before you reach the U-Boot banner printout.
Make sure that you have set the EVK switches as specified in the Denx U-Boot doc/README.mx28evk
file: Set the boot mode DIP switches as:
The next step that you need in order to debug this type of problem is to put serial output early, in the SPL SRAM code. Start by putting putc
statements in arch/arm/cpu/arm926ejs/mxs/spl_boot.c:mxs_common_spl_init()
. For example:
void mxs_common_spl_init(const iomux_cfg_t *iomux_setup,
const unsigned int iomux_size)
{
struct mxs_spl_data *data = (struct mxs_spl_data *)
((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);
debug_putc('a');
uint8_t bootmode = mxs_get_bootmode_index();
debug_putc('b');
mxs_iomux_setup_multiple_pads(iomux_setup, iomux_size);
debug_putc('c');
mxs_power_init();
debug_putc('d');
mxs_mem_init();
debug_putc('e');
data->mem_dram_size = mxs_mem_get_size();
data->boot_mode_idx = bootmode;
mxs_power_wait_pswitch();
}
The putc
that I use for this is borrowed from the Freescale i.MX28 bootlet code:
void debug_putc(char ch)
{
int loop = 0;
while (((*(volatile hw_uartdbgfr_t *) ((0x80000000 + 0x74000) + 0x18)).U)&0x00000020)
{
loop++;
if (loop > 10000)
break;
};
((*(volatile hw_uartdbgdr_t *) ((0x80000000 + 0x74000) + 0x0)).U = (ch));
}
The types that you need are:
typedef unsigned int reg32_t;
typedef unsigned short reg16_t;
typedef unsigned char reg8_t;
typedef union
{
reg32_t U;
struct
{
unsigned DIV_EMI : 6;
unsigned RSRVD1 : 2;
unsigned DIV_XTAL : 4;
unsigned RSRVD2 : 4;
unsigned DCC_RESYNC_ENABLE : 1;
unsigned BUSY_DCC_RESYNC : 1;
unsigned RSRVD3 : 8;
unsigned BUSY_SYNC_MODE : 1;
unsigned BUSY_REF_CPU : 1;
unsigned BUSY_REF_EMI : 1;
unsigned BUSY_REF_XTAL : 1;
unsigned SYNC_MODE_EN : 1;
unsigned CLKGATE : 1;
} B;
} hw_clkctrl_emi_t;
typedef union
{
reg32_t U;
struct
{
unsigned TRG : 5;
unsigned RSRVD1 : 3;
unsigned BO_OFFSET : 3;
unsigned RSRVD2 : 1;
unsigned LINREG_OFFSET : 2;
unsigned RSRVD3 : 2;
unsigned DISABLE_FET : 1;
unsigned ENABLE_LINREG : 1;
unsigned DISABLE_STEPPING : 1;
unsigned PWDN_BRNOUT : 1;
unsigned RSRVD4 : 12;
} B;
} hw_power_vddactrl_t;
typedef union
{
reg32_t U;
struct
{
reg8_t DATA;
unsigned FE : 1;
unsigned PE : 1;
unsigned BE : 1;
unsigned OE : 1;
unsigned RESERVED : 4;
reg16_t UNAVAILABLE;
} B;
} hw_uartdbgdr_t;
typedef union
{
reg32_t U;
struct
{
unsigned CTS : 1;
unsigned DSR : 1;
unsigned DCD : 1;
unsigned BUSY : 1;
unsigned RXFE : 1;
unsigned TXFF : 1;
unsigned RXFF : 1;
unsigned TXFE : 1;
unsigned RI : 1;
unsigned RESERVED : 7;
reg16_t UNAVAILABLE;
} B;
} hw_uartdbgfr_t;
void debug_putc(char c);
I put the types in arch/arm/cpu/arm926ejs/mxs/mxs_init.h
and the putc
implementation in spl_boot.c
. I also tend to put a lot of putc
statements in spl_power_init.c
and spl_mem_init.c
.
Note that mis-programming the PMU spl_power_init.c
can cause a reset that will only show up later when you get to spl_mem_init.c
. Don't let this fake you out.