LGT8F328P-LQFP32 MiniEVB ("LGTBF32BP")
A board that looks exactly like an Arduino Nano, takes the same sketches, and is not one. The
LGT8F328P is a Logic Green LGT8XM core that executes the AVR instruction set inside a chip
with a different clock system, a 12-bit ADC, a DAC, four timers, no real EEPROM and no
crystal. board.build.mcu is literally atmega328p, so everything compiles and most things
silently behave differently. Almost every failure on this board is a Nano assumption that
was not true.
Read the reference files rather than reasoning from ATmega328P knowledge.
reference/board-hardware.md — the complete board reference: the LQFP32 pin map with the
four bonded pads, Arduino pin numbering past D19, timer/PWM map, PMX0/1/2 alternate
routing, the HDR high-current table, power tree, clock tree, memory map and the EEPROM
emulation, plus a development guide (§8 toolchain and measured build sizes, §9 the
clock-prescaler trap, §10 peripheral cookbook, §11 core gotchas, §12 flashing and SWD
recovery, §13 symptom → cause → fix table).
reference/recipes.md — copy-paste code: platformio.ini, board.h, blink, the 12-bit
ADC, measuring the real VCC, the DAC on D4, Timer3 PWM on D1/D2, 80 mA drive, emulated
EEPROM, moving the UART to D5/D6, sleep, and disabling SWD.
template/ — a project that builds clean, in two variants, plus a scaffold script. See
template/README.md.
Confirm the board first
The silkscreen LGTBF32BP is Logic Green's stylisation of LGT8F328P, not a different part.
What actually has to be decided is the package, because it picks the core variant:
| Package |
Board |
PlatformIO board |
build.variant |
| LQFP32 |
Nano-style 30-pin MiniEVB, "purple nano", WAVGAT — this skill |
LGT8F328P |
lgt8fx8p |
| LQFP48 |
MiniEVB 48-pin breakout |
lgt8f328p-LQFP48 |
lgt8fx8p48 |
| SSOP20 |
"green pseudo Pro Mini" |
LGT8F328P-SSOP20 |
lgt8fx8ps20 |
| LQFP32 |
Wemos TTGO XI |
lgt8f328p-wemos-TTGO-XI |
lgt8fx8p-wemos-TTGO-XI |
Count the pins on the chip, not on the header. Getting this wrong gives a build that flashes
and runs with a pin map that is wrong past D19.
Also read the SOP16 USB bridge marking — HT42B534-1 (USB CDC, no driver needed on
macOS/Linux, enumerates as usbmodem/ttyACM) or CH9340C / CH340G (needs the WCH VCP
driver, enumerates as wchusbserial/ttyUSB). It decides why the board does or does not
appear as a port.
Orientation
|
|
| MCU |
LGT8F328P (Logic Green / Prodesign), 8-bit LGT8XM RISC core, AVR-instruction-compatible, 1.8–5.5 V, 0–32 MHz |
| Clock |
No crystal on the MCU. Internal 32 MHz RC ±1 %; CLKPR boots at ÷8 so the part starts at 4 MHz, and the core reprograms it from F_OSC / F_CPU. PB6/PB7 (XTAL) are unused and have no Arduino pin number |
| Memory |
32 KB flash (29,696 B usable — 3 KB bootloader), 2 KB SRAM, no EEPROM array — 0/1/2/4/8 KB emulated out of the same flash at 2× cost |
| LED |
L = D13 / PB5, on = HIGH. Red power LED is not controllable |
| ADC |
12 channels, 12-bit; analogRead() returns 10 bits until analogReadResolution(12). Refs: AVCC, AVREF (PE6), 1.024 / 2.048 / 4.096 V ±1 % |
| DAC |
8-bit, on PD4 = D4. analogWrite(4, v) is an analog voltage, not PWM |
| PWM |
D3 (T2B), D5 (T0B), D6 (T0A), D9 (T1A), D10 (T1B), D11 (T2A) and D1, D2 (Timer3). digitalPinHasPWM() is wrong on this part |
| UART |
D0/D1 — shared with the USB bridge. Movable to D5/D6 via PMX0.TXD6/RXD5 |
| I2C / SPI |
A4=SDA, A5=SCL · D10=SS, D11=MOSI, D12=MISO, D13=SCK |
| Extra pins |
E0 (22, SWC), E2 (23, SWD), E4 (24), E6 (25, AREF), E5 (26), C6 (27, RESET) |
| High current |
80 mA on D5, D6, D1/TX, D2, PE4, PE5 via HDR; 12 mA otherwise |
| Power |
VCC ≈ 4.6 V on USB — a protection diode sits in the 5 V line. One VCC pin and one GND pin on the whole package |
| Debug |
SWD on PE0 (SWC) / PE2 (SWD) — not ICSP. Disableable by one register bit, permanently until a power-up reset trick |
| Toolchain |
PlatformIO + darkautism/pio-lgt8fx (platform lgt8f 1.0.3) + framework-lgt8fx 2.0.7 (the dbuezas lgt8fx core), board = LGT8F328P |
Rules that prevent the expensive mistakes
Each of these produces a failure that points somewhere else.
- Never set
board_build.f_osc to match board_build.f_cpu. F_OSC describes the
oscillator (always 32000000L here — the internal RC); F_CPU describes the core; the core
programs CLKPR from F_DIV = F_OSC / F_CPU. Setting both to 16 MHz makes F_DIV = 1,
the RC stays undivided, and the part runs at 32 MHz while every delay(), micros() and
baud rate is computed for 16 MHz. Everything is 2× off and nothing reports an error.
To run at 16 MHz, change f_cpu alone. Most "how to run at 16 MHz" snippets on the web
contain this bug.
- Set
board_build.clock_source = 1 explicitly. Without a CLOCK_SOURCE define the
core skips lgt8fx8x_clk_src() and leaves its own default prescaler, so F_CPU and the
real clock diverge. 1 = internal RC, 2 = external crystal — and this board has no
crystal on the MCU.
analogReadResolution(12) or you are running a 10-bit ADC. The core ships
analog_resbit = 2 and throws the bottom two bits away for Arduino compatibility. The
symptom is a chip that "isn't any better than a Nano".
analogWrite(4, v) is the DAC, not PWM. D4 = PD4 = DAC0 outputs a real analog
voltage. It also does not call pinMode() and does not short-circuit 0/255 to
digitalWrite(). A ported LED-fade works; a MOSFET gate or an opto driven from D4 does
not, and the scope shows DC instead of edges.
analogWrite(1, …) kills Serial. The LQFP32 bonds PF1 onto the D1 pad, so Timer3's
OC3A comes out on the UART TX pin; analogWrite(2, …) likewise takes INT0. Use another
pin, or move the UART with PMX0.TXD6/RXD5 first.
INTERNAL is 1.024 V, and INTERNAL2V56 is silently 2.048 V. Both are #defined in
this core to the LGT references — INTERNAL2V56 has the same value as
INTERNAL2V048. Ported code that calibrated against 1.1 V is ~7 % out; code asking for
2.56 V is 25 % out. Neither errors.
DEFAULT means AVCC ≈ 4.6 V, not 5.000 V. A protection diode in the board's 5 V line
drops it. Every DEFAULT-referenced reading is scaled by ~0.92. Use an internal
reference, or read the real supply through the chip's own V5D1 channel (recipe 5).
- Four header pads carry two port bits each. D1 = PD1‖PF1, D2 = PD2‖PF2,
E4 =
PE4‖PF4, E5 = PE5‖PF5. Both halves have their own DDRx/PORTx and both drivers reach
the same bond wire — writing them against each other is a short inside the package. The
core handles this for analogWrite(); nothing protects hand-written register code.
- The emulated EEPROM is erased by every upload, including an update. It lives in
program flash, page-swapped by the E2PCTL controller. 1 KB of EEPROM also costs 2 KB of
flash that PlatformIO's 29,696 B budget does not know about, and only 1020 of each 1024
bytes are usable. Anything that must survive a firmware update needs another home.
- Never write
MCUSR with bit 7 set. MCUSR[7] is SWDD — it disables the SWD port,
and with it debugging and ISP recovery, permanently until you hold RESET low through a
power-up so the sketch cannot run. MCUSR = 0; is safe. MCUSR = 0xFF; to "clear the
reset flags" is a brick.
- Keep the 32 MHz RC enabled (
PMCR[0]) even if you switch the master clock. E2P_clk
is 32 MHz ÷ 32 and comes only from that oscillator; without it every EEPROM operation and
every flash self-read stops working, with no error.
digitalPinHasPWM() is wrong here — inherited unchanged from the AVR core, it
reports 3/5/6/9/10/11 and misses D1, D2 and D4. Do not let a library use it to pick a pin.
PMX0, PMX1, PMX2, PMCR, CLKPR and ECCR are write-protected. Set the guard
bit (0x80) first, then complete the real write within 4–6 system clocks. A single
ordinary assignment does nothing at all — the register reads back unchanged and the
feature simply never turns on.
- PE6 is AREF and PC6 is RESET until you say otherwise.
PMX2.E6EN and PMX2.C6EN
turn them into GPIO; taking PC6 also takes away DTR auto-reset, so every subsequent
upload needs a manual reset.
- One VCC pin, one GND pin, six 80 mA pads. The databook says do not drive four
high-current loads at once on this package. The bond wires are the limit, not the pads.
- SRAM is still 2 KB with no MPU.
F() every literal, PROGMEM every table, watch
free RAM — the Nano arithmetic is unchanged, and 32 MHz does not buy you memory.
The watchdog rule from the Nano does not apply: the core installs __patch_wdt() in
.init3 (MCUSR = 0; wdt_disable();) before main(), so a sketch that leaves the WDT
running cannot boot-loop the board.
When the task is porting an ATmega328P sketch
This is the common case, and it compiles on the first try, which is the problem. Work through
in this order:
- Clock — rules 1 and 2. If timing is out by exactly 2× or 8×, stop here.
- Analog reads — rules 3, 6, 7. A ported sketch reads 10 bits against a 4.6 V reference
it believes is 5.000 V. Both errors are silent and they do not cancel.
analogWrite targets — rules 4 and 5. Check D1, D2, D4 specifically.
- EEPROM — rule 9.
EEPROM.put()/get() work, the data does not survive the next
upload.
- Pin numbers past D19 — a Nano has none; here
A6/A7 are 20/21, then E0, E2,
E4, E6, E5, C6 are 22, 23, 24, 25, 26, 27. The core's D25/D26
aliases are swapped relative to their own numbers; use the E* names.
- Libraries that touch registers — anything writing
TCCR*, ADMUX, MCUSR or
assuming digitalPinHasPWM() needs reading. Timer0 is still millis(); Timer3 is new
and lands on D1/D2.
What the port gains, and is worth using instead of working around: 32 MHz, 12-bit ADC with
calibrated internal references, a DAC, a programmable-gain differential amplifier, two
comparators, a fourth timer, and 80 mA outputs.
When the task is analog
The reason to pick this chip over a Nano, and where the Arduino API hides the most.
- The ADC is 12-bit but each
analogRead() costs two conversions: the core takes a
sign-inverted sample via ADCSRC.SPN, averages the pair, then applies a gain correction
(pVal -= pVal >> 7). Budget roughly twice an ATmega328P's conversion time, and do not
expect a raw register read.
- Discard the first sample after any mux or reference change.
- The internal references are ±1 % and calibrated in the factory (
VCAL1/VCAL2/VCAL3);
analogReference() loads the right one. They are far better than a Nano's 1.1 V and are
the right default here — DEFAULT (AVCC) on this board means "referred to a diode drop".
V5D1 (VCC × 1/5), V5D4 (VCC × 4/5) and IVREF are internal ADC channels you pass
straight to analogRead(). Measuring your own supply is two lines (recipe 5).
- The differential amplifier (×1/8/16/32,
ADTMR.DIFS + DAPCR) and the two comparators
have no core API — registers only, and untested in this skill.
- Sleep does not power the analog blocks down. Disable ADC, DAC, comparators and LVD by hand
before sleeping or the µA figures are fiction.
Starting a new project
Do not hand-assemble one. template/ builds clean; scaffold from it:
~/.claude/skills/lgt8f328p-minievb/template/variants/new-project.sh <target-dir> [--full|--minimal]
cd <target-dir> && pio run
--minimal — Blink on LED_BUILTIN (D13). 1,106 B flash, 9 B RAM. Flash this
first on an unfamiliar board: if it does not blink, the problem is the platform, the port
or the bootloader; if it blinks at half or double rate, it is rule 1.
--full (default) — non-blocking heartbeat, serial report of F_CPU/F_OSC/clock source,
12-bit ADC read, real-VCC measurement through V5D1, a DAC ramp on D4, an EEPROM boot
counter and a free-RAM watch. 4,080 B flash, 204 B RAM.
Both figures are what pio run reported with platform lgt8f 1.0.3+sha.dea68b9 /
framework-lgt8fx 2.0.7. Nothing is generated and no paths are embedded, so copying the tree
by hand works identically. template/README.md maps files to subsystems.
When the user already has a project, prefer bringing their platformio.ini and
include/board.h in line with the template over rewriting their code — the clock settings in
rules 1 and 2 are usually the whole bug.
Flashing
Over the USB Micro-B cable, nothing to press — DTR auto-reset opens the bootloader:
pio run -t upload -t monitor
avrdude -c arduino at 57600 (this board definition's default; some bootloaders want
115200 or 19200). The builder always appends -D, which skips the chip erase because the
bootloader erases per page.
Upload failure checklist, in order:
- No port at all → missing WCH VCP driver (CH340G/CH9340C only; HT42B534-1 is CDC and
needs none).
- Wrong port.
- Something wired to D0/D1 — disconnect it. Also check nothing enabled Timer3 PWM on D1.
- Try
upload_speed = 115200, then 19200.
- No auto-reset — press RESET as the upload starts. If a previous sketch set
PMX2.C6EN,
this is now permanent.
avrdude verification mismatch on a board that otherwise runs → add upload_flags = -V.
- Missing TX pull-up: MiniEVB boards are reported to leave D1 without one, which upsets some
bridges during upload; 10 kΩ from D1 to VCC is the known fix.
Recovery is SWD, not ICSP. The ICSP header on the board is a Nano leftover — this chip is
programmed through PE0 (SWC) and PE2 (SWD), which are on the main header. A second Arduino
running the core's LarduinoISP example is the standard programmer: D13→SWC, D12→SWD,
D10→RST, plus VCC/GND, and a 10 µF cap between the programmer's RESET and VCC. Then Burn Bootloader or Upload using Programmer. A purple LQFP32 board with a CH9340C cannot itself
serve as the programmer.
If a sketch disabled SWD (rule 10), hold RESET low while powering the board up so the
sketch never runs, then program over SWD.
Reporting
Be explicit about what is verified. In this skill:
- Built and measured: the template, both variants, against platform
lgt8f
1.0.3+sha.dea68b9 / framework-lgt8fx 2.0.7 / toolchain-atmelavr 1.70300.191015. The
flash and RAM figures above are what the build reported. Every recipe in
reference/recipes.md compiles against this core.
- Verified at the toolchain level: rule 1 — building with
f_cpu = f_osc = 16000000L
makes the preprocessor evaluate F_OSC / F_CPU to 1, while f_cpu = 16000000L alone gives
- Derived from primary documents: the pin map, bonded pads, HDR/PMX/PMCR/MCUSR behaviour,
clock tree, memory map and EEPROM emulation come from the LGT8FX8P databook v1.0.5, the
nulllab LQFP32-Nano schematic and the
lgt8fx core source. Board-level facts (the ≈4.6 V
VCC, the missing TX pull-up, the LT1117-5.0 on VIN) come from the schematic and community
reports and are marked as such in reference/board-hardware.md §3.
- Not verified on hardware by the author of this skill. Nothing here was checked with a
meter, a scope or a load. Recipes 7, 8, 10, 11 and 12 are marked ⚠︎ compile-checked
only in
reference/recipes.md. Say so when a user's measurement disagrees — that is a
gap in this skill, not in their board.
- Untested and API-less: the differential amplifier and the analog comparators. The
dbuezas core exposes no functions for either; the databook register names are in
reference/board-hardware.md §6.
- The databook contradicts itself in two places noted in the reference: the
PMCE write
window (6 clocks in the clock chapter, 4 in the register summary) and flash endurance
(10,000 in the English text, 100,000 in the Chinese line beside it).
1---2name: lgt8f328p-minievb3description: LGT8F328P-LQFP32 MiniEVB ("LGTBF32BP")4---56# LGT8F328P-LQFP32 MiniEVB ("LGTBF32BP")78A board that looks exactly like an Arduino Nano, takes the same sketches, and is not one. The9LGT8F328P is a Logic Green LGT8XM core that executes the AVR instruction set inside a chip10with a different clock system, a 12-bit ADC, a DAC, four timers, no real EEPROM and no11crystal. `board.build.mcu` is literally `atmega328p`, so **everything compiles and most things12silently behave differently**. Almost every failure on this board is a Nano assumption that13was not true.1415Read the reference files rather than reasoning from ATmega328P knowledge.1617- `reference/board-hardware.md` — the complete board reference: the LQFP32 pin map with the18 four bonded pads, Arduino pin numbering past D19, timer/PWM map, PMX0/1/2 alternate19 routing, the HDR high-current table, power tree, clock tree, memory map and the EEPROM20 emulation, **plus** a development guide (§8 toolchain and measured build sizes, §9 the21 clock-prescaler trap, §10 peripheral cookbook, §11 core gotchas, §12 flashing and SWD22 recovery, §13 symptom → cause → fix table).23- `reference/recipes.md` — copy-paste code: `platformio.ini`, `board.h`, blink, the 12-bit24 ADC, measuring the real VCC, the DAC on D4, Timer3 PWM on D1/D2, 80 mA drive, emulated25 EEPROM, moving the UART to D5/D6, sleep, and disabling SWD.26- `template/` — a **project that builds clean**, in two variants, plus a scaffold script. See27 `template/README.md`.2829## Confirm the board first3031The silkscreen `LGTBF32BP` is Logic Green's stylisation of `LGT8F328P`, not a different part.32What actually has to be decided is the **package**, because it picks the core variant:3334| Package | Board | PlatformIO `board` | `build.variant` |35|---|---|---|---|36| **LQFP32** | **Nano-style 30-pin MiniEVB, "purple nano", WAVGAT — this skill** | `LGT8F328P` | `lgt8fx8p` |37| LQFP48 | MiniEVB 48-pin breakout | `lgt8f328p-LQFP48` | `lgt8fx8p48` |38| SSOP20 | "green pseudo Pro Mini" | `LGT8F328P-SSOP20` | `lgt8fx8ps20` |39| LQFP32 | Wemos TTGO XI | `lgt8f328p-wemos-TTGO-XI` | `lgt8fx8p-wemos-TTGO-XI` |4041Count the pins on the chip, not on the header. Getting this wrong gives a build that flashes42and runs with a pin map that is wrong past D19.4344Also read the SOP16 USB bridge marking — **HT42B534-1** (USB CDC, no driver needed on45macOS/Linux, enumerates as `usbmodem`/`ttyACM`) or **CH9340C / CH340G** (needs the WCH VCP46driver, enumerates as `wchusbserial`/`ttyUSB`). It decides why the board does or does not47appear as a port.4849## Orientation5051| | |52|---|---|53| MCU | LGT8F328P (Logic Green / Prodesign), 8-bit **LGT8XM** RISC core, AVR-instruction-compatible, 1.8–5.5 V, 0–32 MHz |54| Clock | **No crystal on the MCU.** Internal 32 MHz RC ±1 %; `CLKPR` boots at ÷8 so the part starts at 4 MHz, and the core reprograms it from `F_OSC / F_CPU`. PB6/PB7 (XTAL) are unused and have no Arduino pin number |55| Memory | 32 KB flash (**29,696 B usable** — 3 KB bootloader), **2 KB SRAM**, **no EEPROM array** — 0/1/2/4/8 KB emulated out of the same flash at 2× cost |56| LED | **L** = D13 / PB5, on = **HIGH**. Red power LED is not controllable |57| ADC | **12 channels, 12-bit**; `analogRead()` returns 10 bits until `analogReadResolution(12)`. Refs: AVCC, AVREF (PE6), **1.024 / 2.048 / 4.096 V** ±1 % |58| DAC | **8-bit, on PD4 = D4.** `analogWrite(4, v)` is an analog voltage, not PWM |59| PWM | D3 (T2B), D5 (T0B), D6 (T0A), D9 (T1A), D10 (T1B), D11 (T2A) **and D1, D2 (Timer3)**. `digitalPinHasPWM()` is wrong on this part |60| UART | D0/D1 — shared with the USB bridge. Movable to D5/D6 via `PMX0.TXD6`/`RXD5` |61| I2C / SPI | A4=SDA, A5=SCL · D10=SS, D11=MOSI, D12=MISO, D13=SCK |62| Extra pins | `E0` (22, SWC), `E2` (23, SWD), `E4` (24), `E6` (**25**, AREF), `E5` (**26**), `C6` (27, RESET) |63| High current | 80 mA on D5, D6, D1/TX, D2, PE4, PE5 via `HDR`; 12 mA otherwise |64| Power | **VCC ≈ 4.6 V on USB** — a protection diode sits in the 5 V line. One VCC pin and one GND pin on the whole package |65| Debug | **SWD on PE0 (SWC) / PE2 (SWD)** — not ICSP. Disableable by one register bit, permanently until a power-up reset trick |66| Toolchain | PlatformIO + `darkautism/pio-lgt8fx` (platform `lgt8f` 1.0.3) + `framework-lgt8fx` 2.0.7 (the dbuezas `lgt8fx` core), `board = LGT8F328P` |6768## Rules that prevent the expensive mistakes6970Each of these produces a failure that points somewhere else.71721. **Never set `board_build.f_osc` to match `board_build.f_cpu`.** `F_OSC` describes the73 oscillator (always 32000000L here — the internal RC); `F_CPU` describes the core; the core74 programs `CLKPR` from `F_DIV = F_OSC / F_CPU`. Setting both to 16 MHz makes `F_DIV = 1`,75 the RC stays undivided, and the part runs at 32 MHz while every `delay()`, `micros()` and76 baud rate is computed for 16 MHz. **Everything is 2× off and nothing reports an error.**77 To run at 16 MHz, change `f_cpu` alone. Most "how to run at 16 MHz" snippets on the web78 contain this bug.792. **Set `board_build.clock_source = 1` explicitly.** Without a `CLOCK_SOURCE` define the80 core skips `lgt8fx8x_clk_src()` and leaves its own default prescaler, so `F_CPU` and the81 real clock diverge. `1` = internal RC, `2` = external crystal — and this board has no82 crystal on the MCU.833. **`analogReadResolution(12)` or you are running a 10-bit ADC.** The core ships84 `analog_resbit = 2` and throws the bottom two bits away for Arduino compatibility. The85 symptom is a chip that "isn't any better than a Nano".864. **`analogWrite(4, v)` is the DAC, not PWM.** D4 = PD4 = DAC0 outputs a real analog87 voltage. It also does not call `pinMode()` and does not short-circuit `0`/`255` to88 `digitalWrite()`. A ported LED-fade works; a MOSFET gate or an opto driven from D4 does89 not, and the scope shows DC instead of edges.905. **`analogWrite(1, …)` kills `Serial`.** The LQFP32 bonds PF1 onto the D1 pad, so Timer3's91 OC3A comes out on the UART TX pin; `analogWrite(2, …)` likewise takes INT0. Use another92 pin, or move the UART with `PMX0.TXD6`/`RXD5` first.936. **`INTERNAL` is 1.024 V, and `INTERNAL2V56` is silently 2.048 V.** Both are `#define`d in94 this core to the LGT references — `INTERNAL2V56` has the *same value* as95 `INTERNAL2V048`. Ported code that calibrated against 1.1 V is ~7 % out; code asking for96 2.56 V is 25 % out. Neither errors.977. **`DEFAULT` means AVCC ≈ 4.6 V, not 5.000 V.** A protection diode in the board's 5 V line98 drops it. Every `DEFAULT`-referenced reading is scaled by ~0.92. Use an internal99 reference, or read the real supply through the chip's own `V5D1` channel (recipe 5).1008. **Four header pads carry two port bits each.** D1 = PD1‖PF1, D2 = PD2‖PF2, `E4` =101 PE4‖PF4, `E5` = PE5‖PF5. Both halves have their own `DDRx`/`PORTx` and both drivers reach102 the same bond wire — writing them against each other is a short inside the package. The103 core handles this for `analogWrite()`; nothing protects hand-written register code.1049. **The emulated EEPROM is erased by every upload, including an update.** It lives in105 program flash, page-swapped by the E2PCTL controller. 1 KB of EEPROM also costs 2 KB of106 flash that PlatformIO's 29,696 B budget does not know about, and only 1020 of each 1024107 bytes are usable. Anything that must survive a firmware update needs another home.10810. **Never write `MCUSR` with bit 7 set.** `MCUSR[7]` is `SWDD` — it disables the SWD port,109 and with it debugging and ISP recovery, permanently until you hold RESET low through a110 power-up so the sketch cannot run. `MCUSR = 0;` is safe. `MCUSR = 0xFF;` to "clear the111 reset flags" is a brick.11211. **Keep the 32 MHz RC enabled (`PMCR[0]`) even if you switch the master clock.** `E2P_clk`113 is 32 MHz ÷ 32 and comes only from that oscillator; without it every EEPROM operation and114 every flash self-read stops working, with no error.11512. **`digitalPinHasPWM()` is wrong here** — inherited unchanged from the AVR core, it116 reports 3/5/6/9/10/11 and misses D1, D2 and D4. Do not let a library use it to pick a pin.11713. **`PMX0`, `PMX1`, `PMX2`, `PMCR`, `CLKPR` and `ECCR` are write-protected.** Set the guard118 bit (`0x80`) first, then complete the real write within 4–6 system clocks. A single119 ordinary assignment does nothing at all — the register reads back unchanged and the120 feature simply never turns on.12114. **PE6 is AREF and PC6 is RESET until you say otherwise.** `PMX2.E6EN` and `PMX2.C6EN`122 turn them into GPIO; taking PC6 also takes away DTR auto-reset, so every subsequent123 upload needs a manual reset.12415. **One VCC pin, one GND pin, six 80 mA pads.** The databook says do not drive four125 high-current loads at once on this package. The bond wires are the limit, not the pads.12616. **SRAM is still 2 KB with no MPU.** `F()` every literal, `PROGMEM` every table, watch127 free RAM — the Nano arithmetic is unchanged, and 32 MHz does not buy you memory.128129The watchdog rule from the Nano does **not** apply: the core installs `__patch_wdt()` in130`.init3` (`MCUSR = 0; wdt_disable();`) before `main()`, so a sketch that leaves the WDT131running cannot boot-loop the board.132133## When the task is porting an ATmega328P sketch134135This is the common case, and it compiles on the first try, which is the problem. Work through136in this order:1371381. **Clock** — rules 1 and 2. If timing is out by exactly 2× or 8×, stop here.1392. **Analog reads** — rules 3, 6, 7. A ported sketch reads 10 bits against a 4.6 V reference140 it believes is 5.000 V. Both errors are silent and they do not cancel.1413. **`analogWrite` targets** — rules 4 and 5. Check D1, D2, D4 specifically.1424. **EEPROM** — rule 9. `EEPROM.put()`/`get()` work, the data does not survive the next143 upload.1445. **Pin numbers past D19** — a Nano has none; here `A6`/`A7` are 20/21, then `E0`, `E2`,145 `E4`, `E6`, `E5`, `C6` are 22, 23, 24, **25**, **26**, 27. The core's `D25`/`D26`146 aliases are swapped relative to their own numbers; use the `E*` names.1476. **Libraries that touch registers** — anything writing `TCCR*`, `ADMUX`, `MCUSR` or148 assuming `digitalPinHasPWM()` needs reading. Timer0 is still `millis()`; Timer3 is new149 and lands on D1/D2.150151What the port *gains*, and is worth using instead of working around: 32 MHz, 12-bit ADC with152calibrated internal references, a DAC, a programmable-gain differential amplifier, two153comparators, a fourth timer, and 80 mA outputs.154155## When the task is analog156157The reason to pick this chip over a Nano, and where the Arduino API hides the most.158159- The ADC is 12-bit but each `analogRead()` costs **two** conversions: the core takes a160 sign-inverted sample via `ADCSRC.SPN`, averages the pair, then applies a gain correction161 (`pVal -= pVal >> 7`). Budget roughly twice an ATmega328P's conversion time, and do not162 expect a raw register read.163- Discard the first sample after any mux or reference change.164- The internal references are ±1 % and calibrated in the factory (`VCAL1`/`VCAL2`/`VCAL3`);165 `analogReference()` loads the right one. They are far better than a Nano's 1.1 V and are166 the right default here — `DEFAULT` (AVCC) on this board means "referred to a diode drop".167- `V5D1` (VCC × 1/5), `V5D4` (VCC × 4/5) and `IVREF` are internal ADC channels you pass168 straight to `analogRead()`. Measuring your own supply is two lines (recipe 5).169- The differential amplifier (×1/8/16/32, `ADTMR.DIFS` + `DAPCR`) and the two comparators170 have **no core API** — registers only, and untested in this skill.171- Sleep does not power the analog blocks down. Disable ADC, DAC, comparators and LVD by hand172 before sleeping or the µA figures are fiction.173174## Starting a new project175176Do not hand-assemble one. `template/` builds clean; scaffold from it:177178```sh179~/.claude/skills/lgt8f328p-minievb/template/variants/new-project.sh <target-dir> [--full|--minimal]180cd <target-dir> && pio run181```182183- `--minimal` — Blink on `LED_BUILTIN` (D13). **1,106 B** flash, **9 B** RAM. **Flash this184 first on an unfamiliar board**: if it does not blink, the problem is the platform, the port185 or the bootloader; if it blinks at half or double rate, it is rule 1.186- `--full` (default) — non-blocking heartbeat, serial report of `F_CPU`/`F_OSC`/clock source,187 12-bit ADC read, real-VCC measurement through `V5D1`, a DAC ramp on D4, an EEPROM boot188 counter and a free-RAM watch. **4,080 B** flash, **204 B** RAM.189190Both figures are what `pio run` reported with platform `lgt8f` 1.0.3+sha.dea68b9 /191`framework-lgt8fx` 2.0.7. Nothing is generated and no paths are embedded, so copying the tree192by hand works identically. `template/README.md` maps files to subsystems.193194When the user already has a project, prefer bringing their `platformio.ini` and195`include/board.h` in line with the template over rewriting their code — the clock settings in196rules 1 and 2 are usually the whole bug.197198## Flashing199200Over the USB Micro-B cable, nothing to press — DTR auto-reset opens the bootloader:201202```sh203pio run -t upload -t monitor204```205206`avrdude -c arduino` at **57600** (this board definition's default; some bootloaders want207115200 or 19200). The builder always appends `-D`, which skips the chip erase because the208bootloader erases per page.209210Upload failure checklist, in order:2112121. **No port at all** → missing WCH VCP driver (CH340G/CH9340C only; HT42B534-1 is CDC and213 needs none).2142. Wrong port.2153. Something wired to D0/D1 — disconnect it. Also check nothing enabled Timer3 PWM on D1.2164. Try `upload_speed = 115200`, then `19200`.2175. No auto-reset — press RESET as the upload starts. If a previous sketch set `PMX2.C6EN`,218 this is now permanent.2196. `avrdude` verification mismatch on a board that otherwise runs → add `upload_flags = -V`.2207. Missing TX pull-up: MiniEVB boards are reported to leave D1 without one, which upsets some221 bridges during upload; 10 kΩ from D1 to VCC is the known fix.222223**Recovery is SWD, not ICSP.** The ICSP header on the board is a Nano leftover — this chip is224programmed through PE0 (SWC) and PE2 (SWD), which are on the main header. A second Arduino225running the core's `LarduinoISP` example is the standard programmer: D13→SWC, D12→SWD,226D10→RST, plus VCC/GND, and a 10 µF cap between the programmer's RESET and VCC. Then `Burn227Bootloader` or `Upload using Programmer`. A purple LQFP32 board with a CH9340C cannot itself228serve as the programmer.229230If a sketch disabled SWD (rule 10), **hold RESET low while powering the board up** so the231sketch never runs, then program over SWD.232233## Reporting234235Be explicit about what is verified. In this skill:236237- **Built and measured**: the template, both variants, against platform `lgt8f`238 1.0.3+sha.dea68b9 / `framework-lgt8fx` 2.0.7 / `toolchain-atmelavr` 1.70300.191015. The239 flash and RAM figures above are what the build reported. Every recipe in240 `reference/recipes.md` compiles against this core.241- **Verified at the toolchain level**: rule 1 — building with `f_cpu = f_osc = 16000000L`242 makes the preprocessor evaluate `F_OSC / F_CPU` to 1, while `f_cpu = 16000000L` alone gives243 2.244- **Derived from primary documents**: the pin map, bonded pads, HDR/PMX/PMCR/MCUSR behaviour,245 clock tree, memory map and EEPROM emulation come from the LGT8FX8P databook v1.0.5, the246 nulllab LQFP32-Nano schematic and the `lgt8fx` core source. Board-level facts (the ≈4.6 V247 VCC, the missing TX pull-up, the LT1117-5.0 on VIN) come from the schematic and community248 reports and are marked as such in `reference/board-hardware.md` §3.249- **Not verified on hardware by the author of this skill.** Nothing here was checked with a250 meter, a scope or a load. Recipes 7, 8, 10, 11 and 12 are marked **⚠︎ compile-checked251 only** in `reference/recipes.md`. Say so when a user's measurement disagrees — that is a252 gap in this skill, not in their board.253- **Untested and API-less**: the differential amplifier and the analog comparators. The254 dbuezas core exposes no functions for either; the databook register names are in255 `reference/board-hardware.md` §6.256- The databook contradicts itself in two places noted in the reference: the `PMCE` write257 window (6 clocks in the clock chapter, 4 in the register summary) and flash endurance258 (10,000 in the English text, 100,000 in the Chinese line beside it).