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

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

cross mob
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

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

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

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

View solution in original post

9 Replies
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

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

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

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

/odissey1,

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

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

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

0 Likes

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.

pastedImage_0.png

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
lock attach
Attachments are accessible only for community members.

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

0 Likes

/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

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

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)"

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

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

0 Likes