beeugene
12 просмотров0 комментариев0

Geekworm X1002 на Repka Pi 5: адаптер Gen2, а тянет Gen3. Проверяем стабильность

TL;DR. Подключил NVMe накопитель к Repka Pi 5 через PCIe-адаптер Geekworm X1002. По документации Geekworm этот адаптер поддерживает только PCIe Gen 2.0, но на практике он стабильно держит Gen3 ×1 без единой ошибки линка — и выдаёт те же ~720 МБ/с, что и более дорогой кейс с NVMe. Под катом — как проверить, на какой скорости реально поднялся линк, и прогнать стресс-тест, чтобы убедиться, что Gen3 здесь не «на грани», а уверенно.

Что вообще собирал и зачем #

Хочу быстрое хранилище на Repka Pi 5. До этого гнал NVMe через кейс Argon NEO 5 (с отдельной M.2-HAT-платой), который я разбирал в отдельном посте — всё работало на Gen3 ×1. Теперь решил попробовать Geekworm X1002 — отдельную PCIe-платку под один M.2 NVMe, тоже через родной PCIe-разъём платы. Вопрос простой: заведётся ли, и на какой скорости?

Компонент Модель
Платформа Repka Pi 5 (Rockchip RK3588)
ОС Repka OS (Ubuntu 25.10), ядро 6.1.115.1-repka-pi5
Адаптер Geekworm X1002 (PCIe Peripheral Board, M.2 NVMe)
SSD CUSU CV3500Q 1TB, PCIe 3.0 ×4, контроллер Maxio, QLC

💡 Что такое X1002. Это плата-переходник от Geekworm: на одном конце — разъём под M.2 NVMe-диск (размеры 2230/2242/2260/2280), на другом — шлейф FFC в родной PCIe-разъём Raspberry Pi 5 / Repka Pi 5. По сути, то же самое, что M.2-HAT, только отдельной платкой. Заявлена строго под NVMe (SATA и AHCI не поддерживает).

Сборка: шлейф, защёлка и пины питания (грабли) #

Прежде чем радоваться цифрам, пара слов о том, как это физически собирать — тут есть два неочевидных места, на которые я лично наступил.

Шлейф FFC и защёлка разъёма #

как выглядит защелка

PCIe-разъём на Repka Pi 5 — это ZIF-коннектор с откидной защёлкой (flip-lock): чтобы вставить шлейф, защёлку надо сначала аккуратно приподнять, вставить ленту до упора, потом опустить обратно. У X1002 защёлка немного другой конструкции, чем у привычных M.2-HAT, и именно тут кроется грабель:

⚠️ Не открывайте защёлку с силой и не тяните за шлейф, не отпустив замок. Пластиковый язычок защёлки хрупкий и при избыточном усилии ломается — а без него шлейф не прижимается к контактам, линк не поднимается, и вы потом долго ищете причину в софте, как я когда-то. Открывать — плавно, ногтём или пластиковой лопаткой, без рычага.

Шлейф вставляется контактами в нужную сторону (у FFC медные «пятаки» только с одной стороны). Этому меня уже научила история с перевёрнутым кабелем на другом адаптере — повторять не хочется. Вставил до упора, опустил защёлку, проверил, что лента сидит плотно и не выпадает при лёгком потягивании.

как выглядит шлейф и как его вставлять

Pogo pins — дополнительное питание через GPIO #

Pogo pins

А вот это — самая важная часть всей сборки, и именно её легко пропустить. У X1002 есть pogo pins: подпружиненные штырьковые контакты на углу платы, которые при установке прижимаются прямо к штырькам GPIO платы и заводят на адаптер дополнительное питание 5 В. Ничего паять не надо — плата просто встаёт так, что пого-пины упираются в нужные GPIO.

Зачем они нужны. По спецификации через сам шлейф FFC можно снять максимум 5 В / 1 А = 5 Вт, а на накопитель приходит 3,3 В (до 3,5 А). Для нетребовательного SSD в простое хватает. Но NVMe под нагрузкой (особенно при пиках записи и сбросе кэша на QLC-памяти) может кратковременно потреблять больше — и тогда по тонкому шлейфу садится напряжение. Симптом я наблюдал лично на Raspberry Pi: без pogo pins, на одном только FFC, диск периодически отваливался — пропадал из системы, в логах появлялись ошибки контроллера. Стоило прижать pogo pins к GPIO — отваливания прекратились.

