cancel
Showing results for 
Search instead for 
Did you mean: 

TIM2 is not generating any interrupts on STM32f051

evert2
Associate II
Posted on December 04, 2012 at 15:56

Dear all,

I've an issue with TIM2 on the STM32f051

I did a port from STM32f103, however the interrupt is not activated anymore.

A big difference is that I use a f0discovery board, so I make use of an internal RC occilator.

I did some changes to use the HSI for clocking the PLL at the correct frequency

Since TIM14 is working, it looks like initialising the clock is working fine.

This is how the clock is initialized:

static void Clk_Init(void)

{

RCC_HSICmd(ENABLE);

while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);

/* Init PLL (8MHZ/2)*12 = 48MHZ */

RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12);

RCC_PLLCmd(ENABLE);

while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

FLASH_PrefetchBufferCmd(ENABLE);

FLASH_SetLatency(FLASH_Latency_1);

/* TIM2,3,14 at 48MHz */

RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2 |

RCC_APB1Periph_TIM3 |

RCC_APB1Periph_TIM14 | RCC_APB1Periph_USART2, ENABLE);

}

This is how the initalisation of the timer is done

void init_timer(void)

{

/* Peripherals InitStructure define */

static TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

static NVIC_InitTypeDef NVIC_InitStructure;

TIM_TimeBaseStructure.TIM_Period = 48;

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* set up Timer 2 */

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure); /* Prescaler configuration */

TIM_PrescalerConfig(TIM2, (NR_MSEC_FOR_MAIN * MSEC), TIM_PSCReloadMode_Immediate);

TIM_InternalClockConfig(TIM2);

TIM_Cmd(TIM2, ENABLE); /* switch timer on */

}

After this initialisation, the micro never enters the TIM2_IRQHandler()

Does someone has any idea? did I forgot any initalisation?

TIM14 is working fine, however it does not make use of an IRQHandler().

Regards,

Evert Huijben

#irq-tim2-discoveryf0
23 REPLIES 23
frankmeyer9
Associate II
Posted on December 06, 2012 at 11:57

I have used the IAP example of ...

 

IAP is tricky, I haven't yet done much with it.

The USART and TIM interrupt handlers are defined by default, so I expect that this should be no problem.

 

I think my idea from yesterday doesn't match your problem. The TIM2 interrupt share the same name. I had been porting an application from a F10x to a F05x, while stumbling over this issue. The ADC interrupts have different names, and the F0 ADC shares his interrupt with the comparator.

But there is another thing you can check. As the F0x-variants have different peripherals, I'm not sure if all use the same vector map. I'm using Crossworks (also GCC--based), which includes a ''stm32fxxx.vec'' file in the startup code (for F10x). That include relies on having the proper variant definition in the project properties. I have not yet checked this for F0 devices.

But I would check for proper placement of the TIM2 interrupt routine both in the map file and finally on the device, using the debugger.

However, I used the template /Source/Template/TrueSTUDIO/startup_stm32f0xx.s.

 

Is this the correct file for usage with a GNU compiler? or should the ARM or GCC_ride version be used?

 

This should be ok.

The Atollic and RIDE startups are very similar, and the vector table section is identical.

Both toolchains are based on GCC, and use the same assembler syntax. Keil does not.

And, by the way, the Cortex M0 does not have a vector table offset register, it's vtable is fixed.

evert2
Associate II
Posted on December 06, 2012 at 14:37

Hi

IAP is tricky, I haven't yet done much with it.

 

 

Indeed, it seems that my problem has something to do with the IAP, because in my bootloader interrups are working fine. From the moment I jump to my application they are not working anymore.

But I would check for proper placement of the TIM2 interrupt routine both in the map file and finally on the device, using the debugger.

 

 

I've checked the map file of my application and the map file of my bootloader.

I see some remarkable things but I don't have that much knowledge about map files.

In the map file of the bootloader I see next entries with the TIM2_IRQHandler

.text.TIM2_IRQHandler

