I have a struct like this:
typedef struct {
boolean isExists = false;
uint16_t readBuffer[32] = {0};
uint16_t writeBuffer[13] = {0};
uint16_t ledBrgBuff[9] = {0};
uint16_t address = 0x0000;
uint16_t id = 0x0000;
uint16_t serial = 0x0000;
String kind = "RESERVED";
String name = "RESERVED";
uint16_t readNum = 21;
uint16_t writeNum = 2;
byte read_failCounter = 0;
byte write_failCounter = 0;
byte allowedFails = 10;
long lastWriteFailMSG = 0;
long lastReadFailMSG = 0;
boolean isTesting = false;
boolean criticalOff = false;
boolean onFault = false;
uint8_t data[RESPONSE_COUNT];
} expStruct;
I was using a dynamically allocated array of struct from ram before like this:
expStruct * expanders[MAX_EXPANDER] EXT_RAM_ATTR; // Globally
void fillStructsTest(){
// Fill all the array of structs with data from a json string from the filesystem
JsonArray hwConf = doc.as<JsonArray>();
memset(expanders, 0, sizeof(expanders)); // here I null all the struct in the array
for(byte i = 0; i < hwConf.size(); i ++){
JsonObject module = hwConf[i];
expanders[expCounter] = new expStruct;
expanders[expCounter]->address = module["address"].as<uint16_t>();
expanders[expCounter]->id = module["moduleid"].as<uint16_t>();
expanders[expCounter]->serial = module["serialnr"].as<uint16_t>();
expanders[expCounter]->kind = module["kind"].as<String>();
expanders[expCounter]->name = module["name"].as<String>();
expCounter++;
}
}
That worked pretty well. I could use my array of structs like this:
void useStructTest(){
if( expanders[0] != 0 ){
expanders[0]->name = "Test";
// I can reach every variable inside any of the structs in the array if the value on the index
// is not 0
}
}
Now I want to place this array of structs into PSRAM on my esp32. I approached it like this:
typedef struct {
boolean isExists = false;
uint16_t readBuffer[32] = {0};
uint16_t writeBuffer[13] = {0};
uint16_t ledBrgBuff[9] = {0};
uint16_t address = 0x0000;
uint16_t id = 0x0000;
uint16_t serial = 0x0000;
String kind = "RESERVED";
String name = "RESERVED";
uint16_t readNum = 21;
uint16_t writeNum = 2;
byte read_failCounter = 0;
byte write_failCounter = 0;
byte allowedFails = 10;
long lastWriteFailMSG = 0;
long lastReadFailMSG = 0;
boolean isTesting = false;
boolean criticalOff = false;
boolean onFault = false;
uint8_t data[RESPONSE_COUNT];
} expStruct;
expStruct *expanders = (expStruct *) ps_malloc(MAX_EXPANDER * sizeof(expStruct));
void fill_PSRAM_StructsTest(){
// Fill all the array of structs with data from a json string from the filesystem
JsonArray hwConf = doc.as<JsonArray>();
// memset(expanders, 0, sizeof(expanders)); // I can't do this now
for(byte i = 0; i < hwConf.size(); i ++){
JsonObject module = hwConf[i];
// expanders[expCounter] = new expStruct; // I can't do this now either.
// also I must replace the -> with . because the compiler erroring me
expanders[expCounter].address = module["address"].as<uint16_t>();
expanders[expCounter].id = module["moduleid"].as<uint16_t>();
expanders[expCounter].serial = module["serialnr"].as<uint16_t>();
expanders[expCounter].kind = module["kind"].as<String>();
expanders[expCounter].name = module["name"].as<String>();
expCounter++;
}
}
Somewhere here my ESP crashing without a meaningful serial output, which is this:
Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400ec9a7 PS : 0x00060630 A0 : 0x80090915 A1 : 0x3ffdaee0
A2 : 0x00000000 A3 : 0x3f80afdc A4 : 0x00000000 A5 : 0x3ffc25fc
A6 : 0x00000000 A7 : 0x3ffdaf64 A8 : 0x800ec9a2 A9 : 0x3ffdaeb0
A10 : 0x00000001 A11 : 0x3f40203a A12 : 0x3ffdafd0 A13 : 0xf655c6f4
A14 : 0x3ffdadc0 A15 : 0x00000005 SAR : 0x00000010 EXCCAUSE: 0x0000001d
EXCVADDR: 0x0000006e LBEG : 0x4008d6b1 LEND : 0x4008d6c1 LCOUNT : 0xfffffff7
ELF file SHA256: 0000000000000000
Backtrace: 0x400ec9a7:0x3ffdaee0 0x40090912:0x3ffdb000
#0 0x400ec9a7:0x3ffdaee0 in mbusTask(void*) at lib/modbus-esp8266-3.0.6/src/Modbus.h:238
(inlined by) mbusTask(void*) at src/Own_Headers/busCommunication.h:559
#1 0x40090912:0x3ffdb000 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)
Rebooting...
ets Jul 29 2019 12:21:46
Should I allocate every index again in a function or what should I do to use it normally like before?
sorry for my english, you can't use String in PSRAM (dynamic)
you use: char name[100]; no String !!!
and... copy from JSON to stuct:-)
strcpy(expanders[expCounter].name, module["name"].as < string > ().c_str());
To move a ArduinoJsonDocument
into PSRAM one needs to do it like so:
struct SpiRamAllocator {
void* allocate(size_t size) {
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
}
void deallocate(void* pointer) {
heap_caps_free(pointer);
}
void* reallocate(void* ptr, size_t new_size) {
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
}
};
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
see here for a more detailed info.
To move any variable into PSRAM memory space one needs to declare it as below for the case of a uint16_t
:
uint16_t* p_buffer_a = (uint16_t*) heap_caps_malloc(307200, MALLOC_CAP_SPIRAM );
where 307200
is the uint16_t byte size memory allocation to that specific variable p_buffer_a
. The maximum element size for this array can be determined like this:
sizeof(p_buffer_a)/sizeof(uint16_t)
Mind you if one needs / wants to use Strings, it needs to rebuild the String class to accommodate PSRAM memory allocation.
Another way to move variable data into PSRAM is by wrapping it in a typedef struct
.To allocate a buffer dynamically at runtime like the one below, one can declare it as follows:
typedef struct{
int len;
uint8_t buff[INTERRUPT_BUFFER_SIZE];
} Buffer;
this particular one stores a variable array named buff
with element size of INTERRUPT_BUFFER_SIZE
. Next is needs to declare a variable name that is stored directly into PSRAM:
Buffer *bufferA = (*Buffer) heap_caps_malloc( sizeof(Buffer), MALLOC_CAP_SPIRAM );
Followed by its initialization in the setup function
//setup() initialization
void setup(){
bufferA = new Buffer();
...
}
Its usage through the code is made this way " bufferA->field
" instead of the regular traditional way " bufferA.field
".
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.