Building firmware with gcc

You are of course correct. I had just realized that and apologize for my stupidity.

I am tracking down the startup problem step by step, literally, using openocd and gdb (and qemu as well, yum). There is an uninitialized function pointer being called in USB_Init. Something should have set up Device_Info and Device_Property. If anyone wants to chase it down while I am going skiing…

With a rational path in place I can now almost compile. Unfortunately Mac Os puts sed in /usr/bin not in /bin so the iar2gas blows out. :cry: I get tired of these random differences, but I thought I would mention it. The configure scripts normally fix this sort of thing.

Have fun skiing I will poke at the init function, but the whole startup world on these embedded micros is pretty opaque to me.

Well the init function is trying to walk a list of device descriptors, from first glance, and I am guessing that the function that populates that list has not been called. Without your trace capabilities I am not going to get much further here. I need to get the rest of my tools working, but I suspect you will get back from skiing before I get that far along.

Last night I fixed the sed path and the data initialization issue (I was simply not copying the initialized data section to the .bin and .hex file, duh). I can verify many things using openocd and gdb on the development board, but when it comes to timers and interrupts it gets difficult. The same goes for anything that depends on input on the GPIO ports which of course are hooked up to different hardware on the real DSO.

So to get any further I think it will be needed to debug directly on a DSO. Maybe Jerry or someone at Seeed has everything set up for this? I haven’t opened my DSO and do not have my little screwdriver around, but from the schematics posted at it seems like it has some kind of JTAG connector inside. But it will certainly not fit my JTAG adapter plug. Is there some pictures from inside the Nano v2 anywhere?

Of course, there can be just some small detail missing in my gcc setup, like those things I have discovered so far, but I am too blind to see my own mistakes :slight_smile:

In any case, I have learned a lot about arm debugging, and I can write up some short tutorials. I think the wiki will be a better place for this though, rather than having the information scattered around forum posts.

Hello Tormod, I do not have a JTAG for debugging, but the DSO Nano certainly has a connector for that - CN7 in the picture attached, lower left (sorry for the poor image quality). There are other interesting pads, too: both CN4 and CN5 have RX/TX connectors - one of them should be the console port.

Great idea! I’d love to learn how to debug at device level: at present I’m pretty much lost without an OS underneath.

Which JTAG board are you using? Do you have recommendations? I know I need to get one soon, but have not yet figured out which one I can get by with.

Has anyone made any more progress here? Are there known issues that need addressing? I expect to have some time later this week so if I can help I will be glad too. I am tracking down a possible JTAG path, that if I can get working will make things much easier for me to work on.

