...
What if those L bits in the interrupt mode settings caused automatic ILOCK on entry and IFREE on exit?
Yes, I think everyone figured that's exactly what you had in mind. Which is why Jmg asked to also have an additional software settable IRQ mask that's OR'd with the automatic one. Both needing to be reset (or set) for the IRQ to be unmasked.
Excellent idea about qualifying the automatic IFREE with that interrupt's enable. Is this 'Automatic' a user option ?I can think of use cases where cog non-int code wants to steal a little time from an INT to finish something important, but does not want to kill the INT totally. A delayed IFREE would be a means to do that. Automatic IFREE that cannot be disabled, could bite.
Another question:
How many clock cycles should last a changing pin value, before being detected as "any edge"?
Is this value latched anywhere?
Yanomani
If the pin went from high to low, or vice-versa, that's "any edge". I was always registering two cycles of a pin, so that I'd have something to look at: a one-clock-ago state and a two-clocks-ago state. I just compare those two for 0-to-1, 1-to-0, or difference ("any edge").
I was expecting any denouncing to be done in sw (or external RC circuit). Chip, so what you are doing is fine by me.
Not sure if denouncing can be done by the smart pins and would this change the interrupt pin change function?
Anyway, what you have done is easy to document and explain, be easy to use, and at the same time answer the critics. And we have 16 cogs of these options!
You may have meant that action, rather than a physical change of a user IFREE flag ?
With automatic initial ILOCK and terminal IFREE, wouldn't this be about the same?
Are you meaning 'automatic', as in implicit in the state engine, and not actually wiggling the user IFREE ?ie the hardware automatically avoids a stream of re-interrupts, of the same interrupt.
I think I'd need to see some examples .... of all 3 sources firing, at different rates.
cgracey said:
Jmg is thinking about a sort of handover to a task - in a multitasking OS. Where that targeted task will be guarenteed to jump to highest priority and finish up the processing while still holding the IRQ mask.
Some driver writers like to own the IRQ.
Well, that would imply that after that special OS routine completes, then the effective return-from-interrupt would execute, in order to get back to the original interrupted code. Wouldn't the ILOCK'd interrupt handler call the OS routine, somehow, and then do the JMP $1Fx instruction, causing an automatic IFREE?
No, I was talking about (I think I understood Jmg's request correctly) being able to mask individual IRQ numbers in the Intel interrupt controllers. Then when the ISR returns the individual IRQ# is still masked and it's up to the ordinary tasks, presumably inside the driver, to handle the unmasking at a later time. EDIT: And, contrary to what I said earlier, it don't have to be a high priority task.
In a proper shared design one would mask the source of the IRQ rather than the IRQ itself.
ie the hardware automatically avoids a stream of re-interrupts, of the same interrupt
Chip's design is using edge detect so they can't re-arm without a state change from the IRQ source.
Sure, but imagine you have interrupt code that takes 10us, fed from a pin toggling at 200KHz.State engine HW is needed to avoid re-trigger, delaying until a RETR, then INT will Fire again from the queued Flag, and will execute (how many? 1?) main routine opcodes during the re-entry.
You cannot expect the real world to always behave, so the silicon needs to be designed to manage this.
There are also designs that deliberately over-run/discard some information sometimes.(I've just done a flash programmer that does exactly that. During PGM time, it discards any Rx Data , recovering when done. )
Hardware debounce would be of limited use unless it was adjustable. Push button switches can have wildly different debounce periods. Some settle quickly while others seem to rattle around for ages.
I perform the action immediately when a button press is sensed and delay for debounce AFTER the action has been completed. My rational is that a button doesn't change state unless the user has pressed it.
Alex,
The IRQ hold-off timer, which was adjustable, is gone now. Replaced by the optional automatic IRQ masking during ISR execution.
Something like keyswitch debounce can be done well in software. That's a good example of where timer interrupts are often used. Ie: Regularly scan the keypad matrix and then apply a debounce to the results.
I got the new system all implemented and it seems to work fine. Oh, and the compiled design got smaller by 30 LE's! This system is quite a bit simpler on the inside. It was way easier to think about.
Here are the new instructions:
INTPER D/# set period for timer interruptINTPIN D/# set pin for edge interruptINTMODE D/# set interrupt modeINTMASK D/# set interrupt mask via d[0] - IFREE/ILOCK
mode %LSS_LPP_LTT
%LSS = streamer interrupt, issues 'LINK $1F0,$1F1 WC,WZ' L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F0 WC WZ' SS: x0 = disable, 01=rollover, 11=block wrap
%LPP = pin edge interrupt, issues 'LINK $1F2,$1F3 WC,WZ'
L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F2 WC,WZ' PP: 00 = disable, 01=any edge, 10=pos edge, 11=neg edge
%LTT = timer interrupt, issues 'LINK $1F4,$1F5 WC,WZ' L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F4 WC,WZ' TT: x0 = disable, 01=initialize and enable, 11=enable
I got the new system all implemented and it seems to work fine. Oh, and the compiled design got smaller by 30 LE's! This system is quite a bit simpler on the inside. It was way easier to think about.Looks good.
How does it run if you toggle the ButtonPin inside the Timer Int (ie flip 2 pins - TimerOUT and PB_in).
That should show int-nesting and int-handover operations.
Thanks for your ongoing interest, Guys.
All these ideas and enthusiasm you have just keep making things better, all around. This is way more stimulating and productive than working alone. Sometimes, working alone is necessary, but otherwise, this is the way to go.
I got the new system all implemented and it seems to work fine. Oh, and the compiled design got smaller by 30 LE's! This system is quite a bit simpler on the inside. It was way easier to think about.Looks good.
How does it run if you toggle the ButtonPin inside the Timer Int (ie flip 2 pins - TimerOUT and PB_in).
That should show int-nesting and int-handover operations.
I haven't tested that, yet, but I'm quite sure it would work, as it's no different than interrupting main code. I would like to test and observe the automatic ILOCK/IFREE assertions (L=1). I'm pretty tired now, though, so I'll do it later.
Do you think we are lacking any helpful masks, or anything? One thing that can be done to mask a source is to just turn it off, and then back on later. It works like a newbie would imagine.
I don't think there are any hidden, gotchas. If you do an INTPIN and switch to another pin which happens to be in the opposite state of the prior pin, the edge sensor won't wrongly trigger because it will wait for two clocks to get two new pin samples. And you can do an INTPER any time. When the timer reloads, it will grab the last-written value.
It seems complete, to me, but there may be some thing(s) missing. Timer and streamer interrupts are quite safe, but pin interrupts can potentially bring things to a halt. Do you think we need some hold-off counter to delay when the next pin interrupt is registered? Pin interrupts concern me.
One thing that can be done to mask a source is to just turn it off, and then back on later. It works like a newbie would imagine.
Good point! That's as good as software setting the mask right there. Just use the INTMODE instruction to temporarily turn off the generation.
It's not a normal CPU feature to have local config for the interrupt source like that so people aren't thinking of it when considering how to handle this. I certainly wasn't.
So, IFREE and ILOCK become variants of INTMODE. And INTMASK goes away.
I thought about some nonsensical INTMODE data pattern being used for IFREE/ILOCK, but it just seemed easier to give it a whole instruction. Do you see a nice way to exploit INTMODE for that purpose?
As in the programmer can easily mess up the value in D field? That's true in the first config instance too ...
I was thinking the assembler could probably hide the numerical detail for typical constructs. Dunno, I don't have a clear visual in my head either. Also ready for bed.
As in the programmer can easily mess up the value in D field? That's true in the first config instance too ...
I was thinking the assembler could probably hide the numerical detail for typical constructs. Dunno, I don't have a clear visual in my head either. Also ready for bed.
Maybe it would be good to break INTMODE into three different instructions: INTXFER, INTEDGE, INTIMER
Seems reasonable, given the three are/have become somewhat independent of each other. This can be an assembler thing still though. Keep INTMODE as the base like JMPRET is the base for other instructions.
Seems reasonable, given the three are/have become somewhat independent of each other. This can be an assembler thing still though. Keep INTMODE as the base like JMPRET is the base for other instructions.
That won't work. What would the INTEDGE instruction place in the INTMODE fields for XFER and TIMER?
Do you think we are lacking any helpful masks, or anything? One thing that can be done to mask a source is to just turn it off, and then back on later. It works like a newbie would imagine.
If you are suggesting that INTMASK could instead be performed by disabling an interrupt with INTMODE, I think that's a bad idea. First of all, INTMASK does not prevent the interrupt from triggering, just delays when the associated LINK is inserted into the pipeline. Temporarily disabling an interrupt with INTMODE causes the code to miss an interrupt altogether. There are use case for both approaches, so I would keep INTMASK.
Also, if you use INTMODE, it means that code will have to track whether a specific interrupt was enabled prior to disabling it, so that it can know whether to enable it again later. INTMASK, on the other hand, can be performed without that knowledge.
It seems complete, to me, but there may be some thing(s) missing. Timer and streamer interrupts are quite safe, but pin interrupts can potentially bring things to a halt. Do you think we need some hold-off counter to delay when the next pin interrupt is registered? Pin interrupts concern me.
Yeah, the lack of a hold-off for pin interrupts concerns me too. If a pin interrupt handler is interrupted with another pin interrupt, you will never return to the "main" thread (the original return address was lost) and the first interrupt handler will repeatedly jump to itself at whatever point the second interrupt had interrupted it. Not good.
Of course, you can auto-lock the pin interrupt, which would prevent this behavior, but you could still end up with a spurious edge transition causing a pending interrupt that you don't really want. You could disable the interrupt altogether, but this has similar issues to those I described in a prior post.
It makes me wonder if the mask needs to be two bits:
00 : not masked01 : delay LINK insertion1- : ignore
The auto-mask bits in INTX, INTP, and INTT (or whatever) would also be two bits.
Comments
A qualifier count, to filter out unwanted edge transitions.
Well, how many are unwanted is the question, I think.
What if those L bits in the interrupt mode settings caused automatic ILOCK on entry and IFREE on exit?
Yes, I think everyone figured that's exactly what you had in mind. Which is why Jmg asked to also have an additional software settable IRQ mask that's OR'd with the automatic one. Both needing to be reset (or set) for the IRQ to be unmasked.
I'm personally thinking it's a bit overkill.
Excellent idea about qualifying the automatic IFREE with that interrupt's enable. Is this 'Automatic' a user option ?I can think of use cases where cog non-int code wants to steal a little time from an INT to finish something important, but does not want to kill the INT totally. A delayed IFREE would be a means to do that. Automatic IFREE that cannot be disabled, could bite.
Another question:
How many clock cycles should last a changing pin value, before being detected as "any edge"?
Is this value latched anywhere?
Yanomani
If the pin went from high to low, or vice-versa, that's "any edge". I was always registering two cycles of a pin, so that I'd have something to look at: a one-clock-ago state and a two-clocks-ago state. I just compare those two for 0-to-1, 1-to-0, or difference ("any edge").
I was expecting any denouncing to be done in sw (or external RC circuit). Chip, so what you are doing is fine by me.
Not sure if denouncing can be done by the smart pins and would this change the interrupt pin change function?
Anyway, what you have done is easy to document and explain, be easy to use, and at the same time answer the critics. And we have 16 cogs of these options!
You may have meant that action, rather than a physical change of a user IFREE flag ?
With automatic initial ILOCK and terminal IFREE, wouldn't this be about the same?
Are you meaning 'automatic', as in implicit in the state engine, and not actually wiggling the user IFREE ?ie the hardware automatically avoids a stream of re-interrupts, of the same interrupt.
I think I'd need to see some examples .... of all 3 sources firing, at different rates.
cgracey said:
Jmg is thinking about a sort of handover to a task - in a multitasking OS. Where that targeted task will be guarenteed to jump to highest priority and finish up the processing while still holding the IRQ mask.
Some driver writers like to own the IRQ.
Well, that would imply that after that special OS routine completes, then the effective return-from-interrupt would execute, in order to get back to the original interrupted code. Wouldn't the ILOCK'd interrupt handler call the OS routine, somehow, and then do the JMP $1Fx instruction, causing an automatic IFREE?
No, I was talking about (I think I understood Jmg's request correctly) being able to mask individual IRQ numbers in the Intel interrupt controllers. Then when the ISR returns the individual IRQ# is still masked and it's up to the ordinary tasks, presumably inside the driver, to handle the unmasking at a later time. EDIT: And, contrary to what I said earlier, it don't have to be a high priority task.
In a proper shared design one would mask the source of the IRQ rather than the IRQ itself.
But none of this pertains to the Propeller.
Chip's design is using edge detect so they can't re-arm without a state change from the IRQ source.
Chip's design is using edge detect so they can't re-arm without a state change from the IRQ source.
Sure, but imagine you have interrupt code that takes 10us, fed from a pin toggling at 200KHz.State engine HW is needed to avoid re-trigger, delaying until a RETR, then INT will Fire again from the queued Flag, and will execute (how many? 1?) main routine opcodes during the re-entry.
You cannot expect the real world to always behave, so the silicon needs to be designed to manage this.
There are also designs that deliberately over-run/discard some information sometimes.(I've just done a flash programmer that does exactly that. During PGM time, it discards any Rx Data , recovering when done. )
I perform the action immediately when a button press is sensed and delay for debounce AFTER the action has been completed. My rational is that a button doesn't change state unless the user has pressed it.
The IRQ hold-off timer, which was adjustable, is gone now. Replaced by the optional automatic IRQ masking during ISR execution.
Something like keyswitch debounce can be done well in software. That's a good example of where timer interrupts are often used. Ie: Regularly scan the keypad matrix and then apply a debounce to the results.
Here are the new instructions:
INTPER D/# set period for timer interruptINTPIN D/# set pin for edge interruptINTMODE D/# set interrupt modeINTMASK D/# set interrupt mask via d[0] - IFREE/ILOCK
mode %LSS_LPP_LTT
%LSS = streamer interrupt, issues 'LINK $1F0,$1F1 WC,WZ' L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F0 WC WZ' SS: x0 = disable, 01=rollover, 11=block wrap
%LPP = pin edge interrupt, issues 'LINK $1F2,$1F3 WC,WZ'
L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F2 WC,WZ' PP: 00 = disable, 01=any edge, 10=pos edge, 11=neg edge
%LTT = timer interrupt, issues 'LINK $1F4,$1F5 WC,WZ' L: 1 = ILOCK on interrupt and IFREE on 'LINK D,$1F4 WC,WZ' TT: x0 = disable, 01=initialize and enable, 11=enable
Here is a program:
dat org
mov dira,#%111 'make pins 2..0 outputs
mov $1F5*4,#tmrint 'set timer interrupt vector mov $1F3*4,#pinint 'set pin interrupt vector
intper #100 'interrupt every 100 clocks intpin #31 'pushbutton input intmode #%011_001 'interrupt on pushbutton and timer
loop xor outa,#%001 'main loop, toggle pin 0 jmp @loop
tmrint xor outa,#%010 'timer interrupt, toggle pin 1 jmp $1F4*4 wc,wz 'return
pinint xor outa,#%100 'pin interrupt, toggle pin 2 jmp $1F2*4 wc,wz 'return
Here is what it looks like running (D2..D0 on the scope are pins 2..0 on the Prop2):
How does it run if you toggle the ButtonPin inside the Timer Int (ie flip 2 pins - TimerOUT and PB_in).
That should show int-nesting and int-handover operations.
All these ideas and enthusiasm you have just keep making things better, all around. This is way more stimulating and productive than working alone. Sometimes, working alone is necessary, but otherwise, this is the way to go.
How does it run if you toggle the ButtonPin inside the Timer Int (ie flip 2 pins - TimerOUT and PB_in).
That should show int-nesting and int-handover operations.
I haven't tested that, yet, but I'm quite sure it would work, as it's no different than interrupting main code. I would like to test and observe the automatic ILOCK/IFREE assertions (L=1). I'm pretty tired now, though, so I'll do it later.
Do you think we are lacking any helpful masks, or anything? One thing that can be done to mask a source is to just turn it off, and then back on later. It works like a newbie would imagine.
I don't think there are any hidden, gotchas. If you do an INTPIN and switch to another pin which happens to be in the opposite state of the prior pin, the edge sensor won't wrongly trigger because it will wait for two clocks to get two new pin samples. And you can do an INTPER any time. When the timer reloads, it will grab the last-written value.
It seems complete, to me, but there may be some thing(s) missing. Timer and streamer interrupts are quite safe, but pin interrupts can potentially bring things to a halt. Do you think we need some hold-off counter to delay when the next pin interrupt is registered? Pin interrupts concern me.
One thing that can be done to mask a source is to just turn it off, and then back on later. It works like a newbie would imagine.
Good point! That's as good as software setting the mask right there. Just use the INTMODE instruction to temporarily turn off the generation.
It's not a normal CPU feature to have local config for the interrupt source like that so people aren't thinking of it when considering how to handle this. I certainly wasn't.
I thought about some nonsensical INTMODE data pattern being used for IFREE/ILOCK, but it just seemed easier to give it a whole instruction. Do you see a nice way to exploit INTMODE for that purpose?
I was thinking the assembler could probably hide the numerical detail for typical constructs. Dunno, I don't have a clear visual in my head either. Also ready for bed.
I was thinking the assembler could probably hide the numerical detail for typical constructs. Dunno, I don't have a clear visual in my head either. Also ready for bed.
Maybe it would be good to break INTMODE into three different instructions: INTXFER, INTEDGE, INTIMER
Here are the new instructions:
Here is a program:
dat org
mov dira,#%111 'make pins 2..0 outputs
mov $1F5*4,#tmrint 'set timer interrupt vector mov $1F3*4,#pinint 'set pin interrupt vector
intper #100 'interrupt every 100 clocks intpin #31 'pushbutton input intmode #%011_001 'interrupt on pushbutton and timer
loop xor outa,#%001 'main loop, toggle pin 0 jmp @loop
tmrint xor outa,#%010 'timer interrupt, toggle pin 1 jmp $1F4*4 wc,wz 'return
pinint xor outa,#%100 'pin interrupt, toggle pin 2 jmp $1F2*4 wc,wz 'return
Hi Chip.
One compiler question.
Can You made in compiler pseudo codes for that returns ?
retit
retip
For simplicity of usage and readablity of programs
That won't work. What would the INTEDGE instruction place in the INTMODE fields for XFER and TIMER?
If you are suggesting that INTMASK could instead be performed by disabling an interrupt with INTMODE, I think that's a bad idea. First of all, INTMASK does not prevent the interrupt from triggering, just delays when the associated LINK is inserted into the pipeline. Temporarily disabling an interrupt with INTMODE causes the code to miss an interrupt altogether. There are use case for both approaches, so I would keep INTMASK.
Also, if you use INTMODE, it means that code will have to track whether a specific interrupt was enabled prior to disabling it, so that it can know whether to enable it again later. INTMASK, on the other hand, can be performed without that knowledge.
Yeah, the lack of a hold-off for pin interrupts concerns me too. If a pin interrupt handler is interrupted with another pin interrupt, you will never return to the "main" thread (the original return address was lost) and the first interrupt handler will repeatedly jump to itself at whatever point the second interrupt had interrupted it. Not good.
Of course, you can auto-lock the pin interrupt, which would prevent this behavior, but you could still end up with a spurious edge transition causing a pending interrupt that you don't really want. You could disable the interrupt altogether, but this has similar issues to those I described in a prior post.
It makes me wonder if the mask needs to be two bits:
00 : not masked01 : delay LINK insertion1- : ignore
The auto-mask bits in INTX, INTP, and INTT (or whatever) would also be two bits.
cgracey said:
Switching is probably 10% here, compared to what it was in P2-Hot.
Does this mean a P2-hot with gating would be warm only ??