2017-08-18 12:40 AM
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_handler2017-08-18 05:04 AM
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.
2017-08-18 10:13 AM
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)
2017-08-18 01:41 PM
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
2017-08-19 01:48 PM
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
2017-08-19 02:54 PM
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
2017-08-19 03:36 PM
>>
I use IARAnd is that profoundly different?
The routine decodes the stack frame and pulls the PC of the faulting instruction.
2017-08-19 03:41 PM
;... 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
;...�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-08-19 04:11 PM
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 */
}}