avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-gcc-list] Newbie question


From: Weddington, Eric
Subject: RE: [avr-gcc-list] Newbie question
Date: Wed, 25 Feb 2009 09:27:11 -0700

 

> -----Original Message-----
> From: 
> address@hidden 
> [mailto:address@hidden
> org] On Behalf Of David VanHorn
> Sent: Wednesday, February 25, 2009 9:05 AM
> To: address@hidden
> Subject: [avr-gcc-list] Newbie question
> 
>  
> :)
>  
> Interrupt latency.
>  
> So my question is, how close can I get to my ASM approach, using C?

You'll probably have to whittle this down in steps.

See comments below.
  
>  
> 0000022D:   9508        RET                      Subroutine return
> @0000022E: __vector_1
> 450:      {
> +0000022E:   921F        PUSH      R1             Push 
> register on stack
> +0000022F:   920F        PUSH      R0             Push 
> register on stack
> +00000230:   B60F        IN        R0,0x3F        In from I/O location
> +00000231:   920F        PUSH      R0             Push 
> register on stack
> +00000232:   2411        CLR       R1             Clear Register
> +00000233:   938F        PUSH      R24            Push 
> register on stack
> +00000234:   939F        PUSH      R25            Push 
> register on stack
> +00000235:   93EF        PUSH      R30            Push 
> register on stack
> +00000236:   93FF        PUSH      R31            Push 
> register on stack
> 451:       if (Raw_Edge_Flag == 0)   // If this is the first time thru
> +00000237:   91800082    LDS       R24,0x0082     Load direct 
> from data space
> +00000239:   2388        TST       R24            Test for 
> Zero or Minus
> +0000023A:   F441        BRNE      PC+0x09        Branch if not equal
> 453:         TCNT1H=0;    // Timer starts at 0
> +0000023B:   BD8D        OUT       0x2D,R24       Out to I/O location
> 454:         TCNT1L=0;
> +0000023C:   BD8C        OUT       0x2C,R24       Out to I/O location
> 455:         Raw_Edge_Flag = 0xFF; // Next time is the end of a pulse
> +0000023D:   EF8F        SER       R24            Set Register
> +0000023E:   93800082    STS       0x0082,R24     Store 
> direct to data space
> 456:         Debug_DDR  |= (1 << Debug_Pin); // Output
> +00000240:   9A8D        SBI       0x11,5         Set bit in 
> I/O register
> 457:         Debug_Port |= (1 << Debug_Pin); // High
> +00000241:   9A95        SBI       0x12,5         Set bit in 
> I/O register

I know that it's not adding much code, but can you remove (comment out) your 
debug statements, like above? I noticed there are more below, too.


> 458:         return;
> +00000242:   C020        RJMP      PC+0x0021      Relative jump
> 462:         Raw_Data[0][Raw_Data_In_Index] = TCNT1;
> +00000243:   91800083    LDS       R24,0x0083     Load direct 
> from data space
> +00000245:   2FE8        MOV       R30,R24        Copy register
> +00000246:   27FF        CLR       R31            Clear Register
> +00000247:   0FEE        LSL       R30            Logical Shift Left
> +00000248:   1FFF        ROL       R31            Rotate Left 
> Through Carry
> +00000249:   57EC        SUBI      R30,0x7C       Subtract immediate
> +0000024A:   4FFF        SBCI      R31,0xFF       Subtract 
> immediate with carry
> +0000024B:   B58C        IN        R24,0x2C       In from I/O location
> +0000024C:   B59D        IN        R25,0x2D       In from I/O location
> +0000024D:   8391        STD       Z+1,R25        Store 
> indirect with displacement
> +0000024E:   8380        STD       Z+0,R24        Store 
> indirect with displacement

Your assignment into an array seems to generate a lot of code. Is there any way 
that you can just use some dedicated global variables while in the ISR, and 
then stuff values to an array during a task in the main loop?


> 463:         Debug_DDR  |= (1 << Debug_Pin); // Output
> +0000024F:   9A8D        SBI       0x11,5         Set bit in 
> I/O register
> 464:         Debug_Port &=~(1 << Debug_Pin); // Low
> +00000250:   9895        CBI       0x12,5         Clear bit 
> in I/O register

More debug statements.


> 465:         Raw_Edge_Flag = 0; // So the next event will be 
> a beginning
> +00000251:   92100082    STS       0x0082,R1      Store 
> direct to data space
> 467:         if ((TIFR & (1<< TOV1))==1) // If we rolled T0
> +00000253:   B788        IN        R24,0x38       In from I/O location
> +00000254:   2799        CLR       R25            Clear Register
> +00000255:   7084        ANDI      R24,0x04       Logical AND 
> with immediate
> +00000256:   7090        ANDI      R25,0x00       Logical AND 
> with immediate
> +00000257:   9701        SBIW      R24,0x01       Subtract 
> immediate from word
> +00000258:   F421        BRNE      PC+0x05        Branch if not equal

Hmm. It seems the compiler is treating this expression as a 16-bit value. It 
could be because of the comparison with the constant '1', which gets 
automatically treated like an int. Can you see if typecasting will help?:

if ((TIFR & (uint8_t)(1<<TOV1)) == (uint8_t)1)

If it works, it should save 2 instructions.


> 470:          TIFR |= (1<<TOV1);    // reset the overflow condition
> +00000259:   B788        IN        R24,0x38       In from I/O location
> +0000025A:   6084        ORI       R24,0x04       Logical OR 
> with immediate
> +0000025B:   BF88        OUT       0x38,R24       Out to I/O location
> +0000025C:   C006        RJMP      PC+0x0007      Relative jump
> 477:          GICR  |= (1 << INT1);   // Enable INT1
> +0000025D:   B78B        IN        R24,0x3B       In from I/O location
> +0000025E:   6880        ORI       R24,0x80       Logical OR 
> with immediate
> +0000025F:   BF8B        OUT       0x3B,R24       Out to I/O location
> 478:          GICR  &=~(1 << INT0);   // Disable INT0
> +00000260:   B78B        IN        R24,0x3B       In from I/O location
> +00000261:   7B8F        ANDI      R24,0xBF       Logical AND 
> with immediate
> +00000262:   BF8B        OUT       0x3B,R24       Out to I/O location

You're doing two assignments back to back to GICR, which causes two separate 
read-modify-write blocks. Is there any way that they can be combined into one 
step? Like so:

GICR = ((GICR & ~(1<<INT0)) | (1 << INT1));

I would think this would compile to an IN,ANDI,ORI,OUT sequence



> +00000263:   91FF        POP       R31            Pop 
> register from stack
> +00000264:   91EF        POP       R30            Pop 
> register from stack
> +00000265:   919F        POP       R25            Pop 
> register from stack
> +00000266:   918F        POP       R24            Pop 
> register from stack
> +00000267:   900F        POP       R0             Pop 
> register from stack
> +00000268:   BE0F        OUT       0x3F,R0        Out to I/O location
> +00000269:   900F        POP       R0             Pop 
> register from stack
> +0000026A:   901F        POP       R1             Pop 
> register from stack
> +0000026B:   9518        RETI 
> 

If we can keep the ISR from using as many other registers as possible, then it 
will help in both the ISR prologue and epilogue.


 
> **************************************************************
> **************
> This communication (including any attachments) is for the use of the
> intended recipient(s) only and may contain information that is
> confidential, privileged or otherwise legally protected. Any
> unauthorized use or dissemination of this communication is
> prohibited. If you have received this communication in error, please
> immediately notify the sender by return e-mail message and delete
> all copies of the original communication. Thank you for your
> cooperation.
> **************************************************************

Any way that you can remove the above confidential notice? You're sending this 
mail to a public mailing list.

Eric Weddington




reply via email to

[Prev in Thread] Current Thread [Next in Thread]