💡 Почему так. Когда по шлейфу не хватает тока, на SSD проваливается напряжение ниже допустимого, и его контроллер уходит в аварийный сброс или отключается. Это та же физика, что и просадки напряжения на слабом БП — только вместо общего питания страдает линия 3,3 В на накопитель. Pogo pins дают второй, независимый путь подвода 5 В, разгружая тонкий FFC-шлейф.

⚠️ Поэтому при сборке следите, чтобы pogo pins действительно упирались в GPIO, а не висели в воздухе и не замыкали соседние контакты. Плата должна стоять ровно, на штатных стойках, чтобы прижим был плотным и стабильным. «Диск отваливается под нагрузкой» — почти всегда симптом именно плохого пита, а не софта.

Pogo pins и как они прижимаются

Подключил. Работает? #

Собрал по этой инструкции (шлейф до упора в правильной ориентации, pogo pins прижаты к GPIO), загрузился. Первым делом — видит ли система диск:

lsblk -o NAME,SIZE,MODEL,TRAN,MOUNTPOINT /dev/nvme0n1
NAME          SIZE MODEL            TRAN   MOUNTPOINT
nvme0n1     953,9G CUSU CV3500Q 1TB nvme   /mnt/nvme
└─nvme0n1p1 953,9G                  nvme   /mnt/nvme

Диск определился, раздел на месте, примонтирован. Пока всё хорошо. Но «определился» — это полдела. Главное — на какой скорости поднялся PCIe-линк.

Лирическое отступление: Gen2 и Gen3 — в чём вообще разница #

Прежде чем смотреть цифры, проговорим, что значит «Gen2» и «Gen3» применительно к PCIe.

PCIe (PCI Express) — это высокоскоростная шина, по которой быстрые устройства общаются с процессором. Она делится на поколения (generations), и каждое следующее быстрее предыдущего:

Поколение Пропускная способность на 1 линию Год
Gen 2.0 5.0 ГТ/с ≈ ~500 МБ/с реальных 2007
Gen 3.0 8.0 ГТ/с ≈ ~985 МБ/с реальных 2010

Ключевое слово — «на 1 линию». Repka Pi 5 выводит на свой PCIe-разъём одну линию (×1), поэтому потолок для нас — это пропускная способность одной линии. На Gen2 это ~500 МБ/с, на Gen3 ~985 МБ/с. Разница — примерно вдвое. Для NVMe это разница между «быстро» и «очень быстро».

💡 Как линк выбирает поколение. PCIe-линк поднимается на младшем из поддерживаемых speeds: если хост умеет Gen3, диск умеет Gen3, но плата-переходник между ними рассчитана только на Gen2 — линк встанет на Gen2. То есть одно «узкое» звено режет всю цепочку. Именно поэтому спецификация X1002 «Gen2-only» имела значение: если она честная, мой NVMe должен был бы работать на ~500 МБ/с, а не на ~985.

Главный вопрос: на какой скорости реально поднялся линк? #

Скорость линка ядро честно пишет в sysfs. Смотрим:

cat /sys/class/nvme/nvme0/device/current_link_speed   # 8.0 GT/s PCIe
cat /sys/class/nvme/nvme0/device/current_link_width   # 1
cat /sys/class/nvme/nvme0/device/max_link_speed       # 8.0 GT/s PCIe

И вот тут — сюрприз. 8.0 GT/s — это Gen3, а не Gen2 (Gen2 было бы 5.0 GT/s). То есть линк встал на Gen3 ×1, хотя спецификация X1002 это прямо запрещает.

Как ядро подняло линк — смотрим в логе:

dmesg | grep -iE "rk-pcie|gen\."
rk-pcie fe150000.pcie: PCIe Link up, LTSSM is 0x230011
rk-pcie fe150000.pcie: PCIe Gen.3 x1 link up

Чистый подъём на Gen3, без единой попытки деградировать. Спойлер: это не значит, что всё хорошо — это значит, что нужно копать дальше. Линк-то поднялся, но «Gen3 на Gen2-плате» — подозрительно. Может, он держится на грани и сыплет ошибками, которые компенсируются повторами? Это надо проверять, а не радоваться цифре.

