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
Pito
Posts: 1498
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: Execute from external SRAM

Post by Pito » Wed Jan 11, 2017 3:30 pm

zmemw16 wrote:..
this one ranged from £11.46 to £12.77
https://www.aliexpress.com/item/Free-sh ... 0.0.4i6Xle

btw there's a slightly smaller pcb 407VET variant, no sram pads underneath.

order date to delivery varied from 18 to 33 days

stephen
I've got it :). Nice board! V3.0, 407ZET6 on it, SRAM pads from the bottom side. Sdcard socket from top. CR1220 holder. Big Jtag connector (great, I got the cable).
Pukao Hats Cleaning Services Ltd.

zmemw16
Posts: 1369
Joined: Wed Jul 08, 2015 2:09 pm
Location: St Annes, Lancs,UK

Re: Execute from external SRAM

Post by zmemw16 » Wed Jan 11, 2017 5:57 pm

i put a bad picture of the small one on the wiki awhile back.
if you follow the links for the variant below, there's a 'user guide', schemetic and sample code.(not sure for which board)
code probably for SPL and uvision5(??)

soldering 0603 resistors, intending to use finger nail holding one in place, tiddlywinks, find resistor

stephen

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

Re: Execute from external SRAM

Post by Pito » Wed Jan 11, 2017 7:29 pm

My Sdcard Logger with FIFO under FreeRtos - http://www.stm32duino.com/viewtopic.php ... ifo#p19835
from EXRAM, allocated ~260kB (10k records) for FIFO buffer:

Code: Select all

Sketch uses 37,544 bytes (7%) of program storage space. Maximum is 524,288 bytes.
Global variables use 296,496 bytes of dynamic memory.
Works, writes data to Sdcard as expected.

Code: Select all

Loading the APP.bin took 19573 usecs
0 0
1 F8
2 7
3 68
4 79
5 34
6 0
7 68
37536 20
37537 28
37538 30
37539 38
37540 D8
37541 79
37542 0
37543 68
Starting the APP.bin:
Type any character to begin
Type any character to end
Done..
I set sampling period a bit shorter, so it slowly consumes the FIFO - for demonstration purposes only :)
LOGGER_EXRAM.JPG
LOGGER_EXRAM.JPG (33.99 KiB) Viewed 389 times
Pukao Hats Cleaning Services Ltd.

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

Re: Execute from external SRAM

Post by Pito » Thu Jan 12, 2017 10:26 am

Update: SdFat's bench, from EXRAM, F_CPU=128M, SPI=32MHz
A 50% speed up with read :)

Code: Select all

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1073.50,97293,5571,7617
1131.34,96151,5570,7227
1157.28,96051,5570,7062
1061.64,96890,5570,7699
1086.09,96610,5570,7530
1108.75,96572,5570,7375

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1278.04,7996,5729,6405
1279.34,8089,5723,6396
1279.34,8081,5744,6399
1279.02,8081,5723,6400
1279.34,8103,5726,6401
1278.69,8741,5720,6401

Done
Type any character to start
Pukao Hats Cleaning Services Ltd.

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

Re: Execute from external SRAM

Post by victor_pv » Thu Jan 12, 2017 1:27 pm

Some interesting reading about routine calls in ARM:
http://infocenter.arm.com/help/topic/co ... /ATPCS.pdf

I haven't finished it yet, but so far I understand the job of saving the SP and registers is left to the Called routine, not the calling one.
Since from the loader the called routine is the startup assembler code the linker script places at the start, and we change the SP already before calling it, I think we need to manually provision for saving that before the call.
R0-R3 do not need to be preserved by the called routine. So we need to do this from the loader:
1. Save R4-R11 to the stack
2. Save SP to a known iram position (just a pointer type variable should work).
3. Save a return address somewhere (exRAM or IRAM?).
4. Change SP
5. Call App
----
6. (Return address pointing to this instruction). Load SP from variable in step 3.
7. Pop R4-R11 from stack.
8. Reconfigure NVIC VTOR.
9. Enable interrupts

From the app, to return, we have to:
1. Disable interrupts.
2. read the address saved in step 3 above.
3. load it to the PC, that will take the PC to step 6.

The peripherals state will be indeterminate at that point. Specially the USB peripheral, and any other using a buffer, since the buffer address was probably changed, and other configuration registers too.

