Writting to FLash Memory

Go To Last Post
97 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

HI all, 

 

This is my first question in the form. I will try my best to follow the rules and be as clear as possible

 

I am working with Atmega32u4 (in Arduino board-this is BASED OF THE CATERINA BOOTLOADER) and I'm trying to write data to flash memory from the application. After a lot of research and long working hours I came close but not there yet.

 

I Defined a function called Do_spm_N () that write data to flash memory, in the bootloader section. Mad sure that the section lives in the bootloader part.

in my application I'm calling the function to write data to flash. however nothing written to flash. memory any idea what could be wrong. here is the code 

 

1- defining function in the bootloader 

// this part in my bootloader.c 

#define BOOTLOADER_SECTION __attribute__ ((section(".bootloader"))) ;
:
:
:
:
...
static void do_spm_N (uint32_t address,  uint8_t *data) BOOTLOADER_SECTION;
:
:
:
:
......
static void do_spm_N (uint32_t address,  uint8_t *data){

	uint16_t i;
    uint8_t sreg;
    // Disable interrupts.
    sreg = SREG;
    cli();
    eeprom_busy_wait ();
    boot_page_erase (address);
    boot_spm_busy_wait ();      // Wait until the memory is erased.
    for (i=0; i<SPM_PAGESIZE; i+=2)
    {
        // Set up little-endian word.
        uint16_t w = *data++;
        w += (*data++) << 8;

        boot_page_fill (address + i, w);
    }
    boot_page_write (address);     // Store buffer in flash page.
    boot_spm_busy_wait();       // Wait until the memory is written.
    // Reenable RWW-section again. We need this if we want to jump back
    // to the application after bootloading.
    boot_rww_enable ();
    // Re-enable interrupts (if they were ever enabled).
    SREG = sreg;
    // this is for indication
	for(int i=0; i >= 5;i++){
	L_LED_ON();
	delay(10);

	RX_LED_OFF();
	TX_LED_OFF();
	L_LED_OFF();
	delay(10);
	RX_LED_ON();
	TX_LED_ON();
	L_LED_ON();
	delay(10);
	RX_LED_OFF();
	TX_LED_OFF();
	L_LED_OFF();
	}

}

2- Adding linker option in makefile

// MAKE FILE
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOT_START)

3- defining the function and calling it in my application 

// APPLication.h

static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

 // Application.ino (the atmerga32u4 lives in an arduino board)
 const char flash_buffer[SPM_PAGESIZE] __attribute__ (( aligned(SPM_PAGESIZE) )) PROGMEM= {};
 char Str [] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVW";
 uint8_t ram_buffer[SPM_PAGESIZE];

void setup() {

  // Init serial
  Serial.begin(9600);
    for (int i = 0; i<=  sizeof(Str);i++){
            ram_buffer[i] =Str[i];
          }

}

 void loop() {
  // no code here
  int i;
  uint8_t c;
  uint16_t w;
   byte data ino 

  // Print current flash buffer content
   if (Serial.available() > 0 ) {
    data = Serial.read() ;

    switch (data) {

        case 'w':{
             do_spm_N ((uint32_t) &flash_buffer[0], *ram_buffer);

        }
    }
   }
 }

Any idea/suggestion ?

 

thanks in advance 

 

Supporting Information:-

 

Last Edited: Thu. Oct 11, 2018 - 03:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What does the hex or nm say?

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

An AVR's idea of the bootloader section depends on its fuses.

The linker's idea of the .bootloader section depends on $(BOOT_START).

Do they match?

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

WHY are you writing to flash memory from a running application?   This is never done.

 

If you need to store lots of data, even through power cycles, use serial EEPROM or FRAM.  Here is an example of a simple 512 x 8 8-pin cheap EEPROM IC.  Other serial EEPROMs hold up to 128K bytes in the same pin-out:

https://www.ebay.com/itm/25LC040...

Last Edited: Fri. Oct 5, 2018 - 02:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is never done.

Rubbish.

 

It is infrequently done, but 'never' is a long time.

 

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Simonetta wrote:
  This is never done.
