How to get timestamp in microseconds using Psoc5lp

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

cross mob
PrSa_4352851
Level 1
Level 1
First like given

Hello,

I am using Psoc Creator IDE for programming my Psoc 5LP. I want to get timestamp in microseconds to get the value for a particular function. I have tried your preprocessor __DATE__ and __TIME__ but it doesn't give value in microseconds. Do you happen to know any preprocessor which can give the timestamp in microseconds. Is there any easy way to get that apart from adding components like counter or RTC. I also tried struct timeval but I am having issues with the precision.

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

PrSa,

Attached updated project, tested OK on PSoC5.

/odissey1

StopWatch_P5_01d_demo_A.png

StopWatch_P5_01d_demo_B.png

View solution in original post

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

Hi,

Sometime ago, I posted a response to a question which requested a timestamp.

PSoC 5LP - RTC UART output

As far as I know RTC usually supports up to second,

sometimes may be to millisecond,

but probably microsecond accuracy would be difficult.

If I need to measure events in microseconds granularity,

I would use a dedicated time and let hardware event to trigger start and stop(capture).

moto

0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

PrSa,

I agree with Moto, for 1us accuracy you have to use either a SysTick or a dedicated Timer component.

/odissey1

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

PrSa,

I believe the SysTick by default has a 1ms resolution.  However there is a way to change the source clock for the resource.

When I need better resolution, I either dedicate a counter for this as indicated by moto or /odissey1 or a find a timer/counter being used by another resource in my application that is in continuous mode.  I then derive the start and end timestamps from the immediate count values.  The problem I run into when using a timer/counter in continuous mode is the wrap-around effect that may occur in my timestamps.

Note:  __DATE__ and __TIME__ are compile-time defines.  Are you looking for run-time timestamp values (as the suggestions above are addressing) or compile-time timestamp?  Can you elaborate your application intent for the timestamp?

Len

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

Hello Len,

My application is I need to find how much time it takes to write to the Flash memory. So I want to get the time taken to write a row in Flash putting the timers around CyWrite functions at various places in my code. So I do not exactly need a run-time stamp here but something that can calculate in microseconds so that  I can find the difference between the time.

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

PrSa,

There is a custom component available to measure elapsed time (StopWatch). Demo project is attached. Import the component into you project or add it into dependencies. Usage is simple:

StopWatch_Start();

// your function here

StopWatch_Stop();

//....

StopWatch_Cycles      returns number of BUS_CLK cycles elapsed between Start and Stop

StopWatch_usec         returns number of microsecons elapsed between Start and Stop

This is a Draft version of the component, more testing is required, no datasheet available at this time. Works on PSoC5 and PSoC4.

/odissey1

StopWatch_P4M_01a.png

StopWatch_P4M_01.PNG

Hello Odissey1

I am not able to import this component for my target. I am using Psoc5LP

pastedImage_0.png

0 Likes

PrSa,

It seems that you imported entire project instead of single component.

Component importing instructions:

https://www.cypress.com/video-library/PSoC/psoc-creator-tutorial-importing-components/107756

0 Likes

Hello Odissey1,

I was following the importing instruction. But it still the same. I tried to compile your project and I found out it that your component is incompatible for CPU Cortex M3 which is my target device CY8C5888LTI-LP097 to be precise. Whenever I select the project device to any Cortex M3 version the component shows the picture above incompatible and I get error after compiling the project ofc. If I select Cortex M0 it is fine.

0 Likes

I will look into it. It used it on P5 as well as P4.

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

PrSa,

Attached updated project, tested OK on PSoC5.

/odissey1

StopWatch_P5_01d_demo_A.png

StopWatch_P5_01d_demo_B.png

odissey\,

I really like that you've created a useful component for debugging and potential for application use.  I love that you're using zero additional PSoC resources (except for a tiny amount of FLASH and RAM).  I also love you found a way to have the timer with the resolution of the BUS_CLK.  However ...

There are many projects where I'm using the ARM CMSIS SysTick for application timing.  It's a darn good 'free' resource.  The StopWatch component as you've currently written it assumes this System timer is not being used by the application.

Suggestion:

  • Implement your StopWatch component with Exit callback hooks.  This allows the user install there own SysTick ISR but has your StopWatch_Reloads variable available.  You can in effect use your StopWatch component as a System Timer extension or wrapper per se.
  • If the user needs a specific SysTick period (let's say the default 1ms), when you change the System Timer counter to the max value, you change the expected period for the application.  Leave the System Timer count as per the user.  However, using timestamps for the uint32_t StopWatch_start_ts and uint32_t StopWatch_end_ts you can use the System Timer in continuous running mode.
  • To use the suggestion point above, you need to incorporate StopWatch_Reloads into bits 24 thru 31 (ie. StopWatch_Reloads<24) of the delta timestamp math.   As long as the delta time being measured doesn't exceed 53.6 seconds (@ BUS_CLK=80MHz, longer if BUS_CLK is slower),  you should avoid a wrap-around miscalculation.

Len

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

Len,

Thank you for suggestion. I will look into it. Maybe it is time to dust-off StopWatch component. I used the component a lot, but never quite finished it. I believe that on Cortex M3 processors there is also another resource (like WDT timer), which may serve same purpose. It's on never-finished todo list...

/odissey1

0 Likes

odissey\,

I know the feeling about things could always be better/more features.

I do like how you are using the BUS_CLOCK resolution which can easily be sub-microsecond which is usually more than sufficient for most application.

Len

Len
"Engineering is an Art. The Art of Compromise."
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,

I tried it, too 😉

call start_measure() before calling the function under test

then just after the function, calling stop_measure() returns the us.

in my sample, test_func  is just calling CyDelayUs(us)

so that we can see if the measured "us" agrees with the "us" waited.

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

start_measre() ;

test_func() ;

us_taken = stop_measure() ;

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

As far as I tested, there seems to be 1~2 us overhead.

So in general, reducing the measured value by 1~2 will be about correct value.

The schematic

001-schematic.JPG

Pin assign

002-pin-assign.JPG

main.c

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

#include "project.h"

#include "stdio.h"

volatile uint32_t tc_count = 0 ;

#define STR_LEN 128

char str[STR_LEN+1] ;

void print(char *str)

{

    UART_PutString(str) ;

}

CY_ISR(timer_tc_isr)

{

    Timer_ReadStatusRegister() ;

    tc_count++ ;

}

void init_hardware(void)

{

    UART_Start() ;

  

    tc_int_ClearPending() ;

    tc_int_StartEx(timer_tc_isr) ;

  

    Timer_Start() ;

  

    CyGlobalIntEnable; /* Enable global interrupts. */  

}

void splash(void)

{

    snprintf(str, STR_LEN, "Timer Test (%s %s)\n", __DATE__, __TIME__) ;

    print(str) ;

}

void cls(void)

{

    print("\033c") ; /* reset */

    CyDelay(100) ;

    print("\033[2J") ; /* clear screen */

    CyDelay(100) ;

}

void start_measure(void)

{

    Timer_Stop() ;

    Timer_ReadStatusRegister() ;

    Timer_WriteCounter(0) ;

    tc_int_ClearPending() ;

    tc_count = 0 ;

    Timer_Enable() ;

}

uint32_t stop_measure(void)

{

    uint32_t count ;

    Timer_Stop() ;

    count = Timer_ReadPeriod() - Timer_ReadCounter() ;

    if (tc_count) {

        count += tc_count * Timer_ReadPeriod() ;

    }

    return( count ) ;

}

void test_func(uint32_t us)

{

    CyDelayUs(us) ;

}

int main(void)

{

    uint32_t count ;

    uint32_t us  = 0 ;

  

    init_hardware() ;

  

    cls() ;

  

    splash() ;

  

    for(;;)

    {

        start_measure() ;

        test_func(us) ;

        count = stop_measure() ;

        snprintf(str, STR_LEN, "%d: %d us\n", us, count) ;

        print(str) ;

      

        us = us + 10 ;

        if (us > 10000) {

            us = 0 ;

        }

        CyDelay(1000) ;

    }

}

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

TeraTerm Log

000-TeraTerm-log.JPG

moto