Hi,
I'm currently doing a baremetal c project on a MK10 and MK20 (both with Cortex M4 cores) with the help of the Processor Expert LDDs.
I want to have the FTM0 free-running with certain channels in capture and others in compare mode. Now, when an edge is detected (captured) the correspondig ISR will be called, which in return writes the current value to a buffer. This buffer is then periodically (not deterministic as of right now) read and processed by a frequency calculation function. To protect against a read-while-write operation I'm thinking about using a mutex variable. I've read in the Cortex-M4 User Guide that such synchronization primitives exist, but I haven't found a demo or a ready to use c function for kinetis. Are either available? Or will I have to get my own assembler instructions running?
Any other solutions for the problem described here? A ringbuffer/fifo? Blocking/disabling the interrupts isn't a good option, because I don't want to miss out on one of those. Doing the processing in the isr isn't the solution I'm looking for either.
Does the DMA make use of such primitives?
As a note: It isn't bad if capture values for the correspondig FTM channel are lost to the mutex every now and then. To protect from that I could just double the buffer (from 2 values to 4) and have either one accessed with a dirty/fresh flag.
Hello Martin,
I think you can build the mutex primitives by using the bit-band feature.
Please refer to the post (http://community.arm.com/message/23697) of the ARM Connected Community.
Best regards,
Yasuhiko Koumoto.
Hi Martin
I would suggets that the optimal solution to capturing values is to use DMA since it has no ISR overhead and also gives the most accurate results without any critical SW response time to treating the captured data.
Configure a DMA channel to transfer the capture count register to a circular buffer (which it also handles automatically).
Set the DMA trigger from the capture edge.
Poll the DMA transfer status (occasionally) to find out where the present transfer is (that is, how many new capture values are ready and where they are located in the buffer) and treat one or more each when found (so that the DMA circular buffer doesn't overflow)
The other SW techniques based on interrupts coordinating a circular buffer and/or processing in a pre-emptable interrupt context, will of course also work but will just not be as efficient or accurate - and the DMA case is in fact easier to implement.
The uTasker UART Rx DMA free-run mode uses this technique with the only differences being that the UART Rx data register is copied to the buffer (rather than a count value) and the DMA trigger is from the UART Rx buffer (rather than from an edge) - otherwise it is identical.
Regards
Mark
Kinetis: µTasker Kinetis support
K20: µTasker Kinetis TWR-K20D72M support / µTasker Kinetis FRDM-K20D50M support / µTasker Kinetis TWR-K20D50M support / µTasker Kinetis support
For the complete "out-of-the-box" Kinetis experience and faster time to market
Thanks for your answer, Mark. I've seen your µTasker before, but never had the time to properly check it out.
I suspected the DMA might be the best solution, but I kind of fear the complexity. Without having had time to properly look into it, this is my understanding of the process:
FTM capture
->DMA Transfer triggered
-->DMA checks if ringbuffer is being accessed?*
--->DMA transfers data to ringbuffer
...and independent of that an asynchronous task checking and analysing the captured values.
*I think this might not be the case. But then how would one assure that the DMA doesn't corrupt the data as it is being read/accessed? Just by never having the ringbuffer overflow and thus the read pointer always being far enough away from the write pointer?
Martin
-->DMA checks if ringbuffer is being accessed?*
The DMA circular buffer operation is fully independent of the processor - it will in fact continue operating when the processor is paused with the debugger - see the following ADC-DAC DMA reference which allows audio to be transferred even when the processor is not operating: https://community.freescale.com/message/370676#370676
This means that the circular buffer will indeed be reused if the SW is too slow to handle the data before it is overwritten. Therefore the buffer size should be chosen suitably to ensure that it doesn't happen in the worst case (that is when your software has its longest delay due to other work load).
It is also possible to program the circular buffer to terminate after a single cyle and the SW then needs to restart it each time - this would avoid overwrites but instead adds critical periods where input will not be operating (and single captures lost). It is therefore a system design/tradeoff but usually it shouldn't be a problem to ensure that the buffer is not cleared in time by dimensioning it adequately.
The DMA also supports a half-buffer interrupt that can be useful if polling is to be avoided.
>>but I kind of fear the complexity
The DMA can be a little complicated in case you haven't used it before but there is a complete solution in the uTasker projet for circular buffer operation (free-running or half-buffer interrupt based) which means tht it can be used by any peripheral with only a couple of address changes. Since the uTasker simulator handles also DMA operation it can be simply tested to ensure that it is configured and operating correctly and any interraction with the application is as envisaged. HW operation would then work without any extra investment.
Regards
Mark
Kinetis: µTasker Kinetis support
K20: µTasker Kinetis TWR-K20D72M support / µTasker Kinetis FRDM-K20D50M support / µTasker Kinetis TWR-K20D50M support / µTasker Kinetis support
For the complete "out-of-the-box" Kinetis experience and faster time to market