System designTroubleshooting

CSI camera short frame errors: match the mode to the sensor output

A CSI camera short frame error plus CRC flags means the declared mode does not match the sensor's bytes. Read the trace, size the lanes, fix the mode table.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01What the trace is telling you
  2. 02The four declarations that must match the link
  3. 03Likely causes in order of probability
  4. 04Test each cause before you edit
  5. 05Worked example: a 2592 × 1944 RAW12 sensor at 30 fps on two lanes
  6. 06Fix the mode table, then the link
  7. 07When the usual fixes do nothing
  8. 08Bring-up checklist for the next sensor
  9. 09Questions

A camera that probes cleanly but fails at first stream almost always has one root cause: the mode your driver declares does not describe the bytes the sensor actually puts on the link. This guide is for engineers bringing up a raw MIPI CSI-2 sensor, direct or through a serializer pair, on an embedded capture chain. You will read the two trace tags that define the failure, check every declared value against the sensor's real output, size the lane rate the payload demands, and fix the mode table in one pass.

What the trace is telling you

Two tags define this failure, and they arrive together. CHANSEL_SHORT_FRAME in the capture engine's event log means the receiver counted a frame complete before the declared number of lines had arrived: data stopped early, the boundaries sat in the wrong place, or the frame never fit its period. The companion interrupt is tagged rtcpu_nvcsi_intr with type STREAM_VC and status 0x00000004, which the firmware logs for a payload CRC error: bytes arrived, but not in the shape the packet format promised.

tag:CHANSEL_SHORT_FRAME channel:0x04 frame:0 data:0x0000200001000000
type:STREAM_VC phy:0 cil:0 st:2 vc:0 status:0x00000004

The user-space symptom sits next to them. v4l2-ctl --list-formats-ext prints the format code with no sizes at all — a bare 'BG10' entry under VIDIOC_ENUM_FMT and nothing else — while v4l2-ctl --all still shows the full driver information. Sizes come from the driver's mode table, and nothing has connected that table to the size enumeration. The same table is what the receiver counts frames against, so an unpopulated table and a corrupted stream often share one root.

If the video node itself never appears, that is the earlier failure in this chain. Start with sensor probes but no video node: fix the devicetree chain and return here once streaming starts.

Every mode node — mode0 and its siblings — describes one sensor output format. Four groups of values must equal what the sensor actually sends:

  • Bit depth. dynamic_pixel_bit_depth and csi_pixel_bit_depth carry the sensor's true output — 12 for the RAW12 RGB-IR sensor in this case, not the 10-bit Bayer code the driver printed first.
  • Frame geometry. Active width and height, total line length and any embedded data rows must match the sensor's frame start and end lines.
  • Lanes and channel. num_lanes must equal the data lanes the sensor or its serializer physically drives; vc_id must match the virtual channel on the wire.
  • Physical timing. mclk_khz, phy_mode, discontinuous_clk and cil_settletime describe the wire itself and must match the sensor's or serializer's configuration.

A mode table is not a control panel. Nothing in it shrinks the sensor's output; the sensor keeps sending what it was configured to send. Declare a value the wire does not carry and the receiver counts lines and bytes against a fiction — that is the mechanism behind both tags.

Likely causes in order of probability

  1. Declared bit depth below the true output. A 12-bit stream parsed as 10-bit makes every line 20% longer in bytes than declared (12 ÷ 10 = 1.2). Packet headers land outside the parsing window: CRC flags first, short frames right behind. For how bit depth and pixel format drift apart, see why 10-bit sensors ship 8-bit images.
  2. Declared geometry smaller than the real frame. This is why a 100 × 90 test window changes nothing: the sensor still sends full frames and the receiver still closes its window with bytes in flight.
  3. Payload the lanes cannot carry. Below the payload's per-lane demand, frames cannot complete inside the frame period. The next section puts numbers on this.
  4. Mode table never enumerated. The format lists without sizes because the driver's size enumeration was never wired to the mode nodes.
  5. Link configuration or integrity. Serializer lane rate too low, cil_settletime wrong for the link, discontinuous_clk disagreeing with the sensor, or a long or stubbed flex.

