User Tools

Site Tools


Vaisala RS92-SGPD firmware

Sonde have 32KB EEPROM chip. Chip contains (probably) some firmware binary patches for VLSI DSP chip, configuration (transmitting frequency, name, callibration data, ..) and others.

Dumping EEPROM with Bus Pirate

EEPROM can be dumped trought servicing connector (flat one). Anny SPI can be used in configuration 00. Digital IO use 2.8V logic, but inputs are 3.3 V tollerant. As power supply can be used anny source in range 4.7-10 V. Voltages bellow cca 7V will result in power-saving mode, but this does not matter for interfacing with EEPROM. Wiring for Bus Pirate is bellow.

Pin RESET must be pulled-down for al least 2 second before anny other operation can start.

Bus Pirate pin Vaisala probe pin
+3V3 NC
+5V 2 - VCC
Vpu NC

Python script for EEPROM dump

TODO: eeprom manipulation scripts and tools


The sonde first used 250kHz clock to read bytes from EEPROM up to addres 376 (included). Then switches to faster bus speed (2MHz).


address space description

Address space in EEPROM can be visualy divided into severall subblocks. Each subblock is separeted from others by wide field of 0x00. Start address of block shows nice alignment to multiple of 0x100 +- frew bytes, those bytes might be missalignment, or more probably footer of previous block.

start address end address name description
0x0000 0x07FF blob 1 firmware, stage 2 bootloader
0x0800 0x4FFF blob 2 firmware, compressed image of X and Y memory (I memory is mapped to X)
0x5000 0x6FFF blob 3 high entropy, (compressed?)
0x7000 0x71FF blob 4 configuration and callibration
0x7200 0x79FF blob 5 event log?
0x7A00 0x7FFF blob 6 runtime status?

blob 1 - stage 2 bootloader

  • series of blobs loaded into X and program memmory
// Structure description in pseudocode
const uint256_t eeprom[32768]; // EEPROM content
int idx = 0;  
while (eeprom[idx] == 1) {
  int data_len = eeprom[idx+1] | (eeprom[idx+2] << 8);
  int addr = eeprom[idx+3] | (eeprom[idx+4] << 8);
  // copy data: X[addr]..X[addr+data_len] = eeprom[idx+5]..eeprom[idx+5+data_len]
  // but some trick for writing program memmory are probably involved
  idx += 5 + data_len;
// end of content
if (eeprom[idx] == 3) {
  data_len = eeprom[idx+1] | (eeprom[idx+2] << 8);
  // data_len souhld be 0
  addr = eeprom[idx+3] | (eeprom[idx+4] << 8);
  goto addr;
  • data_len - bytes to copy into memory
  • addr - data destination address in X memory (instruction memory should be mapped to X+0x2000)

blob 2

This block is compressed. Compression algirithm is rather simple, replaces identical sequences of data with copy-from operation.

struct compressed_block_t {
  chunk_t chunk1;
  chunk_t chunkN;
  chunk_t chunk_exec;    // chunks repeats until EOF chunk is found
struct chunk_t {
  chunk_header_t chunk_header;
  uint8_t chunk_data[];         // chunk size varies and ends with EOF code
struct chunk_header_t {
  uint8_t prefix;      // prefix code used for decompression
  uint1_t bus_type;    // (top bit of address word) 0 => X bus, 1 => Y
  uint15_t address;    // block destionation address
  uint8_t prefix_size; // size of prefix in bites, 0xff for EOF
  • chunk_data are read as bite stream

blob 4 - configuration and calibration

This block (512B long) is repeatedly broadcasted by sonde, in first part of frame.

see Callibration data for details

blob 5 - log

TODO: (verification needed)

  • 4B header
  • 42B superblock
  • 7 * 6B - block

blob 6 - status

address symbol meanign
0x7A02 - 0x7A03 DOWN_CNT have something todo with frame count?
0x7A04 ST4 operation status
  • ST4
    • 0 - low power Tx?
    • 1 - medium power Tx?
    • 2 - normal sonde operation
    • 3 - no Tx, set by FW when battery is low (eg bellow 6 or 7 V, not sure) for some time (100 frames?), sonde stop transmitting


start date (UTC) ID type start location EEPROM dump
2013-02-25 00:00 H2813056 RS92-SGPD CZ, Prague - Libuš
2013-07-03 00:00 H4043220 RS92-SGPD CZ, Prague - Libuš TODO
project/weathersonde/firmware.txt · Last modified: 2018/09/24 11:51 by pinky