EmbeddedRelated.com
Forums
Memfault Beyond the Launch

at91sam7: garbage on DBGU output

Started by Roman Mashak June 16, 2008
Hello,

MCU - at91sam7s64
toolchain - Yagarto (based on gcc-4.2.1)

I have two distinct applications residing in the internal flash. The first 
one located at 0x100000, prints string and transfers control to the second 
application located at 0x104000, which lights the LED and prints a string.

The 1st application is compiled with vectors placed in ROM, while in the 2nd 
application vectors are placed in RAM and it also does remapping, configures 
timer and timer's interrupt handler (where LED blinking occurs and where I 
also print a string out DBGU).

Before transferring control, I also disable all interrupts in the first 
application:

AT91C_BASE_AIC->AIC_IDCR = ~0;
AT91C_BASE_AIC->AIC_ICCR = ~0;

for (i = 0; i < 8; ++i) {
       AT91C_BASE_AIC->AIC_EOICR = 0;
}

The 2nd code, upon receiving control, enables IRQ and FIQ.

The whole thing doesn't work as I expected. First application prints, then 
runs second application, which lights LED on but instead of printing string 
it outputs some garbage on a DBGU port.

The interesting thing is that that string from timer service routine is 
ALWAYS printed properly, while the first AT91F_DBGU_Printk() is clumsy. May 
be after enabling interrupts and before issuing the first 'printk' some 
timeout should pass or there is a special peripheral reset procedure that I 
need to accomplish before passing control to another application?

Looking forward to getting any useful advices. Thanks in advance.

Best regards, Roman Mashak. 


Roman Mashak wrote:
> Hello, > > MCU - at91sam7s64 > toolchain - Yagarto (based on gcc-4.2.1) > > I have two distinct applications residing in the internal flash. The > first one located at 0x100000, prints string and transfers control to > the second application located at 0x104000, which lights the LED and > prints a string. > The 1st application is compiled with vectors placed in ROM, while in > the 2nd application vectors are placed in RAM and it also does > remapping, configures timer and timer's interrupt handler (where LED > blinking occurs and where I also print a string out DBGU). > > Before transferring control, I also disable all interrupts in the > first application: > > AT91C_BASE_AIC->AIC_IDCR = ~0; > AT91C_BASE_AIC->AIC_ICCR = ~0; > > for (i = 0; i < 8; ++i) { > AT91C_BASE_AIC->AIC_EOICR = 0; > } > > The 2nd code, upon receiving control, enables IRQ and FIQ. > > The whole thing doesn't work as I expected. First application prints, > then runs second application, which lights LED on but instead of > printing string it outputs some garbage on a DBGU port. > > The interesting thing is that that string from timer service routine > is ALWAYS printed properly, while the first AT91F_DBGU_Printk() is > clumsy. May be after enabling interrupts and before issuing the first > 'printk' some timeout should pass or there is a special peripheral > reset procedure that I need to accomplish before passing control to > another application? > Looking forward to getting any useful advices. Thanks in advance. >
Looks like a Linker problem to me. The program is linked to one place, but you are executing in another place, so position independent code will execute, but data (the string) is read from another location. You can test the following: unsigned char string[32] volatile unsigned char c; c='T'; string[0] = c; c='h'; string[1] = c; c='i'; string[2] = c; c='s'; string[3] = c; c=' '; string[4] = c; c='i'; string[5] = c; c='s'; string[6] = c; c='a'; string[7] = c; c='t'; string[8] = c; c='e'; string[9] = c; c='s'; string[10] = c; c='t'; string[11] = c; c='!'; string[12] = c; c='\n'; string[13] = c; c='\0'; string[14] = c; printf(string); Check the assmbler code that the characters are loaded as constants and are not loaded with PC relative load instructions. If that is the case, run the program.
> Best regards, Roman Mashak.
-- Best Regards, Ulf Samuelsson This is intended to be my personal opinion which may, or may not be shared by my employer Atmel Nordic AB
Hello, Ulf!
You wrote  on Tue, 17 Jun 2008 06:19:43 +0200:

 US> Looks like a Linker problem to me.
 US> The program is linked to one place, but you are executing in another
 US> place, so position independent code will execute, but data (the string)
 US> is read from another location.

I'm pretty sure the linker script is correct. And I burn the second image at 
the precisely same address, as defined by linker (I also double checked that 
with utility "J-Flash ARM" shipped by Segger along with their JTAG toolkit).

Regarding disabling interrupts before passing control to the second 
application: is it mandatory to do, or depends on requirements? And the same 
question about resetting: I heard that it's recommended to reset CPU before 
another code takes on control, for example in bootloader environments. What 
can you say about it?

 US> You can test the following:
[skip]
I compiled the code and investigated assembly output. I'm not ARM assembly 
expert though, but as I understood characters are loaded as constants:
...
mov r3, #84 ; 0x54 code of 'T'
strb r3, [fp, #-45]
ldrb r3, [fp, #-45]
and r3, r3, #255 ; 0xff
strb r3, [fp, #-44]
mov r3, #104 ; 0x68 code of 'h'
...

With best regards, Roman Mashak.  E-mail: mrv@tusur.ru 



Memfault Beyond the Launch