Hi Rich, I am using an IAR rebranded version of the Segger J-Link ( that came with an IAR dev board that I am borrowing. I have not tried anything else, so I can not recommend any on basis of my own experience. If I would buy one I would maybe look at the ARM-USB-TINY-H or ARM-USB-OCD from It would be important for me that it works well with openocd and other open-source tools, and without any restrictions (like the Segger EDU version has).

Olimex also has a minimal dev board, but I guess buying a LeafLabs Maple ( would make more sense, since it has excellent open-source support and a community around it. Futurlec also sells a cheap STM32 board.

I have currently no time to work on this unfortunately. I do not have any lead to what goes wrong. It is interesting that the IAR 5.0-compiled code also fails to run. I’ll paste some short debugging notes on the wiki in case it can help or inspire someone.

EDIT: Added two tutorials to the Developer’s Corner of the DSO Nano wiki This is gonna be helpful for myself at least :slight_smile:

I’ve been scratching my head over the code, and I can only see a single place where it could fail: I’d say that the culprits are almost certainly the two files ASM_Function-gcc.S. The __Start_APP symbol you mention is only half of the story: also the symbol table in the LIB is likely to be found somewhere else, given that we are using different compilers instead of IAR4.

Thanks a bunch!


That is true. However, it will only play as soon as the APP is launched. And as far as I can see, something goes wrong already when launching the LIB. I have uncommented the “waitforkey” call which is just before the final jump to APP, but nothing appears on the screen anyway. I would have expected the start-up text messages (including “Lib version …”) to show up.

Thanks, all.
I have tried the GCC. It compiles and links fine,but the final hex file can not work.I just got a blank screen on my DSO. I am just learning about GCC,IAR and the startup code. Initially, I thought maybe the different binary file format made the issue. IAR4 uses UBROF that is IAR’s private format, yet IAR5 and GCC use ELF.
Now,I realise that is not the real reason.
The bootloader(just IAP) was compiled by IAR4.X constantly. I used IAR5.0 to compile Ben’s code,it passed. The lib can work, app can’t. Allow me to explain the
procedure when power on. Firstly, the bootloader will run. It will detect one GPIO to determine whether or not to upgrade. If not, it will jump to the lib part.
At the end of “main” function, it will jump to start address of the app part. Using IAR5,app can not work,it means the start address of the app part is wrong.GCC can not work,I think, they have different reasons.

Yes, the elf format is not important. The “real” binary content gets stripped out of the elf file into the bin (or dfu) file, which gets loaded on the Nano. So whether the intermediate format is elf or ubrof does not matter.

Exactly this issue should be fixed by the patch I suggested in viewtopic.php?p=4498#p4498. Basically the patch makes the LIB do the same when jumping to the APP, as the bootloader does when jumping to the LIB: It reads the startup entry (reset handler) from the interrupt vector instead of using a hardcoded address of the startup entry.

I have tested the patch on an emulator, so I know that it compiles correctly and does the right thing. However, I can not see if it works on gcc, so I will need some of you to please test it on IAR 4.0 and 5.0.

Hello Tormod,
last night I have finally been able to compile a working firmware on IAR5. Here are the elf files you asked for: I really hope they let you gain some insight into what is missing for getting the gcc port on par!

Antonio (84.8 KB)

Hi Antonio, thanks for the elf files! I am not sure what to look for, and I have not discovered anything special yet, but I am sure they will be a useful reference.

I have done some great progress. Since the display was not coming up, and I have no JTAG or serial connection, I explored the possibilities of the 1-bit debug facility that is the function generator output :slight_smile: I hooked up a voltmeter to the output, and modified the code to not control the pin from a timer, but as a normal output pin I could toggle manually.

With this I could confirm that the LIB starts up fine, and if I disabled the USB_Init, it would go through the whole main() and jump to the APP. So why didn’t the LCD come up then? I studied the disassembly in LCD_Initial(), and here the elf file from Antonio gave me a nice opportunity to compare with the IAR-generated code. It turns of that some “cowboy” macros in HW_V1_Config.h gives quite different code in gcc versus IAR:

#define LCD_nWR_ACT()   GPIOD_BSRR = GPIOD_BRR  = GPIO_Pin_5

The intention here (which happens to work in IAR) is that GPIO_Pin_5 (which is just one bit) should be written to GPIOD_BRR first, then be written to GPIOD_BSRR, in order to create a 1-0-1 pulse. Although these variables are volatile (and directly mapped to the peripherals registers) it is easy to imagine that the compilers might do things slightly differently. And effectively, changing this and similar constructs to:

#define LCD_nWR_ACT()   GPIOD_BRR  = GPIO_Pin_5 ; GPIOD_BSRR = GPIO_Pin_5

made the LCD came up!

Now if we have hundreds more of these small things to fix, this is going to be fun :slight_smile:

EDIT: I pushed the fixes to my gcc branch, but you will have to disable USB_Init yourself, since the gcc branch should stay in working state for IAR as well.

Congrads Tormod, clever idea! And great news, too: you are getting very close.

To make USB_Init work I guess you need to apply to the APP and LIB ASM_Function.s the same kind of massaging I’ve done with IAR’s linker directives - see the the changes on the svn here.

I have not tried on gcc yet, but instructing the linker to place code at a fixed address does not seem to be much harder than it has been with IAR, judging by this thread: How to locate variable at fixed address?

You should be able to quickly poke at the linker config files, and then modify your iar2gas script in order to translate the relevant instructions from IAR jargon to gcc parlance.


I think I have pretty much taken care of this by linking ASM_Functions.o first, so the branch tables always ends up at the start of the .text section and have stable addresses. For now, I have given up iar2gas and tweak the gcc assembly files by hand.

Instead of adding any addresses to the linker script, I think BenF’s suggestion in the other thread about storing the branch table address inside the LIB vector table would make sense.

BTW, the patch I have applied for jumping from LIB to APP … 0458df6904 should work fine with both IAR 4 and 5 as well. It gets rid of the need to know where __APP_start is located.