I'm having a hard with K60 when i'm trying to use DMA to capture the data from PTB0-PTB7.
I wanted to use PTA27 as the trigger of the DMA transmit,and then the DMA controller copy the data from PTB0-PTB7 to the buffer.
I have read a lot of articles about how to configure the DMA,however,i just can't make it.
I almost get mad.
first of all ,i read the Kinetis Peripheral Module Quick Reference and K60 Sub-Family Reference Manual and decided to write my own code.
i found that it is very easy to configure DMA,and i did as it told me.the Configuration steps are as below:
1. Write the eDMA control register (only necessary if the configuration of another than
the default is required)
2. Configure channel priority registers in the DCHPRIn (if necessary)
3. Enable error interrupts using either the DMAEEI or DMASEEI register (if
necessary)
4. Write the transfer control descriptors for channels that will be used
5. Configure the appropriate peripheral module and configure the eDMA MUX to route
the activation signal to the appropriate channel
for 1: I checked the DMA_CR register and found that there is no need to change it.
for 2: since I only use one channel of DMA,the priority is not important,I left it in default configuration
for 3: OK ,I didn't know I would meet so many problems,I didn't enable any error interrupt .well,that is not a problem.I didn.t use it.
for 4:in this part ,I carefully checked all the TCD registers and write the one by one (except those i ever use)
here i copy my code bellow :
//write the TCD register
(DMA_BASE_PTR)->TCD[0].SADDR=0x400FF050;//am i right? the address of input data of PTB0 ?
(DMA_BASE_PTR)->TCD[0].SOFF=0x00;//always read the same address PTB0-PTB7,so the offset is 0
(DMA_BASE_PTR)->TCD[0].ATTR=0x00;//i don/t quite understand what is the Address Modulo,and i don't use it .
//and Source data transfer size is the same as the destination ,that is 8bit,
(DMA_BASE_PTR)->TCD[0].NBYTES_MLNO=0x01;//evey time only transmit one byte
(DMA_BASE_PTR)->TCD[0].SLAST=0x00;//because my sourse address will not change ,so the is nothing to adjust
(DMA_BASE_PTR)->TCD[0].DADDR=(uint32)(ImageBuf); //the destination address is a array imageBuff[320],so the address of the first byte is imageBuff,
(DMA_BASE_PTR)->TCD[0].DOFF=0x01;//when i finish copying one byte ,i should move to the next byte,
(DMA_BASE_PTR)->TCD[0].CITER_ELINKNO=320;//the majpr Iteration contains 320 times of single transmit.
(DMA_BASE_PTR)->TCD[0].DLAST_SGA=-320;//when finish the main cycle,we need to go back to the fist byte of our buffer,
(DMA_BASE_PTR)->TCD[0].BITER_ELINKNO=320; //related to CITER_ELINKNO,they must be the same
(DMA_BASE_PTR)->TCD[0].CSR=0x000B;//write the very important CSR register,disable elink,disable ESG,disable half-point interrupt,enable end-of-major loop interrput
for 5:i enable the PTA27,DMA_rising,and PTB0-PTB7 input ,pull-up,
then ,i almost forgot where i got the idea that i also should enable the clock that related .they are as followed:
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK; //
SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK; //
after this ,i got more information that i should also configure the DMAMUX,so i got the code bellow:
(DMAMUX_BASE_PTR)->CHCFG[0]=0xB1;//enable the DMA,PS:the slot is 49d,that is the GPIOB
after this ,no more register remains to be configure,then enable all that need to be enable:
(DMA_BASE_PTR)->CINT=0x00;//clear
(DMA_BASE_PTR)->CDNE=0x00;//clear
(DMA_BASE_PTR)->ERQ=0x00;//enable the DMA hardware request
OK,it seems i have write a lot .of course you needn't check line by line,that would be so boring
what i want to say most is that what on earth did i forget to configure?
the DMA is simply not woking at all.
i have tested that it can enter the external interrupt service,but it never go into the DMA interrupt service.My god!
Do you have some simple examples of how to use the DMA,just to read the GPIO data ,not working with the ADC or anything else.
Any help or information is of great value to me !
Dale Gong
解決済! 解決策の投稿を見る。
Please check attached example code which using GPIO pin trigger DMA transfer.
Wish it helps.
Best regards,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Ma Hui,
I test your code with cw105 but could not make it work.
wish olhase example where this the wrong configuration.
need a continuous GPIO DMA read (with FIFO buffer).
thanks,
Carlos.
Hi Carlos,
What kind of DAM application you want to use? DMA communication triggered by GPIO input or DMA transfer GPIO data register value to a varaible (RAM) ?
Best regards,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Ma,
my DMA is ( GPIO ---> RAM).
PE componet DMA, FIFO manegment ok,
your code source not interrupt (isr, not run ). modifier for DMA_CH10.
thanks,
Carlos.
Hi,
I tested K70 + DDR2 = ok it code.
void init_dma ( uint32_t dma_base ,volatile unsigned long dma_dest ){ <----- init or resete base
// Enable clock for DMAMUX and DMA
SIM_SCGC6 |= SIM_SCGC6_DMAMUX0_MASK;
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;
DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(0x35); // ( my case PTE ) ( creat uour PIN to clock_in
// Enable request signal for channel 0
DMA_ERQ |= DMA_ERQ_ERQ0_MASK; //
/* Set the Source Address*/
DMA_TCD0_SADDR = (uint32_t) &dma_source; //GPIOC_PDIR; // my case PORT_B 8bits
/* Destination address */
DMA_TCD0_DADDR = (uint32_t) &DDR2_BASE; // dma_dest. uour RAM and SRAM base
/* Source offset*/
DMA_TCD0_SOFF = 0; // off
/* Destination offset*/
DMA_TCD0_DOFF = 0; // off
// Set source and destination data transfer size
DMA_TCD0_ATTR = DMA_ATTR_SSIZE(0) | DMA_ATTR_DSIZE(0); //source and destination size 0 = 8 bits
// Number of bytes to be transfered in each service request of the channel
DMA_TCD0_NBYTES_MLNO = 1; // 1 byte
DMA_TCD0_CITER_ELINKNO = 1; //1 major loop
DMA_TCD0_BITER_ELINKNO = 1; //1 major loop
// Adjustment value used to restore the source and destiny address to the initial value
DMA_TCD0_SLAST = 0; // fixo
DMA_TCD0_DLASTSGA = 1; // += 1
DMA_TCD0_CSR = 0; //Never clear channel's ERQ bit
}
add in code, init PORT_n and PIN_trigger
it example,
1 clock = RAM[0] 8bits
2 clock = RAM[1] 8bits
3 clock = RAM[2] 8bits
Hi Carlos,
Is your code working?
Best regards,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Please check attached example code which using GPIO pin trigger DMA transfer.
Wish it helps.
Best regards,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I am also stucking configuring the dma to sample a gpio periodically.
In the code of Ma Hui, there is only one example on how to use the gpio as request source for dma and let the dma copy data from sram to PTOR register.
Copying data via dma from sram->ptor is no problem for me.
But now I want to use an Always-On request source for dma, periodically triggered by PIT to sample an GPIO, that is copying PTD->PDIR to a data array in sram.
My code is identically with the one of Dale Gong mujunzhishang, but I am using 0x400FF0D0 as source for the DMA (which is PTD input instead of PTB) - but after enabling the dma request, the controller runs into hardfault handler.
My controller type is K64.
Mod:
My code works now - I don't now why the controller ran into HardFault but now everything is good.
Had just one simple mistake: I wanted to use PIT0 as trigger for DMA Channel 2 but only PIT2 is available for this Channel. But this was not the reason for HardFault.
Thank you anyway
Thank you for answering my question,i will check your code ,if it works,i will click the correct button.
Thank you again!