UDB Counter and counter register read operation

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

cross mob
Anonymous
Not applicable

Hi!

   

I am using a PSoC3 device where I placed a 16 bit UDB up/down counter, with count and direction HW inputs.

   

Period is 65534 (MAX). I am not using any HW output from this counter, but, while clock input is connected to bus clock, count input is connected XORed with value from input pin and a register bit used to change count sensitive edge (double sync on each pin, about 200-400Hz).

   

 

   

While counting, I am polling counter using Counter_ReadCounter() function.

   

From time to time, I am getting incorrect values from this function. This is one example of my output log from serial communication:

   

Polling counter in down count from 1823. Once near 769 (I can see the whole log sequence that counted correctly without issues), I get once 512, then back 741 on next poll, that happens after some time (without changing counter direction, the device is detecting condition and stopping operation due to unexpected count value, than is showing status).

   

This is just one example of what is happening, and it seems issue is quite random, but it is very hard to reproduce in my code.

   

At this point, my code is quite large; I should consider trying with a smaller example that aims to reproduce the issue, but first I am trying to ask if there is anything I am doing wrong or if I should use a different approach to read FIFO of UDB counter, or if there is any known issue related to this counter.

   

Best regards,

   

Stefano

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

It looks like you are capturing exact the same moment the lower half of the 16 bits underflow (when counting from 768 down to 767), and the lower half of the counter is read first (resulting in 0x00 still), and then the higher part is read (resulting in 0x02 already), so the register is read is 0x200 where it should have been 0x2ff.

   

I would not expect this to happen, since Counter_ReadCounter() first does a capture, and then return the results from the FIFO. Which version of Creator are you using, and which version of the counter component? The current data sheets starts at version 2.0 only, so maybe older versions have issues in this regard... (for V2.0 it is stated that the component has been reimplemented as synchronous counter).

   

Also note that (in V2.30) the maximum frequency for a 16bit-UDB-Counter is 33MHz.

0 Likes
Anonymous
Not applicable

Thanks for your reply.

   

As shown in about box, I am using PSoC Creator 2.2 Component pack 5. It should be the latest version.

   

Counter version, in Built-in tab of component, is 2.30.

   

Input count frequency is less than 500Hz, while clock input is 24Mhz.

   

If there is a chance that a glitch on count input might cause this behavoir to happen, I could add an external RC filter or a digital deglitch filter. But maybe there is a workaround (e.g. wait some clock cycles) to ensure that data is properly loaded in FIFO registers...

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Maybe I am missing something. Is the counter running continuously ?

   

 

   

Your polling is in effect a sampling gate, the poll not a sync event, and subject to ISR and

   

firmware activity on other HW, so reading counter would never produce random results ?

   

 

   

I must be missing something......

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

I am polling counter just in main application loop.

   

There is an ISR that reads these counter but, after reading, system is resetted. And this ISR is just called on power fail. This is not what happens.

   

I am reading a number of pulses from an external reed switch. These inpus are debounced by an R-C filter.

   

As I said, system is actually more complex than that. There is a serial communication service on UART port where an external device asks for incremental value of counter and this board replies to this request.

   

But, kept in mind that I am using 16 bytes FIFO buffers for UARTS (and thus there might be interrupts generated automatically by serial communication blocks), the whole communication service (read, detect command and reply) and the related operation of reading counter by software is done in the main application loop.

   

There shouldn't be other ISRs.

   

Counter is running continuously. I cannot stop it while reading value.

   

Most of the times reading counter works fine. This happens about once every, maybe, 100k times, as rule of thumb.

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

@dana the Counter_ReadCounter() method first executes a capture of the current counter value, and then reads the captured value.

   

So either during capture something goes wrong (because for a 16bit counter, 2 UDBs are used, and they need to capture at exactly the same moment). Or 2 reads are intermixed with each other which means that a capture gets executed the same moment when a read occurs.

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

What you could do to find possible reasons:

   
        
  • increase the frequency on the count input, and check whether this inceases the odds of the propblem happening (if yes, it looks like a glitch during capture)
  •     
  • use a fixed-function counter and check whether it happens there (only works when the count clock is derived from a PSoC clock)
  •     
  • in all places where the counter could get accesses (esp. ISRs), toggle a LED to see whether they really are not executed
  •    
   

Can you post your project here, so we can have a look into it?

   

I don't think it has to do with syncing the count input, so a glitch filter won't help (but you might test it nonetheless to be sure 🙂

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

After looking at the component sources, the verilog file and the datapath configuration (a good excuse to read up a little bit more about this stuff 🙂 it looks to me that the counter should work properly. The datapaths are properly chained together, and the transfer from the counter value (stored in the accumulator A0) to the FIFO should be atomic (since the code doing the capture accesses the LSB only). And I doubt the CPU is fast enough to execute the subsequent read of the FIFO registers faster than the UDBs transfer the values (or do you clock the CPU higher than 24MHz?).

0 Likes
Anonymous
Not applicable

Many thanks for your interest and your advices.

   

I'm sorry but I cannot post the full project here (it's not mine, it's for one of our customers). If I have time, I'll try to reproduce the issue on a smaller subset of the application. MASTER_CLOCK and BUS_CLOCK are both 24Mhz. There are no faster clocks.

   

In the mean time, I'll try (I don't like work-arounds) to add some trap points to these error conditions.

   

Just another question:

   

is it possible that a capture event is triggered during rollover? What happens if capture is triggered exactly the same clock edge that increases the less significant (FF) bits and causes rollover (+1 to the upper bits)? There is no chance that this could cause an unexpected behavior?

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

This scenario is exactly what I tried to describe above 🙂 (I just called it underflow instead of rollover). But since the counter should be synchronous (according to the description), and the capture event itself is atomic (at least according to the technical reference manual), it should not happen. But it is the best explanation I have...

   

When it happens more often with a higher count-frequency, it looks like this scenario. If it don't, the it is something else.

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

Here is my first attempt to replicate the bug in a more friendly environment.

   

I attached to this post system log and application code.

   

If I'm not doing anything wrong (and it happens since when changing from original code to this)

   

This is system setup:

   

1. An RX serial receiver is applied to RX_AUX_3

   

2. C1 and C2 inputs are used as counter inputs. Actually I am trying with a signal generator, 1kHz, square wave applied to C2.

   

3. I added debug traps to system log, and this is the result. Here there are some samples of these debug traps (number in HEX format)

   

4. There are interrupts used by debug UART still active. I'll try to use clock derived from system clock to counter input instead of external signal generator.

   

UP COUNTING

   
        
  • FF to 101 transition, spurious 1FF read
  •     
  • A7FF to A801, spurious A8FF read
  •     
  • EDFF to EE00, spurious EEFF read
  •    
   

DOWN COUNTING

   
        
  • C900 to C8FF, spurious C800
  •     
  • B800 to B7FF, read B700
  •     
  • 1700 to 16FF, read 1600
  •    
   

The strange thing is that this does not happen always while there is a lower byte underflow or overflow... Most of the times value is correct.

   

I hope I made supid mistakes, but it seems this is a more complex issue...

   

Do you see any issue in my code? Any idea?

0 Likes
Anonymous
Not applicable

And here is the log...

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable
0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

I suggest to open a support case. I cannot really see something wrong in your project or code.

   

My current guess is this one: Counter_ReadValue() first captures the current counter value, by executing this statement:

   

    (void)Counter_1_COUNTER_LSB;

   

This accesses the counters LSB, and the UDB is configured to  transfer its accumulator (which holds the counter value) to the FIFO (which acts as capture register). And since the 2 UDBs forming the counter are chained, the MSB is captured also.

   

But what happens is that the MSB is somehow captured late - in your log one can see that the MSB has been updated already while the LSB still has the old value. This happens when the capture is done in the same instant the rollover happens (because only then both UDBs are changed) So either the capture is not atomic, or the counter is not synchronous. Both are bugs in the component, I suppose.
 

0 Likes