4 Replies Latest reply on Jan 9, 2018 1:23 AM by RoBO_1287886

    DMA settings


      Dear all,

      We are face to difficulties to configure correctly the DMA.


      Please find below the goal of DMA :

      The topDesign have 4 statusReg, the DMA will copy the statusReg to a tmp value on the SRAM of CortexM4.

      For each overflow, we want transfer the 4 status reg: so TDs (descriptor_X) must chained together.


      The DMA must generate a trig when the 4 status reg are transferred into "Tmp".

      This trig will be use later by an other DMA, but currently we are focus on the first DMA configuration.


      We have done the same flow with a PSoC5LP in the past, we try to perform the same with PSoC6.



        • 1. Re: DMA settings

          Hello Robin,


          Here are some comments on the project you attached -


          TopDesign DMA configuration:

          1. Trigger deactivation & retriggering (for all descriptors): Since your input trigger is not a DMA compliant trigger (i.e. the overflow output from the counter is most likely a pulse of about 1/4.8M width) there is a possibility of the DMA getting retriggered immediately is high with the "retrigger immediately option". You can choose either 16 or 4 SlowClk (50 MHz) cycles before triggering the DMA again from the overflow signal. This is not evident in the project but in the final project, you should keep this in mind
          2. Descriptor 4 configuration:
          • If you want to stop triggering Descriptor 1 again after completion of Descriptor_4, then select Trigger Input type as "An entire descriptor transfer per trigger" - this will only perform Descriptor_4 transfer from the trigger received from 3. You can alternately disable the channel on the completion of the descriptor as well and re-enable it in the interrupt.
          • Interrupt & Trigger output: Select to generate the interrupt on "Descriptor completion". As trigger on entire descriptor chain will never generate the trigger as you have tailed all the descriptors in a circular fashion (endless). Since (and I believe) your goal is to generate interrupt and next trigger on completion of Descriptor_4, this option should be selected.



          1. "tmp" in your code already is a pointer i.e. the reference to "tmp" in the code already means "&tmp[0]". So please remove the '&' before the tmp in the destination address config. Cy_DMA_Descriptor_SetDstAddress(&DMA_Reg2Tmp_Descriptor_1, tmp);  Cy_DMA_Descriptor_SetDstAddress(&DMA_Reg2Tmp_Descriptor_2, tmp+1); ... so on
          2. You are not initializing the descriptors, which is important as well (add the below code before setting the src/dst addresses)-


               Cy_DMA_Descriptor_Init(&DMA_Reg2Tmp_Descriptor_1, &DMA_Reg2Tmp_Descriptor_1_config);

              Cy_DMA_Descriptor_Init(&DMA_Reg2Tmp_Descriptor_2, &DMA_Reg2Tmp_Descriptor_2_config);

              Cy_DMA_Descriptor_Init(&DMA_Reg2Tmp_Descriptor_3, &DMA_Reg2Tmp_Descriptor_3_config);

              Cy_DMA_Descriptor_Init(&DMA_Reg2Tmp_Descriptor_4, &DMA_Reg2Tmp_Descriptor_4_config);


          And now with the above changes, the code seem to transfer the data from status regs to tmp.


          If you want interrupt, them map an ISR component to the DMA interrupt output in TopDesign. Initialize it in the main, map it to your ISR and enable DMA interrupt for operation.


          Let me know if this helps.



          Meenakshi Sundaram R

          1 of 1 people found this helpful
          • 2. Re: DMA settings

            Dear Meenakshi Sundaram R,


            Thank you, following your remarks the project has been updated and now step 1 works fine.

            So we add the next DMA to perform the next step of our goal.



            Currently, this second DMA saves into circular buffer : but only one shot because the latest descriptor disables the channel.

            Down counter values (byte 2 of tmp => 7F 7E ...) are saved in circular buffer :

            - without lost event

            - descriptors seems correctly chained.


            however, if we doesn't disable the channel (in last descriptor), the circular buffer doesn't works.

            In this case, we don't understand the list of value into the circular buffer.


            How configure correctly this second DMA?

            Please find in attachment the updated project with your remarks.




            • 3. Re: DMA settings

              Hello Robin,


              I took a look at the project and have some notes:



              1. Interrupts - Please configure the ISR components to be "Auto-select" rather than "Rising-edge". Since the interrupt is derived from another component and not generated by the ISR component itself, it is recommended to set it to "Auto-select"
              2. DMA 2 configuration - I see that your intention is 3x8 WORD circular buffer - i.e. your buffer size is 24 but you want a notification/interrupt every 8 element transfer (??). If yes, then you dont need 3 descriptors. All you need is one descriptor with 3 X loops - the reason why PSoC 6 has a 2D transfer mode. Since all the 3 8-byte transfers are similar (transfer one-element per transfer and interrupt every 8 element transfer), you can make use of a single desriptor. Only go for multiple descriptors, if you are dealing with different trigger input/output configurations.
              3. Another minor note on the DMA configuration - DMA 2's trigger input is from another DMA, which means the trigger is DMA compliant (unlike DMA 1's case). So you can very well use "Retrigger Immediately" option for the DMA 2's descriptor.



              1. Interrupt service routines: You need to clear the DMA channel's interrupt as well: "Cy_DMA_Channel_ClearInterrupt(DMA_Tmp2CircBuf_DW__BLOCK_HW, DMA_Tmp2CircBuf_DW__CHANNEL_NUMBER);"
              2. The DMA channel/descriptor Init does not enable the channel interrupts, you need to manually enable them for the code to enter generate the interrupt and service it - call this before enabling the channel: Cy_DMA_Channel_SetInterruptMask(DMA_Tmp2CircBuf_DW__BLOCK_HW, DMA_Tmp2CircBuf_DW__CHANNEL_NUMBER, CY_DMA_INTR_MASK);


              With the above the code should function properly.


              Now to why keeping the channel "Enabled" causes an issue - You should note that while debugging, DMA operation is happening in the background i.e. even when CPU is halted DMA keeps transferring as long as it is enabled and configured to transfer stuffs (the case when you leave the channel enabled and chain the descriptors). As a result, when the debugger fetches the data from memory, there is a good chance that when the data is fetched it might be fetched at different instances and each instance might result in a different capture value (as DMA is constantly updating these values in memory). In order for the example to function as expected, you can disable the channel after the descriptor completion and re-enable it after servicing the ISR. i.e. in the "routine_Tmp2CircBuf" function, add "Cy_DMA_Channel_Enable(DMA_Tmp2CircBuf_DW__BLOCK_HW, DMA_Tmp2CircBuf_DW__CHANNEL_NUMBER);" - this enables the channel after the ISR is serviced. Now you can keep a breakpoint in the ISR and monitor the buffer properly.


              Let me know if this helps.



              Meenakshi Sundaram R

              2 of 2 people found this helpful
              • 4. Re: DMA settings

                Dear all,

                With yours contributions, the DMA principle (for our need) is validated by this small project.


                I add an overview of the TOPDesign to illustrate the project :

                our goal is the transfer with DMAs of values from topDesign to a circular buffer of cortexM4 core.


                ---- top design ------- // ---- cortexM4 ------

                event -> statusReg -> tmp -> circularBuffer[]



                it could be useful for other users  of PSoC6, so please find in attachment the archive of my project.