[C] AVR writing/reading pages from FLASH using gcc

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

Hi,

I've been trying to modify the source code code from  app note AVR106 to

be used in AVR Studio and GCC compiler without success.

These days, is it recommended to use that code (for IAR ide), or

we should use the functions from <avr\boot.h> ?

 

I do not want to use bootloader sections at all, and have no intentions of

using bootloader. I just want to use the extra free internal FLASH space, but from

runtime. I exhausted internal EEPROM on AtMega88 and need aditional

memory for storing some permanent data. The data is to be updated in

a page write manner not more than once in a week. The data is to be read

in either a page read to RAM, or read byte-by-byte.

 

I know there are a couple of threads here and there on these forums, but,

I'm afraid, none of them has completely and in detail addressed this issue.

 

Suggestions ?

 

 

This topic has a solution.

Last Edited: Mon. Jan 5, 2015 - 05:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can read flash memory from anywhere.

You can only write to flash memory from the Bootloader area.    e.g. with two words: SPM, RET

 

If you are not prepared to allocate two words in Bootloader area,   you can NOT write to flash.

 

You can always use an external I2C or SPI EEPROM

 

David.

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

Hi David,

 

if you already have tons of PCB assembled, you can not add

external components (actually you can, but, would not look

nice and pro).

Anyway,

 

You can only write to flash memory from the Bootloader area

 

can you elaborate on this?

From this one, I see: NO, you can not write in FLASH from regular program

execution ?

Is there any way of doing this or not, some context switching or anything ?

 

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

You read the data sheet.  especially SPM opcode and related registers.

 

Alternatively,   you read some of the many Bootloader/Flash tutorials.

 

Or just adapt the example program that comes with the <avr/boot.h> documentation.

 

David.

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

I see that for ATmega88,

setting lock bit protection modes is possible to

No restrictions for SPM or LPM accessing the application section.

and

No restrictions for SPM or LPM accessing the boot loader section.

 

so, if I understand correctly from this datasheet,

we should be able to access both FLASH areas. That's clear.

But, other than that, nothing seems to be clearly defined.

I do not want my "regular" program to execute from boot memory

area, or do I ?

 

The Application section can never store any
Boot Loader code since the SPM instruction is disabled when executed from the Application
section.

 

Last Edited: Mon. Jan 5, 2015 - 04:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sit down with a nice cup of tea.    Write down what you want your program to do.  (specification)

 

Then design your solution.    This will involve paper and more cups of tea.

 

It appears that you (or a colleague) has already produced a pcb.

Before you have even written a spec !!

 

Yes,   you can do many things with a microcontroller.    But you need to have some idea of expected size, speed, quantity of data.

And it is never wise to rule out a solution before you have investigated it.

 

David.

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

This is one of those places where you might NOT find all of the necessary information in one location. And, you might end up with seemingly contradictory "information".

 

The quote about SPM being disabled under certain conditions has primacy over everything. 

 

Within that limitation, the previous two quotes about LPM & SPM are completely valid. Those two tell you what the two instructions CAN ACCESS. The single quotation tells you where SPM CAN EXECUTE. So, there is no contradiction. In this case, you need to look at the quotations very carefully.

 

Jim

 

 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Why is this thread in "Tutorial" with a tutorial style "[TUT][C]" in the thread title? It's a question not an article to teach others?!?

 

I'm sort of assuming the question is about tiny/mega so I'll move this to that forum for starters.

 

Moderator.

 

(PS very surprised you could find nothing on doing SPM from the BLS - I've written literally hundreds of posts on the subject at various times and I'm not alone!)

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

Doing SPM from BLS - yes there are articles,

but doing SPM from application - no. I was wondering

if this could be possible to achieve at all.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your reply conveys your misundertsanding. You don't get a choice about this (well only on the smallest AVr Tiny chips that have no BLS). For almost all mega AVR the SPm opcode can *ONLY* execute successfully in the BLS so the code that does it must live there.

 

I think you may have got your terminology confused. Presumably what you meant to say was that you could find many examples of SPM being done in bootloader programs but few/none in application programs. Well here's your magic search term (well for avr-gcc anyway but as you mentioned boot.h I assume that's what you use). The term is BOOTLOADER_SECTION. As I wrote in the Bootloader FAQ (still well worth a read even if you aren't writing a bootloader!) the macro is a misnomer. It's called "BOOTLOADER_SECTION" yet it has nothing to do with writing a bootloader and everything to do with adding SPM code to an application.

 

You will still, typically, use the bootloader_program_page() example from the top of <avr/boot.h> but instead of it being built into a standalone bootloader program you just add the routine to your other C code but the interface:

void boot_program_page (uint32_t page, uint8_t *buf)
{

becomes:

BOOTLOADER_SECTION void boot_program_page (uint32_t page, uint8_t *buf)
{

All the BOOTLOADER_SECTION macro actually does is:

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

but what this means is that when you build your application you can include a linker command to say:

-Wl,-section-start=.bootloader=0x1234

and the code of boot_program_page() (which contains the SPM) will be located at address 0x1234.

 

Obviously 0x1234 is not the right value but you replace this with the BYTE (not Word!) address of the BOLS in your chip and this ensures that your SPM routine is located up at the BLS. Now when main() in the app calls boot_program_page() it is calling code that execute at/above the BLS so the SPM in it will work.

 

(I swear this must be the 50th time I've typed an almost identical reply to this! I'm sure a search for BOOTLOADER_SECTION will hot almost al those prior threads - many have more detail than I typed here)

 

((oh and read the bootloader FAQ!))

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

OK I typed BOLS when I meant BLS. But I rather like it as a typo so I think I'll leave it!! :-)
 

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

Thanks,

 

I really think (without joking) this one is the most complete

post about this issue. Actually one of your post answers

triggered me to even try this and after not succeeding the task,

to again start such thread here.

 

I knew I could force parts of code into BLS section, I used bootloaders

before, but, I was not aware of the fact you could from application section

"just" call a function which is located in BLS (and that this would enable SPM).

 

Thanks again.

 

(and I am just reading bootloader FAQ   :)  

Last Edited: Mon. Jan 5, 2015 - 06:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought that I made it pretty clear that you only need SPM and RET in the BLS in message #2

 

You simply set up all your registers in application space,   and CALL do_SPM    (in the BLS area)

Ok,  this would be RCALL do_SPM in a mega88.

 

David.

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

I really think (without joking) this one is the most complete

post about this issue.

And yet I know it isn't. I have made much more detailed posts about this in the past. I was going to prove that point by listing just 10 threads where I have previously gone into more edtail about "BOOTLOADER_SECTION" but I just went to the search engine here, typed "BOOTLOADER_SECTION" then planned to filter on "author = clawson" except that when I expand the list of authors my name does not appear as the author in any of the 1,005 hits it apparently found. I find this frankly astonishing. I rather suspect that the search here is presenting "author" as meaning "author of the original thread where the point about BOOTLOADER_SECTION came up" rather than "author of the post that mentioned BOOTLOADER_SECTION". As such the search engine is useless so I give up.

 

(But I still know you are wrong! However if I cannot even find my own posts I sympathize with others trying to use this search engine for real).

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

Quote:
I rather suspect that the search here is presenting "author" as meaning "author of the original thread where the point about BOOTLOADER_SECTION came up" rather than "author of the post that mentioned BOOTLOADER_SECTION". As such the search engine is useless so I give up.
Bingo.

 

Filter these:

https://www.google.ca/search?q="BOOTLOADER_SECTION"+"clawson"+site%3Aavrfreaks.net

"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."

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

 

Last Edited: Tue. Jan 6, 2015 - 01:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

However if I cannot even find my own posts I sympathize with others trying to use this search engine for real).

I use the search on the legacy site to find posts I know are there. legacy.avrfreaks.net

 

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

Yes, if you narrow your search with a couple more words

you will find a hit of what you are searching. 

Only if you knew what words you should search for.

 

Anyway, I already said, I am thankful for pointing me to the

right direction and reminding me to read Bootloader faq.

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

One more question here guys,

 

            program_page(starting_address, array_keys);
     bbe:    ae 01           movw    r20, r28
     bc0:    4f 5f           subi    r20, 0xFF    ; 255
     bc2:    5f 4f           sbci    r21, 0xFF    ; 255
     bc4:    9d d9           rcall    .-3270       ; 0xffffff00 

 

this is from .lss, so I am not so sure about this rcall ?

I put my .bootloader section on 0xF80 (word) address,

so, this rcall does not look ok to me.

 

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

0xF80 << 1 = 0x1F00 (in bytes)

 

I would agree that the GCC disassembly is really confusing,   but hey-ho,   that is what you get.

 

Run it in the Studio Simulator.   See for yourself.

I presume that you are using an 8k AVR and the RCALL is relying on the "wrap"

 

David.

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

Just to thank you once again guys,

and to present my final working solution (and explain why i found it could be a good solution as opposed to making new hardware)

 

So once again, I had hardware platform built on Atmega 88pa for rfid key reading, and sending this key ID to a remote cashiers desk.

So no need for ANY non-volatile memory, cause, nothing needed to be saved on the device. More then 400 devices assembled

and about 50 devices remained = laying around = waiting to be used in some new project.

 

Another project just popped-up, and need for a local storage of 350 x 4 byte (used only part of the full Mifare 1K rfid serial code).

I used a couple of bytes from EEprom for some parameters (output relay on/off times, and similar params.), and the rest for keys

(serial numbers of keys). And here is the problem: EEprom memory was not enough, and i knew that mcu is capable of self-flash 

writing. After looking at code examples for bootloader (which we used for Atmega, but separate project in AStudio), I could not be

positive is it possible to make this code jumps and parameter passing back and forth. The resolution here was viable, so to use 1.5k of

unused flash code and make it as a permanent (more or less) storage. The algorithm was:    

  • use EEprom as a primary storage (more writing cycles) when adding keys, and
  • only when EEprom full -> move all EEprom keys to Flash

If I used 112 keys in EEprom, then I would move 112 x 3 x 4 bytes (using SPM page writes, 7 pages to move 112 EEprom keys)

The reading of keys is both from flash and from EEprom (EEprom keys mirrored in RAM so, faster traversing a set of keys) when key detected. 

 

There is NO operation delete keys one by one, only erase ALL keys. So we avoid wear-off flash, and will not exceed this 10k cycle

of writing to it. One would call it a fancy resolution, while others would suggest "make more specification" before making hardware and drink more tea :)   

So, in the end, a couple of days spent here on the forum, and up to 12h programming and testing the solution and we're good to go. 

 

Miroslav

 

 

 

Last Edited: Tue. Jan 20, 2015 - 01:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Historical anecdote. Atmel got famous making eeproms. HC11s were just cpus, so you had to hang a ram and a rom on the board with the cpu to make a computer. I had a Tech Arts HC11 with an Atmel 32K eeprom. There was no eeprom in the hc11, so if one wanted to save config params like you can in an avr, you had to use this trick: Block move a "position independent" subroutine from rom to ram. This subroutine picks up a byte and an address from a location in ram and writes it to the eeprom, then returns from ram to rom to continue execution. The eeprom goes "busy" for 4ms when you write the byte to it, so the cpu cant be running and fetching instructions from the eeprom you are writing to. Man, I walked around all puffed out like Foghorn Leghorn when I got that to work. This worked on the HC11 because you could load some instructions into ram and jump to them and theyd execute just fine. I think the AVR FPSLIC has instruction ram, but its sort of an odd bird. But it runs at 44MHz!

Imagecraft compiler user

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

There was no eeprom in the hc11,

Lots of EEPROM on the HC811, I used to run the entire code on that. wink

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Well, I guess the HC11ED0 that Tech Arts used didnt have the internal eeprom because they expected you to marry it up to an external one. Sorry about remembering wrong from over a decade ago.

 

Imagecraft compiler user