9 Replies Latest reply on Jan 28, 2019 3:52 PM by MoTa_728816

    Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?

    LePo_1062026

      Hi,

       

      I've got a design where I'm using a DMA with a 16bit FF timer.  In the application, I'm reading the counter/capture register with the DMA and storing it to RAM.

      In this design, I configure 1 TD with a 2 byte transfer from the counter/capture register.  It's working.

       

      For reasons not stated here, I've considered changing the 16bit FF timer to a 16bit Basic_Counter component and placing 2 Status Registers connected to the counter's outputs.  However, if I use the DMA to transfer the contents of the Status Regs, I would have to implement 2 chained TDs in the same drq since there is not guarantee that the Status Reg addresses are contiguous.

       

      I leave it for the wisdom of the 'cloud' of forum users:  Which is 'best'?

       

      Note: This would apply to PSoC3, 4 or 5.

       

      Len

        • 1. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
          BoTa_264741

          Len,

          There is community custom component which accomplishes just that, FIFOin by Brad Budlong (AKA "PSoC Sensei"). His blog is no longer available, but the component has been updated for PSoC5LP and can be found here:

          Re: FIFO to sample 8 or 16 bitParallel Inputs

          /odissey1

           

          Example of Counter to FIFoin (8-bit mode). Use 16-bit FIFOin mode (2x8-bit bus) for 2 counters

          buffer_img.PNG

          • 2. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
            BoTa_264741

            Len,

            Attached is example project showing FIFOin in 16-bit (2x8) mode with DMA to RAM tranfer and supplemental librraries

            FIFOin (PSoC Sensei), LPFilter, ADC_SAR_ex_lib and plotting software Multichart.

            /odissey1

             

            Fig.1. Triggered acquisition demo with h/w exponential filtering and decimation. When energized (CReg_Ready),

            system waits for h/w trigger, acquires 1000 data points in RAM and plots result using Multichart s/w.  

            ADC_LPF_FIFO_03_A.png

            Fig.2. Multichart output.

            ADC_LPF_FIFO_03_40kHz.PNG

            • 3. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
              MoTa_728816

              Hi,

               

              I tried playing with BasicCounter method a little,

              as BasicCounter does not have support of "Capture"

              and it does not seem to allow access the count register,

              some external circuit support will be required to "Capture" value.

              On top of that hassle there will be another party of additional circuit required to salvage the value into DMA

              such as couple of status registers as you mentioned.

               

              Please note that I'm not an "EXPERT" and this is my personal opinion,

              IMHO, I would go with 16bit Timer and single DMA transaction method if the resource allows.

              (But I wonder when we add bells and whistles described above, will it end up saving any resource or not?)

               

              moto

              • 4. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                LePo_1062026

                /odissey1,

                 

                Thanks.  You've included a lot of good stuff.  Very thorough!

                 

                Len

                • 5. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                  LePo_1062026

                  moto,

                   

                  Thank you for your reply.

                   

                  Am I saving resources?  Yes and No.  Just using different resources.  That's the reason for my question to the forum.

                   

                  Here's a schematic snippet of the circuit using the Basic_Counter and Status regs.  All I'm trying to do is count the number of Bus_Clk cycles for half the input clock (Clk_in).  I'm using the DMA to store the count value without using the CPU.  In a previous version, I had an ISR instead of the DMA.  It was OK except when Clk_in was too fast or the CPU had temporarily disabled interrupts or the ISR occurred when already in an interrupt.  By using the DMA, I'm almost guaranteed real-time capture of the counter even on very fast Clk_in.

                   

                  Len

                  • 6. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                    BoTa_264741

                    Len,

                    I agree with Motoo Tanaka that it is better to utilize a standard counter, if UDB resources available. Meanwhile, I modified your schematic to be used with interrupt (no DMA) by using Status register in latching "sticky" mode. I further used custom StatusReg32 instead of two standard Status registers. On the negative front of Clock_in, the SReg32_1 latches counter bus and rises interrupt. Once isr is processed, the counter is reset in code, making ready for next cycle.

                     

                    Custom components ControlReg32, StatusReg32 and Sync are included into the project.

                    KIT-059 annotation library can be found here: Annotation library for CY8CKIT-059 Prototyping Kit

                    /odissey1

                    P.S. Project updated, seems to work, needs testing.

                    BasicCounter_01a.png

                    • 7. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                      LePo_1062026

                      /odissey1,

                       

                      Thank for your input and your contributions to the PSoC-universe.

                       

                      My first invocation of this project used an ISR to get the count data. It 'worked' but it could be a bit CPU-intensive and/or deterministic.

                       

                      You see, I'm a HW guy who loves to code as well.  I love the Cypress PSoC infrastructure because it allows me to explore both worlds.  Whenever, I'm asked to use a different CPU, I'm always hamstrung by the limitations imposed by the silicon designers.  It usually requires me to perform herculean feats of SW coding to meet the performance requirements.  Usually I have to sacrifice performance for reliability.

                       

                      With the PSoC's versatile digital and analog configurability, I find I can enhance the performance significantly while maintaining reliability.

                       

                      Being the CPU performance geek that I am, I was trying to avoid the CPU overhead required to service every ISR of a potentially very fast counting period.  By placing the job of acquiring the counter value in DMA, I can off-load the task to HW.  Then the CPU will process the acquired data in a more non-deterministic means.

                       

                      I've got a bit more work on the underlying project but I plan to share it with the PSoC community.  Possibly others can find it beneficial.  Eventually, I hope it can be coded as a reusable component.    Another lesson.  Another day.

                       

                      Len

                      • 8. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                        RodolfoG_11

                        Really good stuff in this post. Just a comment. There is a way to force the placement of status registers in the UDBs, so you can keep them sequential and use a single TD.

                         

                        Refer to the PSoC Creator Help, Building a PSoC Creator Project > Control File > PSoC UDBs in PSoC Creator.

                         

                        In the control file, you can use something like this:

                        attribute placement_force of "STATUS_REGISTER_NAME_A" : label is "U(0,0)"

                        attribute placement_force of "STATUS_REGISTER_NAME_B" : label is "U(0,1)"

                        • 9. Re: Best Approach: Implement DMA on 16bit Timer or 2 Status Registers?
                          MoTa_728816

                          Hi,

                           

                          Since this is one of the most interesting thread I've ever encountered, I also have been trying to figure out my trick.

                          So far I came up with following schematic and verilog design, but I have not figure out how to clear some problems.

                           

                          (1) In the schematic, having Clock_In prevents me from generating application.

                              I wonder how I could place 2 clocks without error.

                             Or should I use a digital input and later connect a pin to the Clock_In?

                           

                          (2) If my verilog design works, I could start counting at the rising edge of Clock_In and stop the counter

                             and acquire the count value at the falling edge of Clock_In. Probably within the verilog it will work.

                             But I wonder if we can assign a value into "known" address or register from verilog.

                             If we can assign the acquired value into a register whose address is known,

                             then we can kick the DMA with the register address as the source address.

                           

                          (3) Then I dreamed that if we can assign a value to a memory location of know address,

                          which is actually the destination address of DMA, then we can save a DMA

                          and let the verilog design  do the task which DMA was supposed to perform.

                           

                          So would someone teach me

                          (Q1) How I can have two clocks into a verilog design?

                          (Q2) How I can specify a destination register whose address is known or specifiable within a  verilog design?

                          (Q3) How I can or can I assign a value from verilog design to a specific memory address?

                           

                          000-schematic.JPG

                           

                          bus_clk_count.v

                          =====================

                          `include "cypress.v"

                          //`#end` -- edit above this line, do not edit this line

                          // Generated on 01/25/2019 at 12:56

                          // Component: bus_clk_count

                          module bus_clk_count (

                          output reg [15:0] count,

                          output reg ready,

                          input   bus_clk,

                          input   clk_in,

                          input   reset

                          );

                           

                          //`#start body` -- edit after this line, do not edit this line

                              reg prev_clk_in ;

                              always @ (posedge reset or posedge bus_clk) begin

                                  if (reset == 1'b1) begin

                                      count <= 16'h0000 ;

                                      ready <= 1'b0 ;

                                      prev_clk_in <= 1'b0 ;

                                  end else begin // bus_clk edge

                                      if ({prev_clk_in, clk_in} == 2'b01) begin // rising edge of clk_in

                                          count <= 16'h0000 ;

                                          ready <= 1'b0 ;

                                      end else if ({prev_clk_in, clk_in} == 2'b10) begin // falling edge of clk_in

                                          ready <= 1'b1 ;

                                          count <= count ;

                                      end else begin

                                          count <= count + 16'h0001 ;

                                          ready <= 1'b0 ;

                                      end

                                      prev_clk_in <= clk_in ;

                                  end

                              end

                             

                          //`#end` -- edit above this line, do not edit this line

                          endmodule

                          //`#start footer` -- edit after this line, do not edit this line

                          //`#end` -- edit above this line, do not edit this line

                          =====================

                           

                          Attached is my study project, which is not capable of generating application because of clocks.

                          Meantime, I have not figured out how I could pass the count value to outside of verilog design world.

                           

                          moto