[STM32GENERIC] FSMC - SRAM

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

[STM32GENERIC] FSMC - SRAM

Post by Pito » Tue May 09, 2017 11:27 pm

Starting to mess with FSMC (..again) :)
While in libmaple era I set heap in ld file as :

Code: Select all

    __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 ( * )
I do not know how to do it in this one.
When I set it as above the malloc takes my internal ram, it seems.
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by victor_pv » Wed May 10, 2017 12:05 am

I think STM may have done half the work already in the HAL MX.
I found this in system_stm32f4xx.c:

Code: Select all

#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
    defined(STM32F469xx) || defined(STM32F479xx)
/**
  * @brief  Setup the external memory controller.
  *         Called in startup_stm32f4xx.s before jump to main.
  *         This function configures the external memories (SRAM/SDRAM)
  *         This SRAM/SDRAM will be used as program data memory (including heap and stack).
  * @param  None
  * @retval None
  */
  ...
  
Haven't gone in details on what the functions do, but there are similar ones for the other series.
Try to generate a project with the HALMX enabling the FSMC and see what you get.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Wed May 10, 2017 12:21 am

I've created the stuff in CubeMX with fsmc for f103.
It does not create linker file, though.. EDIT: it does, I had missed some parts of the CubeMX..
For F103 it creates the basic config for gpios and fsmc and a bunch of functions to access the external sram.
That functions is something I do not need, I need to tell compiler/linker the malloc() and friends shall use the heap which is placed in the external sram.
Easy as pie.. :)
For example an array is created:

Code: Select all

uint32_t* EXRAM32 =  (uint32_t*) malloc(n * sizeof(uint32_t));
and used as usual then..
Update: The new linker script includes a check on heap:

Code: Select all

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
Interestingly we do not have this chunk in our ld file..
Now, the heap has to be somehow shifted into the external sram. In libmaple I did it with:

Code: Select all

  PROVIDE(_lm_heap_start = 0x68000000);
  PROVIDE(_lm_heap_end = ALIGN(0x68000000 + 0x00080000 - 8 ,8));  
and it worked.
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by victor_pv » Wed May 10, 2017 3:08 am

Pito wrote:I've created the stuff in CubeMX with fsmc for f103.
It does not create linker file, though.. EDIT: it does, I had missed some parts of the CubeMX..
For F103 it creates the basic config for gpios and fsmc and a bunch of functions to access the external sram.
That functions is something I do not need, I need to tell compiler/linker the malloc() and friends shall use the heap which is placed in the external sram.
Easy as pie.. :)
For example an array is created:

Code: Select all

uint32_t* EXRAM32 =  (uint32_t*) malloc(n * sizeof(uint32_t));
and used as usual then..
Update: The new linker script includes a check on heap:

Code: Select all

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
Interestingly we do not have this chunk in our ld file..
Now, the heap has to be somehow shifted into the external sram. In libmaple I did it with:

Code: Select all

  PROVIDE(_lm_heap_start = 0x68000000);
  PROVIDE(_lm_heap_end = ALIGN(0x68000000 + 0x00080000 - 8 ,8));  
and it worked.
I suspect the startup file may be different too, and that may be the one relocating the heap to FSMC address:
Called in startup_stm32f4xx.s before jump to main.
Other than that, did you check if the RAM address in the linker script has changed?

ChrisMicro
Posts: 297
Joined: Fri Mar 24, 2017 4:51 pm
Location: Germany

Re: [STM32GENERIC] FSMC - SRAM

Post by ChrisMicro » Wed May 10, 2017 5:27 am

Could you provide the whole example or put it as an example into the STM32GENERIC repository?
This would be the easiest way that people can use it ;)

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

Re: [STM32GENERIC] FSMC - SRAM

Post by danieleff » Wed May 10, 2017 6:07 am

I am also interested in this... for F7.

ag123
Posts: 742
Joined: Thu Jul 21, 2016 4:24 pm

Re: [STM32GENERIC] FSMC - SRAM

Post by ag123 » Wed May 10, 2017 6:51 am

possible to mess with this on VET6 boards? adding 128k bytes would make it 256k bytes sram that feels plenty oh then there is still another 64k CCM RAM :mrgreen:

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Wed May 10, 2017 8:12 am

I still do not have the working solution here.. It is a mess. I must get some HAL insights first..
What I have got is the 512kB sram soldered on a Blue F103ZET6 board, with NE3 chipselect, address 0x68000000, worked in past. It was much easier with the F1 libmaple stuff, though..
Pukao Hats Cleaning Services Ltd.

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

Re: [STM32GENERIC] FSMC - SRAM

Post by stevestrong » Thu May 11, 2017 8:55 am

Pito wrote:It was much easier with the F1 libmaple stuff, though..
Nobody would mind if you would try it with libmaple... :geek:

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

Re: [STM32GENERIC] FSMC - SRAM

Post by Pito » Thu May 11, 2017 9:04 am

First read this blog http://www.stm32duino.com/viewtopic.php?f=28&t=1651 :)

The easiest way is to use the external Sram as the Heap. It is also the fastest variant, as the speed penalty is about x2.5 max.
The Bank1 Region 3 with Blue ZET6 is 3, so you use NE3, that is the 0x68000000 base address.

The CubeMX creates for you 3 functions (CS=NE3, SRAM, data 16bits, addr 18bits, wait disable, byte enable):

Code: Select all

static void MX_GPIO_Init(void);
static void MX_FSMC_Init(void);
HAL_SRAM_MspInit(SRAM_HandleTypeDef* hsram);
That is all what you need.
Then you have to tell in the linker script the heap is from 68000000 as above.

In your code you may use the external sram space via malloc(), or via pointers. For example with malloc() you may create an N large uint32 array:

Code: Select all

uint32_t* EXRAM32 =  (uint32_t*) malloc(N * sizeof(uint32_t));
and use it as usual with EXRAM32[index] within your code..
Now how to get it working here.. I mean what needs to be included where in Daniel's core (stm32f1xx_hal_msp.c, stm32f1xx_hal_it.c, etc).

Within the libmaple it was easier - I put this FSMC init into the start_c.c:

Code: Select all

..
    int *dst = (int*)&__data_start__;
    int exit_code;
	
  // ###### INIT FSMC for External SRAM BANK1 Region3, 10ns, 256kx16
  // ###### Pito 12/2016
    #define DATAST   0x1
    #define ADDSET   0x0
  /* Enable FSMC clock */
  RCC_BASE->AHBENR = 0x00000114;
  /* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */  
  RCC_BASE->APB2ENR = 0x00001E0; 
  /* ---------------  SRAM Data lines, NOE and NWE configuration ---------------*/
  /*----------------  SRAM Address lines configuration -------------------------*/
  /*----------------  NOE and NWE configuration --------------------------------*/  
  /*----------------  NE3 configuration ----------------------------------------*/
  /*----------------  NBL0, NBL1 configuration ---------------------------------*/
  
   GPIOD_BASE->CRL = 0xB4BB44BB; // B-active set for FSMC
   GPIOD_BASE->CRH = 0xBBBBBBBB;
   GPIOE_BASE->CRL = 0xB44444BB; 
   GPIOE_BASE->CRH = 0xBBBBBBBB;
   GPIOF_BASE->CRL = 0x44BBBBBB; 
   GPIOF_BASE->CRH = 0xBBBB4444;
   GPIOG_BASE->CRL = 0x44BBBBBB; 
   GPIOG_BASE->CRH = 0x444B4BB4;
  
  /*----------------  FSMC Configuration ---------------------------------------*/  
  /*----------------  Enable FSMC Bank1_SRAM Bank ------------------------------*/  
  //FSMC_Bank1->BTCR[4] = 0x00001011;
  //FSMC_Bank1->BTCR[5] = 0x00000200;
  FSMC_NOR_PSRAM3_BASE->BCR = (FSMC_BCR_WREN |
                    FSMC_BCR_MTYP_SRAM |
                    FSMC_BCR_MWID_16BITS |
                    FSMC_BCR_MBKEN);
  FSMC_NOR_PSRAM3_BASE->BTR = (DATAST << 8) | ADDSET;
  //
  // ################ End of FSMC INIT #################
	
    /* Initialize .data, if necessary. */
    if (src != dst) {
        int *end = (int*)&__data_end__;
        ..
        
In the sketch:

Code: Select all

..
#include <libmaple/rcc.h>
#include <libmaple/fsmc.h>
// -- SRAM config -------------------------------------------------------------
// Timing configuration - for a 10ns SRAM (to be tested)
#define DATAST   0x1
#define ADDSET   0x0
// Number of SRAM chips wired (max 4 in BANK1)
#define NSRAMCHIPS 1

// Corresponding FSMC configuration registers
__io uint32 *const bcrs[NSRAMCHIPS] = {
    // &FSMC_NOR_PSRAM1_BASE->BCR,
    // &FSMC_NOR_PSRAM2_BASE->BCR,
     &FSMC_NOR_PSRAM3_BASE->BCR,
    // &FSMC_NOR_PSRAM4_BASE->BCR,
};

// Corresponding FSMC timing registers
__io uint32 *const btrs[NSRAMCHIPS] = {
    // &FSMC_NOR_PSRAM1_BASE->BTR,
    // &FSMC_NOR_PSRAM2_BASE->BTR,
     &FSMC_NOR_PSRAM3_BASE->BTR,
    // &FSMC_NOR_PSRAM4_BASE->BTR,
};
 
 void setup() {
  // put your setup code here, to run once:

    fsmc_sram_init_gpios();
    rcc_clk_enable(RCC_FSMC);

    // All wired SRAM chips are of the same type
    for (int i = 0; i < NSRAMCHIPS; i++) {
        *bcrs[i] = (FSMC_BCR_WREN |
                    FSMC_BCR_MTYP_SRAM |
                    FSMC_BCR_MWID_16BITS |
                    FSMC_BCR_MBKEN);
        *btrs[i] = (DATAST << 8) | ADDSET;
    }
    ..
So it could be done in start_c.c or in the sketch.
In the ld script I commented out the original defs of the heap start and end,

Code: Select all

		/**
   *      _lm_heap_start = DEFINED(_lm_heap_start) ? _lm_heap_start : _end;
   *      _lm_heap_end   = DEFINED(_lm_heap_end) ? _lm_heap_end : __msp_init;
		 */
and, put at the very end of the ld script:

Code: Select all

  PROVIDE(_lm_heap_start = 0x68000000);
  PROVIDE(_lm_heap_end = ALIGN(0x68000000 + 0x00080000 - 8 ,8));  
AFIK the Heap must not be initialized in init as you start to using the heap within the sketch, so it is enough to init it in the start() before you start using the malloc()..
Pukao Hats Cleaning Services Ltd.

Post Reply