Проверка стабильности: ошибки линка и стресс-тест #

Раз адаптер работает выше спецификации, главный вопрос — не ценой ли ошибок это достигнуто. Проверяю по двум направлениям: счётчики ошибок PCIe и поведение под нагрузкой.

Шаг 1. Ошибки PCIe AER #

PCIe умеет сам сообщать об ошибках через механизм AER (Advanced Error Reporting). Делятся они на corrected (исправимые — линк сам перестраховался, переотправил пакет) и uncorrectable (неисправимые — данные потеряны). Много corrected — уже тревожно, любые uncorrectable — плохо.

Сначала — нет ли ошибок в логе ядра:

dmesg | grep -iE "aer|pcie.*error|corrected|uncorrectable"

У меня пусто — ни одной ошибки с момента загрузки. Хорошо, но мало: AER-события попадают в dmesg только если они есть, а счётчики накопленных ошибок это ядро тут не экспортирует. Поэтому переходим к более надёжной проверке — реальной нагрузкой.

💡 Почему одной проверки ошибок мало. Можно «прочитать dmesg, увидеть ноль ошибок и успокоиться» — но если диск только что загрузился и на нём ничего не писали, ошибкам было просто неоткуда взяться. Стабильность PCIe проверяют именно под нагрузкой: продолжительной записью и чтением. Если линк «на грани», под нагрузкой он начнёт сыпать corrected-ошибками, ретрейниться (пересогласовывать скорость) или вовсе падать до Gen2.

Шаг 2. Стресс-тест: 3 цикла записи по 1 ГБ #

Пишу гигабайт прямыми операциями ввода-вывода (oflag=direct, в обход кэша — так честнее, видим реальную скорость диска, а не RAM):

for i in 1 2 3; do
  dd if=/dev/zero of=/mnt/nvme/.stress bs=1M count=1024 oflag=direct
done

Результаты трёх циклов:

Цикл Время записи 1 ГБ Скорость
1 ~1,97 с ~520 МБ/с
2 ~1,79 с ~570 МБ/с
3 ~1,93 с ~520 МБ/с

Стабильно, без провалов. Чтение того же файла:

dd if=/mnt/nvme/.stress of=/dev/null bs=1M
# ~1,33 с на 1 ГБ ≈ 770 МБ/с

И классический замер:

hdparm -t /dev/nvme0n1
# Timing buffered disk reads: 2152 MB in 3.00 seconds = 717 MB/sec

Шаг 3. Линк не упал после нагрузки #

Самая важная проверка — повторно смотрю скорость линка и логи после стресс-теста:

cat /sys/class/nvme/nvme0/device/current_link_speed   # 8.0 GT/s PCIe — всё ещё Gen3
dmesg | grep -iE "aer|pcie.*error|link.*(down|fail)|ltssm" | tail

Линк остался на Gen3 ×1, новых сообщений об ошибках или пересогласовании (LTSSM-ретрейнах) в логе не появилось. Файловая система отвечает на запись после нагрузки — данные не повредились.

Шаг 4. Не только dd — реальная нагрузка #

dd — хороший синтетический тест, но он не ответит на главный вопрос: выдержит ли адаптер длительную хаотичную нагрузку, когда на диск одновременно пишут база данных, объектное хранилище и очередь сообщений? Чтобы проверить, я поднял на Repka Pi 5 полноценный Docker-стек из 13 контейнеров:

  • PostgreSQL — постоянные WAL-записи, индексы, транзакции
  • MinIO — объектное хранилище, запись/чтение изображений (JPG 5–7 МБ каждый)
  • Apache Kafka — очередь сообщений, постоянная запись сегментов
  • ML-inference — 4 параллельных классификатора, читают модели из MinIO и пишут результаты

Docker data-root — прямо на NVMe через X1002. Все тома (postgres_data, minio_data, kafka_data) — на NVMe. Это профильная нагрузка, ради которой NVMe и нужен: смешанные случайные чтение/запись, много мелких операций + крупные файлы, 24/7 без перерыва.

Результат за 30+ минут непрерывной работы:

dmesg | grep -c "controller is down"   # 0 — ни одного сбоя
cat /sys/class/nvme/nvme0/device/current_link_speed   # 8.0 GT/s — Gen3, не деградировал

Ноль падений контроллера, ноль ретрейнов линка, ноль ошибок AER. В то время как на RPi5 тот же стек падал за полторы минуты (об этом ниже).

💡 Почему это важно. Синтетический dd пишет один большой файл последовательно — это самая лёгкая нагрузка для контроллера. Реальная работа базы данных и хранилища — это тысячи мелких случайных операций в секунду, и именно они сильнее всего нагружают PCIe-интерфейс. Если адаптер держит такую нагрузку — он держит вообще всё.

Сравнение с предыдущим сетапом #

До X1002 гнал тот же диск через кейс Argon NEO 5. Сравнение:

Параметр Argon NEO 5 Geekworm X1002
Заявленный максимум Gen3 (не ограничено) Gen2 (по спеке)
Реальная скорость линка Gen3 ×1 Gen3 ×1 (вопреки спеке)
Чтение ~757 МБ/с ~717–770 МБ/с
Ошибки линка нет нет
Форм-фактор Кейс с HAT-платой Отдельная платка

По факту — паритет. X1002 не уступает, хотя формально «хуже» по спецификации. Разница в скорости (~40 МБ/с) — в пределах погрешности и теплового состояния диска.

А что на Raspberry Pi 5? (спойлер: не работает) #

Пока собирался с Repka Pi 5, параллельно гонял тот же CUSU CV3500Q на Raspberry Pi 5 — через её родной PCIe-разъём (M.2 HAT, без X1002). И вот там всё пошло совсем по-другому.

Через ~100 секунд после загрузки, под I/O-нагрузкой Docker, ядро начинало сыпать:

nvme nvme0: controller is down; will reset: CSTS=0xffffffff
nvme nvme0: Does your device have a faulty power saving mode enabled?
nvme nvme0: Try "nvme_core.default_ps_max_latency_us=0 pcie_aspm=off pcie_port_pm=off"

Дальше — ext4 переводил файловую систему в read-only (Remounting filesystem read-only), journal падал, Docker зависал. Pi переставала отвечать. Перезагрузка — и снова те же ~100 секунд до падения.