As someone who has done exactly this - written to flash in an app - this just proves what utter nonsense you talk almost all the time. You clearly have no idea how micros are used at all so I don't know who you think you can advise people about the subject with such utter drivel and misinformation?

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

I think the .hex file is correct ( I might be wrong). I looked at the hex and it starts at the correct address (per my calculation )

here is the first 20 lines 

 

:1070000074C000008DC000008BC0000089C000006B
:1070100087C0000085C0000083C0000081C0000060
:107020007FC000007DC0000007C5000079C00000DF
:1070300077C0000075C0000073C0000071C0000080
:107040006FC00000FEC000006BC0000069C00000FF
:1070500067C0000065C0000063C0000061C00000A0
:107060005FC000005DC000005BC0000059C00000B0
:1070700057C0000055C0000053C0000051C00000C0
:107080004FC000004DC000004BC0000049C00000D0
:1070900047C0000045C0000043C0000041C00000E0
:1070A0003FC000003DC000003BC00000873EA03E46
:1070B0004C3FA03E4C3FD83EFA3E4C3F1A3F2C3F3F
:1070C0002203300030003000320034003900340038
:1070D00033003500380000001201100102000008E2
:1070E000AD0AF00100000102030111241FBECFEF21
:1070F000DAE0DEBFCDBF11E0A0E0B1E0E2E2FFE701
:1071000002C005900D92AE39B107D9F721E0AEE982
:10711000B1E001C01D92A73FB207E1F762D3FFC6FD
:107120006FCF84E08093E9008091E80085FD0DC079
:107130008091E8008B778093E8008091E80082FDE1

But what is "nm"?

Last Edited: Fri. Oct 5, 2018 - 12:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

What does the hex or nm say?

 

I think the .hex file is correct ( I might be wrong). I looked at the hex and it starts at the correct address (per my calculation )

here is the first 20 lines 

 

:1070000074C000008DC000008BC0000089C000006B
:1070100087C0000085C0000083C0000081C0000060
:107020007FC000007DC0000007C5000079C00000DF
:1070300077C0000075C0000073C0000071C0000080
:107040006FC00000FEC000006BC0000069C00000FF
:1070500067C0000065C0000063C0000061C00000A0
:107060005FC000005DC000005BC0000059C00000B0
:1070700057C0000055C0000053C0000051C00000C0
:107080004FC000004DC000004BC0000049C00000D0
:1070900047C0000045C0000043C0000041C00000E0
:1070A0003FC000003DC000003BC00000873EA03E46
:1070B0004C3FA03E4C3FD83EFA3E4C3F1A3F2C3F3F
:1070C0002203300030003000320034003900340038
:1070D00033003500380000001201100102000008E2
:1070E000AD0AF00100000102030111241FBECFEF21
:1070F000DAE0DEBFCDBF11E0A0E0B1E0E2E2FFE701
:1071000002C005900D92AE39B107D9F721E0AEE982
:10711000B1E001C01D92A73FB207E1F762D3FFC6FD
:107120006FCF84E08093E9008091E80085FD0DC079
:107130008091E8008B778093E8008091E80082FDE1

But what is "nm"?

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

Simonetta wrote:

WHY are you writing to flash memory from a running application?   This is never done.

 

 

NO< Let me correct you. I searched the web and It was done before for sure. 

the EEPROm is small i need to use the rest of my flash memory to save data 

 

 

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

clawson wrote:

Simonetta wrote:
  This is never done.
As someone who has done exactly this - written to flash in an app - t

 

agree with you it was done before 

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

skeeve wrote:

An AVR's idea of the bootloader section depends on its fuses.

The linker's idea of the .bootloader section depends on $(BOOT_START).

Do they match?

 

I 'm not sure how to check the fuses, any hint ? I am using a make file to compile .

DO you mean BOOTSZ?

Last Edited: Fri. Oct 5, 2018 - 12:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-nm is one of the tools that comes with avr-gcc.

 

If you happen to use AS7 then on the tools menu there is an entry for "Command Prompt". When you select that then PATH is set so all the avr-gcc tools like avr-gcc, avr-objcopy, avr-objdump, avr-ar, avr-nm can be found. It's basically these:

C:\>where avr-gcc
C:\program files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe

C:\>cd C:\program files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin

C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin>dir avr-*.exe
 Volume in drive C is OSDISK
 Volume Serial Number is 7AF3-B2D0

 Directory of C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin

13/09/2017  00:24           494,080 avr-addr2line.exe
13/09/2017  00:24           514,560 avr-ar.exe
13/09/2017  00:24           666,112 avr-as.exe
13/09/2017  00:24           736,768 avr-c++.exe
13/09/2017  00:24           492,544 avr-c++filt.exe
13/09/2017  00:24           735,744 avr-cpp.exe
13/09/2017  00:24            31,744 avr-elfedit.exe
13/09/2017  00:24           736,768 avr-g++.exe
13/09/2017  00:24           734,208 avr-gcc-5.4.0.exe
13/09/2017  00:24            49,664 avr-gcc-ar.exe
13/09/2017  00:24            49,152 avr-gcc-nm.exe
13/09/2017  00:24            49,152 avr-gcc-ranlib.exe
13/09/2017  00:24           734,208 avr-gcc.exe
13/09/2017  00:24           380,928 avr-gcov-tool.exe
13/09/2017  00:24           390,656 avr-gcov.exe
13/09/2017  00:24         3,988,480 avr-gdb-py.exe
13/09/2017  00:24         3,831,296 avr-gdb.exe
13/09/2017  00:24           544,256 avr-gprof.exe
13/09/2017  00:24           942,080 avr-ld.bfd.exe
13/09/2017  00:24           942,080 avr-ld.exe
13/09/2017  00:24           502,272 avr-nm.exe
13/09/2017  00:24           629,760 avr-objcopy.exe
13/09/2017  00:24           730,112 avr-objdump.exe
13/09/2017  00:24           514,560 avr-ranlib.exe
13/09/2017  00:24           393,728 avr-readelf.exe
13/09/2017  00:24           502,272 avr-size.exe
13/09/2017  00:24           495,104 avr-strings.exe
13/09/2017  00:24           629,760 avr-strip.exe
              28 File(s)     21,442,048 bytes

So if I now switch to a directory where a program has been built and give the command:

C:\Users\uid23021\Documents\Atmel Studio\7.0\test1\test1\Debug>avr-nm test1.elf
00000076 T __bad_interrupt
00000062 T __ctors_end
00000062 T __ctors_start
00000096 A __data_load_end
00000096 A __data_load_start
0000ffa0 A __DATA_REGION_LENGTH__
00000062 T __dtors_end
00000062 T __dtors_start
00810000 D __eeprom_end
00010000 A __EEPROM_REGION_LENGTH__
00000002 A __FUSE_REGION_LENGTH__
00000000 W __heap_end
00000062 W __init
00000400 A __LOCK_REGION_LENGTH__
00000400 A __SIGNATURE_REGION_LENGTH__
0000003e a __SP_H__
0000003d a __SP_L__
0000003f a __SREG__
0000045f W __stack
00000094 t __stop_program
00020000 A __TEXT_REGION_LENGTH__
00000000 a __tmp_reg__
00000054 T __trampolines_end
00000054 T __trampolines_start
00000400 A __USER_SIGNATURE_REGION_LENGTH__
00000076 W __vector_1
00000076 W __vector_10
00000076 W __vector_11
00000076 W __vector_12
00000076 W __vector_13
00000076 W __vector_14
00000076 W __vector_15
00000076 W __vector_16
00000076 W __vector_17
00000076 W __vector_18
00000076 W __vector_19
00000076 W __vector_2
00000076 W __vector_20
00000076 W __vector_3
00000076 W __vector_4
00000076 W __vector_5
00000076 W __vector_6
00000076 W __vector_7
00000076 W __vector_8
00000076 W __vector_9
00000000 W __vector_default
00000000 T __vectors
00000001 a __zero_reg__
00800060 D _edata
00800060 D _end
00000096 T _etext
00000092 T _exit
00000092 W exit
00000054 T foo
0000007a T main

All of the code addresses in this are down near location 0. For a bootloader I'd expect these to be up near the BLS address. In fact "__vectors" should have the entry address. In this case that is 00000000.

 

But anyway your .hex file already confirms the location:

:1070000074C000008DC000008BC0000089C000006B

It's the 7000 in that, just after the start of the line that gives the address as 0x7000 which is about right for the bootloader location in a 32K micro. (it'a actually 28K so it's 4K from the end of the chip).

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

clawson wrote:

your .hex file already confirms the location:

:1070000074C000008DC000008BC0000089C000006B

It's the 7000 in that, just after the start of the line that gives the address as 0x7000 which is about right for the bootloader location in a 32K micro. (it'a actually 28K so it's 4K from the end of the chip).

 

 

OH I see. That will come handy one day. thanks for explanation.

Yes the .hex confirm the bot location , but what could i be missing. DO you think I need to set lock bits 

i'm thinking to use something like that 

boot_lock_bits_set (_BV (BLB11));

 

what you think 

 

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

AVATAR_Freaks wrote:
OH I see. That will come handy one day. thanks for explanation.
The full explanation (as for so many things in like) is on Wikipedia:

 

https://en.wikipedia.org/wiki/In...

 

So:

:1070000074C000008DC000008BC0000089C000006B

should be read as:

:10     7000  00    74C000008DC000008BC0000089C00000 6B
length  addr  type  data                             checksum 

As to your problems. Just never go anywhere near lockbits until you are finally ready to deploy the product and they won't trouble you - so as long as there's been a chip erase and reprogram (which resets everything to default) forget the lockbits as an issue - they won't affect this.

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

I am confused about your general setup.

 

#define BOOTLOADER_SECTION __attribute__ ((section(".bootloader"))) ;
...
static void do_spm_N (uint32_t address,  uint8_t *data) BOOTLOADER_SECTION;
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOT_START)

So the function is part of a normal application (located at 0x0000) where only the function is relocated to the boot sector?

static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

But then why are you using a function pointer to call the function?

How is it possible that the pointer can have the same name as the function itself?

Where is this pointer even initialized?

What sense does it make to put the pointer into the .bootloader section?

 

And even more confusing, you have now presented a HEX file which contains a whole application (with interrupt vectors and all) being located in the boot sector.

 

Stefan Ernst

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

When I've done this in the past I have used the fact that <avr/boot.h> already has a definition of a BOOTLOADER_SECTION macro to assign a section attribute.

/** \ingroup avr_boot
    \def BOOTLOADER_SECTION

    Used to declare a function or variable to be placed into a
    new section called .bootloader. This section and its contents
    can then be relocated to any address (such as the bootloader
    NRWW area) at link-time. */

#define BOOTLOADER_SECTION    __attribute__ ((section (".bootloader")))

