Repository navigation
Correct AXP2101 register addresses, fields, and shutdown accesses - #171
Merged
jonasniesner merged 1 commit intoOct 11, 2026
Merged
Conversation
…t register
Checked every AXP2101 register access in the firmware against the AXP2101
datasheet. Several used addresses or bits the AXP2101 does not have. This
corrects them in place and removes the accesses that have nothing to land
on. Where ESPHome test-bed work on the PhotoPainter reads the same
registers (REG00, REG01, VBAT, VBUS, REG30 bit 2, battery percentage), the
datasheet matched the hardware. The other registers follow the same
datasheet.
powerDownAXP2101() (runs at every panel shutdown):
- IRQ status was cleared at 0x44-0x46. The AXP2101's IRQ status
registers are 0x48-0x4A. 0x4A is written 0xDF because its bit 5 is
reserved.
- It also wrote a fourth IRQ-enable register (0x43) and a fourth
IRQ-status register (0x47). The AXP2101 has three of each; these
appear to be vestigial from older PMIC support. The writes were
non-functional and non-erroring: the bus acknowledged them, so
nothing reported a failure. Removed, with their constants.
- REG26 reserved bit 7 was set. No longer set.
- REG91 holds only the DLDO2 enable, but its write was logged as
disabling BLDO1-2, CPUSLDO and DLDO1-2. Those other enables are REG90
bits 4-7, which the shutdown preserved. REG90 is now written 0x00 so
the stated disables happen, and each log line states what its own
write did.
readAXP2101Data() (uncalled diagnostic, flagged in OpenDisplay#155):
- "VBUS" was read from 0x36 (the TS pin); VBUS is 0x38/0x39.
- "System" was read from 0x38 (VBUS); VSYS is 0x3A/0x3B.
- All three voltages used a 12-bit decode with 0.5/1.7/1.4 mV steps.
The AXP2101 is 14-bit, (hi & 0x3F) << 8 | lo, at 1 mV per count.
- REG30 was written 0xFF to enable all ADC channels, which also set
reserved bits 7:6. Now 0x3F.
- Battery presence and VBUS presence read swapped REG00 bits.
- "Charging" read REG00 bit 2 (Battery in Active Mode). Charge
direction is REG01 bits 6:5.
The function remains uncalled.
axp2101_adc_enable_bit0() (OpenDisplay#155 battery reader): REG30 reserved bits 7:6
are written as 0 instead of echoed back. Two host-test expectations
follow. OpenDisplay#155's comments describing the diagnostic's now-fixed defects,
and calling REG34 bits 7:6 "unused" (they are ch_dbg_en), are corrected.
src/main.h: the unused duplicate AXP2101 block, left behind when fd0d73a
moved these functions to display_service.cpp, gets the same corrections:
VBUS/SYS ADC addresses, PWRON/PWROFF status at 0x20/0x21, IRQ status at
0x48-0x4A, the fourth IRQ registers removed, and the REG91 comment.
The REG26 and REG80/90/91 handling follows the datasheet's sleep and wake
sequence (Figure 6-2) and is otherwise unchanged. Not changed: rail policy
beyond what the code already states (including ALDO3), fail-closed
read/modify/write, the hardcoded 0x34 address and ambient Wire use, and
when power state is committed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jonasniesner
approved these changes
Oct 11, 2026
Member
|
Thank you for your contribution |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #170
Summary
Follow-up to #155. I checked every AXP2101 register access in the firmware against the AXP2101 datasheet. Several used addresses or bits the AXP2101 does not have. This corrects them in place and removes the accesses that have no AXP2101 register to land on. It adds no new functions.
The observable runtime changes are concentrated in
powerDownAXP2101(), which runs at every panel shutdown. The live #155 battery helper also sanitizes REG30 reserved bits when it enables the VBAT channel.readAXP2101Data()remains uncalled, and the duplicatemain.hconstants remain unused.This patch is for register correctness only. It intentionally does not change the ALDO3 shutdown policy, so the post-shutdown I²C failure seen with #155's reader remains; that is a separate follow-up.
What changed
Datasheet references are PDF page numbers.
powerDownAXP2101()0x44–0x46. The AXP2101's status registers are0x48–0x4A(p.43–44), and they are now the ones written.0x4Agets0xDFbecause its bit 5 is reserved.0x43) and a fourth IRQ-status register (0x47) are removed, along with their constants. The AXP2101 has three of each, and0x43–0x47are not in its register map. I traced where the four-register layout came from: its names and count (IRQ_ENABLE1–4,IRQ_STATUS1–4) match Allwinner's AXP8191 PMU definitions, and its status addresses match the AXP192, whose REG43 enables N_OE, VBUS-session and APS low-voltage IRQs that the AXP2101 does not have. On the AXP2101 these writes reach no register, so they cannot do what they were written to do. They also never fail: the bus acknowledges them, so nothing reported an error.0x00. This is a deliberate runtime behavior change. REG91 holds only the DLDO2 enable (p.53), but its write was logged as disabling "BLDO1-2, CPUSLDO, DLDO1-2". The BLDO1, BLDO2, CPUSLDO and DLDO1 enables are REG90 bits 4–7 (p.53), which the shutdown preserved even though its log claimed those rails were disabled. Writing0x00now disables BLDO1, BLDO2, CPUSLDO and DLDO1 as well as ALDO1–4 (ALDO1–4 were already cleared). The datasheet establishes where those enables live; turning them off follows the intent stated by the existing shutdown code. Those outputs are unconnected on the tested PhotoPainter, so no board-level effect was observed. Other AXP2101 hardware could observe the difference.DLDO2 disabled(REG91) andALDO1-4, BLDO1-2, CPUSLDO, DLDO1 disabled(REG90).axp2101_adc_enable_bit0()(#155 battery reader, live): REG30 reserved bits 7:6 are written as0instead of echoed back (p.39). On conforming silicon they read as 0, so this is defensive. One named constant is added,AXP2101_ADC_CTRL_RESERVED_MASK.readAXP2101Data()(uncalled diagnostic), corrected line by line:0x36, which is the TS pin0x38/0x39(p.40–41)0x38, which is VBUS0x3A/0x3B(p.41)(H & 0x3F) << 8 | L, 1 mV per count (p.40–41)0xFF: all channels plus reserved bits 7:60x3F: all channels, reserved bits 0 (p.39)src/main.h: the unused duplicate AXP2101 constant block gets the same corrections: VBUS/SYS ADC addresses,POWER_ON_STATUS/POWER_OFF_STATUSat0x20/0x21, IRQ status at0x48–0x4A, the fourth IRQ registers removed, and the REG91 comment.The diagnostic and
main.hchanges do not affect the production binary's control flow. They keep retained AXP2101 code and duplicate definitions from preserving a second, incorrect register map that could be reused later.Comments and tests: #155's comments describing the diagnostic's now-fixed defects are updated, and REG34 bits 7:6 are described as
ch_dbg_enrather than "unused". Intools/test_sensor_axp2101.cpp, only the two expectations affected by the reserved-bit mask change (0xFE -> 0x3F,0xA5 -> 0x25).Why these changes are correct. Each register address and field follows the AXP2101 datasheet. ESPHome test-bed work on the PhotoPainter reads REG00 bits 3 and 5, REG01 bits 6:5, VBAT at
0x34/0x35and VBUS at0x38/0x39with the 14-bit decode, REG30 bit 2, and battery percentage at0xA4, and the datasheet matched the hardware on every one of them. VSYS, the IRQ status registers and REG26 could not be exercised on hardware here; those corrections follow the same datasheet, which has proven reliable on every register we could test.Unchanged: the REG26 sleep/wake sequence apart from bit 7 (it matches the datasheet's Figure 6-2, with GPIO21 driving the IRQ-pin wake; checked against the datasheet, not hardware-tested), DCDC1 and ALDO3/ALDO4 setup, the IRQ enables
0x40–0x42, the REG80 rail disable, REG30 =0x00at shutdown, battery percentage (0xA4), power-on status (0x20), and #155's battery-present and VBAT reads.There is no new
extern, no heap allocation, no new caller, and no new periodic work.Performance
Shutdown does two fewer I²C writes (the removed IRQ registers) and one fewer read (REG90 is written directly). RAM is unchanged on every target. Flash is smaller on every target, for example
esp32-s3-N16R81,529,338 bytes vs 1,529,418 (-80).Testing
Each layer proves something different:
-fsanitize=undefined,addresswith-Wall -Wextra -Werror, with the two expectations above updated. They exercise the AXP2101 battery helper only, notpowerDownAXP2101()or the diagnostic's Wire transaction sequence..github/firmware-targets.json, includingesp32-wrover-e-N4R8, in production and diagnostic profiles. All succeeded with no new warnings.readAXP2101Data()is temporarily called by a diagnostic-only commit.The hardware cycle uses the same four-state pattern as #155. The diagnostic-only commit, not part of this PR, calls
readAXP2101Data()once at the end ofinitAXP2101(), its original position fromb53c778. The fix has the same patch ID applied alone and on top of it.00-main371692501-main-diag02-fix-diag03-fix-mainObserved during boot-to-shutdown validation on the Waveshare ESP32-S3-PhotoPainter (
esp32-s3-N16R8, the only AXP2101 board in the catalog), on USB-C with the battery attached, after a full power drain:All IRQs disabled and status cleared,DLDO2 disabled, andALDO1-4, BLDO1-2, CPUSLDO, DLDO1 disabled. No other shutdown line changed against01. IRQ status registers were not read back after clearing.02): battery present and VBUS presentYes, charge state standby (REG010x14, battery full), VBAT 4171 mV against Report battery voltage from a configured AXP2101 #155's reader 4169 mV in the same boot. Report battery voltage from a configured AXP2101 #155's reader loggedadc_ctrl=0x3F -> 0x3F, so the reserved bits read back as 0.00vs03): baseline and fixed builds followed the same successful boot, refresh, shutdown, and BLE-startup control flow. Refresh duration and other live values varied between captures.Negative devices: Seeed XIAO ESP32-C3 7.5" kit (
esp32-c3-N4) and Seeed EE04 ESP32-S3 (esp32-s3-N16R8). Neither has an AXP2101 configured, so these runs show configuration isolation and no regression on those boards; they do not exercise AXP2101 registers. Both followed the same control flow in every state; only live values such as the MSD sensor byte varied.Not tested: deep-sleep wake, BLE transfers, register readback after the shutdown writes, and long-term behavior beyond the boot-to-shutdown window.
Scope boundaries
Each of these will follow in its own issue and pull request:
powerDownAXP2101()still disables ALDO3. On the PhotoPainter this makes the shared I²C bus unavailable, so the battery reader added by Report battery voltage from a configured AXP2101 #155 fails after panel shutdown. A separate follow-up will keep ALDO3 enabled. This PR intentionally leaves that policy unchanged, including ALDO2.initAXP2101(),powerDownAXP2101()andreadAXP2101Data()hardcode0x34and use ambientWirestate, unlike Report battery voltage from a configured AXP2101 #155's reader.pwrmgm()commits the power state before the PMIC transition, and both helpers returnvoid.AI disclosure: developed with AI assistance (GitHub Copilot and other AI harnesses), with a human reviewing every stage. All hardware observations were made on physical devices by the contributor, and the raw serial, build, and flash logs are retained.
🤖 Generated with Claude Code