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:

  1. Buffering changes in RAM

  2. Only writing to flash on explicit save command

  3. 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