Page 2 of 3
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Fri Sep 29, 2017 1:49 pm
by elagil
I see, that is good to know.
Everything works if the DMA ISR does not send any event but breaks otherwise. The event listener has a stack size of 1024, all other threads (not doing much, really) mostly 256 or 1024.
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Fri Sep 29, 2017 1:57 pm
by Giovanni
I suggest to selectively disable parts of your application until you find the one that triggers the problem.
Giovanni
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Fri Sep 29, 2017 2:07 pm
by elagil
Switching off all other threads does not even help! Interesting.
Only tcp_sender is active, which receives the event.
Now, the stack trace is very short. After only 14 steps, it stops. I am bothered by VectorB0, is that an exception?
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Fri Sep 29, 2017 2:46 pm
by Giovanni
Vector B0 is an ISR.
Giovanni
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 8:24 am
by elagil
I am not aware of creating it, is it doing something in particular? I also often see Vector120.
Adrian
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 9:13 am
by Giovanni
Vector B0 is associated to an USART if I remember well, the list in on the STM32 Reference Manual.
Giovanni
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 9:30 am
by elagil
Ok, thank you. I will have a look.
I have another question, though. I give the DMA a callback function to call on transfer complete. Do I have to treat it just like an ISR?
More specifically, do I need to put
CH_IRQ_PROLOGUE()
and
CH_IRQ_EPILOGUE()
inside the handler? I suppose that this is not an actual ISR but a callback called from the DMA ISR.
Thanks,
Adrian
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 10:18 am
by Giovanni
Hi,
Callbacks must not use macros, just plain functions, macros must be placed only in ISR top level function.
Giovanni
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 10:29 am
by elagil
Thanks, that seems to be it! It does not run into the exception handler anymore. Events work fine now, too.
One last question: The dmaStreamAllocate expects an IRQ priority MASK. However, there are no macros for DMA priority masks. I just give it the number "3". Is that ok? What range of numbers is allowed? I know that 0 and 1 shall not be used.
Thanks again,
Adrian
Here is the complete code for configuring input capture with DMA. I use this for capturing a parallel 16 bit external ADC input. The input capture unit triggers on the ADC sampling clock and requests the DMA to collect the input data from a chosen port (16 bit parallel input in my case).
First, the ICU configuration structure:
It also enables the request for the DMA in the timer. I use timer 1 channel 2 for DMA 2 stream 2.
Code: Select all
/**
* Configuration structure for the input capture unit (ICU)
*/
ICUConfig icucfg = {
ICU_INPUT_ACTIVE_HIGH,
40000000, /** 40 MHz ICU clock frequency. */
NULL,
NULL,
NULL,
ICU_CHANNEL_2,
/** DIER Register for enabling CH2 request on DMA */
STM32_TIM_DIER_UDE | TIM_DIER_CC2DE
};
The following goes in my main() function and starts the ICU and DMA. It also contains the DMA config.
I use a circular DMA with two memory buffers between which the DMA switches each time. They are called mem0 and mem1.
ADC_SAMPLES is #define(d) to 1024 in my case
Code: Select all
/*****************************************************************************
* Configure ICU and DMA for ADC capturing
*/
/**
* Start ICU (input capture unit) for DMA request generation
*
* The ADC clock signal is sampled by this ICU.
*/
icuStart(&ICUD1, &icucfg);
icuStartCapture(&ICUD1);
/**
* Allocate stream, dma_complete_handler is called in case of a complete
* DMA transaction
*/
dmaStreamAllocate(STM32_DMA2_STREAM2,
3,
(stm32_dmaisr_t)dma_complete_handler,
(void *)STM32_DMA2_STREAM2);
/**
* Set the DMA source address, GPIO port J
*/
dmaStreamSetPeripheral(STM32_DMA2_STREAM2, &GPIOJ->IDR);
/**
* Set the DMA destination addresses. This can be configured as a double
* buffer DMA, so two buffers are specified
*/
dmaStreamSetMemory0( STM32_DMA2_STREAM2, mem0);
dmaStreamSetMemory1( STM32_DMA2_STREAM2, mem1);
/**
* Size of one complete DMA transaction in samples of 16 bit
*/
dmaStreamSetTransactionSize( STM32_DMA2_STREAM2, ADC_SAMPLES );
/**
* DMA configuration:
* - Priority 0 (Very high 3..0 Low)
* - Half word transfer size (16 bit)
* - Circular DMA mode
* - Direction: Peripheral to memory
* - Increase memory pointer automatically
* - Enable DMA transfer complete interrupt
* - Select channel 6 (DMA 2, Stream 2, Tim1Ch2)
* - Dual buffer mode, switches between two memories
*/
dmaStreamSetMode( STM32_DMA2_STREAM2,
STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD |
STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_P2M |
STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC |
STM32_DMA_CR_CHSEL(6) | STM32_DMA_CR_TCIE |
STM32_DMA_CR_DBM );
/**
* enable the stream
*/
dmaStreamEnable(STM32_DMA2_STREAM2);
/**
* End configure DMA
****************************************************************************/
This is the DMA transfer complete handler that is called on DMA complete interrupt:
It also sends some events to other parts of my application. Be sure to initialize the event source first if you want to use something similar.
Code: Select all
/**
* Process DMA complete interrupt
*
* Detects, which memory was last filled with data. Starts processing and
* transmission to host PC.
*
*/
void dma_complete_handler(stm32_dma_stream_t * dmastp, uint32_t flags)
{
(void) flags;
/**
* Current buffer is Memory 0
*/
if((dmastp->stream->CR & DMA_SxCR_CT) == 0)
{
chSysLockFromISR();
chEvtBroadcastFlagsI(&dma_event_source, DMA_MEM0_READY);
chSysUnlockFromISR();
}
/**
* Current buffer is Memory 1
*/
else
{
chSysLockFromISR();
chEvtBroadcastFlagsI(&dma_event_source, DMA_MEM1_READY);
chSysUnlockFromISR();
}
dmaStreamClearInterrupt(dmastp);
}
Re: DMA complete ISR -> mailbox post -> SV#8
Posted: Wed Oct 04, 2017 10:48 am
by Giovanni
Hi,
That "mask" is a documentation leftover from an old version, valid values are 2..15.
Giovanni