Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ATtiny827 digitalRead()/digitalWrite() Issue on Specific Pins - Loop Hangs #1190

Open
bmjjr opened this issue Dec 31, 2024 · 2 comments
Open

Comments

@bmjjr
Copy link

bmjjr commented Dec 31, 2024

Description of the Problem:

I am experiencing an issue with the digitalRead() and digitalWrite() functions on an ATtiny827 microcontroller using the megaTinyCore. When these functions are used in combination within the loop() function to control an LED (on PIN_PA7) based on the state of a digital input pin (PIN_PC5), the loop() function appears to hang or stop executing after the setup() phase. One point to note, I have a hardware reset button on PIN_PB4 and chose the selection for remapping the button to PIN_PB4, using the option provided by megatinycore.

The LED will reflect the initial state of the input pin during setup() (e.g., if the input is HIGH during reset, the LED turns on), but it does not update afterward in the loop() function, even though the input pin's state changes. A heartbeat LED, used to indicate whether loop() is running, stops toggling, confirming that loop() is not executing.

However, if I use direct register manipulation to read the input pin and control the LED, the code works perfectly, and the LED updates as expected in response to changes on the input pin.

Minimal Code that Demonstrates the Issue (using digitalRead()/digitalWrite()):

#include <avr/io.h>
#include <util/delay.h>
#include "megaTinyCore.h"
#include "Arduino.h"

const byte vccPin = PIN_PC5;      // Charger detect input
const byte battLed50 = PIN_PA7;   // LED

void setup() {
  pinConfigure(vccPin, PIN_DIR_INPUT, PIN_PULLUP_OFF, PIN_INVERT_OFF, PIN_ISC_DISABLE);
  pinConfigure(battLed50, PIN_DIR_OUTPUT, PIN_PULLUP_OFF, PIN_INVERT_OFF, PIN_ISC_DISABLE);
  digitalWrite(battLed50, LOW); // LED off initially
}

void loop() {
  digitalWrite(battLed50, digitalRead(vccPin));
  _delay_ms(50); 
}

Code that Works (using Direct Register Manipulation):

#include <avr/io.h>
#include <util/delay.h>
#include "megaTinyCore.h"
#include "Arduino.h"

const byte vccPin = PIN_PC5;      // Charger detect input
const byte battLed50 = PIN_PA7;   // LED

void setup() {
  // Configure vccPin as input (no pull-up)
  PORTC.DIRCLR = (1 << 5); // Set PC5 as input
  PORTC.PIN5CTRL &= ~PORT_PULLUPEN_bm; // Disable pull-up

  // Configure battLed50 as output
  PORTA.DIRSET = (1 << 7); // Set PA7 as output
  PORTA.OUTCLR = (1 << 7); // Initially turn LED off
}

void loop() {
  // Check the state of vccPin (PC5)
  if (PORTC.IN & (1 << 5)) { 
    // vccPin is HIGH 
    PORTA.OUTSET = (1 << 7); // Turn LED on
  } else {
    // vccPin is LOW 
    PORTA.OUTCLR = (1 << 7); // Turn LED off
  }
  _delay_ms(50); 
}

Hardware Setup Details:

  • Microcontroller: ATtiny827
  • Clock Speed: 5 MHz (internal oscillator)
  • Startup Time: 8 ms
  • BOD Voltage Level: 1.8V
  • BOD Mode: Disabled/Disabled
  • Save EEPROM: EEPROM Retained
  • UPDI with Reset on: PB4
  • WDT Timeout: Disabled
  • PWM Pins: Default
  • Attach Interrupt Mode: On all pins, new implementation
  • megaTinyCore Version: 2.6.10
  • IDE: Arduino IDE 1.8.13
  • Programmer: Atmel-ICE
  • Operating System: Windows 10

Circuit Description:

The input pin (PIN_PC5) is connected to a voltage divider consisting of two 10K resistors. The voltage divider is connected to the 5V output of a USB-C connector (used for charger detection). The output of the divider is approximately 2.53V when the charger is connected and 0V when disconnected. The LED (PIN_PA7) is connected to the ATtiny827 with an appropriate current-limiting resistor.

Steps Taken:

  • Verified that the loop() function is not running by using a heartbeat LED.
  • Confirmed that the issue is not related to the watchdog timer or interrupt conflicts.
  • Isolated the problem to the use of digitalRead() and digitalWrite() in combination.
  • Developed a workaround using direct register manipulation.

Request:

I would appreciate it if you could investigate this issue. It appears to be a potential bug in the megaTinyCore when using digitalRead() and digitalWrite() with these specific pins on the ATtiny827, or there might be a specific configuration or interaction that I'm not aware of.

Please let me know if you need any further information or if you have any suggestions for further testing.

Thank you for your time and effort in developing and maintaining the megaTinyCore.

@hmeijdam
Copy link

I suspect the culprit is Pinconfigure

I see you are using PIN_ISC_DISABLE and according the documentation that will disable the digital input buffer or the interrupt function of the pin, The documentation is unclear on that point to me.

@hmeijdam
Copy link

Just tested on an Attiny404 and if you remove the argument PIN_ISC_DISABLE for your input pin it works. Apparently that does not disable the interrupt feature for that pin but the input buffer.
399054147-224ea5c4-595a-4e50-b310-626afe4f5388

I think it should be that PIN_ISC_DISABLE should set ISC to 0x0 and PIN_INPUT_DISABLE should set ISC to 0x4

But currently it doesn't and it is also not possible to configure the pin for accepting an interrupt on CHANGE of the level

This sketch prints the hex value of ISC after using pinconfigure.

void setup() {
  Serial.begin(9600);
  pinConfigure(PIN_PA7, PIN_ISC_DISABLE);
  Serial.print("PIN_ISC_DISABLE ");
  Serial.println(PORTA_PIN7CTRL, HEX);
  pinConfigure(PIN_PA7, PIN_ISC_ENABLE);
  Serial.print("PIN_ISC_ENABLE ");
  Serial.println(PORTA_PIN7CTRL, HEX);
  pinConfigure(PIN_PA7, PIN_INPUT_DISABLE);
  Serial.print("PIN_INPUT_DISABLE ");
  Serial.println(PORTA_PIN7CTRL, HEX);
  pinConfigure(PIN_PA7, PIN_INPUT_ENABLE);
  Serial.print("PIN_INPUT_ENABLE ");
  Serial.println(PORTA_PIN7CTRL, HEX);
// trying to set the pin to Interrupt on Change (ISC = 0x1)
  pinConfigure(PIN_PA7, PIN_ISC_ENABLE, PIN_INPUT_ENABLE);
  Serial.print("PIN ISC and INPUT ENABLE ");
  Serial.print(PORTA_PIN7CTRL, HEX);
  Serial.println(" <-- that should have been 0x1");
}

void loop() {
}

So I can confirm your bug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants