mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
feat(bt): Add host-agnostic BT OSAL and shared BLE profile task
- Add bt_osal: event queues, mutexes, semaphores, callouts, etc. - Add the shared BLE profile task and event queue - Bring both up and tear them down in the host init/deinit paths - Add unit tests for the OSAL and the profile task
This commit is contained in:
@@ -114,6 +114,7 @@ list(APPEND bt_common_srcs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/osi/osi.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/osi/semaphore.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ble_log/deprecated/ble_log_spi_out.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/osal/src/bt_osal_freertos.c"
|
||||
)
|
||||
|
||||
list(APPEND bt_common_include_dirs
|
||||
@@ -124,6 +125,7 @@ list(APPEND bt_common_include_dirs
|
||||
"${CMAKE_CURRENT_LIST_DIR}/hci_log/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ble_log/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/ble_log/deprecated/include"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/osal/include"
|
||||
)
|
||||
|
||||
list(APPEND bt_common_priv_include_dirs
|
||||
|
||||
@@ -21,6 +21,21 @@ config BT_BLE_HOST_ALLOW_SUB_SPEC_MIN_CONN_INT
|
||||
this mode; use the Controller's own configuration instead of toggling
|
||||
this host symbol manually.
|
||||
|
||||
menu "OSAL (OS abstraction layer)"
|
||||
depends on BT_ENABLED
|
||||
|
||||
config BT_OSAL_USE_ESP_TIMER
|
||||
bool "Use esp_timer to implement the OSAL callout"
|
||||
default y
|
||||
help
|
||||
Use esp_timer instead of the FreeRTOS software timer to implement the OSAL
|
||||
callout. esp_timer offers higher precision and runs its callbacks in a
|
||||
dedicated high-priority task rather than the shared FreeRTOS timer task.
|
||||
|
||||
Disable to fall back to the FreeRTOS software timer.
|
||||
|
||||
endmenu
|
||||
|
||||
choice BT_SMP_CRYPTO_STACK
|
||||
prompt "SMP cryptographic stack"
|
||||
depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE || BT_NIMBLE_SECURITY_ENABLE || BT_LE_SECURITY_ENABLE || \
|
||||
|
||||
@@ -0,0 +1,686 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file bt_osal.h
|
||||
* @brief OS Abstraction Layer (OSAL) for the Bluetooth host
|
||||
*
|
||||
* Provides the OS primitives the Bluetooth host relies on: event queues,
|
||||
* mutexes, semaphores, callouts (one-shot timers), time conversion and
|
||||
* critical sections.
|
||||
*
|
||||
* Every API declared here dispatches through the function table installed by
|
||||
* bt_osal_freertos_funcs_init(), which MUST be called before any other bt_osal_*
|
||||
* API is used.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BT_OSAL_H_
|
||||
#define _BT_OSAL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct bt_osal_event;
|
||||
|
||||
/**
|
||||
* @brief Event handler invoked when a queued event is dispatched
|
||||
*
|
||||
* @param ev Event being dispatched. Use bt_osal_event_get_arg() to retrieve the
|
||||
* argument registered at bt_osal_event_init() time.
|
||||
*/
|
||||
typedef void bt_osal_event_fn(struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief OSAL error codes
|
||||
*/
|
||||
enum bt_osal_error {
|
||||
BT_OSAL_OK = 0, /*!< Success */
|
||||
BT_OSAL_ENOMEM = 1, /*!< Out of memory */
|
||||
BT_OSAL_EINVAL = 2, /*!< Invalid argument or invalid object state */
|
||||
BT_OSAL_INVALID_PARAM = 3, /*!< Object is not initialized, or allocation for it failed */
|
||||
BT_OSAL_MEM_NOT_ALIGNED = 4, /*!< Memory is not aligned as required */
|
||||
BT_OSAL_BAD_MUTEX = 5, /*!< Mutex is not owned by the calling task */
|
||||
BT_OSAL_TIMEOUT = 6, /*!< Operation timed out before it could complete */
|
||||
BT_OSAL_ERR_IN_ISR = 7, /*!< Operation is not allowed from interrupt context */
|
||||
BT_OSAL_ERR_PRIV = 8, /*!< Operation requires privileges the caller does not have */
|
||||
BT_OSAL_OS_NOT_STARTED = 9, /*!< The OS scheduler has not been started yet */
|
||||
BT_OSAL_ENOENT = 10, /*!< Requested object does not exist */
|
||||
BT_OSAL_EBUSY = 11, /*!< Object is busy */
|
||||
BT_OSAL_ERROR = 12, /*!< Unspecified error */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief OSAL error code type
|
||||
*/
|
||||
typedef enum bt_osal_error bt_osal_error_t;
|
||||
|
||||
/* Include OS-specific definitions */
|
||||
#include "bt_osal_os.h"
|
||||
|
||||
/*
|
||||
* Generic
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Check whether the OS scheduler is running
|
||||
*
|
||||
* @return true if the scheduler has been started, false otherwise
|
||||
*/
|
||||
bool bt_osal_os_started(void);
|
||||
|
||||
/**
|
||||
* @brief Get an opaque identifier of the calling task
|
||||
*
|
||||
* @return Handle of the calling task
|
||||
*/
|
||||
void *bt_osal_get_current_task_id(void);
|
||||
|
||||
/*
|
||||
* Event queue
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize an event queue
|
||||
*
|
||||
* Allocates the queue's backing storage on first use. Calling this on an
|
||||
* already-initialized queue reuses the storage and discards any pending events,
|
||||
* leaving the queue empty.
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param evq Event queue to initialize
|
||||
*/
|
||||
void bt_osal_eventq_init(struct bt_osal_eventq *evq);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize an event queue and release its resources
|
||||
*
|
||||
* Deletes the queue's processing task if one was started, then frees the
|
||||
* backing storage. It is safe to call this on a queue that was never
|
||||
* initialized or already deinitialized.
|
||||
*
|
||||
* @param evq Event queue to deinitialize
|
||||
*/
|
||||
void bt_osal_eventq_deinit(struct bt_osal_eventq *evq);
|
||||
|
||||
/**
|
||||
* @brief Dequeue the next event, waiting for one if the queue is empty
|
||||
*
|
||||
* The returned event is no longer marked as queued, so it may be posted again.
|
||||
*
|
||||
* @note From interrupt context @p tmo MUST be 0; a non-zero timeout asserts.
|
||||
*
|
||||
* @param evq Event queue to take the event from
|
||||
* @param tmo Maximum time to wait, in ticks. Use 0 to poll, or
|
||||
* BT_OSAL_TIME_FOREVER to wait indefinitely.
|
||||
*
|
||||
* @return Next event in the queue, or NULL if none became available within @p tmo
|
||||
*/
|
||||
struct bt_osal_event *bt_osal_eventq_get(struct bt_osal_eventq *evq,
|
||||
bt_osal_time_t tmo);
|
||||
|
||||
/**
|
||||
* @brief Append an event to the back of an event queue
|
||||
*
|
||||
* Does nothing if @p ev is already queued, so an event is never enqueued twice.
|
||||
*
|
||||
* @param evq Event queue to post to
|
||||
* @param ev Event to post
|
||||
*/
|
||||
void bt_osal_eventq_put(struct bt_osal_eventq *evq, struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Insert an event at the front of an event queue
|
||||
*
|
||||
* Same as bt_osal_eventq_put() except the event is dequeued before all events
|
||||
* already pending. Does nothing if @p ev is already queued.
|
||||
*
|
||||
* @param evq Event queue to post to
|
||||
* @param ev Event to post
|
||||
*/
|
||||
void bt_osal_eventq_put_to_front(struct bt_osal_eventq *evq,
|
||||
struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Remove a pending event from an event queue
|
||||
*
|
||||
* Does nothing if @p ev is not currently queued.
|
||||
*
|
||||
* @param evq Event queue holding the event
|
||||
* @param ev Event to remove
|
||||
*/
|
||||
void bt_osal_eventq_remove(struct bt_osal_eventq *evq,
|
||||
struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Start a dedicated task that processes an event queue
|
||||
*
|
||||
* Spawns a task that blocks on bt_osal_eventq_get() and dispatches each dequeued
|
||||
* event with bt_osal_event_run(), so events posted to @p evq are handled
|
||||
* asynchronously in this task's context. The queue must already be initialized
|
||||
* with bt_osal_eventq_init().
|
||||
*
|
||||
* @note Only one processing task may be started per queue.
|
||||
*
|
||||
* @param evq Event queue to process
|
||||
* @param info Attributes (name, priority, stack size, core affinity) of the
|
||||
* processing task; @c info->name must not be NULL. Set
|
||||
* @c info->core_id to BT_OSAL_TASK_NO_AFFINITY to leave the task
|
||||
* unpinned — a zero-initialized @p info pins it to core 0.
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_EINVAL if @p info or @c info->name is NULL, @c info->core_id is
|
||||
* neither a valid core nor BT_OSAL_TASK_NO_AFFINITY, the queue is not
|
||||
* initialized, or it already has a processing task
|
||||
* - BT_OSAL_ENOMEM if the task could not be created
|
||||
*/
|
||||
bt_osal_error_t bt_osal_eventq_start(struct bt_osal_eventq *evq,
|
||||
const struct bt_osal_task_info *info);
|
||||
|
||||
/**
|
||||
* @brief Post a one-shot function to be run from an event queue
|
||||
*
|
||||
* Allocates a self-contained event, posts it to @p evq, and runs @p fn when the
|
||||
* event is dispatched by the queue's processing task (see bt_osal_eventq_start()).
|
||||
* The event's backing storage is freed automatically after @p fn returns, so no
|
||||
* event object needs to be managed by the caller. Inside @p fn the argument
|
||||
* @p arg is retrievable via bt_osal_event_get_arg().
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param evq Event queue to post the work to
|
||||
* @param fn Handler to run when the event is dispatched
|
||||
* @param arg Argument passed to @p fn
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_EINVAL if the queue is not initialized or @p fn is NULL
|
||||
* - BT_OSAL_ERR_IN_ISR if called from interrupt context
|
||||
* - BT_OSAL_ENOMEM if the work item could not be allocated
|
||||
*/
|
||||
bt_osal_error_t bt_osal_eventq_post_func(struct bt_osal_eventq *evq,
|
||||
bt_osal_event_fn *fn, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Initialize an event with its handler and argument
|
||||
*
|
||||
* Allocates the event's backing storage on first use. Calling this on an
|
||||
* already-initialized event reuses the storage and overwrites the handler and
|
||||
* argument.
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param ev Event to initialize
|
||||
* @param fn Handler to run when the event is dispatched
|
||||
* @param arg Argument passed to @p fn, retrievable via bt_osal_event_get_arg()
|
||||
*/
|
||||
void bt_osal_event_init(struct bt_osal_event *ev, bt_osal_event_fn *fn,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize an event and free its backing storage
|
||||
*
|
||||
* The event must not be queued; remove it with bt_osal_eventq_remove() first.
|
||||
* It is safe to call this on an event that was never initialized or already
|
||||
* deinitialized.
|
||||
*
|
||||
* @param ev Event to deinitialize
|
||||
*/
|
||||
void bt_osal_event_deinit(struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Clear the queued flag of an event
|
||||
*
|
||||
* Only clears the flag; it does NOT unlink the event from a queue it is still
|
||||
* pending on. To take a queued event out of its queue, use
|
||||
* bt_osal_eventq_remove().
|
||||
*
|
||||
* @warning The event MUST NOT be queued when this is called. Resetting a still-
|
||||
* queued event desynchronizes its flag from the queue and, with the
|
||||
* intrusive-list backend, leaves it linked while marked free — a later
|
||||
* put() then relinks the same node and corrupts the list. Callers must
|
||||
* bt_osal_eventq_remove() (or let it be dispatched) first; the flag is
|
||||
* checked with an assertion in debug builds.
|
||||
*
|
||||
* @param ev Event to reset (must not be currently queued)
|
||||
*/
|
||||
void bt_osal_event_reset(struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Check whether an event is pending in an event queue
|
||||
*
|
||||
* @param ev Event to query
|
||||
*
|
||||
* @return true if the event is queued and not yet dispatched, false otherwise
|
||||
*/
|
||||
bool bt_osal_event_is_queued(struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Get the argument registered with an event
|
||||
*
|
||||
* @param ev Event to query
|
||||
*
|
||||
* @return Argument passed to bt_osal_event_init() or bt_osal_event_set_arg()
|
||||
*/
|
||||
void *bt_osal_event_get_arg(struct bt_osal_event *ev);
|
||||
|
||||
/**
|
||||
* @brief Replace the argument registered with an event
|
||||
*
|
||||
* @param ev Event to update
|
||||
* @param arg New argument to pass to the event handler
|
||||
*/
|
||||
void bt_osal_event_set_arg(struct bt_osal_event *ev, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Check whether an event queue holds no pending events
|
||||
*
|
||||
* @param evq Event queue to query
|
||||
*
|
||||
* @return true if the queue is empty, false otherwise
|
||||
*/
|
||||
bool bt_osal_eventq_is_empty(struct bt_osal_eventq *evq);
|
||||
|
||||
/**
|
||||
* @brief Run an event's handler in the calling context
|
||||
*
|
||||
* Invokes the handler registered by bt_osal_event_init() synchronously; the
|
||||
* event is not required to have been queued.
|
||||
*
|
||||
* @param ev Event to dispatch
|
||||
*/
|
||||
void bt_osal_event_run(struct bt_osal_event *ev);
|
||||
|
||||
/*
|
||||
* Mutexes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a recursive mutex
|
||||
*
|
||||
* Allocates the mutex on first use; calling this on an already-initialized
|
||||
* mutex leaves it untouched and succeeds.
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param mu Mutex to initialize
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_ENOMEM if the mutex could not be allocated
|
||||
*/
|
||||
bt_osal_error_t bt_osal_mutex_init(struct bt_osal_mutex *mu);
|
||||
|
||||
/**
|
||||
* @brief Acquire a mutex, waiting for it if it is held by another task
|
||||
*
|
||||
* The mutex is recursive: a task already owning it acquires it again without
|
||||
* blocking, and must release it once per successful pend.
|
||||
*
|
||||
* @note Must not be called from interrupt context; doing so asserts.
|
||||
*
|
||||
* @param mu Mutex to acquire
|
||||
* @param timeout Maximum time to wait, in ticks. Use 0 to try without blocking,
|
||||
* or BT_OSAL_TIME_FOREVER to wait indefinitely.
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK if the mutex was acquired
|
||||
* - BT_OSAL_TIMEOUT if it was still held when @p timeout elapsed
|
||||
* - BT_OSAL_INVALID_PARAM if the mutex is not initialized
|
||||
*/
|
||||
bt_osal_error_t bt_osal_mutex_pend(struct bt_osal_mutex *mu,
|
||||
bt_osal_time_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Release a mutex held by the calling task
|
||||
*
|
||||
* A recursively acquired mutex is only released to other tasks once this has
|
||||
* been called as many times as it was successfully pended.
|
||||
*
|
||||
* @note Must not be called from interrupt context; doing so asserts.
|
||||
*
|
||||
* @param mu Mutex to release
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_BAD_MUTEX if the calling task does not own the mutex
|
||||
* - BT_OSAL_INVALID_PARAM if the mutex is not initialized
|
||||
*/
|
||||
bt_osal_error_t bt_osal_mutex_release(struct bt_osal_mutex *mu);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a mutex and free its resources
|
||||
*
|
||||
* The mutex must not be held when it is deinitialized.
|
||||
*
|
||||
* @param mu Mutex to deinitialize
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_INVALID_PARAM if the mutex is not initialized
|
||||
*/
|
||||
bt_osal_error_t bt_osal_mutex_deinit(struct bt_osal_mutex *mu);
|
||||
|
||||
/*
|
||||
* Semaphores
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a counting semaphore
|
||||
*
|
||||
* Allocates the semaphore on first use; calling this on an already-initialized
|
||||
* semaphore leaves it untouched (including its token count) and succeeds.
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param sem Semaphore to initialize
|
||||
* @param tokens Initial number of tokens
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_ENOMEM if the semaphore could not be allocated
|
||||
*/
|
||||
bt_osal_error_t bt_osal_sem_init(struct bt_osal_sem *sem, uint16_t tokens);
|
||||
|
||||
/**
|
||||
* @brief Take one token from a semaphore, waiting if none is available
|
||||
*
|
||||
* @note From interrupt context @p timeout MUST be 0; a non-zero timeout asserts.
|
||||
*
|
||||
* @param sem Semaphore to take a token from
|
||||
* @param timeout Maximum time to wait, in ticks. Use 0 to try without blocking,
|
||||
* or BT_OSAL_TIME_FOREVER to wait indefinitely.
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK if a token was taken
|
||||
* - BT_OSAL_TIMEOUT if no token became available within @p timeout
|
||||
* - BT_OSAL_INVALID_PARAM if the semaphore is not initialized
|
||||
*/
|
||||
bt_osal_error_t bt_osal_sem_pend(struct bt_osal_sem *sem,
|
||||
bt_osal_time_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Return one token to a semaphore, unblocking a waiter if any
|
||||
*
|
||||
* @param sem Semaphore to give a token to
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_INVALID_PARAM if the semaphore is not initialized
|
||||
* - BT_OSAL_ERROR if the token could not be returned (semaphore already full)
|
||||
*/
|
||||
bt_osal_error_t bt_osal_sem_release(struct bt_osal_sem *sem);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a semaphore and free its resources
|
||||
*
|
||||
* No task may be pending on the semaphore when it is deinitialized.
|
||||
*
|
||||
* @param sem Semaphore to deinitialize
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_INVALID_PARAM if the semaphore is not initialized
|
||||
*/
|
||||
bt_osal_error_t bt_osal_sem_deinit(struct bt_osal_sem *sem);
|
||||
|
||||
/**
|
||||
* @brief Get the number of tokens currently held by a semaphore
|
||||
*
|
||||
* @param sem Semaphore to query
|
||||
*
|
||||
* @return Current token count
|
||||
*/
|
||||
uint16_t bt_osal_sem_get_count(struct bt_osal_sem *sem);
|
||||
|
||||
/*
|
||||
* Callouts
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a callout (one-shot timer)
|
||||
*
|
||||
* The callout is created stopped; arm it with bt_osal_callout_reset().
|
||||
*
|
||||
* On expiry, if @p evq is non-NULL the callout's event is posted to that queue
|
||||
* and @p ev_cb runs in the context of the task processing the queue. If @p evq
|
||||
* is NULL, @p ev_cb is instead run directly in timer context, where it must not
|
||||
* block and must keep its stack usage small.
|
||||
*
|
||||
* Allocates the callout's backing storage on first use; calling this on an
|
||||
* already-initialized callout reuses the storage and rebinds the queue, handler
|
||||
* and argument.
|
||||
*
|
||||
* @note Allocates memory, so it must not be called from interrupt context.
|
||||
*
|
||||
* @param co Callout to initialize
|
||||
* @param evq Event queue to post the event to on expiry, or NULL to run
|
||||
* @p ev_cb in timer context
|
||||
* @param ev_cb Handler to run when the callout expires
|
||||
* @param ev_arg Argument passed to @p ev_cb
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_ENOMEM if the callout or its underlying timer could not be created
|
||||
*/
|
||||
bt_osal_error_t bt_osal_callout_init(struct bt_osal_callout *co, struct bt_osal_eventq *evq,
|
||||
bt_osal_event_fn *ev_cb, void *ev_arg);
|
||||
|
||||
/**
|
||||
* @brief Stop a callout, delete its timer and free its resources
|
||||
*
|
||||
* It is safe to call this on a callout that was never initialized or already
|
||||
* deinitialized.
|
||||
*
|
||||
* @param co Callout to deinitialize
|
||||
*/
|
||||
void bt_osal_callout_deinit(struct bt_osal_callout *co);
|
||||
|
||||
/**
|
||||
* @brief (Re)arm a callout to expire after the given delay
|
||||
*
|
||||
* Stops the callout if it is already running, then restarts it, so the delay is
|
||||
* always measured from this call.
|
||||
*
|
||||
* @param co Callout to arm
|
||||
* @param ticks Delay before expiry, in ticks
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_INVALID_PARAM or BT_OSAL_EINVAL if the underlying timer rejected the request
|
||||
* - BT_OSAL_ERROR on any other failure
|
||||
*/
|
||||
bt_osal_error_t bt_osal_callout_reset(struct bt_osal_callout *co,
|
||||
bt_osal_time_t ticks);
|
||||
|
||||
/**
|
||||
* @brief Stop a callout so it will not expire
|
||||
*
|
||||
* Does nothing if the callout is not running. If a previous expiry already
|
||||
* posted an event to the callout's event queue, that event is removed from
|
||||
* the queue as part of stopping (unless it has already been dequeued for processing).
|
||||
*
|
||||
* @param co Callout to stop
|
||||
*/
|
||||
void bt_osal_callout_stop(struct bt_osal_callout *co);
|
||||
|
||||
/**
|
||||
* @brief Check whether a callout is armed and has not expired yet
|
||||
*
|
||||
* @param co Callout to query
|
||||
*
|
||||
* @return true if the callout is running, false otherwise
|
||||
*/
|
||||
bool bt_osal_callout_is_active(struct bt_osal_callout *co);
|
||||
|
||||
/**
|
||||
* @brief Get the absolute time at which a callout will expire
|
||||
*
|
||||
* @param co Callout to query
|
||||
*
|
||||
* @return Expiry time in ticks, or 0 if it cannot be determined
|
||||
*/
|
||||
bt_osal_time_t bt_osal_callout_get_ticks(struct bt_osal_callout *co);
|
||||
|
||||
/**
|
||||
* @brief Get the time left before a callout expires
|
||||
*
|
||||
* @param co Callout to query
|
||||
* @param time Reference time to measure from, in ticks (typically bt_osal_time_get())
|
||||
*
|
||||
* @return Ticks remaining until expiry, or 0 if the callout has already expired
|
||||
* at @p time or its expiry time cannot be determined
|
||||
*/
|
||||
bt_osal_time_t bt_osal_callout_remaining_ticks(struct bt_osal_callout *co,
|
||||
bt_osal_time_t time);
|
||||
|
||||
/**
|
||||
* @brief Replace the argument passed to a callout's handler
|
||||
*
|
||||
* @param co Callout to update
|
||||
* @param arg New argument to pass to the handler on expiry
|
||||
*/
|
||||
void bt_osal_callout_set_arg(struct bt_osal_callout *co,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* @brief Clear the queued flag of a callout's event
|
||||
*
|
||||
* Lets the callout be armed again after its event was dropped without being
|
||||
* dispatched. It does not stop the timer.
|
||||
*
|
||||
* @param co Callout whose event should be reset
|
||||
*/
|
||||
void bt_osal_callout_mem_reset(struct bt_osal_callout *co);
|
||||
|
||||
/*
|
||||
* Time functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the current time
|
||||
*
|
||||
* @return Time since boot, in ticks
|
||||
*/
|
||||
bt_osal_time_t bt_osal_time_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get the tick value that means "wait forever"
|
||||
*
|
||||
* Use it as the timeout of a pend/get to block indefinitely. Also available as
|
||||
* the BT_OSAL_TIME_FOREVER macro.
|
||||
*
|
||||
* @return Tick value representing an infinite timeout
|
||||
*/
|
||||
bt_osal_time_t bt_osal_get_time_forever(void);
|
||||
|
||||
/**
|
||||
* @brief Convert milliseconds to ticks
|
||||
*
|
||||
* @param[in] ms Duration in milliseconds
|
||||
* @param[out] out_ticks Resulting duration in ticks
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_EINVAL if the result does not fit in bt_osal_time_t
|
||||
*/
|
||||
bt_osal_error_t bt_osal_time_ms_to_ticks(uint32_t ms, bt_osal_time_t *out_ticks);
|
||||
|
||||
/**
|
||||
* @brief Convert ticks to milliseconds
|
||||
*
|
||||
* @param[in] ticks Duration in ticks
|
||||
* @param[out] out_ms Resulting duration in milliseconds
|
||||
*
|
||||
* @return
|
||||
* - BT_OSAL_OK on success
|
||||
* - BT_OSAL_EINVAL if the result does not fit in uint32_t
|
||||
*/
|
||||
bt_osal_error_t bt_osal_time_ticks_to_ms(bt_osal_time_t ticks, uint32_t *out_ms);
|
||||
|
||||
/**
|
||||
* @brief Convert milliseconds to ticks, without overflow checking
|
||||
*
|
||||
* @param ms Duration in milliseconds
|
||||
*
|
||||
* @return Duration in ticks
|
||||
*/
|
||||
bt_osal_time_t bt_osal_time_ms_to_ticks32(uint32_t ms);
|
||||
|
||||
/**
|
||||
* @brief Convert ticks to milliseconds, without overflow checking
|
||||
*
|
||||
* @param ticks Duration in ticks
|
||||
*
|
||||
* @return Duration in milliseconds
|
||||
*/
|
||||
uint32_t bt_osal_time_ticks_to_ms32(bt_osal_time_t ticks);
|
||||
|
||||
/**
|
||||
* @brief Block the calling task for the given duration
|
||||
*
|
||||
* @note Must not be called from interrupt context.
|
||||
*
|
||||
* @param ticks Duration to block for, in ticks
|
||||
*/
|
||||
void bt_osal_time_delay(bt_osal_time_t ticks);
|
||||
|
||||
/*
|
||||
* Hardware-specific
|
||||
*
|
||||
* These symbols should be most likely defined by application since they are
|
||||
* specific to hardware, not to OS.
|
||||
*/
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
|
||||
/**
|
||||
* @brief Install an interrupt handler for the given interrupt
|
||||
*
|
||||
* @param irqn Interrupt number to install the handler for
|
||||
* @param addr Address of the interrupt handler
|
||||
*/
|
||||
void bt_osal_hw_set_isr(int irqn, uint32_t addr);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enter a critical section, disabling interrupts
|
||||
*
|
||||
* Critical sections nest: each call must be paired with a
|
||||
* bt_osal_hw_exit_critical() call, and interrupts are only re-enabled by the
|
||||
* outermost one. Keep the section as short as possible and never block in it.
|
||||
*
|
||||
* @return Context to be passed back to bt_osal_hw_exit_critical()
|
||||
*/
|
||||
uint32_t bt_osal_hw_enter_critical(void);
|
||||
|
||||
/**
|
||||
* @brief Leave a critical section entered with bt_osal_hw_enter_critical()
|
||||
*
|
||||
* @param ctx Context returned by the matching bt_osal_hw_enter_critical() call
|
||||
*/
|
||||
void bt_osal_hw_exit_critical(uint32_t ctx);
|
||||
|
||||
/**
|
||||
* @brief Check whether the caller is inside a critical section
|
||||
*
|
||||
* @return true if at least one critical section is currently entered, false otherwise
|
||||
*/
|
||||
bool bt_osal_hw_is_in_critical(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BT_OSAL_H_ */
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
|
||||
#ifndef _BT_OSAL_FREERTOS_H_
|
||||
#define _BT_OSAL_FREERTOS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* Use esp timer instead of FreeRTOS timer to implement the callout. */
|
||||
#ifdef CONFIG_BT_OSAL_USE_ESP_TIMER
|
||||
#define BT_OSAL_USE_ESP_TIMER (1)
|
||||
#else
|
||||
#define BT_OSAL_USE_ESP_TIMER (0)
|
||||
#endif
|
||||
|
||||
typedef void bt_osal_event_fn(struct bt_osal_event *ev);
|
||||
|
||||
struct bt_osal_event_freertos {
|
||||
bool queued;
|
||||
bt_osal_event_fn *fn;
|
||||
void *arg;
|
||||
struct bt_osal_event *next; /*!< Next event in the queue's list, or NULL; valid only while @ref queued */
|
||||
};
|
||||
|
||||
struct bt_osal_eventq_freertos {
|
||||
struct bt_osal_event *head; /*!< First event to dequeue, NULL when the queue is empty */
|
||||
struct bt_osal_event *tail; /*!< Last event in the list, NULL when the queue is empty */
|
||||
SemaphoreHandle_t sem; /*!< Binary "work pending" flag waking a blocked eventq_get(); the list is the source of truth, this only signals */
|
||||
portMUX_TYPE lock; /*!< Spinlock protecting head/tail and each event's next (task- and ISR-safe) */
|
||||
TaskHandle_t task; /*!< Handle of the task started to process this event queue, NULL if none */
|
||||
SemaphoreHandle_t done; /*!< Signalled by the worker just before it self-deletes, so eventq_deinit() can wait for a clean exit; NULL if no task */
|
||||
bool stop; /*!< Set by eventq_deinit() to ask the worker to exit at its next safe point (between events) */
|
||||
};
|
||||
|
||||
struct bt_osal_callout_freertos {
|
||||
#if BT_OSAL_USE_ESP_TIMER
|
||||
esp_timer_handle_t handle;
|
||||
#else
|
||||
TimerHandle_t handle;
|
||||
#endif
|
||||
struct bt_osal_eventq *evq;
|
||||
struct bt_osal_event ev;
|
||||
};
|
||||
|
||||
struct bt_osal_mutex_freertos {
|
||||
SemaphoreHandle_t handle;
|
||||
};
|
||||
|
||||
struct bt_osal_sem_freertos {
|
||||
SemaphoreHandle_t handle;
|
||||
};
|
||||
|
||||
typedef void bt_osal_event_fn_freertos(struct bt_osal_event_freertos *ev);
|
||||
|
||||
// Eventq
|
||||
struct bt_osal_event *bt_osal_freertos_eventq_get(struct bt_osal_eventq *evq,
|
||||
bt_osal_time_t tmo);
|
||||
|
||||
void bt_osal_freertos_eventq_put(struct bt_osal_eventq *evq,
|
||||
struct bt_osal_event *ev);
|
||||
|
||||
void bt_osal_freertos_eventq_put_to_front(struct bt_osal_eventq *evq,
|
||||
struct bt_osal_event *ev);
|
||||
|
||||
void bt_osal_freertos_eventq_remove(struct bt_osal_eventq *evq,
|
||||
struct bt_osal_event *ev);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_eventq_start(struct bt_osal_eventq *evq,
|
||||
const struct bt_osal_task_info *info);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_eventq_post_func(struct bt_osal_eventq *evq,
|
||||
bt_osal_event_fn *fn, void *arg);
|
||||
|
||||
// Mutex
|
||||
bt_osal_error_t bt_osal_freertos_mutex_init(struct bt_osal_mutex *mu);
|
||||
bt_osal_error_t bt_osal_freertos_mutex_deinit(struct bt_osal_mutex *mu);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_mutex_pend(struct bt_osal_mutex *mu,
|
||||
bt_osal_time_t timeout);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_mutex_release(struct bt_osal_mutex *mu);
|
||||
|
||||
// Semephore
|
||||
bt_osal_error_t bt_osal_freertos_sem_init(struct bt_osal_sem *sem, uint16_t tokens);
|
||||
bt_osal_error_t bt_osal_freertos_sem_deinit(struct bt_osal_sem *sem);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_sem_pend(struct bt_osal_sem *sem,
|
||||
bt_osal_time_t timeout);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_sem_release(struct bt_osal_sem *sem);
|
||||
|
||||
// Callout
|
||||
bt_osal_error_t bt_osal_freertos_callout_init(struct bt_osal_callout *co,
|
||||
struct bt_osal_eventq *evq,
|
||||
bt_osal_event_fn *ev_cb, void *ev_arg);
|
||||
|
||||
void bt_osal_freertos_callout_deinit(struct bt_osal_callout *co);
|
||||
|
||||
void bt_osal_freertos_callout_stop(struct bt_osal_callout *co);
|
||||
|
||||
bool bt_osal_freertos_callout_is_active(struct bt_osal_callout *co);
|
||||
|
||||
bt_osal_time_t bt_osal_freertos_callout_get_ticks(struct bt_osal_callout *co);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_callout_reset(struct bt_osal_callout *co,
|
||||
bt_osal_time_t ticks);
|
||||
|
||||
bt_osal_time_t bt_osal_freertos_callout_remaining_ticks(struct bt_osal_callout *co,
|
||||
bt_osal_time_t now);
|
||||
|
||||
// Time
|
||||
bt_osal_error_t bt_osal_freertos_time_ms_to_ticks(uint32_t ms,
|
||||
bt_osal_time_t *out_ticks);
|
||||
|
||||
bt_osal_error_t bt_osal_freertos_time_ticks_to_ms(bt_osal_time_t ticks,
|
||||
uint32_t *out_ms);
|
||||
|
||||
// Hardware
|
||||
uint32_t bt_osal_freertos_hw_enter_critical(void);
|
||||
|
||||
void bt_osal_freertos_hw_exit_critical(uint32_t ctx);
|
||||
|
||||
/**
|
||||
* @brief Allocate and populate the OSAL function table
|
||||
*
|
||||
* Must be called before any bt_osal_* API is used; they all dispatch through the
|
||||
* table. Asserts if the table cannot be allocated.
|
||||
*/
|
||||
void bt_osal_freertos_funcs_init(void);
|
||||
|
||||
/**
|
||||
* @brief Free the OSAL function table allocated by bt_osal_freertos_funcs_init()
|
||||
*/
|
||||
void bt_osal_freertos_funcs_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Get the OSAL function table
|
||||
*
|
||||
* @return Pointer to the table, or NULL if bt_osal_freertos_funcs_init() has not
|
||||
* been called (or the table has since been deinitialized)
|
||||
*/
|
||||
struct bt_osal_funcs_t *bt_osal_freertos_funcs_get(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BT_OSAL_FREERTOS_H_ */
|
||||
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*/
|
||||
|
||||
#ifndef _BT_OSAL_OS_H_
|
||||
#define _BT_OSAL_OS_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) \
|
||||
(sizeof(array) / sizeof((array)[0]))
|
||||
#endif
|
||||
|
||||
extern int ets_printf(const char *fmt, ...);
|
||||
#define BT_OSAL_ASSERT(con) \
|
||||
do{ \
|
||||
if(!(con)) { \
|
||||
ets_printf("assertion:%s\n",#con); \
|
||||
ets_printf("line:%d,function:%s\n", __LINE__, __func__);\
|
||||
assert(0); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#define BT_OSAL_OS_ALIGNMENT (4)/*bt_osal_get_os_alignment()*/
|
||||
|
||||
#define BT_OSAL_TIME_FOREVER bt_osal_get_time_forever()
|
||||
|
||||
/* This should be compatible with TickType_t */
|
||||
typedef uint32_t bt_osal_time_t;
|
||||
typedef int32_t bt_osal_stime_t;
|
||||
|
||||
struct bt_osal_event;
|
||||
typedef void bt_osal_event_fn(struct bt_osal_event *ev);
|
||||
|
||||
struct bt_osal_event {
|
||||
void *event;
|
||||
};
|
||||
|
||||
struct bt_osal_eventq {
|
||||
void *eventq;
|
||||
};
|
||||
|
||||
struct bt_osal_callout {
|
||||
void *co;
|
||||
};
|
||||
|
||||
struct bt_osal_mutex {
|
||||
void *mutex;
|
||||
};
|
||||
|
||||
struct bt_osal_sem {
|
||||
void *sem;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Core affinity value meaning "let the scheduler pick any core"
|
||||
*/
|
||||
#define BT_OSAL_TASK_NO_AFFINITY ((BaseType_t)tskNO_AFFINITY)
|
||||
|
||||
/**
|
||||
* @brief Attributes for the task started to service an event queue
|
||||
*
|
||||
* Passed to bt_osal_eventq_start() so each queue's worker task can be given its
|
||||
* own name, priority, stack and core affinity.
|
||||
*/
|
||||
struct bt_osal_task_info {
|
||||
const char *name; /*!< Name of the task */
|
||||
uint8_t prio; /*!< FreeRTOS priority of the task */
|
||||
uint32_t stack_size; /*!< Stack depth of the task, in bytes */
|
||||
BaseType_t core_id; /*!< Core to pin the task to, or BT_OSAL_TASK_NO_AFFINITY to leave it unpinned */
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple APIs are just defined as static inline below, but some are a bit more
|
||||
* complex or require some global state variables and thus are defined in .c
|
||||
* file instead and static inline wrapper just calls proper implementation.
|
||||
* We need declarations of these functions and they are defined in header below.
|
||||
*/
|
||||
#include "bt_osal_freertos.h"
|
||||
|
||||
struct bt_osal_funcs_t {
|
||||
bool (*p_bt_osal_os_started)(void);
|
||||
void *(*p_bt_osal_get_current_task_id)(void);
|
||||
void (*p_bt_osal_eventq_init)(struct bt_osal_eventq *);
|
||||
void (*p_bt_osal_eventq_deinit)(struct bt_osal_eventq *);
|
||||
struct bt_osal_event * (*p_bt_osal_eventq_get)(struct bt_osal_eventq *, bt_osal_time_t);
|
||||
void (*p_bt_osal_eventq_put)(struct bt_osal_eventq *, struct bt_osal_event *);
|
||||
void (*p_bt_osal_eventq_remove)(struct bt_osal_eventq *, struct bt_osal_event *);
|
||||
void (*p_bt_osal_event_run)(struct bt_osal_event *);
|
||||
bool (*p_bt_osal_eventq_is_empty)(struct bt_osal_eventq *);
|
||||
void (*p_bt_osal_event_init)(struct bt_osal_event *, bt_osal_event_fn *, void *);
|
||||
void (*p_bt_osal_event_deinit)(struct bt_osal_event *);
|
||||
void (*p_bt_osal_event_reset)(struct bt_osal_event *);
|
||||
bool (*p_bt_osal_event_is_queued)(struct bt_osal_event *);
|
||||
void * (*p_bt_osal_event_get_arg)(struct bt_osal_event *);
|
||||
void (*p_bt_osal_event_set_arg)(struct bt_osal_event *, void *);
|
||||
bt_osal_error_t (*p_bt_osal_mutex_init)(struct bt_osal_mutex *);
|
||||
bt_osal_error_t (*p_bt_osal_mutex_deinit)(struct bt_osal_mutex *);
|
||||
bt_osal_error_t (*p_bt_osal_mutex_pend)(struct bt_osal_mutex *, bt_osal_time_t);
|
||||
bt_osal_error_t (*p_bt_osal_mutex_release)(struct bt_osal_mutex *);
|
||||
bt_osal_error_t (*p_bt_osal_sem_init)(struct bt_osal_sem *, uint16_t);
|
||||
bt_osal_error_t (*p_bt_osal_sem_deinit)(struct bt_osal_sem *);
|
||||
bt_osal_error_t (*p_bt_osal_sem_pend)(struct bt_osal_sem *, bt_osal_time_t);
|
||||
bt_osal_error_t (*p_bt_osal_sem_release)(struct bt_osal_sem *);
|
||||
uint16_t (*p_bt_osal_sem_get_count)(struct bt_osal_sem *);
|
||||
bt_osal_error_t (*p_bt_osal_callout_init)(struct bt_osal_callout *, struct bt_osal_eventq *, bt_osal_event_fn *, void *);
|
||||
bt_osal_error_t (*p_bt_osal_callout_reset)(struct bt_osal_callout *, bt_osal_time_t);
|
||||
void (*p_bt_osal_callout_stop)(struct bt_osal_callout *);
|
||||
void (*p_bt_osal_callout_deinit)(struct bt_osal_callout *);
|
||||
void (*p_bt_osal_callout_mem_reset)(struct bt_osal_callout *);
|
||||
bool (*p_bt_osal_callout_is_active)(struct bt_osal_callout *);
|
||||
bt_osal_time_t (*p_bt_osal_callout_get_ticks)(struct bt_osal_callout *);
|
||||
uint32_t (*p_bt_osal_callout_remaining_ticks)(struct bt_osal_callout *, bt_osal_time_t);
|
||||
void (*p_bt_osal_callout_set_arg)(struct bt_osal_callout *, void *);
|
||||
uint32_t (*p_bt_osal_time_get)(void);
|
||||
bt_osal_error_t (*p_bt_osal_time_ms_to_ticks)(uint32_t ms, bt_osal_time_t *);
|
||||
bt_osal_error_t (*p_bt_osal_time_ticks_to_ms)(bt_osal_time_t, uint32_t *);
|
||||
bt_osal_time_t (*p_bt_osal_time_ms_to_ticks32)(uint32_t);
|
||||
uint32_t (*p_bt_osal_time_ticks_to_ms32)(bt_osal_time_t);
|
||||
void (*p_bt_osal_time_delay)(bt_osal_time_t);
|
||||
void (*p_bt_osal_hw_set_isr)(int, uint32_t);
|
||||
uint32_t (*p_bt_osal_hw_enter_critical)(void);
|
||||
void (*p_bt_osal_hw_exit_critical)(uint32_t);
|
||||
uint32_t (*p_bt_osal_get_time_forever)(void);
|
||||
uint8_t (*p_bt_osal_hw_is_in_critical)(void);
|
||||
void (*p_bt_osal_eventq_put_to_front)(struct bt_osal_eventq *, struct bt_osal_event *);
|
||||
bt_osal_error_t (*p_bt_osal_eventq_start)(struct bt_osal_eventq *evq, const struct bt_osal_task_info *info);
|
||||
bt_osal_error_t (*p_bt_osal_eventq_post_func)(struct bt_osal_eventq *evq, bt_osal_event_fn *fn, void *arg);
|
||||
};
|
||||
|
||||
extern struct bt_osal_funcs_t *bt_osal_funcs;
|
||||
|
||||
static inline bool
|
||||
IRAM_ATTR bt_osal_os_started(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_os_started();
|
||||
}
|
||||
|
||||
static inline void *
|
||||
IRAM_ATTR bt_osal_get_current_task_id(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_get_current_task_id();
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_eventq_init(struct bt_osal_eventq *evq)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_init(evq);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_eventq_deinit(struct bt_osal_eventq *evq)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_deinit(evq);
|
||||
}
|
||||
|
||||
static inline struct bt_osal_event *
|
||||
IRAM_ATTR bt_osal_eventq_get(struct bt_osal_eventq *evq, bt_osal_time_t tmo)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_get(evq, tmo);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_eventq_put(struct bt_osal_eventq *evq, struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_put(evq, ev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_eventq_put_to_front(struct bt_osal_eventq *evq, struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_put_to_front(evq, ev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_eventq_remove(struct bt_osal_eventq *evq, struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_remove(evq, ev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_event_run(struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_run(ev);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IRAM_ATTR bt_osal_eventq_is_empty(struct bt_osal_eventq *evq)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_is_empty(evq);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_event_init(struct bt_osal_event *ev, bt_osal_event_fn *fn,
|
||||
void *arg)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_init(ev, fn, arg);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IRAM_ATTR bt_osal_event_is_queued(struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_is_queued(ev);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
IRAM_ATTR bt_osal_event_get_arg(struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_get_arg(ev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_event_set_arg(struct bt_osal_event *ev, void *arg)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_set_arg(ev, arg);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_mutex_init(struct bt_osal_mutex *mu)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_mutex_init(mu);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_mutex_deinit(struct bt_osal_mutex *mu)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_mutex_deinit(mu);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_mutex_pend(struct bt_osal_mutex *mu, bt_osal_time_t timeout)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_mutex_pend(mu, timeout);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_mutex_release(struct bt_osal_mutex *mu)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_mutex_release(mu);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_sem_init(struct bt_osal_sem *sem, uint16_t tokens)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_sem_init(sem, tokens);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_sem_deinit(struct bt_osal_sem *sem)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_sem_deinit(sem);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_sem_pend(struct bt_osal_sem *sem, bt_osal_time_t timeout)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_sem_pend(sem, timeout);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_sem_release(struct bt_osal_sem *sem)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_sem_release(sem);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
IRAM_ATTR bt_osal_sem_get_count(struct bt_osal_sem *sem)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_sem_get_count(sem);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_callout_init(struct bt_osal_callout *co, struct bt_osal_eventq *evq,
|
||||
bt_osal_event_fn *ev_cb, void *ev_arg)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_init(co, evq, ev_cb, ev_arg);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_callout_deinit(struct bt_osal_callout *co)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_deinit(co);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_callout_reset(struct bt_osal_callout *co, bt_osal_time_t ticks)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_reset(co, ticks);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_callout_stop(struct bt_osal_callout *co)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_stop(co);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IRAM_ATTR bt_osal_callout_is_active(struct bt_osal_callout *co)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_is_active(co);
|
||||
}
|
||||
|
||||
static inline bt_osal_time_t
|
||||
IRAM_ATTR bt_osal_callout_get_ticks(struct bt_osal_callout *co)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_get_ticks(co);
|
||||
}
|
||||
|
||||
static inline bt_osal_time_t
|
||||
IRAM_ATTR bt_osal_callout_remaining_ticks(struct bt_osal_callout *co,
|
||||
bt_osal_time_t time)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_remaining_ticks(co, time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_callout_set_arg(struct bt_osal_callout *co, void *arg)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_set_arg(co, arg);
|
||||
}
|
||||
|
||||
static inline bt_osal_time_t
|
||||
IRAM_ATTR bt_osal_time_get(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_get();
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_time_ms_to_ticks(uint32_t ms, bt_osal_time_t *out_ticks)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_ms_to_ticks(ms, out_ticks);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_time_ticks_to_ms(bt_osal_time_t ticks, uint32_t *out_ms)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_ticks_to_ms(ticks, out_ms);
|
||||
}
|
||||
|
||||
static inline bt_osal_time_t
|
||||
IRAM_ATTR bt_osal_time_ms_to_ticks32(uint32_t ms)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_ms_to_ticks32(ms);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
IRAM_ATTR bt_osal_time_ticks_to_ms32(bt_osal_time_t ticks)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_ticks_to_ms32(ticks);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_time_delay(bt_osal_time_t ticks)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_time_delay(ticks);
|
||||
}
|
||||
|
||||
#if NIMBLE_CFG_CONTROLLER
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_hw_set_isr(int irqn, uint32_t addr)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_hw_set_isr(irqn, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint32_t
|
||||
IRAM_ATTR bt_osal_hw_enter_critical(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_hw_enter_critical();
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_hw_exit_critical(uint32_t ctx)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_hw_exit_critical(ctx);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IRAM_ATTR bt_osal_hw_is_in_critical(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_hw_is_in_critical();
|
||||
}
|
||||
|
||||
static inline bt_osal_time_t
|
||||
IRAM_ATTR bt_osal_get_time_forever(void)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_get_time_forever();
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_callout_mem_reset(struct bt_osal_callout *co)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_callout_mem_reset(co);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_event_deinit(struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_deinit(ev);
|
||||
}
|
||||
|
||||
static inline void
|
||||
IRAM_ATTR bt_osal_event_reset(struct bt_osal_event *ev)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_event_reset(ev);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_eventq_start(struct bt_osal_eventq *evq, const struct bt_osal_task_info *info)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_start(evq, info);
|
||||
}
|
||||
|
||||
static inline bt_osal_error_t
|
||||
IRAM_ATTR bt_osal_eventq_post_func(struct bt_osal_eventq *evq, bt_osal_event_fn *fn, void *arg)
|
||||
{
|
||||
return bt_osal_funcs->p_bt_osal_eventq_post_func(evq, fn, arg);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BT_OSAL_OS_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user