CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Counting time with interrupts disabled

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

Counting time with interrupts disabled
PostPosted: Thu Mar 26, 2020 5:49 am     Reply with quote

Hi all,

I am working on a program which counts time when an input is high. I used the example here by ckielstra as inspiration.

My modified interrupt:
Code:

//////////////////////////////////////////////////////////////////////////
//Timer Interrupt
//////////////////////////////////////////////////////////////////////////
#INT_TIMER1
void TIMER1_isr()
{
   if (input_state(MOTORRUNNING))   //Only modify the counter if the motor running input is high
   {
      Ticker -= 65536;                        // Decrement ticker by clocks per interrupt
         if ( Ticker < 65536 )                   // If second has expired
          {  Ticker += TIMER1_FREQUENCY;          //   Increment ticker by clocks per second
              seconds++;                           //   Increment number of seconds
              output_toggle(SECONDTICKER);
          }
          if (seconds > 59)   //If seconds roll over, increment the minute counter
          {
            seconds = 0;
            minutes += 1;
            write_int16_eeprom(MinutesAddress, Minutes);
            if (minutes > 59) //If minutes roll over, increment the hour counter
            {
               minutes = 0;
               Hours += 1;   
               write_int16_eeprom(HoursAddress, Hours);
            }
           
          }
   }

}

This all seems to work pretty well, however there are a couple warnings that come up that I want to make sure won't bite me in the butt in the future.
Code:

>>> Warning 216 "\Firmware\MaintenanceTimer.c" Line 189(1,2): Interrupts disabled during call to prevent re-entrancy:  (@PUTCHAR_1_)
>>> Warning 216 "\Firmware\MaintenanceTimer.c" Line 189(1,2): Interrupts disabled during call to prevent re-entrancy:  (@PSTRINGC7_780)
>>> Warning 216 "\Maintenance Timer\Firmware\MaintenanceTimer.c" Line 189(1,2): Interrupts disabled during call to prevent re-entrancy:  (@delay_ms1)
>>> Warning 216 "\Maintenance Timer\Firmware\MaintenanceTimer.c" Line 189(1,2): Interrupts disabled during call to prevent re-entrancy:  (write_int16_eeprom)

The first two warnings are related to RS232, then general delays, and finally writing to EEPROM.

Will these greatly affect the accuracy of the time keeping? I need to keep time somewhat accurately, although no real hard requirement. I will be counting up to 8000hrs, I would say at that total time I need +/- 1hr or so.

Thanks in advance!
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 6:23 am     Reply with quote

Yes...
You should NOT be writing to the EEPROM inside any ISR. If the typical write to EEPROM takes 10 ms, and you hit the ISR 6 times, there's a minimum of 60ms 'time' will be off. Hmm, you write every minute and every hour, so 60+24=84 writes, that's at least 840 ms/day time is off AND it gets worse every minute of every day. I'm sure someone can 'do the math' to see how bad it will be after a year.

Honestly, add a $1 RTC like a DS3231 module, that'll have EEPROM as well. That WILL give you very accurate time, a known interrupt AND battery backed RTC. I couldn't go 8000hrs (a year +-) without several power failures.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 8:57 am     Reply with quote

Thank you for the information.

I was hoping to avoid the RTC. I would like to stay away from a battery if at all possible. I guess I could use the EEPROM and only use it for my time delta.

I will modify the code to handle the EEPROM writes external to the ISR, I agree that was a silly thing to do...

However, when reading the warnings it looks like the interrupt will be disabled during those writes. If I am understanding this correctly, wont that mean that I wont be increment time there during the EEPROM write?
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 10:57 am     Reply with quote

Correct, interrupts are disabled, so no time keeping THAT'S why I suggest an RTC module (which has it's own battery).
Even if you add a battery to your PIC project, that adds cost and extra code (as when the main power fails). Acording to 'Murphy', that will happen during an EEPROM write and the entire EEPROM 'magically' will have all '1's in it after power is restored. Sad
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 1:00 pm     Reply with quote

Also important to understand a couple of things:
1) The limited life of EEPROM. If you are writing at all often you can
quickly kill it. EEPROM is designed for things that change infrequently,
like configuration values, not things that change at all often.
2) The great sloth of EEPROM. A write to a single byte typically
takes something like 4mSec. Conversely a RTC chip with built in
SRAM can write a byte in a few uSec. EEPROM writes inside an interrupt
are a piece of hell....

Interrupts won't be disabled in EEPROM writes if they are only done
external to the ISR's. However you have to remember if you are writing
values that can be changed by the ISR, you would need to save these
with interrupts disabled, into a temporary variable, and then write this.
Otherwise an individual byte of the value could change during the write.
Result garbage....
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Thu Mar 26, 2020 5:10 pm     Reply with quote

As a further recommendation, consider using a buffer for your EEPROM and a buffer for your UART calls in the interrupts you have. That way your interrupts can simply buffer the data and at that point either your main can handle actually sending the data when convenient, or for the UART you can have the TX interrupt handle outputting the data when the UART is available.

So instead of write_int16_eeprom() make an array of 16 bit values, and a function to place a new value on the array. Then somewhere in your loop you can have the main see if the array has data and if so, write it out to EEPROM as needed using a different function. You can model it after the circular buffers used in the example files ex_sisr.c and ex_stisr.c (for ideas on how to implement it safely in the presence of interrupts). If that seems too complicated, then you can simply disable interrupts when removing a 16 bit value from the array and changing the index in the main code. That should be super quick with no noticeable impact to your timer interrupt.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 3:58 am     Reply with quote

All,

Thank you for your incredibly detailed and helpful comments, I really appreciate it.

After thinking about this, I really do want to take the RTC w/EEPROM approach. However I am a little confused as to how implement an RTC in this scenario. My understanding is that an RTC will keep time consistently from the moment it is set. In my application I only want to keep time if an external input is TRUE, only when the PIC is powered. I am not sure how to implement this using an RTC?

Thanks!!
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 4:15 am     Reply with quote

Most RTC chips also contain battery backed user RAM.

So when the interrupt triggers, just copy the time to this RAM (or if
the chip is always going to have power just into some temporary
variables). Then when the interrupt goes off, the total 'on time' is
just the time 'now', less the stored time.
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 4:24 am     Reply with quote

Thank you,

I actually ended up finding the DS1683, which looks like it is exactly what I need.

https://datasheets.maximintegrated.com/en/ds/DS1683.pdf

Looks like with suitable bulk capacitance, this should do the trick!
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 5:20 am     Reply with quote

I downloaded the datasheet as I was curious.

First, it has a basic RC oscillator as it's clock, a 'nominal' 250ms (237 to 262ms), so in the long term it will not be nearly as accurate as a true RTC device, especially over the 8000 hrs (almost a year !).

Second, COST ! Digikey list 4 versions, $2 to $4. I pay LESS than $2 for a complete PCB module with DS3231, EEPROM, battery holder, pullups, I/O pins.

As I don't know all the details about your project, I'd like to offer my opinions.

As a 'time keeping' device, the DS3231 module is far more accurate and offers 'free', battery backed storage of a few bytes of fast RAM. It also has an internal temperature sensor.

The DS3231 modules I buy, for less than the DS1683 also have an EEPROM chip. That could be useful for storing LOTS of additonal data. Even if this project doesn't use it, perhaps the next project will.

If you go with ANY external 'time keeping device', you need to design PCB, test, confirm wiring, etc. so buying an RTC module for LESS than just a DS1683 chip makes sense. As a designer, I need to be economical. The DS1683 is a one purpose, expensive, inaccurate device that will take a lot of R&D time to breadboard, cut code, test, design PCB, etc. The DS3231 is an 'off the shelf' product that works, has far more features and cost less.

In the good old days, I'd buy chips, wirewrap and spend 100s of hours on a project. Today, thanks to technology, I buy premade 'modules' that work. Maybe as I've spent 1/2 my 66 years 'playing with PICs' but I enjoy cutting code a LOT more than cutting up defective PCBs as I flipped +D and -D or similar easy to do mistakes.

You may not actually need an external 'time keeper' though. Almost any PIC can easily emulate the DS1683. CCS supplies a 'stopwatch' example program (ex_stwt.c ????) which is similar in concept to your requirement. It could be modified into an 'elasped time' program.

Jay
demedeiros



Joined: 27 Dec 2013
Posts: 71

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 6:07 am     Reply with quote

Thanks Jay,

This will be converted over to a PCB at some point. Quantity is fairly low, so price per component isnt a huge deal thankfully.

Running it all on the PIC would be ideal. Removing the EEPROM writes from the interrupt routine was straightforward. To help reduce the number of EEPROM writes I guess I could emulate the behavior of the DS1683, only writing to the EEPROM when the event goes low.

I guess the only thing I'll have to figure out is the power off during an EEPROM write. Should be easy enough.

Thanks!!
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 27, 2020 7:19 am     Reply with quote

this...
Quote:
I guess the only thing I'll have to figure out is the power off during an EEPROM write.

might be done by...

Checking if PIC main power has failed (some PICs have bits set for brownout, VDD < a value).
If this happens then write to EEPROM.

As long as a 'reservoir' capacitor has enough electrons in it, the EEPROM will store the data. if the EEPROM needs 5ms for a cycle, choose cap with say 15-20ms of capacity.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group