Bootloader for Atmega4808 or Atmega 0 series

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey all, 
I'm having trouble writing my first bootloader and need your help. First of all about the basic conditions.

 

Controller: AtMega4808
IDE: MPLAP X
Programmer: UPDI via PicKit4
My knowledge: I have been programming Atmegas for a while but only register based in C and no deeper settings like the range from which it should boot. I never had to change any settings on Linker or similar.

 

the ultimate goal is to do updates OTA. And that via a Rs485 interface connected to the predefined USART 2. 
But I am not that far yet. It fails already with a supposedly simple program in which the following program is compiled and in Hex in the later Bootloader program. 

 


#define F_CPU 160000UL

#include <util/delay.h>
#include <avr/io.h>


#define OP_LED_PD0 (1<<0)

void main(void) 
{
    CCP = 0xD8; //enable disabled registers
    CLKCTRL.MCLKCTRLB=0; //Edit locked registers to remove the prescaler for the system clock
    
    PORTD.DIR |= OP_LED_PD0; //LED as output
    while(1)
    {
        PORTD.OUT^=OP_LED_PD0;
       _delay_ms(500);
    }
    return;
}

I have looked through the following references without success and tried to complete. 

https://ww1.microchip.com/downlo...
https://github.com/arduino/Ardui...
https://www.avrfreaks.net/forum/...

 

I have already made the following settings in MPLAB:
Project Properties -> Conf -> avr-ID ->Gerneral-> Do not use standard files -> (check)
Project Properties -> Conf -> avr-ID ->Memory Settings-> FLASH segment -> ".text=0x200"

 

i find the GiHub link very interesting. But I couldn't get it to work after several attempts. Especially since I don't know the format how to transfer the new program via the USART interface and the correct settings in MPLAB. 

My program always hangs and restarts (the LED is toggling continuously). 

I have understood the general principle of the bootloader but I am still missing the transition to the Atmega 0 series and the real implementation of a bootloader.

Does anyone of you have a reasonable source to read specifically for this series? From the App Note from Microchip I could take nothing at all. 
Or might take the time to summarize the whole thing understandably and explain it with an example.

I hope you undestand my Problem and somebody can help me!

If i forgot something feel free to ask questions

 

Regards

Roger

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't understand what you've done.  You say that you're writing a bootloader?  Please show us your bootloader code, and not the application that it fails to load!

 

Does anyone of you have a reasonable source to read specifically for this series?

https://github.com/Optiboot/opti... ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a simple bootloader for any avr0/1 with only slight modifications needed, in this case for a tiny3217. Whether better or worse than what is in the links I do not know (didn't look), but it is another example.

 

https://godbolt.org/z/ExWxnPn5P

 

To make it simple and allow some standard app to do the programming (a terminal app or command line in Linux), xmodem was chosen as it is simple (I didn't do a lot of thinking for this example, so you get what you pay for). Should be mostly self explanatory.

 

The bootloader gets written and programmed as any other app, except you will need to set fuses accordingly- BOOTEND specifically to set the size of the bootloader, the other fuses are set to whatever will be suitable (the app loaded via bootloader cannot change fuses, so your app gets what is already programmed).

 

At the bottom of the example there is a simple example app to blink an led. When creating an app which will be loaded via bootloader, you will have to move the .text section up to the bootloader end address, 0x800 in this example which is a 0x400 word address (linker option uses a word address). That is the only important option. The bootloader is dealing with simple binary, so in this case will also need to make a binary from the compiled elf file (a scripted solution in the after build options would be the place to do it, but I just manually ran the avr-objcopy command to make a bin file).

 

The example bootloader above was created online, then was loaded into MPLABX and programmed into a tiny3217. The example app was also loaded/compiled in MPLABX and a bin file created. The command I used in Linux to program the bin file is shown in the example. It was tested and it works (led blinks after loading app via xmodem).

 

So, you can see that it is relatively simple, if kept simple. The harder part is choosing how to communicate to the outside world, what determines if the bootloader runs or not, what kind of pc app will be used (or will you create your own), etc. There are lots of details that can come into play the deeper you go, like any other type of programming.

 

edit-

Not that it matters much, but since I am not a fan of defines I moved most of the defines to native C language values and made a few changes (blink led when waiting for xmodem to start, instead of ignoring the packet block values I just see if the pair are correct values, app example now shows getting back to bootloader by pressing switch)-

https://godbolt.org/z/esK64n549

 

I usually use C++ and rarely use defines, but when in C and doing simple projects I revert to old ways and start creating defines. The compilers are smart, so static const values can replace many defines and you get the same results (and same size). The main advantage is your code is not hidden behind defines/macros, so its you and the compiler fighting it out one-on-one instead of having a word processor thrown into the mix to confuse things.

 

edit-

and you can keep adding more features, such as adding an option to do xmodem-crc instead-

https://godbolt.org/z/sasE7W9xb

it never ends.

 

 

A more permanent place-

https://github.com/cv007/Avr01-X...

Last Edited: Fri. Jul 22, 2022 - 06:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the two links and the explanations, I'll work my way through them over the next few days and see if I can get them to work.
If I then have more explicit questions I come back to you.
Thanks a lot!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi curtvm, 

many thanks for your work. But im still strugelling. I have some points i have to write about.

 

First of all in your GitHub Link  at bootloader.c line 99 you write 

Sw              = { &PORTB, 7, 1<<0, 0 };

 but instead it should be

Sw              = { &PORTB, 7, 1<<7, 0 };

nothing really big but maybe somebody have to search a while befor finding this mistake :D

 

 

 

An other point ist that i cant compile the example code if i add the line:

 

avr-objcopy -binary my_project.elf -O my_project.bin

Of course i changed this to my programm names but this doesnt help. I already try to search for this on the Internet but nothing could change the problem.

process_begin: CreateProcess(NULL, avr-objcopy -binary ecmpl.elf -O ecmpl.bin, ...) failed.
make (e=2): Das System kann die angegebene Datei nicht finden.

make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
"User defined post-build step: [avr-objcopy -binary ecmpl.elf -O ecmpl.bin]"
nbproject/Makefile-default.mk:111: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/strau/iCloudDrive/Arbeit/IPU BUS/Bootloader/Neuer Ordner/Bootloader_cv007.X/ecmpl.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed

BUILD FAILED (exit value 2, total time: 360ms)

 

This is the Text in the Output Window. Im working with MPLAB X v5.50 on Windows.

For the first try i manualy changed the hex file into a bin file. Maybe this is also the trouble for the next problem.

 

 

After transfering the data via Tera Term into the Atmega it doesnt jump into the application Code the Programm only restartet all the time (Or better it try to jump to the application Code but it is corrupted). I think this is because in the Program Memory of the chip their is the transmittet Data in Ascii Code not as executable code. 

Did you already now this Problem? If this works for you their is probaly a problem with my Terminal to transmitt the data with XMODEM.

 

Address    Value                                                        Ascii
0400	313A	3030	3034	3030	3030	3943	3434	3038	:1004000 00C94480
0408	3032	3943	3534	3032	3032	3943	3534	3032	20C94520 20C94520
0410	3032	3943	3534	3032	3232	0D36	3A0A	3031	20C94520 226..:10
0418	3430	3031	3030	4330	3439	3235	3230	4330	0410000C 9452020C
0420	3439	3235	3230	4330	3439	3235	3230	4330	9452020C 9452020C
0428	3439	3235	3230	4330	0A0D	313A	3030	3234	9452020C ..:10042
0430	3030	3030	3943	3534	3032	3032	3943	3534	0000C945 2020C945

At the moment i only have the data transmittet in Hex but it looks the same in binary but only with 0 and 1 or 0x30 0and 0x31 in Ascii.

I will now try to build a function that convert Ascii in real hex befor loading it in the programm memory but their should be a other way if the program works for you.

 

Best regards 

Roger

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Roger__ wrote:

An other point ist that i cant compile the example code if i add the line:

 

avr-objcopy -binary my_project.elf -O my_project.bin

That is missing some detail. You have to tell it WHAT from the ELF you want to include in the output. Usually you use either -j's to say which sections should be included or -R's to say which sections should be removed.

 

Most build systems favour -R so that if additional, named sections, are added then they will not be filtered out. If using -j's you have to add each extra section to make sure it's included in the binary image.

 

For something as simple a s bootloader you would probably use -j):

avr-objcopy -O binary -j .text - j .data my_project.elf my_project.bin

Note you were also using -O incorrectly. You use things like "-O ihex", "-O binary" to sy what kind of format you want the copy destination to be.

 

Oh and your terminal output seems to suggest you are sending HEX when BIN is expected ?!?

 

PS just to note that  xmodem-crc is easy when the SPM page size is the same as the xmodem-crc packet size (128 bytes) but for smaller devices the SPM page may be smaller (64, 32?)  in which case there would need to be additional code to split each 128 byte edlivery.

Last Edited: Thu. Jul 28, 2022 - 08:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but instead it should be

Thanks. I was making changes and made a mistake at one point. It was hidden from me by the fact that the demo app was correct, so I could press the sw at power up and get to the bootloader bu the demo app was getting me into the bootloader via sw press, not the bootloader sw press. Corrected.

 

I also seem to have mixed up the objcopy command in the example, this is what I am actually doing on the command line-

    avr-objcopy my_project.elf -O binary my_project.bin

The additional specifying of sections does not seem to be needed as the text section contains all we need (the data section load values are in the text section), and it seems objcopy by default does just the text section (for binary anyway). At least in my case (gcc 7.3.0) I am seeing the correct bin files, with the data load values at the end of text where they should be.

 

 

PS just to note that  xmodem-crc is easy when the SPM page size is the same as the xmodem-crc packet size (128 bytes) but for smaller devices the SPM page may be smaller (64, 32?)  in which case there would need to be additional code to split each 128 byte edlivery.

The code in github takes that into account and writes at a page crossing if reached before the 128 bytes (64 page size is the only lower page size in the avr0/1).

 

 

I'll try xmodem on a Windows pc to see how that works. I have been using linux, and the sx command as listed in the example.

 

edit- tested on a Win10 laptop, used tera term (downloaded latest version), set to correct serial port/baud rate/etc, could see the 'C' coming in (coms ok), send file via xmodem, worked ok.

 

On the linux pc, I had put the (correct) objcopy command in the after build steps so my app bin file is generated automatically at build time. Trying to get that objcopy command entered into that line properly is kind of awkward, so a better idea would be to just create a bash/cmd/bat script to do this, then put script name into that after build line instead.

 

 

Another thing to note- objcopy will create a binary from start of text to end of text section with the bin data, so the bin file is a file of a length same as the text size (app size). When transferring this bin file, xmodem will pad the data at the end (if needed) to make the last packet 128 bytes. This extra data is harmless in the mcu as it is not used (I think its 0x1A/SUB), but just be aware it will show up in the mcu at the end of the app (if padding was needed).

 

 

I don't know if this xmodem-crc is a great idea or not (makes an easy example), but for a Linux pc it does simplify the pc app side as a simple command via sx does the job (I would think sx is on every linux distro). On Windows I would guess there is a way to automate things, but probably more awkward and probably ends up simpler to create your own pc app (at which point you probably think of doing something other than xmodem, although having xmodem in place is still nice as it allows falling back to some standard app when the custom programming app is not around for some reason).

 

Also added to the github code is a 'dump' of flash/eeprom/userrow/fuses at the end of programming (takes about 1.5sec at 230400). Its kind of backwards, but it allows getting info from the mcu without any command. If only this data is wanted, or want this data before programming, just send a 0 length bin file (EOT is sent, so no programming takes place) and the data will be dumped. Then you can trigger the bootloader again if needed (or can write a 1 byte bin file of 0xFF if want to stay in bootloader after the reset as 0xFF at app start will prevent bootloader from jumping to app). The crc xmodem uses is probably good enough, along with the mcu verifying each page write, but the flash dump at the end also allows one more verification of what is in the mcu.

 

Another thing I noticed- at first it appears that making the mcu initiate the xmodem transfer by sending a 'C' (crc) also seems opposite of what we typically do (bootloaders normally wait for pc to initiate communications), but at second glance this is also not necessarily a bad way to go. Making the pc figure out the baud rate the mcu is using is one possibility, and you can also start the pc side transfer before the bootloader is ready to go since it waits to see a 'C' before starting its xmodem transfer. 

Last Edited: Fri. Jul 29, 2022 - 06:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


But after sending some Binary Code my Program Memory looks like this:

 

 

 

Your suggestions for building the binary file have not been successful yet, but if the internal data processing does something like this, it can't work in general. Or do I see this wrong?

For my understanding why are you working with binary data and not hexadecimal? 

Could you maybe post your binary file created with MPLAB here? Then I could test with it. Thanks a lot!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
The additional specifying of sections does not seem to be needed as the text section contains all we need (the data section load values are in the text section), and it seems objcopy by default does just the text section (for binary anyway).
That is to do with whether the linker has tagged the sections as "loadable" or not. You only need -j/-R if there is a possibility of other "loadable" sections you don't want.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Roger__ wrote:
But after sending some Binary Code my Program Memory looks like this:
That memory contains Intel Hex records. It is not binary - at some stage the wrong kind of file was used. You are supposed to convert from ELF to Binary not IHex then it is that binary that is transmitted.

 

I thought that was the purpose of the:

 avr-objcopy my_project.elf -O binary my_project.bin

so it is project.bin from this that needs to go the AVR.

 

It's possible that if you are using MPLABX/Studio7 it is already doing a full build that involves a different objcopy that converts ELF->HEX but it's the output of the additional ELF->BIN that needs to be used.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You will have to determine if you are producing a binary file first. You get an elf and hex file by default from your ide, and the hex file is normally used for programming. We need a binary file, so have to use avr-objcopy to produce a binary file from the elf file. A hex file is a readable format/representation of data to use for programming, which is not used in this case.

 

So, to get the binary file you have to somehow get this command to run-

    avr-objcopy my_project.elf -O binary my_project.bin

which needs to change to suite your situation- where is avr-objcopy located (if not in your environment path, will have to specify its full path), what is the name of the project's elf file, etc.

 

Now, with a my_project.bin file (whose file size will match your app size since it is a binary 1:1 of your app, exactly the same as what your mcu will use), you xfer that to the mcu via xmodem. The app was built with the .text offset to the bootloader size (app start), the bootloader flashes the binary to the app section.

 

Attached is a bin file for the demo app.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Thank you very much for your help. I have taken the syntax from the output window of MPLAB and adjusted the command set. 
with the following line I then also got the desired binary output. 
"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin"\avr-objcopy -O binary "dist/default/production/ecmpl.X.production.elf" "dist/default/production/ecmpl.X.production.bin"

With this file the transfer with TeraTerm worked!

Now it's just a matter of adapting the whole thing to my imagination.