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.
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...
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......
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.
@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.
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 :)
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?).
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?
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.
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.
- FF to 101 transition, spurious 1FF read
- A7FF to A801, spurious A8FF read
- EDFF to EE00, spurious EEFF read
- 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?
CounterTest.cywrk.Archive01.zip 307.4 K
And here is the log...
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:
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.