From 25e87628bb6c642283d1d9f3f38542eb4969cbe4 Mon Sep 17 00:00:00 2001 From: Yusuke Shimizu - Workshop Asahi Date: Sat, 8 Aug 2026 00:26:20 +0000 Subject: [PATCH 1/3] Fix operator precedence in ADC-disabled check `!ADC0.CTRLA & 0x01` evaluates as `(!ADC0.CTRLA) & 0x01`, so the early return for a disabled ADC never fired as intended. Parenthesize the mask. The same expression appears twice (analogRead paths for the two ADC generations); the other checks in this file already had the parentheses right. --- megaavr/cores/dxcore/wiring_analog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/megaavr/cores/dxcore/wiring_analog.c b/megaavr/cores/dxcore/wiring_analog.c index ef69aee1..9978acab 100644 --- a/megaavr/cores/dxcore/wiring_analog.c +++ b/megaavr/cores/dxcore/wiring_analog.c @@ -418,7 +418,7 @@ inline __attribute__((always_inline)) void check_valid_resolution(uint8_t res) { #endif return ADC_ERROR_BAD_PIN_OR_CHANNEL; } - if (!ADC0.CTRLA & 0x01) return ADC_ERROR_DISABLED; + if (!(ADC0.CTRLA & 0x01)) return ADC_ERROR_DISABLED; if (ADC0.COMMAND & ADC_START_gm) return ADC_ERROR_BUSY; // gotta be careful here - don't want to shit ongoing conversion - unlikle classic AVRs @@ -730,7 +730,7 @@ inline __attribute__((always_inline)) void check_valid_resolution(uint8_t res) { #endif return ADC_ERROR_BAD_PIN_OR_CHANNEL; } - if (!ADC0.CTRLA & 0x01) return ADC_ERROR_DISABLED; + if (!(ADC0.CTRLA & 0x01)) return ADC_ERROR_DISABLED; if (ADC0.COMMAND & ADC_START_gm) return ADC_ERROR_BUSY; // gotta be careful here - don't want to shit ongoing conversion - unlikle classic AVRs From 63c042fd9a2ca26957ce309239657df3d419fc03 Mon Sep 17 00:00:00 2001 From: Yusuke Shimizu - Workshop Asahi Date: Sat, 8 Aug 2026 00:26:26 +0000 Subject: [PATCH 2/3] Fix unreachable chan=255 (auto-select) in event generator pin setup `(chan + 1) < 3` promotes chan to int, so the documented auto-select value chan = 255 evaluated as 256 < 3 and could never take this path. Compare explicitly instead. --- megaavr/cores/dxcore/wiring_extra.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/megaavr/cores/dxcore/wiring_extra.cpp b/megaavr/cores/dxcore/wiring_extra.cpp index 6a4e99bc..261d9d6e 100644 --- a/megaavr/cores/dxcore/wiring_extra.cpp +++ b/megaavr/cores/dxcore/wiring_extra.cpp @@ -158,7 +158,7 @@ void pinConfigure(uint8_t digital_pin, uint16_t pin_config) { uint8_t _setEventPin(uint8_t pin, uint8_t chan) { // Works the same was as uint8_t temp = digitalPinToPort(pin); - if (temp != NOT_A_PIN && (chan + 1) < 3) { + if (temp != NOT_A_PIN && (chan == 255 || chan < 2)) { // (chan + 1) < 3 promoted to int, so chan = 255 could never take this path volatile uint8_t* p; p = (volatile uint8_t*) (uint16_t) (digitalPinToPortStruct(temp)); p += 0x18; // now p pointing to evgenctrl. From 30f456d70831c18c2f5bc5ff908ad1ce69ada2aa Mon Sep 17 00:00:00 2001 From: Yusuke Shimizu - Workshop Asahi Date: Sat, 8 Aug 2026 00:26:37 +0000 Subject: [PATCH 3/3] Flash: fix writeBytes - dropped trailing byte, corrupted neighbour, lost data pointer Three bugs in the unaligned/odd-length paths: - the unaligned leading byte was written without advancing the data pointer, so the rest of the buffer was written shifted by one - writeWords was called without afterwards advancing tAddress/data/ length, so the odd-byte epilogue used stale values - the trailing byte was written to tAddress + length - 2 with a recomputed data offset, landing on the wrong address and corrupting the neighbouring byte while dropping the intended one Rewrite the function to advance state explicitly at each stage. Also return early on a zero-length request (FLASHWRITE_0LENGTH). --- megaavr/libraries/Flash/src/Flash.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/megaavr/libraries/Flash/src/Flash.cpp b/megaavr/libraries/Flash/src/Flash.cpp index d813fe1f..b2c01fda 100644 --- a/megaavr/libraries/Flash/src/Flash.cpp +++ b/megaavr/libraries/Flash/src/Flash.cpp @@ -405,20 +405,28 @@ uint8_t FlashClass::writeWords(const uint32_t address, const uint16_t* data, uin uint8_t FlashClass::writeBytes(const uint32_t address, const uint8_t* data, uint16_t length) { uint32_t tAddress = address; - uint8_t status; - if(address & 0x01) { - status = writeByte(tAddress++, *(data)); + uint8_t status = FLASHWRITE_OK; + if (length == 0) { + return FLASHWRITE_0LENGTH; + } + if (tAddress & 0x01) { + // Unaligned start: write the leading byte, then continue word-aligned. + status = writeByte(tAddress++, *data++); if (status) return status; length--; } - if(length > 1) { - status = writeWords(tAddress, (uint16_t*) data, (length >> 1)); + if (length > 1) { + // The bulk of the data, as whole words. + uint16_t words = length >> 1; + status = writeWords(tAddress, (uint16_t*) data, words); if (status) return status; + tAddress += ((uint32_t) words) << 1; + data += words << 1; + length -= words << 1; // 0 or 1 byte left } - // there may be one more byte... if (length & 1) { - data += (length & 0xFFFE); // what we wrote with the word above... - status = writeByte(tAddress + length - 2, *data); + // And finally the trailing byte, if the length was odd. + status = writeByte(tAddress, *data); } return status; }