13 Replies Latest reply on Jun 7, 2012 4:02 AM by gautam.das.g

    UDB to VDAC DMA transfer

    meenakshi.s

      Hi,

         

      I am developing a simple application where I have a counter design in UDB. The counter value is written into a status register.

         

      I have a DMA which is triggered by CPU_REQ , which transfers the 8 bit counter value to the VDAC. The output  at the VDAC  should be  a saw tooth wave. However I am not gettin the same. When I use a Timer to trigger the DMA req as well as the counter, I am able to get the sawtooth wave. Could anybody please help me with this. Following is my main.c file

         

       

         

      #include <device.h>

      void main()
      {    uint8 channel;
           uint8 td;

        

           
              #if (defined(__C51__))             
              //  channel = DMA_DmaInitialize(1, 1, 0, 0);
                channel = DMA_DmaInitialize(0, 0, 0, 0);
             #else
               // channel = DMA_DmaInitialize(1, 1, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(VDAC8_viDAC8__D) );
            channel = DMA_DmaInitialize(0, 0, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(VDAC8_viDAC8__D) );
             #endif 

          while(1){       
                  td=CyDmaTdAllocate();
              if(td!=DMA_INVALID_TD)
                break;
                } 
             CyDmaTdSetConfiguration(td, 1, td,0 );
             CyDmaTdSetAddress(td, LO16((uint32)Status_Reg_sts_reg__STATUS_REG), LO16((uint32)VDAC8_viDAC8__D) );      
             CyDmaChSetInitialTd(channel, td);                    

             CyDmaChPriority(channel,0);
             CyDmaChEnable(channel, 1);
             CyDmaChSetRequest(channel, CPU_REQ);
             Timer_Start();   
           VDAC8_Start();
          
          for(;;)
          {
      //     VDAC8_SetValue(Status_Reg_Read());
              /* Place your application code here. */
          }

         

      }

         

       

         

      Regards

         

      meenz

        • 1. Re: UDB to VDAC DMA transfer
          gautam.das.g

          Hey Meenz, are you using UDB based Counter or built a Custom Counter component using component creation tool?

          • 2. Re: UDB to VDAC DMA transfer
            meenakshi.s

            Hi dasg

               

            I have implemented the counter in UDB. It was a simple experiment to experiment the access of UDB via DMA

               

            I am attaching the archived project . Could you please tell me if I have to make any specific DMA setiings

               

             

               

            Regards

               

            meenz

            • 3. Re: UDB to VDAC DMA transfer
              meenakshi.s

              Also, I am attaching the project with Timer generating the request.

                 

               

                 

              Regards

                 

              meenz

              • 4. Re: UDB to VDAC DMA transfer
                udayan.umapathi
                      
                • When you trigger the DMA and the counter using same clock(in this case, a Timer), DMA and the counter operates at the rate determined by input clock. Hence every incremental count from the counter is effectively transferred by DMA. DMA takes only one BUS CLOCK cycle. 
                •    
                   

                 

                   
                      
                • However, when the DMA is trigger in CPU, you might be triggering it continuously and each transfer finishes in one BUS Clock period. The counter increments at the rate determined by the Timer. Hence the values transferred from the status register to DAC will be irregular. After every CPU trigger it might be necessary to wait until the counter has incermented and then move on to the next step.
                •    
                   

                I hope this helps !

                • 5. Re: UDB to VDAC DMA transfer
                  meenakshi.s

                  Hi U2,

                     

                  Thanks for the quick response. However I have one doubt. When running DMA in CPU mode, The counter is incremented continuously at bus clock. The Timer dependency does not exist for both DMA and the counter. In such a scenario I expect that every BUS clock, my counter value is incremented and the DMA transfers this value to the DAC. However, I am not getting any output at the DAC other than a DC level.

                     

                   

                     

                  Regards

                     

                  Meenz

                  • 6. Re: UDB to VDAC DMA transfer
                    udayan.umapathi

                    Couple of observations

                       
                          
                    1. VDAC Configuration: The VDAC_Speed is set to Slow, hence settling time is higher, you might want to change it to fast to improve settling time at the output. 
                    2.     
                    3. Output Range in your project is set to 0-4V. In this case the maximum updaterate of VDAC component is 250Ksps. This will be the limit on the output update rate. So even if your DMA is capable of transferring the data at Bus Clock(24 Mhz) DAC is not capable of updating. Reduce the output range to 0-1V to get a output rate of 1MSPS(4X of 0-4V range ).
                    4.    
                       

                    DMA Configuration:

                       
                          
                    1. In your project if you intend to perform CPU trigger, the parameter of interest is the REQUEST_PER_BURST parameter in the API, DMA_DmaInitialize(). If this parameter is set to 1, it is required to provide a CPU request for every transfer. Hence in your project since CyDmaChSetRequest(channel, CPU_REQ) is called only once, only first transfer would occur. If the parameter REQUEST_PER_BURST is set to zero then the DMA will transfer number of bytes as specified by TD(In your case it is 1). Hence you would get a DC value as seen by you.
                    2.     
                    3. DMA takes 6 cycles for transferring data if the REQUEST_PER_BURST parameter is set to 1. Be it CPU or External trigger given to DRQ terminal it requires 6 cycles for the DMA to fetch address from TD and complete the transfer. However if this parameter is set to zero, only the first byte transfer will take 6 cycles. Every other transfer will take 1 cycle.
                    4.    
                       

                    I hope these things should get you going. 

                    • 7. Re: UDB to VDAC DMA transfer
                      meenakshi.s

                      Hi U2,

                         

                      Thanksa lot for  your response. In my project I required that the td of length 1 byte be executed continuously. So the REQUEST_PER_BURST was set to '0' as mentioned by you.  In addition to that  I made one more change. I set the TD_AUTO_EXEC_NEXT in CyDmaTdSetConfiguration(). With this setting I was able to get the expected output.

                         

                      Thanks a lot for your help

                         

                      Regards

                         

                      meenz

                      • 8. Re: UDB to VDAC DMA transfer
                        meenakshi.s

                        Hi,

                           

                        As an add on to the previous experiment, instead of output to VDAC, I want to read back the counter value through UART. So basically the flow would be Counter->DMA->Buffer After DMA transfer is complete,read buffer data through UART.

                           

                        What is happening is that in the read back data, the count value increases in steps of 4/5 instead of continuously increasing. Does each DMA operation take 5 cycles for burst read? As per my understanding from previous posts, after the initial latency, I should expect a new data every cycle when the REQUEST_PER_BURST is set to '0'. following are the DMA settings.

                           

                        uint8 buffer[4096];

                           

                         /// Burst count is 1 ; After the initial CPU request, execute all other bursts continuously;

                           

                          #if (defined(__C51__))             
                                  channel = DMA_DmaInitialize(1, 0, 0, 0);
                            #else
                              channel = DMA_DmaInitialize(1, 0, HI16(Status_Reg_sts_reg__STATUS_REG), HI16(buffer) );
                             #endif 
                        ////// Allocate TD
                            while(1){       
                                    td=CyDmaTdAllocate();
                                if(td!=DMA_INVALID_TD)
                                  break;
                                  } 
                        /// Execute TD and stop. Increment only destination addr     
                               CyDmaTdSetConfiguration(td, 4095, DMA_INVALID_TD,(TD_INC_DST_ADR) );

                               CyDmaTdSetAddress(td, LO16((uint32)Status_Reg_sts_reg__STATUS_REG), LO16((uint32)buffer) );      
                               CyDmaChSetInitialTd(channel, td);                    
                               CyDmaChPriority(channel,0);
                               CyDmaChEnable(channel, 1);

                           

                        /// Start DMA
                               CyDmaChSetRequest(channel, CPU_REQ);

                           

                         

                           

                        Regards

                           

                        meenz

                        • 9. Re: UDB to VDAC DMA transfer
                          udayan.umapathi

                          Hi Meenz,

                             

                          In your project since the burst count is set to 1, the DMA chain terminates after one transfer. As a result the entire TD configuration needs to be reloaded after one transfer and everytime. This will eat up some time. Increase the Burst count to maximum of say 127(maximum allowed) to avoid this delay.

                          • 10. Re: UDB to VDAC DMA transfer
                            bandia.ebk

                            hi,
                            I need urgent help to implement a UDB or a
                            documented example of implementation in UDB
                            thank you in advance.
                            bye

                            • 11. Re: UDB to VDAC DMA transfer
                              bandia.ebk

                              Hi Meenz

                                 

                              I need urgent help to implement a UDB or a documented example of implementation in UDB
                              best regards.
                              bye

                                 

                              Bonjour l'ami

                              J'ai besoin d'aide pour comprendre comment implémenter un UDB block reconfigurable de CYpress avec un PSOC5

                              Merci d'avance.

                              Cordialement

                                 

                              EBK

                              • 12. Re: UDB to VDAC DMA transfer
                                loren.snyder

                                U2 or others:

                                   

                                What is the significance of setting Request per burst to 0? Does this make the DMA operate continuously? What if the number were greater than 1, would you have to perform more than one request to get the DMA to respond? Thanks.

                                • 13. Re: UDB to VDAC DMA transfer
                                  gautam.das.g

                                  Hi porcine_aviator,

                                     

                                   

                                     

                                  The Request Per Byte should always be either a 0 or 1.

                                     

                                  If the Request per Burst is set to 0, then all the subsequest bursts after the first burst will be automatically requested and carried out.

                                     

                                   

                                     

                                  If the Request per Burst is 1, then all the subsequent bursts after the first burst must also be individually requested.

                                     

                                   

                                     

                                  Regarding your question about using a value other than 0 and 1, it is not advisable to do it. In the API implementation, the "RequestPerBurst" value is ANDed with 0x01 and left shifted 7 times. Hence, the value will be sent to MSB which will determine whether Request per Burst is enabled or not.

                                     

                                  Hence, if you use an even number (with LSB = 0), then it is equivalent to giving Request per Burst as 0. If you use an odd number (with LSB = 1), then it is equivalent to giving Request Per Burst as 1.

                                     

                                   

                                     

                                  Hope this helps.