Need advice on setintflags

johndk

Senior Member
I'm running a large program on 28x2 which uses up all four slots. I've got an active hardware interrupt in slot 0 which works fine, getting reset each time I return from another slot. However, I'm trying to implement an interrupt based on the timer in slot 3. The code compiles fine, and runs, but totally ignores the interrupt. I'm probably missing something, but can't see it. Advice on how to set up this interrupt would be appreciated.

CODE:

#picaxe 28x2
#terminal 9600
#no_data
#no_table
#slot 3 ;sensor read functions

setintflags %10000000,%10000000 ;Interrupt on flag7 - toflag
poke bptr_count, 0
flag7 = 0 ;clear the timer overflow flag
settimer timer_100_8 ;timer at 0.1 sec intervals timer_100_8 = 62411
timer = 0

<slot 3 code body>

interrupt:
flag7 = 0 ;clear the timer overflow flag
setintflags %10000000,%10000000 ; Interrupt on flag7 - toflag
bptr = bptr_count
inc @bptr
sertxd(#@bptr,cr,lf)
timer = 0
return
 

PhilHornby

Senior Member
Code:
#picaxe 28x2
#terminal 9600
#no_data
#no_table
#slot 3    ;sensor read functions

setintflags %10000000,%10000000     ;Interrupt on flag7 - toflag
poke bptr_count, 0
flag7 = 0                        ;clear the timer overflow flag
settimer timer_100_8                ;timer at 0.1 sec intervals    timer_100_8 = 62411
timer = 0

<slot 3 code body>

interrupt:
    flag7 = 0                        ;clear the timer overflow flag
    setintflags %10000000,%10000000     ; Interrupt on flag7 - toflag
    bptr = bptr_count
    inc @bptr
    sertxd(#@bptr,cr,lf)
    timer = 0
return
I'm no expert - having only used this once - to get a 5 second timer interrupt, on a 20X2 @ 64MHz...but ...

I think it's your SETTIMER parameters that are wrong, rather than the SETINTFLAGS ... Wouldn't TIMER need to be "65535", rather than "0" ... so it overflows on the first MAJOR tick?

62411 looks like it will give a 0.1S MAJOR tick :-

(assuming 8MHz, with 32uS minor tick)

65536 - 62411 = 3125
3125 x 32uS = 0.1S

TIMER is thus incremented every 0.1S, until it overflows from 65535 -> 0. But since it's starting at zero, this will be in 65536 x 0.1 = 6553.6Secs (1.8 hours :confused: )

Also, I'm not sure if you should be using a 0.1Sec MAJOR tick, if you want the actual interrupt every 0.1Secs. Maybe, you want a 0.01Sec tick (say), with the interrupt after every 10 of them.

(In my example, the T1S_16 value (3036) of 1 second @ 16MHz, became 250mS @ 64MHz. I wanted 20 x 250mS (5S), so I set TIMER to 65535-19 (19 MAJOR+1 minor) and SETTIMER to 3036. I was never completely clear why it wasn't 65535-20 instead, but 250mS was neither here nor there in my application, so I never pursued it further).
 
Last edited:

inglewoodpete

Senior Member
Attached is a (cut-down) piece of code that I used for a GPS data receiver. It used both the hardware (background) serial UART and the background timer, ticking at 125mS. Both features used interrupt flags.

To make the code work, you can add an LED. While coded for a LED on C.3, this can easily be changed in the symbol area.
Code:
[color=Green]'GPS Signal receiver decoder [/color]
[color=Blue]Symbol Version [/color][color=DarkCyan]= [/color][color=Navy]3  [/color][color=Green]'28-Jan-2018  225 bytes Cut down as background timer example
'[/color]
[color=Blue]Symbol Major [/color][color=DarkCyan]= [/color][color=Navy]0    [/color][color=Green]' Major revision ID
'[/color]
[color=Navy]#PICAXE [/color][color=Black]28X2[/color]
[color=Navy]#COM 1
#Terminal 19200[/color]
[color=Green]'[/color]
[color=Navy]#No_Table[/color]
[color=Green]'
' **** Hardware Pins Definitions - i prefix for inputs; o for outputs; b for bothway pins
'[/color]
[color=Blue]Symbol oRedLED       [/color][color=DarkCyan]= [/color][color=Blue]C.3
Symbol [/color][color=Purple]oPinValRedLED [/color][color=DarkCyan]= [/color][color=Purple]outpinC.3[/color]
[color=Green]'
' **** Variables - t prefix: bit variable; b: byte; w: word; r: other RAM; s: scratchpad; e: EEPROM
'[/color]
[color=Blue]Symbol [/color][color=Purple]tFlashRed     [/color][color=DarkCyan]= [/color][color=Purple]bit4   [/color][color=Green]'b0,w0 Flag to flash Red LED[/color]
[color=Blue]Symbol [/color][color=Purple]tRFlashState  [/color][color=DarkCyan]= [/color][color=Purple]bit5   [/color][color=Green]'b0,w0 Current Red LED State (if flashing)
'[/color]
[color=Blue]Symbol [/color][color=Purple]bLoopCtr      [/color][color=DarkCyan]= [/color][color=Purple]b4     [/color][color=Green]'w2
'[/color]
[color=Blue]Symbol [/color][color=Purple]bEighthSecs   [/color][color=DarkCyan]= [/color][color=Purple]b51    [/color][color=Green]'w19  v0.16 1/8 Seconds (125mS Tick)[/color]
[color=Blue]Symbol [/color][color=Purple]bSeconds      [/color][color=DarkCyan]= [/color][color=Purple]b52    [/color][color=Green]'w25
'
' **** Constants - Prefix = c
'[/color]
[color=Blue]Symbol False         [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]Symbol True          [/color][color=DarkCyan]= [/color][color=Navy]1[/color]
[color=Blue]Symbol Out           [/color][color=DarkCyan]= [/color][color=Navy]1      [/color][color=Green]'Link is out: Pin is pulled high by internal pullup[/color]
[color=Blue]Symbol In            [/color][color=DarkCyan]= [/color][color=Navy]0      [/color][color=Green]'Link is in: Pin is pulled low by the link[/color]
[color=Blue]Symbol cDataReady    [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]Symbol cNoData       [/color][color=DarkCyan]= [/color][color=Navy]1[/color]
[color=Blue]Symbol cNoBreak      [/color][color=DarkCyan]= [/color][color=Navy]0[/color]
[color=Blue]Symbol cBreak        [/color][color=DarkCyan]= [/color][color=Navy]1[/color]
[color=Blue]Symbol cDQuote       [/color][color=DarkCyan]= [/color][color=Navy]34[/color]
[color=Green]'
'Interrupt masks[/color]
[color=Blue]Symbol mskSerialOnly [/color][color=DarkCyan]= [/color][color=Navy]%00100000[/color]
[color=Blue]Symbol flgSerialOnly [/color][color=DarkCyan]= [/color][color=Navy]%00100000[/color]
[color=Blue]Symbol mskTmrAndSer  [/color][color=DarkCyan]= [/color][color=Navy]%10100000[/color]
[color=Blue]Symbol flgTmrAndSer  [/color][color=DarkCyan]= [/color][color=Navy]%10100000[/color]
[color=Blue]Symbol mskBGTimer    [/color][color=DarkCyan]= [/color][color=Navy]%10000000[/color]
[color=Blue]Symbol flgBGTimer    [/color][color=DarkCyan]= [/color][color=Navy]%10000000[/color]
[color=Green]'Timer constants[/color]
[color=Blue]Symbol tmrIntOn1stTick [/color][color=DarkCyan]= [/color][color=Navy]65535   [/color][color=Green]'Interrupt to be caused by roll over on first major tick[/color]
[color=Blue]Symbol t125mS_16     [/color][color=DarkCyan]= [/color][color=Navy]57724     [/color][color=Green]'SetTimer value for 1/8 second ticks @ 16MHz[/color]
[color=Blue]Symbol cOneMinute    [/color][color=DarkCyan]= [/color][color=Navy]60[/color]
[color=Blue]Symbol cOneHour      [/color][color=DarkCyan]= [/color][color=Navy]60        [/color][color=Green]'Minutes, not seconds
'
'Pause periods at 16MHz[/color]
[color=Blue]Symbol c100mS        [/color][color=DarkCyan]=  [/color][color=Navy]200      [/color][color=Green]' 100mS[/color]
[color=Blue]Symbol c1S           [/color][color=DarkCyan]= [/color][color=Navy]2000      [/color][color=Green]'1000mS
'
' **** Scratchpad - Prefix = s (28X2 - Bytes 0 to 1023d)
'[/color]
[color=Blue]Symbol sSerInBuffStart  [/color][color=DarkCyan]= [/color][color=Navy]0      [/color][color=Green]'[/color]
[color=Blue]Symbol sSerInBuffSecond [/color][color=DarkCyan]= [/color][color=Navy]1      [/color][color=Green]'Second byte of serial input buffer
'[/color]
[color=Black]Init: [/color][color=Blue]Output oRedLED
      Low oRedLED
      SetFreq m16
      Pause c1S
      [/color][color=Green]'
      [/color][color=Blue]For [/color][color=Purple]bLoopCtr [/color][color=DarkCyan]=  [/color][color=Navy]1 [/color][color=Blue]to [/color][color=Navy]16       [/color][color=Green]'8 flashes
         [/color][color=Blue]Pause c100mS               [/color][color=Green]'Put Pause first to allow SetFreq to settle
         [/color][color=Blue]Toggle oRedLED
      Next [/color][color=Purple]bLoopCtr
      [/color][color=Blue]SerTxd (CR[/color][color=Black], [/color][color=Blue]LF[/color][color=Black], [/color][color=Blue]CR[/color][color=Black], [/color][color=Blue]LF[/color][color=Black], [/color][color=Red]"Booted: GPS Data Receiver v"[/color][color=Black], #[/color][color=Blue]Major[/color][color=Black], [/color][color=Red]"."[/color][color=Black], #[/color][color=Blue]Version[/color][color=Black], [/color][color=Blue]CR[/color][color=Black], [/color][color=Blue]LF)
      [/color][color=Green]'
      'Initialise serial downlink for GPS comms
      [/color][color=Purple]Ptr [/color][color=DarkCyan]= [/color][color=Blue]sSerInBuffStart
      [/color][color=Purple]hSerPtr [/color][color=DarkCyan]= [/color][color=Blue]sSerInBuffStart
      hSerSetup B9600_16[/color][color=Black], [/color][color=Navy]%00001    [/color][color=Green]'9600 baud @ 16MHz, Background, no inversion
      '              %abcde where, for X2 chips:
      '              Bit e (bit 0): Foregrd/Backgrd mode e=0 foreground; e=1*background
      '              Bit d (bit 1): Transmit mode -      d=0*No invert;  d=1 Invert transmit
      '              Bit c (bit 2): Receive  mode -      c=0*No invert;  c=1 Invert receive
      '              Bit b (bit 3): disable hserout      b=0 enable;     b=1 disable
      '              Bit a (bit 4): disable hserin       a=0 enable;     a=1 disable
      '
      'Start the background timer (runs continuously)
      [/color][color=Purple]Timer [/color][color=DarkCyan]= [/color][color=Blue]tmrIntOn1stTick
      SetTimer t125mS_16            [/color][color=Green]'Expires after 1/8 second @ 16 MHz
      [/color][color=Purple]Flags [/color][color=DarkCyan]= [/color][color=Navy]0                     [/color][color=Green]'Reset serial reception flag
      [/color][color=Blue]SetIntFlags [/color][color=DarkCyan]Or [/color][color=Blue]flgTmrAndSer[/color][color=Black], [/color][color=Blue]mskTmrAndSer [/color][color=Green]'Set timer 0 or hSerial to interrupt
      '
      [/color][color=Purple]tFlashRed [/color][color=DarkCyan]= [/color][color=Blue]True
      SerTxd ([/color][color=Red]"Initialisation Complete: Enter Main Loop"[/color][color=Black], [/color][color=Blue]CR[/color][color=Black], [/color][color=Blue]LF)
      [/color][color=Green]'
      ' ------ MAIN LOOP
      '
      [/color][color=Blue]Do
         [/color][color=Green]'Main loop code goes here
      [/color][color=Blue]Loop[/color]
[color=Green]'[/color]
[color=Blue]Interrupt:If [/color][color=Purple]hSerInFlag [/color][color=DarkCyan]= [/color][color=Blue]True then
            [/color][color=Purple]hSerInFlag [/color][color=DarkCyan]= [/color][color=Blue]False
          EndIf
          If [/color][color=Purple]TOFlag [/color][color=DarkCyan]= [/color][color=Blue]True then
            [/color][color=Purple]TOFlag [/color][color=DarkCyan]= [/color][color=Blue]False                            [/color][color=Green]'Reset (clear) the flag first
            [/color][color=Blue]Inc [/color][color=Purple]bEighthSecs
            bEighthSecs [/color][color=DarkCyan]= [/color][color=Purple]bEighthSecs [/color][color=DarkCyan]And [/color][color=Navy]%00000111   [/color][color=Green]'Limit to 0 - 7
            [/color][color=Blue]If [/color][color=Purple]bEighthSecs [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]Then                   [/color][color=Green]'Ie Once every second
               [/color][color=Blue]If [/color][color=Purple]tFlashRed [/color][color=DarkCyan]= [/color][color=Blue]True Then               [/color][color=Green]'Flash the red LED
                  [/color][color=Blue]Inc [/color][color=Purple]tRFlashState
                  oPinValRedLED [/color][color=DarkCyan]= [/color][color=Purple]tRFlashState
               [/color][color=Blue]EndIf
               Inc [/color][color=Purple]bSeconds
            [/color][color=Blue]EndIf
            [/color][color=Purple]Timer [/color][color=DarkCyan]= [/color][color=Blue]tmrIntOn1stTick                   [/color][color=Green]'Then reset the timer
          [/color][color=Blue]EndIf    [/color][color=Green]'Timer has ticked
          [/color][color=Blue]SetIntFlags [/color][color=DarkCyan]Or [/color][color=Blue]flgTmrAndSer[/color][color=Black], [/color][color=Blue]mskTmrAndSer   [/color][color=Green]'Set timer 0 or hSerial to interrupt
          [/color][color=Blue]Return[/color]
 
Last edited:

inglewoodpete

Senior Member
However, I'm trying to implement an interrupt based on the timer in slot 3. The code compiles fine, and runs, but totally ignores the interrupt. I'm probably missing something, but can't see it. Advice on how to set up this interrupt would be appreciated.
Just re-read your post - slot 3. Do you have the interrupt handler in each of the four slots? A timer interrupt may occur at any time and there needs to be a valid interrupt handler available should the interrupt occur in any slot.

Note that my previous reply is still valid, demonstrating the timer tick interrupt that Phil discusses.
 

PhilHornby

Senior Member
A timer interrupt may occur at any time and there needs to be a valid interrupt handler available should the interrupt occur in any slot.
Wouldn't a "RUN n" command effectively disable any interrupts though?

I've not used a 28X2, and the 20X2 only has one slot - but I've done quite a lot playing with the 14M2 (which has two slots). Although it's not documented, I got the impression from my experiments, that the hardware state was reset to default on entering a new slot - with the exception of RAM, which is left intact.

UPDATE - Pin states aren't reset by "RUN n" either.
 
Last edited:

inglewoodpete

Senior Member
Wouldn't a "RUN n" command effectively disable any interrupts though?
I think you're right. It's been about 3 years since I did the multi-slot 40X2 project. To capture a timer interrupt, the interrupt needs to be initialised and executed in each slot. Multi-slot working can get mighty complicated!
 

hippy

Technical Support
Staff member
TIMER is thus incremented every 0.1S, until it overflows from 65535 -> 0. But since it's starting at zero, this will be in 65536 x 0.1 = 6553.6Secs (1.8 hours :confused: )
That would be my analysis.

Code:
#Picaxe 28X2
#Terminal 9600
#Slot 3

SetTimer T1S_8
Gosub Interrupt_Enable:
Do
Loop

Interrupt:
  SerTxd( "IRQ " )
Interrupt_Enable:
  toFlag = 0
  timer = $FFFF
  SetIntFlags $80, $80
  Return
Code:
#Picaxe 28X2
#Terminal 9600
#Slot 0
Run 3
 

PhilHornby

Senior Member
Is there a recommendation, as to whether to go for one long tick, or lots of shorter ticks? (i.e. 1 x 0.1Sec vs 10 x 0.01Sec or even 100 x 0.001Sec)

I'm wondering if there is an overhead on the processor from short ticks ... but maybe with an increase in accuracy?
 

johndk

Senior Member
Thanks for all the comments. My major error was a logical one. I was assuming the ToFlag was set on minor tick overflows, not major. So setting the timer to $FFFF not 0 was required to get the ToFlag set. Also, in response to other comments, the interrupts DO get wiped on slot changes. But I have accounted for that. The interrupt I want is in slot 3 and only slot 3.

Having said that, my interrupt is still not working. So there must be something else I'm overlooking. Even Hippy's code (which almost never fails) did not perform the required interrupt. I tried several different settimer values, none of which had any effect. The total time spent in slot 3 is 1.4s So I should have had an interrupt even with Hippy's T1S_8 value.

All I'm doing in this slot is a number of sensor readings using the hi2c calls. I'm getting an unexplained hang every once in a great while (days sometimes weeks of continuous operation) that puts my remote sensor in a non-operative state except for using up battery. My clever work-around was going to be to use the interrupt to time out the slot during such a hang and return to normal operations in slot 0.

Yes, I can already hear you. That's a cheat and I should fix the problem instead. That IS my intention ... but in the meantime, my clever hack should work, no?

Any ideas?
 

hippy

Technical Support
Staff member
Is there a recommendation, as to whether to go for one long tick, or lots of shorter ticks? (i.e. 1 x 0.1Sec vs 10 x 0.01Sec or even 100 x 0.001Sec)
I would say one long tick would be better. T1S_8 would interrupt your PICAXE program once for a one second interval. Why have 10, 100 or more interrupts to achieve the same thing ?

There's overhead for every tick but more so for more frequent ticks, and the accuracy probably decreases with shorter ticks. If there is 1us lost per tick that's almost nothing over a one second period with one tick, but a full millisecond if you had a 1,000 ticks in the same period.
 

hippy

Technical Support
Staff member
Even Hippy's code (which almost never fails) did not perform the required interrupt. I tried several different settimer values, none of which had any effect.
I tested that on a physical 28X2 before posting so I guess there's something with your code affecting things.
 

johndk

Senior Member
PROBLEM SOLVED.
I found the problem in my slot code. I had transplanted a sub from another slot (need to repeat functions often going between slots). In that function I was updating my clock for which I'm using 'timer' in the other slots. So I was updating the timer value with the current second, ... i.e. no interrupt ever happened. Disabled that setting in slot 3 and viola, interrupt.

Thanks everyone for the comments.
 
Top