DMA triggered by GPIO (KDS,PE)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA triggered by GPIO (KDS,PE)

1,327 Views
valeremar
Contributor I

Hello,

I am using KDS with Processor Expert KSDK-1.3.0 and a FRDM-KL26z board for test.

I am trying to set up a DMA Transfer from memory to memory triggered by a GPIO (PTC9).

I can make a DMA transfer from memory to memory with success as explained in the API Reference manual. OK

I can setup as well with success an interrupt on a GPIO.OK

I cannot make a DMA transfer from memory to memory triggered by a GPIO. Symptoms are : "nothing happens" (stuck in the while loop).

Attached are my PE settings.

For the DMA memory to memory transfer , I have  implemented in main.c

  1. Initialize the DMA module: dma_init().
  2. Request a DMA channel: dma_request_channel().
  3. Configure the TCD: dma_config_transfer().
  4. Register callback function: dma_register_callback().
  5. Start the DMA channel: dma_start_channel().
  6. [OPTION] Stop the DMA channel: dma_stop_channel().
  7. Free the DMA channel: dma_free_channel().

For the DMA memory to memory transfer triggered by GPIO, I am really really confused!

Where does the GPIO DMA "Request" intervene?

Do I have to implement 1 to 4 and the GPIO starts at 5 -> does not seem to work though.

  1. Initialize the DMA module: dma_init().
  2. Request a DMA channel: dma_request_channel().
  3. Configure the TCD: dma_config_transfer().
  4. Register callback function: dma_register_callback().

while(1) {}

If the GPIO starts at 2 "request", where to implement 3 to 7? I could not read as well a line in the PE generated code for this configuration between DMA and GPIO. I am missing something right?

My question is similar to this post Trouble using DMA triggered by GPIO but the answers could not help much.

Thank you for any inputs !!!

0 Kudos
7 Replies

882 Views
valeremar
Contributor I

It looks like the bit ERQ of the DMA_DCR1 is not set right (0 instead of 1).

If I set it "manually" to 1 using DMA_DCR1|=0x40000000u; it works !

How to set it up right with fsl_dma? Should'nt it be set right with the function DMA_DRV_RequestChannel???

0 Kudos

882 Views
mjbcswitzerland
Specialist V

Hi

Check that DMA triggering is enable in PORTC_PCR9 - that is, set bit 0x200.

Regards

Mark

0 Kudos

882 Views
valeremar
Contributor I

Sorry I don't understand your point. PORTC_PCR9 is setup so:

PCR9.png

It seems OK.

Thank you very much for helping. I appreciate.

0 Kudos

882 Views
mjbcswitzerland
Specialist V

The DMA edge is set OK. PE is a bit confusing for me since it doesn't use easily understandable defines and I mis-read the setting.

I have no idea whether PE works for this configuration - it is just a case tool spitting out some prepared code based on your config - it may have done it before and work or it may have bugs. Basically it is best to use reference library code that is proven to compare with since you may need to debug PE generated code. Personally I don't like the case tools because they dumb-down the developer so that solving problems is something that they are then ill prepared to have to do. Understanding the workings usually makes for much faster and better solutions, even if it takes a bit of effort at the start.

Regards

Mark

0 Kudos

882 Views
valeremar
Contributor I

I have been trying all morning ... no success !

The code looks like this:

void DMA_callback(void *param, dma_channel_status_t chanStatus)

{
    OSA_SemaPost(&sema); }
  // Init DMA module.
  dma_state_t state;
  memset(&state, 0, sizeof(dma_state_t));
  DMA_DRV_Init(&state);
  // Create semaphore to synchronize dma transaction
  osa_status_t  syncStatus;
  OSA_SemaCreate(&sema, 0);
 //p365, p??
  //DMAMUX0_CHCFG1 = (DMAMUX0_CHCFG_SOURCE_PORTC | DMAMUX_CHCFG_ENBL); 
  DMAMUX0_CHCFG1|=0x33;
  DMAMUX0_CHCFG1|=0x80;
  PORTC_PCR9|=PORT_PCR_IRQC(0x02);      //Interrupt on falling edge 0010 p205 0x02
  
      uint32_t channel = 1;
      uint32_t i;
      // Fill zero to dest buffer
      for (i = 0; i < BUFFER_SIZE ; i ++)
      {
          destAddr[i] = 0;
      }
      //Possibly overwrite the register; SEE fsl_dma_request.h
      if (kDmaInvalidChannel == DMA_DRV_RequestChannel(channelID,kDmaRequestMux0PortC,channelstate))
      {
             PRINTF("\r\nCannot request channel for interrupt No. %d", channelID);
             DMA_DRV_Deinit();
       }
      debug_printf("\r\nRequested channel for PORTC ... ");
      //With/Without : does not change 
      //DMAMUX0_CHCFG1|=0x33; DMAMUX0_CHCFG1|=0x80;
      //PORTC_PCR9|=PORT_PCR_IRQC(0x02);
       if(kStatus_DMA_Success != DMA_DRV_ConfigTransfer(&dmatest_ChnState0,           \
                             kDmaMemoryToMemory,  \
                             TRANSFER_SIZE,       \
                             (uint32_t)srcAddr,   \
                             (uint32_t)destAddr,  \
                             BUFFER_SIZE)){
            debug_printf("\r\nERROR with DMA configuration");
       }
       // Add callback for dma handler
       DMA_DRV_RegisterCallback(&dmatest_ChnState0, DMA_callback, NULL);
      while(1) {
             PRINTF("\r\n Press to start transfer ...");
              // Wait until transfer is complete
              do
               {
                   syncStatus = OSA_SemaWait(&sema, OSA_WAIT_FOREVER);
               } while(syncStatus == kStatus_OSA_Idle);
          for (i = 0; i < BUFFER_SIZE; i ++)
               {
                    PRINTF(" %u", destAddr[i]);
               }
      }

The same version for DMA memory to memory works. Basically, the difference is in requesting the DMA
(kDmaRequestMux0PortC) and I have tried adding the low-level lines as suggested by Mark (although in my
understanding PE should care for this).

I have the additional PE components Init_GPIO, Init_DMAMUX, fsl_dma in my project. Definitely something I am missing ...

					
				
			
			
				
			
			
				
			
			
			
			
			
			
		
0 Kudos

882 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,

I was wondering if you can share the demo, then I can check the demo on my site.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

882 Views
mjbcswitzerland
Specialist V

Hi

To trigger DMA from a port you need to ensure that the port is configured to generate an interrupt on the required edge, but set the DMA mode bit so that it actually triggers a DMA transfer instead of the interrupt.

Then ensure that the DMA mux setting routes the trigger source to the DMA channel's trigger. For port C:

DMAMUX0_CHCFGn = (DMAMUX0_CHCFG_SOURCE_PORTC | DMAMUX_CHCFG_ENBL); // trigger DMA channel n on port C changes

That is (0x33 | 0x80), where n is 0..3 on the KL familiy parts with DMA controller.

Regards

Mark

0 Kudos