Why does clock() returns -1 in C

358 views Asked by At

I'm trying to implement an error handler using the clock() function from the "time.h" library. The code runs inside an embeeded system (Colibri IMX7 - M4 Processor). The function is used to monitor a current value within a specific range, if the value of the current isn't correct the function should return an error message.

The function will see if the error is ocurring and in the first run it will save the first appearance of the error in a clock_t as reference, and then in the next runs if the error is still there, it will compare the current time using clock() with the previous reference and see if it will be longer than a specific time.

The problem is that the function clock() is always returning -1. What should I do to avoid that? Also, why can't I declare a clock_t variable as static (e.g. static clock_t start_t = clock()?

Please see below the function:

bool CrossLink_check_error_LED_UV_current_clock(int current_state, int current_at_LED_UV)
{
    bool has_LED_UV_current_deviated = false;
    static int current_number_of_errors_Current_LED_CANNON = 0;
    clock_t startTimeError = clock();

    const int maximum_operational_current_when_on = 2000;
    const int minimum_turned_on_LED_UV_current = 45;     
    
    if( (current_at_LED_UV > maximum_operational_current_when_on)
      ||(current_state!=STATE_EMITTING && (current_at_LED_UV > minimum_turned_on_LED_UV_current))
      ||(current_state==STATE_EMITTING && (current_at_LED_UV < minimum_turned_on_LED_UV_current)) ){
        current_number_of_errors_Current_LED_CANNON++;
        if(current_number_of_errors_Current_LED_CANNON > 1) {
            if (clock() - startTimeError > 50000){ // 50ms
                has_LED_UV_current_deviated = true;
                PRINTF("current_at_LED_UV: %d", current_at_LED_UV);
                if(current_state==STATE_EMITTING){
                    PRINTF(" at state emitting");
                }
                PRINTF("\n\r");
            }
        }else{
            if(startTimeError == -1){
                startTimeError = clock();
            }
        }
    }else{
        startTimeError = 0;
        current_number_of_errors_Current_LED_CANNON = 0;
    }
    return has_LED_UV_current_deviated;
}

Edit: I forgot to mention before, but we are using GCC 9.3.1 arm-none-eabi compiler with CMake to build the executable file. We have an embedeed system (Colibri IMX7 made by Toradex) that consists in 2 A7 Processors that runs our Linux (more visual interface) and the program that is used to control our device runs in a M4 Processor without an OS, just pure bare-metal.

3

There are 3 answers

0
Victor Hugo Martins Marques On BEST ANSWER

in the end the problem was that since we are running our code on bare metal, the clock() function wasn't working. We ended up using an internal timer on the M4 Processor that we found, so now everything is fine. Thanks for the answers.

0
Tom V On

To answer the second part of your question:

static clock_t start_time = clock();

is not allowed because the return value of the function clock() is not known until runtime, but in C the initializer of a static variable must be a compile-time constant.

You can write:

static clock_t start_time = 0;

if (start_time == 0)
{
  start_time = clock();
}

But this may or may not be suitable to use in this case, depending on whether zero is a legitimate return value of the function. If it could be, you would need something like:

static bool start_time_initialized = false;
static clock_t start_time;

if (!start_time_initialized)
{
  start_time_initialized = true;
  start_time = clock();
}

The above is reliable only if you cannot have two copies of this function running at once (it is not re-entrant).

If you have a POSIX library available you could use a pthread_once_t to do the same as the above bool but in a re-entrant way. See man pthread_once for details.

Note that C++ allows more complicated options in this area, but you have asked about C.

Note also that abbreviating "start time" as start_t is a very bad idea, because the suffix _t means "type" and should only be used for type names.

3
Locke On

For a lot of provided functions in the c standard library, if you have the documentation installed (usually it gets installed with the compiler), you can view documentation using the man command in the shell. With man clock, it tells me that:

NAME
       clock - determine processor time

SYNOPSIS
       #include <time.h>

       clock_t clock(void);

DESCRIPTION
       The clock() function returns an approximation of processor time used by the program.

RETURN VALUE
       The  value  returned  is  the  CPU time used so far as a clock_t; to get the number of seconds used, divide by
       CLOCKS_PER_SEC.  If the processor time used is not available or its value cannot be represented, the  function
       returns the value (clock_t) -1.

etc.

This tells us that -1 means that the processor time (CLOCK_PROCESS_CPUTIME_ID) is unavailable. The solution is to use CLOCK_MONOTONIC instead. We can select the clock we want to use with clock_gettime.

timespec clock_time;

if (clock_gettime(CLOCK_MONOTONIC, &clock_time)) {
    printf("CLOCK_MONOTONIC is unavailable!\n");
    exit(1);
}

printf("Seconds: %d Nanoseconds: %ld\n", clock_time.tv_sec, clock_time.tv_nsec);