cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault from ADC_IS_CONVERSION_ONGOING_REGULAR macro

paolovasta9
Associate II
Posted on August 18, 2017 at 09:40

Hello, I'm using a STM32L071CB.

Some times my code go to HardFault_Handler.

After many test I seen that the interrupt start from  

if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)

in HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)

I don't understand why this error. Code generate with CubeMx 4.22 and L0 library are 1.9.0

attached the adc settings 

void MX_ADC_Init(void)

{

ADC_ChannelConfTypeDef sConfig;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc.Instance = ADC1;

hadc.Init.OversamplingMode = DISABLE;

hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV32;

hadc.Init.Resolution = ADC_RESOLUTION_12B;

hadc.Init.SamplingTime = ADC_SAMPLETIME_39CYCLES_5;

hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc.Init.ContinuousConvMode = ENABLE;

hadc.Init.DiscontinuousConvMode = DISABLE;

hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc.Init.DMAContinuousRequests = ENABLE;

hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc.Init.LowPowerAutoWait = DISABLE;

hadc.Init.LowPowerFrequencyMode = DISABLE;

hadc.Init.LowPowerAutoPowerOff = DISABLE;

HAL_ADC_Init(&hadc);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_9;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_VREFINT;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(adcHandle->Instance==ADC1)

{

/* USER CODE BEGIN ADC1_MspInit 0 */

/* USER CODE END ADC1_MspInit 0 */

/* ADC1 clock enable */

__HAL_RCC_ADC1_CLK_ENABLE();

/**ADC GPIO Configuration

PB1 ------> ADC_IN9

*/

GPIO_InitStruct.Pin = GPIO_PIN_1;

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

GPIO_InitStruct.Pull = GPIO_NOPULL;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* ADC1 DMA Init */

/* ADC Init */

hdma_adc.Instance = DMA1_Channel1;

hdma_adc.Init.Request = DMA_REQUEST_0;

hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_adc.Init.MemInc = DMA_MINC_ENABLE;

hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

hdma_adc.Init.Mode = DMA_CIRCULAR;

hdma_adc.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma_adc);

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc);

/* ADC1 interrupt Init */

HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);

/* USER CODE BEGIN ADC1_MspInit 1 */

/* USER CODE END ADC1_MspInit 1 */

}

}

thank you for help

#dma-adc #adc_is_conversion_ongoing_regular #hardfault_handler
8 REPLIES 8
Posted on August 18, 2017 at 14:04

So probably not the code shown. Consider exactly where the processor tells you where it is faulting, and with what registers. Disassembly view.

Interrupt related check the stack size and usage.

Cortex-M0 is also fussy about memory alignment of 16 and 32-bit memory accesses.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
paolovasta9
Associate II
Posted on August 18, 2017 at 19:13

How can I find where the faulty is?

I used the step by step IAR's debug and every time the faulty was after

if (ADC_IS_CONVERSION_ONGOING_REGULAR(hadc) == RESET)

Posted on August 18, 2017 at 20:41

And where is that in the context of the initialization code you provided?

Does the macro expect &hadc ? Hard Fault suggests you are handing over a bogus address to something. So ponder the structure, and the content within the structure.

Have a proper Hard Fault handler so you can examine the code (the stuff the processor executes, not your high level macro). Disassemble the instructions that are faulting. Look at those and the processor registers in the context of why they would fault.

Here is an example of a Handler that isn't a non-instructive while(1) loop,

https://community.st.com/0D50X00009XkfOXSAZ

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 19, 2017 at 22:48

Check obvious stuff like what hadc is, and if it's valid

Check how you're using 

HAL_ADC_Start_DMA(), you don't show that code.

Best to present a complete example

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 19, 2017 at 21:54

thank you for support..

I seen that the example posted is for Keil. I use IAR.

How can I save the PC and other register when Hard_Fault interrupt fire to understand where is the issue?

If I check the PC when code arrive at the while(1) loop in the hard_fault headler the address in PC is the while(1) instruction... obviusly

thank you

Posted on August 19, 2017 at 22:36

 >>

I use IAR

And is that profoundly different?

The routine decodes the stack frame and pulls the PC of the faulting instruction.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 19, 2017 at 22:41

;... In startup_stm32xxx.s (IAR)
;... Replace PUBWEAK, and code in stm32xxx_it.c
 EXTERN hard_fault_handler_c
 PUBLIC HardFault_Handler
 SECTION .text:CODE:REORDER:NOROOT(1)
HardFault_Handler
 TST lr, #4 ; Determine correct stack
 ITE EQ
 MRSEQ R0, MSP ; Read MSP (Main)
 MRSNE R0, PSP ; Read PSP (Process)
 
 MOV R1, R4 ; Registers R4-R6, as parameters 2-4 of the function called
 MOV R2, R5
 MOV R3, R6 ; sourcer32@gmail.com
 
 B hard_fault_handler_c
;...�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 19, 2017 at 23:11

Header file:

extern uint16_t VBattery;

extern uint16_t TemperatureC;

void UpdateAnalogValue(void);

uint16_t VRef(void);

uint16_t Temperature(uint16_t VBatteryRef);

uint16_t VBatt(uint16_t VBatteryRef);

C file:

uint16_t Int_Vref;

uint16_t VBattery;

uint16_t TemperatureC;

uint16_t ADC_Value[3];

void UpdateAnalogValue(void)

{

HAL_GPIO_WritePin(OPAMP_PWR_GPIO_Port, OPAMP_PWR_Pin, GPIO_PIN_RESET);

HAL_Delay(200);

HAL_ADC_Start_DMA(&hadc, (uint32_t*)ADC_Value, 3);

HAL_Delay(200);

while(!( __HAL_ADC_GET_FLAG(&hadc, ADC_FLAG_EOS))){;}

HAL_ADC_Stop_DMA(&hadc);

HAL_GPIO_WritePin(OPAMP_PWR_GPIO_Port, OPAMP_PWR_Pin, GPIO_PIN_SET);

Int_Vref = VRef();

VBattery = VBatt(Int_Vref);

TemperatureC = Temperature(Int_Vref);

sprintf(debug,'Battery Voltage %d mV\n\rTemperature %d C\n\r',VBattery,TemperatureC);

HAL_UART_Transmit(&huart4,(uint8_t *)debug,strlen(debug),500);

}

uint16_t VRef(void)

{

return (uint16_t)__LL_ADC_CALC_VREFANALOG_VOLTAGE(ADC_Value[1],LL_ADC_RESOLUTION_12B);

}

uint16_t Temperature(uint16_t VBatteryRef)

{

return (uint16_t)__LL_ADC_CALC_TEMPERATURE(VBatteryRef,ADC_Value[2],LL_ADC_RESOLUTION_12B);

}

uint16_t VBatt(uint16_t VBatteryRef)

{

return __LL_ADC_CALC_DATA_TO_VOLTAGE(VBatteryRef,ADC_Value[0]*2,LL_ADC_RESOLUTION_12B);

}

ADC settings generated with Cube MX

ADC_HandleTypeDef hadc;

DMA_HandleTypeDef hdma_adc;

/* ADC init function */

void MX_ADC_Init(void)

{

ADC_ChannelConfTypeDef sConfig;

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

hadc.Instance = ADC1;

hadc.Init.OversamplingMode = DISABLE;

hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV32;

hadc.Init.Resolution = ADC_RESOLUTION_12B;

hadc.Init.SamplingTime = ADC_SAMPLETIME_39CYCLES_5;

hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc.Init.ContinuousConvMode = ENABLE;

hadc.Init.DiscontinuousConvMode = DISABLE;

hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc.Init.DMAContinuousRequests = ENABLE;

hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc.Init.LowPowerAutoWait = DISABLE;

hadc.Init.LowPowerFrequencyMode = DISABLE;

hadc.Init.LowPowerAutoPowerOff = DISABLE;

HAL_ADC_Init(&hadc);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_9;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

/**Configure for the selected ADC regular channel to be converted.

*/

sConfig.Channel = ADC_CHANNEL_VREFINT;

HAL_ADC_ConfigChannel(&hadc, &sConfig);

}

void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(adcHandle->Instance==ADC1)

{

/* USER CODE BEGIN ADC1_MspInit 0 */

/* USER CODE END ADC1_MspInit 0 */

/* ADC1 clock enable */

__HAL_RCC_ADC1_CLK_ENABLE();

/**ADC GPIO Configuration

PB1 ------> ADC_IN9

*/

GPIO_InitStruct.Pin = GPIO_PIN_1;

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

GPIO_InitStruct.Pull = GPIO_NOPULL;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* ADC1 DMA Init */

/* ADC Init */

hdma_adc.Instance = DMA1_Channel1;

hdma_adc.Init.Request = DMA_REQUEST_0;

hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_adc.Init.MemInc = DMA_MINC_ENABLE;

hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

hdma_adc.Init.Mode = DMA_CIRCULAR;

hdma_adc.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma_adc);

__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc);

/* ADC1 interrupt Init */

HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);

/* USER CODE BEGIN ADC1_MspInit 1 */

/* USER CODE END ADC1_MspInit 1 */

}

}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)

{

if(adcHandle->Instance==ADC1)

{

/* USER CODE BEGIN ADC1_MspDeInit 0 */

/* USER CODE END ADC1_MspDeInit 0 */

/* Peripheral clock disable */

__HAL_RCC_ADC1_CLK_DISABLE();

/**ADC GPIO Configuration

PB1 ------> ADC_IN9

*/

HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1);

/* ADC1 DMA DeInit */

HAL_DMA_DeInit(adcHandle->DMA_Handle);

/* ADC1 interrupt Deinit */

HAL_NVIC_DisableIRQ(ADC1_COMP_IRQn);

/* USER CODE BEGIN ADC1_MspDeInit 1 */

/* USER CODE END ADC1_MspDeInit 1 */

}

}