123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- #ifndef ZEPHYR_DRIVERS_ADC_ADC_CONTEXT_H_
- #define ZEPHYR_DRIVERS_ADC_ADC_CONTEXT_H_
- #include <drivers/adc.h>
- #include <sys/atomic.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- struct adc_context;
- static void adc_context_start_sampling(struct adc_context *ctx);
- static void adc_context_update_buffer_pointer(struct adc_context *ctx,
- bool repeat_sampling);
- static void adc_context_enable_timer(struct adc_context *ctx);
- static void adc_context_disable_timer(struct adc_context *ctx);
- struct adc_context {
- atomic_t sampling_requested;
- #ifdef ADC_CONTEXT_USES_KERNEL_TIMER
- struct k_timer timer;
- #endif
- struct k_sem lock;
- struct k_sem sync;
- int status;
- #ifdef CONFIG_ADC_ASYNC
- struct k_poll_signal *signal;
- bool asynchronous;
- #endif
- struct adc_sequence sequence;
- struct adc_sequence_options options;
- uint16_t sampling_index;
- };
- #ifdef ADC_CONTEXT_USES_KERNEL_TIMER
- #define ADC_CONTEXT_INIT_TIMER(_data, _ctx_name) \
- ._ctx_name.timer = Z_TIMER_INITIALIZER(_data._ctx_name.timer, \
- adc_context_on_timer_expired, \
- NULL)
- #endif
- #define ADC_CONTEXT_INIT_LOCK(_data, _ctx_name) \
- ._ctx_name.lock = Z_SEM_INITIALIZER(_data._ctx_name.lock, 0, 1)
- #define ADC_CONTEXT_INIT_SYNC(_data, _ctx_name) \
- ._ctx_name.sync = Z_SEM_INITIALIZER(_data._ctx_name.sync, 0, 1)
- static inline void adc_context_request_next_sampling(struct adc_context *ctx)
- {
- if (atomic_inc(&ctx->sampling_requested) == 0) {
- adc_context_start_sampling(ctx);
- } else {
-
- ctx->status = -EBUSY;
- }
- }
- #ifdef ADC_CONTEXT_USES_KERNEL_TIMER
- static inline void adc_context_enable_timer(struct adc_context *ctx)
- {
- k_timer_start(&ctx->timer, K_NO_WAIT, K_USEC(ctx->options.interval_us));
- }
- static inline void adc_context_disable_timer(struct adc_context *ctx)
- {
- k_timer_stop(&ctx->timer);
- }
- static void adc_context_on_timer_expired(struct k_timer *timer_id)
- {
- struct adc_context *ctx =
- CONTAINER_OF(timer_id, struct adc_context, timer);
- adc_context_request_next_sampling(ctx);
- }
- #endif
- static inline void adc_context_lock(struct adc_context *ctx,
- bool asynchronous,
- struct k_poll_signal *signal)
- {
- k_sem_take(&ctx->lock, K_FOREVER);
- #ifdef CONFIG_ADC_ASYNC
- ctx->asynchronous = asynchronous;
- ctx->signal = signal;
- #endif
- }
- static inline void adc_context_release(struct adc_context *ctx, int status)
- {
- #ifdef CONFIG_ADC_ASYNC
- if (ctx->asynchronous && (status == 0)) {
- return;
- }
- #endif
- k_sem_give(&ctx->lock);
- }
- static inline void adc_context_unlock_unconditionally(struct adc_context *ctx)
- {
- if (!k_sem_count_get(&ctx->lock)) {
- k_sem_give(&ctx->lock);
- }
- }
- static inline int adc_context_wait_for_completion(struct adc_context *ctx)
- {
- #ifdef CONFIG_ADC_ASYNC
- if (ctx->asynchronous) {
- return 0;
- }
- #endif
- k_sem_take(&ctx->sync, K_FOREVER);
- return ctx->status;
- }
- static inline void adc_context_complete(struct adc_context *ctx, int status)
- {
- #ifdef CONFIG_ADC_ASYNC
- if (ctx->asynchronous) {
- if (ctx->signal) {
- k_poll_signal_raise(ctx->signal, status);
- }
- k_sem_give(&ctx->lock);
- return;
- }
- #endif
-
- if (status != 0) {
- ctx->status = status;
- }
- k_sem_give(&ctx->sync);
- }
- static inline void adc_context_start_read(struct adc_context *ctx,
- const struct adc_sequence *sequence)
- {
- ctx->sequence = *sequence;
- ctx->status = 0;
- if (sequence->options) {
- ctx->options = *sequence->options;
- ctx->sequence.options = &ctx->options;
- ctx->sampling_index = 0U;
- if (ctx->options.interval_us != 0U) {
- atomic_set(&ctx->sampling_requested, 0);
- adc_context_enable_timer(ctx);
- return;
- }
- }
- adc_context_start_sampling(ctx);
- }
- static inline void adc_context_on_sampling_done(struct adc_context *ctx,
- const struct device *dev)
- {
- 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->sampling_index);
- } else {
- action = ADC_ACTION_CONTINUE;
- }
- switch (action) {
- case ADC_ACTION_REPEAT:
- repeat = true;
- break;
- case ADC_ACTION_FINISH:
- finish = true;
- break;
- default:
- if (ctx->sampling_index <
- ctx->options.extra_samplings) {
- ++ctx->sampling_index;
- } else {
- finish = true;
- }
- }
- if (!finish) {
- adc_context_update_buffer_pointer(ctx, repeat);
-
- if (ctx->options.interval_us == 0U) {
- adc_context_start_sampling(ctx);
- } else if (atomic_dec(&ctx->sampling_requested) > 1) {
- adc_context_start_sampling(ctx);
- }
- return;
- }
- if (ctx->options.interval_us != 0U) {
- adc_context_disable_timer(ctx);
- }
- }
- adc_context_complete(ctx, 0);
- }
- #ifdef __cplusplus
- }
- #endif
- #endif
|