EDIT: The more I think about it, the more I think it may be better to reset the MCU to restart the program in flash when the app is finished like Roger suggested, otherwise there too many things to control.
Of course you can make sure the Loader and the app do not use the same peripherals, so the peripherals for the loader have not changed state on return, but that limits what you do. Seems better to just reboot and let the loader pick a new app.
Last edited by victor_pv on Thu Jan 12, 2017 1:36 pm, edited 2 times in total.

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

Re: Execute from external SRAM

Post by victor_pv » Thu Jan 12, 2017 1:30 pm

Pito wrote:Update: SdFat's bench, from EXRAM, F_CPU=128M, SPI=32MHz
A 50% speed up with read :)

Code: Select all

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1073.50,97293,5571,7617
1131.34,96151,5570,7227
1157.28,96051,5570,7062
1061.64,96890,5570,7699
1086.09,96610,5570,7530
1108.75,96572,5570,7375

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1278.04,7996,5729,6405
1279.34,8089,5723,6396
1279.34,8081,5744,6399
1279.02,8081,5723,6400
1279.34,8103,5726,6401
1278.69,8741,5720,6401

Done
Type any character to start
You can make the sdfat buffer much bigger, if you haven't already, it is configurable, and that should speed up reading and writing files as bigger portions of the FAT table can be kept in that buffer.

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

Re: Execute from external SRAM

Post by Pito » Thu Jan 12, 2017 6:18 pm

The jumpback from APP via reset may work. From long term perspective I would vote for a mechanism as you have described (store/restore the xLOADER's context). The reason is sometimes in the future you may decide a "context switcher" could handle the APPs..
In big OSes the kernel is isolated from user's APPs physically, so the kernel context and APP one is preserved.
We may agree the only peripheral xLOADER is using is the Serial1. That is the xLOADER's console. I already have CL parser working in the xLOADER, I will update xLOADER soon.
Pukao Hats Cleaning Services Ltd.

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

Re: Execute from external SRAM

Post by victor_pv » Thu Jan 12, 2017 7:17 pm

You need also access to a storage device to load the App from, such as an SDcard, usb pendrive or something. Handlers can be closed and all, but adds bit more complication.

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

Re: Execute from external SRAM

Post by Pito » Thu Jan 12, 2017 7:39 pm

Code: Select all

### Hello from xLOADER v1.02 ! ###
    Usage:
          help
          run APP1
          test
          test1 param

> help
    Usage:
          help
          run APP1
          test
          test1 param

> test
This is the test..
> test1 hello1234
This is the test1..
Parameter: hello1234
> run DHRYSTONE
Loading the DHRYSTONE took 8201 usecs
0 0
1 F8
2 7
3 68
4 39
5 6
6 0
7 68
25836 B8
25837 52
25838 0
25839 68
25840 78
25841 4D
25842 0
25843 68
Starting the DHRYSTONE ...

Dhrystone Benchmark, Version 2.1 (Language: C)
Execution starts, 300000 runs through Dhrystone

Execution ends
Microseconds for one run through Dhrystone: 57.35
Dhrystones per Second: 17437.23
VAX MIPS rating = 9.92
***

Code: Select all

// THE xLOADER v1.02
// 2017/1/12 - added a simple CLI
//
// LOADS an USER APP binary into the EXRAM and RUNS it
// bin.h includes the APP.bin in form of
//    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;
//
// more info at stm32duino forum
// No warranties of any kind. Provided as-is. Use at your own risk.
// by Pito January 12th 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();
}

const uint32 maxntokens = 10;
char line[80];
char* param[10];  // max 10 parameters parsed from readline

// my simple dirty readline
uint32 readline (void) {
  uint32 i = 0;
  uint32 numc;
  uint8 data;
  while (1) {
    while (Serial1.available() == 0) ;
    data = Serial1.read();
    // echo to terminal
    Serial1.write(data);
    //
    line[i] = data;
    if ((line[i] == '\n') || (line[i] == '\r') || (i == 70)) break;
    i++;
  }
  line[i] = 0;
  Serial1.println();
  return i;
}

// CL parser - a splitter with delimiters
int dtsplit(char *str, int *length) {
  uint32 i = 0;
  char *token;
  /* get the first token */
  token = strtok(str, " ,/"); // Delimiters
  /* get the others */
  while ( (token != NULL) && ( i <= maxntokens) )
  {
    param[i]   = token;
    i++;
    token = strtok(NULL, " ,/"); // Delimiters
  }
  *length = i;
  return 1;
}

void jump2APP() {
  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 ");
  Serial1.print(param[1]);
  Serial1.print(" took ");
  Serial1.print(elapsed);
  Serial1.print(" usecs");
  Serial1.println();

  // print out first 8 and last 8 bytes of the APP stored in EXRAM for a check
  // if the FSMC does not work, 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 starting from 0x2000FC00
  for (i = 0; i < 512; i++) {
    IRAMVT(i) = bin[i];
  }

  Serial1.print("Starting the ");
  Serial1.print(param[1]);
  Serial1.println(" ... ");
  Serial1.println();
  delay(10);

  /* Jump to code loaded in EXRAM memory and execute it!! *************************/

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

  nvicDisableInterrupts();

  *(int volatile*)0xE000ED08 = (volatile uint32_t) 0x2000FC00;

  /* Initialize user application's Stack Pointer */
  __set_CONTROL(0); // Change from PSP to MSP
  __set_MSP(*(__IO uint32_t*) ApplicationAddress);

  Jump_To_Application();
}

void setup() {

  Serial1.begin(115200);

  // wait on USB
  // while(!Serial1.isConnected());

  // Splash screen
  Serial1.println();
  Serial1.println("### Hello from xLOADER v1.02 ! ###");
  Serial1.println("    Usage:");
  Serial1.println("          help");
  Serial1.println("          run APP1");
  Serial1.println("          test");
  Serial1.println("          test1 param");
  Serial1.println();
  delay(100);

}

void loop() {

  // Command Line Interpreter loop

  int i;
  int count = 0;
  while (1) {

    line[0] = 0;  // clean the command line
    Serial1.flush();

    Serial1.print("> ");
    readline();
    dtsplit(line, &count);

    if (strcmp(param[0], "run") == 0) {
      // APP name could be in param[1]
      delay(10);
      jump2APP();
    }
    else if (strcmp(param[0], "test") == 0) {
      Serial1.println("This is the test..");
    }
    else if (strcmp(param[0], "test1") == 0) {
      Serial1.println("This is the test1..");
      Serial1.print("Parameter: ");
      Serial1.println(param[1]);
    }
    else if (strcmp(param[0], "help") == 0) {
      Serial1.println("    Usage:");
      Serial1.println("          help");
      Serial1.println("          run APP1");
      Serial1.println("          test");
      Serial1.println("          test1 param");
      Serial1.println();
    }
    else
      Serial1.println("Wrong command, try again..");

    delay(10);
  }
}
Adding the SdCard - done. Reading the file - easy, will be done in v1.03.
Returning from APP - long way to go? :)
Pukao Hats Cleaning Services Ltd.

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

Re: Execute from external SRAM

Post by Pito » Thu Jan 12, 2017 9:25 pm

Now we read from a file placed on the SDcard. In this case Dhrystone.bin.
Reading from file via 8192b large buffer.
No bin.h used anymore, great !!! :)
Edit: added dir :)

Code: Select all

### Hello from xLOADER v1.03 ! ###
    Usage:
          help
          dir
          run APP.bin
> dir
Root dir:
Dhrystone.bin
STM_Dhrystone128.ino.bin
STM_HelloToggle_fromEXRAM.ino.bin
STM_SDLOGGER_FreeRtos_FIFO__FIRFILTER.ino.bin
STM_Whetstone.ino.bin
STM_bench.ino.bin
STM_BubbleSort_EXRAM_ALL.ino.bin
STM_Dhrystone.ino.bin
> run Dhrystone.bin
Reading file..
Loading the Dhrystone.bin 25844 bytes large took 17531 usecs
First 8 bytes in EXRAM: 0 F8 7 68 39 6 0 68
Starting the Dhrystone.bin ...

Dhrystone Benchmark, Version 2.1 (Language: C)
Execution starts, 300000 runs through Dhrystone

Execution ends
Microseconds for one run through Dhrystone: 57.35
Dhrystones per Second: 17437.23
VAX MIPS rating = 9.92
***
Pukao Hats Cleaning Services Ltd.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest