Zephyr ADC Async Completion: A Zero Signal Result Does Not Certify the Requested Sampling Interval

A zero asynchronous ADC completion result can coexist with a recorded sampling-interval overrun in a particular Zephyr v4.4.0 path. The shared context stores the overrun in one variable, while normal asynchronous completion signals a different value. Correctly reading the signal does not reconstruct status that was never placed in it.

This is a conditional source analysis of the shared ADC context and the nrfx SAADC driver. It is not an executed reproduction, a confirmed upstream issue report, or a claim about every ADC driver. The result requires an overlap to be recorded, otherwise normal completion and no intervening error.

Establish which timer path the build uses

The nrfx driver’s start_read() selects its internal-timer optimization only when exactly one channel is active, options are present, there is no sequence callback, and the nonzero interval is within the implementation’s supported bound. A valid multichannel sequence does not take that branch.

For the worked path, assume a successfully configured multichannel sequence, a nonzero interval, enough buffer space and repeated samplings that normally continue to completion. Its external timer handler calls adc_context_request_next_sampling(). The driver’s conversion-done handling eventually calls adc_context_on_sampling_done().

Those assumptions matter. A trace from the optimized single-channel internal-timer mode does not demonstrate this same timer-request chain. An unsupported channel, buffer failure or conversion-start error is also a different case and must retain its own error handling.

Separate submission, notification and result

adc_read_async() returns the submission result and optionally uses a supplied poll signal for completion. In the inspected context, the asynchronous branch of adc_context_wait_for_completion() returns zero without waiting for the sequence to finish. That return cannot certify the later sampling schedule.

Poll readiness and the signal’s stored result are further observations. A ready event means the completion notification is available; the value carried by that notification comes from the producer’s completion call. This article assumes the caller uses a valid signal correctly, with no stale state or competing reset. Passing NULL provides no completion notification at all.

Keep these fields separate in a diagnostic record. A single variable named “ADC success” can otherwise conceal which boundary was actually checked.

Follow the recorded overlap into normal completion

When a timer request finds sampling already outstanding, the shared context records ctx->status = -EBUSY. It does not start another sampling directly from that overlapping request. Pending work can continue after the current sampling completes.

The normal sequence end calls adc_context_complete(ctx, 0). Its synchronous branch preserves an existing context error when the argument is zero, then wakes the waiter. Its asynchronous branch instead raises the poll signal using the completion argument and releases the context lock.

Conditional starting state: ctx->status = -EBUSY
Normal final call:          adc_context_complete(ctx, 0)
Synchronous waiter:         returns stored -EBUSY
Asynchronous signal:       carries completion argument 0
A recorded minus EBUSY status reaches normal ADC completion with argument zero; the synchronous branch preserves the stored error while the asynchronous signal receives zero.
Original conditional source trace for the nrfx SAADC kernel-timer path. No test or hardware timing result is asserted.

This is the narrow reporting difference. The async signal does not copy the earlier interval-overrun value on that normal-completion branch. A nonzero argument supplied by a different error path is outside the stated case; the analysis does not say asynchronous completion always reports success.

Preserve the meaning of the interval warning

The public read documentation describes interval-related -EBUSY as a previous sampling still being in progress when another was triggered. It states that requested samples are written, with some taken later than scheduled. Do not translate the warning into an unsupported claim that the buffer necessarily lost samples.

Equally, selecting a small numeric interval does not prove that every target will enter the overlap branch. Channel configuration, conversion work, timer behavior and workload determine whether that condition occurs. The source establishes what follows from a recorded overlap, not a measured threshold for causing one.

Switching the same logical request to synchronous operation changes visibility of the stored status in this path. It does not make the requested interval physically achievable. A blocking return carrying more information is not a timing repair.

Test propagation separately from acquisition timing

A proposed controlled context test should arrange one outstanding sampling, introduce the overlapping request and then drive the otherwise normal completion path. Record the stored status, completion argument, synchronous return and asynchronous signal result as distinct values. Include a no-overlap control and a separately signaled completion error. This fixture has not been run.

After confirming the deployed source path, qualify cadence on an isolated target under its intended load. A sequence callback timestamp is a software observation, not automatically the physical acquisition instant. Correlate it with a documented hardware timing reference if sampling time is an acceptance requirement.

No firmware image, ADC operation or timing measurement was executed here. The useful conclusion is specific: for this tagged kernel-timer path, an async signal result of zero does not certify that the context never recorded an interval overrun. Preserve independent cadence evidence instead of assigning that stronger meaning to normal completion.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *