atmega 2560 sd bootloader

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

Ive been trying to get https://spaces.atmel.com/gf/proj... working on an atmega2560. i have everything set up and the code compiles, but it doesnt ever seem to find the file. it can init the card properly but thats it. it also wont output reasonable data to the uart. i fixed all the uart settings, but it just sits there sending 0xFFs regardless of what its supposed to be doing. any suggestions? attached is a zipped folder with my modified code for the 2560

Attachment(s): 

Last Edited: Wed. Apr 8, 2015 - 11:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you don't own a JTAG debugger then I fear it will be fairly vital to get the UART working correctly in order to be able to diagnose what is going wrong. It's true that I keep literal strings in PROGMEM (flash) so on a 2560 where the code will not be located in the first 64K I can see there might be an issue is accessing the strings and I'm pretty sure that's going to be the reason for any issue on a 2560.

 

I don't have a >64K chip to test this on myself (well not easily anyway) so, as I say, you need to start by resolving the UART issue. It's almost certainly going to be a mis-matched clock problem.

 

If you forget the bootloader for the time being and just try an app in the chip using the UART does that work? That will rule out issues like wiring or CPU speed so should make fixing the UART access in the bootloader easier.

 

BTW why use my bootloader on a 2560? Mine is designed/implemented to shoe-horn some FAT reading code into 1K..2K for smaller AVRs with limited bootloader sizes. I haven't checked but I sort of assume 2560 has an 8K bootloader option? If so you could easily fit something using Chan's "Petit" FatFs into that kind of space.
 

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

so if im understanding you properly, progmem doesnt work properly on this chip, and i should avoid using it. correct? i went with your bootloader because it was available, trying not to re invent the wheel.

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

so if im understanding you properly, progmem doesnt work properly on this chip, and i should avoid using it. correct? i went with your bootloader because it was available, trying not to re invent the wheel.

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

Well PROGMEM "kind of works". But there are issues.

 

The problem starts with the fact that pointers in AVRs are 16 bits. That means giving the address of something in the address range 0..65535 is easy. That handles everything in chips up to 64K. Beyond 64K (so 128K and 256K chips) you need to provide one or more additional bits of addressing info to fully specify the location of something. In the AVR and for the purposes of LPM that extra info comes from a register called RAMPZ. In addition you no longer use LPM but ELPM which is a version of LPM that uses the 24 bits of RAMPZ+Z rather than just 16 bits of Z.

 

In my bootloader code I do things like:

            if (mem_cmpP(&Buff[i], PSTR("AVRAP"), 5) == 0) {

mem_cmpP() is a special version of memcmp() that expects to find one of the things being compared in flash and I provide that using PSTR(). So the text "AVARP" here is located in flash than mem_cmpP() goes looking for it in flash using LPM but note the interface to mem_cmpP()...

static inline int mem_cmpP(const void* dst, const void* src, int cnt);

those void * pointers, like any pointers on AVR, are only 16 bit. So even if I managed to get "AVRAP" to locate to a flash address in the 4th bank of 64K in the mega2560 there's no way it's additional address info (RAMPZ=3) can be passed to the function in 16 bits. Now you could try a hack. At present mem_cmpP() is implemented as:

static inline
int mem_cmpP(const void* dst, const void* src, int cnt) {
    const char *d = (const char *)dst, *s = (const char *)src;
    int r = 0;
    while (cnt-- && (r = *d++ - pgm_read_byte(s++)) == 0) ;
    return r;
}

(I stole that from Chan's original code!).  But you could try:

static inline
int mem_cmpP(const void* dst, const void* src, int cnt) {
    const char *d = (const char *)dst;
    uint32_t s = (const char *)src + 0x30000;
    int r = 0;
    while (cnt-- && (r = *d++ - pgm_read_byte_far(s++)) == 0) ;
    return r;
}

which converts "src" to a 32 bit int and adds a 0x30000 offset to it which should it in the same location where this bootloader code is located. However I have no way here to even test if that compiles OK.

 

Also this is just one occasion where I know I'm using flash data. It would be necessary to fix up all such occurrences. Another one that comes to mind is code such as:

    UART_puts(PSTR("B/L start"));

Where:

void UART_puts(const char * str) {
    char c;
    do {
        c = pgm_read_byte(str++);
        if (c) {
            UART_put(c);
        }
    } while (c != 0);
}

Once again it's the pgm_read_byte() in this that would need to be fixed.

 

What I guess I should do is update the code to stop using PROGMEM and pgm_read_*() and use the more modern __memx which can hold 24 bit pointers (well 23 bit really) which would be a better "fix".

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

Thank you for the very explanative reply. i am going to re read this and take another stab at it when i get home later.

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

is it progmem thats the issue or pointers in general? Chan's original code doesn't actually use progmem in his mem_cmp function. is this always going to be an issue with using pointers in the bootloader code?

Last Edited: Thu. Apr 16, 2015 - 02:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any AVR with over 64K of Flash has issues accessing flash data beyond 64K simply because pointers in AVR C compilers are just 16 bits wide and can only address 64K. For "normal" apps this doesn't usually matter as the C compiler arranges to put any data in flash just beyond the reset jump and vector table in the lower 64K. You only hit problems when you go beyond 64K of data. 

 

Once you get beyond 64K you need to switch to using 32bit addressing but C does not have native support for this. 

 

A bootloader is a bit different because the entire thing is beyond 64K. Usually at the very end of 128K or 256K so if you want to access flash data there you have to worry about RAMPZ and ELPM and creating 32 bit addresses. The pgmspace.h has support for this (_far functions) but you have to make a deliberate choice to use them knowing where the data is located. 

 

My bootloader is aimed at 16K/32K AVRs so I put no thought into trying to cater for all this. I may well update it.