using interrupt pin as general input

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Apologies in advance if this newbie question has already been asked and answered.

I want to know if a pin configured as an external interrupt (eg. INT0) can also be used as a general digital input while the ISR (interrupt service routine) is in progress. I mean whether SBIC and SBIS will still work. Will the timings for these change in any way? Should I bite the bullet and just use another port pin?

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm pretty sure this is independent of the actual AVR being used, but if anyone needs to know, it is ATTiny2313, running at 20MHz.

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes, you can still read the pin value, no matter how the pin is configured, or alternate function being used.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks.

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm still having trouble with this. :( I'm feeding a pulse train into PD2 (INT0 on the tn2313). The first pulse (start pulse) triggers the interrupt, then the ISR reads the subsequent pulses. The pulse width is three clock cycles, but even if I send all 1s (effectively a single pulse 15 clock cycles wide, read 5 times by the ISR, the ISR is reading all pulses as 0s.

The interrupt is working fine, (low level on INT0) but the port is always reading low (SBIC and SBIS). :(

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is awfully fast. The MINIMUM time to get to the first instruction of a "naked" ISR is nearly the 15-cycle pulse width. If you use the infinite-value compiler brand, and/or do anything significant in the ISR, the SREG and used register saving can perhaps be several dozen more cycles.

Are you trying to count pulses? I'd suggest using Tn and a separate trigger to indicate the start of a pulse train and then stop counting after the appropriate time (perhaps with ICP).

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When the ISR invokes, you need to disable the interrupt until you are ready to exit the ISR, otherwise the avr will try to invoke teh ISR again.

the first line of code in your ISR should be

CLI

Then the last lines should be:

SEI
RETI

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

When the ISR invokes, you need to disable the interrupt until you are ready to exit the ISR, otherwise the avr will try to invoke teh ISR again.

the first line of code in your ISR should be

CLI

Then the last lines should be:

SEI
RETI


Simply untrue, inaccurate, and also opens the door to cascading interrupts and stack windup.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:
When the ISR invokes, you need to disable the interrupt until you are ready to exit the ISR, otherwise the avr will try to invoke teh ISR again.

the first line of code in your ISR should be

CLI

Then the last lines should be:

SEI
RETI

Jim

Jim, the processor disables interrupts for you, when it enters into the ISR. Unless using an old verison of GCC, (and using INTERRUPT) the compiler does not turn them back on either. So there is no need for a manual CLI in a handler.

Yes you need a RETI at the end. If using C the compiler will autmatically add this for you. RETI re-enable interrupts, so there is no need for SEI at the end either. And as Lee stated it is dangerious to do so, as manually enabling CLI can allow a 2nd interrupt to execute before the first one has fully returned, potentially leading to stack overflows. Though technically if the SEI is the VERY LAST instruction before RETI, then it is still safe. The side effect being is that the main loop is completely starved of any execution cycles. (at minimum one instruction will execute after a SEI before the next interrupt happens)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Lee stated it is dangerious to do so, as manually enabling CLI can allow a 2nd interrupt to execute before the first one has fully returned

Glitch:
'CLI' does not enable interrupts, It disables them.
Also, you pointed out how things are handled in 'c'. I use assembler, but I don't think that has any bearing in theis case.

Lee:
Since the processor already has disabled then what is the big deal of an extra 'CLI' as the first line of teh ISR?

Well, ok then. If I am wrong then so be it. learn something new everyday

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The interrupts are periodic, so I'm pretty safe there. Also, I'm giving ample delay before reading the port pin, I think. AFAIK it takes about 6 clock cycles to respond to an interrupt (not 15 - I'm doing it in assembly language, so maybe that's where our calculations differ).

This has been confirmed using an oscilloscope, as for debugging purposes the first instruction of the ISR is to send a port pin HIGH, and I send that port pin LOW just before I exit the ISR, so I have a nice rectangular wave to look at.

This is a frame based bidirectional uC to uC single wire interface, so I'm counting clock cycles at both ends.

There is a 1 cycle uncertainty at interrupt (due to the fact that the current instruction is executed before the interrupt is registered, and at least one of the instructions in a wait loop is a 2 cycle instruction).

There is another 1 cycle uncertainty while reading the data on the port pin (due to the synchronizer that is there to prevent 'metastability') so if the pulse is 3 clock cycles wide, the resulting jitter shouldn't matter.

My point is, if I'm sampling a 15 cycle wide pulse 5 times, at least one of the freaking samples should be high, shouldn't it? (we need a wallbash icon for this forum)

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,

But what's the point in wasting an unneeded opcode it wastes both space and performance ?

And while SEI may be safe if immediately preceding the RETI it's pointless for the same reasons and dangerous if someone later decides to add something in between the SEI and RETI.

Personally I'd let the AVR do the CLI as it jumps via the vector and leave the RETI to provide the SEI. (unsurprisingly that's exactly what C compilers choose to do)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff,
I did not say I was right, I even said that two posts up. Agreed if the processor does it automatically then fine.

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

More to the point, perhaps:

Global interrupt enable is automatically cleared when every ISR is executed and is enabled, again, as part of the reti.

HOWEVER, if there are interrupt creating events while an ISR is executing, the corresponding interrupt bit will still be set. And, as soon as the reti is executed, it will enter the next ISR. Thus, if there are interrupt enabling events during the ISR, of the sort suggested by the original post, it would be good to clear that interrupt flag bit as one of the last actions before returning from the interrupt. Otherwise, the ISR will re-execute based on an "old" interrupt. Another way to deal with this would be to disable the generation of that interrupt flag bit at the start of the ISR and turn it back on again at the end.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very true, but we are going off topic a little. I have just the one interrupt, that is completely serviced before the next interrupt comes along.

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, other "digital inputs" on a pin that is enabled as an interrupt pin could cause additional interrupt events!

jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I >>was<< on-topic. Show your ISR, the generated code, and tell again about this pulse width. Chances are it is long gone before you try anything useful inside the ISR.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Well, other "digital inputs" on a pin that is enabled as an interrupt pin could cause additional interrupt events!

Er.. not according to the datasheet.
Quote:
When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts
are disabled.

As soon as an interrupt is acknowledged and the ISR begins, interrupts are disabled. They get re-enabled by the RETI, or by an SEI if nested interrupts are desired.

*code coming next*

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Prior to interrupt:

clr r26 ;all bits low, will be set by ISR

ISR:

XINT0:
sbi PORTD,5 ;send PD5 high for debugging (INT ACK)
nop ;padding for synchronisation as needed.
nop
sbic PORTD,2 ;skip if data in is low 
ori r26,0b00010000 ;set r26 bit 4
nop
sbic PORTD,2 
ori r26,0b00001000 ;set r26 bit 3
nop
sbic PORTD,2 
ori r26,0b00000100 ;set r26 bit 2
nop
sbic PORTD,2 
ori r26,0b00000010 ;set r26 bit 1
nop
sbic PORTD,2 
ori r26,0b00000001 ;set r26 bit 0
nop
cbi PORTD,5 ;send PD5 low for debugging (end INT ACK)
reti

The lower 5 bits of r26 should now contain the data received.

PD5 (INT ACK) goes high about 6-8 clock cycles after INT0 goes low. PD5 goes low before INT0 goes high again, so INT0 is NOT being retriggered.

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your naked ISR should hit in about 10 cycles on the average. Is your pulse longer than that?

If there is ANY meaningful code in the main loop, then you must preserve and restore SREG.

And, #1 on the Top Ten list, read PIN, write PORT.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

And, #1 on the Top Ten list, read PIN, write PORT.

Thanks, I'll try that. :)

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:

Glitch:
'CLI' does not enable interrupts, It disables them.
Also, you pointed out how things are handled in 'c'. I use assembler, but I don't think that has any bearing in theis case.

That was a brain glitch... I meant SEI there. Note that I describe CLI and SEI correctly in the rest of my response. Sorry for the mistake.

I was pointing out both assembler and C, since the OP did not state which he was using.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I work exclusively in assembly language. Tried learning C once but got thoroughly confused by the plethora of C variants out there. :P

Sorry for the delay. Different time zones, etc. By the time I had finished backing up and changing the project version number, then changing all the PORT reads to PIN reads, it was time for bed. Will get on with it right after breakfast.

If you think education is expensive, try ignorance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
And, #1 on the Top Ten list, read PIN, write PORT.
Lee

Thank you, thank you, thank you!

This worked. I still have to do a bit of tweaking, but at least I'm getting something. :D

:oops: I knew I was doing something stupid. :oops:

If you think education is expensive, try ignorance.