[STM32GENERIC] FSMC - SRAM

Discussions about the STM32generic core
User avatar
Pito
Posts: 1628
Joined: Sat Mar 26, 2016 3:26 pm
Location: Rapa Nui

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 10:54 am

Back to This core:
The CubeMX creates also the system_stm32f1xx.c file which includes the FSMC init equivalent to the libmaple start_c.c one above.
I do not know how/where to integrate it safely within the Daniel's core, so a hint would be welcomed..
Pukao Hats Cleaning Services Ltd.

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] FSMC - SRAM

Post by danieleff » Thu May 11, 2017 11:04 am

Uncomment the #define DATA_IN_ExtSRAM in system_stm32f1xx.c to test. Later we can put it into boards.txt build.extra_flags.

SystemInit is called from _startup, and with this define SystemInit_ExtMemCtl.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 12:39 pm

This is what needs to be changed in syscalls.c in order to take over the NEW heap start/end from the ld script (PROVIDE.. as above):

Code: Select all

/*----------------------------------------------------------------------------
 *        Exported variables
 *----------------------------------------------------------------------------*/

#undef errno
extern int errno ;
extern int  _end ;

/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then
 * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by
 * the linker */
#ifndef CONFIG_HEAP_START
extern unsigned int _lm_heap_start;
#define CONFIG_HEAP_START               ((void *)&_lm_heap_start)
#endif
#ifndef CONFIG_HEAP_END
extern unsigned int  _lm_heap_end;
#define CONFIG_HEAP_END                 ((void *)&_lm_heap_end)
#endif

/*----------------------------------------------------------------------------
 *        Exported functions
 *----------------------------------------------------------------------------*/
extern void _exit( int status ) ;
extern void _kill( int pid, int sig ) ;
extern int _getpid ( void ) ;

extern caddr_t _sbrk(int incr) {
    static void * pbreak = NULL; /* current program break */
    void * ret;

    if (pbreak == NULL) {
        pbreak = CONFIG_HEAP_START;
    }

    if ((CONFIG_HEAP_END - pbreak < incr) ||
        (pbreak - CONFIG_HEAP_START < -incr)) {
       // errno = ENOMEM;     <<< commented out by Pito as it throws it is not defined
        return (void *)-1;
    }

    ret = pbreak;
    pbreak += incr;
    return ret;
}

/** ORIGINAL _sbrk
 *extern caddr_t _sbrk ( int incr )
 *{
 *  static unsigned char *heap = NULL ;
 *  unsigned char *prev_heap ;
 *
 *  if ( heap == NULL )
 *  {
 *    heap = (unsigned char *)&_end ;
 *  }
 *  prev_heap = heap;
 *
 *  heap += incr ;
 *
 *  return (caddr_t) prev_heap ;
 *}
 */
And this is the FSMC init from system_stm32f1xx.c which works here:

Code: Select all

void SystemInit_ExtMemCtl(void) 
{
  __IO uint32_t tmpreg;
  /*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is 
    required, then adjust the Register Addresses */

  /* Enable FSMC clock */
  RCC->AHBENR = 0x00000114;

  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_FSMCEN);
  
  /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */
  RCC->APB2ENR = 0x000001E0;
  
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPDEN);

  (void)(tmpreg);
  
/* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
/*----------------  SRAM Address lines configuration -------------------------*/
/*----------------  NOE and NWE configuration --------------------------------*/  
/*----------------  NE3 configuration ----------------------------------------*/
/*----------------  NBL0, NBL1 configuration ---------------------------------*/
  
  GPIOD->CRL = 0xB4BB44BB;  
  GPIOD->CRH = 0xBBBBBBBB;

  GPIOE->CRL = 0xB44444BB;  
  GPIOE->CRH = 0xBBBBBBBB;

  GPIOF->CRL = 0x44BBBBBB;  
  GPIOF->CRH = 0xBBBB4444;

  GPIOG->CRL = 0x44BBBBBB;  
  GPIOG->CRH = 0x444B4B44;
   
/*----------------  FSMC Configuration ---------------------------------------*/  
/*----------------  Enable FSMC Bank1_Region3_SRAM Bank ------------------------------*/

  //FSMC_Bank1->BTCR[4] = 0x00001091;
  //FSMC_Bank1->BTCR[5] = 0x00110212;
    #define DATAST   0x1
    #define ADDSET   0x0
  FSMC_Bank1->BTCR[4] = 0x00001091;
  FSMC_Bank1->BTCR[5] = (DATAST << 8) | ADDSET;   // this is the "BTRx" reg   
}
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F100xE || STM32F101xE || STM32F101xG || STM32F103xE || STM32F103xG */
You do not need to add anything else into your sketch in order to use the Heap in the external SRAM.

Thus in order to recap (for F1 chips):
=============================================
1. uncomment the #define DATA_IN_ExtSRAM in system_stm32f1xx.c
2. the _sbrk has to be changed as above in syscalls.c - NOTE: it has to be modified such it works with the internal heap too..
3. use the above init sequence for 10ns 256kx16 SRAM in system_stm32f1xx.c (the fastest settings, Bank1, Region 3), the

Code: Select all

    #define DATAST   0x1
    #define ADDSET   0x0
are the best speed settings for 10ns Sram.
4. add to your linker ld script (for 256kx16 Sram, Bank1, Region3, CS=NE3):

Code: Select all

..
EXTERN(_lm_heap_start);
EXTERN(_lm_heap_end);

/* Entry Point */
ENTRY(Reset_Handler)
..
   _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM
  
  PROVIDE ( _end = . );
  
  PROVIDE(_lm_heap_start = 0x68000000); 
  PROVIDE(_lm_heap_end = ALIGN(0x68000000 + 0x00080000 - 8 ,8));  
  

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    ..
5. use your sketch as is, but with malloc() creating your variables located in the external Heap Sram.. You may use pointers to the 0x68000000(+512kB) space as well.
:)
Last edited by Pito on Thu May 11, 2017 4:35 pm, edited 11 times in total.
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 12:55 pm

Bubble Sort 3000 random numbers:
Arrays located in the Heap in the internal Sram:

Code: Select all

Generating 3000 8bit uints:
Checksum: 383933
BubbleSorting 8bit uints:
Elapsed: 1189  msecs
Generating 3000 16bit uints:
Checksum: 99006717
BubbleSorting 16bit uints:
Elapsed: 940  msecs
Generating 3000 32bit uints:
Checksum: 2798690133398
BubbleSorting 32bit uints:
Elapsed: 1190  msecs
Arrays located in Heap in the External Sram:

Code: Select all

Generating 3000 8bit uints:
Checksum: 383933
BubbleSorting 8bit uints:
Elapsed: 2411  msecs
Generating 3000 16bit uints:
Checksum: 99006717
BubbleSorting 16bit uints:
Elapsed: 2473  msecs
Generating 3000 32bit uints:
Checksum: 2798690133398
BubbleSorting 32bit uints:
Elapsed: 3282  msecs
enerating 3000 64bit uints:
Checksum: 16959245246837334
BubbleSorting 64bit uints:
Elapsed: 5302  msecs
Here are the old results in libmaple:
http://www.stm32duino.com/viewtopic.php ... 651#p21714
Not sure why the 64bit results are much faster in This core, however :)
Note: the checksum for 32bit and 64bit is wrong as we cannot print 64bit uints yet..
Last edited by Pito on Thu May 11, 2017 7:06 pm, edited 5 times in total.
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 1:27 pm

This is to demonstrate we really work with Heap in the External Sram - 300kB of variables in total allocated in the Heap placed in the external Sram (Blue F103ZET @72MHz, 256kx16 10ns sram):

Code: Select all

Allocating EXRAM8, EXRAM16, EXRAM32, EXRAM64 memory..
********
Generating 20000 8bit uints:
Checksum: 2556578
BubbleSorting 8bit uints:
Elapsed: 106900  msecs
2x compare count: 0
2x rd and 2x wr count: 0
Checksum: 2556578
Sorted last 10 in ascending order:
19990 255
19991 255
19992 255
19993 255
19994 255
19995 255
19996 255
19997 255
19998 255
19999 255
********
Generating 20000 16bit uints:
Checksum: 656944195
BubbleSorting 16bit uints:
Elapsed: 109857  msecs
2x compare count: 0
2x rd and 2x wr count: 0
Checksum: 656944195
Sorted last 10 in ascending order:
19990 65510
19991 65515
19992 65517
19993 65522
19994 65522
19995 65523
19996 65524
19997 65529
19998 65531
19999 65531
********
Generating 20000 32bit uints:
Checksum: 18681914029997
BubbleSorting 32bit uints:
Elapsed: 146438  msecs
2x compare count: 0
2x rd and 2x wr count: 0
Checksum: 18681914029997
Sorted last 10 in ascending order:
19990 1999238604
19991 1999306563
19992 1999424184
19993 1999451338
19994 1999457766
19995 1999465354
19996 1999558287
19997 1999650861
19998 1999652871
19999 1999901586
********
Generating 20000 64bit uints:
Checksum: 111575624063623152
BubbleSorting 64bit uints:
Elapsed: 236449  msecs
2x compare count: 0
2x rd and 2x wr count: 0
Checksum: 111575624063623152
Sorted last 10 in ascending order:
19990 11868698567724
19991 11868882412866
19992 11869207321128
19993 11869235688114
19994 11871884373798
19995 11872081464387
19996 11872393614036
19997 11873118183327
19998 11873121418992
19999 11873209577505
Note: we do not have print with 64bits uints yet.
Last edited by Pito on Thu May 11, 2017 6:50 pm, edited 1 time in total.
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 6:38 pm

Here is the simple Bubble Sort Demo - you may test your INTERNAL / EXTERNAL Heap :)
UPDATE 10.6.2017
UPDATE 15.8.2017 - comment out LED, print the EXRAM32 start address

Code: Select all

// Bubble Sort Demo in Heap
// Pito c 5/2017, 6/2017, 8/2017
// Adjust the Array size such it fits into your Heap

//#include <stdio.h>
//#include <stddef.h>
#include "Arduino.h"

 void setup() {
  delay(4000);  // wait on USB

 // pinMode(PF9, OUTPUT);
 // digitalWrite(PF9, LOW);

  Serial.begin(115200);

  uint32_t n = 4000; // Number of uint32 elements

  uint32_t c, d, tmp, swap32, elapsed, i;
  uint64_t sum, sum1;

   Serial.println("Allocating EXRAM32 memory..");

    /* EXRAM32 Initial memory allocation */
    uint32_t* EXRAM32 =  (uint32_t*) malloc(n * sizeof(uint32_t));
    if (NULL == EXRAM32) {
        Serial.println("      ############### EXRAM32 MALLOC FAILED..");
         //return -1;
        }
   Serial.println((uint32_t)EXRAM32);
   
// 32bit
   sum = 0;
   sum1 = 0;
   randomSeed(3864);
   Serial.println("********");
   Serial.print("Generating ");
   Serial.print(n);
   Serial.println(" 32bit uints:");
    for (uint32_t i=0; i<n; i++){
          tmp = random(1999999999);
          EXRAM32[i] = tmp;
          sum1 = sum1 + tmp;
          sum = sum + EXRAM32[i];
    }
    Serial.print("Checksum of generated random numbers: ");
    Serial.println(sum1);
    Serial.print("Checksum of unsorted EXRAM32 content: ");
    Serial.println(sum);
   Serial.println("BubbleSorting 32bit uints:");
   elapsed = millis();

  for (c = 0 ; c < ( n - 1 ); c++)
  {
    if ( (c % 1000) == 0) {
      Serial.print("Wait while BubbleSorting.. Loops "); Serial.print(c);
      Serial.print(" out of "); Serial.println(n);
    }
    for (d = 0 ; d < n - c - 1; d++)
    {
      if (EXRAM32[d] > EXRAM32[d+1]) /* For decreasing order use < */
      {
        swap32       = EXRAM32[d];
        EXRAM32[d]   = EXRAM32[d+1];
        EXRAM32[d+1] = swap32;
      }
    }
  }

  elapsed = millis() - elapsed;
     Serial.print("Elapsed: ");
     Serial.print(elapsed);
     Serial.print(" ");
     Serial.println(" msecs");

    sum = 0;
    for (uint32_t i=0; i<n; i++){
        sum = sum + EXRAM32[i];
    }
    Serial.print("Checksum of sorted numbers: ");
    Serial.println(sum);

  Serial.println("Sorted last 10 in ascending order:");

  for ( c = n-10 ; c < n ; c++ ) {
     Serial.print(c);
     Serial.print(" ");
     Serial.println(EXRAM32[c]);
  }

  // digitalWrite(PF9, HIGH);
    delay(2000);
    free(EXRAM32);
 }

void loop() {
}
An Example only (it may differ based on the sketch update):

Code: Select all

Allocating EXRAM32 Array in the memory..
********
Generating 20000 32bit uints:
Checksum: 18681914029997
BubbleSorting 32bit uints:
Wait while BubbleSorting.. Loops 0 out of 20000
Wait while BubbleSorting.. Loops 1000 out of 20000
Wait while BubbleSorting.. Loops 2000 out of 20000
Wait while BubbleSorting.. Loops 3000 out of 20000
Wait while BubbleSorting.. Loops 4000 out of 20000
Wait while BubbleSorting.. Loops 5000 out of 20000
Wait while BubbleSorting.. Loops 6000 out of 20000
Wait while BubbleSorting.. Loops 7000 out of 20000
Wait while BubbleSorting.. Loops 8000 out of 20000
Wait while BubbleSorting.. Loops 9000 out of 20000
Wait while BubbleSorting.. Loops 10000 out of 20000
Wait while BubbleSorting.. Loops 11000 out of 20000
Wait while BubbleSorting.. Loops 12000 out of 20000
Wait while BubbleSorting.. Loops 13000 out of 20000
Wait while BubbleSorting.. Loops 14000 out of 20000
Wait while BubbleSorting.. Loops 15000 out of 20000
Wait while BubbleSorting.. Loops 16000 out of 20000
Wait while BubbleSorting.. Loops 17000 out of 20000
Wait while BubbleSorting.. Loops 18000 out of 20000
Wait while BubbleSorting.. Loops 19000 out of 20000
Elapsed: 145993  msecs
Checksum: 18681914029997
Sorted last 10 in ascending order:
19990 1999238604
19991 1999306563
19992 1999424184
19993 1999451338
19994 1999457766
19995 1999465354
19996 1999558287
19997 1999650861
19998 1999652871
19999 1999901586
********
Last edited by Pito on Wed Aug 16, 2017 5:46 pm, edited 12 times in total.
Pukao Hats Cleaning Services Ltd.

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] FSMC - SRAM

Post by danieleff » Sat May 13, 2017 1:08 pm

I have added setHeap(char *start, char *end) to syscalls.c, so it is possible for variants to set it.

I added weak preinitVariant() to system_stm32xxx.c that is called before constructor initialization, so variants can fiddle with ram before any real stuff is called. Here it is possible to move heap (using previous function), or initialize data / bss in CCM ram, SRAM, and other things later.

With these enabling for F7 is basically this: https://github.com/danieleff/STM32GENER ... 0b85341f63
  • Add DATA_IN_ExtSDRAM to boards.txt. You need to check STM32/system/STM32xx/HAL_Src/system_stm32xxxx.c what to define
  • Add preinitVariant() to variant.cpp to move heap. If you don't like the default SystemInit_ExtMemCtl(), you can put your extram init here. Later this can be used to initialize extra ram data/bss with ldscript also.
I put an example sketch also. AFAIK the only other board with external ram currently is Discovery F429ZI. I do not have it.

NOTE: There is also a stm32xxxx_hal_sdram.c if one does not want to work with registers.

User avatar
Zingg_JM
Posts: 40
Joined: Tue Jan 17, 2017 10:46 am

Re: [STM32GENERIC] FSMC - SRAM

Post by Zingg_JM » Mon Jun 05, 2017 5:26 pm

Hi all,

Seems I have found the right topic for the following simple question:

Is there an example how to initialize FSMC for use with 1: SRAM, 2: FSMC TFT connector in an Arduino program or C++ library class?

I have a STMF32F407ZET6 board with a 1MB static ram chip on board (e-paper demo board).
And I have black STM32F407VET6 and STM32F407ZET6 boards with FSMC TFT connector (I use bit-bang so far).

This topic indicates the answer is there somewhere, but you might help me with some links, thank you.

Jean-Marc Zingg
I like clickable and valid links that point to relevant information

danieleff
Posts: 336
Joined: Thu Sep 01, 2016 8:52 pm
Location: Hungary
Contact:

Re: [STM32GENERIC] FSMC - SRAM

Post by danieleff » Tue Jun 06, 2017 4:54 am

This thread is about my arduino implementation, not libmaple. I do not have F4 with external fsmc components, so cannot give working examples.

For SRAM, if you add -DDATA_IN_ExtSRAM to boards.txt, it should initialize to bank1 which starts at 0x60000000(?). Check with a pointer if you can write/read. (Do you have a link to the board?)
For TFT, its best to ask STM32CubeMX to generate the setup code. If you still want to go down this way I can give more pointers.

User avatar
Zingg_JM
Posts: 40
Joined: Tue Jan 17, 2017 10:46 am

Re: [STM32GENERIC] FSMC - SRAM

Post by Zingg_JM » Tue Jun 06, 2017 5:34 am

Thank you again for your response, it really makes things clearer for me.

I had no Idea how this [STM32GENERIC] section is related to the 2 STM32 Arduino packages I know.
I had just searched for FSMC.

In a post above I found an example of FSMC initialization using direct register access. This is what I am looking for. I will try that way.

My question is related to my recent post about memory available for Arduino on STM32F707ZET6; in it there is a link to the DESTM32-L board.

http://www.stm32duino.com/viewtopic.php ... =50#p29154
I like clickable and valid links that point to relevant information

Post Reply