Question or suggestion, upload to Flash, then copy to RAM at runtime.

STM32duino bootloader aka Maple bootloader
victor_pv
Posts: 1739
Joined: Mon Apr 27, 2015 12:12 pm

Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by victor_pv » Fri May 15, 2015 3:27 pm

I was just thinking, that some people seems to need speed for some things, and as we noticed when moving PIN_MAP to flash, running from Flash is quite slower than RAM apparently.

So in that line of thiking, I thought, what if you need to run a sketch that fits in RAM (i.e. in a 64Kb device), you need all the speed you can get for whatever reason, but you need the sketch to be permanently on the board, not upload to RAM each time?
I think the solution could come in the form of a bootloader that stores the code in flash, not RAM, then on device boot up it copies that code to RAM, and start running there, like it if it was uploaded with the DFU option to upload to RAM, only it saves it permanently in Flash and copies it over to RAM each time.
That gives the advantage of the speed, while keeping the sketch permanently on the board.

Does anyone need the extra speed? I already have thought on a way to do it without much more code in the bootloader.

User avatar
Rick Kimball
Posts: 1056
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by Rick Kimball » Fri May 15, 2015 6:24 pm

You want to use the linker and some custom startup code to copy your routines from flash to ram at reset. This post should give you an idea of what needs to happen:

https://forum.sparkfun.com/viewtopic.ph ... 61&start=0

-rick
-rick

victor_pv
Posts: 1739
Joined: Mon Apr 27, 2015 12:12 pm

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by victor_pv » Fri May 15, 2015 6:56 pm

Rick, the copy to RAM part could be integrated in the DFU bootloader, just as another option, so it wouldn't need any extra at compile time of the sketch if the bootloader manages the copy process.
My question I guess is, does this look like something useful for anyone?
It just occurred to me that should be fairly easy to add to the maple DFU bootloader, but I dont know if anyone here had found himself needing that.

User avatar
Rick Kimball
Posts: 1056
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by Rick Kimball » Fri May 15, 2015 6:59 pm

Modify your common.inc file and add a '.ramtext' section in the data area:

Code: Select all

$ git diff -w common.inc
diff --git a/STM32F1/variants/generic_stm32f103c/ld/common.inc b/STM32F1/variants/generic_
index 0c2b6a4..ebac91d 100644
--- a/STM32F1/variants/generic_stm32f103c/ld/common.inc
+++ b/STM32F1/variants/generic_stm32f103c/ld/common.inc
@@ -140,6 +140,9 @@ SECTIONS
         *(.got.plt) *(.got)
         *(.data .data.* .gnu.linkonce.d.*)
 
+        . = ALIGN(4);
+        *(.ramtext)
+
         . = ALIGN(8);
         __data_end__ = .;
       } > REGION_DATA AT> REGION_RODATA
(END)
Then in your code use an attribute to set the section name ".ramtext" for the ram_delay() function. This forces the code to stored in flash but the linker will set the execution addresses to ram at run time. The c init function that copies the data variables from flash to ram will now also copy your code into ram.

Code: Select all

/*  Show use of .ramtext */

__attribute__((section(".ramtext"))) void ram_delay();

void ram_delay() {
  volatile unsigned x = 10000;
  do {
     __asm__("nop");
  } while(--x);
}

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(PC13, OUTPUT);
}
 

// the loop function runs over and over again forever
void loop() {
  digitalWrite(PC13, LOW); // turn the LED on
  delay(200);                // wait
  digitalWrite(PC13, HIGH);// turn the LED off
  delay(800);              // wait
  ram_delay();
}
Now when I run it under the debugger and break in the ram_delay() function. You can see the execution address start with 0x2000xxxx.
ramtext.png
ramtext.png (137.61 KiB) Viewed 1248 times
-rick

User avatar
Rick Kimball
Posts: 1056
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by Rick Kimball » Fri May 15, 2015 7:06 pm

And yes this feature is certainly useful if you have code that you want to run with zero wait states. However, if you are bouncing back and forth between flash and ram, the veneer code overhead might wipe out any performance gains you make.

Compile up that code and disassemble it look for the ram_delay veneer function to see all the code is executed before it jumps to the ram code.

-rick
-rick

User avatar
Rick Kimball
Posts: 1056
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by Rick Kimball » Fri May 15, 2015 7:33 pm

Sorry I think I got your question all wrong.

However, you could modify the ldscript to put only the __start__ code and the interrupt vectors into "rom" and have the rest of the code stored in the the REGION_DATA and then the linker would resolve all of the execution addresses to ram. The only veneers in this case the ctors and the call to main. Everything else would be in ram.
-rick

victor_pv
Posts: 1739
Joined: Mon Apr 27, 2015 12:12 pm

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by victor_pv » Fri May 15, 2015 9:48 pm

I was thinking on 2 possible ways. Something like that, modifying the linker script so the code goes to RAM positions. Do you think it would work and the start code would copy all that from flash to RAM like it copies the variables area? or perhaps the assembler code that needs to do the copy would need to be modified?

The other way I thought, letting the linker script like in the upload to RAM option, but then in the bootloader code, set some check, that if the reset vector
(which I believe is the second word of the upload as the first one is the stack address) is in an address in the RAM range 2xxxxxxxx address, rather than call the code right away, first copy it to RAM, then run it. That would eliminate the need to make a different linker script, but add a bit of complexity to the bootloader. Still I think it should not be to complicated, something like this should work:

Code: Select all

if (checkUserCode(USER_CODE_FLASH0X8002000+4)) 
copySketchToRam ();
jumpToUser(USER_CODE_RAM);
}
checkUserCode would need to check for a pattern that covers the whole 64KB of RAM, that's 20000000 to 2000FFFF, so (... && FFFF0000 == 20000000) is a positive, that is slightly different than what we check for right now for the sp, so may need to add a second function for that.

And copySketchToRam is the only new function, it would just copy whatever fixed size is the maximum allowed to RAM.
We don't even need a new Upload ID, ID2 could work. As long as the second word in the sketch storage area is an address in the RAM range, it would do the copy and then run from there. So it would like with the option to run from RAM, but upload with the options to upload to flash, so it saves it to flash space.

I'll give this a shot later and see what happens, shouldn't blow up the board anyway ;)

victor_pv
Posts: 1739
Joined: Mon Apr 27, 2015 12:12 pm

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by victor_pv » Sat May 16, 2015 1:00 am

Well I just implemented pretty much as shown above, and works fine.
I can upload to RAM, upload to flash ID1 in x5000, upload to flash ID2 x2000, and upload to flash ID2 an sketch linked with the normal RAM script, and the bootloader detects it correctly and copies it from flash to RAM and run it from there.
Takes about 200bytes more than before, although I am sure that can be reduced, and is still just 7.1KB

User avatar
RogerClark
Posts: 7442
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by RogerClark » Sat May 16, 2015 6:20 am

Victor,

I'm not sure how many people would want to run from RAM. I can see it could make the code run faster than in Flash, but I'm not sure how much faster.

I've not looked into this in detail, but the ARM processors have complicated pipelining of instructions with prefetch etc
see http://infocenter.arm.com/help/index.js ... GJICF.html

So I suspect the gains you get many not be as much as just comparing flash vs ram speeds


Also.
I'm not too sure how you are working this. Are you getting the bootloader to upload to Flash, but doing a pre-copy from flash into ram each time it boots up

How does the bootloader know that the Flash contains a program that has been linked to run in RAM ? Or are you saying this only works after upload, i.e it uploads to flash and then copies to RAM?

The issue I had with the RAM based upload, was that after a RAM upload, for some reason the bootloader didn't just jump to the RAM start location, it seemed reset the bootloader, in which case it would have no definite way to know whether the last upload was to RAM or flash

The only way I could see to do it, was to put a magic number into RAM, to indicate that the last upload was to RAM and hope that the sketch would never put the same magic number into the same location in RAM. i.e it could be made to work for 99.999% of the time, but I could not make it work 100% of the time because I'd have no way to guarantee what the sketch was going to put into the RAM (at the magic number location)

User avatar
zoomx
Posts: 540
Joined: Mon Apr 27, 2015 2:28 pm
Location: Mt.Etna, Italy

Re: Question or suggestion, upload to Flash, then copy to RAM at runtime.

Post by zoomx » Mon May 18, 2015 4:18 pm

Maybe this work can be done by the program itself that has a routine that copies the other part from flash to RAM and then start it.

Post Reply