0x08004bd8 0x50 /tmp/ccSj94Ve.o

0x08004bd8 TIM2_IRQHandler

in the map file of the application I only see next entries when searching for the irq handler of TIM2:

.dataf 0x20000d34 0x7c /tmp/ccmPzkVI.o

0x20000d34 TIM2_IRQHandler

0x20000d84 start_event_timer

Maybe there is a relation with the definition of the IRQ handler:

What does FASTCALL mean in the prefix of this function?

By the way, omitting FASTCALL doen't resolve the problem.

void FASTCALL TIM2_IRQHandler(void)

{

......

}

I found that debugging is very difficult on this device, especially with interrupts,

Some more idea's, tips or tricks?

Regards,

Evert Huijben

frankmeyer9
Associate II
Posted on December 06, 2012 at 15:51

Maybe there is a relation with the definition of the IRQ handler:

 

What does FASTCALL mean in the prefix of this function?

 

By the way, omitting FASTCALL doen't resolve the problem.

 

IMHO ''FASTCALL'' does not make sense at all here.

It is basically for interfacing ASM routines. It's effect is to put some function argument into registers, and not on the stack. First, the ARM ABI does that anyway, and second (and more important), an interrupt handler has no arguments. So no wonder the effect is nil...

But to understand your application:

You have a bootloader, which uses UART and TIM2, and this part is working.

This bootloader downloads your application, and stores it into FLASH.

Is this also assumed to replace the interrupt handler in question ?

Not sure how that would work without relocatable vector table.

Is it possible that a TIM2 interrupt is then diverted to your old, ''bootloader''- TIM2 handler routine ?

Posted on December 06, 2012 at 15:54

Examine how AN4065 handles the relocation of the vector table into RAM

STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\binary_template\src

...
 /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define APPLICATION_ADDRESS (uint32_t)0x08003000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint32_t TimingDelay;
#if (defined ( __CC_ARM ))
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#elif (defined (__ICCARM__))
#pragma location = 0x20000000
__no_init __IO uint32_t VectorTable[48];
#elif defined ( __GNUC__ )
__IO uint32_t VectorTable[48] __attribute__((section(''.RAMVectorTable'')));
#elif defined ( __TASKING__ )
__IO uint32_t VectorTable[48] __at(0x20000000);
#endif
/* Private function prototypes -----------------------------------------------*/
void Delay(__IO uint32_t nTime);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
uint32_t i = 0;
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f0xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f0xx.c file
*/
/* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/
/* Copy the vector table from the Flash (mapped at the base of the application
load address 0x08003000) to the base address of the SRAM at 0x20000000. */
for(i = 0; i < 48; i++)
{
VectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i<<2));
}
/* Enable the SYSCFG peripheral clock*/
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Remap SRAM at 0x00000000 */
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);
...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
evert2
Associate II
Posted on December 06, 2012 at 16:21

Hi,

You have a bootloader, which uses UART and TIM2, and this part is working.

 

That's correct

This bootloader downloads your application, and stores it into FLASH.

 

Is this also assumed to replace the interrupt handler in question ?

 

Indeed, Those interrupts should be independant from each other.

Is it possible that a TIM2 interrupt is then diverted to your old, ''bootloader''- TIM2 handler routine ?

Since my application is started from a new adress in flash, including 'another' vector table, I don't expect that 'old' code is loaded.

What can be  an issue is that still some reset's needs to be done before jumping to my application. I already disable all interrupts before jumping to the new application location.

Evert Huijben

evert2
Associate II
Posted on December 06, 2012 at 16:25

Hi Clive,

This is exactly how I've implemented my application, I've put my own functions after this code.

Do you think some more reset's needs to be done in my bootloader before I jump to the application? Right now I disable all interrupts before jumping.

Regards,

Evert Huijben

Posted on December 06, 2012 at 17:23

No, I really don't think any additional initialization/resetting is required, you will need to enable interrupts if you have disabled them,but I'm not wholly convinced that's required if you deinitialize things properly before leaving the boot loader.

