Issue reading char * data from SDRAM with M4 core

I only noticed this recently, but when I am reading floating point values, all seems to be OK - when setting data in SDRAM from M7, and reading the same data from M4.

When the data is a char* value however, I get errors.

For example - if I were to print an IP address 192.168.000.204, I get 1926168.0000204

I get similar substitutions of character values in the string with other data (a device name, other IP addresses (DNS, GW, SN etc.).

When I print the same data from the M7 side (reading the same data in SDRAM, and printing it), the data is correct.

The data in the SDRAM is written once by the M7 core, and then read repeatedly by the M4 (except when checking the data in M7, I may read it there as well).

Also if I RPC.write the char* string 1 character at a time, I get the same error.

As mentioned, floating point data values seem to be read with no errors.

The issue should not be SDRAM data being overwritten by some other part of the code inadvertently, as mentioned it prints correctly when printed from the M7 side.

Anyone run across anything like this?

Sample of output

RPC IP=1926168.0000204
RPC SN=255.2.5.255.00
RPC DNS=192.1680000.150
RPC GW=1.2.168.0.0.001

should be 

RPC IP=192.168.000.204
RPC SN=255.255.255.000
RPC DNS=192.168.000.150
RPC GW=192.168.000.001

I think you mean character data (C-strings, or zero terminated character arrays).

"char*" is a pointer.

For help with code, post the code, using code tags.

pointer to character string.

I save a block at the start of the SDRAM - the address is passed by RPC call to M4, and then the data locations of all the data are known.

for example below is my setup structure

struct _RPCSetupVars {
  char deviceName[MAX_STRLEN_CM4_SETUPVARS];
  bool useDHCP;
  char ip[30];
  char sn[30];
  char dns[30];
  char gw[30];
  bool useGmail;
  char setupEmailAddr[MAX_STRLEN_CM4_SETUPVARS];
  char exchServerIPFQDN[MAX_STRLEN_CM4_SETUPVARS];
  char setupPassword[MAX_STRLEN_CM4_SETUPVARS];
  int setupSMTPPort;
  char sendToEmail[MAX_STRLEN_CM4_SETUPVARS];
  char accountUserName[MAX_STRLEN_CM4_SETUPVARS];
  char accountPassword[MAX_STRLEN_CM4_SETUPVARS];
  bool swapModbusFloatBytes;
  char NTPTimeServer[MAX_STRLEN_CM4_SETUPVARS];  // the NTP time server to use
  long NTPUpdateInterval;                        // the update interval for the NTP server
  long NTPTimeZone;                              // the time zone, offset in seconds from GMT
  bool NTPDST;                                   // if true - use Daylight savings time
  int DSTIndex;                                  // index in DST array for selected time zone
  float altitude;                                // CO2 sensor altitude
  float tempOffset;                              // CO2 sensor Temp Offset
  bool doSPILCD;                                 // which LCD to display on
} *RPCSetupVars = NULL;

RPCSetupVars - is set to the SDRAM address in both M4 and M7

The data is filled in by the M7 core, and then the values are available in the M4 core.

I copy the IP address for example in the ip[30] string, and that is what I am printing from the M4 and the M7 side

Interestingly enough, I replaced

                char ipDisp[4][30];


                sprintf(ipDisp[0], " IP=%s", RPCSetupVars->ip);

with

                char ipDisp[4][30];


                strcpy(ipDisp[0], " IP=");
                strcat(ipDisp[0], RPCSetupVars->ip);

And that displays OK on my M4 side (being printed on LCD screen).

When sending the data by RPC from M4->M7 with

                RPC.print("\nRPC IP=");   // I am sending on purpose one character at a time to see if error in sending whole string
                for (int j = 0; j < 15; j++)   // no diffrence however - same error whether send one character at a time, or whole string at a time
                  RPC.print(RPCSetupVars->ip[j]);

I still get the errors

Or to a single character.

For help with code, post ALL the code. You appear to be unfamiliar with multidimensional arrays.

That is more or less the whole code - I set the IP string in M7, and I read it in M4 as above

ipDisp[4][30] is the multidimensional array (I print 4 lines on the LCD display)

ip[30] is a single char array in the RPCSetupVars structure

I was RPC.print'ing one character at a time, or whole string at a time to see if there was a difference, and both give the same error.

However reading the string with a strcat(dest, SDRAMsourcestring), seems to work???

I swapped the shared memory location for regular RAM instead of SDRAM, and all works OK.

    //RPCSetupVars = (struct _RPCSetupVars *)SDRAM_RPCSetupVars; // this was an SDRAM address
    RPCSetupVars = (struct _RPCSetupVars *)malloc(sizeof(struct _RPCSetupVars));
    if (RPCSetupVars == NULL) {
        SerDebugln(F("Error Allocating RPCSetupVars"));
    }**strong text**

I was passing the address to M4 (via an RPC call), so no change in the code on teh M4 side.

The outputs are clean

RPC IP=IP = 192.168.000.203
RPC SN=IP = 192.168.000.203
RPC DNS=SN = 255.255.255.000
RPC GW=DNS= 192.168.000.150

I will try to open a support call with Arduino to see if there is anything that prevents M4 from reading long sequences of SDRAM data

When passing pointers between cores you must implement cache cleaning and or updating or else you will see corrupted data. If you don't do that and your last code seems to work, that's pure luck. I've been bit numerous times, seeing the kind of problems that you have.

Thanks - i had tried using hal shared nemory regions, but could not get it to work well, that is why i used sdram.

I did not think that sdram regions were cached, do you know if that is the case.

My data is written once, and then never changed, so likely the cache gets flushed out, and that is why it works with the regular memory.

I have not heard anything from arduino support about shared sdram yet.

Yes, sdram is cached. I know this from working with it not by reading a manual but by seeing what happens if you don't manage the cache properly.

There is an example that shows how to use dual mode DMA. It has the code that I started working from and that made it work for me. The memory that you use must be properly aligned in memory, and you need to account for cache lines being at least 32 bytes. That example has memory alignment lines like

/* Variable containing ADC conversions results */
ALIGN_32BYTES(__IO uint32_t   aADCDualConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]);    /* ADC dual mode interleaved conversion results (ADC master and ADC slave results concatenated on data register 32 bits of ADC master). */
ALIGN_32BYTES(__IO uint16_t   aADCxConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]);       /* For the purpose of this example, dispatch dual conversion values into arrays corresponding to each ADC conversion values. */
ALIGN_32BYTES(__IO uint16_t   aADCyConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]);       /* For the purpose of this example, dispatch dual conversion values into arrays corresponding to each ADC conversion values. */

It also has the HAL functions that you need to call. The example is part of a zip file that you need to download from ST Micro. The path is something like STM32Cube\Repository\STM32Cube_FW_H7_V1.10.0\Projects\STM32H747I-DISCO\Examples\ADC\ADC_DualModeInterleaved\CM7\Src\main.c

Hi,
can you please post here some minimal working example of sharing SDRAM? I've tried clearing and invalidating cache, but my shared string is mess - more specifically every 4th char is wrong :smiley:

Thanks