Unknown vector causing unhandled exception
Posted: Sat Aug 05, 2017 9:27 am
Quick information: I am using a custom STM32F405RGT6 board, chibios176 with ChibiStudio Preview 19, writing in a combination of C and C++, using ST Link V2 for debugging.
I am attempting to configure ADC1 and ADC2 in Dual Mode Injected Simultaneous Only, to be triggered by TIM1 CC4. I haven't figured out how to do this using the provided drivers, so I've disabled the ADC drivers and manually configured the ADC registers. This set up does not work at the moment, and while trying to figure out the problem, I've tried to force the injected conversion and interrupt as follows:
With this, I get thrown into _unhandled_exception(). Looking at the fault registers, VCATCH in the Debug Fault Status Register is set, but no flags are set in the Debug Exception and Monitor Control Register. I then manually put in handlers for each vector to see what's leading to _unhandled_exception(). Each handler only executes the BKPT instruction.
Oddly, Vector1BC (in position 95) is where it breaks. The STM32F405xx vector table only shows up to position 81, that is Vector184. Additionally, if I comment out Vector1BC, it breaks at Vector1B8 (position 94) instead of going through the weak Vector1BC handler in vectors.c which would end up in _unhandled_exception(). Furthermore, commenting out the vector in position 94 causes it break at 93, and so on to some unknown extent.
I've run out of ideas on how to proceed at this point, and any suggestions will be greatly appreciated.
Extra information: The TIM1 CC4 should be generated using the Chibios PWM driver, but even though the callback for CC4 is called, the ADC injected conversion doesn't seem to be triggered.
The full ADC configuration sequence is as follows (I've left all the clearing operations just to be clear for now, and I'm not even sure this configuration is 100% correct):
I am attempting to configure ADC1 and ADC2 in Dual Mode Injected Simultaneous Only, to be triggered by TIM1 CC4. I haven't figured out how to do this using the provided drivers, so I've disabled the ADC drivers and manually configured the ADC registers. This set up does not work at the moment, and while trying to figure out the problem, I've tried to force the injected conversion and interrupt as follows:
Code: Select all
...
ADC1->CR1 |= ADC_CR1_JEOCIE;
ADC2->CR2 |= ADC_CR1_JEOCIE;
nvicEnableVector(STM32_ADC_NUMBER, STM32_ADC_IRQ_PRIORITY); //STM32_ADC_NUMBER = 18
ADC1->CR2 |= ADC_CR2_JSWSTART;
...
With this, I get thrown into _unhandled_exception(). Looking at the fault registers, VCATCH in the Debug Fault Status Register is set, but no flags are set in the Debug Exception and Monitor Control Register. I then manually put in handlers for each vector to see what's leading to _unhandled_exception(). Each handler only executes the BKPT instruction.
Oddly, Vector1BC (in position 95) is where it breaks. The STM32F405xx vector table only shows up to position 81, that is Vector184. Additionally, if I comment out Vector1BC, it breaks at Vector1B8 (position 94) instead of going through the weak Vector1BC handler in vectors.c which would end up in _unhandled_exception(). Furthermore, commenting out the vector in position 94 causes it break at 93, and so on to some unknown extent.
I've run out of ideas on how to proceed at this point, and any suggestions will be greatly appreciated.
Extra information: The TIM1 CC4 should be generated using the Chibios PWM driver, but even though the callback for CC4 is called, the ADC injected conversion doesn't seem to be triggered.
The full ADC configuration sequence is as follows (I've left all the clearing operations just to be clear for now, and I'm not even sure this configuration is 100% correct):
Code: Select all
//Enable clocks for ADC1 and ADC2
rccEnableADC1(FALSE);
rccEnableADC2(FALSE);
//ADC1 (Master, ADC_CHANNEL_14 injected)
ADC1->CR1 &= ~(ADC_CR1_RES); //Resolution = ADC_RESOLUTION_12B
ADC1->CR1 &= ~(ADC_CR1_SCAN); //ScanConvMode = DISABLE
ADC1->CR1 &= ~(ADC_CR1_DISCEN); //DiscontinuousConvMode = DISABLE
ADC1->CR1 &= ~(ADC_CR1_JAUTO); //AutoInjectedConv = DISABLE
ADC1->CR1 &= ~(ADC_CR1_JDISCEN); //InjectedDiscontinuousConvMode = DISABLE
ADC1->CR1 |= ADC_CR1_JEOCIE;
ADC1->CR2 &= ~(ADC_CR2_CONT); //ContinuousConvMode = DISABLE
ADC1->CR2 &= ~(ADC_CR2_EXTEN); //ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE
ADC1->CR2 &= ~(ADC_CR2_EXTSEL);
ADC1->CR2 &= ~(ADC_CR2_ALIGN); //DataAlign = ADC_DATAALIGN_RIGHT
ADC1->CR2 &= ~(ADC_CR2_DDS); //DMAContinuousRequests = DISABLE
ADC1->CR2 |= ADC_CR2_EOCS; //EOCSelection = ADC_EOC_SINGLE_CONV
ADC1->CR2 &= ~(ADC_CR2_JEXTSEL); //ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_CC4
ADC1->CR2 &= ~(ADC_CR2_JEXTEN);
ADC1->CR2 |= ADC_CR2_JEXTEN_0; //ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONVEDGE_RISING
ADC1->CR2 |= ADC_CR2_ADON; //ExternalTrigConv = ADC_SOFTWARE_START
ADC1->SQR1 &= ~(ADC_SQR1_L); //NbrOfConversion = 1
static const uint32_t ADC_CHANNEL_IN14 = 14;
ADC1->SMPR1 &= ~(ADC_SMPR1_SMP10 << (3*(ADC_CHANNEL_IN14 - 10))); //InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES
ADC1->JSQR = ADC_CHANNEL_IN14 << 15; //InjectedNbrOfConversion = 1, InjectedChannel = ADC_CHANNEL_14
ADC1->JOFR1 &= ~(ADC_JOFR1_JOFFSET1); //InjectedOffset = 0
//ADC2 (Slave, ADC_CHANNEL_15 injected)
ADC2->CR1 &= ~(ADC_CR1_RES); //Resolution = ADC_RESOLUTION_12B
ADC2->CR1 &= ~(ADC_CR1_SCAN); //ScanConvMode = DISABLE
ADC2->CR1 &= ~(ADC_CR1_DISCEN); //DiscontinuousConvMode = DISABLE
ADC2->CR1 &= ~(ADC_CR1_JAUTO); //AutoInjectedConv = DISABLE
ADC2->CR1 &= ~(ADC_CR1_JDISCEN); //InjectedDiscontinuousConvMode = DISABLE
ADC2->CR1 |= ADC_CR1_JEOCIE;
ADC2->CR2 &= ~(ADC_CR2_EXTSEL);
ADC2->CR2 &= ~(ADC_CR2_ALIGN); //DataAlign = ADC_DATAALIGN_RIGHT
ADC2->CR2 &= ~(ADC_CR2_DDS); //DMAContinuousRequests = DISABLE
ADC2->CR2 |= ADC_CR2_EOCS; //EOCSelection = ADC_EOC_SINGLE_CONV
ADC2->CR2 |= ADC_CR2_ADON; //ExternalTrigConv = ADC_SOFTWARE_START
ADC2->SQR1 &= ~(ADC_SQR1_L); //NbrOfConversion = 1
static const uint32_t ADC_CHANNEL_IN15 = 15;
ADC2->SMPR1 &= ~(ADC_SMPR1_SMP10 << (3*(ADC_CHANNEL_IN15 - 10))); //InjectedSamplingTime = ADC_SAMPLETIME_3CYCLES
ADC2->JSQR = ADC_CHANNEL_IN15 << 15; //InjectedNbrOfConversion = 1, InjectedChannel = ADC_CHANNEL_15
ADC2->JOFR1 &= ~(ADC_JOFR1_JOFFSET1); //InjectedOffset = 0
//ADC Common (Dual ADC mode)
ADC->CCR &= ~(ADC_CCR_ADCPRE);
ADC->CCR |= ADC_CCR_ADCPRE_0; //ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4
ADC->CCR &= ~(ADC_CCR_MULTI);
ADC->CCR |= ((uint32_t)(ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0)); //Mode = ADC_DUALMODE_INJECSIMULT
ADC->CCR &= ~(ADC_CCR_DMA); //DMAAccessMode = ADC_DMAACCESSMODE_DISABLED
ADC->CCR &= ~(ADC_CCR_DELAY); //TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_5CYCLES
nvicEnableVector(STM32_ADC_NUMBER, STM32_ADC_IRQ_PRIORITY);
ADC1->CR2 |= ADC_CR2_SWSTART;
ADC2->CR2 |= ADC_CR2_SWSTART;
ADC1->CR2 |= ADC_CR2_JSWSTART; //Force conversion to see if it works