Я перепробовал всё, что рекомендует сообщество (Raspberry Pi Forums, тред t=395256; Kuron's blog):

Фикс Результат
Force PCIe Gen 2 (pciex1_gen=2) ❌ упал через 105 сек
Disable ASPM (pcie_aspm=off) ❌ упал
Disable NVMe APST (default_ps_max_latency_us=0) ❌ упал
Force PCIe Gen 1 (2.5 GT/s, самая медленная) ⚠️ проработал чуть дольше, но всё равно упал
Все четыре вместе ❌ упал

Диск при этом абсолютно здоров — SMART: critical_warning:0, media_errors:0, percentage_used:0%. Проблема не в SSD, а в PCIe-контроллере Raspberry Pi 5 — он фундаментально нестабилен с некоторыми накопителями (особенно бюджетными: CUSU, некоторые партии Samsung). Это не баг конкретного экземпляра, а класс проблем — на форумах сотни таких отчётов.

💡 Вывод. Тот же диск, который каждые 100 секунд падал на RPi5, на Repka Pi 5 + X1002 работает часами без единого сбоя. Разница — реализация PCIe-контроллера: RK3588 (Repka) стабильнее, чем Broadcom BCM2712 (RPi5), по крайней мере с бюджетными NVMe. Если планируете держать данные на NVMe — Repka Pi 5 надёжнее.

Это не значит, что RPi5 вообще нельзя использовать — с SD-картой она работает штатно (просто медленнее). Но NVMe на RPi5 — это лотерея: повезёт с конкретным экземпляром SSD или нет. С X1002 на Repka — не лотерея, а стабильный результат.

Бонус: корпус P580 #

Всё это хозяйство у меня живёт в корпусе P580 — это специальный корпус от Geekworm, спроектированный как раз под связку «плата + X1002» (адаптер встаёт внутрь на штатное место, всё прячется). Под Repka Pi 5 он почти полностью совместим: посадочные, стойки, вырезы под GPIO и pogo pins — совпадают.

Единственный нюанс, на который стоит обратить внимание при сборке, — вырезы под видеовыходы. Корпус проектировался под Raspberry Pi 5, а у неё и у Repka Pi 5 разъёмы отличаются: в P580 вырезы сделаны под HDMI, тогда как нужно под micro-HDMI. Функционально это ни на что не влияет — просто отверстия не совпадают по форме «один в один», при необходимости подгоняются надфилем или не используются (если монитор подключён иначе).

Подробный разбор корпусов под Repka Pi 5 — что подходит из «малинковой» экосистемы, что нужно подпиливать, а что встаёт идеально — я соберу в отдельном посте. Здесь упомянул только как факт: P580 с X1002 внутри — рабочий и аккуратный вариант.

Итоги #

Параметр Значение
Адаптер Geekworm X1002
Статус ✅ работает
Линк по спецификации Gen2-only
Линк реально Gen3 ×1 (8.0 GT/s) — выше спецификации
Запись (direct I/O) ~520–570 МБ/с
Чтение ~720–770 МБ/с
Ошибки AER 0
Ретрейны / падения линка 0
Износ (SMART) 0%, ошибок носителя нет
Реальная нагрузка (Docker, 13 контейнеров) ✅ 30+ мин, 0 сбоев контроллера

Geekworm X1002 подключился, определился и стабильно держит Gen3 ×1 под нагрузкой, хотя заявлен как Gen2-only. Выдаёт ~720 МБ/с чтения — столько же, сколько более дорогой кейс с отдельной HAT-платой. Ошибок линка и пересогласований за весь стресс-тест не возникло, то есть Gen3 тут не «на грани», а уверенно.

Пять уроков, которые я вынес #

  1. Спецификация — не приговор. «Gen2-only» у X1002, видимо, перестраховка производителя (длинный шлейф, трассировка). На практике Gen3 встаёт чисто. Но это не повод доверять слепо — проверять надо.
  2. «Линк поднялся» ≠ «всё хорошо». На скорости линка легко успокоиться и пропустить, что он держится ценой потока corrected-ошибок. Стабильность PCIe проверяют под нагрузкой: записью, чтением и контролем ошибок после.
  3. Сравнивайте с альтернативой. Когда есть второй сетап (тут — Argon NEO 5), прогон одного и того же диска на обоих сразу даёт честную картину, кто кого. X1002 оказался не хуже — а значит, более дешёвая платка имеет право на жизнь.
  4. «Диск отваливается» — сначала питание, потом софт. Периодическое пропадание NVMe под нагрузкой почти всегда означает, что по FFC-шлейфу не хватает тока, а не баг драйвера. Проверяйте pogo pins (плотный прижим к GPIO) и БП — и только потом лезьте в логи и конфиги.
  5. Стабильный адаптер не спасёт от выдёргивания шнура. На том же стенде накопилось 23 unsafe shutdown в SMART — от выдёргиваний питания без poweroff. Каждый незавершённый shutdown повреждает journal ext4 и может перевести файловую систему в read-only. Для устройства «в чужие руки» обязателен UPS (хотя бы power bank с passthrough) + commit=1 в fstab. Стабильность X1002 — это половина дела; питание без рывков — вторая половина.

Шпаргалка команд #

# Диск виден?
lsblk
ls /dev/nvme*

# Скорость и ширина линка (Gen3 = 8.0 GT/s, Gen2 = 5.0 GT/s)
cat /sys/class/nvme/nvme0/device/current_link_speed
cat /sys/class/nvme/nvme0/device/current_link_width

# Как ядро подняло линк
dmesg | grep -iE "rk-pcie|gen\."

# Ошибки PCIe AER
dmesg | grep -iE "aer|corrected|uncorrectable"

# Стресс-тест записи (1 ГБ, прямой I/O — в обход кэша)
dd if=/dev/zero of=/mnt/nvme/.stress bs=1M count=1024 oflag=direct

# Замер скорости чтения
sudo hdparm -t /dev/nvme0n1

# SMART и здоровье
sudo nvme smart-log /dev/nvme0

# Следить за отваливанием диска под нагрузкой в реальном времени
# (запустите в одном окне, стресс-тест — в другом)
dmesg -w | grep -iE "nvme|pcie|aer|link|reset"

Ссылки #


0

Комментарии (0)

Для участия в обсуждении Вы должны быть авторизованным пользователем

Еще посты по теме

Наиболее интересные по мнению читателей



Темы

Навигация

ВойтиРегистрация