cancel
Showing results for 
Search instead for 
Did you mean: 

SPI TXE flag interrupt

shannon2
Associate II
Posted on January 31, 2012 at 06:01

I'm using the SPI TXE interrupt.  My ISR simply checks to see if there is anything more to transmit in the buffer.  If there is, it sends it, moves the buffer pointer, and returns.  If there isn't anything left to transmit in the buffer, it simply returns.  I'm getting stuck in this ISR I think.

I see that the TXE flag is only cleared by writing to the SPI_DR.  Since there is no more data to send (at the moment) I don't write to the DR and I think I'm stuck re-entering the ISR over and over.

My question is this, is it standard procedure to disable the SPI peripheral at the end of each transfer?  Seems kinda silly but I can't imagine another way of getting the TXE flag cleared.
4 REPLIES 4
ColdWeather
Senior
Posted on January 31, 2012 at 12:08

You should disable the TXE interrupt in the ISR when no data more to transmit (see TXEIE bit in SPI_CR2 register). When starting the new transaction outside the ISR, send the first byte, - it clears the TXE flag,- and reenable the interrupt via TXEIE.

Watch the following well known issue regarding disabling the interrupt inside the ISR: due to the cortex core architecture the interrupt being disabled in the ISR shortly before the ISR returns can cause the ISR to trigger again immediately. There are two solutions:

1 - to place enough code between the instruction that disables the interrupt and the end of the ISR - often that is the case, and people never experience the bug.

2 - to place __DSB() call at the end of the ISR - see core_cmInstr.h from CMSIS.

shannon2
Associate II
Posted on January 31, 2012 at 16:23

Thanks for the answer ColdWeather.  I'm used to clearing an ISR flag directly as is typical with most of the other flags.  Just surprised me in this instance to have to disable the interrupt entirely.  Code-wise it really makes little difference except that you have to re-enable the interrupt each time you start to transmit more than one byte.  Not a big deal just different procedure.

This one is working now.  On to trying to understand why my EXTI interrupt is never firing.  If it isn't one thing....

ColdWeather
Senior
Posted on January 31, 2012 at 17:06

1). SPI. Well, you can have always the same procedure to send via SPI in interrupt mode: ALL bytes to send in the ISR; the ''main'' procedure just prepares the buffer, inits counters/pointers and just enables the SPI interrupt. At this moment, due to the fact, that TXE is active, ISR triggers immediately, you send the first byte there, move pointers/reduce counters, and if there are still data to send, exit the ISR, else (was a single byte only) disable the SPI TXE interrupt first. That's all.

But please remember: I suppose, you have to control the chip select (some GPIO) output to mark the beginning and the end of the SPI transaction to let the peripheral to latch the received data. So, the STM32F10x has double buffered SPI. It means, after the last byte has been written to DR, TXE goes high almost immediately, but the data are still clocked out. Thus you should wait for BSY flag reset before you play with the chip select.

I did not understand, what you meant saying ''disable interrupts entirely''... You work just with SPI TXEIE bit (and NVIC corresponding to your SPI, of course) but not with global interrupts.

2). To have EXTI active, you should take a look at TWO units in STM32F: not only EXTI but AFIO, too. Saying nothing of RCC, naturally, to clock all of them.

shannon2
Associate II
Posted on January 31, 2012 at 22:50

I will post my code snip-it when I'm at home just for the sake of completeness.  I hate old threads that never show the final resolution.

I will start a separate thread for my continued EXTI problems.

Thanks for all the help!