PSoC 6 Measuring IRQ interval

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

cross mob
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,

One of my customer wants to measure time between external IRQ signal,

which is supposed to be about 1ms.

So I tried with the following schematic using CY8CKIT-062-BLE.

Note: Counter_2 is used to generate dummy IRQ signal generator.

011-schematic.JPG

And Tera Term output seems to be OK,

Note : I'm changing the interval by 1 in the firmware loop.

010-Tera-Term-log.JPG

But the customer is anxious if triggering both reload and capture with same edge could cause wrong sequence,

for example, if there is/are chance that the captured value is the reload(ed) value (aka 0).

IMHO, if TCPWM was designed in usual sync manner, 

the following two will take place at the same time,

so captured value won't be overwritten with the reload value.

(1) Counter Value -> Capture Value

(2) 0 -> Counter Value

 

Question: Is my assumption correct?

Or is/are there something I need to be aware of to do this measurement?

My test project is attached.

 

moto

 

0 Likes
1 Solution
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,

It's been a long (wrong?) day.

So I changed schematic something like

001-schematic.JPG

Pins

002-Pins.JPG

Somehow with my CY8CKIT-062-BLE, restore input did not seem to clear the counter.

So I added Timer_1_SetCounter(0) in the main loop

#include "project.h"
#include "stdio.h"
#include "tty_utils.h"

volatile int32_t sensor1_period = 0 ;
volatile int     sensor1_flag = 0 ;

void Pin_2_Write(int v)
{
    Cy_GPIO_Write(Pin_2_0_PORT, Pin_2_0_NUM, v) ;
}

void sensor_irq1_isr(void)
{
    int32_t source ;
    
    Pin_2_Write(1) ;
    sensor1_flag = 1 ;
    sensor1_period = Counter_1_GetCapture() ;
    source = Counter_1_GetInterruptStatus() ;
    Counter_1_ClearInterrupt(source) ;
}

void sensor_irq1_init(void)
{
    const cy_stc_sysint_t SysInt_1_cfg = {
        .intrsrc=(IRQn_Type)SysInt_1__INTC_NUMBER,
        .intrPriority = SysInt_1__INTC_CORTEXM4_PRIORITY
    } ;
    Cy_SysInt_Init(&SysInt_1_cfg, sensor_irq1_isr) ;
    NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc) ;
    NVIC_EnableIRQ((IRQn_Type)SysInt_1_cfg.intrSrc) ;
}

void init_hardware(void)
{
    __enable_irq(); /* Enable global interrupts. */    
    
    Pin_2_Write(0) ;
    
    tty_init() ;
    
    sensor_irq1_init() ;
    
}

int main(void)
{
    int32_t prev_period = 0 ;
    int32_t period = 0 ;
    int32_t delta = 0 ;
    int32_t test_period = 0 ;
    int32   count = 0 ;
    
    init_hardware() ;
    
    cls() ;
    
    splash("PSoC 6 Interval Timer Test") ;
    
    Counter_1_Start() ;

    for(;;)
    {
        if (sensor1_flag) {
            Pin_2_Write(0) ;
            Counter_1_SetCounter(0) ; // <=======
            period = sensor1_period ;
            sensor1_flag = 0 ;
            if (prev_period != period) {
                snprintf(str, STR_BUF_LEN, "Sensor1:%d\n\r", period) ;
                print(str) ;
           
                prev_period = period ;
            }
        }
    }
}

Now my PSoC 6 project can measure the interval of the negative pulse output of PSoC 4 project.

 

PSoC 4 (Signal Generator Project) Tera Term log

004-PSoC4_TeraTerm.JPG

PSoC 6 (Interval Measurement Program)

(Showing the last part of the previous PSoC 4 output, period = 2000 with 2MHz clock)

003-PSoC6_TeraTerm.JPG

I'm glad that I could follow Len-san's suggestion and tested with an external signal 😉

moto

Note: Attached projects

PSoC 6 (CY8CKIT-062-BLE) timer_test_210606b

PSoC 4 (CY8CKIT-044) timer_test_210606

... I should have payed more attention about naming the project ... >_<

View solution in original post

0 Likes
7 Replies
Aashita_R
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi @MotooTanaka ,

I have gone through your attached project. The understanding seems to be correct. However, there are a few things which can be tried before concluding this. These changes can be made in the project to check out this interesting intuition.

1. Configure Interrupt on capture/compare in the TCPWM component.

2. When the Capture Interrupt takes place, print the Counter Value on the serial terminal.

3. Trigger Reload and Capture at the same time.

You can try this out at your end and confirm for your understanding. Meanwhile, I am trying to develop a working PSoC Creator project for the same.

Hope this helps!

Best Regards,

Aashita

 

 

 

 

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Dear Aashita-san,

Thank you very much for your taking time to check this project and question.

1. Configure Interrupt on capture/compare in the TCPWM component.

2. When the Capture Interrupt takes place, print the Counter Value on the serial terminal.

3. Trigger Reload and Capture at the same time.

I think that I have done all of these, except that since the expected interval is around 1ms,

printing all values will delay the system, so I'm checking and printing only if the captured value

has changed from the previous value. (This means that my program is capturing at all triggers,

but is not printing the same value(s)) .

Anyway, I really appreciate your trying to test this at your site,

and if you notice any possible issue(s), please teach me that.

Best Regards,

5-Jun-2021

Motoo Tanaka

 

0 Likes
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

moto-san,

I also believe your assumptions are correct.  The TCPWM is a synchronous state machine.

Having said that, to prove the flawless operation your customer seeks, I recommend you use a different source for your 1ms IRQ simulation.

Here is the issue as I see it.  In your project you are using a TCPWM (Counter_2) to generate the 1ms IRQ stimulus which you feed back into another TCPWM (Counter_1).  BOTH use the same base clock (Clk_Peri).  Because of this common clock base the edges of your IRQ stimulus is ALWAYS in-sync with Counter_2s state machine.

You need to create a 'forced' asynchronicity in your system to see if the synchronized TCPWM state machine design will operate flawlessly.

In my years of designing systems, I have found the most subtle issues occur when the system's ability to adapt to asynchronous signals is not considered.  The issue may not occur frequently but usually occurs in the field if not caught and fixed in development.

What you need to do is provide the IRQ 1ms stimulus from another source outside the PSoC6 you're working with.

This can be accomplished very easily in two ways.  Use a AWG or use another PSoC to generate the IRQ stimulus.

For example if you program two PSoC6s (CPU1 and CPU2) with the same code.  You feed the IRQ from CPU1 to the Counter_1 of CPU2 and the IRQ from CPU2 to Counter_1 of CPU1.   This will allow you to test two systems with asynchronous IRQ stim simultaneously over many cycles to see if a failure occurs.

This 'forced' asynchronicity will help to flush out subtle timing issues that your customer is questioning.  Since both CPU1 and CPU2 have a IMO at +/- 1% you're guaranteed that over time, each Clk_Peri will NOT be EXACTLY the same frequency.   In this way an AWG has the same effect.  The 1ms for any system is nominal (+/- 1%).

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

Dear Len-san,

Thank you very much for your thoughtful response and suggestion!

So I created a simple project with CY8CKIT-044 which generates about same signal with the Counter_2.

But surprisingly (or naturally?), the PSoC 6 program  decided to stop working 😜

I grabbed out my oscilloscope and so far, found that pulse from CY8CKIT-044 is received OK,

and ISR set flag correctly, but the reading value of the Counter_1's capture is 0. >_<

May be this is what the customer was anxious about. (With the reload, the Captured value might be cleared)

I will look into this more tomorrow.

So for the time, just FYI 😉

Best Regards,

6-Jun-2021

Motoo Tanaka

 

0 Likes

moto-san,

Interesting result!  It looks like the changes you made after this post appear to work with an asynchronous input.

As I indicated, I have found in my years of design, synchronicity is usually easy.  It's the asynchronous events that yield the surprises.   In most cases, it usually takes a long time to manifest an issue.  In your case, it appeared quickly.   (This is a blessing.   Quicker is better to reduce development time.)

CPU core design tries to be as synchronous as possible,  It reduces the number of gates needed and vastly improves performance.   However, "real world" is asynchronous.  When you read inputs from the "real world" you may need to synchronize it to the logic inside the CPU to prevent things like meta-stable clocked latch logic conditions.

This is why the Cypress has a SYNC components and the GPIO inputs have Sync Mode: settings such as Transparent, Single-sync and Double-sync.   Except for Transparent, each sync mode adds a D-flipflop in front of the input.  Therefore the input result to the CPU is delayed by up to 1 to 2 BUS_CLK periods.  This is the price to pay to resync.

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

Dear Len-san,

Your description about the Sync Mode of GPIO input, reminded me of the days of ASIC design.

Yes, to make the synchronized design system work reliably, sampling input with registers were kind of must. But recently, somehow I have not paying attention(s).

As assigning the input as synchronous mode sounded promising,

I tested my originally posted design with Single-Sync and Double-Sync with external signal,

but alas it did not work. So my current conclusion is that to take care of external (async) signal, we need to have some time interval(s) between capture and reload.

Anyway, thank you very much for your suggestions!

I think that I can go forward from here 😉

Best Regards,

7-Jun-2021

Motoo Tanaka

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,

It's been a long (wrong?) day.

So I changed schematic something like

001-schematic.JPG

Pins

002-Pins.JPG

Somehow with my CY8CKIT-062-BLE, restore input did not seem to clear the counter.

So I added Timer_1_SetCounter(0) in the main loop

#include "project.h"
#include "stdio.h"
#include "tty_utils.h"

volatile int32_t sensor1_period = 0 ;
volatile int     sensor1_flag = 0 ;

void Pin_2_Write(int v)
{
    Cy_GPIO_Write(Pin_2_0_PORT, Pin_2_0_NUM, v) ;
}

void sensor_irq1_isr(void)
{
    int32_t source ;
    
    Pin_2_Write(1) ;
    sensor1_flag = 1 ;
    sensor1_period = Counter_1_GetCapture() ;
    source = Counter_1_GetInterruptStatus() ;
    Counter_1_ClearInterrupt(source) ;
}

void sensor_irq1_init(void)
{
    const cy_stc_sysint_t SysInt_1_cfg = {
        .intrsrc=(IRQn_Type)SysInt_1__INTC_NUMBER,
        .intrPriority = SysInt_1__INTC_CORTEXM4_PRIORITY
    } ;
    Cy_SysInt_Init(&SysInt_1_cfg, sensor_irq1_isr) ;
    NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc) ;
    NVIC_EnableIRQ((IRQn_Type)SysInt_1_cfg.intrSrc) ;
}

void init_hardware(void)
{
    __enable_irq(); /* Enable global interrupts. */    
    
    Pin_2_Write(0) ;
    
    tty_init() ;
    
    sensor_irq1_init() ;
    
}

int main(void)
{
    int32_t prev_period = 0 ;
    int32_t period = 0 ;
    int32_t delta = 0 ;
    int32_t test_period = 0 ;
    int32   count = 0 ;
    
    init_hardware() ;
    
    cls() ;
    
    splash("PSoC 6 Interval Timer Test") ;
    
    Counter_1_Start() ;

    for(;;)
    {
        if (sensor1_flag) {
            Pin_2_Write(0) ;
            Counter_1_SetCounter(0) ; // <=======
            period = sensor1_period ;
            sensor1_flag = 0 ;
            if (prev_period != period) {
                snprintf(str, STR_BUF_LEN, "Sensor1:%d\n\r", period) ;
                print(str) ;
           
                prev_period = period ;
            }
        }
    }
}

Now my PSoC 6 project can measure the interval of the negative pulse output of PSoC 4 project.

 

PSoC 4 (Signal Generator Project) Tera Term log

004-PSoC4_TeraTerm.JPG

PSoC 6 (Interval Measurement Program)

(Showing the last part of the previous PSoC 4 output, period = 2000 with 2MHz clock)

003-PSoC6_TeraTerm.JPG

I'm glad that I could follow Len-san's suggestion and tested with an external signal 😉

moto

Note: Attached projects

PSoC 6 (CY8CKIT-062-BLE) timer_test_210606b

PSoC 4 (CY8CKIT-044) timer_test_210606

... I should have payed more attention about naming the project ... >_<

0 Likes