cancel
Showing results for 
Search instead for 
Did you mean: 

How to do SRAM3 shared memory mapping in user space for data transfer between the A7 cores and the M4 core.

Kvan .6
Associate II

I want to use part of the SRAM3 shared memory for data transfer between the A7 cores and the M4 core. On the A7 core I used mmap on /dev/mem to remap the sram to user space and copy the data to/from the SRAM3 buffers. The result is however not stable.

When reading the data at the M4 side the data sometimes seems to be changed.

On the M4 side I did add an extra memory area (RAM3_ipc_shm):

MEMORY

{

 RETRAM_interrupts (xrw) : ORIGIN = 0x00000000, LENGTH = 0x00000298

 FLASH_text (rx) : ORIGIN = 0x10000000, LENGTH = 128K

 RAM1_data (xrw) : ORIGIN = 0x10020000, LENGTH = 128K

 RAM2_ipc_shm (xrw) : ORIGIN = 0x10040000, LENGTH = 0x00008000

 RAM3_ipc_shm   (xrw)  : ORIGIN = 0x10048000, LENGTH = 0x00004000

}

And just read /write to this area like:

 volatile uint16_t *data_in = 0x10048000;

 volatile uint16_t *data_out = 0x1004A000;

nof_write_bits = 16 * data_in[0];

// set output data

for (int i = 0; .....

{

// DO0-DO3 & clear data clock & clear latch

outputs0 = (data_in[4 + i] << 11) & DO03_mask;

// D04-D05

outputs1 = (data_in[4 + i] << (14 - 4)) & DO45_mask;

// read inputs

inputs0 = (uint16_t) ((DI0_GPIO_Port->IDR & DI03_mask) >> 3);

inputs1 = (uint16_t) ((DI4_GPIO_Port->IDR & DI45_mask) >> (12 - 4));

data_out[i - read_bits_offs] = inputs0 | inputs1;

}

On the A7 side:

volatile uint8_t *the_smem_buf;

volatile uint8_t *the_read_pos;

// Map the shared memory windows

the_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);

the_smem_buf = static_cast<volatile uint8_t *>(mmap (NULL, 0x4000, PROT_READ | PROT_WRITE, MAP_SHARED, the_mem_fd, 0x10048000));

 the_read_pos = the_smem_buf + 0x2000;

// write data to M4 

  for (int i = 0; i < len; i++)

    the_smem_buf[i] = ((uint8_t *) pData)[i];

// read data from M4

 memcpy(pData, (void *) the_read_pos, len);

I use the rpmsg mechanism to sync between writes and reads to the M4 core.

Observations: for the first 4 16 bit values in the shared data buffer everything looks OK, but when having non-zero data in higher regions, the data sometimes is missing or non-zero where it should be zero.

Any idea what goes wrong here? Do I have to add the memory area to the device tree? Or is it not possible at all to do transfer by a memory mapped area? Is there something missing in the memory map in the linker script at the M4 side?

1 ACCEPTED SOLUTION

Accepted Solutions
Kvan .6
Associate II

Patrick and Olivier,

Thanks for your help. Took me some effort but I did find out that the synchronization between the A7 core and the M4 with RPMsg was causing the problem: at the start I send a start command over RPMsg and waited for the M4 to reply over RPMsg, but somehow another messages was received, causing a synchronization mismatch, causing a write of new data by the A7 core before the M4 had finished its cycle. I repaired this by introducing a serial id in my communication over RPMsg.

With the synchronization fixed, I could remove the sleeps of 200us and everything worked OK.

So lessons learned: mapping SRAM memory to user space with mmap on /dev/mem does work ok! No specific driver for mapping the SRAM is needed, neither the specification of the memory area in the DT (although I think it is wise to do, to be clear that the memory area is used).

View solution in original post

4 REPLIES 4
Kvan .6
Associate II

I did find out that when doing a sleep of 200 usec just before the write and read of 1KB at the A7 core the problem seems to have disappeared.

Probably some timing issue which I don't understand. The strange thing is that the extra sleep is not between the write at the A7 side and the read on the M4 side, but just before the next write at the A7 side, it looks like that when not doing the extra sleep that some data of the previous write cycle will not be overwritten by the newly written data.. Does someone have an explanation for this behavior?

Kees van Walraven

Hi,

I'm not expert, but I found this post which might be relevant for you:

https://community.st.com/s/question/0D53W00000uXp2hSAC/rpmsg-sdb-cached-buffer

Regards.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
Olivier GALLIEN
ST Employee

Hi @Kvan .6​ ,

post https://community.st.com/s/question/0D53W000013pGreSAE/reallocation-of-sram-memory-to-stm32mp157a may also be relevant.

You have to take care that new partitioning of SRAM3 is properly declared in Linux DT

Olivier

Olivier GALLIEN
In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
Kvan .6
Associate II

Patrick and Olivier,

Thanks for your help. Took me some effort but I did find out that the synchronization between the A7 core and the M4 with RPMsg was causing the problem: at the start I send a start command over RPMsg and waited for the M4 to reply over RPMsg, but somehow another messages was received, causing a synchronization mismatch, causing a write of new data by the A7 core before the M4 had finished its cycle. I repaired this by introducing a serial id in my communication over RPMsg.

With the synchronization fixed, I could remove the sleeps of 200us and everything worked OK.

So lessons learned: mapping SRAM memory to user space with mmap on /dev/mem does work ok! No specific driver for mapping the SRAM is needed, neither the specification of the memory area in the DT (although I think it is wise to do, to be clear that the memory area is used).