AVR – Do I Have to Wait for Internal Pullup to Stabilize?

assemblyavr

speaking of an ATMega2560 (not Arduino!), I connected a simple push-button between PB6 and GND.

There is a bootloader and BOOTRST flag is set, i.e. the bootloader always starts first.

I want to use the button for skipping the bootloader, so I'm going to modify the bootloader:

//Defines for the guard button
#define GRD_PORT PORTB
#define GRD PB6

#define GRD_PIN GRD_PORT - 2
#define GRD_DDR GRD_PORT - 1

//Init guard button as input
cbi    GRD_DDR, GRD   ; clear PB6 in DDR -> making it input
sbi    GRD_PORT, GRD  ; set PB6 in PORT  -> enabling internal pullup

sbic   GRD_PIN, GRD   ; skip next if PB6 is cleared (low) in PIN register
jmp    my_app

But my problem is that jmp is always skipped, i.e it seems internal pullup enabling is slower and PINB6 still remains 0.

Is this valid? Do I have to initialize this port somehow different when using assembly?

Best Answer

Yes, you need a delay for two reasons.

First of all, the internal pull-up is weak, so it can take a while before the voltage has risen enough to read as logic 1. How many clock cycles it takes depends on the stray capacitances.

Second reason is the input pin synchronizer, explained on datasheet page 70. The synchronization adds a delay, so even if you did toggle an output pin, you will need at least one NOP before you can read PIN register to see that the state has updated.

So most likely you need to add a delay loop which is the tightest code to achieve any arbitrary delay you want, due to weak pull up a few nops might not be enough.