Як прочитати SPD планки DDR5: Windows, CH341A і ESP32 — і чому дампи відрізняються
Це частина ремонту планки Corsair Vengeance DDR5 — основна стаття. Тут — як ми прочитали SPD трьома способами, що вийшло, чому файл із Windows виявився неповним, і як зібрати читач на ESP32: схема, прошивка, наші дампи для порівняння.
Що таке SPD у DDR5
SPD — це «паспорт» планки: обʼєм, швидкості й затримки, профіль XMP, виробник. У DDR5 він лежить у мікросхемі-хабі (SPD5118 чи подібній), займає 1024 байти і поділений на 8 сторінок по 128 байтів. Одночасно видно лише одну сторінку; яку саме — обирає регістр хаба MR11. Хто не вміє перемикати сторінки, той бачить лише першу — це ключ до всієї історії нижче.
Три способи, які ми пробували
| Спосіб | Що потрібно | Результат |
|---|---|---|
| Windows + Thaiphoon Burner | робочий компʼютер, планка в слоті | 1024 байти, але насправді перша сторінка, повторена 8 разів; контрольна сума не сходиться |
| Програматор CH341A + AsProgrammer | програматор, перехідник 1.8 В, дроти до гребінки | жодна адреса не відповіла — ні на робочій, ні на неробочій планці |
| ESP32 + власна прошивка | плата ESP32, 2 резистори, блок 5 В | обидві планки, 1024 байти, 0 помилок читання, контрольна сума правильна |
1. Windows і Thaiphoon Burner
Найпростіше: поставити планку в компʼютер і прочитати програмою. Мінус очевидний — так читається лише робоча планка: неробоча не дає компʼютеру стартувати. Thaiphoon зберігає результат у власному форматі .thp (1029 байтів, дані закодовані) — для порівняння байт у байт він не годиться. Але поруч із програмою вона кладе файл резервної копії, де ті самі 1024 байти лежать у сирому вигляді (після 8 службових байтів). Саме цей сирий масив ми й порівнювали.
2. Програматор CH341A
Звичайний програматор мікросхем EEPROM пам’яті DDR5 не читає. Хаб DDR5 — не проста EEPROM на кшталт 24C02: перед читанням його треба перевести командою в потрібний режим і перемикати сторінки регістром MR11, а сама планка має бути живлена через свій контролер живлення (PMIC). Програма AsProgrammer цього не робить. Ми перебрали адреси 0x50–0x53, 0x18, 0x36, 0x37 — без відповіді на обох планках. Висновок: справа в інструменті, а не в планках.
3. ESP32 із власною прошивкою — спрацювало
Плата ESP32 вміє все потрібне: поговорити з хабом по I²C, перемкнути сторінки й видати дамп у монітор порту. Послідовність ініціалізації ми взяли з відкритого проєкту SPD-Reader-Writer (автор 1a2m3): перевірити відповідь хаба (0x50) і PMIC (0x48), записати MR11 = 0 (сторінка 0, звичайний режим I²C), прочитати тип пристрою (MR0 = 0x51, MR1 = 0x18 — хаб із датчиком температури), далі — 8 сторінок по 128 байтів.
Наші дампи
| Файл | Що це | Розмір |
|---|---|---|
| ddr5_module1_not_working_esp32.bin | планка 1 (неробоча), ESP32 — сирі 1024 байти | 1024 B |
| ddr5_module2_working_esp32.bin | планка 2 (робоча), ESP32 — сирі 1024 байти | 1024 B |
| ddr5_module1_not_working_esp32_serial.txt | планка 1: вивід Serial Monitor як є | 3607 B |
| ddr5_module2_working_esp32_serial.txt | планка 2: вивід Serial Monitor як є | 3607 B |
| ddr5_windows_thaiphoon_raw.bin | Windows, Thaiphoon Burner — сирий масив із його резервної копії | 1024 B |
| ddr5_windows_thaiphoon.thp | Windows, Thaiphoon Burner — файл у власному форматі програми | 1029 B |
| esp32_ddr5_spd_reader.ino | прошивка ESP32 (Arduino) | 6776 B |
Дампи ESP32 обох планок однакові до байта. Контрольна сума базового блоку (CRC-16, байти 0–509) в обох обчислюється в A7AB — рівно те, що записано в самому SPD. Тобто опис неробочої планки цілий: причина поломки не в SPD, і перезаписувати його марно.
| Адреса | Значення | Що це |
|---|---|---|
| 0x002 | 12 | тип памʼяті: DDR5 |
| 0x003 | 02 | тип модуля: UDIMM |
| 0x1FE–0x1FF | AB A7 | контрольна сума базового блоку (A7AB) |
| 0x200–0x201 | 02 9E | виробник модуля: Corsair |
| 0x205–0x208 | 00 00 00 00 | серійний номер модуля: у наших планок не записаний |
| 0x209–0x21A | CMH32GX5M2E6000C36 | номер моделі (ASCII) |
| 0x228–0x229 | 80 2C | виробник чіпів: Micron |
| 0x280 | 0C … | початок профілю XMP 3.0 |
Перш ніж викладати свій дамп, гляньте байти 0x205–0x208: це серійний номер модуля. У наших планок там нулі, тому дампи викладено як є. Якщо у вашій планці там не нулі — перед публікацією замініть ці чотири байти нулями (контрольна сума 0x1FE лічить лише байти 0–509, її це не зачіпає) або не публікуйте дамп зовсім.
Чому дамп із Windows відрізняється від дампу ESP32
Відрізняються 436 байтів із 1024. Але це не «інший вміст планки», а неповне читання. Докази:
- Кожна з 8 сторінок файлу з Windows — це перша сторінка SPD: збіг у 1021 байті з 1024 (три розбіжні байти — в одній копії, схоже на збій читання по спільній шині).
- Контрольна сума в такому файлі не сходиться: обчислено
9778, а на місці, де вона має бути, — нулі. - За адресою 0x200, де лежить код виробника, у файлі з Windows стоїть
30 10— це перші два байти SPD. Тому Thaiphoon і назвав файл «Unknown (JEDEC ID 3010h)»: він прочитав «виробника» з повтору першої сторінки.
Причину описує сам Thaiphoon у своїй довідці: на платформах Intel, якщо в BIOS увімкнено захист «SPD Write Disable», програма не має доступу до всього масиву в 1024 байти, і розшифровка може виглядати зіпсованою. Найімовірніше, захист не дає програмі змінити регістр сторінки хаба, тож на будь-який запит вона отримує першу сторінку — саме так і виглядає наш файл. ESP32 працює з планкою напряму, без BIOS, і сам перемикає сторінки — тому читає все.
Як прочитати повністю в Windows. У BIOS плат на Intel цей пункт часто називається «SPD Write Disable»: на час читання поставити його в FALSE (Disabled), прочитати, повернути назад. Пункт вимикає захист від запису в SPD — залишати його вимкненим не варто.
Схема підключення ESP32
| ESP32 / джерело | Контакт планки | Сигнал | Навіщо |
|---|---|---|---|
| GPIO21 (SDA) | 5 | HSDA | дані I²C + підтяжка до 1.8 В планки |
| GPIO22 (SCL) | 4 | HSCL | такт I²C + підтяжка до 1.8 В планки |
| GND | 150 | Vss | спільна маса: ESP32, блок 5 В, планка |
| — (на масу) | 148 | HSA | адреса 0 і сервісний режим хаба |
| 3V3 | 151 | PWR_EN | дозвіл роботи PMIC |
| блок 5 В «+» | 3 | VIN_BULK | живлення PMIC планки |
| R1, R2 4.7–5.1 кОм | — | 1.8 V | від SDA і SCL до конденсатора 1.8 В біля SPD-хаба |
Що важливо:
- Живлення планки — через її PMIC, як у компʼютері: 5 В на вхід живлення, 3.3 В на сигнал дозволу PWR_EN. PMIC сам зробить усі внутрішні напруги, зокрема 1.8 В для хаба.
- Підтяжки — до 1.8 В самої планки: найзручніше взяти цю напругу з конденсатора біля мікросхеми SPD-хаба (він зʼявляється, щойно PMIC стартував; перевірте мультиметром). Окреме джерело 1.8 В не потрібне.
- Контакт 148 (HSA) — на масу: це адреса 0 і сервісний режим хаба.
- Контакт 3: ми подавали 5 В саме на нього (так описано в документації Bus Pirate), і PMIC стартував. У даташиті UniIC живлення позначено на контактах 1, 145, 146, а 3 — як резерв. Тому перед подачею 5 В продзвоніть на своїй планці, що контакт 3 зʼєднаний із 145/146.
- Внутрішні підтяжки ESP32: бібліотека Wire вмикає власні слабкі підтяжки (десятки кОм) до 3.3 В. З нашими 4.7–5.1 кОм до 1.8 В лінія у спокої — розрахунково трохи вище за 1.8 В (≈1.9 В). У нас так працювало; хто хоче точно 1.8 В — вимикає внутрішні підтяжки після
Wire.begin(). - Як дістатися до контактів гребінки: або тонкі дроти, обережно прикріплені до потрібних позолочених контактів, або слот DDR5 від непотрібної плати як «гніздо». Головне — не замкнути сусідні контакти: крок гребінки менше міліметра.
Ноутбучна памʼять і захист SPD від запису
Ще кілька фактів, які знадобляться, — за документацією Bus Pirate про DDR5 (ми їх не перевіряли на своєму обладнанні).
| Сигнал | UDIMM (ПК) | SO-DIMM (ноутбук) |
|---|---|---|
| HSDA (дані I²C) | 5 | 6 |
| HSCL (такт I²C) | 4 | 4 |
| PWR_EN (дозвіл PMIC, 3.3 В) | 151 | 8 |
| HSA (адреса / сервісний режим) | 148 | 2 |
| PWR_GOOD (живлення в нормі, вихід) | 147 | 7 |
| BULK_VIN (5 В) | 3 | 1 |
| маса | 150 | 9 |
- Захист від запису. 1024 байти SPD поділено на 16 блоків по 64 байти; які з них захищені, задають біти регістрів хаба MR12 і MR13. Поставити захист можна будь-коли, а зняти — лише в сервісному режимі (HSA на масу) — тобто саме в тому підключенні, яким ми читаємо. Наша прошивка лише читає, але будь-який запис у SPD може зробити планку нездатною стартувати: спершу збережіть дамп.
- Стан хаба — регістр MR48: окремі біти показують «іде запис» і «сервісний режим».
- У хабі є датчик температури (регістри 49–50) — ним можна дивитись, як гріється планка.
Прошивка ESP32
Файл esp32_ddr5_spd_reader.ino — скетч для Arduino IDE (плата «ESP32 Dev Module»). Після завантаження відкрийте Serial Monitor на 115200 бод і вводьте команди:
| Команда | Що робить |
|---|---|
| s | шукає пристрої на шині I²C (наша планка відповідала на 0x18, 0x48 — PMIC — і 0x50 — хаб SPD) |
| d | перевіряє хаб: має бути MR0 = 0x51, MR1 = 0x18 (хаб із датчиком температури) |
| p | перевіряє PMIC за адресою 0x48 |
| r | читає всі 1024 байти й друкує дамп; наприкінці — «Read errors: 0 / 1024 bytes» |
| h | підказка |
Перетворити надрукований дамп на файл .bin (збережіть вивід монітора в dump.txt):
# Linux / Git Bash
grep -E '^[0-9A-F]{3}:' dump.txt | cut -d: -f2 | tr -d ' \r\n' | xxd -r -p > dump.bin
# Python (будь-яка система)
python -c "import re,sys; d=bytes(int(b,16) for l in open(sys.argv[1]) if re.match(r'^[0-9A-F]{3}:',l) for b in l.split(':')[1].split()); open(sys.argv[2],'wb').write(d)" dump.txt dump.bin
Розмір має вийти рівно 1024 байти. Два дампи порівнюються командою cmp a.bin b.bin (порожній вивід — файли однакові) або fc /b a.bin b.bin у Windows.
Журнал змін статті
| Дата | Що змінилось |
|---|---|
| 30.10.2026 | Контакти SO-DIMM, захист SPD від запису, регістри стану й температури (за документацією Bus Pirate). Перша версія: три способи читання, дампи, пояснення розбіжності з Windows, схема й прошивка ESP32. |