2017-10-03 10:25 AM
Hi
I'm using the SPC560P40L1
Im trying to switch a GPIO using pre-defined data stored in memory. I would like the GPIO to switch after a rising edge on a PWM pin which is being monitored by ETC/eTimer. I also need the DMA to control all of this. The CPU is pretty loaded already.
Is there an example code I could use? Im using the SPC5studio and they only have examples of DMA use with SPI and ADC.
I looked at the reference manual and that is not easy to start of with as a beginner to DMA
Can anyone point me in the right direction to get started?
-Thanks
2017-10-04 02:12 AM
Hello Raghu,
Sorry , There is no DMA drivers with ETC/eTIMER
and we have no example with
SPC560P40L1
You can create your own configuration by API
You can use DMA_MUX Channel 16,17,18,19 for eTimer
SPC5_ADC0_DMA_DEV_ID ==> Channel 16
Do not hesitate to update the file icu_lld.c to follow the ADC Example below (by the patch mode)
/**
* @brief DMA configuration for ADC0.
*/
#if SPC5_ADC_USE_ADC0 || defined(__DOXYGEN__)
#if (SPC5_ADC_DMA_MODE == SPC5_ADC_DMA_ON) || defined(__DOXYGEN__)
static const edma_channel_config_t adc_adc0_dma_config = {
SPC5_ADC_ADC0_DMA_CH_ID,
SPC5_ADC0_DMA_DEV_ID,
SPC5_ADC_ADC0_DMA_IRQ_PRIO,
adc_serve_adc_irq, adc_serve_dma_error_irq, &ADCD1
};
#endif /* SPC5_ADC_DMA_MODE */
#endif /* SPC5_ADC_USE_ADC0 */�?�?�?�?�?�?�?�?�?�?�?�?�?
For init,
adcp->adc_dma_channel = edmaChannelAllocate(&adc_adc0_dma_config);�?
For Start,
#if SPC5_ADC_DMA_MODE == SPC5_ADC_DMA_ON
/* Starting DMA channels.*/
edmaChannelStart(adcp->adc_dma_channel);
#endif /* SPC5_ADC_DMA_MODE */�?�?�?�?
Best regards
Erwan
2017-10-04 04:27 PM
Hi Erwan
Thanks for the reply. But what about switching the GPIO using the DMA (DMA transfers data between memory and GPIO). Is that possible?
I do not think it is from the following line in the manual,
DMA transfers possible between system memories, DSPIs, ADC, FlexPWM, eTimer and CTU
but just wanted to confirm with you.
In which case maybe I can use one of the DSPI pins to switch following a memory map? So using the DSPI pins to output a certain data from memory and make it function like a GPIO.
I still need the DMA transfer to start after an interrupt from eTimer ICU.
Do you have any suggestions that could make this easier or am I on the right path?
2017-10-05 02:27 AM
Hello Raghu ,
for GPIO Ports, you have to use the Onchip Memory
'Using the GPIO Ports to drive or sample waveforms. By configuring the DMA to transfer
data to one or more GPIO ports, it is possible to create complex waveforms usingtabular data stored in on-chip memory. Conversely, using the DMA to periodicallytransfer data from one or more GPIO ports, it is possible to sample complex waveformsand store the results in tabular form in on-chip memory.'Use eTimer /CTU/DSPI (Cf Table 246).
if you enable DMA Transfer for eTimer ICU, the DMA Interrupt will be handled not the ICU Interrupt.
Check DMA MUX (Chapter 20)
For RLA & HAL Drivers , there are a nice example how to configure the DMA Channel.
Best regards
Erwan
2017-10-05 06:41 PM
Hi Erwan
I looked at the section you referenced and it mentions to use a PIT to configure a periodic SPI or GPIO transfer.
But in the PIT section, there is no information on how to setup trigger for DMA? Is it automatic i.e as soon as I enable the PIT, will it generate a continuous trigger depending on its period? Do I need to enable the PIT interrupt?
'Besides the normal routing functionality, the first four channels of the DMA Mux provide a special periodic triggering capability that can be used to provide an automatic mechanism to transmit bytes, frames or packets at fixed intervals without the need for processor intervention. The trigger is generated by the Periodic Interrupt Timer (PIT); as such, the configuration of the periodic triggering interval is done via configuration registers in the PIT. Please refer to Chapter 31: Periodic Interrupt Timer (PIT) for more information on this topic'
2017-10-06 01:56 AM
Hello Raghu ,
the PIT is used only for the DMA triggering.
First , configure 1 PIT channel (#1 , #2, #3 or #4) with your timer settings
Second, you have to use the corresponding DMA Channel #0 to DMA Channel #3 in settings the good source..
Best regards
Erwan
2017-10-10 04:48 PM
Hi Erwan
I have the following configuration set for using DSPI_1 TX which is source 3 for my device for using DMA with PIT
1. Configure DSPI1 TX1 for Ch 2
2. Configure PIT CH 3. PIT timer is set for ~15KHz
3. Write 0xC3 to CH2CONFIG register.
But I am confused about how to implement the spi_lld_send(&SPID2, 256, buff) command for periodic data to be sent. Do I have to implement this in a for loop. Right now I do not see any data being sent on the TX pin. I have tried both in an infinite for loop and outside of it with the same result.
I have confirmed the PIT working with a GPIO pin toggle in a callaback.
I have also confirmed the DMA SPI transfer just by itself. If I set CH2CONFIG to 0x83, and implement spi_lld_send(&SPID2, 256, buff) in a infinite for loop, I can see output on TX pin continuously.
but PIT with DSPI using DMA is not working. My final goal is to send SPI data at 15KHz timing and change the SPI data every now and then. Would appreciate any feedback...
2017-10-18 06:19 PM
Hi Erwan
Any chance you have an update on my question?
-Thanks
2017-10-19 04:15 AM
Hello Raghu ,
No loop is required.you should configure your edma descriptors in order to map with DSPI.PUSHR in your case
(Cf below as example)
// Transfer Control Descriptor for DSPI C TFFF
EDMA.TCD[2].SADDR = (vuint32_t) &DSPI_TXQUEUE[0]; // Start Address
EDMA.TCD[2].DADDR = DSPIPUSHR; // Destination address
EDMA.TCD[2].SMOD = 0x00; // Source address modulo
EDMA.TCD[2].DMOD = 0x00; // Destination address modulo
EDMA.TCD[2].DSIZE = 0x02; // Destination transfer size : 32 Bits
EDMA.TCD[2].SSIZE = 0x02; // Source transfer size : 32 Bits
EDMA.TCD[2].SOFF = 0x4; // Signed source address offset
EDMA.TCD[2].NBYTES = 0x4; // Inner 'minor' byte count
EDMA.TCD[2].SLAST = 0; // last Signed source address adjust
EDMA.TCD[2].DOFF = 0x0; // Signed destination address offset
EDMA.TCD[2].DLAST_SGA = 0x0; // Signed destination address adjust
EDMA.TCD[2].BITERE_LINK = 0x0; // //Channel-to-channel Linking on Minor Loop Complete
EDMA.TCD[2].BITER = 0x1; // begining 'major' iteration count
EDMA.TCD[2].CITERE_LINK = 0x0; // Channel-to-channel Linking on Minor Loop Complete
EDMA.TCD[2].CITER=0x1; // Current “major�? iteration count Disabled
EDMA.TCD[2].BWC = 0x00; // Bandwidth control : No DMA Stalls
EDMA.TCD[2].MAJORLINKCH = 0x00; // Major Channel number
EDMA.TCD[2].MAJORE_LINK = 0x0; // Major Channel Link : Disabled
EDMA.TCD[2].DONE = 0x00; // Channel Done
EDMA.TCD[2].ACTIVE = 0x00; // Channel ACtive
EDMA.TCD[2].E_SG = 0x0; // Enable Scatter/Gather : Disabled
EDMA.TCD[2].D_REQ = 0x0; // Do NOT disable TCD When done
EDMA.TCD[2].INT_HALF = 0x0; // Interrupt on minor loop count
EDMA.TCD[2].INT_MAJ = 0x0; // Interrupt on major loop completion : Disabled
EDMA.TCD[2].START = 0x00; // Explicit Channel Start bit�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
in IRQ #13 for Channel 2 , you can prepare in dma done in order to prepare the next frames to send.
Best regards
Erwan