Test each cause before you edit

  • Sizes and formats. Run v4l2-ctl --list-formats-ext -d /dev/video2 (substitute your capture node). A bare format with no sizes is cause 4; discrete sizes with 30.000 fps intervals mean the table enumerates.
  • Driver picture. v4l2-ctl --all -d /dev/video2 prints the driver, card and current format even when the size list is empty. Compare every value there with the sensor data sheet.
  • Trace pattern. Stream once and read the runtime firmware trace. CRC-heavy output points at causes 1 and 5; short-frame-only output points at causes 2 and 3.
  • Bandwidth probe. Raise the four capture clocks — vi, isp, nvcsi and emc — to their maxima through the debugfs clock tree:
echo 1 > /sys/kernel/debug/bpmp/debug/clk/vi/mrq_rate_locked
cat /sys/kernel/debug/bpmp/debug/clk/vi/max_rate | tee /sys/kernel/debug/bpmp/debug/clk/vi/rate

Repeat for isp, nvcsi and emc, stream once, and re-read the trace. Errors that thin out at maximum clocks mean bandwidth (cause 3); unchanged errors mean the format declarations (causes 1 and 2) are still wrong.

Worked example: a 2592 × 1944 RAW12 sensor at 30 fps on two lanes

Inputs, all from the case: 2592 × 1944 active pixels (the sensor's real frame — the 5M in its name), RAW12 output at 12 bits per pixel, a 30 fps target, and two data lanes (num_lanes = 2).

The rule in words: the payload a stream must move equals pixels per frame times frames per second times bits per pixel; each lane carries an equal share; and because CSI-2 data lanes are clocked on both edges, the clock lane runs at half the per-lane bit rate.

payload (bit/s) = active pixels/frame × fps × bits/pixel per-lane rate (bit/s) = payload ÷ num_lanes clock lane (Hz) = per-lane rate ÷ 2

The arithmetic:

  • 2592 × 1944 = 5,038,848 pixels per frame
  • 5,038,848 px × 30 fps = 151,165,440 px/s ≈ 151.2 Mpx/s
  • 151,165,440 px/s × 12 bit = 1,813,985,280 bit/s ≈ 1.81 Gbit/s of payload, about 227 MB/s
  • 1,813,985,280 bit/s ÷ 2 lanes = 906,992,640 bit/s ≈ 907 Mbit/s per lane — active payload only
  • 907 Mbit/s ÷ 2 ≈ 454 MHz on the clock lane

Add the wire overhead — packet headers, frame start and end short packets, embedded data rows and blanking, typically 10-20% — and each lane needs roughly 1.0-1.1 Gbit/s to deliver this stream inside the 33.3 ms frame period (1 ÷ 30).

Decision: set the lane rate at or above about 1.1 Gbit/s per lane. A link running 800 Mbit/s per lane moves 1.6 Gbit/s across two lanes — 12% short of the 1.81 Gbit/s active payload alone — so every frame overruns its period and ends short, exactly like the trace above. At 1.5 Gbit/s per lane the same stream carries roughly 40% headroom over payload plus overhead. The same arithmetic run from the other direction is in the MIPI CSI-2 frame rate estimation guide.

  1. Set the declared bit depths to the sensor's true output — 12 here — and select the raw format code that matches. An RGB-IR sensor needs its own RGB-IR raw code, not the 10-bit Bayer code the driver printed first. Confirm what actually arrives with Bayer raw stream from an RGB camera: how to know you have it.
  2. Correct the geometry. Active width and height, line length and embedded data rows go to the sensor's real frame, exactly as the data sheet prints them.
  3. Make the driver enumerate every mode so v4l2-ctl --list-formats-ext prints one discrete size and interval per mode. In the corrected case the sizes appeared — 1280 × 960, 1600 × 1300 and 2560 × 1984 at 0.033 s intervals — and the short-frame tags were gone from the very next trace.
  4. Chase the remaining CRC on the link. If correctly sized frames now arrive but STREAM_VC status flags stay, re-check the serializer's lane rate against the worked example, then cil_settletime, discontinuous_clk and the flex. One such bring-up ended at a serializer output register set for the wrong lane configuration. Where the receiver reports no data at all rather than CRC errors, a walk-through of a CSI link that delivers no camera data covers that delivery-path failure.

When the usual fixes do nothing

  • Shrinking the test resolution. A smaller declared window under a full-size output guarantees the mismatch continues. A small mode works only when the sensor is reconfigured to genuinely send fewer pixels.
  • Boosting clocks. This buys bandwidth only. It cannot fix a 10-bit declaration under a 12-bit stream.
  • Changing the format from user space. The receiver's expected format is fixed by the mode table — that is why camera pixel formats refuse to change, and how to set them properly.
  • Rewriting the driver wholesale. The fault is almost never the framework; it is four declared values.

Bring-up checklist for the next sensor

  • Copy frame size, bit depth and lane count from the sensor's data sheet into the mode node before the first stream — the table describes the sensor, never the reverse.
  • Confirm v4l2-ctl --list-formats-ext lists every mode with sizes and intervals before debugging any stream error.
  • Stream once and read the trace before touching resolution or format in user space.
  • Run the payload arithmetic for the largest mode and set the link rate with at least 20% margin over payload plus overhead.
  • Match phy_mode, discontinuous_clk and cil_settletime to the sensor's or serializer's actual configuration, not to a copied example.

When a clean mode table still leaves CRC flags, weigh the remaining work against a camera that needs none of it: board-level cameras with USB3 or GigE output skip link bring-up entirely, and the camera configurator narrows the field by sensor, interface and resolution. More capture-chain debugging sits on the systems topic page, and if a custom sensor must stay on the link, bring the trace and the mode table to our contact page — we read both.

Questions

Why does a smaller test resolution not stop the short frame errors?

The mode table describes the sensor; it does not control it. A 100 x 90 declared window under a sensor still sending full frames guarantees the receiver closes its window while bytes are in flight. A small mode only works when the sensor itself is reconfigured over its register interface to crop or bin to that size, so the wire genuinely carries fewer pixels per frame and the declaration matches the new output.

Short frames are gone but CRC flags remain — what is left to check?

The format declarations are right and the link is not. Work outward from the receiver: first the lane rate against the payload arithmetic, then the settle time and clock mode against the sensor's configuration, then the serializer's output format and lane registers, and finally the flex assembly itself. Swap the flex before suspecting the silicon — a marginal link reproduces CRC errors at temperature that never show at the bench.

Can I declare a 10-bit format for a 12-bit sensor to save memory bandwidth?

No. The link carries the bits the sensor emits, and the receiver's byte and line counters follow the declared depth. Declaring 10 under a 12-bit stream makes each line 20% longer on the wire than the declared length, desynchronises packet parsing, and produces CRC flags and short frames together. Capture in the matching 12-bit format and compress downstream if memory bandwidth is the concern.

What should a correct driver print for v4l2-ctl --list-formats-ext?

One entry per mode, each with discrete sizes and their intervals — for example a mode at 3840 x 2160 with a 0.033 s (30.000 fps) interval, or several sizes all at 30 fps. A bare format code with no Size lines means the driver's size enumeration is not connected to the mode table; fix that before debugging stream errors, because the same table defines the frame the receiver expects.

How do I separate a bandwidth problem from a format problem?

Run the payload arithmetic first: pixels per frame times frame rate times bit depth, divided by lane count. If the per-lane wire rate sits below that number plus 10-20% overhead, the stream cannot fit and the failure is bandwidth, whatever the format. If the rate is comfortably above it, let the trace decide: CRC-heavy output points at bit depth or packet alignment, short-frame-only output points at frame geometry.