Then I just wrote the rest of the code like "normal C" just applying that macro to the handful of functions that needed to remain visible while SPM was operating (the rest of the code just switches to all 0xFFFF opcodes). No special consideration was needed for making the calls from the app functions to the SPM functions. Just code it like normal C but keep in mind that fact about "things disappearing" so relocate all the functions that might be required while SPM executes. And that, basically, is all there is to it. (not forgetting to do the -section-start thing on ".bootloader" to place it at/above the BLS address

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

 

:10     7000  00    74C000008DC000008BC0000089C00000 6B
length  addr  type  data                             checksum 

 

is there a way to understand what "74C000008DC000008BC0000089C00000" actually means ?

ALso, If I erase and upload the bootloader , and the lockbits not set then i wont be able  to use SPM right ? 

 

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

sternst wrote:

I am confused about your general setup.

static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

 

 

The function called do_spm_N() lives in the bootloader sector which is located at address 0x7000 which is the start of the bootloader.

 

this is how i define it in my application which could be wrong:-

static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ; --> in application 

[

sternst wrote:

 

But then why are you using a function pointer to call the function?

I though this is the way i should call it from my application, how else can I called from the application? i tried to use "extern" but it didn't compile any suggestions ?

 

[

sternst wrote:

 

How is it possible that the pointer can have the same name as the function itself?

Where is this pointer even initialized?

 

 

SO how can I point to an external function that is not defined in my sketch ?

 

 

[

sternst wrote:

 

What sense does it make to put the pointer into the .bootloader section?

 

 

 

NO the pointer is in the sketch 

 

[

sternst wrote:

 

And even more confusing, you have now presented a HEX file which contains a whole application (with interrupt vectors and all) being located in the boot sector.

 

Yes it is a full application, but I only put the relevant parts :)

 

 

 

 

 

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

clawson wrote:

When I've done this in the past I have used the fact that <avr/boot.h> already has a definition of a BOOTLOADER_SECTION macro to assign a section attribute.

/** \ingroup avr_boot

#define BOOTLOADER_SECTION    __attribute__ ((section (".bootloader")))

 

this is basically what I'm doing.

 

 

clawson wrote:

Then I just wrote the rest of the code like "normal C" just applying that macro to the handful of functions that needed to remain visible while SPM was operating (the rest of the code just switches to all 0xFFFF opcodes). No special consideration was needed for making the calls from the app functions to the SPM functions. Just code it like normal C but keep in mind that fact about "things disappearing" so relocate all the functions that might be required while SPM executes. And that, basically, is all there is to it. (not forgetting to do the -section-start thing on ".bootloader" to place it at/above the BLS address

 

I feel like i taken care of all of that as you see previously, but i think maybe the way I call the function from my application 

 

SO when I upload my bootloader to the baord and run an application both RX& TX LEDs are on as a sold color (not flashing), like it gets stuck.

 

Only if there is a ways  to debug, when the application call Do_SPM_N , does the bootloader  goes to that function or no?

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

So actually you have a bootloader and the function do_spm_N is part of it?

 

Then all this is nonsense:

#define BOOTLOADER_SECTION __attribute__ ((section(".bootloader"))) ;
...
static void do_spm_N (uint32_t address,  uint8_t *data) BOOTLOADER_SECTION;
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOT_START)
static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

 

All you need in the application is a correctly initialized function pointer:

void (*do_spm_N)(uint32_t address, uint8_t *data) = 0xXXXX;

Replace 0xXXXX with the word address of do_spm_N within the bootloader.

Stefan Ernst

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

I wrote some words the other day (which turned out at the time to be misguided) about sharing bootloader functions to an application:

 

https://www.avrfreaks.net/commen...

 

You may find something of use there. The basic principle here is that the only piece of "shared knowledge" between the app code and the boot code is a 16 bit pointer passed from one to the other and also that each knows the order of entries in an array of function pointers (who's base address is passed as that 16 bit value). The actual routines in the boot code that are shared to the app can actually live anywhere in the bootloader space.

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

clawson wrote:

Simonetta wrote:
  This is never done.
As someone who has done exactly this - written to flash in an app ...

 

joeymorin wrote:
It is infrequently done, but 'never' is a long time.

 

Agree with "perhaps unusual but not unheard of".  I suppose one needs to put aside for the moment the merit of it?  I well might determine in an app that it might be easier/more cost efficient/smaller footprint to e.g. get a bigger model of the AVR family versus adding e.g. external flash or EEPROM or similar storage chip.

 

Atmel chose to put out an app note many years ago, with a sample application:

 

Butterfly Logger:  https://www.brokentoaster.com/bu...

 

Doesn't  ButtLoad store the ISP image into flash?

 

Arduino discussions:  (many)

https://forum.arduino.cc/index.p...

https://arduino.stackexchange.co...

 

 

Prior discussions here:  (many)

https://www.avrfreaks.net/forum/...

https://community.atmel.com/foru...

https://www.avrfreaks.net/forum/...

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

AVATAR_Freaks wrote:
skeeve wrote: An AVR's idea of the bootloader section depends on its fuses. The linker's idea of the .bootloader section depends on $(BOOT_START). Do they match? I 'm not sure how to check the fuses, any hint ? I am using a make file to compile . DO you mean BOOTSZ?
Yes.  Your IDE probably has a section for it somewhere.

If no IDE, avrdude can read them if you are not stuck with the wrong USB drivers.

The default bootloader section size is 0x1000 bytes.  Starts at 0x7000.

The smallest is 0x200 bytes.  Starts at 0x7E00.

If you place SPM at 0x7E00, the BOOTSZ bits won't matter.

 

Edit: correction

 

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

Last Edited: Fri. Oct 5, 2018 - 06:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
The smallest is 0x200 bytes. Starts at 0x7E00. If you place SPM at 0xFE00, the BOOTSZ bits won't matter.
Typo?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

joeymorin wrote:
Typo?

No, probably not.  App SPM writes must be from legal bootloader area, right?  So if (say) no bootloader, that would be  "safe" address irregardless of BOOTSZ fuse setting.

 

Note the reference to "fuse settings".  Lock bits and boot lock bits are a devildifferent matter. 

[hmmm--on second thought one probably needs to pay attention to BLB...]

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Fri. Oct 5, 2018 - 05:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But a 32K micro doesn't have flash at 0xFE00? That's up near the end of a 64K micro.
.
#1 mentions 32U4

Last Edited: Fri. Oct 5, 2018 - 05:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I wrote some words the other day (which turned out at the time to be misguided) about sharing bootloader functions to an application:

 

https://www.avrfreaks.net/commen...

 

You may find something of use there. The basic principle here is that the only piece of "shared knowledge" between the app code and the boot code is a 16 bit pointer passed from one to the other and also that each knows the order of entries in an array of function pointers (who's base address is passed as that 16 bit value). The actual routines in the boot code that are shared to the app can actually live anywhere in the bootloader space.

 

when i tried your method in the other form i came acorss this error 

 

 

 

Severity	Code	Description	Project	File	Line
Error		section .bootloader loaded at [00007000,00007001] overlaps section .text loaded at [00007000,00007f67]	SNSBootloader		1
Error		recipe for target 'Caterina.elf' failed	SNSBootloader	C:\Users\bghobreal\Documents\Atmel Studio\7.0\SNSBootloader\SNSBootloader\Makefile	652
Error		ld returned 1 exit status	SNSBootloader	collect2.exe	0

I wonder why the compiler complained when I tried to have a pointer to the function (do_spm_N) ; 

this is what I tried


 void do_spm_N (void)BOOTLOADER_SECTION;
typedef void(*P_do_spm_N)(void);
 P_do_spm_N functions[]={
	 do_spm_N
 };

and this 

 void do_spm_N (void)BOOTLOADER_SECTION;


int main(void)
{
	
	    TCNT1 = &do_spm_N;
	    :
	    :
	    :
	    :
	    ................
	    
}

 

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

theusch wrote:

joeymorin wrote:
Typo?

No, probably not.  App SPM writes must be from legal bootloader area, right?  So if (say) no bootloader, that would be  "safe" address irregardless of BOOTSZ fuse setting.

 

Note the reference to "fuse settings".  Lock bits and boot lock bits are a devildifferent matter. 

[hmmm--on second thought one probably needs to pay attention to BLB...]

 

yes but  0xFE00  way out of the boot section ,that wont work 

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

joeymorin wrote:

skeeve wrote:
The smallest is 0x200 bytes. Starts at 0x7E00. If you place SPM at 0xFE00, the BOOTSZ bits won't matter.
Typo?

Yes, will edit, though the statement is true as is :-)

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

Last Edited: Fri. Oct 5, 2018 - 07:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

I wrote some words the other day (which turned out at the time to be misguided) about sharing bootloader functions to an application:

 

https://www.avrfreaks.net/commen...

 

	TCNT1 = &functions;

 

what did you use TCNT1 , it compiles but it doesn't allow me to load to the MC

 

 

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

sternst wrote:

So actually you have a bootloader and the function do_spm_N is part of it?

 

Then all this is nonsense:

#define BOOTLOADER_SECTION __attribute__ ((section(".bootloader"))) ;
...
static void do_spm_N (uint32_t address,  uint8_t *data) BOOTLOADER_SECTION;
LDFLAGS += -Wl,--section-start=.bootloader=$(BOOT_START)
static void (*do_spm_N)(uint32_t address,  uint8_t *data)__attribute__ ((section(".bootloader"))) ;

 

All you need in the application is a correctly initialized function pointer:

void (*do_spm_N)(uint32_t address, uint8_t *data) = 0xXXXX;

Replace 0xXXXX with the word address of do_spm_N within the bootloader.

 

I tried that but it still doesn't work 

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

*Declare*do_spm_N in the application source.

"Define* it with the linker.  --define-symbol or something like that.

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

skeeve wrote:

*Declare*do_spm_N in the application source.

"Define* it with the linker.  --define-symbol or something like that.

 

I am not sure how can I define a function in the linker ?

Never done that before ?

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

DO I need to do anything with the bit locks ?

the manual says the following 

 

 

 

 

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

AVATAR_Freaks wrote:

skeeve wrote:

*Declare*do_spm_N in the application source.

"Define* it with the linker.  --define-symbol or something like that.

 

I am not sure how can I define a function in the linker ?

Never done that before ?

Define the symbol do_spm_N .

To find the correct value, look at the output of avr-nm bootloater.elf .

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

skeeve wrote:

AVATAR_Freaks wrote:

skeeve wrote:

*Declare*do_spm_N in the application source.

"Define* it with the linker.  --define-symbol or something like that.

 

I am not sure how can I define a function in the linker ?

Never done that before ?

Define the symbol do_spm_N .

To find the correct value, look at the output of avr-nm bootloater.elf .

 

 

 

What should I look for tho in the .elf file ?

 

 

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

AVATAR_Freaks wrote:
l i need to use the rest of my flash memory to save data

 

Static data?  i.e. known at compile time?  if so, then use flash keyword on your data array to store in flash

If dynamic, at run time, you do know the max writes to flash is about 10k times. i.e. if writing to only once per second, will only be usable for ~3 hours.

 

Jim

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

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

AVATAR_Freaks wrote:

skeeve wrote:

AVATAR_Freaks wrote:

skeeve wrote:

*Declare*do_spm_N in the application source.

"Define* it with the linker.  --define-symbol or something like that.

 

I am not sure how can I define a function in the linker ?

Never done that before ?

Define the symbol do_spm_N .

To find the correct value, look at the output of avr-nm bootloater.elf .

 

 

 

What should I look for tho in the .elf file ?

 

 

 

 

when I look at my .elf file I can't find do_SPM_N ???

 

 

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

I was looking at the linker ,

IS it okay that the .text and the .bootloader sets at the same address  location  ??

 

Address of section .text set to 0x7000
Address of section .bootloader set to 0x7000

 

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

AVATAR_Freaks wrote:
I was looking at the linker ,
IS it okay that the .text and the .bootloader sets at the same address  location  ??
Only if one is empty.

Note that in the normal course of events, the bootloader's .text section is in the AVR's bootloader section.

The bootloader is a complete program.

If you wish to have your application use a function in the bootloader.

The application will have to know its address, hence avr-nm .

If you do not know the function's name, that would be a problem.

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

skeeve wrote:

 

If you wish to have your application use a function in the bootloader.

The application will have to know its address, hence avr-nm .

If you do not know the function's name, that would be a problem.

 

Yes I know my function name, but when I run avr-nm I cant see my function, Hence I don't know the address ??

 

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

AVATAR_Freaks wrote:
Yes I know my function name, but when I run avr-nm I cant see my function, Hence I don't know the address ??
You sure that it is a function and not a macro?

If all else fails look at the bootloader's .lss file and look for the SPM instruction.

If your bootloader lacks an SPM, it won't work.

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

Last Edited: Wed. Oct 10, 2018 - 06:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

let me ask a simple question, I want to do a simple test 

I would like to have a CONSTANT value in my boot loader at specific adress and read it from my application how can DO that ?

 

can I do somthin like 

static uni32_t = 0x5a5a 

 

how Can i read it from the application ?

 

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

AVATAR_Freaks wrote:

let me ask a simple question, I want to do a simple test 

I would like to have a CONSTANT value in my boot loader at specific adress and read it from my application how can DO that ?

 

can I do somthin like 

static uni32_t = 0x5a5a 

 

how Can i read it from the application ?

 

You have your syntax wrong.

In any case, the application needs the address.

If it's in flash, you have roughly the situation you have with do_spm_N.

You'll need LPM.

In-ram also works.

You will need to go through some contortions to ensure

neither code writes over it before the app reads it.

End of RAM is probably best.

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

If you want to "share" a value from boot to app the best place to pass it is one of the SFRs. Modern AVRs have GPIOR0, GPIOR1, GPIOR2 for this purpose. Both "sides of the fence" already know the (unchanging) address of these storage locations.

 

Having said that you can actually use any (otherwise unused) SFR for this. In the past I have used TWAR and also TCNT1 as 8 or 16 bit registers that can just be used to pass some data.

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

clawson wrote:
f you want to "share" a value from boot to app the best place to pass it is one of the SFRs. Modern AVRs have GPIOR0, GPIOR1, GPIOR2 for this purpose. Both "sides of the fence" already know the (unchanging) address of these storage locations.
I'd thought they were wiped out by a watchdog reset.

"For every Christmas tree lit before Thanksgiving,
an elf drowns a baby reindeer"

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

Nothing to stop the bootloader setting the register AFTER the WDT reset (assuming there even is one).

 

As I've shown elsewhere, if the boot wants to share a table of function pointers to make certain routines (UART, SPM etc) available to the app, so it can save some of its flash, then the boot can pass the 16 bit base address of the dispatch table in some "known place" such as a 16 bit SFR. This negates the need for app/boot to share "internal addresses" such as might happen if, otherwise, the bootloader decided to fix such a table at 0x7FF0 or something like that. The only "common thing" is that single 16 bit pointer and a shared knowledge of the order of entries in the function pointer array.

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

clawson wrote:

Nothing to stop the bootloader setting the register AFTER the WDT reset (assuming there even is one).

 

As I've shown elsewhere, if the boot wants to share a table of function pointers to make certain routines (UART, SPM etc) available to the app, so it can save some of its flash, then the boot can pass the 16 bit base address of the dispatch table in some "known place" such as a 16 bit SFR. This negates the need for app/boot to share "internal addresses" such as might happen if, otherwise, the bootloader decided to fix such a table at 0x7FF0 or something like that. The only "common thing" is that single 16 bit pointer and a shared knowledge of the order of entries in the function pointer array.

skeeve wrote:

clawson wrote:
f you want to "share" a value from boot to app the best place to pass it is one of the SFRs. Modern AVRs have GPIOR0, GPIOR1, GPIOR2 for this purpose. Both "sides of the fence" already know the (unchanging) address of these storage locations.
I'd thought they were wiped out by a watchdog reset.

 

Okay so my understanding is if I use one of the sfrs or GPIOR I can pass a value between the application and the bootloader right? I will try that.

 

BTW, MY bootloader based on the Catrerina Bootloader , with some editing to it.

SHould I put the bootloader here if you guys wanna take a look at it ?

 

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

If you want to "publish" code you are far better off doing it on github, Microchip "Spaces", or similar.

 

(actually I see that Sparkfun and Adafruit each already have versions of "Caterina" on github too).

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

clawson wrote:

If you want to "publish" code you are far better off doing it on github, Microchip "Spaces", or similar.

 

(actually I see that Sparkfun and Adafruit each already have versions of "Caterina" on github too).

 

 

Yes, I know I want to have as a reference. Have you ever used the caterina or went through it ?

I am just afraid that there is something in that code disabling SPM , because every time i try to use my own function from the application the board freezes.

 

 

 

 

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

Actually looking at the caterina, it uses 

    /* Undo TIMER1 setup and clear the count before running the sketch */
    TIMSK1 = 0;
    TCCR1B = 0;
    TCNT1H = 0;        // 16-bit write to TCNT1 requires high byte be written first
    TCNT1L = 0;
    /

 

so I can't use TCNT1

Pages