๐ฌ Vape Pimp Speedrun
SMOK Novo 6 / Raz TN9000 / Kraze HD7K N32G031 ARM Cortex-M0 ยท 48MHz ยท 64KB Flash
๐จ SAFETY
๐ Battery FIRST ๐งค Gloves ALWAYS โก 3.3V ONLY ๐ฅ MOSFET = fire risk
1. Pry bottom cap Plastic spudger only
CC1 โ SWDIO CC2 โ SWCLK
openocd -f stlink.cfg
-f n32g031.cfg
PNG โ RGB565 80ร160 big-endian
SPI: TL866 / CH341A Desolder + SSOP adapter
2. Disconnect battery FIRST โ puncture = ๐ฅ
GND โ GND 3.3V logic ONLY โก
dump_image fw.bin
0x08000000 0x10000
Python + Pillow
struct.pack('>H',...)
SWD: flash write_image
Or flashrom via RPi
3. Clean PCB 99% IPA + nitrile gloves ๐งค
USB-C breakout
- 5.1kฮฉ pull-downs
0xFFFFFFFF? โ FMC ๐ Chip-erase or ISP
MADCTL 0x36
Bit3: RGBโBGR swap
N32G031-based vape โ pocket console. Novo 6 ยท Raz TN9000 ยท Kraze HD7K & clones.
graph LR A["๐ OPEN<br>Teardown + clean<br><i>spudger, IPA+gloves</i>"] B["๐ CONNECT<br>USB-C SWD tap<br><i>CC1=SWDIO, CC2=SWCLK<br>3.3V ONLY!</i>"] C["๐ฅ DUMP<br>OpenOCD flash<br><i>0x08000000<br>64KB MCU, 1MB SPI NOR</i>"] D["๐จ MOD<br>RGB565 bitmaps<br><i>80ร160 px, big-endian<br>Pillow</i>"] E["๐ค FLASH<br>SPI/SWD write<br><i>TL866 / CH341A<br>flashrom</i>"] A -->|"โฑ๏ธ"| B -->|"โฑ๏ธ"| C -->|"โฑ๏ธ"| D -->|"โฑ๏ธ"| E style A fill:#4a9,color:#fff style B fill:#49a,color:#fff style C fill:#69c,color:#fff style D fill:#e9973f,color:#fff style E fill:#a882ff,color:#fff
๐งค GLOVES MANDATORY ยท ๐ DISCONNECT BATTERY FIRST
๐ง HW Overview
graph TD HW["๐ HW SPECS"] MCU["๐ง MCU<br>N32G031K8Q7<br>ARM Cortex-M0 ยท 48MHz<br>64KB Flash ยท 8KB SRAM"] SCR["๐บ Screen<br>0.96โณ 80ร160 IPS TFT<br>ST7735S or GC9107<br>4-wire SPI"] FLS["๐พ Flash<br>GT25Q80A 8Mbit (1MB)<br>bitmaps, puff counters, config"] CEL["๐ Cell<br>13450 Li-ion ~1700mAh<br>UNPROTECTED ยท puncture = ๐ฅ"] COI["โก Coil<br>N-ch MOSFET driver<br>latch HIGH = fire hazard โ ๏ธ"] HW --- MCU HW --- SCR HW --- FLS HW --- CEL HW --- COI style HW fill:#69c,color:#fff,stroke:#357,stroke-width:2px style CEL fill:#f44,color:#fff,stroke:#a00,stroke-width:2px style COI fill:#f80,color:#fff,stroke:#a50,stroke-width:2px
1. ๐ ๏ธ Teardown
| # | Do | โ ๏ธ |
|---|---|---|
| 1 | Pry bottom cap โ slide sled out | Plastic spudger only |
| 2 | Disconnect battery lead FIRST | Puncture = thermal runaway ๐ฅ |
| 3 | Clean PCB: 99% IPA + nitrile gloves ๐งค | Nicotine absorbs through skin |
| 4 | ID chip markings (QFN32/LQFP32) | Varies between production runs |
๐ฅ PULL GENTLY: Do NOT puncture the 13450-size 1700mAh lithium-ion battery! Puncture = Thermal runaway = fire.
๐งค E-liquid has nicotine (toxic and absorbs through skin!). Use 99% Isopropyl Alcohol to clean the logic board and wear nitrile gloves!
2. ๐ SWD Tap
The USB-C SWD Hack: Hardware engineers often wire the SWDIO and SWCLK debug lines directly to the unused CC1/CC2 pins on the USB-C port!
graph LR subgraph USB["๐ USB-C Port"] CC1["CC1"] CC2["CC2"] GND_U["GND"] VBUS["VBUS 5V"] end subgraph PRB["๐ฌ Debug Probe"] SWDIO["SWDIO"] SWCLK["SWCLK"] PGND["GND"] end subgraph MCU["๐ง N32G031"] PA13["PA13"] PA14["PA14"] end CC1 -->|"data"| SWDIO -->|"debug"| PA13 CC2 -->|"clock"| SWCLK -->|"debug"| PA14 GND_U -->|"common"| PGND VBUS -.->|"LETHAL"| PA13 style VBUS fill:#f44,color:#fff,stroke:#a00,stroke-width:3px style CC1 fill:#4a9,color:#fff style CC2 fill:#49a,color:#fff style PA13 fill:#6a6,color:#fff style PA14 fill:#6a6,color:#fff style SWDIO fill:#4a9,color:#fff style SWCLK fill:#49a,color:#fff
# USB-C Debug Accessory Mode: CC1โSWDIO | CC2โSWCLK | GNDโGND
# โ ๏ธ 3.3V ONLY โ 5V probe = dead MCU | Need breakout + 5.1kฮฉ pull-downs
openocd -f interface/stlink.cfg -f target/n32g031.cfg \
-c "init; halt; dump_image fw.bin 0x08000000 0x10000; exit"
# Got 0xFFFFFFFF? โ FMC read-protection ON ๐ โ chip-erase (loses factory FW)
# Alt: SRAM injection via ISP (BOOT0 pin) or UART bootloader| Tool | Use |
|---|---|
| ST-Link V2 / J-Link / CMSIS-DAP | SWD debug โ 3.3V logic |
| Custom USB-C breakout | Expose CC1/CC2 + 5.1kฮฉ pull-downs |
| OpenOCD / pyOCD | halt โ dump_image โ flash write_image |
3. ๐ฅ FW Extraction
flowchart TD A(["๐ฌ Connect SWD"]) --> B{"halt + dump?"} B -->|"got data"| C["๐ Ghidra/IDA"] B -->|"0xFF..."| D{"๐ FMC Locked"} D -->|"nuke it"| E["๐ฃ Chip Erase"] D -->|"bypass"| F["๐ SRAM Inject"] D -->|"alt"| G["๐ก UART Boot"] E --> H["โ ๏ธ Factory FW Gone"] H --> I(["๐ค Flash Custom"]) F --> J["๐ RAM Bypass"] G --> J J --> C C --> K["๐บ๏ธ Locate Bitmaps"] style A fill:#4a9,color:#fff style D fill:#f44,color:#fff,stroke:#a00,stroke-width:3px style H fill:#f80,color:#fff style E fill:#fa0,color:#000 style I fill:#4c9,color:#fff style K fill:#69c,color:#fff
๐ FMC Lock? If the memory dump gives you endless
0xFFFFFFFF, the Flash Memory Controller (FMC) is locked. Youโll need SRAM injection via ISP mode or a Whole Chip Erase (destroys factory firmware forever).
4. ๐จ Display Mod
Pixel Format: RGB565 โ 16-bit color (5 bits Red, 6 bits Green, 5 bits Blue) stored in big-endian layout. ๐
flowchart LR A(["๐ผ๏ธ PNG"]) -->|"Pillow"| B["๐ 80x160"] B -->|"convert"| C["๐จ RGB565"] C -->|"pack BE"| D["๐ฆ out.bin"] D -->|"desolder"| E["๐ง SSOP Adapt"] E -->|"program"| F["๐พ TL866/CH341A"] F -->|"resolder"| G(["โ Custom LCD"]) style A fill:#69c,color:#fff style C fill:#e9973f,color:#fff style D fill:#a882ff,color:#fff style G fill:#4c9,color:#fff
# PNG โ RGB565 binary (big-endian!) โ flash to GT25Q80A via TL866/CH341A/flashrom
from PIL import Image; import struct
img = Image.open('custom.png').convert('RGB').resize((80,160))
open('out.bin','wb').write(b''.join(
struct.pack('>H',((r>>3)<<11)|((g>>2)<<5)|(b>>3))
for y in range(160) for x in range(80) for r,g,b in [img.getpixel((x,y))]))| Programmer | Interface | Notes |
|---|---|---|
| MiniPro TL866 | SPI NOR | Desolder chip, SSOPโDIP adapter |
| CH341A | SPI NOR | Cheapest option, clip or desolder |
| flashrom | CLI | flashrom -p ch341a_spi -r dump.bin |
5. ๐ฅ๏ธ LCD Init
sequenceDiagram participant MCU as MCU participant LCD as LCD rect rgb(68, 207, 110, 0.1) Note over MCU,LCD: Reset Phase MCU->>LCD: SWRESET 0x01 Note over LCD: 150ms wait MCU->>LCD: SLPOUT 0x11 Note over LCD: 500ms wait end rect rgb(83, 223, 221, 0.1) Note over MCU,LCD: Config Phase MCU->>LCD: COLMOD 0x3A 0x05 (RGB565) MCU->>LCD: MADCTL 0x36 (orientation) Note right of MCU: Bit3 = RGB/BGR swap MCU->>LCD: CASET 0x2A (col range) MCU->>LCD: RASET 0x2B (row range) end rect rgb(168, 130, 255, 0.1) Note over MCU,LCD: Activate Phase MCU->>LCD: DISPON 0x29 MCU->>LCD: RAMWR 0x2C + pixels end
SWRESET(0x01) โ SLPOUT(0x11) โ COLMOD(0x3A,0x05=RGB565) โ MADCTL(0x36) โ DISPON(0x29)
- ๐ Red/blue swapped? XOR
MADCTLwith0x08(bit 3 toggles RGBโBGR). Donโt rewire. - โฌ Black border/offset? Set
CASET(0x2A)/RASET(0x2B)โ try_colstart=0x01or0x1A. - ๐ฒ GC9107 blank? Must send unlock
0xFFโ0xA5before any command. Init may start0xFE/0xEF/0xEB.
6. ๐พ Custom FW
graph TD subgraph SDK["๐ Community SDKs"] A["ColorLCDVape-RE"] -->|"memory maps"| C["โก Custom FW"] B["Vaporware SDK"] -->|"display API"| C D["RAZ-RE"] -->|"HW pinouts"| C end C -->|"compile"| E["๐ง arm-gcc"] E -->|"flash"| F["๐ค SWD Write"] F --> G(["๐ฎ Pocket Console"]) subgraph SAFE["๐จ Safety Critical"] C -->|"must have"| H["โฑ๏ธ Timer ISR"] H -->|"kills"| I["๐ MOSFET Off"] C -->|"must have"| J["๐ ADC Watch"] J -->|"triggers"| K["๐ LVC Cutoff"] end style H fill:#f44,color:#fff,stroke:#a00,stroke-width:3px style J fill:#fa0,color:#000,stroke:#a50,stroke-width:2px style G fill:#4c9,color:#fff style I fill:#f44,color:#fff style K fill:#fa0,color:#000
โ ๏ธ THE COIL OF DEATH: If you write your own C code and your MOSFET pin latches HIGH by accident, your coil will melt, the pod will catch fire, and the battery will vent. ALWAYS code a strict hardware-timer-backed thermal cutoff limit! โฑ๏ธ๐จ
๐ก๏ธ Safety Pattern
// MANDATORY: hardware-timer-backed coil cutoff โ main loop bugs CANNOT override
#define MAX_FIRE_MS 10000 // 10s hard ceiling
#define MIN_VBAT_MV 3000 // 3.0V low-voltage cutoff
void init_safety(void) {
GPIO_ResetBits(GPIOA, COIL_PIN); // default: coil OFF
TIM_SetAutoReload(TIM3, MAX_FIRE_MS); // ISR kills MOSFET
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
ADC_AnalogWatchdogThresholdsConfig(ADC1, 0xFFF, MIN_VBAT_MV);
}๐ฆ Deps & Tools
| Category | Item | Notes |
|---|---|---|
| ๐ง Probe | ST-Link V2 / J-Link / CMSIS-DAP | SWD debug โ 3.3V logic |
| ๐พ Programmer | MiniPro TL866 / CH341A / flashrom | SPI NOR read/write (desolder chip) |
| ๐ฅ๏ธ Debug | OpenOCD / pyOCD | halt โ dump_image โ flash write_image |
| ๐ฌ RE | Ghidra / IDA Free | ARM Cortex-M0 disassembly |
| ๐ Convert | Python + Pillow | PNGโRGB565 |
| โ๏ธ Compile | arm-none-eabi-gcc | Custom firmware cross-compile |
| ๐ ColorLCDVape-RE | ginbot86 | Memory maps, re-theming docs |
| ๐ RAZ-RE | xbenkozx | HW revision pinouts |
| ๐ Vaporware SDK | ImoverEngineering | Minimal C SDK โ display only, no coil code |
๐จ Gotchas
| Trap | Fix | |
|---|---|---|
| ๐ฅ | MOSFET latch-of-death โ GPIO HIGH on crash = coil melts โ fire โ battery vent | Hardware timer ISR kills MOSFET; never trust main loop |
| ๐ | FMC/ROP โ 0xFFFFFFFF dump = read-protected | Chip-erase unlocks but destroys factory FW forever |
| โก | 5V probe on 3.3V MCU = instant death | Level-shift or use 3.3V probe |
| ๐งช | Nicotine residue on PCB absorbs through skin | Nitrile gloves + 99% IPA clean |
| ๐ | Same model โ same chips โ HW revisions swap MCU/display/flash | Verify markings every unit |
| ๐ | RGB565 byte order โ 16-bit big-endian (5R/6G/5B) | Garbled colors = wrong endianness |
| ๐ฑ | USB-C DAM โ standard cables donโt expose CC1/CC2 | Custom breakout + 5.1kฮฉ pull-downs |
| ๐ง | SWD locked? โ ISP via UART BOOT0 pin | Check N32G031 datasheet ยง3.4 |
๐๏ธ Full Architecture
graph TB subgraph L1["๐ Physical"] A["๐ฆ Device"] -->|"pry open"| B["๐ง Teardown"] B -->|"99% IPA"| C["๐งน Clean"] end subgraph L2["๐ Debug"] C -->|"expose CC"| D["๐ USB-C Break"] D -->|"3.3V"| E["๐ฌ SWD Probe"] E -->|"connect"| F["๐ป OpenOCD"] end subgraph L3["๐ฅ Extract"] F -->|"halt"| G{"๐ FMC?"} G -->|"unlocked"| H["๐พ MCU 64KB"] G -->|"locked"| I["๐ฃ Erase"] I -->|"blank MCU"| J["๐ Fresh"] F -->|"SPI read"| K["๐พ Flash 1MB"] end subgraph L4["๐จ Mod"] H -->|"disasm"| L["๐ฌ Ghidra"] K -->|"extract"| M["๐ผ๏ธ Bitmaps"] M -->|"Pillow"| N["๐จ RGB565"] N -->|"program"| O["๐ค Flash SPI"] end subgraph L5["๐พ Custom OS"] L -->|"understand"| P["๐ Write FW"] P -->|"safety!"| Q["๐จ ISR Guard"] Q -->|"deploy"| R(["โ Done"]) end style I fill:#f44,color:#fff,stroke:#a00,stroke-width:2px style Q fill:#f80,color:#fff,stroke:#a50,stroke-width:2px style A fill:#69c,color:#fff style R fill:#4c9,color:#fff style G fill:#f44,color:#fff
๐บ๏ธ Visual workflow map: NovoModCanvas โ