Timer Interrupt Unhandled Exception

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
acsmith
Posts: 2
Joined: Wed Jan 28, 2015 11:43 pm

Timer Interrupt Unhandled Exception

Post by acsmith »

Hi guys,

I'm having a really strange issue with a Timer interrupt handler on a STM32F303 Discovery board. I've taken the stock demo app and added in some basic code to turn on TIM4, count up and when it reaches an overflow generates an interrupt.

Code: Select all

/*
    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "ch.h"
#include "hal.h"
#include "test.h"
#include "console.h"

/*
 * Blinker thread #1.
 */
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {

  (void)arg;

  chRegSetThreadName("blinker");
  while (true) {
    palSetPad(GPIOE, GPIOE_LED3_RED);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED3_RED);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED7_GREEN);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED7_GREEN);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED10_RED);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED10_RED);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED6_GREEN);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED6_GREEN);
    chThdSleepMilliseconds(125);
  }
}

/*
 * Blinker thread #2.
 */
static THD_WORKING_AREA(waThread2, 128);
static THD_FUNCTION(Thread2, arg) {

  (void)arg;

  chRegSetThreadName("blinker");
  while (true) {
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED5_ORANGE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED5_ORANGE);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED9_BLUE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED9_BLUE);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED8_ORANGE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED8_ORANGE);
    chThdSleepMilliseconds(125);
    palSetPad(GPIOE, GPIOE_LED4_BLUE);
    chThdSleepMilliseconds(125);
    palClearPad(GPIOE, GPIOE_LED4_BLUE);
  }
}


CH_IRQ_HANDLER(TIM4_IRQHandler)
{
   CH_IRQ_PROLOGUE();
 
   /* IRQ handling code, preemptable if the architecture supports it.*/
 
   //chSysLockFromIsr();
   /* Invocation of some I-Class system APIs, never preemptable.*/
   //chSysUnlockFromIsr();
 
   /* More IRQ handling code, again preemptable.*/
 
  CH_IRQ_EPILOGUE();
}


/*
 * Application entry point.
 */
int main(void) {

  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 1 using the driver default configuration.
   * PA9(TX) and PA10(RX) are routed to USART1.
   */
  sdStart(&SD1, NULL);
  palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(7));
  palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(7));

  /*
   * Creates the example threads.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+1, Thread1, NULL);
  chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO+1, Thread2, NULL);

chSysDisable();
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
chSysEnable();

// Find the optimal prescaler value
uint32_t prescaler = 1099; //(uint32_t)(TIMEVT_INPUT_CLOCK / ((float)MAX_FREQUENCY)); // Initial value

TIM4->CR1 = 0;
TIM4->CR1 |= TIM_CR1_URS;

nvicEnableVector(TIM4_IRQn, 10);

TIM4->ARR = 0xFFFF;
TIM4->PSC = 5000;// arbitrary number, just so LEDs go for a few seconds
TIM4->SR = 0;
TIM4->EGR = TIM_EGR_UG;
TIM4->DIER |= TIM_DIER_UIE;
TIM4->CR1 |= TIM_CR1_CEN;

  /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop and check the button state, when the button is
   * pressed the test procedure is launched.
   */
  while (TRUE) {
    if (palReadPad(GPIOA, GPIOA_BUTTON))
      TestThread(&SD1);
    chThdSleepMilliseconds(500);
  }
}


Problem is, as soon as it hits the interrupt it gets an unhandled exception and sits in the infinite loop in vectors.c

Code: Select all

(gdb) bt
#0  _unhandled_exception () at ../../../os/common/ports/ARMCMx/compilers/GCC/vectors.c:76
#1  <signal handler called>
#2  0x55555554 in ?? ()
#3  0x55555554 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)


Anybody see any obvious reason why this could be happening? Timer counts up properly and things are fine if I remove the TIM_DIER_UIE bit.

Thanks for the help.

Andrew
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Timer Interrupt Unhandled Exception

Post by Giovanni »

Hi,

Your problem is here:

CH_IRQ_HANDLER(TIM4_IRQHandler)

You need to write:

CH_IRQ_HANDLER(vectorXX)

Where XX is the hexadecimal offset in the vectors table, in your case it should be:

CH_IRQ_HANDLER(vectorB8)

For details see the table 30 in the STM32F3xx RM and the file vectors.c in ChibiOS.

Giovanni
acsmith
Posts: 2
Joined: Wed Jan 28, 2015 11:43 pm

Re: Timer Interrupt Unhandled Exception

Post by acsmith »

Thanks Giovanni, that did it.

Question related to that, I've used this code on a STM32F105 and it appears to function properly. I think that's because the STM32F1xx has the #define for TIM4_IRQHandler mapped to VectorB8. Any reason this wasn't done for the STM32F3xx? Also, since it's not remapped for the STM32F3xx, why didn't it come up during compiling as "reference to unknown ..."? I don't need these answered, just thought I'd bring it up.

One last item related to this. The example code I posted works with your fix. However, my actual code is a bit more complex and it still seems to be hitting an unhandled exception even with your fix. Obviously it's due to an error somewhere else in my code that I'll have to sniff out. Is there anyway to get more information from the "unhandled exception" section of code in vector.c to try and determine the culprit ... apart from "stepi" along until it falls into the handler? The stack trace doesn't seem to help much. Debugging tips to catch there errors?

Thanks again for your help Giovanni.

Andrew
User avatar
Giovanni
Site Admin
Posts: 14893
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 997 times

Re: Timer Interrupt Unhandled Exception

Post by Giovanni »

Hi,

We don't use anymore "readable names" for vectors, the vectors table is the same for all devices. We stopped creating those named vectors in the new STM32 platforms. In ChibiOS 3.0 all names have been removed.

Vector names are "weak" symbols and they jump by default in _unhandled_exception. When you declare somewhere a function with name vectorXX, your symbol "wins" and replaces the original vector. If you declare an ISR with a wrong name it just declares a function not called by anything so you get no error.

About the _unhandled_exception, after stopping there you should examine the NVIC registers that will give you any information about the nature of the exception. See the Cortex-M manual for details about the NVIC registers. Usually it happens when:
- One of the system exceptions is triggered.
- An IRQ is triggered with no associated ISR (what happened to you).
You could also replace _unhandled_exception by making all unused vectors point to your code.

Giovanni
genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Has thanked: 1 time
Been thanked: 1 time

Re: Timer Interrupt Unhandled Exception

Post by genosensor »

I ran into difficulty exactly because of the weak binding behavior described.
As a debugging aid, I've revised vectors.c so that it creates unique, weakly bound unhandled exception handlers for each vector -- only when compiling without any optimization (i.e. when debugging)

An example for ChiBios 2.6 on the STM32L1xx is here:
https://raw.githubusercontent.com/brent ... /vectors.c

I would expect this code could be easily ported to 3.0.

Now, when you break after the system freezes due to an unhandled exception, the debugger shows you which exception vector was unhandled.

Note that this version also utilizes macro expansion to reduce repetition in the code.
It also disables all interrupts when any unhandled exception occurs. This it important to ensure that the system doesn't stray further "into the weeds".
Post Reply