You need to verify the placement of VectorTable[] in your .MAP file. If that's broken none of the interrupt stuff is going to work.

You could look at the Atollic Linker Script

STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\binary_template\TrueSTUDIO\STM320518_EVAL\stm32_flash.ld

Although I personally would use something different in GNU/GCC via Yagarto.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
evert2
Associate II
Posted on December 07, 2012 at 10:44

Hi Clive,

I use the linker file you mentioned in your post (the atollic version) is the one I use in my application. It has some changesto put the vector table in RAM.

My changes are only related to the memory locations:

MEMORY

{

/* Right now first 24K is occupied by the bootloader */

FLASH (rx) : ORIGIN = 0x08008000, LENGTH = 64K - 0x8000

VTRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xc0 /* First part of RAM is reserved to the vector table */

RAM (xrw) : ORIGIN = 0x200000c0, LENGTH = 8K - 0xc0

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

}

When I look in the MAP file, I see the vector table (isr_vector) is placed at 0x20000000. This seems correct. I also see next:

.RAMVectorTable

0x20000000 0xc0

*(.RAMVectorTable)

.RAMVectorTable

0x20000000 0xc0 /tmp/ccML7ryR.o

0x20000000 VectorTable

It alo looks fine.

I've added my MAP file as an attachment, maybe you can take a look into it. Also the IRQ's are mentioned in this file,

Regards,

Evert Huijben

________________

Attachments :

gdr216-app.map : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I0da&d=%2Fa%2F0X0000000bbk%2FeVeU8q1J4ZRkxDTH0_6n7uvd3RUE9g4Cax.rurNmy4U&asPdf=false
evert2
Associate II
Posted on December 10, 2012 at 16:35

Dear all,

This issue is resolved,

Since I disabled my interrupts before jumping to my application by using __disable_irq(), you have to enable them with __enable_irq(). This needs to be done before you enable your individual interrupts again.

I got some troubles because I immidiatly got pending interrupts, but I resolved them by catching them in the bootloader before the disable.

This is what I did before the jump to the application:

while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) /* is also dummy read to reset all error flags */

       {

          USART_ReceiveData(USART1); /* read buffer */

       }

       USART_ReceiveData(USART1); /* read buffer */

       NVIC_ClearPendingIRQ(USART_IT_1);

       USART_DeInit(USART_NR);

       Jump_To_Application();

Thanks everybody for the support!

Evert Huijben

hkamba
Associate II
Posted on January 29, 2014 at 20:48

Dear All,

I need your help. My MCU is STM32F030C8.

I wrote a bootloader firmware and an application for this system.

The bootloader is supposed to start at 0x0800 0000 and is 0x3000 in size.

The application is supposed to start at 0x0800 3000 and is 0xC800 in size. (I keep the last two pages for device information).

My problem is that I cannot successfully jump to the app...

In my app I ensured to have done the following:

/* Private macro -------------------------------------------------------------*/

#if   (defined ( __CC_ARM ))

  __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));

#elif (defined (__ICCARM__))

#pragma location = 0x20000000

  __no_init __IO uint32_t VectorTable[48];

#elif defined   (  __GNUC__  )

  __IO uint32_t VectorTable[48] __attribute__((section(''.RAMVectorTable'')));

#elif defined ( __TASKING__ )

  __IO uint32_t VectorTable[48] __at(0x20000000);

#endif

/************************************************************//**

* \brief Main application entry point

* At this stage the microcontroller clock setting is already configured, 

* this is done through SystemInit() function which is called from startup

* file (startup_stm32f030x8.s) before to branch to application main.

* To reconfigure the default setting of SystemInit() function, refer to

* startup_stm32f030x8.c file

*  

*****************************************************************/

int main( void )

{

uint32_t i = 0;

/* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  

  /* Copy the vector table from the Flash (mapped at the base of the application

     load address 0x08003000) to the base address of the SRAM at 0x20000000. */

  for(i = 0; i < 48; i++)

  {

    VectorTable[i] = *(__IO uint32_t*)(IAP_APP_ADDRESS + (i<<2));

  }

RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;   /* Enable the SYSCFG peripheral clock*/

SYSCFG->CFGR1 = SYSCFG_CFGR1_MEM_MODE; /* Remap SRAM at 0x00000000 */

/***************** Application code starts here   ***************************/

}

I am developing on Keil uVision 5 and used the following scatter loading file for bootloader and application.

LR_IROM1 0x08000000 0x00003000  {    ; load region size_region

  ER_IROM1 0x08000000 0x00003000  {  ; load address = execution address

   *.o (RESET, +First)

   *(InRoot$$Sections)

   .ANY (+RO)

  }

  RW_IRAM1 0x2000000

0 0x0000

200

0  {  ; RW data

   .ANY (+RW +ZI)

  }

}

LR_IROM1 0x08003000 0x0000C800  {    ; load region size_region

  ER_IROM1 0x08003000 0x0000C800  {  ; load address = execution address

   *.o (RESET, +First)

   *(InRoot$$Sections)

   .ANY (+RO)

  }

  RW_IRAM1 0x200000C0 0x00001FD0  {  ; RW data

   .ANY (+RW +ZI)

  } 

}

The section of code to jump to the app is as follows :

void INTFLASH_execute_main_app(const char mode)

{

  MyFunc_ptr AppEntry;

         

__disable_irq();

  

  AppEntry = (MyFunc_ptr) INTFLASH_calculate_page_addr(IAP_APP_START_PAGE);

  

  if( mode || intflash_check_main_app() )

  {

    Main_App_ptr = (uint8_t*)AppEntry;

    if( (*Main_App_ptr != 0xFF) &&  (Main_App_ptr) )

    { 

AppEntry();

    }

  }           

  __enable_irq();

}

When the code reaches AppEntry(); It causes an Hardwarde Fault exception and ends up here:

HardFault_Handler\

                PROC

                EXPORT  HardFault_Handler              [WEAK]

                B       HardFault_Handler_C

                ENDP

As you can see I directed the exception to HardFault_Handler_C ISR inside system_stm32f0xx.c which is defined as follows:

void HardFault_Handler_C(unsigned int* hardfault_args)

{

unsigned int buffer[14];

    buffer[0] = hardfault_args[0];         //R0

    buffer[1] = hardfault_args[1];         //R1

    buffer[2] = hardfault_args[2];         //R2

    buffer[3] = hardfault_args[3];         //R3

    buffer[4] = hardfault_args[4];         //R12

    buffer[5] = hardfault_args[5];         //LR

    buffer[6] = hardfault_args[6];         //PC

    buffer[7] = hardfault_args[7];         //PSR

    buffer[8] = *(unsigned int*)0xE000ED38; //BFAR

    buffer[9] = *(unsigned int*)0xE000ED28; //CFSR

    buffer[10] = *(unsigned int*)0xE000ED2C; //HFSR

    buffer[11] = *(unsigned int*)0xE000ED30; //DFSR

    buffer[12] = *(unsigned int*)0xE000ED3C; //AFSR

    buffer[13] = SCB->SHCSR;                //SHCSR

    

while (1);

}

The content of buffer is {0x20000c00, 0x080059e5, 0x080059ed, 0x080059ef, 0, 0, 0, 0,0 ,0....}

Looking at the map of the main app. I saw that the addresses above match:

__initial_sp                             0x20000c00   Data           0  startup_stm32f030x8.o(STACK)

Reset_Handler                       0x080059e5   Thumb Code     8  startup_stm32f030x8.o(.text)

NMI_Handler                        0x080059ed   Thumb Code     2  startup_stm32f030x8.o(.text)

HardFault_Handler                 0x080059ef   Thumb Code     2  startup_stm32f030x8.o(.text)

Can you please help me understand what is going on? I cannot successfully jump to the app...