Boot Sequence
EEPROM Boot (Hardware)
Section titled “EEPROM Boot (Hardware)”The SkyWalker-1 firmware is stored in a 24Cxx-family I2C EEPROM in Cypress C2 format. On power-up, the FX2 boot ROM reads this firmware automatically — no host interaction is required.
C2 EEPROM Format
Section titled “C2 EEPROM Format”| Offset | Size | Field | SkyWalker-1 Value |
|---|---|---|---|
| 0 | 1 | Marker | 0xC2 (external memory, large code model) |
| 1 | 2 | VID (LE) | 0x09C0 |
| 3 | 2 | PID (LE) | 0x0203 |
| 5 | 2 | DID (LE) | 0x0000 |
| 7 | 1 | Config | 0x40 (400 kHz I2C) |
Code segments follow the header: 2-byte length (BE) + 2-byte target address (BE) + data. Maximum segment size is 1023 bytes (FX2 I2C boot ROM buffer limit). All SkyWalker-1 variants use 10 segments.
The terminator is 0x80xx (high bit set) + 2-byte entry point address (0xE600 = CPUCS register).
Kernel Driver Boot Flow
Section titled “Kernel Driver Boot Flow”After USB enumeration, the Linux dvb_usb_gp8psk driver executes this initialization sequence:
-
GET_8PSK_CONFIG (0x80) — Read the configuration status byte. Check bit 0 (
bm8pskStarted). -
BOOT_8PSK (0x89, wValue=1) — If not started, power on the BCM4500 demodulator. Then read the firmware version via GET_FW_VERS (0x92).
-
LOAD_BCM4500 (0x88) — If bit 1 (
bm8pskFW_Loaded) is clear, load BCM4500 firmware. This only applies to Rev.1 Warm (PID 0x0201). On SkyWalker-1, this bit is always set and 0x88 returns STALL. -
START_INTERSIL (0x8A, wValue=1) — If bit 2 (
bmIntersilOn) is clear, enable the LNB power supply. -
SET_DVB_MODE (0x8E, wValue=1) — Attempt to set DVB mode. This STALLs on all SkyWalker-1 firmware versions (the command is a no-op).
-
ARM_TRANSFER (0x85, wValue=0) — Abort any pending MPEG-2 transfer to ensure a clean state.
-
Device ready for tuning — The kernel driver reports the frontend as available.
BCM4500 Demodulator Boot (BOOT_8PSK, 0x89)
Section titled “BCM4500 Demodulator Boot (BOOT_8PSK, 0x89)”The BOOT_8PSK command handler powers on the BCM4500 demodulator and writes three initialization register blocks via I2C. This sequence was reverse-engineered from stock v2.06 firmware (FUN_CODE_1D4F + FUN_CODE_0ddd) and re-implemented in custom firmware v3.01.0.
-
Assert BCM4500 RESET — Drive P0.5 LOW. This holds the BCM4500’s digital logic in reset while power is applied.
-
Power on — Set P0.1 HIGH (power enable), P0.2 LOW (power disable off). The SkyWalker-1 has complementary power control pins.
-
Wait for power settle — 30 ms delay. The power supply must reach regulation before releasing reset.
-
Release RESET — Drive P0.5 HIGH. The BCM4500 begins its internal power-on reset (POR) and mask ROM boot sequence.
-
Wait for BCM4500 POR — 50 ms delay. The chip needs time for its internal oscillator to stabilize and mask ROM to execute.
-
I2C probe — Read direct register 0xA2 (status) at I2C address 0x08 to verify the chip is alive and responding. If this fails, boot aborts.
-
Write init block 0 — 7 bytes to indirect page 0, starting at register 0x06. Data:
{06 0b 17 38 9f d9 80}. -
Write init block 1 — 8 bytes to indirect page 0, starting at register 0x07. Data:
{07 09 39 4f 00 65 b7 10}. -
Write init block 2 — 3 bytes to indirect page 0, starting at register 0x0F. Data:
{0f 0c 09}. -
Set config_status — OR in
BM_STARTED | BM_FW_LOADED(0x03). Subsequent vendor commands check this flag before operating.
Each init block is written using the BCM4500 indirect register protocol: page select (0xA6 = 0x00), data to 0xA7 (multi-byte with auto-increment), trailing zero to 0xA7, then commit (0xA8 = 0x03). The firmware polls 0xA8 until the command completes before proceeding.
Total boot time: approximately 90 ms (30 ms power settle + 50 ms POR delay + ~10 ms I2C transactions).
Boot Results
Section titled “Boot Results”| Metric | Value |
|---|---|
| Boot time | ~90 ms total |
| config_status after boot | 0x03 (STARTED + FW_LOADED) |
| Direct registers 0xA2-0xA8 | All return 0x02 (powered, not locked — expected without signal) |
| Signal lock | 0x00 (no lock — no satellite signal present) |
Firmware Version Identification
Section titled “Firmware Version Identification”The kernel reads the firmware version on boot via GET_FW_VERS (0x92) and logs it:
gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13Kernel revision constants for hardware detection:
GP8PSK_FW_REV1 = 0x020604 // v2.06.4GP8PSK_FW_REV2 = 0x020704 // v2.07.4If fw_vers >= GP8PSK_FW_REV2, the kernel enables Rev.2-specific code paths. The v2.10 and v2.13 firmwares are newer than either constant and trigger Rev.2 behavior.
FX2 CPUCS Recovery
Section titled “FX2 CPUCS Recovery”The FX2’s CPUCS register at 0xE600 is accessible via the standard vendor request bRequest=0xA0 (RAM read/write), which is handled by the FX2 boot ROM in silicon — not by user firmware. This means firmware can be reloaded over a completely hung device without a physical USB unplug:
sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3Writing 0x01 to CPUCS halts the CPU. New code is written to RAM. Writing 0x00 restarts it. The device re-enumerates with the new firmware.
Custom Debug Boot Modes (v3.01.0)
Section titled “Custom Debug Boot Modes (v3.01.0)”The custom firmware extends BOOT_8PSK (0x89) with incremental debug modes for isolating boot failures:
| wValue | Action | Purpose |
|---|---|---|
| 0x80 | No-op: return config_status and boot_stage | Status check without side effects |
| 0x81 | GPIO + power + delays only (no I2C) | Test power sequencing |
| 0x82 | GPIO + power + I2C probe | Test I2C after power-on |
| 0x83 | GPIO + power + probe + init block 0 | Test first register write |
| 0x84 | I2C probe only (chip already powered) | Isolate I2C from power sequencing |
| 0x85 | Same as 0x82 without bmSTOP | Confirmed the STOP corruption bug |
| 0x01 | Full boot (production) | Normal operation |
| 0x00 | Shutdown | Power down demodulator |
These modes were instrumental in identifying the I2C STOP corruption bug — mode 0x82 (with bmSTOP) failed while mode 0x85 (without bmSTOP) succeeded, pinpointing the exact cause.