HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
I'm playing with a modified 'STM IRQ_Channels' example utilising some code from 'toggle_with_CircleOS' in a Circle app to toggle the LEDs.
First time I debugged, I think I saw a HardwareFaultException reported in the disassembly window, as I stepped through the last line of this code block:
Entire Code
/********************** (C) COPYRIGHT 2007-2009 RAISONANCE ********************
* File Name : Application.c
* Author :
* Date First Issued :
* Description : Circle_App CircleOS application template.
* Revision :
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "circle_api.h"
/* Private defines -----------------------------------------------------------*/
// The following should be the minimal CircleOS version needed by your application
#define NEEDEDVERSION "V 3.7"
/* Private function prototypes -----------------------------------------------*/
static enum MENU_code MsgVersion(void);
void RCC_Configuration(void);
void TIM_Configuration(void);
void TIM2_IRQHandler(void);
void TIM3_IRQHandler(void);
/* Public variables ----------------------------------------------------------*/
const char Application_Name[8+1] = {"LEDFlshr"}; // Max 8 characters
/* Private variables ---------------------------------------------------------*/
NVIC_InitTypeDef NVIC_InitStructure;
static int CurrentLedModeGreen = LED_OFF;
static int CurrentLedModeRed = LED_OFF;
/*******************************************************************************
* Function Name : Application_Ini
* Description : Initialization function of Circle_App. This function will
* be called only once by CircleOS.
* Input : None
* Return : MENU_CONTINUE_COMMAND
*******************************************************************************/
enum MENU_code Application_Ini(void)
{
// Ensure that the current OS version is recent enough
if(strcmp(UTIL_GetVersion(), NEEDEDVERSION) < 0)
{
return MsgVersion();
}
// TODO: Write your application initialization function here.
//LED_Set( LED_GREEN, LED_ON ); //Initial Testing
//LED_Set( LED_RED, LED_ON ); //Initial Testing
LCD_SetBackLightOff();
RCC_Configuration();
TIM_Configuration();
/*
#ifdef VECT_TAB_RAM
// Set the Vector Table base location at 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else // VECT_TAB_FLASH
// Set the Vector Table base location at 0x08000000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
*/
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the TIM2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the TIM3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //previously 1
NVIC_Init(&NVIC_InitStructure);
*/
return MENU_CONTINUE_COMMAND;
}
/*******************************************************************************
* Function Name : Application_Handler
* Description : Management of the Circle_App.
*
* Input : None
* Return : MENU_CONTINUE
*******************************************************************************/
enum MENU_code Application_Handler(void)
{
// TODO: Write your application handling here.
// This routine will get called repeatedly by CircleOS, until we return MENU_LEAVE
#if 1
// If the button is pressed, the application is exited
if(BUTTON_GetState() == BUTTON_PUSHED)
{
BUTTON_WaitForRelease();
return MENU_Quit();
}
#endif
return MENU_CONTINUE; // Returning MENU_LEAVE will quit to CircleOS
}
/*******************************************************************************
* Function Name : MsgVersion
* Description : Display the current CircleOS version and the version needed
* exit to main menu after 4 secondes
*
* Input : None
* Return : MENU_REFRESH
*******************************************************************************/
static enum MENU_code MsgVersion(void)
{
int hh,mm,ss,ss2;
DRAW_DisplayString(5,60,"CircleOS",17);
DRAW_DisplayString(80,60,UTIL_GetVersion(),6);
DRAW_DisplayString(5,34,NEEDEDVERSION,6);
DRAW_DisplayString(50,34," required",12);
RTC_GetTime( &hh, &mm, &ss);
ss = ss + 4; // 4 secondes
ss = ss%60;
do
{
RTC_GetTime( &hh, &mm, &ss2 );
}
while ( ss2 != ss ); // do while < 4 secondes
DRAW_Clear();
return MENU_REFRESH;
}
/*******************************************************************************
* @brief Configures the different system clocks
* @param None
* @retval None
*******************************************************************************/
void RCC_Configuration(void)
{
/* Setup the microcontroller system. Initialize the Embedded Flash Interface,
initialize the PLL and update the SystemFrequency variable. */
//SystemInit(); //Intended for STMicroelectronics EVAL Boards - function performed by CircleOS
/* Enable TIM2 and TIM3 clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3 , ENABLE);
}
/*******************************************************************************
* @brief Configures the used Timers.
* @param None
* @retval None
*******************************************************************************/
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* TIM2 configuration */
TIM_TimeBaseStructure.TIM_Period = 0x4AF;
TIM_TimeBaseStructure.TIM_Prescaler = 0xEA5F;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0000;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_Pulse = 0x0;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
/* TIM3 configuration */
TIM_TimeBaseStructure.TIM_Period = 0x95F; // 3 s = 0xE0F
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
/* Immediate load of TIM2 Precaler value */
TIM_PrescalerConfig(TIM2, 0xEA5F, TIM_PSCReloadMode_Immediate);
/* Immediate load of TIM3 Precaler value */
TIM_PrescalerConfig(TIM3, 0xEA5F, TIM_PSCReloadMode_Immediate);
/* Clear TIM2 update pending flag */
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
/* Clear TIM3 update pending flag */
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
/* Enable TIM2 Update interrupt */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* Enable TIM3 Update interrupt */
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
}
/******************************************************************************/
/* STM32F10x Peripherals Interrupt Handlers */
/******************************************************************************/
/**
* @brief This function handles TIM2 global interrupt request.
* @param None
* @retval None
*/
void TIM2_IRQHandler(void)
{
/* Clear TIM2 update interrupt */
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
/* Toggle LED1 */
CurrentLedModeGreen = (CurrentLedModeGreen == LED_ON) ? LED_OFF : LED_ON;
LED_Set ( LED_RED,CurrentLedModeGreen);
}
/**
* @brief This function handles TIM3 global interrupt request.
* @param None
* @retval None
*/
void TIM3_IRQHandler(void)
{
/* Clear TIM3 update interrupt */
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
/* Toggle LED2 */
CurrentLedModeRed = (CurrentLedModeRed == LED_ON) ? LED_OFF : LED_ON;
LED_Set ( LED_RED,CurrentLedModeRed);
}
Each subsequent time I debug, and at the same place, I no longer get a hardware fault exception, but the debug environment freezes - at a symbol called 'dummy handler' in the disassembly window.
Any suggestions appreciated - I'm a noobie - and going completely up a paddle without a creek!
Last edited by hairykiwi (2009-07-16 10:32:48)
Offline
#
2
2009-07-16 07:43:06HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
Re: HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
You should not: 1. Change the vector table. CircleOS already manages the vector table in RAM. If you want to add an interrupt entry, use the API. 2. CircleOS uses the Timer2 irq too. You should at least call the default handler.
Offline
#
3
2009-07-16 10:51:17HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
Re: HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
Thanks for the quick reply Francis.
And many thanks for your advice; it's a steep learning curve getting to know a device && an API && C concurrently!
Re Timer 2 IRQ, it's used for the MEMS GPIO isn't it? So if my app doesn't need the MEMS, would it be considered bad practise to reassign/appropriate its timer for my own app? And is this because I'd need to reassign TIM2 back to the MEMS on exiting my app? I know there are plenty of timers without my app using TIM2, but I ask the question anyway for better understanding.
Offline
#
4
2009-07-16 12:50:40HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
Re: HardwareFaultException thrown after "NVIC_Init(&NVIC_InitStructure);"
In the API, there are 2 functions: UTIL_SetIrqHandler and UTIL_GetIrqHandler that allow to modify/restore the original irq handler. In version 3.7, the Timer2 is used for both the MEMS (SPI) and the audio configuration (I2C for volume, ...). If you don't need any of these feature, just redirect the irq to your own handler, (but restore the original handler when exiting your application).