DMA to GPIO

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

 Hello,

   

Can DMA be setup between (FLASH / SRAM)  memory and GPIO?

   

My requirement is:

   

1K data is stored in memory (FLASH / SRAM)

   

Want to flush this data (8-bit wide) on 8-bit wide GPIO on some event. 

   

I am new to PSOC. Have gone though example aps of DMAs Mem2Mem, Mem2Peripheral, Peripheral2Peripheral.

   

Not able to relate my requirement of DMA to GPIO to these examples (if architecture allows to do so)

   

 

   

Manish

0 Likes
16 Replies
Anonymous
Not applicable

 Hi,

   

Yes it is possible to do this.

   
        
  • Assume the data being sent is 8 bit wide. Place a Control Register which is available under Digital --> Register folder in the Component Catalog. Configure it for 8 bits.
  •     
  • Connect 8 Pins(GPIOS) to the control register and configure the Pins for Strong drive mode.
  •     
  • Configure a DMA with the source address as SRAM where your data is loacted and destination as the Control Register.
  •     
  • The DMA transfer can be triggered using the DRQ terminal available on the DMA component. With the help of DRQ you can control the rate at which data is transferred.
  •    
       

Hope this helps.

   

-Udayan

0 Likes
Anonymous
Not applicable

 See the image available     here.

0 Likes
Anonymous
Not applicable

 Thanks Udayan for you reply.

   

I was not able to figure-out what should be the  "destinatin addrress" for DMA!

   

I will try the "control register" method which you have mentioned.

   

But wondering, I will need an API to transfer data from control register to port.

   

something like: Pin_1_Write( ControlReg_Read() )

   

This will "cost" me some CPU cycles and I might not get data "flushed-out" on port on every clock as one would expect in DMA.

   

The purpose of using DMA here is, downstream device-FPGA connected to PSOC port needs 1Kbytes data clock-by-clock once DMA is called. I believe there's  way to take clock out on PSOC port and connect it to downstram device. 

   

So the clock may be contineous, but data transiotions to occur only when DMA is called due to certain events in PSOC and downstream devices get 1K bytes of data for 1K clocks thereafter. 

   

Again, pardon my PSOC knowledge! - Is this possible architecture-wise?

   

Manish 

0 Likes
Anonymous
Not applicable

Hi,

   
        
  • It is not necessary to perform a Control Register to Pin Write operation. The output terminals of the Control register(which in this case is connected to Pins - GPIO) gets updated as soon as the DMA writes to the Control Register. Hence you will not be losing any clock cycle.
  •     
  • Yes it is possible to bring out a clock signal on one of the PSoC pins. Drag drop a clock component available in the Sytem Folder of Component Catalog. Connect it to a Digital Pin with Strong drive mode. See this      image.
  •     
  • The clock speed can be set to a desired value as shown      here.
  •    
   

 

   

-Udayan

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

 Hi Udayan,

   

I tried the DMA with ControlReg. It worked for me. 

   

I have also sent system clock - 24MHz  out on another single-bit port.

   

I have a PSOC board, I probbed the pins on Oscilloscope. 

   

The pattern which I had loeaded was 64 samples of 0xaa, 0x55, 0xaa, 0x55 ...........

   

As a result, I got a square wave output at POSOC pin. 

   

But its period is a concern. For every clock of 24MHz  i should get fresh data sample, as result of DMA. 

   

But thats not happening. A sample gets updated after 2 clocks. 

   

I have attacghed waveform saved from Oscilloscope.

   

BLUE signal is clock 

   

Yellow signal is bit-0 of 8-bit data bus taken out of MEMORY-->DMA--ControlReg-->Port

   

Whats' wrong in this?

   

Beow is my main.c

   

---------------------------------------main.c---------------------------

   

   

#include <device.h>

   

#define BUFFER_SIZE 64

   

#define TRUE 1

   

#define FALSE 0

   

uint8 Finished = 0; 

   

/* Variable to store the status of DMA execution */

   

 /* The buffer that should be copied to RAM.  */

   

CYCODE const uint8 SrcBuffer[BUFFER_SIZE] =

   

{   

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55, 

   

    0xaa, 0x55, 0xaa, 0x55

   

}; 

   

 

   

CY_ISR(DmaDone)

   

{

   

Finished = 1;

   

}

   

 

   

void main()

   

{

   

uint8 MyTD;

   

uint8 MyChannel;

   

 

   

LCD_Display_Start();

   

ISR_DMATransfer_Start();

   

/* Perform dma in one burst.*/

   

#if (defined(__C51__))

   

/* PSoC 3 */

   

    #define DMA_SRC_BASE (CYDEV_FLS_BASE)

   

    #define DMA_DST_BASE (Control_Reg_1_ctrl_reg__CONTROL_REG)

   

MyChannel = DMA_1_DmaInitialize (

   

0,

   

0, /* Automatically request carry out bursts.*/

   

HI16(DMA_SRC_BASE), /* upper address bits are zero. */

   

HI16(Control_Reg_1_ctrl_reg__CONTROL_REG)); /* upper address bits are zero. ????? */

   

#else

   

/* PSoC 5 */

   

    #define DMA_SRC_BASE (CYDEV_FLASH_BASE)

   

    #define DMA_DST_BASE (Control_Reg_1_ctrl_reg__CONTROL_REG)

   

MyChannel = DMA_1_DmaInitialize (

   

0,

   

      0,

   

HI16(DMA_SRC_BASE), /* upper address bits are zero. */

   

      HI16(Control_Reg_1_ctrl_reg__CONTROL_REG) /*///// ????????????*/

   

);

   

#endif

   

 

   

/* Get a Transaction Descriptor. */

   

MyTD = CyDmaTdAllocate();

   

if(MyTD == DMA_INVALID_TD)

   

{

   

/* Error Condition. */

   

LCD_Display_Position(0,0);

   

LCD_Display_PrintString("INIT NOT DONE");

   

while(1)

   

{

   

/* Wait in an indefinite loop as the initialization could not be completed */

   

;

   

}

   

}

   

/* Setup a TD. */

   

/* Set TD to transfer 100 bytes with no next TD, */

   

CyDmaTdSetConfiguration (

   

MyTD,

   

BUFFER_SIZE,

   

DMA_INVALID_TD,

   

TD_INC_SRC_ADR | DMA_1__TD_TERMOUT_EN

   

);

   

 

   

/* Copy from SrcBuffer to DesBuffer */

   

CyDmaTdSetAddress (

   

MyTD,

   

      (uint16)SrcBuffer,

   

      (uint16)Control_Reg_1_ctrl_reg__CONTROL_REG //// ??????

   

);

   

 

   

/* Associate the TD with the channel. */

   

CyDmaChSetInitialTd(MyChannel, MyTD);

   

 

   

/* Setup the Interrupt connected to the nrq terminal. */

   

isr_1_SetVector(DmaDone);

   

isr_1_SetPriority(7);

   

isr_1_Enable();

   

   

/* Enable the channel. */

   

/* PreserveTds is set to 0 as the TD gets executed only once. */

   

//MYR CyDmaChEnable(MyChannel, 0);

   

CyDmaChEnable(MyChannel, TRUE); // 

   

 

   

/* Request DMA action. */

   

CyDmaChSetRequest(MyChannel, CPU_REQ);

   

/* Wait for the interrupt to signal completion. */

   

while(!Finished)

   

;

   

/* We are done with the DMA and Interrupt components. */

   

isr_1_Disable();

   

DMA_1_DmaRelease();

   

while(1);

   

 

   

}

   

   

/* [] END OF FILE */

   
     ----------------------------------------------------------------------------------------------------------------   
0 Likes
Anonymous
Not applicable

Hi,

   

I will work on this and get back to you.

   

-Udayan

0 Likes
Anonymous
Not applicable

 Hi Manish,

   

Can you archive and attach your project so that i can look in to it. I tried replicating your design. But looks like there is one ISR routine ISR_DMATransfer_Start which you have used. Can you add that part of code ?

   

-Udayan

0 Likes
Anonymous
Not applicable

 Hi Udayan,

   

My code is  the extract from different DMA example codes available on Cypress docs.

   

There's nothing much being done in ISR.

   

I have attached the archive here. 

   

Thanks for your continued efforts to solve my problem.

   

 

   

Manish

0 Likes
Anonymous
Not applicable

 For some reason, the archive didn't go through.

   

Trying to send it again ...

0 Likes
Anonymous
Not applicable

 Hi, 

   

Looks there's some problem on uploading project archive as size being ~2MB

   

Hence now uploading a small zip file (GenFiles.zip) containing all "generated codes" and  the schematic view

   

I hope this time it goes through!

   

 

   

Manish 

0 Likes
Anonymous
Not applicable

Hi Manish,

   

Can you e-mail the same to uday@cypress.com

0 Likes
Anonymous
Not applicable

Hi,

   

Are you testing on this on PSoC3 device or PSoC5? Which Silicon revision are you using, ES2/ES3?

0 Likes
Anonymous
Not applicable

 Hi Uday,

   

I am using PSOC5 

   

The kit I am using is: CY8CKIT-001 PSoC® Development Kit   [http://www.cypress.com/?rID=37464]

   

 

   

The PSOC chip is: CY8C5588AXI-060ES1

   

 

   

Manish

0 Likes
Anonymous
Not applicable

Uday,

   

I need the reverse of this and was just playing around with PSOC Creator. So I can use a status register in sticky mode and then declare the clock input to latch the data, correct?

   

My problem is that, how do I know when the DMA has read the status register so I can send and ACK back to the device sending the data so it knows it can send more data???

   

Thanks

   

Gordon

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

One thing I noticed about your code is that the base address for the control register is set wrong. It should be like (copy from my own code):

   

#define DMA_DIG_SRC_BASE (CYDEV_PERIPH_BASE)
Chan = DMA_DIG_DmaInitialize(DMA_DIG_BYTES_PER_BURST, DMA_DIG_REQUEST_PER_BURST,
        HI16(DMA_DIG_SRC_BASE), HI16(DMA_DIG_DST_BASE));
 

   

Your code used HI16(ControlReg), which is maybe wrong for PSoC5 (for PSoC3 I think it still might be correct).

   

 

   

Did you look at your DMA priority levels? If your DMA has a priority other than 0 or 1, it gets only 50% of bus bandwidth (or even less).

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

@Wavelength: no, sticky mode would be wrong. In this mode, when an input goes high than the registeres marks it as high - even when it goes low afterwards. I think you want to look a the DFlip Flop. It can be used with a 8bit bus width, and can be used to capture the input state as you want.

   

If you have an external request, I think a simple state machine built with a LUT would be enough.

0 Likes