You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the bug
When the adc_read_async method is called (zephyr/include/drivers/adc.h) with a sequence pointer placed on the heap, and sequence.options pointer placed on the heap, the same pointers are not returned in the options.callback function pointer.
Instead, in zephyr/drivers/adc/adc_context.h, the given pointers are dereferenced in the method 'adc_context_start_read'.
Essentially, the 'struct adc_sequence' contents are cloned and a pointer to the cloned contents is passed as callback argument.
As this is passed, there is no way of using CONTAINER_OF() in the options.callback function, as the pointer value is different as to what was passed in the adc_read_async.
When adc_read_async is called, passing pointers that are on the stack, the dereferencing makes sense, but in order to do something in the options.callback function, they must be on the heap.
To Reproduce
Steps to reproduce the behavior:
#pragma once
#include <drivers/adc.h>
#include <cassert>
namespace Test::IO {
// Circumvent leaky abstractions from Zephyr
#if defined(ADC)
#undef ADC
#endif
class ADC
{
private:
const struct device* _dev;
uint8_t _channel;
struct adc_channel_cfg _config;
uint8_t _resolution;
struct IsrContext {
struct k_work work;
ADC* self;
struct adc_sequence_options options;
struct adc_sequence sequence;
int16_t buffer;
int16_t sample;
} _isrContext;
public:
ADC(const struct device* dev, const struct adc_channel_cfg& config, uint8_t resolution)
: _dev(dev)
, _config(config)
, _resolution(resolution)
{
int result = 0;
assert(dev != nullptr);
// Configure ADC channel
result = adc_channel_setup(_dev, &_config);
assert(result == 0);
// Configure soft IRQ
k_work_init(&_isrContext.work, _soft_isr);
_isrContext.self = this;
}
/**
* Starts the capture of a continuous sequence of samples.
* @param interval_us Interval in microseconds between each consecutive sample.
*/
virtual void readAsync(uint32_t interval_us = 0) override {
_isrContext.options = {
.interval_us = interval_us,
.callback = _hard_isr,
};
_isrContext.sequence = {
.options = &_options,
.channels = BIT(_config.channel_id),
.buffer = &_isrContext.buffer,
.buffer_size = sizeof(_isrContext.buffer),
.resolution = _resolution,
};
int res = adc_read_async(_dev, &_isrContext.sequence, nullptr);
assert(res == 0);
}
/**
* Cancel async read and stops the capture, does nothing in case there is
* no capture in progress.
*/
virtual void cancelRead() override {
// TODO: To be implemented
}
private:
static void _soft_isr(struct k_work *work) {
}
static enum adc_action _hard_isr(const struct device *,
const struct adc_sequence *sequence,
uint16_t sampling_index __unused)
{
IsrContext* context = CONTAINER_OF(sequence, IsrContext, sequence);
// Store a copy of the conversion buffer
context->sample = context->buffer;
// Forward IRQ to kernel worker thread.
k_work_submit(&context->work);
// Continue sampling
return ADC_ACTION_REPEAT;
}
};
} // namespace Test::IO
Create a main that constructs an ADC instance and calls readAsync()
Describe the bug
When the adc_read_async method is called (zephyr/include/drivers/adc.h) with a sequence pointer placed on the heap, and sequence.options pointer placed on the heap, the same pointers are not returned in the options.callback function pointer.
Instead, in zephyr/drivers/adc/adc_context.h, the given pointers are dereferenced in the method 'adc_context_start_read'.
Essentially, the 'struct adc_sequence' contents are cloned and a pointer to the cloned contents is passed as callback argument.
As this is passed, there is no way of using CONTAINER_OF() in the options.callback function, as the pointer value is different as to what was passed in the adc_read_async.
When adc_read_async is called, passing pointers that are on the stack, the dereferencing makes sense, but in order to do something in the options.callback function, they must be on the heap.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
adc_read_async sequence.option.callback method uses same passed sequence pointer
Impact
We have created our own k_timer that calls an adc_read (synchronous call) decoupled by a system worker queue item.
Environment (please complete the following information):
The text was updated successfully, but these errors were encountered: