RAK15007 FRAM addressing

Please include the following information, in order for us to help you as effectively as possible.

  • What product do you wish to discuss? RAK15007

  • What firmware are you using? Arduino BSP

  • Computer OS? Windows

  • What Computer OS version? Windows 11

@beegee ,

I am using the RAK15007 as a place to store LoRa payload when my tracker (RAK19007, RAK4631, RAK12500, RAK1904, RAK1906, RAK15007) when it is out of the LoRa coverage area. When the LoRa coverage is back, the RAK15007 content written it was out of LoRa coverage.

I would like to understand better how is the addressing process in the RAK15007 code RAK15007_FRAM_Read_Write_CY15B108QN

  • In the sentence “for (uint32_t addr = 0; addr < 0xFF; addr += sizeof(specialSector_wBuf) / sizeof(char))”, “addr” is defined as a uint32_t with initial value zero.

  • In the sentence “fram_cy15b108.specialSectorWrite(addr, (uint8_t*)specialSector_wBuf , sizeof(specialSector_wBuf) / sizeof(char));” addr is FRAM address where the specialSector_wBuf content will be wirtten

Should be addr hexadecimal? If addr is hexadecimal, where it is defined this way?

Could you help me?

Regards,

Cláudio

void specialSectorWriteAndReadTest(void)
{
  char specialSector_wBuf[32] = "<Special Sector Write And Read>";
  char specialSector_rBuf[32] = {0};
  uint32_t successCount = 0;
  uint32_t failCount = 0;

  float progress = 0;

  for (uint32_t addr = 0; addr < 0xFF; addr += sizeof(specialSector_wBuf) / sizeof(char))
  {
    fram_cy15b108.writeEnable(true);
    fram_cy15b108.specialSectorWrite(addr, (uint8_t*)specialSector_wBuf , sizeof(specialSector_wBuf) / sizeof(char));
    fram_cy15b108.specialSectorRead( addr, (uint8_t*)specialSector_rBuf , sizeof(specialSector_rBuf) / sizeof(char));
    fram_cy15b108.writeEnable(false);

    if (memcmp(specialSector_wBuf , specialSector_rBuf , sizeof(specialSector_rBuf)) == 0)
    {
      successCount++;
    }
    else
    {
      failCount++;
    }
    Serial.printf("Special Sector Write And Read Test Progress: %5.2f%% , successCount: %ld , failCount:%ld \n", progress, successCount, failCount);
    progress = (float)(addr + sizeof(specialSector_wBuf) / sizeof(char)) * 100 / 0xff;
    memset(specialSector_rBuf , '0' , sizeof(specialSector_rBuf) / sizeof(char));
    delay(100);
  }
}

@carlrowan ,

Could you help me with this problem? I opened this topic to @beegee because the github code for RAK15007 , it was made by him, but after 3 day without answer, I suppose that he is on vacation or busy.

Regards,

Claudio

Not sure if I understand Should be addr hexadecimal?
You can write the address in decimal, binary or hexadecimal. The compiler will take care of it.

specialSectorWrite takes as parameters the address, a pointer to the data to write and the size of the data.

Good morning,

I am doing for a Railroad company, a wagon tracking (RAK12500/RAK1904), wagon monitoring (RAK5801 brakes air pressure with a pressure transducer), device environment health monitor(RAK1906). The point is that not always in the railway network we will have LoRa coverage. Then the FRAM (RAK15007) or SD Card (RAK15002) will be used to store the WisCayenneLPP buffer until the LoRa coverage is available again, then device will read from FRAM/SD Card, move the content to the LoRa payload to be sent.

Now I am testing how to:

  1. Save the last memory address used to write next WisCayenneLPP buffer in the next memory address available
  RAK15007.writeEnable(true);
    RAK15007.specialSectorWrite(endereco, (uint8_t*)WisCayenneLPP.getBuffer() , sizeof(WisCayenneLPP.getBuffer()));
    RAK15007.specialSectorRead(endereco, &PayloadBufferTam , sizeof(PayloadBufferTam));
    RAK15007.writeEnable(false);

    if (memcmp(WisCayenneLPP.getBuffer() , &PayloadBufferTam , sizeof(PayloadBufferTam)) == 0)
    {
      successCount++;
    }
    else
    {
      failCount++;
    }

Ok, so you need the large FRAM to store as many payloads as possible and then access them one by one to send them out when connection is available.

If you payload size is different in sizes, you will need to save the entry address for each payload.

On option I can think of is to write into the FRAM like a queue
<number-of-payload-1><size-of-payload-1><payload-1>,<number-of-payload-2><size-of-payload-2><payload-2>,...>
or similar to know where the payloads are.

Or have beside of the payloads a table with address pointers to the payloads in the FRAM.

Based on LoRa requirements, in the worst case for transmission (SF 12), the maximum payload size is 51 bytes, then I am planning to work at maximum of 51 bytes for WisCayenneLPP buffer.

This following your idea, ",,…>, when the device is reading the FRAM(RAK15007), how to know/where store and recover the information queue?

I loved with both solutions: queue and table. The point is how/where to handle(store/recover) the information queue/table?

Could you give a example how to handle this queue/table in the FRAM?

Well, when I finished the solution development for FRAM, I will need to create a similar thing for SD Card(RAK15002) :slight_smile:

Claudio

With the first option <number-of-payload-1><size-of-payload-1><payload-1>,<number-of-payload-2><size-of-payload-2><payload-2>,...> you do not need a separate table, as each entry will tell you where the next entry is (address of number-of-payload-n + size-of-payload). You only need to make sure that the first “empty” entry has a marker, e.g. number-of-payload-n+1 == 0xFF.

On the second option, you could start with the payloads from address 0x00 and put the table at the very end of the FRAM storage.

For me it would be important to have the payloads + the information about address + size in the FRAM, so you will not loose it on a power-brownout.
However, more details are needed to avoid an invalid queue or table in case a power brownout occurs while writing to the FRAM. This could be a CRC on both the payloads and table or in the queue.

Thank you.

I will develop the solution and I give news as soon as possible.

Just to give the idea how I am building the payload, this is the payload code:

    WisCayenneLPP.reset();

    WisCayenneLPP.addUnixTime(LPP_UNIXTIME, RAK12500.UNIXEpoch);
    WisCayenneLPP.addVoltage(LPP_VOLTAGE, VBat.real_vbat);
    WisCayenneLPP.addAccelerometer(LPP_ACCELEROMETER,RAK1904.EixoX,RAK1904.EixoY,RAK1904.EixoZ);
    WisCayenneLPP.addTemperature(LPP_TEMPERATURE, RAK1906.Temperatura);
    WisCayenneLPP.addRelativeHumidity(LPP_RELATIVE_HUMIDITY, RAK1906.Humidade);
    WisCayenneLPP.addBarometricPressure(LPP_BAROMETRIC_PRESSURE, RAK1906.PressAtm);
    WisCayenneLPP.addGNSS_6(LPP_GPS6, RAK12500.Latitude, RAK12500.Longitude, RAK12500.Altitude);

    TamanhoPayload = WisCayenneLPP.getSize();

Claudio