Flash Memory Layout
The AddVantage PPG uses flash memory for firmware and persistent configuration storage. The SKEAZ128 has 128KB flash organized to support the DFU bootloader, application firmware, and EEPROM emulation.
Memory Map Overview
Full Flash Map (with DFU Bootloader)
Address Range |
Size |
Purpose |
|---|---|---|
0x00000000 - 0x000003FF |
1KB |
Vector table (bootloader) |
0x00000400 - 0x0000040F |
16B |
Flash Configuration Field (FCF) |
0x00000410 - 0x00002FFF |
~12KB |
DFU Bootloader code |
0x00003000 - 0x000030FF |
256B |
Application header |
0x00003100 - 0x0001EFFF |
~112KB |
Application code |
0x0001F000 - 0x0001FEFF |
3840B |
Configuration storage (EEPROM) |
0x0001FF00 - 0x0001FFFF |
256B |
Reserved |
Legacy Map (without Bootloader)
Address Range |
Size |
Purpose |
|---|---|---|
0x00000000 - 0x0001EFFF |
124KB |
Application code |
0x0001F000 - 0x0001FEFF |
3840B |
Configuration storage |
0x0001FF00 - 0x0001FFFF |
256B |
Reserved |
DFU Bootloader Memory Layout
The DFU bootloader occupies the first 12KB of flash and enables field firmware updates via UART.
Bootloader Region (0x0000 - 0x2FFF)
Address |
Size |
Description |
|---|---|---|
0x0000 - 0x00BF |
192B |
Bootloader vector table |
0x00C0 - 0x03FF |
832B |
Bootloader code (pre-FCF) |
0x0400 - 0x040F |
16B |
Flash Configuration Field (FCF) |
0x0410 - 0x2FFF |
~11KB |
Bootloader code (post-FCF) |
Important: The FCF at 0x400 must never be erased or the device will become inaccessible.
Application Header (0x3000 - 0x30FF)
The application header contains metadata used by the bootloader to validate firmware:
typedef struct {
uint32_t magic; // Must be 0xADD7A9E0
uint32_t header_version; // Header structure version
uint32_t app_version_major;
uint32_t app_version_minor;
uint32_t app_version_patch;
uint32_t app_size; // Size of application code
uint32_t app_crc32; // CRC-32 of application code
uint32_t app_entry_point; // Entry point address
uint32_t vector_table_addr; // Vector table address
uint32_t build_timestamp; // Unix timestamp
uint8_t build_id[32]; // Build identifier
uint8_t reserved[184]; // Reserved (0xFF)
} app_header_t; // Total: 256 bytes
Application Code Region (0x3100 - 0x1EFFF)
Application code starts at 0x3100 (immediately after the header). Maximum size is approximately 112KB.
Address |
Purpose |
|---|---|
0x3100 |
Application vector table |
0x31C0 |
Application code start |
RAM Layout
Address Range |
Size |
Purpose |
|---|---|---|
0x1FFFF000 - 0x1FFFF003 |
4B |
DFU magic value location |
0x1FFFF004 - 0x20002FFF |
~16KB |
Application RAM |
0x20003000 |
- |
Stack top (grows down) |
DFU Magic Value
The bootloader checks address 0x1FFFF000 for the magic value 0xDF00CAFE to determine if DFU mode was requested by the application.
#define DFU_MAGIC_ADDRESS 0x1FFFF000
#define DFU_MAGIC_VALUE 0xDF00CAFE
Configuration Storage (0x1F000)
The configuration region is organized as follows:
Reserved Area (0-99)
Address |
Size |
Description |
|---|---|---|
0-99 |
100B |
Reserved for future use |
Configuration Parameters (100-127)
Address |
Name |
Default |
Description |
|---|---|---|---|
100 |
CUTOFF_PRESSURE |
50 |
Gas pressure cutoff (PSI) |
101 |
CUTOFF_TEMP_LOW |
20 |
Low temperature cutoff (°C) |
102 |
CUTOFF_TEMP_HIGH |
100 |
High temperature cutoff (°C) |
103 |
FUEL_MAP_SELECT |
1 |
Active fuel map (1-4) |
104 |
BAUD_DIV10 |
25 |
CAN baud rate / 10 (25 = 250kbit) |
105 |
GAS_ENABLE |
1 |
Gas flow enabled (0/1) |
106 |
EEC_MSB |
0 |
Engine type multiplier MSB |
107 |
EEC_LSB |
100 |
Engine type multiplier LSB |
108 |
RPM_MAX |
30 |
Max RPM / 100 (30 = 3000 RPM) |
109 |
RPM_OFFSET |
0 |
RPM axis offset for fuel map |
110 |
TORQUE_MAX |
100 |
Max torque percentage |
111 |
TORQUE_OFFSET |
0 |
Torque axis offset |
112-119 |
Reserved |
- |
- |
120 |
TANK_FULL |
200 |
Tank full ADC reading |
121 |
TANK_EMPTY |
50 |
Tank empty ADC reading |
122 |
PRESSURE_GAIN |
100 |
Pressure sensor gain |
123 |
PRESSURE_OFFSET |
0 |
Pressure sensor offset |
124 |
ENGINE_PROFILE |
1 |
Engine profile (1-18) |
125 |
FLAGS |
0 |
Configuration flags |
126 |
INJECTORDEADTIME |
10 |
Injector dead time (0.1ms units) |
127 |
INJECTORBASEMULT |
100 |
Base fuel multiplier |
Temperature Correction Map (128-227)
100-byte lookup table for temperature-based fuel correction.
Address |
Temperature |
Description |
|---|---|---|
128 |
-40°C |
Correction at -40°C |
129 |
-39°C |
Correction at -39°C |
… |
… |
… |
168 |
0°C |
Correction at 0°C |
188 |
20°C |
Correction at 20°C (100 = no correction) |
208 |
40°C |
Correction at 40°C |
227 |
59°C |
Correction at 59°C |
Interpretation: Value of 100 = 100% (no correction). Value of 110 = 110% (10% more fuel).
Legacy Temperature Map (228-239)
12-byte legacy temperature correction table (deprecated, for backwards compatibility).
Differential Pressure Correction (240-255)
16-byte lookup table for gas pressure compensation.
Address |
Pressure |
Description |
|---|---|---|
240 |
0 PSI |
Correction at 0 PSI differential |
241 |
5 PSI |
Correction at 5 PSI |
… |
… |
… |
255 |
75 PSI |
Correction at 75 PSI |
Fuel Maps (256-1279)
Four 16x16 fuel maps, 256 bytes each.
Fuel Map 1 (256-511)
Offset |
RPM Bin |
Torque Bin |
Description |
|---|---|---|---|
0 |
0 |
0 |
Low RPM, low torque |
1 |
0 |
1 |
Low RPM, torque bin 1 |
… |
… |
… |
… |
15 |
0 |
15 |
Low RPM, high torque |
16 |
1 |
0 |
RPM bin 1, low torque |
… |
… |
… |
… |
255 |
15 |
15 |
High RPM, high torque |
Map Value Interpretation:
0 = No gas injection
50 = 50% of base timing
100 = 100% of base timing
150 = 150% of base timing (50% enrichment)
Fuel Map 2-4 (512-767, 768-1023, 1024-1279)
Same format as Fuel Map 1. Used for different engine profiles or operating modes.
Manifold Pressure Correction (768-783)
16-byte lookup table for manifold absolute pressure (MAP) correction.
Address |
MAP |
Description |
|---|---|---|
768 |
0 kPa |
Correction at vacuum |
769 |
10 kPa |
… |
… |
… |
… |
783 |
150 kPa |
Correction at boost |
Telemetry Persistence (1280-3839)
Ring buffer storage for cumulative telemetry data.
Address |
Size |
Description |
|---|---|---|
1280-1535 |
256B |
Ring buffer 1 |
1536-1791 |
256B |
Ring buffer 2 |
1792-2047 |
256B |
Ring buffer 3 |
2048-3839 |
1792B |
Reserved for expansion |
Each ring buffer stores:
Cumulative gas usage
Cumulative diesel usage
Operating hours
Timestamp
Flash Programming API
Reading Configuration
#include "flash.h"
// Read single byte
uint8_t value = flash_read_byte(OFFSET_CUTOFF_PRESSURE);
// Read fuel map value
uint8_t map_value = flash_read_map(rpm_bin, torque_bin, map_number);
Writing Configuration
// Write single byte
flash_write_byte(OFFSET_CUTOFF_PRESSURE, 60);
// Write fuel map value
flash_write_map(rpm_bin, torque_bin, map_number, new_value);
// Commit changes (required after writes)
flash_commit();
Factory Reset
// Reset all configuration to defaults
flash_factory_reset();
Flash Wear Considerations
The SKEAZ128 flash has approximately 10,000 erase cycles per sector. The firmware minimizes wear by:
Buffering changes in RAM
Only writing to flash on explicit save command
Using wear-leveling for telemetry ring buffers
Recommendation: Avoid frequent configuration changes in production. Calibration should be done during initial setup.
Backup and Restore
Use the serial console to backup configuration:
# Connect at 57600 baud
# Enter password
m # Memory dump - outputs all flash contents as hex
Configuration can be restored using the r command:
r 100,50 # Set address 100 to value 50
r 127,110 # Set base multiplier to 110%
Address Constants (flash.h)
#define FLASH_BASE_ADDR 0x1F000
#define OFFSET_CUTOFF_PRESSURE 100
#define OFFSET_CUTOFF_TEMP_LOW 101
#define OFFSET_CUTOFF_TEMP_HIGH 102
#define OFFSET_FUEL_MAP_SELECT 103
#define OFFSET_BAUD_DIV10 104
#define OFFSET_GAS_ENABLE 105
#define OFFSET_EEC_MSB 106
#define OFFSET_EEC_LSB 107
#define OFFSET_RPM_OFFSET 109
#define OFFSET_ENGINE_PROFILE 124
#define OFFSET_INJECTORDEADTIME 126
#define OFFSET_INJECTORBASEMULT 127
#define OFFSET_TEMP_MAP 128
#define OFFSET_DIFF_PRESS_MAP 240
#define OFFSET_FUEL_MAP_1 256
#define OFFSET_FUEL_MAP_2 512
#define OFFSET_FUEL_MAP_3 768
#define OFFSET_FUEL_MAP_4 1024
#define OFFSET_TELEMETRY_RING 1280