cancel
Showing results for 
Search instead for 
Did you mean: 

Dual core concurrent access to the same FMC memory address

scuba
Associate II

Hello,

We have a STM32H755 with an FRam (similar to SRAM) module attached to the FMC. We have been seeing CPU exceptions when the M4 core tries to access (read only) the same memory location the M7 core is writing to.

So, it seems that the FMC does not arbitrate between the two cores... Is that correct? or do we potentially have the FMC configured incorrectly.

 

We have the FRam memory address region configured in the MPU as shareable (M7 - read/write) and read-only (M4 - reads only) and tried with cache disabled as well with same cpu exception...

Thanks,

-mike

8 REPLIES 8
mƎALLEm
ST Employee

Hello,

I don't think there is a limitation in term of concurrent access to the same memory between both cores, either from internal or external memories . The bus matrix is there to manage that kind of arbitration.

If I understood well, the exception is seen from CM4, right not from CM7? and what do you mean by "the M4 core tries to access (read only)"? code execution? reading only data?

 

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.

Thanks mƎALLEm for the response, I'm Scuba's minion following up with more details.  The CM7 generates the exception.  Its reading only data, no code execution/instructions.

What we are seeing is if the M4 and M7 are accessing different addresses on the FRam, it works fine but if the M7 is writing to an address when the M4 is polling(reading) the SAME address for changes, the M7 will generate a memmanage fault if there is a "simultaneous" access. If its not simultaneous, there is no issue. We've tested ensuring D-Cache is disabled, slowed down timing, tweaked FMC / MPU settings, nothing has helped. We'd prefer not to add complexity by using a hardware semaphore(or equivalent strategy) to ensure there is no simultaneous access to it so asking for verification if the FMC correctly arbitrates this situation or not? Since the M4 is polling, it doesn't matter who goes first,

here is some of the code:

M7 configures FMC as follows:

hsram1.Instance = FMC_NORSRAM_DEVICE;
hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;

/* hsram1.Init */
hsram1.Init.NSBank = FMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FMC_WRITE_BURST_ENABLE;
hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;

/* Timing */
Timing.AddressSetupTime = 11;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 11;
Timing.BusTurnAroundDuration = 11;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/* ExtTiming */

if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
{
Error_Handler( );
}


M7's MPU configuration, should be Strongly Ordered:

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

HAL_MPU_ConfigRegion(&MPU_InitStruct);

M4's MPU is same except Read-Only Access Permission.


Here is some pseudo code, FramCounter are at the same address for both in the external FRam:


The M7 is effectively just doing:

__attribute__((section(".Fram"))) uint16_t FramCounter;
uint16_t InternalCounter = 0;

// The trigger happened, increment the counter
FramCounter = InternalCounter;
++InternalCounter;

Then the M4 is polling/reading the FramCounter to change:

__attribute__((section(".Fram"))) uint16_t FramCounter;
uint16_t InternalCounter;
uint16_t PreviousCounter = 0;

//inside a function that runs periodically
InternalCounter = FramCounter;
if(InternalCounter != PreviousCounter)
{
    //Do Work
    PreviousCounter = InternalCounter;
}

Given that simultaneous access to the same address causes a MemManage fault on the M7, can ST confirm if this is expected behavior due to lack of FMC arbitration?  Although you mentioned the bus matrix handles this arbitration?  In this situation, is the only supported solution to serialize access (e.g., hardware semaphore or software lock), or is there an FMC/MPU configuration that allows safe concurrent access?

Hello,

As I said previously to my knowledge we don't have a limitation on this situation at least at the current time. None of our customers reported that.

What if you access by address and make CM7 / CM4 access to different FRAM addresses?

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.

Thank you for the follow up.

You asked, "What if you access by address and make CM7 / CM4 access to different FRAM addresses?"

We had confirmed accessing different FRAM addresses does NOT cause a fault and works correctly.

The fault only occurs when the M4(polling read) and the M7 (write) attempt to access the SAME address simultaneously.

Is there any other information or settings that might help figure out investigate / how to fix it?

Try now to access the same location but by using access by address: define a pointer and use it as the address of the variable that you need to write to/read from ..

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.

Hi mƎALLEm,
I tried doing it by address, if I used the same address on M4 to read and M7 to write, still faulted.  If I used different addresses, no fault.

M7:

static uint16_t *FramCounter= reinterpret_cast<uint16_t *>(0x60009000);
uint16_t InternalCounter = 0;

// The trigger happened, copy the current counter to FRAM
*FramCounter = InternalCounter;
++InternalCounter;

M4:

static uint16_t *FramCounter= reinterpret_cast<uint16_t *>(0x60009000);
uint16_t InternalCounter;
uint16_t PreviousCounter = 0;

//inside a function that runs periodically
InternalCounter = *FramCounter;
if(InternalCounter != PreviousCounter)
{
    //Do Work
    PreviousCounter = InternalCounter;
}


Then if I change the M7's FramCounter to the following so its a DIFFERENT address, 0x6000900C, fault goes away:

static uint16_t *FramCounter = reinterpret_cast<uint16_t *>(0x6000900c);

 

You mentioned the bus matrix handles arbitration.  I looked into our code and we are not configuring the AXI/AHB bus matrix, therefore we are using the default settings.  When sharing memory between cores like in this case, is there specific bus settings that should be configured?

 

Thank you ahead of time

There is no specific configuration needed for AXI for this scenario. But what fault CM7 is reporting?

Another question, what if you do the same test on the AXI-SRAM memory instead of FMC?

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.

Hello,

I just did the same test on a STM32H745_DISCO board with an access to two locations: SDRAM and AXI-SRAM using IAR IDE and didn't face any issue. The memory location content is incremented from CM7 side and it is read from CM4 side. No fault faced from both cores:

CM7: showing the written value to SDRAM (0xD0000000):

mALLEm_0-1759500862396.png

CM4: showing the read value from SDRAM (0xD0000000):

mALLEm_1-1759500873481.png

So I'm sure you have something else in your project. Check also your linker file, could it be a stack corruption?

For your reference, I've attached the project I used for the test. So please refer to the MPU config, the linker scripts. SDRAM configuration is already done in system_stm32h7xx.c by activating the define DATA_IN_ExtSDRAM.

Hope that helps.

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.