drivers: adc: make a copy of sequence struct

We should not be storing the sequence pointer, as
adc_read_async() returns immediately. The memory could
be heap allocated, or on a call stack. Make a copy of
it instead.

Fixes: #15039

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-03-29 17:24:28 -07:00 committed by Anas Nashif
commit 1efaae5949
5 changed files with 22 additions and 20 deletions

View file

@ -54,7 +54,8 @@ struct adc_context {
bool asynchronous;
#endif /* CONFIG_ADC_ASYNC */
const struct adc_sequence *sequence;
struct adc_sequence sequence;
struct adc_sequence_options options;
u16_t sampling_index;
};
@ -91,7 +92,7 @@ static inline void adc_context_request_next_sampling(struct adc_context *ctx)
#ifdef ADC_CONTEXT_USES_KERNEL_TIMER
static inline void adc_context_enable_timer(struct adc_context *ctx)
{
u32_t interval_us = ctx->sequence->options->interval_us;
u32_t interval_us = ctx->options.interval_us;
u32_t interval_ms = ceiling_fraction(interval_us, 1000UL);
k_timer_start(&ctx->timer, 0, interval_ms);
@ -181,13 +182,15 @@ static inline void adc_context_complete(struct adc_context *ctx, int status)
static inline void adc_context_start_read(struct adc_context *ctx,
const struct adc_sequence *sequence)
{
ctx->sequence = sequence;
ctx->sequence = *sequence;
ctx->status = 0;
if (ctx->sequence->options) {
if (sequence->options) {
ctx->options = *sequence->options;
ctx->sequence.options = &ctx->options;
ctx->sampling_index = 0U;
if (ctx->sequence->options->interval_us != 0U) {
if (ctx->options.interval_us != 0U) {
atomic_set(&ctx->sampling_requested, 0);
adc_context_enable_timer(ctx);
return;
@ -205,16 +208,15 @@ static inline void adc_context_start_read(struct adc_context *ctx,
static inline void adc_context_on_sampling_done(struct adc_context *ctx,
struct device *dev)
{
if (ctx->sequence->options) {
adc_sequence_callback callback =
ctx->sequence->options->callback;
if (ctx->sequence.options) {
adc_sequence_callback callback = ctx->options.callback;
enum adc_action action;
bool finish = false;
bool repeat = false;
if (callback) {
action = callback(dev,
ctx->sequence,
&ctx->sequence,
ctx->sampling_index);
} else {
action = ADC_ACTION_CONTINUE;
@ -229,7 +231,7 @@ static inline void adc_context_on_sampling_done(struct adc_context *ctx,
break;
default: /* ADC_ACTION_CONTINUE */
if (ctx->sampling_index <
ctx->sequence->options->extra_samplings) {
ctx->options.extra_samplings) {
++ctx->sampling_index;
} else {
finish = true;
@ -244,7 +246,7 @@ static inline void adc_context_on_sampling_done(struct adc_context *ctx,
* a zero interval or if the timer expired again while
* the current sampling was in progress.
*/
if (ctx->sequence->options->interval_us == 0U) {
if (ctx->options.interval_us == 0U) {
adc_context_start_sampling(ctx);
} else if (atomic_dec(&ctx->sampling_requested) > 1) {
adc_context_start_sampling(ctx);
@ -253,7 +255,7 @@ static inline void adc_context_on_sampling_done(struct adc_context *ctx,
return;
}
if (ctx->sequence->options->interval_us != 0U) {
if (ctx->options.interval_us != 0U) {
adc_context_disable_timer(ctx);
}
}

View file

@ -366,7 +366,7 @@ static void adc_context_start_sampling(struct adc_context *ctx)
struct adc_quark_d2000_info *info =
CONTAINER_OF(ctx, struct adc_quark_d2000_info, ctx);
info->channels = ctx->sequence->channels;
info->channels = ctx->sequence.channels;
adc_quark_d2000_start_conversion(info->dev);
}
@ -376,7 +376,7 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx,
{
struct adc_quark_d2000_info *info =
CONTAINER_OF(ctx, struct adc_quark_d2000_info, ctx);
const struct adc_sequence *entry = ctx->sequence;
const struct adc_sequence *entry = &ctx->sequence;
if (repeat) {
info->buffer = (u16_t *)entry->buffer;

View file

@ -441,7 +441,7 @@ static void adc_quark_se_ss_start_conversion(struct device *dev)
{
struct adc_info *info = dev->driver_data;
const struct adc_config *config = info->dev->config->config_info;
const struct adc_sequence *entry = info->ctx.sequence;
const struct adc_sequence *entry = &info->ctx.sequence;
u32_t adc_base = config->reg_base;
u32_t ctrl, tmp_val, sample_window;
@ -492,7 +492,7 @@ static void adc_context_start_sampling(struct adc_context *ctx)
{
struct adc_info *info = CONTAINER_OF(ctx, struct adc_info, ctx);
info->channels = ctx->sequence->channels;
info->channels = ctx->sequence.channels;
adc_quark_se_ss_start_conversion(info->dev);
}
@ -501,7 +501,7 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx,
bool repeat)
{
struct adc_info *info = CONTAINER_OF(ctx, struct adc_info, ctx);
const struct adc_sequence *entry = ctx->sequence;
const struct adc_sequence *entry = &ctx->sequence;
if (repeat) {
info->buffer = (u16_t *)entry->buffer;
@ -556,7 +556,7 @@ static void adc_quark_se_ss_rx_isr(void *arg)
struct device *dev = (struct device *)arg;
struct adc_info *info = dev->driver_data;
const struct adc_config *config = dev->config->config_info;
const struct adc_sequence *seq = info->ctx.sequence;
struct adc_sequence *seq = &info->ctx.sequence;
u32_t adc_base = config->reg_base;
u32_t reg_val;

View file

@ -183,7 +183,7 @@ static void adc_context_start_sampling(struct adc_context *ctx)
struct mcux_adc16_data *data =
CONTAINER_OF(ctx, struct mcux_adc16_data, ctx);
data->channels = ctx->sequence->channels;
data->channels = ctx->sequence.channels;
data->repeat_buffer = data->buffer;
mcux_adc16_start_channel(data->dev);

View file

@ -150,7 +150,7 @@ static void adc_context_start_sampling(struct adc_context *ctx)
{
struct adc_sam_data *data = CONTAINER_OF(ctx, struct adc_sam_data, ctx);
data->channels = ctx->sequence->channels;
data->channels = ctx->sequence.channels;
adc_sam_start_conversion(data->dev);
}