Update bt fork to be based on v5.3

This commit is contained in:
jacqueline
2024-08-13 06:02:54 +00:00
committed by cooljqln
parent be9725c1c7
commit 5a02f34ed9
508 changed files with 42429 additions and 5168 deletions
+315
View File
@@ -0,0 +1,315 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef H_HCI_TRANSPORT_
#define H_HCI_TRANSPORT_
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#include "os/os_mempool.h"
#define BLE_HCI_TRANS_CMD_SZ 260
/*** Type of buffers for holding commands and events. */
/**
* Controller-to-host event buffers. Events have one of two priorities:
* o Low-priority (BLE_HCI_TRANS_BUF_EVT_LO)
* o High-priority (BLE_HCI_TRANS_BUF_EVT_HI)
*
* Low-priority event buffers are only used for advertising reports. If there
* are no free low-priority event buffers, then an incoming advertising report
* will get dropped.
*
* High-priority event buffers are for everything except advertising reports.
* If there are no free high-priority event buffers, a request to allocate one
* will try to allocate a low-priority buffer instead.
*
* If you want all events to be given equal treatment, then you should allocate
* low-priority events only.
*
* Event priorities solve the problem of critical events getting dropped due to
* a flood of advertising reports. This solution is likely temporary: when
* HCI flow control is added, event priorities may become obsolete.
*
* Not all transports distinguish between low and high priority events. If the
* transport does not have separate settings for low and high buffer counts,
* then it treats all events with equal priority.
*/
#define BLE_HCI_TRANS_BUF_EVT_LO 1
#define BLE_HCI_TRANS_BUF_EVT_HI 2
/* Host-to-controller command. */
#define BLE_HCI_TRANS_BUF_CMD 3
/** Callback function types; executed when HCI packets are received. */
typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD)
#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI)
#define ble_transport_free ble_hci_trans_buf_free
struct ble_hci_trans_funcs_t {
int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om);
int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd);
int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om);
int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev);
int(*_ble_hci_trans_reset)(void);
int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb, void *arg);
};
extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr;
/**
* Sends an HCI event from the controller to the host.
*
* @param cmd The HCI event to send. This buffer must be
* allocated via ble_hci_trans_buf_alloc().
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx
/**
* Sends ACL data from controller to host.
*
* @param om The ACL data packet to send.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx
/**
* Sends an HCI command from the host to the controller.
*
* @param cmd The HCI command to send. This buffer must be
* allocated via ble_hci_trans_buf_alloc().
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx
/**
* Sends ACL data from host to controller.
*
* @param om The ACL data packet to send.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx
/**
* Allocates a flat buffer of the specified type.
*
* @param type The type of buffer to allocate; one of the
* BLE_HCI_TRANS_BUF_[...] constants.
*
* @return The allocated buffer on success;
* NULL on buffer exhaustion.
*/
extern uint8_t *r_ble_hci_trans_buf_alloc(int type);
#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc
/**
* Frees the specified flat buffer. The buffer must have been allocated via
* ble_hci_trans_buf_alloc().
*
* @param buf The buffer to free.
*/
extern void r_ble_hci_trans_buf_free(uint8_t *buf);
#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free
/**
* Configures a callback to get executed whenever an ACL data packet is freed.
* The function is called immediately before the free occurs.
*
* @param cb The callback to configure.
* @param arg An optional argument to pass to the callback.
*
* @return 0 on success;
* BLE_ERR_UNSUPPORTED if the transport does not
* support this operation.
*/
extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb
/**
* Configures the HCI transport to operate with a controller. The transport
* will execute specified callbacks upon receiving HCI packets from the host.
*
* @param cmd_cb The callback to execute upon receiving an HCI
* command.
* @param cmd_arg Optional argument to pass to the command
* callback.
* @param acl_cb The callback to execute upon receiving ACL
* data.
* @param acl_arg Optional argument to pass to the ACL
* callback.
*/
extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
void *cmd_arg,
ble_hci_trans_rx_acl_fn *acl_cb,
void *acl_arg);
#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll
/**
* Configures the HCI transport to operate with a host. The transport will
* execute specified callbacks upon receiving HCI packets from the controller.
*
* @param evt_cb The callback to execute upon receiving an HCI
* event.
* @param evt_arg Optional argument to pass to the event
* callback.
* @param acl_cb The callback to execute upon receiving ACL
* data.
* @param acl_arg Optional argument to pass to the ACL
* callback.
*/
extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
void *evt_arg,
ble_hci_trans_rx_acl_fn *acl_cb,
void *acl_arg);
#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs
/**
* Resets the HCI module to a clean state. Frees all buffers and reinitializes
* the underlying transport.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
extern int r_ble_hci_trans_reset(void);
#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset
void esp_ble_hci_trans_init(uint8_t);
#else
/**
* Sends an HCI event from the controller to the host.
*
* @param cmd The HCI event to send. This buffer must be
* allocated via ble_hci_trans_buf_alloc().
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev);
/**
* Sends ACL data from controller to host.
*
* @param om The ACL data packet to send.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int ble_hci_trans_ll_acl_tx(struct os_mbuf *om);
/**
* Sends an HCI command from the host to the controller.
*
* @param cmd The HCI command to send. This buffer must be
* allocated via ble_hci_trans_buf_alloc().
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
/**
* Sends ACL data from host to controller.
*
* @param om The ACL data packet to send.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
/**
* Allocates a flat buffer of the specified type.
*
* @param type The type of buffer to allocate; one of the
* BLE_HCI_TRANS_BUF_[...] constants.
*
* @return The allocated buffer on success;
* NULL on buffer exhaustion.
*/
int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd);
/**
* Sends ACL data from host to controller.
*
* @param om The ACL data packet to send.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om);
/**
* Allocates a flat buffer of the specified type.
*
* @param type The type of buffer to allocate; one of the
* BLE_HCI_TRANS_BUF_[...] constants.
*
* @return The allocated buffer on success;
* NULL on buffer exhaustion.
*/
uint8_t *esp_ble_hci_trans_buf_alloc(int type);
/**
* Frees the specified flat buffer. The buffer must have been allocated via
* ble_hci_trans_buf_alloc().
*
* @param buf The buffer to free.
*/
void esp_ble_hci_trans_buf_free(uint8_t *buf);
/**
* Configures the HCI transport to operate with a host. The transport will
* execute specified callbacks upon receiving HCI packets from the controller.
*
* @param evt_cb The callback to execute upon receiving an HCI
* event.
* @param evt_arg Optional argument to pass to the event
* callback.
* @param acl_cb The callback to execute upon receiving ACL
* data.
* @param acl_arg Optional argument to pass to the ACL
* callback.
*/
void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb,
void *evt_arg,
ble_hci_trans_rx_acl_fn *acl_cb,
void *acl_arg);
/**
* Resets the HCI module to a clean state. Frees all buffers and reinitializes
* the underlying transport.
*
* @return 0 on success;
* A BLE_ERR_[...] error code on failure.
*/
int esp_ble_hci_trans_reset(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* H_HCI_TRANSPORT_ */
+21
View File
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
void *bt_osi_mem_malloc(size_t size);
void *bt_osi_mem_calloc(size_t n, size_t size);
void *bt_osi_mem_malloc_internal(size_t size);
void *bt_osi_mem_calloc_internal(size_t n, size_t size);
void bt_osi_mem_free(void *ptr);
+296
View File
@@ -0,0 +1,296 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_ENDIAN_
#define H_ENDIAN_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Internal helpers */
#ifndef os_bswap_64
#define os_bswap_64(x) ((uint64_t) \
((((x) & 0xff00000000000000ull) >> 56) | \
(((x) & 0x00ff000000000000ull) >> 40) | \
(((x) & 0x0000ff0000000000ull) >> 24) | \
(((x) & 0x000000ff00000000ull) >> 8) | \
(((x) & 0x00000000ff000000ull) << 8) | \
(((x) & 0x0000000000ff0000ull) << 24) | \
(((x) & 0x000000000000ff00ull) << 40) | \
(((x) & 0x00000000000000ffull) << 56)))
#endif
#ifndef os_bswap_32
#define os_bswap_32(x) ((uint32_t) \
((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24)))
#endif
#ifndef os_bswap_16
#define os_bswap_16(x) ((uint16_t) \
((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8)))
#endif
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#ifndef ntohll
#define ntohll(x) ((uint64_t)(x))
#endif
#ifndef htonll
#define htonll(x) ((uint64_t)(x))
#endif
#ifndef ntohl
#define ntohl(x) ((uint32_t)(x))
#endif
#ifndef htonl
#define htonl(x) ((uint32_t)(x))
#endif
#ifndef ntohs
#define ntohs(x) ((uint16_t)(x))
#endif
#ifndef htons
#define htons(x) ((uint16_t)(x))
#endif
#ifndef htobe16
#define htobe16(x) ((uint16_t)(x))
#endif
#ifndef htole16
#define htole16(x) os_bswap_16 (x)
#endif
#ifndef be16toh
#define be16toh(x) ((uint16_t)(x))
#endif
#ifndef le16toh
#define le16toh(x) os_bswap_16 (x)
#endif
#ifndef htobe32
#define htobe32(x) ((uint32_t)(x))
#endif
#ifndef htole32
#define htole32(x) os_bswap_32 (x)
#endif
#ifndef be32toh
#define be32toh(x) ((uint32_t)(x))
#endif
#ifndef le32toh
#define le32toh(x) os_bswap_32 (x)
#endif
#ifndef htobe64
#define htobe64(x) ((uint64_t)(x))
#endif
#ifndef htole64
#define htole64(x) os_bswap_64 (x)
#endif
#ifndef be64toh
#define be64toh(x) ((uint64_t)(x))
#endif
#ifndef le64toh
#define le64toh(x) os_bswap_64 (x)
#endif
#else
#ifndef ntohll
#define ntohll(x) os_bswap_64(x)
#endif
#ifndef htonll
#define htonll ntohll
#endif
/* These are not used in NimBLE and ESP-IDF uses them from LwIP */
#if 0
#ifndef ntohl
#define ntohl(x) os_bswap_32(x)
#endif
#ifndef htonl
#define htonl ntohl
#endif
#ifndef htons
#define htons(x) os_bswap_16(x)
#endif
#ifndef ntohs
#define ntohs htons
#endif
#endif
#ifndef htobe16
#define htobe16(x) os_bswap_16(x)
#endif
#ifndef htole16
#define htole16(x) ((uint16_t)(x))
#endif
#ifndef be16toh
#define be16toh(x) os_bswap_16(x)
#endif
#ifndef le16toh
#define le16toh(x) ((uint16_t)(x))
#endif
#ifndef htobe32
#define htobe32(x) os_bswap_32(x)
#endif
#ifndef htole32
#define htole32(x) ((uint32_t)(x))
#endif
#ifndef be32toh
#define be32toh(x) os_bswap_32(x)
#endif
#ifndef le32toh
#define le32toh(x) ((uint32_t)(x))
#endif
#ifndef htobe64
#define htobe64(x) os_bswap_64(x)
#endif
#ifndef htole64
#define htole64(x) ((uint64_t)(x))
#endif
#ifndef be64toh
#define be64toh(x) os_bswap_64(x)
#endif
#ifndef le64toh
#define le64toh(x) ((uint64_t)(x))
#endif
#endif
#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
void r_put_le16(void *buf, uint16_t x);
#define put_le16 r_put_le16
void r_put_le24(void *buf, uint32_t x);
#define put_le24 r_put_le24
void r_put_le32(void *buf, uint32_t x);
#define put_le32 r_put_le32
void r_put_le64(void *buf, uint64_t x);
#define put_le64 r_put_le64
uint16_t r_get_le16(const void *buf);
#define get_le16 r_get_le16
uint32_t r_get_le24(const void *buf);
#define get_le24 r_get_le24
uint32_t r_get_le32(const void *buf);
#define get_le32 r_get_le32
uint64_t r_get_le64(const void *buf);
#define get_le64 r_get_le64
void r_put_be16(void *buf, uint16_t x);
#define put_be16 r_put_be16
void r_put_be24(void *buf, uint32_t x);
#define put_be24 r_put_be24
void r_put_be32(void *buf, uint32_t x);
#define put_be32 r_put_be32
void r_put_be64(void *buf, uint64_t x);
#define put_be64 r_put_be64
uint16_t r_get_be16(const void *buf);
#define get_be16 r_get_be16
uint32_t r_get_be24(const void *buf);
#define get_be24 r_get_be24
uint32_t r_get_be32(const void *buf);
#define get_be32 r_get_be32
uint64_t r_get_be64(const void *buf);
#define get_be64 r_get_be64
void r_swap_in_place(void *buf, int len);
#define swap_in_place r_swap_in_place
void r_swap_buf(uint8_t *dst, const uint8_t *src, int len);
#define swap_buf r_swap_buf
#else
void put_le16(void *buf, uint16_t x);
void put_le24(void *buf, uint32_t x);
void put_le32(void *buf, uint32_t x);
void put_le64(void *buf, uint64_t x);
uint16_t get_le16(const void *buf);
uint32_t get_le24(const void *buf);
uint32_t get_le32(const void *buf);
uint64_t get_le64(const void *buf);
void put_be16(void *buf, uint16_t x);
void put_be24(void *buf, uint32_t x);
void put_be32(void *buf, uint32_t x);
void put_be64(void *buf, uint64_t x);
uint16_t get_be16(const void *buf);
uint32_t get_be24(const void *buf);
uint32_t get_be32(const void *buf);
uint64_t get_be64(const void *buf);
void swap_in_place(void *buf, int len);
void swap_buf(uint8_t *dst, const uint8_t *src, int len);
#endif
#ifdef __cplusplus
}
#endif
#endif
+66
View File
@@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _OS_H
#define _OS_H
#include <assert.h>
#include "esp_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !defined __cplusplus && !defined static_assert
#define static_assert _Static_assert
#endif
#include "nimble/nimble_npl.h"
#define OS_ALIGN(__n, __a) ( \
(((__n) & ((__a) - 1)) == 0) ? \
(__n) : \
((__n) + ((__a) - ((__n) & ((__a) - 1)))) \
)
#define OS_ALIGNMENT (BLE_NPL_OS_ALIGNMENT)
typedef uint32_t os_sr_t;
#define OS_ENTER_CRITICAL(_sr) (_sr = ble_npl_hw_enter_critical())
#define OS_EXIT_CRITICAL(_sr) (ble_npl_hw_exit_critical(_sr))
#define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical())
/* Mynewt components (not abstracted in NPL) */
#include "os/endian.h"
#include "os/queue.h"
#include "os/os_error.h"
#include "os/os_mbuf.h"
#include "os/os_mempool.h"
#ifdef __cplusplus
}
#endif
#endif /* _OS_H */
+69
View File
@@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_OS_ERROR_
#define H_OS_ERROR_
#include "os/os.h"
#ifdef __cplusplus
extern "C" {
#endif
/* OS error enumerations */
enum os_error {
OS_OK = 0,
OS_ENOMEM = 1,
OS_EINVAL = 2,
OS_INVALID_PARM = 3,
OS_MEM_NOT_ALIGNED = 4,
OS_BAD_MUTEX = 5,
OS_TIMEOUT = 6,
OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */
OS_ERR_PRIV = 8, /* Privileged access error */
OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */
OS_ENOENT = 10, /* No such thing */
OS_EBUSY = 11, /* Resource busy */
OS_ERROR = 12, /* Generic Error */
};
typedef enum os_error os_error_t;
/**
* @brief Converts an OS error code (`OS_[...]`) to an equivalent system error
* code (`SYS_E[...]`).
*
* @param os_error The OS error code to convert.
*
* @return The equivalent system error code.
*/
int os_error_to_sys(os_error_t os_error);
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
+407
View File
@@ -0,0 +1,407 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @addtogroup OSKernel
* @{
* @defgroup OSMempool Memory Pools
* @{
*/
#ifndef _OS_MEMPOOL_H_
#define _OS_MEMPOOL_H_
#include <stdbool.h>
#include "os/os.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* A memory block structure. This simply contains a pointer to the free list
* chain and is only used when the block is on the free list. When the block
* has been removed from the free list the entire memory block is usable by the
* caller.
*/
struct os_memblock {
SLIST_ENTRY(os_memblock) mb_next;
};
/* XXX: Change this structure so that we keep the first address in the pool? */
/* XXX: add memory debug structure and associated code */
/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
SLIST_HEAD(,os_memblock) mp_head; */
/**
* Memory pool
*/
struct os_mempool {
/** Size of the memory blocks, in bytes. */
uint32_t mp_block_size;
/** The number of memory blocks. */
uint16_t mp_num_blocks;
/** The number of free blocks left */
uint16_t mp_num_free;
/** The lowest number of free blocks seen */
uint16_t mp_min_free;
/** Bitmap of OS_MEMPOOL_F_[...] values. */
uint8_t mp_flags;
/** Address of memory buffer used by pool */
uint32_t mp_membuf_addr;
STAILQ_ENTRY(os_mempool) mp_list;
SLIST_HEAD(,os_memblock);
/** Name for memory block */
const char *name;
};
/**
* Indicates an extended mempool. Address can be safely cast to
* (struct os_mempool_ext *).
*/
#define OS_MEMPOOL_F_EXT 0x01
struct os_mempool_ext;
/**
* Block put callback function. If configured, this callback gets executed
* whenever a block is freed to the corresponding extended mempool. Note: The
* os_memblock_put() function calls this callback instead of freeing the block
* itself. Therefore, it is the callback's responsibility to free the block
* via a call to os_memblock_put_from_cb().
*
* @param ome The extended mempool that a block is being
* freed back to.
* @param data The block being freed.
* @param arg Optional argument configured along with the
* callback.
*
* @return Indicates whether the block was successfully
* freed. A non-zero value should only be
* returned if the block was not successfully
* released back to its pool.
*/
typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data,
void *arg);
struct os_mempool_ext {
struct os_mempool mpe_mp;
/* Callback that is executed immediately when a block is freed. */
os_mempool_put_fn *mpe_put_cb;
void *mpe_put_arg;
};
#define OS_MEMPOOL_INFO_NAME_LEN (32)
/**
* Information describing a memory pool, used to return OS information
* to the management layer.
*/
struct os_mempool_info {
/** Size of the memory blocks in the pool */
int omi_block_size;
/** Number of memory blocks in the pool */
int omi_num_blocks;
/** Number of free memory blocks */
int omi_num_free;
/** Minimum number of free memory blocks ever */
int omi_min_free;
/** Name of the memory pool */
char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
};
/**
* Get information about the next system memory pool.
*
* @param mempool The current memory pool, or NULL if starting iteration.
* @param info A pointer to the structure to return memory pool information
* into.
*
* @return The next memory pool in the list to get information about, or NULL
* when at the last memory pool.
*/
struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
struct os_mempool_info *);
#if (OS_ALIGNMENT == 4)
typedef uint32_t os_membuf_t;
#elif (OS_ALIGNMENT == 8)
typedef uint64_t os_membuf_t;
#elif (OS_ALIGNMENT == 16)
typedef __uint128_t os_membuf_t;
#else
#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`"
#endif /* OS_ALIGNMENT == * */
#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n))
/** Calculates the number of bytes required to initialize a memory pool. */
#define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
/**
* Initialize a memory pool.
*
* @param mp Pointer to a pointer to a mempool
* @param blocks The number of blocks in the pool
* @param blocks_size The size of the block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
#define os_mempool_init r_os_mempool_init
/**
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
* are not specified when this function is called; they are assigned manually
* after initialization.
*
* @param mpe The extended memory pool to initialize.
* @param blocks The number of blocks in the pool.
* @param block_size The size of each block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
#define os_mempool_ext_init r_os_mempool_ext_init
/**
* Removes the specified mempool from the list of initialized mempools.
*
* @param mp The mempool to unregister.
*
* @return 0 on success;
* OS_INVALID_PARM if the mempool is not
* registered.
*/
os_error_t r_os_mempool_unregister(struct os_mempool *mp);
#define os_mempool_unregister r_os_mempool_unregister
/**
* Clears a memory pool.
*
* @param mp The mempool to clear.
*
* @return os_error_t
*/
os_error_t r_os_mempool_clear(struct os_mempool *mp);
#define os_mempool_clear r_os_mempool_clear
/**
* Performs an integrity check of the specified mempool. This function
* attempts to detect memory corruption in the specified memory pool.
*
* @param mp The mempool to check.
*
* @return true if the memory pool passes the integrity
* check;
* false if the memory pool is corrupt.
*/
bool r_os_mempool_is_sane(const struct os_mempool *mp);
#define os_mempool_is_sane r_os_mempool_is_sane
/**
* Checks if a memory block was allocated from the specified mempool.
*
* @param mp The mempool to check as parent.
* @param block_addr The memory block to check as child.
*
* @return 0 if the block does not belong to the mempool;
* 1 if the block does belong to the mempool.
*/
int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr);
#define os_memblock_from r_os_memblock_from
/**
* Get a memory block from a memory pool
*
* @param mp Pointer to the memory pool
*
* @return void* Pointer to block if available; NULL otherwise
*/
void *r_os_memblock_get(struct os_mempool *mp);
#define os_memblock_get r_os_memblock_get
/**
* Puts the memory block back into the pool, ignoring the put callback, if any.
* This function should only be called from a put callback to free a block
* without causing infinite recursion.
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
#define os_memblock_put_from_cb r_os_memblock_put_from_cb
/**
* Puts the memory block back into the pool
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr);
#define os_memblock_put r_os_memblock_put
#else
/**
* Initialize a memory pool.
*
* @param mp Pointer to a pointer to a mempool
* @param blocks The number of blocks in the pool
* @param blocks_size The size of the block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
/**
* Initializes an extended memory pool. Extended attributes (e.g., callbacks)
* are not specified when this function is called; they are assigned manually
* after initialization.
*
* @param mpe The extended memory pool to initialize.
* @param blocks The number of blocks in the pool.
* @param block_size The size of each block, in bytes.
* @param membuf Pointer to memory to contain blocks.
* @param name Name of the pool.
*
* @return os_error_t
*/
os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks,
uint32_t block_size, void *membuf, const char *name);
/**
* Removes the specified mempool from the list of initialized mempools.
*
* @param mp The mempool to unregister.
*
* @return 0 on success;
* OS_INVALID_PARM if the mempool is not
* registered.
*/
os_error_t os_mempool_unregister(struct os_mempool *mp);
/**
* Clears a memory pool.
*
* @param mp The mempool to clear.
*
* @return os_error_t
*/
os_error_t os_mempool_clear(struct os_mempool *mp);
/**
* Clears an extended memory pool.
*
* @param mpe The extended memory pool to clear.
*
* @return os_error_t
*/
os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe);
/**
* Performs an integrity check of the specified mempool. This function
* attempts to detect memory corruption in the specified memory pool.
*
* @param mp The mempool to check.
*
* @return true if the memory pool passes the integrity
* check;
* false if the memory pool is corrupt.
*/
bool os_mempool_is_sane(const struct os_mempool *mp);
/**
* Checks if a memory block was allocated from the specified mempool.
*
* @param mp The mempool to check as parent.
* @param block_addr The memory block to check as child.
*
* @return 0 if the block does not belong to the mempool;
* 1 if the block does belong to the mempool.
*/
int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
/**
* Get a memory block from a memory pool
*
* @param mp Pointer to the memory pool
*
* @return void* Pointer to block if available; NULL otherwise
*/
void *os_memblock_get(struct os_mempool *mp);
/**
* Puts the memory block back into the pool, ignoring the put callback, if any.
* This function should only be called from a put callback to free a block
* without causing infinite recursion.
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr);
/**
* Puts the memory block back into the pool
*
* @param mp Pointer to memory pool
* @param block_addr Pointer to memory block
*
* @return os_error_t
*/
os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _OS_MEMPOOL_H_ */
/**
* @} OSMempool
* @} OSKernel
*/
+212
View File
@@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef _QUEUE_H_
#define _QUEUE_H_
/* The common BSD linked list queue macros are already defined here for ESP-IDF */
#include <sys/queue.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This file defines circular queues. The other types of data structures:
* singly-linked lists, singly-linked tail queues, lists and tail queues
* are used from sys/queue.h
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A singly-linked tail queue is headed by a pair of pointers, one to the
* head of the list and the other to the tail of the list. The elements are
* singly linked for minimum space and pointer manipulation overhead at the
* expense of O(n) removal for arbitrary elements. New elements can be added
* to the list after an existing element, at the head of the list, or at the
* end of the list. Elements being removed from the head of the tail queue
* should use the explicit macro for this purpose for optimum efficiency.
* A singly-linked tail queue may only be traversed in the forward direction.
* Singly-linked tail queues are ideal for applications with large datasets
* and few or no removals or for implementing a FIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*
*
* SLIST LIST STAILQ TAILQ CIRCLEQ
* _HEAD + + + + +
* _HEAD_INITIALIZER + + + + +
* _ENTRY + + + + +
* _INIT + + + + +
* _EMPTY + + + + +
* _FIRST + + + + +
* _NEXT + + + + +
* _PREV - - - + +
* _LAST - - + + +
* _FOREACH + + + + +
* _FOREACH_REVERSE - - - + +
* _INSERT_HEAD + + + + +
* _INSERT_BEFORE - + - + +
* _INSERT_AFTER + + + + +
* _INSERT_TAIL - - + + +
* _REMOVE_HEAD + - + - -
* _REMOVE + + + + +
*
*/
/*
* Circular queue declarations.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ (void *)&(head), (void *)&(head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue functions.
*/
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_FOREACH(var, head, field) \
for ((var) = CIRCLEQ_FIRST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_NEXT((var), field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for ((var) = CIRCLEQ_LAST((head)); \
(var) != (void *)(head) || ((var) = NULL); \
(var) = CIRCLEQ_PREV((var), field))
#define CIRCLEQ_INIT(head) do { \
CIRCLEQ_FIRST((head)) = (void *)(head); \
CIRCLEQ_LAST((head)) = (void *)(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \
CIRCLEQ_PREV((elm), field) = (listelm); \
if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
CIRCLEQ_NEXT((listelm), field) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (listelm); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \
if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
CIRCLEQ_PREV((listelm), field) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \
CIRCLEQ_PREV((elm), field) = (void *)(head); \
if (CIRCLEQ_LAST((head)) == (void *)(head)) \
CIRCLEQ_LAST((head)) = (elm); \
else \
CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \
CIRCLEQ_FIRST((head)) = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
CIRCLEQ_NEXT((elm), field) = (void *)(head); \
CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \
if (CIRCLEQ_FIRST((head)) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = (elm); \
else \
CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \
CIRCLEQ_LAST((head)) = (elm); \
} while (0)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \
CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \
else \
CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \
CIRCLEQ_PREV((elm), field); \
if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \
CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \
else \
CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \
CIRCLEQ_NEXT((elm), field); \
} while (0)
#ifdef __cplusplus
}
#endif
#endif /* !_SYS_QUEUE_H_ */
+45
View File
@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_OS_UTIL_
#define H_OS_UTIL_
/* Helpers to pass integers as pointers and vice-versa */
#define POINTER_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
#define UINT_TO_POINTER(u) ((void *) ((uintptr_t) (u)))
#define POINTER_TO_INT(p) ((int) ((intptr_t) (p)))
#define INT_TO_POINTER(u) ((void *) ((intptr_t) (u)))
/* Helper to retrieve pointer to "parent" object in structure */
#define CONTAINER_OF(ptr, type, field) \
((type *)(((char *)(ptr)) - offsetof(type, field)))
/* Helper to calculate number of elements in array */
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(array) \
(sizeof(array) / sizeof((array)[0]))
#endif
#endif
+240
View File
@@ -0,0 +1,240 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
#include <assert.h>
#include "os/os.h"
#include "mem_api.h"
#include "bt_osi_mem.h"
#include "esp_err.h"
#if CONFIG_BT_NIMBLE_ENABLED
#include "syscfg/syscfg.h"
#endif
#define SYSINIT_PANIC_ASSERT(rc) assert(rc);
static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
#if CONFIG_BT_NIMBLE_ENABLED
#define OS_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT)
#define OS_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE)
#define OS_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT)
#define OS_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE)
#define OS_MSYS_1_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT)
#define OS_MSYS_2_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT)
#if CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP
#define OS_MSYS_BLOCK_FROM_HEAP (1)
#else
#define OS_MSYS_BLOCK_FROM_HEAP (0)
#endif // CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP
#else
#define OS_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT
#define OS_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE
#define OS_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT
#define OS_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE
#define OS_MSYS_1_SANITY_MIN_COUNT 0
#define OS_MSYS_2_SANITY_MIN_COUNT 0
#if CONFIG_BT_LE_MSYS_BUF_FROM_HEAP
#define OS_MSYS_BLOCK_FROM_HEAP (1)
#else
#define OS_MSYS_BLOCK_FROM_HEAP (0)
#endif // CONFIG_BT_LE_MSYS_BUF_FROM_HEAP
#endif
#if OS_MSYS_1_BLOCK_COUNT > 0
#define SYSINIT_MSYS_1_MEMBLOCK_SIZE \
OS_ALIGN(OS_MSYS_1_BLOCK_SIZE, 4)
#define SYSINIT_MSYS_1_MEMPOOL_SIZE \
OS_MEMPOOL_SIZE(OS_MSYS_1_BLOCK_COUNT, \
SYSINIT_MSYS_1_MEMBLOCK_SIZE)
#if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
static os_membuf_t *os_msys_init_1_data;
static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
static struct os_mempool os_msys_init_1_mempool;
#endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
#endif
#if OS_MSYS_2_BLOCK_COUNT > 0
#define SYSINIT_MSYS_2_MEMBLOCK_SIZE \
OS_ALIGN(OS_MSYS_2_BLOCK_SIZE, 4)
#define SYSINIT_MSYS_2_MEMPOOL_SIZE \
OS_MEMPOOL_SIZE(OS_MSYS_2_BLOCK_COUNT, \
SYSINIT_MSYS_2_MEMBLOCK_SIZE)
#if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
static os_membuf_t *os_msys_init_2_data;
static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
static struct os_mempool os_msys_init_2_mempool;
#endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
#endif
#if CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
extern int r_esp_ble_msys_init(uint16_t msys_size1, uint16_t msys_size2, uint16_t msys_cnt1, uint16_t msys_cnt2, uint8_t from_heap);
extern void r_esp_ble_msys_deinit(void);
int os_msys_init(void)
{
return r_esp_ble_msys_init(SYSINIT_MSYS_1_MEMBLOCK_SIZE,
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
OS_MSYS_1_BLOCK_COUNT,
OS_MSYS_2_BLOCK_COUNT,
OS_MSYS_BLOCK_FROM_HEAP);
}
void os_msys_deinit(void)
{
r_esp_ble_msys_deinit();
}
#else // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
#if OS_MSYS_SANITY_ENABLED
/**
* Retrieves the minimum safe buffer count for an msys pool. That is, the
* lowest a pool's buffer count can be without causing the sanity check to
* fail.
*
* @param idx The index of the msys pool to query.
*
* @return The msys pool's minimum safe buffer count.
*/
static int
IRAM_ATTR os_msys_sanity_min_count(int idx)
{
switch (idx) {
case 0:
return OS_MSYS_1_SANITY_MIN_COUNT;
case 1:
return OS_MSYS_2_SANITY_MIN_COUNT;
default:
BLE_LL_ASSERT(0);
return ESP_OK;
}
}
static int
IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg)
{
const struct os_mbuf_pool *omp;
int min_count;
int idx;
idx = 0;
STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
min_count = os_msys_sanity_min_count(idx);
if (omp->omp_pool->mp_num_free < min_count) {
return OS_ENOMEM;
}
idx++;
}
return ESP_OK;
}
#endif
static void
os_msys_init_once(void *data, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool,
int block_count, int block_size, const char *name)
{
int rc;
rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
name);
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_msys_register(mbuf_pool);
SYSINIT_PANIC_ASSERT(rc == 0);
}
int
os_msys_buf_alloc(void)
{
#if OS_MSYS_1_BLOCK_COUNT > 0
os_msys_init_1_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE));
if (!os_msys_init_1_data) {
return ESP_ERR_NO_MEM;
}
#endif
#if OS_MSYS_2_BLOCK_COUNT > 0
os_msys_init_2_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE));
if (!os_msys_init_2_data) {
#if OS_MSYS_1_BLOCK_COUNT > 0
bt_osi_mem_free(os_msys_init_1_data);
os_msys_init_1_data = NULL;
#endif
return ESP_ERR_NO_MEM;
}
#endif
return ESP_OK;
}
void
os_msys_buf_free(void)
{
#if OS_MSYS_1_BLOCK_COUNT > 0
bt_osi_mem_free(os_msys_init_1_data);
os_msys_init_1_data = NULL;
#endif
#if OS_MSYS_2_BLOCK_COUNT > 0
bt_osi_mem_free(os_msys_init_2_data);
os_msys_init_2_data = NULL;
#endif
}
void os_msys_init(void)
{
#if OS_MSYS_SANITY_ENABLED
int rc;
#endif
os_msys_reset();
#if OS_MSYS_1_BLOCK_COUNT > 0
os_msys_init_once(os_msys_init_1_data,
&os_msys_init_1_mempool,
&os_msys_init_1_mbuf_pool,
OS_MSYS_1_BLOCK_COUNT,
SYSINIT_MSYS_1_MEMBLOCK_SIZE,
"msys_1");
#endif
#if OS_MSYS_2_BLOCK_COUNT > 0
os_msys_init_once(os_msys_init_2_data,
&os_msys_init_2_mempool,
&os_msys_init_2_mbuf_pool,
OS_MSYS_2_BLOCK_COUNT,
SYSINIT_MSYS_2_MEMBLOCK_SIZE,
"msys_2");
#endif
#if OS_MSYS_SANITY_ENABLED
os_msys_sc.sc_func = os_msys_sanity;
os_msys_sc.sc_checkin_itvl =
OS_TICKS_PER_SEC * MYNEWT_VAL(MSYS_SANITY_TIMEOUT) / 1000;
rc = os_sanity_check_register(&os_msys_sc);
SYSINIT_PANIC_ASSERT(rc == 0);
#endif
}
#endif // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
@@ -0,0 +1,167 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _NIMBLE_NPL_H_
#define _NIMBLE_NPL_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ble_npl_event;
typedef void ble_npl_event_fn(struct ble_npl_event *ev);
enum ble_npl_error {
BLE_NPL_OK = 0,
BLE_NPL_ENOMEM = 1,
BLE_NPL_EINVAL = 2,
BLE_NPL_INVALID_PARAM = 3,
BLE_NPL_MEM_NOT_ALIGNED = 4,
BLE_NPL_BAD_MUTEX = 5,
BLE_NPL_TIMEOUT = 6,
BLE_NPL_ERR_IN_ISR = 7,
BLE_NPL_ERR_PRIV = 8,
BLE_NPL_OS_NOT_STARTED = 9,
BLE_NPL_ENOENT = 10,
BLE_NPL_EBUSY = 11,
BLE_NPL_ERROR = 12,
};
typedef enum ble_npl_error ble_npl_error_t;
/* Include OS-specific definitions */
#include "nimble/nimble_npl_os.h"
/*
* Generic
*/
bool ble_npl_os_started(void);
void *ble_npl_get_current_task_id(void);
/*
* Event queue
*/
void ble_npl_eventq_init(struct ble_npl_eventq *evq);
void ble_npl_eventq_deinit(struct ble_npl_eventq *evq);
struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq,
ble_npl_time_t tmo);
void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev);
void ble_npl_eventq_remove(struct ble_npl_eventq *evq,
struct ble_npl_event *ev);
void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
void *arg);
bool ble_npl_event_is_queued(struct ble_npl_event *ev);
void *ble_npl_event_get_arg(struct ble_npl_event *ev);
void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg);
bool ble_npl_eventq_is_empty(struct ble_npl_eventq *evq);
void ble_npl_event_run(struct ble_npl_event *ev);
/*
* Mutexes
*/
ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu);
ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu,
ble_npl_time_t timeout);
ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu);
ble_npl_error_t ble_npl_mutex_deinit(struct ble_npl_mutex *mu);
/*
* Semaphores
*/
ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens);
ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem,
ble_npl_time_t timeout);
ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem);
ble_npl_error_t ble_npl_sem_deinit(struct ble_npl_sem *sem);
uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem);
/*
* Callouts
*/
int ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
ble_npl_event_fn *ev_cb, void *ev_arg);
ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *co,
ble_npl_time_t ticks);
void ble_npl_callout_stop(struct ble_npl_callout *co);
bool ble_npl_callout_is_active(struct ble_npl_callout *co);
ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co);
ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
ble_npl_time_t time);
void ble_npl_callout_set_arg(struct ble_npl_callout *co,
void *arg);
/*
* Time functions
*/
ble_npl_time_t ble_npl_time_get(void);
ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks);
ble_npl_error_t ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms);
ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms);
uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks);
void ble_npl_time_delay(ble_npl_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
void ble_npl_hw_set_isr(int irqn, uint32_t addr);
#endif
uint32_t ble_npl_hw_enter_critical(void);
void ble_npl_hw_exit_critical(uint32_t ctx);
bool ble_npl_hw_is_in_critical(void);
#ifdef __cplusplus
}
#endif
#endif /* _NIMBLE_NPL_H_ */
@@ -1,9 +1,7 @@
/*
* SPDX-FileCopyrightText: 2019-2023 The Apache Software Foundation (ASF)
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2023 Espressif Systems (Shanghai) CO LTD
*/
#include <assert.h>
@@ -18,7 +16,6 @@
#include "freertos/timers.h"
#include "freertos/portable.h"
#include "nimble/npl_freertos.h"
#include "nimble/nimble_port.h"
#include "os/os_mempool.h"
#include "esp_log.h"
@@ -481,32 +478,32 @@ IRAM_ATTR npl_freertos_mutex_release(struct ble_npl_mutex *mu)
ble_npl_error_t
npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
{
struct ble_npl_sem_freertos *semaphor = NULL;
struct ble_npl_sem_freertos *semaphore = NULL;
#if OS_MEM_ALLOC
if (!os_memblock_from(&ble_freertos_sem_pool,sem->sem)) {
sem->sem = os_memblock_get(&ble_freertos_sem_pool);
semaphor = (struct ble_npl_sem_freertos *)sem->sem;
semaphore = (struct ble_npl_sem_freertos *)sem->sem;
if (!semaphor) {
if (!semaphore) {
return BLE_NPL_INVALID_PARAM;
}
memset(semaphor, 0, sizeof(*semaphor));
semaphor->handle = xSemaphoreCreateCounting(128, tokens);
BLE_LL_ASSERT(semaphor->handle);
memset(semaphore, 0, sizeof(*semaphore));
semaphore->handle = xSemaphoreCreateCounting(128, tokens);
BLE_LL_ASSERT(semaphore->handle);
}
#else
if(!sem->sem) {
sem->sem = malloc(sizeof(struct ble_npl_sem_freertos));
semaphor = (struct ble_npl_sem_freertos *)sem->sem;
semaphore = (struct ble_npl_sem_freertos *)sem->sem;
if (!semaphor) {
if (!semaphore) {
return BLE_NPL_INVALID_PARAM;
}
memset(semaphor, 0, sizeof(*semaphor));
semaphor->handle = xSemaphoreCreateCounting(128, tokens);
BLE_LL_ASSERT(semaphor->handle);
memset(semaphore, 0, sizeof(*semaphore));
semaphore->handle = xSemaphoreCreateCounting(128, tokens);
BLE_LL_ASSERT(semaphore->handle);
}
#endif
@@ -516,19 +513,19 @@ npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
ble_npl_error_t
npl_freertos_sem_deinit(struct ble_npl_sem *sem)
{
struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
struct ble_npl_sem_freertos *semaphore = (struct ble_npl_sem_freertos *)sem->sem;
if (!semaphor) {
if (!semaphore) {
return BLE_NPL_INVALID_PARAM;
}
BLE_LL_ASSERT(semaphor->handle);
vSemaphoreDelete(semaphor->handle);
BLE_LL_ASSERT(semaphore->handle);
vSemaphoreDelete(semaphore->handle);
#if OS_MEM_ALLOC
os_memblock_put(&ble_freertos_sem_pool,semaphor);
os_memblock_put(&ble_freertos_sem_pool,semaphore);
#else
free((void *)semaphor);
free((void *)semaphore);
#endif
sem->sem = NULL;
@@ -540,22 +537,22 @@ IRAM_ATTR npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
{
BaseType_t woken;
BaseType_t ret;
struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
struct ble_npl_sem_freertos *semaphore = (struct ble_npl_sem_freertos *)sem->sem;
if (!semaphor) {
if (!semaphore) {
return BLE_NPL_INVALID_PARAM;
}
BLE_LL_ASSERT(semaphor->handle);
BLE_LL_ASSERT(semaphore->handle);
if (in_isr()) {
BLE_LL_ASSERT(timeout == 0);
ret = xSemaphoreTakeFromISR(semaphor->handle, &woken);
ret = xSemaphoreTakeFromISR(semaphore->handle, &woken);
if( woken == pdTRUE ) {
portYIELD_FROM_ISR();
}
} else {
ret = xSemaphoreTake(semaphor->handle, timeout);
ret = xSemaphoreTake(semaphore->handle, timeout);
}
return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT;
@@ -566,21 +563,21 @@ IRAM_ATTR npl_freertos_sem_release(struct ble_npl_sem *sem)
{
BaseType_t ret;
BaseType_t woken;
struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
struct ble_npl_sem_freertos *semaphore = (struct ble_npl_sem_freertos *)sem->sem;
if (!semaphor) {
if (!semaphore) {
return BLE_NPL_INVALID_PARAM;
}
BLE_LL_ASSERT(semaphor->handle);
BLE_LL_ASSERT(semaphore->handle);
if (in_isr()) {
ret = xSemaphoreGiveFromISR(semaphor->handle, &woken);
ret = xSemaphoreGiveFromISR(semaphore->handle, &woken);
if( woken == pdTRUE ) {
portYIELD_FROM_ISR();
}
} else {
ret = xSemaphoreGive(semaphor->handle);
ret = xSemaphoreGive(semaphore->handle);
}
BLE_LL_ASSERT(ret == pdPASS);
@@ -773,8 +770,8 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co)
uint16_t
IRAM_ATTR npl_freertos_sem_get_count(struct ble_npl_sem *sem)
{
struct ble_npl_sem_freertos *semaphor = (struct ble_npl_sem_freertos *)sem->sem;
return uxSemaphoreGetCount(semaphor->handle);
struct ble_npl_sem_freertos *semaphore = (struct ble_npl_sem_freertos *)sem->sem;
return uxSemaphoreGetCount(semaphore->handle);
}
@@ -842,15 +839,35 @@ ble_npl_time_t
IRAM_ATTR npl_freertos_callout_get_ticks(struct ble_npl_callout *co)
{
#if BLE_NPL_USE_ESP_TIMER
/* Currently, esp_timer does not support an API which gets the expiry time for
* current timer.
* Returning 0 from here should not cause any effect.
uint32_t exp = 0;
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
uint64_t expiry = 0;
esp_err_t err;
struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
//Fetch expiry time in microseconds
err = esp_timer_get_expiry_time((esp_timer_handle_t)(callout->handle), &expiry);
if (err != ESP_OK) {
//Error. Could not fetch the expiry time
return 0;
}
//Convert microseconds to ticks
npl_freertos_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp);
#else
//esp_timer_get_expiry_time() is only available from IDF 5.0 onwards
/* Returning 0 from here should not cause any effect.
* Drawback of this approach is that existing code to reset timer would be called
* more often (since the if condition to invoke reset timer would always succeed if
* timer is active).
*/
exp = 0;
#endif //ESP_IDF_VERSION
return 0;
return exp;
#else
struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co;
return xTimerGetExpiryTime(callout->handle);