Skip to main content
Visitor II
May 22, 2025
Question

MemMnage_handle Fault After Enabling MPU for ADC1 (STM32)

  • May 22, 2025
  • 2 replies
  • 657 views

Hello,

Why am I getting a Memory Management fault when enabling the MPU for ADC1, even though the MPU region is configured correctly?

Could it be due to alignment issues or internal access within the HAL code (e.g., ADC12_Common)?

Any guidance would be appreciated!

Thanks in advance.

 

MPU Configuration

 

/* Update MPU settings for newly activating Zone */
void osZoneSetup_Callback (uint32_t zone) {
ARM_MPU_Disable();
ARM_MPU_Load(mpu_table[zone], MPU_REGIONS);
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
}

MPU Region for ADC

// ADC1, ADC12_Common (0x40022000..0x400227FF)
{ .RBAR = ARM_MPU_RBAR(3U, 0x40022000), .RASR = ARM_MPU_RASR_EX(1U, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(0U), 0x00U, ARM_MPU_REGION_SIZE_16KB) },
// VREFBUF (0x58003C00..0x58003FFF)
{ .RBAR = ARM_MPU_RBAR(4U, 0x58003C00), .RASR = ARM_MPU_RASR_EX(1U, ARM_MPU_AP_FULL, ARM_MPU_ACCESS_DEVICE(0U), 0x00U, ARM_MPU_REGION_SIZE_1KB) },

 

ADC1 Initialization

static void MX_ADC1_Init(void)
{

/* USER CODE BEGIN ADC1_Init 0 */

/* USER CODE END ADC1_Init 0 */

ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};

/* USER CODE BEGIN ADC1_Init 1 */

/* USER CODE END ADC1_Init 1 */

/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_8B;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.Oversampling.Ratio = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}

/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
sConfig.OffsetSignedSaturation = DISABLE;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}

Kindly help me.

 

SRMahalakshmi_1-1747897685287.png

    This topic has been closed for replies.

    2 replies

    Visitor II
    May 26, 2025

    Hello ST team,

     

    I’m following up on query as I haven’t received a response yet. Please let me know if there’s any update or if you need more details from my side to move forward.

    Thank you, and I look forward to your reply.

    Visitor II
    May 26, 2025

    SRMahalakshmi_0-1748262096799.png

    Please refer to the image above. I can now confirm that hadc1.Instance correctly points to ADC1 at address 0x40022000; however, sConfig.Channel appears to be mapped to an incorrect memory location. Any suggestions to help resolve this issue would be helpful. Thank you.

     

    Explorer
    May 26, 2025

    > ... however, sConfig.Channel appears to be mapped to an incorrect memory location.

    I don't know what this sConfig / Channel parameter are used for, I don't use Cube/HAL in any of my projects.
    But it is supposedly related to the channel setup, and most probably not the cause for the MPU fault.

    I suggest to debug in single-step mode, to see which access actually triggers the MPU fault.
    Or retrieve the fault address from the respective Syscfg register in the fault handler afterwards, and crosscheck with the map file.

    Visitor II
    May 27, 2025

     

    Thank you for your assistance.

    I am working with the STM32H733 microcontroller and handling multiple ADC channels as shown in the example below:

    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_19;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
    sConfig.Offset = 0;
    sConfig.OffsetSignedSaturation = DISABLE;
    
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    {
     Error_Handler();
    }
     
     

    The function HAL_ADC_ConfigChannel internally calls the low-level driver functions, and during this process, the line

     

    adc1.Instance->PCSEL_RES0 |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfig.Channel) & 0x1FUL));

    is executed, which triggers a Memory Management fault.

     

     if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) == 0UL)
     {
     if (!(__LL_ADC_IS_CHANNEL_INTERNAL(sConfig->Channel)))
     {
    #if defined(ADC_VER_V5_V90)
     if (hadc->Instance != ADC3)
     {
     /* ADC channels preselection */
     hadc->Instance->PCSEL_RES0 |= (1UL << (__LL_ADC_CHANNEL_TO_DECIMAL_NB((uint32_t)sConfig->Channel) & 0x1FUL));
     }
    
    #ifndef __ARM_COMPAT_H
    __STATIC_FORCEINLINE void __disable_irq(void)
    {
     __ASM volatile ("cpsid i" : : : "memory");
    }

    Could you please clarify the following points:

    1. Is the PCSEL_RES0 register valid and accessible for ADC channel preselection on my STM32 MCU?

    2. Are there specific conditions or initializations required before accessing this register?

    3. Is it safe to use the macro __LL_ADC_CHANNEL_TO_DECIMAL_NB() with channels?

    4. Are there any known issues or recommended debugging steps related to this part of the ADC HAL/LL drivers?