WROVER and PSRAM

czuvich
Posts: 36
Joined: Tue Sep 04, 2018 1:58 am

WROVER and PSRAM

Postby czuvich » Sun Dec 23, 2018 11:08 pm

I’m getting memory issues with the WROVER, but I’m fairly certain I have plenty of available heap. Having said that, I probably have a misunderstanding of memory mapping and PSRAM.

I have a WROVER DEV kit v4.1 running BLE scams using BLEDevice library in Arduino. I’m currently running Arduino 1.0 release.

My questions are:

1) If I use standard “new” instantiation of objects do they go into PSRAM or internal? According to the docs, it looks like it should use PSRAM since Arduino uses “Provide external RAM via malloc()” configuration.

2) Is BLE using PSRAM for heap allocations? Again, I think it should be based on that confit entry.

3) is std::string using PSRAM?

fivdiAtESP32
Posts: 47
Joined: Thu Dec 20, 2018 9:47 am

Re: WROVER and PSRAM

Postby fivdiAtESP32 » Mon Dec 24, 2018 3:47 am

If menuconfig option "SPI RAM access method" is set to "Make RAM allocatable using malloc() as well" then the memory allocation strategy will allocate memory where ever it wants, i.e., in internal RAM or external PSRAM.

The allocation strategy will take menuconfig option "Maximum malloc() size, in bytes, to always put in internal memory" into account. Here's what the menuconfig help has to say about this option:

If malloc() is capable of also allocating SPI-connected ram, its allocation strategy will prefer to allocate chunks less than this size in internal memory, while allocations larger than this will be done from external RAM. If allocation from the preferred region fails, an attempt is made to allocate from the non-preferred region instead, so malloc() will not suddenly fail when either internal or external memory is full.

1) If I use standard “new” instantiation of objects do they go into PSRAM or internal? According to the docs, it looks like it should use PSRAM since Arduino uses “Provide external RAM via malloc()” configuration.

- They will go wherever the allocation strategy decides to put them. Sometimes that will be internal RAM sometimes it will be external RAM.

2) Is BLE using PSRAM for heap allocations? Again, I think it should be based on that confit entry.

- I'm afraid I can't provide any further information here.

3) is std::string using PSRAM?

- The memory allocated for the characters in the string will go wherever the allocation strategy decides to put them. Sometimes that will be internal RAM sometimes it will be external RAM.

The test program below allocates three large memory chunk that are each of size 1 megabyte, one using malloc, one using std::string and one using new. They will all be allocated in external memory as they are so big.

The output of the program provides useful information, especially the output of "heap_caps_print_heap_info(MALLOC_CAP_DEFAULT)" which is very useful for debugging memory issues.

To the best of my knowledge the memory allocator used by malloc and new can only use 4 megabytes of external memory even if 8 megabytes are available. In other words, the memory allocator will not use himem.

Code: Select all

#include <stdio.h>
#include <string.h>
#include <string>
#include "esp_system.h"
#include "esp_himem.h"
#include "esp_heap_caps.h"

#define SIZE 1024 * 1024

static void print_info() {
    printf("\n");

    printf("esp_himem_get_phys_size: %d\n", esp_himem_get_phys_size());
    printf("esp_himem_get_free_size: %d\n", esp_himem_get_free_size());

    printf("esp_get_free_heap_size: %d\n", esp_get_free_heap_size());
    printf("esp_get_minimum_free_heap_size: %d\n", esp_get_minimum_free_heap_size());

    printf("heap_caps_get_free_size: %d\n", heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
    printf("heap_caps_get_minimum_free_size: %d\n", heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT));

    heap_caps_print_heap_info(MALLOC_CAP_DEFAULT);

    printf("\n");
}

extern "C" void app_main() {
    print_info();

    char *str = (char *) malloc(SIZE);
    if (str == NULL) {
        printf("can't allocate memory with malloc\n");
        return;
    }
    printf("memory allocated with malloc\n");
    memset(str, 0xff, SIZE);
    memset(str, 0x55, SIZE);
    memset(str, 0xaa, SIZE);
    memset(str, 0x00, SIZE);
    print_info();

    std::string cppstr(SIZE, 'a');
    printf("std::string allocated\n");
    print_info();

    char *chars = new char[SIZE];
    printf("chars allocated\n");
    print_info();

    free(str);
    printf("memory allocated with malloc freed\n");
    print_info();

    delete[] chars;
    printf("chars freed\n");
    print_info();
}
Here's the output of the program:

Code: Select all

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 4196932
esp_get_minimum_free_heap_size: 4196932
heap_caps_get_free_size: 4196932
heap_caps_get_minimum_free_size: 4196932
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 3932120 allocated 0 min_free 3932120
    largest_free_block 3932120 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 4196932 allocated 54552 min_free 4196932 largest_free_block 3932120

memory allocated with malloc

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 3148352
esp_get_minimum_free_heap_size: 3148352
heap_caps_get_free_size: 3148352
heap_caps_get_minimum_free_size: 3148352
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 2883540 allocated 1048576 min_free 2883540
    largest_free_block 2883540 alloc_blocks 1 free_blocks 1 total_blocks 2
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 3148352 allocated 1103128 min_free 3148352 largest_free_block 2883540

std::string allocated

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 2099768
esp_get_minimum_free_heap_size: 2099768
heap_caps_get_free_size: 2099768
heap_caps_get_minimum_free_size: 2099768
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 1834956 allocated 2097156 min_free 1834956
    largest_free_block 1834956 alloc_blocks 2 free_blocks 1 total_blocks 3
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 2099768 allocated 2151708 min_free 2099768 largest_free_block 1834956

chars allocated

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 1051188
esp_get_minimum_free_heap_size: 1051188
heap_caps_get_free_size: 1051188
heap_caps_get_minimum_free_size: 1051188
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 786376 allocated 3145732 min_free 786376
    largest_free_block 786376 alloc_blocks 3 free_blocks 1 total_blocks 4
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 1051188 allocated 3200284 min_free 1051188 largest_free_block 786376

memory allocated with malloc freed

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 2099764
esp_get_minimum_free_heap_size: 1051188
heap_caps_get_free_size: 2099764
heap_caps_get_minimum_free_size: 1051188
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 1834952 allocated 2097156 min_free 786376
    largest_free_block 1048576 alloc_blocks 2 free_blocks 2 total_blocks 4
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 2099764 allocated 2151708 min_free 1051188 largest_free_block 1048576

chars freed

esp_himem_get_phys_size: 4456448
esp_himem_get_free_size: 4456448
esp_get_free_heap_size: 3148344
esp_get_minimum_free_heap_size: 1051188
heap_caps_get_free_size: 3148344
heap_caps_get_minimum_free_size: 1051188
Heap summary for capabilities 0x00001000:
  At 0x3f800000 len 3932159 free 2883532 allocated 1048580 min_free 786376
    largest_free_block 1834956 alloc_blocks 1 free_blocks 2 total_blocks 3
  At 0x3ffae6e0 len 6432 free 8 allocated 6296 min_free 8
    largest_free_block 8 alloc_blocks 23 free_blocks 1 total_blocks 24
  At 0x3ffb30b0 len 184144 free 135740 allocated 48256 min_free 135740
    largest_free_block 135740 alloc_blocks 28 free_blocks 1 total_blocks 29
  At 0x3ffe0440 len 15296 free 15260 allocated 0 min_free 15260
    largest_free_block 15260 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 3148344 allocated 1103132 min_free 1051188 largest_free_block 1834956

czuvich
Posts: 36
Joined: Tue Sep 04, 2018 1:58 am

Re: WROVER and PSRAM

Postby czuvich » Mon Dec 24, 2018 6:09 pm

Thank you for the excellent explanation! So I've learned a few things about SPI RAM, allocators, and Arduino. I'll post my findings in another thread.

Who is online

Users browsing this forum: Google [Bot] and 132 guests