System designTroubleshooting

Tiled camera feed: debug the GMSL2 SerDes link step by step

A tiled GMSL2 camera feed is a periodic wrap somewhere in the link. Dump the raw Bayer frame and let its contents decide: SerDes settings or host capture.

LumaSpec Vision10 min read Share on LinkedIn

On this page 9 sections
  1. 01What a tiled frame is telling you
  2. 02Rank the likely causes
  3. 03Capture the raw frame before the ISP
  4. 04Worked example: sizing a 2592 × 1944 RG10 dump
  5. 05Read the dump: the tiles decide the layer
  6. 06Fix the SerDes configuration
  7. 07Verify it and keep it fixed
  8. 08When a different interface is the better answer
  9. 09Questions

A live image that tiles itself into a grid of copies of the scene is one of the strangest faults a GMSL2 camera can produce, and one of the easiest to misdiagnose. The sensor register dumps match, the host trace looks identical, and the frame still arrives as a mosaic — sometimes a different mosaic after each restart. The procedure below is for engineers bringing a CSI-2 camera up over a serializer and deserializer pair on an embedded host. It gives you one decision method: dump the raw Bayer frame below the ISP, weigh and view that single file, and let it name the layer to fix — the SerDes link configuration or the host capture path.

What a tiled frame is telling you

Tiling is structure, not noise. Pixel data is being written into memory at a fixed period that is shorter than one real line. When the period divides the sensor's true line width exactly — a 2592-pixel line wrapped every 648 pixels, for example — the wrap repeats cleanly and you see four tiles across. When it does not, the same fault shows as a diagonal shear or torn bands. The tile edges are the wrap points, so the pattern itself measures the misconfiguration before you open a register map.

Bit errors on the coax look nothing like this: white sparkle, sporadic dropped frames or a blank image, not a stable grid. A grid that changes between restarts adds a second clue. The sensor registers were identical in both states of the case behind this guide, so the sensor was innocent and the wrap geometry was being latched differently at each start — a configuration timing problem, not a broken device.

Rank the likely causes

With the sensor ruled out, four link settings and one host path cover nearly every tiled frame. Work down the list in this order:

  1. CSI lane count mismatch. The serializer re-emits the sensor's CSI-2 stream and the deserializer re-creates it for the host. If the lane counts differ, pixels are de-interleaved in the wrong order and the image breaks into a mosaic.
  2. Line length mismatch. A receiver set for a shorter line than the sensor delivers wraps early, which produces the clean grid or shear described above. Multiply the tile width by the number of tiles across: if the product equals the sensor's active line width, the receiver is wrapping at that tile width.
  3. Lane polarity reversed. A swapped lane pair delivers garbage on one lane — bands or streaks rather than clean tiles. Rule it out before blaming the chip, especially with custom cabling.
  4. Data type or bit depth mismatch. A 10-bit Bayer stream declared as 12-bit, or as YUV422, shifts every byte by a fixed amount and smears the image into columns. The file-size check in the worked example below catches it immediately.
  5. Host capture path. Wrong stride, embedded data lines counted as pixels, or a format negotiation that never matched the stream. Investigate this branch only when the raw dump comes back clean.

Capture the raw frame before the ISP

The decision input is one raw file, captured below every processing layer. Set the format to the sensor's native geometry and Bayer code — 2592 × 1944 as RG10 in this case, not the 1920 × 1080 the tiled preview showed — and write a single frame straight to disk:

v4l2-ctl -d /dev/video0 --set-fmt-video=width=2592,height=1944,pixelformat=RG10 --set-ctrl bypass_mode=0 --stream-mmap --stream-count=1 --stream-to=test.raw

v4l2-ctl selects the capture device, --set-fmt-video requests the native geometry and Bayer code, --set-ctrl bypass_mode=0 takes the standard capture route, and the --stream-mmap --stream-count=1 --stream-to=test.raw combination writes exactly one frame's raw bytes to disk. RG10 is V4L2's code for 10-bit Bayer with an RGGB ordering. Run ls -l on the result and keep the file; every later step reads it.

If your module streams YUV422 rather than raw Bayer, dump it the same way with the four-character code the pipeline actually outputs — the GMSL2 YUV422 capture walkthrough covers that negotiation. What raw output means at each stage of a CSI chain is spelled out in CSI camera with no ISP, and capturing raw Bayer RG10 frames with v4l2-ctl scales the same dump to several cameras.

Worked example: sizing a 2592 × 1944 RG10 dump

The inputs, and where each comes from: width 2592 px and height 1944 px, the sensor's native frame as set in the dump command above; pixel format RG10, the V4L2 10-bit Bayer format that stores each sample in a 16-bit word, that is 2 bytes per pixel. The rule in words: expected file size equals width × height × bytes per pixel. A driver that keeps the MIPI wire packing instead — 4 pixels per 5 bytes — stores 1.25 bytes per pixel.

pixels = 2592 px × 1944 px = 5,038,848 px unpacked size = 5,038,848 px × 2 B/px = 10,077,696 B packed size = 5,038,848 px × 1.25 B/px = 6,298,560 B

The decision: ls -l test.raw must report either 10,077,696 bytes or 6,298,560 bytes. Any other size means the capture path's stride or pixel format does not match the request, and you fix that before interpreting geometry — every row-based observation on a wrongly shaped file is meaningless. A larger file points at added stride padding; a smaller one at a packing or depth mismatch.

Once the size matches and the image looks like the scene, the dump path is proven, and any tiling still in the file is real corruption on the link. Bright pixels sit near 65,472 rather than 1,023, because RG10 stores each 10-bit sample left-aligned in its word (1023 × 64 = 65,472). The same alignment shows at 12-bit depth, where values top out near 65,520 — 12-bit data in a 16-bit V4L2 frame walks through that case.

Read the dump: the tiles decide the layer

What the dump shows Where the wrap lives Fix it at
Size correct, tiling already in the raw frame SerDes CSI configuration Serializer and deserializer settings
Size correct, raw frame clean, processed image tiled Host capture or ISP Capture driver: stride, embedded data lines, format negotiation
Size wrong Capture path format or stride Pixel format and stride settings
Blank or dropped frames, sparkle Link itself, power or polarity Link enable order, cable seating, lane polarity

The first row settles the argument. When the file is correctly shaped and the tiles are already in it, the data was scrambled before it reached memory: only the serializer's CSI input, the link and the deserializer's CSI output sit between sensor and buffer. The sensor's registers matched, and the ISP was never in that path, so a tiled raw dump is a SerDes configuration error. When the raw frame is clean but the processed image still tiles, the link is proven good and the wrap lives in the host: start with camera pipeline format negotiation, then the capture driver's line handling — padded line widths, which green frames from a CSI camera covers line by line.

Fix the SerDes configuration

Work with one change per iteration, dumping a fresh raw frame after each step:

  1. Match the serializer's CSI input to the sensor: lane count and CSI data type for the Bayer depth you are streaming, 10-bit for an RG10 stream.
  2. Match the deserializer's CSI output to the host: lane mapping and lane count per port. Confirm the mode the chip supports — the MAX9296, for example, only supports a 2x4 lane mode — then confirm num_lanes matches the lane count of each CSI port, and check whether lane polarity is reversed on any pair.
  3. Match line lengths: the receiver's active line length must equal the sensor's active line width, with embedded data lines carried as their own entries rather than folded into the pixel count.
  4. Diff the new dump against the previous one before moving on. A change that shifts the tile pattern is progress even when the image is still wrong; a change that leaves the pattern untouched gets reverted.

Two settings changed at once can alias into a new wrap that looks like improvement. One register group per iteration keeps the evidence readable, and the fresh dump after every step matters more than the register writes themselves.

Verify it and keep it fixed

Three checks close the fault. First, size: ls -l still reports 10,077,696 bytes for this frame. Second, image: point the camera at a checkerboard or any straight-edged target and confirm no tile boundary cuts it — tile edges show fastest on straight lines. Third, cold start: power-cycle camera, serializer, deserializer and host together, and confirm the very first frame is clean, because startup order is where the changing-pattern race hides.

To keep it fixed, apply the serializer, deserializer and host configuration from one script, in one fixed order, before the first frame is requested — never let the receiver start first and catch up. Record the expected file size next to each sensor mode in your bring-up notes, and keep one known-good dump as a regression reference. The habit transfers to other buses: prove the earliest clean stage before tuning anything downstream, which is exactly how a black-line image corruption on a robot vision camera gets traced and fixed.

When a different interface is the better answer

The decision, case by case. Tiling in a correctly sized raw dump: fix lane count, lane polarity, data type and line length at the serializer and deserializer, one change per dump. Clean raw frame with a tiled processed image: fix stride, embedded data handling or format negotiation in the capture driver. Wrongly sized dump: fix the format before trusting any image check at all.

If you are selecting hardware for a new build rather than rescuing one, ask whether the product truly needs the single-coax, long-distance run that GMSL links exist for. Where the camera sits within a few meters of the host, standard interfaces remove that whole configuration surface. The embedded camera interface comparison lines the interfaces up side by side, and the camera finder filters area scan cameras by interface, resolution and shutter. Standard runs then need ordinary camera data cables.

A 2.5 MP GigE camera with a global shutter such as the MV-CU020-90GC covers most conveyor and presence checks, and the LS-CMR-0166 adds 12 MP over USB3 at 30 fps where the detail is finer:

Area scan camerasHikrobot MV-CU020-90GC 2.5 MP Area Scan Camera, GigE, GMAX4002, ColorMV-CU020-90GC
Sensor format
1/1.7"
Lens mount
C-mount
$309.00View part
Area scan cameras12 MP USB3 area scan camera, IMX226, 1/1.7" rolling shutter, 30 fps, 4000 × 3000 resolution (LS-CMR-0166)LS-CMR-0166
Sensor format
1/1.7"
Interface
USB3
$560.00View part

If a wrap outlives the register table, bring the dump command, the file size and the tile geometry to the contact page and we will read the pattern with you. More capture-path guides sit on the systems topic page.

Questions

Does a bad coax or connector cause a tiled image?

Rarely with this geometry. Bit errors on a serial link surface as dropped frames, blank frames or link error counters, because the link checks its packets and discards corrupt ones rather than mis-writing them into a grid. A stable tile pattern means data is being written consistently at the wrong period — a lane, line-length or data-type wrap. Seat the connectors once, then spend your iterations on the CSI configuration.

Why does the tiling pattern change between restarts?

Because the geometry the receiver latches depends on when its lane count and line length were applied relative to the first packets of the stream. Identical register dumps with different tiles is the signature: the values match, the latched state does not. Apply the serializer and deserializer configuration in one fixed order before streaming starts, then power-cycle the whole chain; a stable misconfiguration tiles the same way every start.

How do I view a raw RG10 dump?

Open the file as raw data with the captured width, height and 16 bits per pixel — 2592 × 1944 for the example frame. Each 16-bit word holds one 10-bit sample left-aligned, so the low six bits read zero. For a quick look, take the top eight bits of every word and export a PNG, or plot the per-row mean: the row where the wrap begins shows up as a step, which locates the wrap point without an image viewer.

Does the same test work for YUV422 GMSL2 modules?

Yes. Capture with the four-character code your pipeline actually outputs and expect two bytes per pixel: a 1920 × 1080 YUV422 frame is 1920 × 1080 × 2 = 4,147,200 bytes. The wrap logic is identical, because a lane or line-length mismatch tiles the image regardless of pixel format; only the viewing step changes, since YUV422 needs no demosaic. The raw dump still decides between SerDes settings and the host capture path.

How many frames do I need to dump?

One frame settles geometry faults: tiling, a wrong width and shifted lanes repeat deterministically, so a single dump proves them. Take several consecutive frames — set --stream-count=10 — when the fault looks intermittent. Torn lines that come and go point at timing or bandwidth rather than a fixed configuration wrap, and comparing file sizes across the set also catches a pixel format that changes between captures.