cancel
Showing results for 
Search instead for 
Did you mean: 

Understanding MPU config for FMC LCD on STM32H7

BEvan.2
Associate II

Hi,

I'm currently trying to understand the recommended MPU config (when settings up an 8 bit LCD connected via the FMC on an STM32H742. Everything is currently working, but I haven't been able to wrap my head around why configuring the MPU regions with size MPU_REGION_SIZE_32B is working correctly. The recommended config can be found here: https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/STM32_MPU_tips.html  

I'm configuring the system to use FMC bank 1 with NE2, A18 as data select. The MPU is configured so that regions in FMC bank1 are strongly ordered, similar to that below:

 

    MPU_Region_InitTypeDef configMPU = {0};

    HAL_MPU_Disable();

    // Configure regions for FMC LCD
    configMPU.Enable = MPU_REGION_ENABLE;
    configMPU.Number = MPU_REGION_NUMBER1;
    configMPU.BaseAddress = 0x64000000U;
    configMPU.Size = MPU_REGION_SIZE_32B;
    configMPU.SubRegionDisable = 0x0U;
    configMPU.TypeExtField = MPU_TEX_LEVEL0;
    configMPU.AccessPermission = MPU_REGION_FULL_ACCESS;
    configMPU.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
    configMPU.IsShareable = MPU_ACCESS_SHAREABLE;
    configMPU.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    configMPU.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    HAL_MPU_ConfigRegion(&configMPU);

    // Configure region for FMC LCD data
    configMPU.Enable = MPU_REGION_ENABLE;
    configMPU.Number = MPU_REGION_NUMBER2;
    configMPU.BaseAddress = 0x64040000U;
    configMPU.Size = MPU_REGION_SIZE_32B;    // How does this work when writing past this?
    configMPU.SubRegionDisable = 0x0U;
    configMPU.TypeExtField = MPU_TEX_LEVEL0;
    configMPU.AccessPermission = MPU_REGION_FULL_ACCESS;
    configMPU.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
    configMPU.IsShareable = MPU_ACCESS_SHAREABLE;
    configMPU.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    configMPU.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    HAL_MPU_ConfigRegion(&configMPU);

    // Enable the MPU
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    SRAM_HandleTypeDef hsram1;
    FMC_NORSRAM_TimingTypeDef Timing = {0};    

    // Init FMC for LCD
    hsram1.Instance = FMC_NORSRAM_DEVICE;
    hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
    hsram1.Init.NSBank = FMC_NORSRAM_BANK2;
    hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
    hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
    hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_8;
    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_DISABLE;
    hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
    hsram1.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
    hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;

    // Timing etc. initialised here
    HAL_SRAM_Init(&hsram1, &Timing, NULL)

 

I think this makes sense if performing small writes (less than 32B) to addresses 0x64000000U (commands) and 0x64040000U (data). However, for data, I'm currently using MDMA to transfer larger chunks of data far larger than 32B and everything continues to work as expected. MDMA is set up like this:

 

    MDMA_HandleTypeDef hmdma_mdma_channel40_sw_0 = {0};

    // Configure MDMA request hmdma_mdma_channel40_sw_0 on MDMA_Channel0
    hmdma_mdma_channel40_sw_0.Instance = MDMA_Channel1;
    hmdma_mdma_channel40_sw_0.Init.Request = MDMA_REQUEST_SW;
    hmdma_mdma_channel40_sw_0.Init.TransferTriggerMode = MDMA_REPEAT_BLOCK_TRANSFER;
    hmdma_mdma_channel40_sw_0.Init.Priority = MDMA_PRIORITY_MEDIUM;
    hmdma_mdma_channel40_sw_0.Init.Endianness = MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE;
    hmdma_mdma_channel40_sw_0.Init.SourceInc = MDMA_SRC_INC_HALFWORD;
    hmdma_mdma_channel40_sw_0.Init.DestinationInc = MDMA_DEST_INC_HALFWORD;
    hmdma_mdma_channel40_sw_0.Init.SourceDataSize = MDMA_SRC_DATASIZE_HALFWORD;
    hmdma_mdma_channel40_sw_0.Init.DestDataSize = MDMA_DEST_DATASIZE_HALFWORD;
    hmdma_mdma_channel40_sw_0.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
    hmdma_mdma_channel40_sw_0.Init.BufferTransferLength = 128U;
    hmdma_mdma_channel40_sw_0.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
    hmdma_mdma_channel40_sw_0.Init.DestBurst = MDMA_DEST_BURST_SINGLE;
    hmdma_mdma_channel40_sw_0.Init.SourceBlockAddressOffset = 0U;
    hmdma_mdma_channel40_sw_0.Init.DestBlockAddressOffset = 0U;
    // Callbacks
    hmdma_mdma_channel40_sw_0.XferCpltCallback = TransferCompleteMDMA;
    hmdma_mdma_channel40_sw_0.XferErrorCallback = TransferErrorMDMA;

    HAL_MDMA_Init(&hmdma_mdma_channel40_sw_0);

 

MDMA transfers of pixel data are triggered like this (where w = 320 and h is usually >= 40):

 

    // Init MDMA transfer
    ret = HAL_MDMA_Start_IT(&hmdma_mdma_channel40_sw_0, (uint32_t) pixels, (uint32_t) 0x64040000U, w * 2U, h);

 

So my question is, how is this MPU config working when I'm seemingly writing past the end of the configured region? If fact, even if I change the line above and make the MPU write to address 0x64040100U, everything seems to continue working. If I remove the MPU REGION 2 all together, it no longer works.

I'm leaning towards applying one config to the entire bank to make it strongly ordered but before making any further decisions would like to wrap my head around how the current config is working.

Regards,

Ben

1 ACCEPTED SOLUTION

Accepted Solutions
SofLit
ST Employee

Hi,

MPU is internal to CPU. Only CPU accesses are affected by the MPU. All other masters accesses are not!

Attached the block diagram of the CM7 showing the MPU block:

SofLit_0-1692705455641.png

 

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.

View solution in original post

2 REPLIES 2
Pavel A.
Evangelist III

DMA controllers are not affected by the MPU at all. 

SofLit
ST Employee

Hi,

MPU is internal to CPU. Only CPU accesses are affected by the MPU. All other masters accesses are not!

Attached the block diagram of the CM7 showing the MPU block:

SofLit_0-1692705455641.png

 

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.