Simple timer ISR for STM32F103 (StdPeriphLib / CMSIS)

I’m trying to get a simple timer ISR to fire with one of the STM cortex micros. It’s a pared-down version of one of the examples, and I can’t make it go:

The code below is what I beilieve I need to set up the timer and the ISR. The code builds ok, the timer appears to function (I can see the counter clocking away in my IDE) But the ISR is never taken. Any thoughts?

(The USB stuff is there because this is the USB example that I’m trying to get working, but I suspected that interrupts aren’t setup right, so I decided to do a simple timer just as a sanity check)

I’m using gcc/gdb.

#include "stm32f10x.h"
#include "usb_lib.h"
#include "hw_config.h"
#include "usb_pwr.h"

__IO uint16_t CCR1_Val = 49152;
__IO uint16_t CCR2_Val = 32768;
__IO uint16_t CCR3_Val = 16384;
__IO uint16_t CCR4_Val = 8192;

void nvic_init(void);
void timer_init(void);
void gpio_init(void);

int global_counter;

int main(void)
{
  global_counter = 0;
  Set_System();
  
  //USB_Interrupts_Config();
  //Set_USBClock();
  //USB_Init();

  nvic_init();
  gpio_init();

  timer_init();
  /* TIM2 enable counter */
  TIM_Cmd(TIM3, ENABLE);
  __enable_irq();

  while (1)
  {
/*
    if (bDeviceState == CONFIGURED)
    {
      if (JoyState() != 0)      
      {
        Joystick_Send(JoyState());
      }
    }
*/    
  }
}
void TIM3_IRQHandler(void) {
    int i;
    for(i=0; i<10; i++) {
        global_counter += 1;
    }
}

void timer_init(void) {
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    /* Prescaler configuration */
    TIM_PrescalerConfig(TIM3, 4, TIM_PSCReloadMode_Immediate);

    /* Output Compare Timing Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC1Init(TIM3, &TIM_OCInitStructure);

    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);

    /* TIM IT enable */
    TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);

}


void nvic_init(void) {

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 gloabal Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

void gpio_init(void) {
  /*RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                         RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
                         RCC_APB2Periph_GPIOE, ENABLE);
*/
GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, DISABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  //GPIO_Init(GPIOA, &GPIO_InitStructure);
  //GPIO_Init(GPIOC, &GPIO_InitStructure);
  //GPIO_Init(GPIOD, &GPIO_InitStructure);
  //GPIO_Init(GPIOE, &GPIO_InitStructure);
}

I’m trying to get up to speed on the STM32 myself. I’ve not started using the ST library calls yet so I may have missed something, but it looks like the interrupt should be enabled. [edit: what I meant to say here was that I could not see a problem with the code.]

Did you verify that the TIMER3 entry in your vector table points to your TIM3_IRQHandler() routine? I think that should be in the vicinity of 0x080000b4. (Although I’d think the uC would hang in the default handler if this were not right.)

It’s my understanding that

TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);

should enable that interrupt.

I’ve checked the vector table in the .lss file generated by the build process, and in the micro using the IDE, and it appears that it points correctly to the handler. The program isn’t jumping off and hanging in the default handler, for sure.

Now I think maybe your interrupt routine needs to clear the interrupt bit in the timer status register.

Which bit specifically needs to be cleared? My timer status register is 0x1f, which is all the CC interrupt flags set, as well as the update flag set. Do these need to be cleared at the end of an ISR? Or do I ahve to do something with the NVIC?

I’ve retooled the code to clear all the flags in the status register, both when I initialize the timer, (though I think that should happen when I initialize the peripheral anyways) and when the ISR gets called. The flag is obviously cleared when I clear it at startup. (I can check its value with the IDE), but the ISR is never called, even though after running for sometime after the timer is configured, the flag gets set. (In fact, ALL the CC flags in the SR get set, plus the Update Interrupt Flag)

I am boggled. I appreciate the thoughtful suggestions! :shock:

I am stumped also then. If that were the only problem, you’d expect clearing the register to zero to fix it.

I’ll try to get my include directories and whatnot set up to compile your example. (Sounds trivial but I’m very much in baby-step mode at this point.)

I’ll try to paste in a short timer interrupt example that works. It looks nothing like your code, but there is an outside chance that looking at it will give you an idea.

