cancel
Showing results for 
Search instead for 
Did you mean: 

25 microSecond (not milli) Interrupt Advice

estersci2
Associate III
Posted on September 18, 2015 at 10:43

Hi,

I would be grateful for some advice on Sampling logic-level signal with a timer.

I haven't done embedded programming in a very long time and so have little experience with the current STM32 offering - and at the moment I am still waiting on Hardware to program. The FW will involve sampling at high frequency, and I see from the Forum that others have run into problems with their approach as regards over saturating the micro etc. I would be grateful if those with experience could tell me if the following approach seems reasonable. 

Basically I want to use a timer at 40kHz to sample the level of a pin and write it to an array element, incrementing along once every 25 uS, in an STM32F417 micro. Systick would remain at the usual 1mS. 

I would be using the cube TIM_timebase example for G-Eval board as a starting point and adjusting the timer and periods to achieve the above rate. Is that a bit naive or does it sound ok? Any ideas as to what kind of rate the above approach could be pushed to, i.e 0.5 MHz?

Thanks.

10 REPLIES 10
e1369008
Associate II
Posted on September 18, 2015 at 11:17

40KHz sampling is not an issue for that microcontroller. The question is where are you going to write that much data? Your SRAM will run out in couple of seconds. Do you have some kind of external memory?

estersci2
Associate III
Posted on September 18, 2015 at 11:48

Thanks. Its a circular buffer really, only need a fraction of a second history signal for processing purposes, then overwrite. 

jpeacock
Associate II
Posted on September 18, 2015 at 14:32

Since you are looking at one pin my approach would be to treat it as an A/D conversion.  Connect your signal to an ADC input, set up the ADC for TIM triggered ample rate (you can go far higher than 40KHz) and use DMA to read the samples.  Data reduction is picking an arbitrary level for assert and deassert to convert to binary.  Use BitBand to write out the result bit to a word array that maps back to packed bits.

This offloads data capture from interrupts.  With an F4 the data capture time is almost free since you can run the DMA in parallel if you are careful about assigning the DMA buffer to reduce SRAM bus collisions with the rest of the program.

With a circular buffer you can reduce one half the buffer while capturing the other half, using DMA half transfer events.

  Jack Peacock
Posted on September 18, 2015 at 14:33

You're going to have a headache as the interrupt rates head into the 100's of KHz. The way to sample pins at high/fixed rates is to use a TIM to drive a DMA action (GPIO bank to memory), and decimate the interrupt rate using the HT and TC interrupts of the DMA

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
estersci2
Associate III
Posted on September 20, 2015 at 10:39

Clive,

Thanks for your suggestion, but I have a query on NTDR and transfer callbacks (for the 40kHz case).

I would like to set up a

continuous

DMA transfer from a single pin to a incrementing circular

buffer, so that I have, say, 1 second of signal logic level history.

As the DMA increments, I would like to know what was the last updated array element,

and have a function called to do some time/sync-critical processing (elsewhere) - i.e. called after the latest array element transfer,to be completed before the next DMA array element transfer.

For a starting point, I was planning to use your code at

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Data%20transfer%20from%20GPIO%20port%20to%20RAM%20buffer%20using%20DMA%20upon%20receiving%20a%20trigger%20signal%20on%20the%20timer%20capture...

I was wondering if you could please show me some code to do a per element transfer callback,reporting the last transferred array element index - maybe based on NTDR.

From this callback I could call another function to do some time critical functions elsewhere.

Also, a newbie DMA question - is it ok to read (just read) a value from a circular buffer that is

continously being updated? Especially if you explicitly wait until an array element is reported before making the read? What if you don't explicitly wait and just read - is there a risk of corrupted data or is access atomically locked to be either old or latest data?

...and if doing a dma transfer memory to peripheral continuous, can you write to an array that

is a live DMA source, or must you write to another array and then switch it over?

Thanks

Posted on September 20, 2015 at 13:06

Generally that's why I use HT/TC (Half Transfer/Transfer Complete) so I split the buffer into two halves (ping/pong) and work on the half that's just finished, and is thus not ''live'', and prone to change underneath me.

You then have about that half time, less some safety margin to process the data. Yes, you could probably check the pointer, and chase it, but you'd need to be very wary. I'd want to be able to process the data significantly faster than it's generated, if you're approaching parity, you need to rethink what you're doing.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on September 20, 2015 at 13:16

There is not way to get locked/atomic access, the DMA operates autonomously from the core. You should tell the compiler the data array is volatile. You can stop the timer or disable the DMA, of course, but that is likely to create more problems than it solves.

Some parts permit a ''double buffering'' DMA mode which is a bit like the ping/pong method but with independent/non-linear buffers, and you can perhaps juggle three or more buffers, or chain them, but that adds more complexity than I care for.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
estersci2
Associate III
Posted on September 21, 2015 at 15:00

Clive, 

Thanks. If you consider the basic example of an ADC continuously dma transferring its value to a location, such as in the ADC_RegularConversion_DMA example, how did ST expect users, in a practical sense, to do something practical with the transferred data?

It kind-of implies that it is safe just to read from the value that is transferred in - because otherwise what use is that DMA configuration/example?

Do you think a situation could arise where you read out the value mid way through an element update and get corrupted data? 

Tomas DRESLER
Senior II
Posted on May 05, 2017 at 21:28

You can use the DMA in circular mode and store 1 second of data at this rate. In the same time, you can get SysTick IRQ @ 1 ms, read DMA->NDTR (remaining data till end of the buffer) and process the data between previous NDTR sample and the new one.

Tested, working, used as intermediate buffer for UART Rx reception with AT command parsing engine behind 🙂