cancel
Showing results for 
Search instead for 
Did you mean: 

Help getting ISR callback for timer?

skeezix
Associate II
Posted on January 14, 2014 at 22:24

I'm quite likely missing something obvious to someone, but so far this is eluding me 🙂

I've got an STM32F205RE by itself on a breadboard (no eval or discovery board here.) I'm using libopencm3 for linker-script and some sample code, and using the https://launchpad.net/gcc-arm-embedded toolchain, along with openocd for flashing. Linux based environment. I've added external 8mhz crystal and associated caps to ground, and using the libopencm3 go-to-120MHz function, but nothing else on the board.

Code in question is quite short, here:

http://pastebin.com/xTxn5829

Essentially a blinking light hello world app, but goal being to toggle the LED in an ISR callback from the timer. I have a variation of that code that polls the timer and works fine .. so I know I can build code and deploy it okay in general, but this particular version isn't working.

I suspect something out of the code (so the vector table is goofy, and my ISR function is not being seen at all?), or perhaps I'm just missing a register assignment somewhere. I'm new to STM32 world so trying to get my head around the documentation and so on .. if you spot anything, let me know 🙂

I'm using linkerscript as from libopencm3-examples, though modified to have the right ROM and RAM size for my chip (since there is onyl 1 sample for the F2 chip).

In case its a deployment issue, I'm deploying like this:

openocd -f interface/stlink-v2.cfg \

                    -f target/stm32f2x_stlink.cfg \                                                                                                                                         -c ''init'' -c ''reset init'' \

                    -c ''stm32f2x mass_erase 0'' \

                    -c ''flash write_image miniblink.hex'' \

                    -c ''reset'' \

                    -c ''shutdown'' $(NULL)

I flash the code, hit reset on the chip (pull it to ground for a moment), and then led just stays on. I've not hooked up any debugger yet (next thing to figure out), so I'm not sure if its crashed or hanging on blocked interupts or what.

Thank you for any help, and for your patience in reading,

jeff
11 REPLIES 11
skeezix
Associate II
Posted on January 15, 2014 at 06:43

Actually, it would seem the ISR is in fact being called.. but putting a GPIO toggle in there is not working.

If I instead set a volatile int to a value, and then check the value in the main loop and toggle the GPIO, everything works peachy.

Toggling a GPIO is quick, and the timer frequency is low, so I'm surprised by this..

I'll keep digging, but any advice?

troy1818
Senior
Posted on January 15, 2014 at 10:21

Yes, seems a little strange.

Have you tried this with CMSIS ?

example can be found here:

http://en.radzio.dxp.pl/stm32vldiscovery/lesson4%2cblinking%2cwith%2ctimer%2cinterrupts.html

I think COOCOX is supporting your chip if you want to make a quick test with this lib.

http://www.coocox.org/CooCox_CoIDE.htm

Regards,

rygelxvi

skeezix
Associate II
Posted on January 15, 2014 at 16:11

AFAIK CooCox does not support the F2 line at all 'officially', though a few people have hacked support in place. Googling doesn't boost confidence in it, and their official supported chipset doesn't list it (surprising!)

I've not traced the history back, but it really does seem like more people use F4 than F2 .. either everyone wants the high performance, or F4 came out earlier ?! .. so many tools do not support F2, its surprising 🙂

troy1818
Senior
Posted on January 15, 2014 at 16:21

That is too bad, I did not know that f2 wasn't supported. I sorry to say that I cannot see what is wrong here. If what you say is true and if you can toggle the pin in the same way outside irq function I cannot see why it should not work inside it. Perhaps someone else will have time to comment on this too.

Regards,

rygelxvi

skeezix
Associate II
Posted on January 15, 2014 at 16:42

Here is an odd find.. if I change the code slightly:

volatile unsigned int poop = 0;

void tim2_isr ( void ) {

  //gpio_clear ( GPIOC, GPIO3 );                                                                                                                                                        

  //TIM2_SR &= ~TIM_SR_UIF;    //clearing update interrupt flag                                                                                                                         

  TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */

#if 1

  poop = 1;

#endif

  gpio_toggle(GPIOC, GPIO3); /* LED on/off. */

}

Note:

- if the 'clearing update' is at the bottom (where it was, where I would expect it should be), no luck; moving it up the top of function, and it may work..

- .. but only if the volatile is kept (and is now unused.)

main loop now just does 'if poop, poop = 0' with its gpio toggle commented out.

If I remove the volatile 'poop' (sorry, it was late) entirely, no joy.

Let me try adding some other fluff .. I wonder if somehow there is a minimum size thing here, or a 'it needs to run just a bit longer', or something .. or maybe the interupt is triggering twice in a row, then waiting a secon, then twicfe, etc, so as to cancel itself out or something..

edit: yesm, just adding a few delay NOPs in place, makes it happy. Still have to have the 'clearing interupt' at the first thing though:

void tim2_isr ( void ) {

  //TIM2_SR &= ~TIM_SR_UIF;    //clearing update interrupt flag                                                                                                                         

  TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */

  unsigned long int j;

  for ( j = 0; j < 100; j++ ) {

    __asm__(''nop'');

  }

  gpio_toggle(GPIOC, GPIO3); /* LED on/off. */

}

... so weird. Is it being double-called and thus needing to block itself, or is there some minimum duration requirement here?! 🙂

chen
Associate II
Posted on January 15, 2014 at 16:59

Hi

Firstly, Im being fussy but the title of this thread is WRONG.

You are talking about the ISR. You do NOT have an ISR callback function.

A callback function is a function which is registered (set) into the ISR.

Then at the right time, the ISR will execute the callback function - hence it is often refered to as a callback!

Can you actually show us the code, we cannot help you unless you show us the code.

We still need to see how you set up the IO ports, the Timer and the main loop

skeezix
Associate II
Posted on January 15, 2014 at 17:05

Sorry, though I included the link; the current full code is here:

http://pastebin.com/KXH1HDnB

Essentially, the ISR part is:

void tim2_isr ( void ) {

  TIM_SR(TIM2) &= ~TIM_SR_UIF; /* Clear interrrupt flag. */

  __asm__(''nop'');

  gpio_toggle(GPIOC, GPIO3); /* LED on/off. */

}

If the 'nop' is removed, it doesn't work. If the UIF clear is moved to bottom of the function, it doesn't work.

But exactly like this, and it does work...

Posted on January 15, 2014 at 17:18

a) TIM->SR isn't a RMW register, just write the mask

b) There is a pipeline hazard wrt tail-chaining, do ANY read/write after the TIM->SR write, you won't see it.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
skeezix
Associate II
Posted on January 15, 2014 at 17:27

Can you explain further? especially on point b .. are you suggesting after any setting to SR, you shoudl 'nop' or something, to make sure your next opcode(s) aren't ignored?!

Also.. tail chaining.. maybe can be disabled in nvic, I'll look into it .. but, what would cause multiple triggers of this interupt? It should be a few times a second in this code, so should never be 'too quick' or repeating very quickly, to cause a tail chaining type optimzation?