#include "stm32f10x.h"

__IO uint16_t count;

int main(void){
   RCC->APB2ENR = RCC_APB2ENR_IOPAEN;
   RCC->APB1ENR = RCC_APB1ENR_TIM6EN;
   GPIOA->CRL = 0x22222222;    /* PA0-7 2MHz out      */
   NVIC_EnableIRQ(TIM6_IRQn);
   TIM6->PSC = 1 << 12;        /* 4 MHz -> 1 KHz      */
   TIM6->ARR = 1 << 8;         /* 4 Hz               */
   TIM6->DIER = TIM_DIER_UIE;  /* interrupt on update */
   TIM6->CR1 = TIM_CR1_CEN;    /* enable */
   while (1) {
      GPIOA->ODR = count;
   }
   /* return 0; */
}

void TIM6_IRQHandler(void){
   TIM6->SR = 0;
   count++;
}

Here’s an observation I just made.

I went to look at the vector table to confirm that my ISR got correctly put in there, so I set a simple watch in GDB for the address in the vector table where my ISR is supposed to be: 0x000000b4 (the TIM3 global interrupt entry)

The address listed there is as follows: 0x8000875

However, below is an excerpt from my .lss file:

08000874 <TIM3_IRQHandler>:
}
void TIM3_IRQHandler(void) {
 8000874:	b580      	push	{r7, lr}
 8000876:	b081      	sub	sp, #4
 8000878:	af00      	add	r7, sp, #0
    int i;
    for(i=0; i<10; i++) {
 800087a:	f04f 0300 	mov.w	r3, #0
 800087e:	603b      	str	r3, [r7, #0]
 8000880:	e00f      	b.n	80008a2 <TIM3_IRQHandler+0x2e>
        global_counter += 1;
 8000882:	f240 13b4 	movw	r3, #436	; 0x1b4
 8000886:	f2c2 0300 	movt	r3, #8192	; 0x2000

Is this possibly what’s mucking things up? Am I giving it something that’s not word aligned and it’s barfing? What would even cause this address to be incorrect (if it is incorrect?) I’m using the ST startup code for the high density line.

That part looks good to me. The lsb has to be set in any address vector that points to thumb code. (Instructions are always word - aligned.)

Did not know that about the LSB. Good to know, given that the cortex m3 is thumb-2 only!

So I copied your code (with the tim6 isr) into my project, and built/ran it. It doesn’t work either. ISR is never taken! The timer seems to work, and the flag in the status register seems to get set, but no dice!

Could I have a look at your startup code? Maybe there’s something wrong there on my end?

Observation: Whenever my part comes out of reset, it triggers a hardfault exception (I don’t know how soon out of reset, it happens immediately) If I place the PC at the first instruction in the startup code, it runs fine from there. The problem only happens after hardware reset. My startup code is below, for reference.

/**
 ******************************************************************************
 * @file      startup_stm32f10x_hd.s
 * @author    MCD Application Team
 * @version   V3.3.0
 * @date      04/16/2010
 * @brief     STM32F10x High Density Devices vector table for RIDE7 toolchain. 
 *            This module performs:
 *                - Set the initial SP
 *                - Set the initial PC == Reset_Handler,
 *                - Set the vector table entries with the exceptions ISR address
 *                - Configure the clock system and the external SRAM mounted on 
 *                  STM3210E-EVAL board to be used as data memory (optional, 
 *                  to be enabled by user)
 *                - Branches to main in the C library (which eventually
 *                  calls main()).
 *            After Reset the Cortex-M3 processor is in Thread mode,
 *            priority is Privileged, and the Stack is set to Main.
 *******************************************************************************
 * @copy
 *
 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
 *
 * <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>
 */
    
  .syntax unified
  .cpu cortex-m3
  .fpu softvfp
  .thumb

.global  g_pfnVectors
.global  Default_Handler

/* start address for the initialization values of the .data section. 
defined in linker script */
.word  _sidata
/* start address for the .data section. defined in linker script */  
.word  _sdata
/* end address for the .data section. defined in linker script */
.word  _edata
/* start address for the .bss section. defined in linker script */
.word  _sbss
/* end address for the .bss section. defined in linker script */
.word  _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */

.equ  BootRAM,        0xF1E0F85F
/**
 * @brief  This is the code that gets called when the processor first
 *          starts execution following a reset event. Only the absolutely
 *          necessary set is performed, after which the application
 *          supplied main() routine is called. 
 * @param  None
 * @retval : None
*/

    .section  .text.Reset_Handler
  .weak  Reset_Handler
  .type  Reset_Handler, %function
Reset_Handler:  

/* Copy the data segment initializers from flash to SRAM */  
  movs  r1, #0
  b  LoopCopyDataInit

CopyDataInit:
  ldr  r3, =_sidata
  ldr  r3, [r3, r1]
  str  r3, [r0, r1]
  adds  r1, r1, #4
    
LoopCopyDataInit:
  ldr  r0, =_sdata
  ldr  r3, =_edata
  adds  r2, r0, r1
  cmp  r2, r3
  bcc  CopyDataInit
  ldr  r2, =_sbss
  b  LoopFillZerobss
/* Zero fill the bss segment. */  
FillZerobss:
  movs  r3, #0
  str  r3, [r2], #4
    
LoopFillZerobss:
  ldr  r3, = _ebss
  cmp  r2, r3
  bcc  FillZerobss
/* Call the clock system intitialization function.*/
  bl  SystemInit   
/* Call the application's entry point.*/
  bl  main
  bx  lr    
.size  Reset_Handler, .-Reset_Handler

/**
 * @brief  This is the code that gets called when the processor receives an 
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 * @param  None     
 * @retval None       
*/
    .section  .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b  Infinite_Loop
  .size  Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
* 
*******************************************************************************/
   .section  .isr_vector,"a",%progbits
  .type  g_pfnVectors, %object
  .size  g_pfnVectors, .-g_pfnVectors
    
    
g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  HardFault_Handler
  .word  MemManage_Handler
  .word  BusFault_Handler
  .word  UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  SVC_Handler
  .word  DebugMon_Handler
  .word  0
  .word  PendSV_Handler
  .word  SysTick_Handler
  .word  WWDG_IRQHandler
  .word  PVD_IRQHandler
  .word  TAMPER_IRQHandler
  .word  RTC_IRQHandler
  .word  FLASH_IRQHandler
  .word  RCC_IRQHandler
  .word  EXTI0_IRQHandler
  .word  EXTI1_IRQHandler
  .word  EXTI2_IRQHandler
  .word  EXTI3_IRQHandler
  .word  EXTI4_IRQHandler
  .word  DMA1_Channel1_IRQHandler
  .word  DMA1_Channel2_IRQHandler
  .word  DMA1_Channel3_IRQHandler
  .word  DMA1_Channel4_IRQHandler
  .word  DMA1_Channel5_IRQHandler
  .word  DMA1_Channel6_IRQHandler
  .word  DMA1_Channel7_IRQHandler
  .word  ADC1_2_IRQHandler
  .word  USB_HP_CAN1_TX_IRQHandler
  .word  USB_LP_CAN1_RX0_IRQHandler
  .word  CAN1_RX1_IRQHandler
  .word  CAN1_SCE_IRQHandler
  .word  EXTI9_5_IRQHandler
  .word  TIM1_BRK_IRQHandler
  .word  TIM1_UP_IRQHandler
  .word  TIM1_TRG_COM_IRQHandler
  .word  TIM1_CC_IRQHandler
  .word  TIM2_IRQHandler
  .word  TIM3_IRQHandler
  .word  TIM4_IRQHandler
  .word  I2C1_EV_IRQHandler
  .word  I2C1_ER_IRQHandler
  .word  I2C2_EV_IRQHandler
  .word  I2C2_ER_IRQHandler
  .word  SPI1_IRQHandler
  .word  SPI2_IRQHandler
  .word  USART1_IRQHandler
  .word  USART2_IRQHandler
  .word  USART3_IRQHandler
  .word  EXTI15_10_IRQHandler
  .word  RTCAlarm_IRQHandler
  .word  USBWakeUp_IRQHandler
  .word  TIM8_BRK_IRQHandler
  .word  TIM8_UP_IRQHandler
  .word  TIM8_TRG_COM_IRQHandler
  .word  TIM8_CC_IRQHandler
  .word  ADC3_IRQHandler
  .word  FSMC_IRQHandler
  .word  SDIO_IRQHandler
  .word  TIM5_IRQHandler
  .word  SPI3_IRQHandler
  .word  UART4_IRQHandler
  .word  UART5_IRQHandler
  .word  TIM6_IRQHandler
  .word  TIM7_IRQHandler
  .word  DMA2_Channel1_IRQHandler
  .word  DMA2_Channel2_IRQHandler
  .word  DMA2_Channel3_IRQHandler
  .word  DMA2_Channel4_5_IRQHandler
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  0
  .word  BootRAM       /* @0x1E0. This is for boot in RAM mode for 
                         STM32F10x High Density devices. */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler. 
* As they are weak aliases, any function with the same name will override 
* this definition.
* 
*******************************************************************************/
    
  .weak  NMI_Handler
  .thumb_set NMI_Handler,Default_Handler
  
  .weak  HardFault_Handler
  .thumb_set HardFault_Handler,Default_Handler
  
  .weak  MemManage_Handler
  .thumb_set MemManage_Handler,Default_Handler
  
  .weak  BusFault_Handler
  .thumb_set BusFault_Handler,Default_Handler

  .weak  UsageFault_Handler
  .thumb_set UsageFault_Handler,Default_Handler

  .weak  SVC_Handler
  .thumb_set SVC_Handler,Default_Handler

  .weak  DebugMon_Handler
  .thumb_set DebugMon_Handler,Default_Handler

  .weak  PendSV_Handler
  .thumb_set PendSV_Handler,Default_Handler

  .weak  SysTick_Handler
  .thumb_set SysTick_Handler,Default_Handler

  .weak  WWDG_IRQHandler
  .thumb_set WWDG_IRQHandler,Default_Handler

  .weak  PVD_IRQHandler
  .thumb_set PVD_IRQHandler,Default_Handler

  .weak  TAMPER_IRQHandler
  .thumb_set TAMPER_IRQHandler,Default_Handler

  .weak  RTC_IRQHandler
  .thumb_set RTC_IRQHandler,Default_Handler

  .weak  FLASH_IRQHandler
  .thumb_set FLASH_IRQHandler,Default_Handler

  .weak  RCC_IRQHandler
  .thumb_set RCC_IRQHandler,Default_Handler

  .weak  EXTI0_IRQHandler
  .thumb_set EXTI0_IRQHandler,Default_Handler

  .weak  EXTI1_IRQHandler
  .thumb_set EXTI1_IRQHandler,Default_Handler

  .weak  EXTI2_IRQHandler
  .thumb_set EXTI2_IRQHandler,Default_Handler

  .weak  EXTI3_IRQHandler
  .thumb_set EXTI3_IRQHandler,Default_Handler

  .weak  EXTI4_IRQHandler
  .thumb_set EXTI4_IRQHandler,Default_Handler

  .weak  DMA1_Channel1_IRQHandler
  .thumb_set DMA1_Channel1_IRQHandler,Default_Handler

  .weak  DMA1_Channel2_IRQHandler
  .thumb_set DMA1_Channel2_IRQHandler,Default_Handler

  .weak  DMA1_Channel3_IRQHandler
  .thumb_set DMA1_Channel3_IRQHandler,Default_Handler

  .weak  DMA1_Channel4_IRQHandler
  .thumb_set DMA1_Channel4_IRQHandler,Default_Handler

  .weak  DMA1_Channel5_IRQHandler
  .thumb_set DMA1_Channel5_IRQHandler,Default_Handler

  .weak  DMA1_Channel6_IRQHandler
  .thumb_set DMA1_Channel6_IRQHandler,Default_Handler

  .weak  DMA1_Channel7_IRQHandler
  .thumb_set DMA1_Channel7_IRQHandler,Default_Handler

  .weak  ADC1_2_IRQHandler
  .thumb_set ADC1_2_IRQHandler,Default_Handler

  .weak  USB_HP_CAN1_TX_IRQHandler
  .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler

  .weak  USB_LP_CAN1_RX0_IRQHandler
  .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler

  .weak  CAN1_RX1_IRQHandler
  .thumb_set CAN1_RX1_IRQHandler,Default_Handler

  .weak  CAN1_SCE_IRQHandler
  .thumb_set CAN1_SCE_IRQHandler,Default_Handler

  .weak  EXTI9_5_IRQHandler
  .thumb_set EXTI9_5_IRQHandler,Default_Handler

  .weak  TIM1_BRK_IRQHandler
  .thumb_set TIM1_BRK_IRQHandler,Default_Handler

  .weak  TIM1_UP_IRQHandler
  .thumb_set TIM1_UP_IRQHandler,Default_Handler

  .weak  TIM1_TRG_COM_IRQHandler
  .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler

  .weak  TIM1_CC_IRQHandler
  .thumb_set TIM1_CC_IRQHandler,Default_Handler

  .weak  TIM2_IRQHandler
  .thumb_set TIM2_IRQHandler,Default_Handler

  .weak  TIM3_IRQHandler
  .thumb_set TIM3_IRQHandler,Default_Handler

  .weak  TIM4_IRQHandler
  .thumb_set TIM4_IRQHandler,Default_Handler

  .weak  I2C1_EV_IRQHandler
  .thumb_set I2C1_EV_IRQHandler,Default_Handler

  .weak  I2C1_ER_IRQHandler
  .thumb_set I2C1_ER_IRQHandler,Default_Handler

  .weak  I2C2_EV_IRQHandler
  .thumb_set I2C2_EV_IRQHandler,Default_Handler

  .weak  I2C2_ER_IRQHandler
  .thumb_set I2C2_ER_IRQHandler,Default_Handler

  .weak  SPI1_IRQHandler
  .thumb_set SPI1_IRQHandler,Default_Handler

  .weak  SPI2_IRQHandler
  .thumb_set SPI2_IRQHandler,Default_Handler

  .weak  USART1_IRQHandler
  .thumb_set USART1_IRQHandler,Default_Handler

  .weak  USART2_IRQHandler
  .thumb_set USART2_IRQHandler,Default_Handler

  .weak  USART3_IRQHandler
  .thumb_set USART3_IRQHandler,Default_Handler

  .weak  EXTI15_10_IRQHandler
  .thumb_set EXTI15_10_IRQHandler,Default_Handler

  .weak  RTCAlarm_IRQHandler
  .thumb_set RTCAlarm_IRQHandler,Default_Handler

  .weak  USBWakeUp_IRQHandler
  .thumb_set USBWakeUp_IRQHandler,Default_Handler

  .weak  TIM8_BRK_IRQHandler
  .thumb_set TIM8_BRK_IRQHandler,Default_Handler

  .weak  TIM8_UP_IRQHandler
  .thumb_set TIM8_UP_IRQHandler,Default_Handler

  .weak  TIM8_TRG_COM_IRQHandler
  .thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler

  .weak  TIM8_CC_IRQHandler
  .thumb_set TIM8_CC_IRQHandler,Default_Handler

  .weak  ADC3_IRQHandler
  .thumb_set ADC3_IRQHandler,Default_Handler

  .weak  FSMC_IRQHandler
  .thumb_set FSMC_IRQHandler,Default_Handler

  .weak  SDIO_IRQHandler
  .thumb_set SDIO_IRQHandler,Default_Handler

  .weak  TIM5_IRQHandler
  .thumb_set TIM5_IRQHandler,Default_Handler

  .weak  SPI3_IRQHandler
  .thumb_set SPI3_IRQHandler,Default_Handler

  .weak  UART4_IRQHandler
  .thumb_set UART4_IRQHandler,Default_Handler

  .weak  UART5_IRQHandler
  .thumb_set UART5_IRQHandler,Default_Handler

  .weak  TIM6_IRQHandler
  .thumb_set TIM6_IRQHandler,Default_Handler

  .weak  TIM7_IRQHandler
  .thumb_set TIM7_IRQHandler,Default_Handler

  .weak  DMA2_Channel1_IRQHandler
  .thumb_set DMA2_Channel1_IRQHandler,Default_Handler

  .weak  DMA2_Channel2_IRQHandler
  .thumb_set DMA2_Channel2_IRQHandler,Default_Handler

  .weak  DMA2_Channel3_IRQHandler
  .thumb_set DMA2_Channel3_IRQHandler,Default_Handler

  .weak  DMA2_Channel4_5_IRQHandler
  .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler

/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/

I used the crt0.s supplied by arm in the CMSIS/… folder of the ST libs. I don’t think I changed anything. I’ll post it around 16:00 (GMT -6)

Managed to build your example and determine that it does not work here either. (ISP problems here Tuesday evening.)

Does the TIM6 example you posted work under the same conditions?

Our startup files are almost but not quite identical.

My “project” is at http://www.overtracks.com/sos/20100922/tim6d.zip

I guess I have to say “yes” (with reservations) about my example working under the same conditions. What I did was to copy stm32f10x_gpio.c and .h to my project directory, as well as _rcc., _tim., and misc.*. (I commented out a couple of remaining lines that appeared to relate to USB.) I didn’t bother to create a library - after compilation I linked the entire misc.o, _rcc.o etc in with main.o and ctr0.o to make a 29KB binary file, and uploaded that to the target.

So, I kept the same crt0.s and the same .ld linker command file. The structure of the Makefile was the same, but the additional .c and .o files were involved.

I’m using this board as target: [ET-STM32_Stamp. It should be easy enough to hook up the jtag lines but I’ve not done that yet. So far I’ve been uploading via serial port and “debugging” via LED blinks and serial port output. In the process of tweaking your code to toggle a few PA lines, I may have broken something. More research required.

Lately I’ve been using the 2009q3 (Linux) precompiled version of the gcc cross-compiler from CodeSourcery.

BTW, I spent literally a couple of hours trying to work around the assert_params() functions sprinkled around the ST library files. Now that my internet connection is back up I’ll go research that.

One other bit of trivia that disappointed me: I noticed that ST has (or have if you’re not from USA) given the same peripheral bit different names in different header files. For example, RCC_APB2ENR_IOPAEN from stm32f10x.h is the same as RCC_APB2Periph_GPIOA in stm32f10x_rcc.h.](ET-STM32 Stamp Module)

Oh my gosh your version does work! My edits had a typo where I enabled clocks for “B | B” instead of “A | B”. As soon as I fixed that it started working.

I uploaded that project to http://www.overtracks.com/sos/20100922/tim3a.zip. I included the .hex and .bin files this time (as well as all the .o). Not sure if it is safe for you to try to load it on your test board; PA0 - PA7 are all driven as outputs.

The entire misc.o, gpio.o, rcc.o, and tim.o are still linked in, but it only came out to around 13k this time. (My assert_params() workaround clearly was not the most efficient.)

[edit: link fixed. I could swear I tested that…]

Dead link on that zipfile, I’m anxious to try it!

Still plugging away at mine…

If your hex file didn’t work for my board… what then? Is it possible that there’s a hardware difference with our boards that kept mine from working? Does that even make sense? I’m fairly new to these parts (and the ARM architecture in general), so I’m not as educated about what is and is not possible.

-R

Well, I have the best intentions in the world, but… I might just be slowing you down here. There may be someone in the forums at st.com that uses your board and development system and has seen an identical behavior.

Off the top of my head, I don’t know of any external hardware connections etc. that would be likely to prevent a counter interrupt from firing or from being called. I’d be inclined to try your code without your debugger running. When I browsed through the Cortex-m3 Technical Reference Manual, I was surprised at how many registers exist for core and system debug. I’ve not even begun to understand how all that really fits together.

Okay last gasp before bedtime:

I downloaded your zip file, tried to load your binaries exactly as they are. They load into the micro just fine and seem to run, but that ISR is again, never taken. This is without me even rebuilding, just taking your object file, and loading it into my micro with GDB. This leaves either the kit I’m using, or the jtag/gdb configuration to blame.

Going to sleep now, more tomorrow.

Edit: Yeah, might try without the debugger, but as I said, I’m hitting a hardfault out of reset, so I’ve got that to deal with :confused:

-R

Hah! Using your example, I get no hardfault out of reset, and the ISR works. All I had to do was reset the part and run from a “clean” start.

Now to figure out what’s different.

-R

Got this resolved! See the post at here:

viewtopic.php?f=11&t=23882

The hardfault I was getting at startup (that I was simply working around using the debugger) was actually convincing the part that I was always in a hardfault exception handler. Therefore, no ISR would execute because of the priority of the hard fault.

I resolved the cause of the hardfault (bad LSB in the reset handler entry in the vector table) and now everything works as expected, even my USB!