blob: 1b6b1e0b949c65fd07fa81aca76010aee1102d24 [file] [log] [blame]
/*
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_ASYNC_CONTEXT_THREADSAFE_BACKGROUND_H
#define _PICO_ASYNC_CONTEXT_THREADSAFE_BACKGROUND_H
/** \file pico/async_context.h
* \defgroup async_context_threadsafe_background async_context_threadsafe_background
* \ingroup pico_async_context
*
* \brief async_context_threadsafe_background provides an implementation of \ref async_context that handles asynchronous
* work in a low priority IRQ, and there is no need for the user to poll for work
*
* \note The workers used with this async_context MUST be safe to call from an IRQ.
*/
#include "pico/async_context.h"
#include "pico/sem.h"
#include "pico/mutex.h"
#include "hardware/irq.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ASYNC_CONTEXT_THREADSAFE_BACKGROUND_MULTI_CORE
#define ASYNC_CONTEXT_THREADSAFE_BACKGROUND_MULTI_CORE LIB_PICO_MULTICORE
#endif
typedef struct async_context_threadsafe_background async_context_threadsafe_background_t;
/**
* \brief Configuration object for async_context_threadsafe_background instances.
*/
typedef struct async_context_threadsafe_background_config {
/**
* \brief the priority of the low priority IRQ
*/
uint8_t low_priority_irq_handler_priority;
/**
* \brief a specific alarm pool to use (or NULL to use ta default)
*
* \note this alarm pool MUST be on the same core as the async_context
*
* The default alarm pool used is the "default alarm pool" (see
* \ref alarm_pool_get_default()) if available, and if that is on the same
* core, otherwise a private alarm_pool instance created during
* initialization.
*/
alarm_pool_t *custom_alarm_pool;
} async_context_threadsafe_background_config_t;
struct async_context_threadsafe_background {
async_context_t core;
alarm_pool_t *alarm_pool; // this must be on the same core as core_num
absolute_time_t last_set_alarm_time;
recursive_mutex_t lock_mutex;
semaphore_t work_needed_sem;
volatile alarm_id_t alarm_id;
#if ASYNC_CONTEXT_THREADSAFE_BACKGROUND_MULTI_CORE
volatile alarm_id_t force_alarm_id;
bool alarm_pool_owned;
#endif
uint8_t low_priority_irq_num;
volatile bool alarm_pending;
};
/*!
* \brief Initialize an async_context_threadsafe_background instance using the specified configuration
* \ingroup async_context_threadsafe_background
*
* If this method succeeds (returns true), then the async_context is available for use
* and can be de-initialized by calling async_context_deinit().
*
* \param self a pointer to async_context_threadsafe_background structure to initialize
* \param config the configuration object specifying characteristics for the async_context
* \return true if initialization is successful, false otherwise
*/
bool async_context_threadsafe_background_init(async_context_threadsafe_background_t *self, async_context_threadsafe_background_config_t *config);
/*!
* \brief Return a copy of the default configuration object used by \ref async_context_threadsafe_background_init_with_defaults()
* \ingroup async_context_threadsafe_background
*
* The caller can then modify just the settings it cares about, and call \ref async_context_threadsafe_background_init()
* \return the default configuration object
*/
async_context_threadsafe_background_config_t async_context_threadsafe_background_default_config(void);
/*!
* \brief Initialize an async_context_threadsafe_background instance with default values
* \ingroup async_context_threadsafe_background
*
* If this method succeeds (returns true), then the async_context is available for use
* and can be de-initialized by calling async_context_deinit().
*
* \param self a pointer to async_context_threadsafe_background structure to initialize
* \return true if initialization is successful, false otherwise
*/
static inline bool async_context_threadsafe_background_init_with_defaults(async_context_threadsafe_background_t *self) {
async_context_threadsafe_background_config_t config = async_context_threadsafe_background_default_config();
return async_context_threadsafe_background_init(self, &config);
}
#ifdef __cplusplus
}
#endif
#endif