1

I have to write a class that implements the given interface below. When I call the start function it should starts counting every 1 millisecond and when I call the stop function it should stop counting. The read function should return the value of the counter.

How should I go about writing this implementation as I'm implementing this on for a microcontroller without any RTOS. As such this project is strictly single threaded and I don't see a way as how to implement this without threads.

class Counter{
public:
    virtual void stop() = 0;
    virtual void start() = 0;
    virtual int read() = 0;
};

example usage:

int main()
{
   Counter *cnt = new Counter_Implemented();
   cnt->start();

   //do some heavy task here

   cnt->stop();
   int duration = cnt->read();
}
Tarick Welling
  • 3,119
  • 3
  • 19
  • 44
  • Hardware interrupts were how we did it in the 8-bit computer days (C=64, Atari). – Dave S Jun 11 '20 at 18:39
  • So `read` should just return the number of milliseconds between the `start` and `stop` calls? I don't see why threading should even be a consideration here -- just use `std::chrono`. – G.M. Jun 11 '20 at 18:43
  • 1
    @G.M. std is implemented in the very limited way on the uCs. it is not the way to go. – 0___________ Jun 11 '20 at 19:37
  • @P__J__ True but the post is tagged `c++17` so... Perhaps the OP can clarify what is/isn't available. – G.M. Jun 11 '20 at 19:41
  • 1
    @G.M. Standard does not matter when you consider the targets with very limited resources. The rule of thiumb - no exceptions, no RTTI, almost no std etc etc. This world has its own rules. – 0___________ Jun 11 '20 at 19:46
  • @P__J__ Understood, but those are important details so, as I say, the OP should clarify. – G.M. Jun 11 '20 at 19:49

3 Answers3

4

If you have access to std::chrono on your MCU platform/compiler you could use the following code below. Otherwise the solution would be to use the HAL or the integrated timers with interrupts. Such as stated by P__J__


You can use the difference between two timestamps to achieve this. Have start store the current time stamp and then stop will store the ending time stamp. read would then give you the difference or if the timer is currently running, then get the different of now vs the start point. That would look like

class Counter{
public:
    void stop()
    {
        end = std::chrono::steady_clock::now();
    }
    void start() 
    { 
        start = std::chrono::steady_clock::now();
    }
    int read()
    {
        if (start >= end) // timmer currently running
            return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
        return std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    }
private
    std::chrono::time_point<std::chrono::steady_clock> start{};
    std::chrono::time_point<std::chrono::steady_clock> end{};
};
Tarick Welling
  • 3,119
  • 3
  • 19
  • 44
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
1

If you use HAL libraries:

class Counter{
public:
    void stop()
    {
        end = HAL_GetTick();
    }
    void start() 
    { 
        start = HAL_GetTick();
    }
    uint32_t read()  
    {
        return end-start;
    }
};

If you want to be able stop counting just use any hardware timer this purpose instead of SysTick.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • @TarickWelling do not edit my answers the way you did. If you want to share some additional knowledge comment or write your own one. Your elaborations about the interrupts and overflows was something I did not have in my answer. – 0___________ Jun 12 '20 at 11:08
  • But it **did** make it better. And for someone who despises the HAL it was quite odd not to include how to use normal timers for this job. But alas have it your way, I won't start some edit war over this. – Tarick Welling Jun 12 '20 at 11:14
  • 1
    @TarickWelling ***`But it did make it better`*** no in my opinion o. It is **MY** answer and only **I** can do such a changes. If I edit someone answer - I only correct obvious mistakes and typos. Never amend or expand the answer. If I want to I comment or write my own answer. – 0___________ Jun 12 '20 at 11:40
1

May be developers of hardware supports sys/time.h? There is implemented:

int   getitimer(int, struct itimerval *);
int   setitimer(int, const struct itimerval *, struct itimerval *);
int   gettimeofday(struct timeval *, void *);
int   select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
int   utimes(const char *, const struct timeval [2]);

I think, one of this functions can help you/

  • You are on the right track but what you should look for is the RTC (realtime clock) peripheral. This implements such clock features but isn't always available. – Tarick Welling Jun 12 '20 at 10:15
  • I don't know how to insert code in comments, but here it is: uint32_t rtcGetTimeTmMilli(RTCDriver *rtcp, struct tm *timp) { RTCTime timespec = {0,0}; rtcGetTime(rtcp, &timespec); localtime_r((time_t *)&(timespec.tv_sec), timp); return timespec.tv_msec; } – Anton Anisimov Jun 13 '20 at 14:54
  • Seems like you got the rtc functions from ChibiOS? But you shouldn't add code to comments just edit your original answer to make it better. The question is about the STM32 so I would suggest you add information about the HAL functions for RTCs – Tarick Welling Jun 13 '20 at 17:17