Execute from external SRAM

Generic boards that are not Maple or Maple mini clones, and don't contain the additional USB reset hardware
User avatar
RogerClark
Posts: 5917
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Execute from external SRAM

Post by RogerClark » Sun Jan 08, 2017 10:59 pm

Victor

I presumed that Pito must have already been handling the stack etc before jumping to the Application code, as the sketch must be copying the Application from its static array into flash before it jumps

Returning back could be a bit tricky as you'd need to restore all registers etc as the Application will have left them in some unknown state.

To start with, I'd presume that you need to reboot to exit from your application code, and then sort out how to return later.
(As I presume the Application code, would need to have the Return feature built into it, as the sketch code, and its interrupts etc will no longer be functioning as soon as the Application code starts running.)

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

Re: Execute from external SRAM

Post by victor_pv » Mon Jan 09, 2017 1:55 am

RogerClark wrote:Victor

I presumed that Pito must have already been handling the stack etc before jumping to the Application code, as the sketch must be copying the Application from its static array into flash before it jumps

Returning back could be a bit tricky as you'd need to restore all registers etc as the Application will have left them in some unknown state.

To start with, I'd presume that you need to reboot to exit from your application code, and then sort out how to return later.
(As I presume the Application code, would need to have the Return feature built into it, as the sketch code, and its interrupts etc will no longer be functioning as soon as the Application code starts running.)
The last version I saw of his loader sketch just changes the SP register to the new one before jumping but does not save anything, specially not the current SP value.
About restoring all other registers, it depends what we do exactly after going back to the loader sketch. If we just restore the SP and finish that function with a return, there would be no need to save any register since they would be not used right?
Atherwise we could add some assembler code right before changing the SP to push all the general registers to stack, then chance the SP, call the EXRAM code, and upon return restore the SP, and pull all the registers from that stack, and then return the function.

For the interrupt you just need to restore the VTOR register to point back to the flash NVIC table, which is always at the start of flash, so it is a known value. But your comment make me realize the peripherals may also be in an unknown state. So yes perhaps a reset is the best to get everything in order.
Still the loader and the App codes could pass some information to each other with some area of RAM.

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

Re: Execute from external SRAM

Post by RogerClark » Mon Jan 09, 2017 4:38 am

Victor

I think "finishing" the function would require all registers to be pushed to the stack before the Jump to the Application, also the PC would need to be pushed onto the Application stack, so that the Application would know where to jump back to.

User avatar
Pito
Posts: 1109
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Execute from external SRAM

Post by Pito » Mon Jan 09, 2017 9:02 am

@Roger, upload of APPs to EXRAM directly from IDE is good for testing of the basic functionality of EXRAM, but for the actual usage I think not so much, because the EXRAM is volatile.
So the only way people would like imho is to use a media connected to the MCU for the storing of binaries, ie SDcard, internal flash, external flash, usb flash, punch tape :)

Returning to xLOADER from EXRAM's APP is vital, SO IT MUST BE SOLVED WITH HELP OF THE EXPERTS HERE, as then you can create an xLOADER (I do not want to name it an "OS" as it might happen I would be banned here :) ) which, when connected to an SDcard via SdFat, will list for example:

Code: Select all

Hello Roger from xLOADER v3.12 !
> dir
24567 APPs found
APP1.bin APP2.bin ...
.. APP24567.bin
> run APP3.bin
Hello World from EXRAM!!!
> run APP2238.bin
Whetstone..
> date
2017 01 09
> time
10:02 AM
>
To write such an xLOADER may take 1 hour for a talented sw guy from here (not me..).

PS: pls read this thread always also few my posts backwards as I edit/add some information I mess/forget.
I write and post and read and fix..
Pukao Hats Cleaning Services Ltd.

User avatar
Pito
Posts: 1109
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Execute from external SRAM

Post by Pito » Mon Jan 09, 2017 9:34 am

Here is the xLOADER v1.01

Code: Select all

// THE xLOADER v1.01
//
// LOADS an USER APP binary into the EXRAM and RUNS the APP off the EXRAM
// The APP must fit into EXRAM (text, data, bss, heap, stack)
// The bin.h includes the APP.bin in form of (for example):
//
//    static const unsigned char bin[] = {
//       0x00, 0xf8, 0x07, 0x68, 0x39, 0x06, 0x00, 0x68, 0x91, 0x09, 0x00, 0x68,
//       0x95, 0x09, 0x00, 0x68, 0x99, 0x09, 0x00, 0x68, 0x9d, 0x09, 0x00, 0x68,
//       ..
//       0xb8, 0x52, 0x00, 0x68, 0x78, 0x4d, 0x00, 0x68
//    };
//    unsigned int bin_len = 25844;
//
// The bin.h could be generated from APP.bin by a tool called "xxd"
//
// More info at stm32duino forum
// No warranties of any kind. Provided as is. Use at your own risk.
// by Pito January 8th 2017
//

#include "bin.h"

__attribute__( ( always_inline ) ) static inline void __set_CONTROL(uint32_t control) {
  __asm volatile ("MSR control, %0" : : "r" (control) : "memory");
}
__attribute__( ( always_inline ) ) static inline void __set_MSP(uint32_t topOfMainStack) {
  __asm volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
}

typedef  void (*pFunction)(void);
#define ApplicationAddress       ((uint32_t)0x68000000)
#define __IO volatile
pFunction Jump_To_Application;
__IO uint32_t JumpAddress;

// Start of FSMC SRAM BANK 1, REGION 3
static uint8 *const sram_start8 = (uint8*)0x68000000;
#define EXRAM8(x) (*(sram_start8+x))

// Start of the APP Vector Table in IRAM
static uint8 *const iram_VT = (uint8*)0x2000FC00;
#define IRAMVT(x) (*(iram_VT+x))

void nvicDisableInterrupts() {
  NVIC_BASE->ICER[0] = 0xFFFFFFFF;
  NVIC_BASE->ICER[1] = 0xFFFFFFFF;
  NVIC_BASE->ICPR[0] = 0xFFFFFFFF;
  NVIC_BASE->ICPR[1] = 0xFFFFFFFF;

  /* disable the systick, which operates separately from nvic */
  systick_disable();
}

void setup() {

  Serial1.begin(115200);

  // wait on USB
  // while(!Serial.isConnected()){};

  int i;
  uint32 elapsed = micros();
  // copy the APP.bin into the EXRAM
  for (i = 0; i < bin_len; i++) {
    EXRAM8(i) = bin[i];
  }
    elapsed = micros() - elapsed;
    Serial1.print("Loading the APP.bin took ");
    Serial1.print(elapsed);
    Serial1.print(" usecs");
    Serial1.println(" ");

  // print out first 8 and last 8 bytes of the APP binary stored in EXRAM for a check
  // if the FSMC does not work properly, the "FF"s will be returned
  for (i = 0; i < 8; i++) {
    Serial1.print(i);
    Serial1.print(" ");
    Serial1.println(EXRAM8(i), HEX);
  }
  for (i = bin_len - 8; i < bin_len; i++) {
    Serial1.print(i);
    Serial1.print(" ");
    Serial1.println(EXRAM8(i), HEX);
  }

  // copy the APP Vector_Table to IRAM (ie. starting from 0x2000FC00)
  for (i = 0; i < 512; i++) {
    IRAMVT(i) = bin[i];
  }

  Serial1.println("Starting the APP.bin:");
  delay(10);  // wait till Serial prints all the chars out

  /* jump to USER APP code loaded in EXRAM memory and execute it!! */

  JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
  Jump_To_Application = (pFunction) JumpAddress;

  nvicDisableInterrupts();

   // set the new VTOR
  *(int volatile*)0xE000ED08 = (volatile uint32_t) 0x2000FC00;

  /* initialize USER APP Stack Pointer */
  __set_CONTROL(0); // Change from PSP to MSP
  __set_MSP(*(__IO uint32_t*) ApplicationAddress);

  Jump_To_Application();
}

void loop() {
}
Last edited by Pito on Mon Jan 09, 2017 11:55 am, edited 5 times in total.
Pukao Hats Cleaning Services Ltd.

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

Re: Execute from external SRAM

Post by RogerClark » Mon Jan 09, 2017 9:39 am

@pito

Edit. I just noticed you posted while I was writing this. So I've not read your code yet.



I know EXRAM is volatile, so I presumed that you wanted to store the Application code on a SD card, and then load in whichever Application you have on the SD.

My thought, was also that you would want a simple way to create the Application, in the IDE and upload it to the board (for the board to store in EXRAM and also in SD), or perhaps, straight to SD and then load EXRAM from SD later.


Anyway, back to returning from the Jump to the Application in EXRAM:

I think...

In order to return, you will need to push all the regs onto the stack, then switch stack to the EXRAM stack and do your other setup e.g. VTOR table, and then, push the return address (PC + x ) onto the EXRAM stack, and them Jump to the EXRAM Application start

When the application has finished, you will need to pull the return address PC from the EXRAM stack, and then jump to that location.
The Main code then needs to restore its unwind, change the stack address and restore registers from stack etc

stevestrong
Posts: 1139
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Execute from external SRAM

Post by stevestrong » Mon Jan 09, 2017 9:48 am

Just as a layman for return from RAM App to Flash: wouldn't be this handled automatically by the CPU when returning from

Code: Select all

Jump_To_Application();
?

User avatar
Pito
Posts: 1109
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Execute from external SRAM

Post by Pito » Mon Jan 09, 2017 10:01 am

Also the user APP usually ends with an endless loop.. Or can we stop it with CTRL_Q for example ?? :)
Let us think for a while.
A code samples will be welcomed. But better when you own a board with a SRAM on it. Porting to other board is easy (when you have done it once :) )
Usually this kind of exercise ends up with something called **ix kernel :) :)
But for 2017 let us set a goal to create an xLOADER which can load/run/reload/rerun SDcard stored APP binaries based on a very simple "command line interpreter" as depicted above.. A Sunday's exercise when we tackle the return from an APP running in the EXRAM back to the CLI (command line interpreter)..

Here is a GUIDE - a short intro we may enhance slowly http://www.stm32duino.com/viewtopic.php ... 100#p22119
Pukao Hats Cleaning Services Ltd.

stevestrong
Posts: 1139
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: Execute from external SRAM

Post by stevestrong » Mon Jan 09, 2017 10:31 am

Pito wrote:Also the user APP usually ends with an endless loop.. Or can we stop it with CTRL_Q for example ?? :)
And I thought a main loop, or any usual "int my_function()" would end normally with a "return (int);" :?
What about collecting all the info on a wiki page?

User avatar
Pito
Posts: 1109
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Execute from external SRAM

Post by Pito » Mon Jan 09, 2017 10:57 am

FYI - I've found in my junk box from some older projects:
1Mx16 10ns
mem2MB.jpg
mem2MB.jpg (7.6 KiB) Viewed 179 times
2Mx16 55ns
mem4MB.jpg
mem4MB.jpg (15.93 KiB) Viewed 179 times
4Mx16 70ns
mem8MB.jpg
mem8MB.jpg (8.67 KiB) Viewed 179 times
Last edited by Pito on Mon Jan 09, 2017 5:01 pm, edited 1 time in total.
Pukao Hats Cleaning Services Ltd.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest