Strange behaviour of ATmega128 with Arduino framework

I have found an old board with an ATmega128 and some nice driver ICs on it, so I would like to use the board for a current project. But: a simple test (using two onboard LEDs) drives me crazy :confused:

platformio.ini:

[env:ATmega128_test]
platform = atmelavr
board = ATmega128
framework = arduino

lib_compat_mode = strict
lib_archive = no

Code:

#include <Arduino.h>

const uint8_t ledPin1 =  8;             // LED 1 on PB0
const uint8_t ledPin2 = 10;             // LED 2 on PB2 

void setup( void)
{
    DDRB |= (1<<PB0);
    DDRB |= (1<<PB2);
    pinMode( ledPin1, OUTPUT);          // LEDs are active low
    pinMode( ledPin2, OUTPUT);
}

void loop ( void) {}

Result:
Which LED will be switched on/off by the pinMode()-function calls varies by

  • whether the DDRB register has been set before by bit manipulation,
  • in which order the pinMode() calls are executed,
  • whether another pinMode() call for another port pin follows.

Examples (the code given is the complete contents of setup()):

  pinMode( ledPin1, OUTPUT);
  pinMode( ledPin2, OUTPUT);

β†’ only LED1 is on (error: LED2 should be on too)

  pinMode( ledPin2, OUTPUT);
  pinMode( ledPin1, OUTPUT);

β†’ only LED2 is on (error: LED1 should be on too)

  pinMode( ledPin1, INPUT);
  pinMode( ledPin2, OUTPUT);

β†’ only LED2 is on (okay)

With one more code line

  pinMode( ledPin1, INPUT);
  pinMode( ledPin2, OUTPUT);
  pinMode( ledPin1, OUTPUT);

β†’ no LED is on

The same with DDR register manipulation before:

  DDRB |= (1<<PB2);
  pinMode( ledPin1, INPUT);
  pinMode( ledPin2, OUTPUT);
  pinMode( ledPin1, OUTPUT);

β†’ only LED2 is on (error: LED1 should be on too)

And so on… I have no clue what does happen here.

Is the

board = ATmega128

statement sufficient to let the Arduino core/libs to know what to do???

By the way, a piece of plain C++ code does work like expected:

#include <avr/io.h>
#include <util/delay.h>

int main( void)
{
	DDRB |= _BV(0);
	DDRB |= _BV(2);

	while ( 1 )
	{
		PORTB &= ~_BV(0);
		PORTB |=  _BV(2);
		_delay_ms( 500);

		PORTB |=  _BV(0);
		PORTB &= ~_BV(2);
		_delay_ms( 500);
	}
}

Appreciate your help :wink:
Ralph

Well then let’s look at the implementation of that pinMode() function. As you can see in the board definition file it uses the MegaCore

And the pinMode() function is implemented as

So behavior like

Is expected since calling pinMode() with INPUT will clear the respective bit in the output register of the port. Thus at the next OUTPUT call, PORTB has already been cleared and it will output a 0.

Now that is actually unexplainable, since pinMode() does not modify the output register but only the data direction register when called with OUTPUT as the second argument. I’ll try if I can reproduce this.

Thanks for the insight into the implementation details.

Nevertheless I do not agree to

The LEDs are both active low, so a port register bit value 0 should be fine.