ArduinoJson icon indicating copy to clipboard operation
ArduinoJson copied to clipboard

Can arduinojson work with ESP spi.transfer() ?

Open zekageri opened this issue 1 year ago • 0 comments

I'm using a library for an external RAM. Currently i can write and read char arrays like this:

SRAM.writeBlock(START_ADDRESS, size, (void*)buff);
SRAM.readBlock(START_ADDRESS, size, buff);

The underlying code in the library just using the standard ESP32 spi library.

size_t SRAM_23LC::readBlock(const uint32_t address, const size_t length, void * buffer)
{
  if (address >= _capacity || length == 0) {
    return(0);
  }

  startCommand(SRAM_23LC_COMMAND_READ, address);
  _spi->transfer(buffer, length);
  endCommand();

  return(length);
}

size_t SRAM_23LC::writeBlock(const uint32_t address, const size_t length, void * buffer)
{
  uint8_t *buf = reinterpret_cast<uint8_t *>(buffer);
  size_t len = length;

  if (address >= _capacity || length == 0) {
    return(0);
  }

  startCommand(SRAM_23LC_COMMAND_WRITE, address);
  while (len--) {
    _spi->transfer(*buf);
    buf++;
  }
  endCommand();

  return(length);
}

void SRAM_23LC::startCommand(const uint8_t command, const uint32_t address)
{
  _spi->beginTransaction(_spiSettings);
  digitalWrite(_chipSelect, LOW);

  _spi->transfer(command);
  if (command == SRAM_23LC_COMMAND_READ || command == SRAM_23LC_COMMAND_WRITE) {
    sendAddressBytes(address);
  }
}

Currently i have to do something like this in order to write to the ram.

boolean Sram::writeJson(JsonDocument doc){
    size_t size = measureJson(doc);
    char* buff;
    if(!hshSystem.alloc(buff,size)){ return false; } // Just a malloc wrapper
    size_t result = serializeJson(doc, buff, size);
    if( result ){
        result = SRAM.writeBlock(START_ADDRESS, size, (void*)buff);
        Serial.printf("(%d) SRAM write result: %d\n",size,result);
    }
    free(buff);
    return result;
}

As you can see i have to allocate a buffer and send it to the ram, this isn't bad at all but the problem starts when i have to read it. I don't know the buffer size ahead of time so i have created this

boolean Sram::readJson(JsonDocument doc){
    char* buff;
    if(!hshSystem.alloc(buff,MAX_BUFF_SIZE)){ return false;} // Just a malloc wrapper
    size_t result = SRAM.readBlock(START_ADDRESS, MAX_BUFF_SIZE, buff); // Must read everything? Including garbage.
    if(result){
        DeserializationError error = deserializeJson(doc, buff, MAX_BUFF_SIZE);
        result = error != DeserializationError::Ok;
    }
    free(buff);
    return result;
}

This method allocates MAX_BUFF_SIZE which is the maximum amount of space in the external ram. Can i use spi transfer like a stream so i can deserialize it directly into JsonDocument without creating unnecessary buffers for read? The problem that the write is working ( in theory ) but the deserialization fails. Probably because it also reads garbage values.

I have no problem modifying the library in any way

zekageri avatar Jan 22 '24 09:01 zekageri