Access of SDRAM by both M4 and M7 cores

Does anyone know if it is possible for both cores to have access to the SDRAM - I would like to use it as a shared memory location.

1 Like

Yes, you can do that. I use SDRAM by allocating byte arrays and casting them to classes as an object.

The way I do dual core is by using RPC between the cores to get each other's pointers. Either core can work with them. You need to clean or update the cache depending on the situation. CORE_CM4 has no cache, CORE_CM7 does. You may need to add some RPC functions to clean or update the cache on CORE_CM7 from CORE_CM4. The STM32 HAL API has functions for doing that. Read its documentation, the size must be at least 32 bytes (size of a cache line).

Thanks for the confirmation, that is what I did as well, and it is working so far (Just wanted to make sure it wont crash periodically because of some conflict).

I save a certain amount of dat space at 0x60000000 (and start SDRAM.begin after that reserved space.

This way as the address location is reserved in the header file, both cores automatically know where the data is.

I also malloc'ed a structure that I pass the pointer from M7 to M4, and then I share the regular MCU SRAM as well - that works too (for variables that are accessed more frequently, I use the SRAM for speed).

The only negative of the whole process is that most of my data is kept in an array of a class (each class defines a sensor), and also a setup class.

I don't think it is possible to send a pointer to the class that is defined in M7 to M4 to use it, so I end up having to copy the required data into a structure array which has a list of pointers, and those pointers indicate where the data is located in each of the classes.

A little clunky, but at least the data transfer is relatively invisible to the code, and no significant duplication of RAM space is required.

I send pointers back and forth all the time, just cast it to a uint32_t then cast it back to what it is on the other side, and of course handle the caching properly. That has always worked for me.

Thanks for sharing your experience. Altogether the Portenta H7 Lite works pretty well for me. I use dual core, RPC, SDRAM, QSPI flash for USBMSD, and STM32CubeIDE for prototyping HAL functions for ADC, timers, GPIO, DMA. I do the Portenta build in a makefile project in the same IDE for debugging with ST-Link v2. Not bad at all though it took me a long time to figure it out.

Do you have some minimal code example please? I am struggling with similar topic :-/ :smiley:

My original way of sharing data via SDRAM did not work as well as expected, and it all related to caching of the data when written by one core, and then not being available when read by the other core.

I still need to try creating a block of memory - say 16kB at the start of the 0x60000000 SDRAM address space, and then allocating variables manually inside that space as I was doing. HAL routines are available that can define an area of memory as shareable - to prevent the cache issues.

I have been busy with other issues, and have not had a chance to do this. I will post the code if it works when implemented.

Hi, any progres?? :slight_smile:
Thanks

I was never able to get it to work reliably. I am not sure if the actual simultaneous access by two cores has anything to do with it at the hardware level. The errors I was getting (mo0stly replacement of single characters in a C string) were always present (not random). I had reserved the first 1MB of SDRAM for this use, and had declared that segment of SDRAM as non_cacheable and shareable as below

  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.BaseAddress = 0x60000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_1MB;
  //MPU_InitStruct.SubRegionDisable = 0x00;
  //MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

I would write a value, and read it immediately, and see the data read back was not what was written. If the same data was read from the other core, errors were still present, but non necessarily the same ones.

Changing the code to simply use a malloc'ed area in regular RAM (with no other changes) worked OK.

As I write the data mostly just once, and never update it, cache is not usually a concern - and I did not make this area shareable, but that can still be done.

Sorry can't help more than this