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

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

[avr-gcc-list] Re: optimizer removes volatile pin access code. why?


From: David Brown
Subject: [avr-gcc-list] Re: optimizer removes volatile pin access code. why?
Date: Thu, 29 Oct 2009 11:20:10 +0100
User-agent: Thunderbird 2.0.0.23 (Windows/20090812)

df_welch wrote:
Hello,
I'm mainly an assembly language user and not a heavy weight C user but this thread has peaked my interest. I'm currently working with the ATmega 2561 and in the course or reading and re-reading the data sheet I found an example on page 72,73 and an example on page 74 showing that there are some issues with the IO Ports that may be part of the issue here. the discussion is in section 13.2.4 "Reading the Pin Value" starting on page 72 of the 2549L–AVR–08/07 preliminary data sheet.

Basically as shown below in the Data sheet excerpt, a NOP is necessary following a write to DDRB(n), and prior to seeing the change on pin(n).

I'm not sure that this extends to the entire 8 bit family but it might be worth looking at.

Excerpt follows ==========================================
The following code example shows how to set port B pins 0 and 1 high, 2 and 3 low, and define the port pins from 4 to 7 as input with pull-ups assigned to port pins 6 and 7. The resulting pin values are read back again, but as previously discussed, a NOP instruction is included to be able
to read back the value recently assigned to some of the pins.

Assembly Code Example(1)
========================================
...
; Define pull-ups and set outputs high
; Define directions for port pins
ldi r16,(1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0)
ldi r17,(1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0)
out PORTB,r16
out DDRB,r17
; Insert NOP for synchronization
nop
; Read port pins
in r16,PINB
...
=======================================
C Code Example
------------------------------------
unsigned char i;
...
/* Define pull-ups and set outputs high */
/* Define directions for port pins */
PORTB = (1<<PB7)|(1<<PB6)|(1<<PB1)|(1<<PB0);
DDRB = (1<<DDB3)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0);
/* Insert nop for synchronization*/
__no_operation();
/* Read port pins */
i = PINB;
...


Note: 1. For the assembly program, two temporary registers are used to minimize the time from pullups are set on pins 0, 1, 6, and 7, until the direction bits are correctly set, defining bit 2 and 3
as low and redefining bits 0 and 1 as strong high drivers.
13.2.5 Digital Input Enable and Sleep Modes
As shown in Figure 13-2, the digital input signal can be clamped to ground

Hope this sheds some light on what is going on.


This is, I think, a very different situation. What you are seeing here is the pipelining and clocking effects when you set a pin and then try to read a pin to see the effects - the pin write has an extra cycle of latency, so if you follow a pin write by a pin read, you'll get the read from the same clock cycle as the write takes place, rather than the cycle after it. If you've got pin IO that is affected by such timing issues, then you need to make sure there is a delay between the pin write and the pin read, regardless of any optimisation issues.





reply via email to

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