Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootloader build problem #1

Closed
mmattern76 opened this issue Jul 2, 2014 · 14 comments
Closed

Bootloader build problem #1

mmattern76 opened this issue Jul 2, 2014 · 14 comments

Comments

@mmattern76
Copy link

Building the bootloader on a Raspberry PI (latest wheezy image with GCC 4.6.3 as well as when updated to jessie with GCC 4.9 and avr-gcc 4.8.1) results in a bootloader with the following behavior:

  • after flashing bootloader.hex with avrdude, the device resets and jumps into bootloader; serial UART messages can be read
  • an OTA flash of a .eq3 firmware file with flash-ota from hmland works, and after receiving the firmware file, the device correctly enters the firmware; if compiled with #USE_SERIAL, UART messages can be read

But as soon as the device is disconnected from voltage, it becomes useless:
When switching on voltage, the config LED blinks once (usually signalling that it has jumped into the bootloader) but then nothing happens anymore... and no messages at all can be read via UART.

This happens when using an unmodified "git clone" version of the bootloader...
A ready-built bootloader from https://owncloud.isengard.at/public.php?service=files&t=0df535e31ad6999664f0e84c95bd2ea5 works just fine with the same firmware...

@jankantert
Copy link

Sounds like a problem with code locations. When fuses for bootloader are set it will start at 0xE000. Since the flash only contains NOOP instructions the cpu will eventually run into the bootloader (if code starts at a later point). When you flash an actual program this changes and will jump into the programm instead of running in the bootloader.

Alternatively fuses are not set it runs over the NOOPs into the bootloader until the programm is flashed. There may be an issue with the flashing itself.

Can you verify that fuses are correct?

@mmattern76
Copy link
Author

Fuses are set to:
avrdude -p m644 -P gpio -c gpio -U lfuse:w:0xFD:m -U hfuse:w:0xD8:m

According to http://www.engbedded.com/fusecalc, for an atmega644 this means a boot start address of 0x7000...

Actually, the fuse settings are the same for flashing the working version under https://owncloud.isengard.at/public.php?service=files&t=0df535e31ad6999664f0e84c95bd2ea5 and the self-compiled version... Something is wrong with the bootloader file that results from building on Raspberry PI - but also when I tried out on a VirtualBox Ubuntu 13.10 image the result was the same...

Which of the fuses are you referring to - BOOTRST? With hfuse D8 it is enabled (set to 0), so the device should always jump to 0x7000 after reset... but wait a minute... 0x7000 is the address in 16-bit words, so it would be 0xE000 in bytes... and that is the value that is set in the Makefile as "-Wl,--section-start=.text=0xE000". So everything should be fine from this point...

I assume that it somehow results from a different version of some library (e.g. avr-libc) or some compiler setting that was different...

@mmattern76
Copy link
Author

Ok, I've experimented a little with the fuses:

With the self-compiled bootloader, I get this:
Setting hfuse to D9 (causing the device to jump directly into the firmware) with
avrdude -p m644 -P gpio -c gpio -U lfuse:w:0xFD:m -U hfuse:w:0xD9:m
leads to a functioning device - directly starting firmware after reboot; this also applies for a powercycle setting;

setting hfuse to D8 again makes the device enter the bootloader (and jump into firmware after timeout)... powercycling the device leads to a "dead" device again... it somehow hangs in the bootloader...

hfuse to D9 again starts the firmware...

Does the OTA flash somehow also play with the fuses?

@mmattern76
Copy link
Author

Did another experiment:
Set hfuse to DA and compiled with -Wl,--section-start=.text=0xF000 (boot size 2048 words instead of 4096 since the bootloader is small enough for that)...
same behavior: toggling between DA/DB for hfuse gives the same behavior as D8/D9 for bootsize 4096 words...

@mmattern76
Copy link
Author

one more experiment - self-compiled bootloader that calls startApplication() right after the first blinking does work, also after powercycle...
flashed the bootloader normally and then the firmware with -D option so that the bootloader remained untouched...

When flashing the unchanged self-compiled bootloader (as per a clean git clone) to the device, flashing firmware with avrdude and -D option to preserve bootloader, the behavior is just as with OTA flash - device is fine until powercycle, hfuse D9 jumps into application, after that hfuse D8 starts bootloader again until powercycle.

So it has nothing to do with flashing the firmware (either OTA flash or avrdude), but the problem has to be somewhere between blinking the config LED and emitting the first UART message (that doesn't come out anymore)...

so, it's this part of bootloader.c that needs evaluation in my opinion - maybe timer should be started after opening UART?
"

// map to correct interrupt table for bootloader
setup_interrupts_for_bootloader();

// setup timer for timeout counter
setup_timer();

// setup interrupts for cc1100
setup_cc1100_interrupts();

// init uart
uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); 

// Activate interrupts
sei();

"

@jankantert
Copy link

Can you add some blinking between the commands to debug the exact location?

@mmattern76
Copy link
Author

Ok - it hangs directly after the call to uart_init(...)

a blink after sei() is not executed anymore...

Could you maybe build the bootloader with -g option and create a disassembly with
avr-objdump -d -M intel -S bootloader.elf > bootloader-dis.txt
?

My disassembly file is here: https://drive.google.com/file/d/0B-0Azq4CaV61eVNzR0d0Q2lZS0k/edit?usp=sharing

bootloader.hex: https://drive.google.com/file/d/0B-0Azq4CaV61UUViU0U4VkgyZ0E/edit?usp=sharing
bootloader.elf: https://drive.google.com/file/d/0B-0Azq4CaV61NHBtSUV5Z1N0b1k/edit?usp=sharing
bootloader.c: https://drive.google.com/file/d/0B-0Azq4CaV61OThpOUEyRUFkd0U/edit?usp=sharing
Makefile: https://drive.google.com/file/d/0B-0Azq4CaV61Si1qUkswZFNTSTQ/edit?usp=sharing
(in Makefile there's an added target debug2 which compiles with -O3 option; also, both debug targets have added the 0xE000 start option)

@jankantert
Copy link

I'm still on a business trip. I can do it next week. Meanwhile you could just comment out all uart stuff in bootloader. Maybe you can use an ifdef and we add an makefile target for this. What do you think?

However, the behaviour is still very strange... We need to investigate further.

@mmattern76
Copy link
Author

bootloader.c with IFDEFs is here - bootloader.c: https://drive.google.com/file/d/0B-0Azq4CaV61OThpOUEyRUFkd0U/edit?usp=sharing

The device still hangs right after sei();

It looks a little as if the interrupts are not moved correctly...
I've read about some cases where the code generated by the compiler does not respect the "four cycles" limit after setting IVCE to 1, but to me the disassembly shows that this is not the culprit here...

I think the best would be to - as soon as you get to it:

  • you compile bootloader with debug information and get the disassembly
  • post the new bootloader.hex so I can verify that it still works
  • and then we can hunt for differences in generated code...

@mmattern76
Copy link
Author

Hi,
when you get to it - would be great if you could produce a bootloader with debug info and disassembly... I guess we'll find the reason for the strange behavior quickly then...
Thanks!

@unimatrix27
Copy link
Collaborator

Hi,

i think I have fixed the problem by removing the sei() before the initialization of the CC in main(). I assume the CC is in an undefined state before initialization, which was the cause for the bootloader to end up in an endless interupt loop.

In a previous commit this sei() was also not done and those builds also run without problems.

@mmattern76
Copy link
Author

@unimatrix27: so you just removed the sei() or put it in later (where)?

@unimatrix27
Copy link
Collaborator

@mmattern76 it was already in the next function called anyway. actually the code before my change had one too many sei();

@jabdoa2
Copy link
Owner

jabdoa2 commented Jul 19, 2014

Since the problem is fixed now. I will close this issue

@jabdoa2 jabdoa2 closed this as completed Jul 19, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants