Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

RTC and interrupts

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR
View previous topic :: View next topic  
Author Message
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 471

newzealand.gif
PostPosted: Thu Dec 27, 2018 1:29 am    Post subject: RTC and interrupts Reply with quote

I am using timer 3 to generate a 1sec int to synchronize my RTC. Timer 0 does nothing except flash a heartbeat LED
A global long called "Local_secL" is incremented every second by T3, which in turn is used to generate the date and time variables.

Every 15 minutes, i do a data upload to a server via cellular, and there is a standard HTTP response from the server, which includes GMT.
The GMT response from the server is decoded and the date$/time$ variables are corrected if necessary.
The RTC is kept to local time by decoding the return from the server every 15 minutes, in the sub below.

The problem I have is about once per month, an upload get missed completely, and I have been trying to find the cause for several months.
I suspect that the Var TTRN is simply not getting set, and the server upload is missed because of this.
I am also confused about interrupt priority. The help says that
Quote:

When an interrupt is serviced no other interrupts can occur because the processor(not the compiler) will disable all interrupts by clearing the master interrupt enable bit.


Does this mean that it is possible that one of my timer int is missed because the processor could be away doing the other timer int ? This would explain why TTRN doesnt get set sometimes?



The code is as follows. I have only included the relevant parts because the code is 6000 lines long.
Code:

 '*******************************************************************************
$regfile = "m1284pdef.dat"            
$crystal = 9830400                                          
$framesize = 800                                          
$hwstack = 550                                            
$swstack = 550                                              
$frameprotect = 1


'---------------------------------------------------------------------
'Config the RTC
'RTC is incremented by incrementing a flag local_secL
Config Clock = User
Config Date = Dmy , Separator = Slash                       'dd/mm/yy


 '-----------------------------------------------------------
 'Timer 0 = 8 bit counter, 9.8304mhx xtal, 1024 prescaler = overflows 37.5 times per sec
 'Flashes the heartbeat led
Config Timer0 = Timer , Prescale = 1024
Enable Timer0
 'Start Timer0

On Timer0 Timer0overflow Nosave                             'happens 37.5 times/sec        

 '---------------------------------------------------------------------------------
'Timer 3 = 16 bit rolls over every 1 second,set by timer preset in the ISR
'This timer checks TTRN
'takes care of the RTC

Config Timer3 = Timer , Prescale = 1024                     'Counts 9830400/1024 = 9600 ck pulses per sec                '
                                        '

On Timer3 Timer3overflow
Enable Timer3
Start Timer3

dim local_secL as long
dim TTRN as byte    
dim Dn5 as byte   ' done
TTRN = 0


'-------------------------------------------------------------------------------
'MAIN LOOP
DO
       
          If TTRN = 1 then

               ' do lots of things
               'upload to server. 'The standard server HTTP GMT response (with junk removed)  is now in "responseSTR
               verify_time(responsestr)      'function
              call UpdatemyRTC
 
               TTRN = 0
 
          end if


LOOP



'*****************************************************************************
Function Verify_time(byval Responsestr As String) As String

        'input dd/MM/yyyy,HH:mm:ss,nnnnnnnnnn and is 30 bytes long
        'output dd/MM/yyyy,HH:mm:ss,nnnnnnnnnn 30 bytes long  OR "null"
   Local Error As Byte
   Error = 1

   If Len(responsestr) = 30 Then

      If Mid(responsestr , 3 , 1) = "/" Then
         If Mid(responsestr , 6 , 1) = "/" Then
            If Mid(responsestr , 14 , 1) = ":" Then
               If Mid(responsestr , 17 , 1) = ":" Then
                  If Mid(responsestr , 7 , 2) = "20" Then
                     If Mid(responsestr , 11 , 1) = "," Then
                        If Mid(responsestr , 20 , 1) = "," Then

                           Error = 0                        'no errors, no changes to responsestr
                           Print #1 , ">> good verify"
                        End If
                     End If
                  End If
               End If
            End If
         End If
      End If

   End If

   If Error <> 0 Then
      Responsestr = "null"
      Print #1 , "time from server failed at function verify_time "
   End If

   Verify_time = Responsestr


End Function






'***************************************************************************
sub updatemyRTC()
         
        'format is now dd/MM/yyyy,HH:mm:ss,nnnnnnnnnn and needs to be   dd/MM/yy,HH:mm:ss,nnnnnnnnnn  


         If Len(responsestr) = 30 Then

            Delchar responsestr , 7                            'delete y
            Delchar responsestr , 7                            'delete y  string is now dd/MM/yy,HH:mm:ss .. etc
            Time$ = Mid(responsestr , 10 , 8)             'HH:mm:ss
            Date$ = Left(responsestr , 8)                    'dd/MM/yy
            Local_secl = Syssec()                               'this is local time  i.e. includes DST
           
             
            Print #1 , ">> local_secL=" ; Local_secl:
         Else
            Print #1 , ">> bad local time response length from server. Len was" ; Len(responsestr)
         End If


end sub



 '*****************************************************************************
Sub Check_ttrn()
   'is it TTRN  (time to read noise).
   'This sub called once every sec under interrupt of timer3
   'Dn5 lets  ttrn->1  happen only once per 15 min
   'TTRN is latched in this sub and unlatched when data is sent

   

      If Dn5 = 0 Then
         If _min = 0 Or _min = 15 Or _min = 30 Or _min = 45 Then
            Dn5 = 1
            Ttrn = 1                                        'time to read noise
            Print #1 , ">> time to read 15min noise"
         End If

      Else

         If Ttrn = 0 And _min <> 0 And _min <> 15 And _min <> 30 And _min <> 45 Then
            Dn5 = 0

         End If

      End If
 
End Sub

'****************************************************

Timer0overflow:

   'called 37 x per second
   'flashes heartbeat LED once per sec




   $asm

      push r24                                             ;save r24
      in r24, sreg                                         ;r24<-sreg
      push r24                                             ;save status register to stack
      lds r24, {btimer0}                                   ;load direct
      inc r24
      cpi r24,37                                           ;compare
      brlo timer0ovf                                       ;br if r24 < 37
      clr r24                                              ;clear r24
      sbi heartbeat_pin,heartbeat_bit                       ; write 1 to pin = toggle led
Timer0ovf:
      sts {btimer0},r24                                     ;store btimer0 <- r24
      pop r24
      Out Sreg , R24                                        'get Sregister back
      pop r24

   $end Asm

Return
'******************************************************************************


Timer3overflow:
   'T3 rolls over every 1 second


   Timer3 = 55936                                           '65536 - 9600x1
   Call Check_ttrn                                          'is it time to read the noisemeter
   Incr Local_secl
   Time$ = Time(local_secl)                                 'calculate time & update RTC
Return

'*******************************************************************************

End


(BASCOM-AVR version : 2.0.7.9 , Latest : 2.0.8.1 )

_________________
Neil
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Thu Dec 27, 2018 11:40 am    Post subject: Reply with quote

I have a one second tic for real time on many of my projects
I try to do as little as possible in the interrupt
In my web server project I update from the time servers
I use bascoms inbuilt time constant, system second
below is the basic isr
Regards Paul


Code:

 Config Timer0 = Timer , Prescale = 1024


 On Ovf0 Tim0_isr                                           'Define ISR handler
 

Tim0_isr:



         Bres = Bres + 262144                               '262144 = prescaler:1024 * timer0:256
         If Bres > 8000000 Then                             '8 000 000 = xtal frequency
         Bres = Bres - 8000000
         'Top = 1
            'Set Portd.6                                     'top test 1 second
            ' Waitms 10
             'Reset Portd.6
         End If


         Return


 
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2335

blank.gif
PostPosted: Thu Dec 27, 2018 9:18 pm    Post subject: Re: RTC and interrupts Reply with quote

njepsen wrote:
Does this mean that it is possible that one of my timer int is missed because the processor could be away doing the other timer int ?

Interrupt flags memorize one trigger event, the corresponding (enabled) interrupt is executed as soon interrupts are globally (re-)enabled, return from an ISR re-enable interrupts.
As there's only one bit per flag, two or more of the same triggers - while blocked - lead to only one executed corresponding interrupt.
However, it does not look like the timer interrupts may block out each other for that long.

Did you think about what may happen as local_secl can be accessed from main-code and from interrupt?
local_secl is a 4-byte variable and an 8bit processor can handle only one byte at one time.
Race-conditions anyone?

Some subs look like interrupt-related only, I would pack them into the ISR directly.
Back to top
View user's profile
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 471

newzealand.gif
PostPosted: Thu Dec 27, 2018 9:35 pm    Post subject: Reply with quote

MWS - Thanks for the insight into timer interrupts. You raise the ? of race condition, good point. Yes - Local_sec1 can be changed both in the timer ISR and in the sub, but this would cause a max error of 1 sec ?. What I dont show is that the "Update RTC" sub only gets called once every 15 minutes.

But for TTRN to not get set, the _min variable would need to be set to not equal 0,15,30,45 or 60, which would take an error of 60sec with the 1 second tic. I'm struggling to see how this might happen.

_________________
Neil
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2335

blank.gif
PostPosted: Fri Dec 28, 2018 1:58 am    Post subject: Reply with quote

A) If you would know the culprit, you would not ask.
B) You can not solve unknown bugs, if you don't care about the obvious first.

Quote:
What I dont show is that the "Update RTC" sub only gets called once every 15 minutes.

You actually did show it through your code and I was aware of it.
Assume your RTC is a bit off, then you may have every 15 minutes an error bigger than one second.
Considering a 'long' is built of 4 bytes, and double access may create some chimera from both, it should be obvious there can be a problem.

Another potential issue may be, if the newly fetched GMT is wrong, but made it through your check-routines.
Is the time difference between the last good upload and the next good exactly 30 minutes?
Did you try syncing time only at startup and the rest of the month without re-sync?

Last, may the upload fail simply because of wireless connection problems?
By adding a field 'time of previous upload attempt' to your upload data, you will know.
Back to top
View user's profile
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 471

newzealand.gif
PostPosted: Fri Dec 28, 2018 2:48 am    Post subject: Reply with quote

Thanks MWS. I am assuming that the bug is failure to set TTRN. The only way this can happen is if _min <>0,15,30 or 45, which could happen if at the next 15 minute correction, the correct time was 1 minute faster than Time$. If that happened, then _min could theoretically jump from 59 to 01, or 14 to 16 for example.
[quote]
Another potential issue may be, if the newly fetched GMT is wrong, but made it through your check-routines.
[\quote]
Yes thats possible but I'm guessing that the cellular response has some sort of error checking in the HTTP protocol. I think its pretty unlikely that the response would pass the checks i am looking for but then again - you could be right. i dont know.

Yes it can happen that communications fails for an hour or so, but that has never happened prior to the issue I'm bugged by.


Quote:

Did you try syncing time only at startup and the rest of the month without re-sync?
No I havent - thats easy to do. I do know (from tests) that after a month I would be a minute or so out because my system Xtal is nothing special, and I dont make any attempt to trim it to frequency.

Quote:

Last, may the upload fail simply because of wireless connection problems?
This doesnt matter, and is taken care of in code. The RTC of course just trucks on, til next interval. I have tested this for several days and it works fine.

Quote:
By adding a field 'time of previous upload attempt' to your upload data, you will know.
I do log everything I can, and when there is a failure, the two uploads on either side of the missing one a exactly on the correct time.
Quote:

Considering a 'long' is built of 4 bytes, and double access may create some chimera from both, it should be obvious there can be a problem.
Hmm possible but the next upload would be 'anywhere!' and this doesnt happen.

Thanks MWS for helping with this - my best guess at the moment is that TTRN isnt being set, and one possibility as I said earlier is that the server upload is causing time to 'jump over' my _min check.
To test this I will do a range check, 5 minutes wide at each 15 min interval, and see if the problem changes.

_________________
Neil
Back to top
View user's profile
MWS

Bascom Member



Joined: 22 Aug 2009
Posts: 2335

blank.gif
PostPosted: Fri Dec 28, 2018 9:59 am    Post subject: Reply with quote

njepsen wrote:
I am assuming that the bug is failure to set TTRN.

You assumed that from the very start, and it can be.
If you want understand the mechanism of a bug, you need to scrutinize its origin and eliminate every potential bug on this way.
But it's your bug, so surely you can approach it as you like.

Tell me: are you able to compile the shown code from your entry post?
Nowhere in this code you dim Responsestr, but you use it in
Code:
verify_time(responsestr)

which should throw an error.
Code:
Function Verify_time(byval Responsestr As String) As String

creates a local copy of the string on the frame, which must be considered void after the function exits.
Even if you actually use a global variable with same name 'Responsestr' I would avoid such double-naming.

If you condense code for the purpose of showing the basics, that's ok, but at least it should be functional, i.e. represent the actual problem.
Back to top
View user's profile
laborratte

Bascom Expert



Joined: 27 Jul 2005
Posts: 305
Location: Berlin

germany.gif
PostPosted: Sat Dec 29, 2018 12:37 am    Post subject: Reply with quote

You are accessing both Local_secl and time$ in main and isr. For non-byte-vars that are changed in a isr every access has to be blocked from interrupt in main:

Code:

disable interrupts
   Time$ = Mid(responsestr , 10 , 8)             'HH:mm:ss
    Date$ = Left(responsestr , 8)                    'dd/MM/yy
    Local_secl = Syssec()                               'this is local time  i.e. includes DST
enable interrupts
 


This is mandatory, even if you are reading vars. In your case you access a pseudo-var time$ which is actually a subroutine. This makes it even worse as there is a good chance that this routine is not reentrant.
Back to top
View user's profile
njepsen

Bascom Member



Joined: 13 Aug 2007
Posts: 471

newzealand.gif
PostPosted: Sat Dec 29, 2018 4:45 am    Post subject: Reply with quote

Thankyou MWS and Laborratte. Great responses, and easy fix. I will do the suggested and get back to the thread in a week or three, when I am confident that a good test has been made.
many thx both of you.

_________________
Neil
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR All times are GMT + 1 Hour
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
You cannot attach files in this forum
You cannot download files in this forum