Add new porting file

This commit is contained in:
GengYuchao 2022-06-17 21:37:48 +08:00
parent 7916f45d58
commit 61ee34f713
25 changed files with 7621 additions and 0 deletions

View File

@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_ESP_NIMBLE_CONTROLLER
struct os_mempool;
struct os_mbuf_pool;
int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
uint32_t block_size, char *name, void **out_buf);
#define mem_malloc_mempool r_mem_malloc_mempool
int r_mem_malloc_mempool_ext(struct os_mempool_ext *mempool, uint16_t num_blocks,
uint32_t block_size, char *name, void **out_buf);
#define mem_malloc_mempool_ext r_mem_malloc_mempool_ext
int r_mem_malloc_mbuf_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, uint16_t num_blocks,
uint32_t block_size, char *name,
void **out_buf);
#define mem_malloc_mbuf_pool r_mem_malloc_mbuf_pool
int r_mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, char *name,
void **out_buf);
#define mem_malloc_mbufpkt_pool r_mem_malloc_mbufpkt_pool
int r_mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
struct os_mbuf_pool *mbuf_pool, int num_blocks,
int block_size, const char *name);
#define mem_init_mbuf_pool r_mem_init_mbuf_pool
/**
* Specifies a function used as a callback. Functions of this type allocate an
* mbuf chain meant to hold a packet fragment. The resulting mbuf must contain
* a pkthdr.
*
* @param frag_size The number of data bytes that the mbuf will
* eventually contain.
* @param arg A generic parameter.
*
* @return An allocated mbuf chain on success;
* NULL on failure.
*/
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
mem_frag_alloc_fn *alloc_cb, void *cb_arg);
#define mem_split_frag r_mem_split_frag
void *r_mem_pullup_obj(struct os_mbuf **om, uint16_t len);
#define mem_pullup_obj r_mem_pullup_obj
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,50 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include "sdkconfig.h"
IRAM_ATTR void *bt_osi_mem_malloc(size_t size)
{
#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#else
return malloc(size);
#endif
}
IRAM_ATTR void *bt_osi_mem_calloc(size_t n, size_t size)
{
#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
#else
return calloc(n, size);
#endif
}
IRAM_ATTR void *bt_osi_mem_malloc_internal(size_t size)
{
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
}
IRAM_ATTR void *bt_osi_mem_calloc_internal(size_t n, size_t size)
{
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
}
IRAM_ATTR void bt_osi_mem_free(void *ptr)
{
heap_caps_free(ptr);
}

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);

View File

@ -0,0 +1,318 @@
/*
* 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_BLE_
#define H_BLE_
#include <inttypes.h>
#include <string.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
#ifdef __cplusplus
extern "C" {
#endif
/* The number of advertising instances */
#define BLE_ADV_INSTANCES (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1)
/* BLE encryption block definitions */
#define BLE_ENC_BLOCK_SIZE (16)
/* 4 byte header + 251 byte payload. */
#define BLE_ACL_MAX_PKT_SIZE 255
struct ble_encryption_block
{
uint8_t key[BLE_ENC_BLOCK_SIZE];
uint8_t plain_text[BLE_ENC_BLOCK_SIZE];
uint8_t cipher_text[BLE_ENC_BLOCK_SIZE];
};
/*
* BLE MBUF structure:
*
* The BLE mbuf structure is as follows. Note that this structure applies to
* the packet header mbuf (not mbufs that are part of a "packet chain"):
* struct os_mbuf (16)
* struct os_mbuf_pkthdr (8)
* struct ble_mbuf_hdr (8)
* Data buffer (payload size, in bytes)
*
* The BLE mbuf header contains the following:
* flags: bitfield with the following values
* 0x01: Set if there was a match on the whitelist
* 0x02: Set if a connect request was transmitted upon receiving pdu
* 0x04: Set the first time we transmit the PDU (used to detect retry).
* channel: The logical BLE channel PHY channel # (0 - 39)
* crcok: flag denoting CRC check passed (1) or failed (0).
* rssi: RSSI, in dBm.
*/
struct ble_mbuf_hdr_rxinfo
{
uint16_t flags;
uint8_t channel;
uint8_t handle;
int8_t rssi;
/* XXX: we could just use single phy_mode field */
int8_t phy;
uint8_t phy_mode;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
int8_t rpa_index;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
void *user_data;
#endif
};
/*
* Flag definitions for rxinfo
*
* Note: it's ok to have symbols with the same values as long as they cannot be
* set for the same PDU (e.g. one use by scanner, other one used by
* connection)
*/
#define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000)
#define BLE_MBUF_HDR_F_IGNORED (0x8000)
#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000)
#define BLE_MBUF_HDR_F_INITA_RESOLVED (0x2000)
#define BLE_MBUF_HDR_F_TARGETA_RESOLVED (0x2000)
#define BLE_MBUF_HDR_F_EXT_ADV_SEC (0x1000)
#define BLE_MBUF_HDR_F_EXT_ADV (0x0800)
#define BLE_MBUF_HDR_F_RESOLVED (0x0400)
#define BLE_MBUF_HDR_F_AUX_PTR_WAIT (0x0200)
#define BLE_MBUF_HDR_F_AUX_INVALID (0x0100)
#define BLE_MBUF_HDR_F_CRC_OK (0x0080)
#define BLE_MBUF_HDR_F_DEVMATCH (0x0040)
#define BLE_MBUF_HDR_F_MIC_FAILURE (0x0020)
#define BLE_MBUF_HDR_F_SCAN_RSP_TXD (0x0010)
#define BLE_MBUF_HDR_F_SCAN_RSP_RXD (0x0008)
#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x0007)
/* Transmit info. NOTE: no flags defined */
struct ble_mbuf_hdr_txinfo
{
uint8_t flags;
uint8_t offset;
uint8_t pyld_len;
uint8_t hdr_byte;
};
struct ble_mbuf_hdr
{
union {
struct ble_mbuf_hdr_rxinfo rxinfo;
struct ble_mbuf_hdr_txinfo txinfo;
};
uint32_t beg_cputime;
uint32_t rem_usecs;
};
#define BLE_MBUF_HDR_IGNORED(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_IGNORED))
#define BLE_MBUF_HDR_SCAN_REQ_TXD(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD))
#define BLE_MBUF_HDR_EXT_ADV_SEC(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV_SEC))
#define BLE_MBUF_HDR_EXT_ADV(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV))
#define BLE_MBUF_HDR_DEVMATCH(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH))
#define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD))
#define BLE_MBUF_HDR_AUX_INVALID(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID))
#define BLE_MBUF_HDR_WAIT_AUX(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT))
#define BLE_MBUF_HDR_CRC_OK(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_CRC_OK))
#define BLE_MBUF_HDR_MIC_FAILURE(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_MIC_FAILURE))
#define BLE_MBUF_HDR_RESOLVED(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED))
#define BLE_MBUF_HDR_INITA_RESOLVED(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_INITA_RESOLVED))
#define BLE_MBUF_HDR_TARGETA_RESOLVED(hdr) \
(!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED))
#define BLE_MBUF_HDR_RX_STATE(hdr) \
((uint8_t)((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK))
#define BLE_MBUF_HDR_PTR(om) \
(struct ble_mbuf_hdr *)((uint8_t *)om + sizeof(struct os_mbuf) + \
sizeof(struct os_mbuf_pkthdr))
/* BLE mbuf overhead per packet header mbuf */
#define BLE_MBUF_PKTHDR_OVERHEAD \
(sizeof(struct os_mbuf_pkthdr) + sizeof(struct ble_mbuf_hdr))
#define BLE_MBUF_MEMBLOCK_OVERHEAD \
(sizeof(struct os_mbuf) + BLE_MBUF_PKTHDR_OVERHEAD)
/* Length of host user header. Only contains the peer's connection handle. */
#define BLE_MBUF_HS_HDR_LEN (2)
#define BLE_DEV_ADDR_LEN (6)
extern uint8_t g_dev_addr[BLE_DEV_ADDR_LEN];
extern uint8_t g_random_addr[BLE_DEV_ADDR_LEN];
/* BLE Error Codes (Core v4.2 Vol 2 part D) */
enum ble_error_codes
{
/* An "error" code of 0x0 means success */
BLE_ERR_SUCCESS = 0x00,
BLE_ERR_UNKNOWN_HCI_CMD = 0x01,
BLE_ERR_UNK_CONN_ID = 0x02,
BLE_ERR_HW_FAIL = 0x03,
BLE_ERR_PAGE_TMO = 0x04,
BLE_ERR_AUTH_FAIL = 0x05,
BLE_ERR_PINKEY_MISSING = 0x06,
BLE_ERR_MEM_CAPACITY = 0x07,
BLE_ERR_CONN_SPVN_TMO = 0x08,
BLE_ERR_CONN_LIMIT = 0x09,
BLE_ERR_SYNCH_CONN_LIMIT = 0x0a,
BLE_ERR_ACL_CONN_EXISTS = 0x0b,
BLE_ERR_CMD_DISALLOWED = 0x0c,
BLE_ERR_CONN_REJ_RESOURCES = 0x0d,
BLE_ERR_CONN_REJ_SECURITY = 0x0e,
BLE_ERR_CONN_REJ_BD_ADDR = 0x0f,
BLE_ERR_CONN_ACCEPT_TMO = 0x10,
BLE_ERR_UNSUPPORTED = 0x11,
BLE_ERR_INV_HCI_CMD_PARMS = 0x12,
BLE_ERR_REM_USER_CONN_TERM = 0x13,
BLE_ERR_RD_CONN_TERM_RESRCS = 0x14,
BLE_ERR_RD_CONN_TERM_PWROFF = 0x15,
BLE_ERR_CONN_TERM_LOCAL = 0x16,
BLE_ERR_REPEATED_ATTEMPTS = 0x17,
BLE_ERR_NO_PAIRING = 0x18,
BLE_ERR_UNK_LMP = 0x19,
BLE_ERR_UNSUPP_REM_FEATURE = 0x1a,
BLE_ERR_SCO_OFFSET = 0x1b,
BLE_ERR_SCO_ITVL = 0x1c,
BLE_ERR_SCO_AIR_MODE = 0x1d,
BLE_ERR_INV_LMP_LL_PARM = 0x1e,
BLE_ERR_UNSPECIFIED = 0x1f,
BLE_ERR_UNSUPP_LMP_LL_PARM = 0x20,
BLE_ERR_NO_ROLE_CHANGE = 0x21,
BLE_ERR_LMP_LL_RSP_TMO = 0x22,
BLE_ERR_LMP_COLLISION = 0x23,
BLE_ERR_LMP_PDU = 0x24,
BLE_ERR_ENCRYPTION_MODE = 0x25,
BLE_ERR_LINK_KEY_CHANGE = 0x26,
BLE_ERR_UNSUPP_QOS = 0x27,
BLE_ERR_INSTANT_PASSED = 0x28,
BLE_ERR_UNIT_KEY_PAIRING = 0x29,
BLE_ERR_DIFF_TRANS_COLL = 0x2a,
/* BLE_ERR_RESERVED = 0x2b */
BLE_ERR_QOS_PARM = 0x2c,
BLE_ERR_QOS_REJECTED = 0x2d,
BLE_ERR_CHAN_CLASS = 0x2e,
BLE_ERR_INSUFFICIENT_SEC = 0x2f,
BLE_ERR_PARM_OUT_OF_RANGE = 0x30,
/* BLE_ERR_RESERVED = 0x31 */
BLE_ERR_PENDING_ROLE_SW = 0x32,
/* BLE_ERR_RESERVED = 0x33 */
BLE_ERR_RESERVED_SLOT = 0x34,
BLE_ERR_ROLE_SW_FAIL = 0x35,
BLE_ERR_INQ_RSP_TOO_BIG = 0x36,
BLE_ERR_SEC_SIMPLE_PAIR = 0x37,
BLE_ERR_HOST_BUSY_PAIR = 0x38,
BLE_ERR_CONN_REJ_CHANNEL = 0x39,
BLE_ERR_CTLR_BUSY = 0x3a,
BLE_ERR_CONN_PARMS = 0x3b,
BLE_ERR_DIR_ADV_TMO = 0x3c,
BLE_ERR_CONN_TERM_MIC = 0x3d,
BLE_ERR_CONN_ESTABLISHMENT = 0x3e,
BLE_ERR_MAC_CONN_FAIL = 0x3f,
BLE_ERR_COARSE_CLK_ADJ = 0x40,
BLE_ERR_TYPE0_SUBMAP_NDEF = 0x41,
BLE_ERR_UNK_ADV_INDENT = 0x42,
BLE_ERR_LIMIT_REACHED = 0x43,
BLE_ERR_OPERATION_CANCELLED = 0x44,
BLE_ERR_PACKET_TOO_LONG = 0x45,
BLE_ERR_MAX = 0xff
};
/* HW error codes */
#define BLE_HW_ERR_DO_NOT_USE (0) /* XXX: reserve this one for now */
#define BLE_HW_ERR_HCI_SYNC_LOSS (1)
/* Own Bluetooth Device address type */
#define BLE_OWN_ADDR_PUBLIC (0x00)
#define BLE_OWN_ADDR_RANDOM (0x01)
#define BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT (0x02)
#define BLE_OWN_ADDR_RPA_RANDOM_DEFAULT (0x03)
/* Bluetooth Device address type */
#define BLE_ADDR_PUBLIC (0x00)
#define BLE_ADDR_RANDOM (0x01)
#define BLE_ADDR_PUBLIC_ID (0x02)
#define BLE_ADDR_RANDOM_ID (0x03)
#define BLE_ADDR_ANY (&(ble_addr_t) { 0, {0, 0, 0, 0, 0, 0} })
#define BLE_ADDR_IS_RPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
((addr)->val[5] & 0xc0) == 0x40)
#define BLE_ADDR_IS_NRPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
((addr)->val[5] & 0xc0) == 0x00)
#define BLE_ADDR_IS_STATIC(addr) (((addr)->type == BLE_ADDR_RANDOM) && \
((addr)->val[5] & 0xc0) == 0xc0)
typedef struct {
uint8_t type;
uint8_t val[6];
} ble_addr_t;
static inline int ble_addr_cmp(const ble_addr_t *a, const ble_addr_t *b)
{
int type_diff;
type_diff = a->type - b->type;
if (type_diff != 0) {
return type_diff;
}
return memcmp(a->val, b->val, sizeof(a->val));
}
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_ */

View File

@ -0,0 +1,407 @@
/*
* 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_HCI_TRANSPORT_
#define H_HCI_TRANSPORT_
#include <inttypes.h>
#include "os/os_mempool.h"
#ifdef __cplusplus
extern "C" {
#endif
struct os_mbuf;
#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 CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
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.
*/
uint8_t *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 ble_hci_trans_buf_free(uint8_t *buf);
/**
* 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.
*/
int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg);
/**
* 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.
*/
void 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);
/**
* 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 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 ble_hci_trans_reset(void);
/**
* 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 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_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
/*
* 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 _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
*/
void 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_ */

View File

@ -0,0 +1,34 @@
/*
* 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_NIMBLE_OPT_
#define H_NIMBLE_OPT_
#ifdef __cplusplus
extern "C" {
#endif
/* Include automatically-generated settings. */
#include "nimble/nimble_opt_auto.h"
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,124 @@
/*
* 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_NIMBLE_OPT_AUTO_
#define H_NIMBLE_OPT_AUTO_
#include "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
#endif
/***
* Automatic options.
*
* These settings are generated automatically from the user-specified syscfg
* settings.
*/
#undef NIMBLE_BLE_ADVERTISE
#define NIMBLE_BLE_ADVERTISE \
(MYNEWT_VAL(BLE_ROLE_BROADCASTER) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
#undef NIMBLE_BLE_SCAN
#define NIMBLE_BLE_SCAN \
(MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER))
#undef NIMBLE_BLE_CONNECT
#define NIMBLE_BLE_CONNECT \
(MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL))
/** Supported client ATT commands. */
#undef NIMBLE_BLE_ATT_CLT_FIND_INFO
#define NIMBLE_BLE_ATT_CLT_FIND_INFO \
(MYNEWT_VAL(BLE_GATT_DISC_ALL_DSCS))
#undef NIMBLE_BLE_ATT_CLT_FIND_TYPE
#define NIMBLE_BLE_ATT_CLT_FIND_TYPE \
(MYNEWT_VAL(BLE_GATT_DISC_SVC_UUID))
#undef NIMBLE_BLE_ATT_CLT_READ_TYPE
#define NIMBLE_BLE_ATT_CLT_READ_TYPE \
(MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS) || \
MYNEWT_VAL(BLE_GATT_DISC_ALL_CHRS) || \
MYNEWT_VAL(BLE_GATT_DISC_CHRS_UUID) || \
MYNEWT_VAL(BLE_GATT_READ_UUID))
#undef NIMBLE_BLE_ATT_CLT_READ
#define NIMBLE_BLE_ATT_CLT_READ \
(MYNEWT_VAL(BLE_GATT_READ) || \
MYNEWT_VAL(BLE_GATT_READ_LONG) || \
MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS))
#undef NIMBLE_BLE_ATT_CLT_READ_BLOB
#define NIMBLE_BLE_ATT_CLT_READ_BLOB \
(MYNEWT_VAL(BLE_GATT_READ_LONG))
#undef NIMBLE_BLE_ATT_CLT_READ_MULT
#define NIMBLE_BLE_ATT_CLT_READ_MULT \
(MYNEWT_VAL(BLE_GATT_READ_MULT))
#undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE
#define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE \
(MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS))
#undef NIMBLE_BLE_ATT_CLT_WRITE
#define NIMBLE_BLE_ATT_CLT_WRITE \
(MYNEWT_VAL(BLE_GATT_WRITE))
#undef NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP
#define NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP \
(MYNEWT_VAL(BLE_GATT_WRITE_NO_RSP))
#undef NIMBLE_BLE_ATT_CLT_PREP_WRITE
#define NIMBLE_BLE_ATT_CLT_PREP_WRITE \
(MYNEWT_VAL(BLE_GATT_WRITE_LONG))
#undef NIMBLE_BLE_ATT_CLT_EXEC_WRITE
#define NIMBLE_BLE_ATT_CLT_EXEC_WRITE \
(MYNEWT_VAL(BLE_GATT_WRITE_LONG))
#undef NIMBLE_BLE_ATT_CLT_NOTIFY
#define NIMBLE_BLE_ATT_CLT_NOTIFY \
(MYNEWT_VAL(BLE_GATT_NOTIFY))
#undef NIMBLE_BLE_ATT_CLT_INDICATE
#define NIMBLE_BLE_ATT_CLT_INDICATE \
(MYNEWT_VAL(BLE_GATT_INDICATE))
/** Security manager settings. */
#undef NIMBLE_BLE_SM
#define NIMBLE_BLE_SM (MYNEWT_VAL(BLE_SM_LEGACY) || MYNEWT_VAL(BLE_SM_SC))
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
/*
* 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 _NIMBLE_PORT_H
#define _NIMBLE_PORT_H
#include "nimble/nimble_npl.h"
#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
#if (CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2)
#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
#endif
#ifdef __cplusplus
extern "C" {
#endif
void nimble_port_init(void);
void nimble_port_deinit(void);
void nimble_port_run(void);
int nimble_port_stop(void);
struct ble_npl_eventq *nimble_port_get_dflt_eventq(void);
struct ble_hs_cfg;
esp_err_t esp_nimble_init();
esp_err_t esp_nimble_enable(void *host_task);
esp_err_t esp_nimble_disable();
esp_err_t esp_nimble_deinit();
#ifdef __cplusplus
}
#endif
#endif /* _NIMBLE_PORT_H */

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
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

View File

@ -0,0 +1,74 @@
/*
* 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>
#ifdef __cplusplus
extern "C" {
#endif
#if !defined __cplusplus
#define static_assert _Static_assert
#endif
#ifndef min
#define min(a, b) ((a)<(b)?(a):(b))
#endif
#ifndef max
#define max(a, b) ((a)>(b)?(a):(b))
#endif
#include "soc/soc_caps.h"
#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 */

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 <stdbool.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

View File

@ -0,0 +1,408 @@
/*
* 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
/**
* 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
*/

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
* $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
*/
#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_ */

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

View File

@ -0,0 +1,206 @@
/*
* 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)
#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
#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)
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
#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)
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
#define OS_MSYS_SANITY_ENABLED \
(OS_MSYS_1_SANITY_MIN_COUNT > 0 || \
OS_MSYS_1_SANITY_MIN_COUNT > 0)
#if OS_MSYS_SANITY_ENABLED
static struct os_sanity_check os_msys_sc;
#endif
#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_1_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_FAIL;
}
#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) {
return ESP_FAIL;
}
#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
}

View File

@ -0,0 +1,381 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
#ifndef _NIMBLE_NPL_OS_H_
#define _NIMBLE_NPL_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 BLE_LL_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 BLE_NPL_OS_ALIGNMENT (4)/*ble_npl_get_os_alignment()*/
#define BLE_NPL_TIME_FOREVER ble_npl_get_time_forever()
/* This should be compatible with TickType_t */
typedef uint32_t ble_npl_time_t;
typedef int32_t ble_npl_stime_t;
struct ble_npl_event;
typedef void ble_npl_event_fn(struct ble_npl_event *ev);
struct ble_npl_event {
void *event;
};
struct ble_npl_eventq {
void *eventq;
};
struct ble_npl_callout {
void *co;
};
struct ble_npl_mutex {
void *mutex;
};
struct ble_npl_sem {
void *sem;
};
/*
* 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 "npl_freertos.h"
struct npl_funcs_t {
bool (*p_ble_npl_os_started)(void);
void *(*p_ble_npl_get_current_task_id)(void);
void (*p_ble_npl_eventq_init)(struct ble_npl_eventq *);
void (*p_ble_npl_eventq_deinit)(struct ble_npl_eventq *);
struct ble_npl_event * (*p_ble_npl_eventq_get)(struct ble_npl_eventq *, ble_npl_time_t);
void (*p_ble_npl_eventq_put)(struct ble_npl_eventq *, struct ble_npl_event *);
void (*p_ble_npl_eventq_remove)(struct ble_npl_eventq *, struct ble_npl_event *);
void (*p_ble_npl_event_run)(struct ble_npl_event *);
bool (*p_ble_npl_eventq_is_empty)(struct ble_npl_eventq *);
void (*p_ble_npl_event_init)(struct ble_npl_event *, ble_npl_event_fn *, void *);
void (*p_ble_npl_event_deinit)(struct ble_npl_event *);
void (*p_ble_npl_event_reset)(struct ble_npl_event *);
bool (*p_ble_npl_event_is_queued)(struct ble_npl_event *);
void * (*p_ble_npl_event_get_arg)(struct ble_npl_event *);
void (*p_ble_npl_event_set_arg)(struct ble_npl_event *, void *);
ble_npl_error_t (*p_ble_npl_mutex_init)(struct ble_npl_mutex *);
ble_npl_error_t (*p_ble_npl_mutex_deinit)(struct ble_npl_mutex *);
ble_npl_error_t (*p_ble_npl_mutex_pend)(struct ble_npl_mutex *, ble_npl_time_t);
ble_npl_error_t (*p_ble_npl_mutex_release)(struct ble_npl_mutex *);
ble_npl_error_t (*p_ble_npl_sem_init)(struct ble_npl_sem *, uint16_t);
ble_npl_error_t (*p_ble_npl_sem_deinit)(struct ble_npl_sem *);
ble_npl_error_t (*p_ble_npl_sem_pend)(struct ble_npl_sem *, ble_npl_time_t);
ble_npl_error_t (*p_ble_npl_sem_release)(struct ble_npl_sem *);
uint16_t (*p_ble_npl_sem_get_count)(struct ble_npl_sem *);
void (*p_ble_npl_callout_init)(struct ble_npl_callout *, struct ble_npl_eventq *, ble_npl_event_fn *, void *);
ble_npl_error_t (*p_ble_npl_callout_reset)(struct ble_npl_callout *, ble_npl_time_t);
void (*p_ble_npl_callout_stop)(struct ble_npl_callout *);
void (*p_ble_npl_callout_deinit)(struct ble_npl_callout *);
void (*p_ble_npl_callout_mem_reset)(struct ble_npl_callout *);
bool (*p_ble_npl_callout_is_active)(struct ble_npl_callout *);
ble_npl_time_t (*p_ble_npl_callout_get_ticks)(struct ble_npl_callout *);
uint32_t (*p_ble_npl_callout_remaining_ticks)(struct ble_npl_callout *, ble_npl_time_t);
void (*p_ble_npl_callout_set_arg)(struct ble_npl_callout *, void *);
uint32_t (*p_ble_npl_time_get)(void);
ble_npl_error_t (*p_ble_npl_time_ms_to_ticks)(uint32_t ms, ble_npl_time_t *);
ble_npl_error_t (*p_ble_npl_time_ticks_to_ms)(ble_npl_time_t, uint32_t *);
ble_npl_time_t (*p_ble_npl_time_ms_to_ticks32)(uint32_t);
uint32_t (*p_ble_npl_time_ticks_to_ms32)(ble_npl_time_t);
void (*p_ble_npl_time_delay)(ble_npl_time_t);
void (*p_ble_npl_hw_set_isr)(int, uint32_t);
uint32_t (*p_ble_npl_hw_enter_critical)(void);
void (*p_ble_npl_hw_exit_critical)(uint32_t);
uint32_t (*p_ble_npl_get_time_forever)(void);
uint8_t (*p_ble_npl_hw_is_in_critical)(void);
};
extern struct npl_funcs_t *npl_funcs;
static inline bool
IRAM_ATTR ble_npl_os_started(void)
{
return npl_funcs->p_ble_npl_os_started();
}
static inline void *
IRAM_ATTR ble_npl_get_current_task_id(void)
{
return npl_funcs->p_ble_npl_get_current_task_id();
}
static inline void
IRAM_ATTR ble_npl_eventq_init(struct ble_npl_eventq *evq)
{
return npl_funcs->p_ble_npl_eventq_init(evq);
}
static inline void
IRAM_ATTR ble_npl_eventq_deinit(struct ble_npl_eventq *evq)
{
return npl_funcs->p_ble_npl_eventq_deinit(evq);
}
static inline struct ble_npl_event *
IRAM_ATTR ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo)
{
return npl_funcs->p_ble_npl_eventq_get(evq, tmo);
}
static inline void
IRAM_ATTR ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
{
return npl_funcs->p_ble_npl_eventq_put(evq, ev);
}
static inline void
IRAM_ATTR ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev)
{
return npl_funcs->p_ble_npl_eventq_remove(evq, ev);
}
static inline void
IRAM_ATTR ble_npl_event_run(struct ble_npl_event *ev)
{
return npl_funcs->p_ble_npl_event_run(ev);
}
static inline bool
IRAM_ATTR ble_npl_eventq_is_empty(struct ble_npl_eventq *evq)
{
return npl_funcs->p_ble_npl_eventq_is_empty(evq);
}
static inline void
IRAM_ATTR ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn,
void *arg)
{
return npl_funcs->p_ble_npl_event_init(ev, fn, arg);
}
static inline bool
IRAM_ATTR ble_npl_event_is_queued(struct ble_npl_event *ev)
{
return npl_funcs->p_ble_npl_event_is_queued(ev);
}
static inline void *
IRAM_ATTR ble_npl_event_get_arg(struct ble_npl_event *ev)
{
return npl_funcs->p_ble_npl_event_get_arg(ev);
}
static inline void
IRAM_ATTR ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg)
{
return npl_funcs->p_ble_npl_event_set_arg(ev, arg);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_mutex_init(struct ble_npl_mutex *mu)
{
return npl_funcs->p_ble_npl_mutex_init(mu);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_mutex_deinit(struct ble_npl_mutex *mu)
{
return npl_funcs->p_ble_npl_mutex_deinit(mu);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout)
{
return npl_funcs->p_ble_npl_mutex_pend(mu, timeout);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_mutex_release(struct ble_npl_mutex *mu)
{
return npl_funcs->p_ble_npl_mutex_release(mu);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens)
{
return npl_funcs->p_ble_npl_sem_init(sem, tokens);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_sem_deinit(struct ble_npl_sem *sem)
{
return npl_funcs->p_ble_npl_sem_deinit(sem);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout)
{
return npl_funcs->p_ble_npl_sem_pend(sem, timeout);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_sem_release(struct ble_npl_sem *sem)
{
return npl_funcs->p_ble_npl_sem_release(sem);
}
static inline uint16_t
IRAM_ATTR ble_npl_sem_get_count(struct ble_npl_sem *sem)
{
return npl_funcs->p_ble_npl_sem_get_count(sem);
}
static inline void
IRAM_ATTR ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq,
ble_npl_event_fn *ev_cb, void *ev_arg)
{
return npl_funcs->p_ble_npl_callout_init(co, evq, ev_cb, ev_arg);
}
static inline void
IRAM_ATTR ble_npl_callout_deinit(struct ble_npl_callout *co)
{
return npl_funcs->p_ble_npl_callout_deinit(co);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks)
{
return npl_funcs->p_ble_npl_callout_reset(co, ticks);
}
static inline void
IRAM_ATTR ble_npl_callout_stop(struct ble_npl_callout *co)
{
return npl_funcs->p_ble_npl_callout_stop(co);
}
static inline bool
IRAM_ATTR ble_npl_callout_is_active(struct ble_npl_callout *co)
{
return npl_funcs->p_ble_npl_callout_is_active(co);
}
static inline ble_npl_time_t
IRAM_ATTR ble_npl_callout_get_ticks(struct ble_npl_callout *co)
{
return npl_funcs->p_ble_npl_callout_get_ticks(co);
}
static inline ble_npl_time_t
IRAM_ATTR ble_npl_callout_remaining_ticks(struct ble_npl_callout *co,
ble_npl_time_t time)
{
return npl_funcs->p_ble_npl_callout_remaining_ticks(co, time);
}
static inline void
IRAM_ATTR ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg)
{
return npl_funcs->p_ble_npl_callout_set_arg(co, arg);
}
static inline ble_npl_time_t
IRAM_ATTR ble_npl_time_get(void)
{
return npl_funcs->p_ble_npl_time_get();
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks)
{
return npl_funcs->p_ble_npl_time_ms_to_ticks(ms, out_ticks);
}
static inline ble_npl_error_t
IRAM_ATTR ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms)
{
return npl_funcs->p_ble_npl_time_ticks_to_ms(ticks, out_ms);
}
static inline ble_npl_time_t
IRAM_ATTR ble_npl_time_ms_to_ticks32(uint32_t ms)
{
return npl_funcs->p_ble_npl_time_ms_to_ticks32(ms);
}
static inline uint32_t
IRAM_ATTR ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks)
{
return npl_funcs->p_ble_npl_time_ticks_to_ms32(ticks);
}
static inline void
IRAM_ATTR ble_npl_time_delay(ble_npl_time_t ticks)
{
return npl_funcs->p_ble_npl_time_delay(ticks);
}
#if NIMBLE_CFG_CONTROLLER
static inline void
IRAM_ATTR ble_npl_hw_set_isr(int irqn, uint32_t addr)
{
return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr);
}
#endif
static inline uint32_t
IRAM_ATTR ble_npl_hw_enter_critical(void)
{
return npl_funcs->p_ble_npl_hw_enter_critical();
}
static inline void
IRAM_ATTR ble_npl_hw_exit_critical(uint32_t ctx)
{
return npl_funcs->p_ble_npl_hw_exit_critical(ctx);
}
static inline bool IRAM_ATTR ble_npl_hw_is_in_critical(void)
{
return npl_funcs->p_ble_npl_hw_is_in_critical();
}
#define ble_npl_get_time_forever (*npl_funcs->p_ble_npl_get_time_forever)
#define ble_npl_callout_mem_reset (*npl_funcs->p_ble_npl_callout_mem_reset)
#define ble_npl_event_deinit (*npl_funcs->p_ble_npl_event_deinit)
#define ble_npl_event_reset (*npl_funcs->p_ble_npl_event_reset)
#ifdef __cplusplus
}
#endif
#endif /* _NPL_H_ */

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
#ifndef _NIMBLE_PORT_FREERTOS_H
#define _NIMBLE_PORT_FREERTOS_H
#include "nimble/nimble_npl.h"
#ifdef __cplusplus
extern "C" {
#endif
void nimble_port_freertos_init(TaskFunction_t host_task_fn);
void nimble_port_freertos_deinit(void);
void npl_freertos_funcs_init(void);
void npl_freertos_funcs_deinit(void);
int npl_freertos_mempool_init(void);
struct npl_funcs_t * npl_freertos_funcs_get(void);
#ifdef __cplusplus
}
#endif
#endif /* _NIMBLE_PORT_FREERTOS_H */

View File

@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
*/
#ifndef _NPL_FREERTOS_H_
#define _NPL_FREERTOS_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef void ble_npl_event_fn(struct ble_npl_event *ev);
struct ble_npl_event_freertos {
bool queued;
ble_npl_event_fn *fn;
void *arg;
};
struct ble_npl_eventq_freertos {
QueueHandle_t q;
};
struct ble_npl_callout_freertos {
#if CONFIG_BT_NIMBLE_USE_ESP_TIMER
esp_timer_handle_t handle;
#else
TimerHandle_t handle;
#endif
struct ble_npl_eventq *evq;
struct ble_npl_event ev;
};
struct ble_npl_mutex_freertos {
SemaphoreHandle_t handle;
};
struct ble_npl_sem_freertos {
SemaphoreHandle_t handle;
};
typedef void ble_npl_event_fn_freertos(struct ble_npl_event_freertos *ev);
struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void);
struct ble_npl_event *npl_freertos_eventq_get(struct ble_npl_eventq *evq,
ble_npl_time_t tmo);
void npl_freertos_eventq_put(struct ble_npl_eventq *evq,
struct ble_npl_event *ev);
void npl_freertos_eventq_remove(struct ble_npl_eventq *evq,
struct ble_npl_event *ev);
ble_npl_error_t npl_freertos_mutex_init(struct ble_npl_mutex *mu);
ble_npl_error_t npl_freertos_mutex_deinit(struct ble_npl_mutex *mu);
ble_npl_error_t npl_freertos_mutex_pend(struct ble_npl_mutex *mu,
ble_npl_time_t timeout);
ble_npl_error_t 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);
ble_npl_error_t npl_freertos_sem_deinit(struct ble_npl_sem *sem);
ble_npl_error_t npl_freertos_sem_pend(struct ble_npl_sem *sem,
ble_npl_time_t timeout);
ble_npl_error_t npl_freertos_sem_release(struct ble_npl_sem *sem);
void npl_freertos_callout_init(struct ble_npl_callout *co,
struct ble_npl_eventq *evq,
ble_npl_event_fn *ev_cb, void *ev_arg);
void npl_freertos_callout_deinit(struct ble_npl_callout *co);
void npl_freertos_callout_stop(struct ble_npl_callout *co);
bool npl_freertos_callout_is_active(struct ble_npl_callout *co);
ble_npl_time_t npl_freertos_callout_get_ticks(struct ble_npl_callout *co);
ble_npl_error_t npl_freertos_callout_reset(struct ble_npl_callout *co,
ble_npl_time_t ticks);
ble_npl_time_t npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co,
ble_npl_time_t now);
ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms,
ble_npl_time_t *out_ticks);
ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks,
uint32_t *out_ms);
uint32_t npl_freertos_hw_enter_critical(void);
void npl_freertos_hw_exit_critical(uint32_t ctx);
#ifdef __cplusplus
}
#endif
#endif /* _NPL_FREERTOS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <inttypes.h>
#include "driver/uart.h"
/**
* Function prototype for UART driver to ask for more data to send.
* Returns -1 if no more data is available for TX.
* Driver must call this with interrupts disabled.
*/
typedef int (*hci_uart_tx_char)(void *arg);
/**
* Function prototype for UART driver to report that transmission is
* complete. This should be called when transmission of last byte is
* finished.
* Driver must call this with interrupts disabled.
*/
typedef void (*hci_uart_tx_done)(void *arg);
/**
* Function prototype for UART driver to report incoming byte of data.
* Returns -1 if data was dropped.
* Driver must call this with interrupts disabled.
*/
typedef int (*hci_uart_rx_char)(void *arg, uint8_t byte);
/**
* Initializes given uart. Mapping of logical UART number to physical
* UART/GPIO pins is in BSP.
*/
int hci_uart_init_cbs(int uart, hci_uart_tx_char tx_func,
hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg);
/**
* Applies given configuration to UART.
*
* @param port_num The UART number to configure
* @param speed The baudrate in bps to configure
* @param databits The number of databits to send per byte
* @param stopbits The number of stop bits to send
* @param parity The UART parity
* @param flow_ctl Flow control settings on the UART
*
* @return 0 on success, non-zero error code on failure
*/
int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl);
/**
* Close UART port. Can call hal_uart_config() with different settings after
* calling this.
*
* @param port_num The UART number to close
*/
int hci_uart_close(int port_num);
/**
* More data queued for transmission. UART driver will start asking for that
* data.
*
* @param port_num The UART number to start TX on
*/
void hci_uart_start_tx(int port_num);
/**
* Upper layers have consumed some data, and are now ready to receive more.
* This is meaningful after uart_rx_char callback has returned -1 telling
* that no more data can be accepted.
*
* @param port_num The UART number to begin RX on
*/
void hci_uart_start_rx(int port_num);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,190 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "hci_uart.h"
#include "esp_log.h"
#include "esp_attr.h"
#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART
static const char *TAG = "hci_uart";
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
#define HCI_UART_TX_PIN CONFIG_BT_LE_HCI_UART_TX_PIN
#define HCI_UART_RX_PIN CONFIG_BT_LE_HCI_UART_RX_PIN
#ifdef CONFIG_BT_LE_HCI_UART_FLOWCTRL
#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_CTS_RTS
#define HCI_UART_RTS_PIN CONFIG_BT_LE_HCI_UART_RTS_PIN
#define HCI_UART_CTS_PIN CONFIG_BT_LE_HCI_UART_CTS_PIN
#else
#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_DISABLE
#define HCI_UART_RTS_PIN (-1)
#define HCI_UART_CTS_PIN (-1)
#endif
typedef struct {
bool uart_opened;
uart_port_t port;
uart_config_t cfg;
QueueHandle_t evt_queue;
TaskHandle_t rx_task_handler;
hci_uart_tx_char tx_char;
hci_uart_tx_done tx_done;
hci_uart_rx_char rx_char;
void *u_func_arg;
} hci_uart_t;
static hci_uart_t hci_uart;
static void IRAM_ATTR hci_uart_rx_task(void *pvParameters)
{
uart_event_t event;
uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);
while (hci_uart.uart_opened) {
//Waiting for UART event.
if (xQueueReceive(hci_uart.evt_queue, (void * )&event, (TickType_t)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
ESP_LOGD(TAG, "uart[%d] event:", hci_uart.port);
switch (event.type) {
//Event of UART receving data
/*We'd better handler data event fast, there would be much more data events than
other types of events. If we take too much time on data event, the queue might
be full.*/
case UART_DATA:
// ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(hci_uart.port, dtmp, event.size, portMAX_DELAY);
for (int i = 0 ; i < event.size; i++) {
hci_uart.rx_char(hci_uart.u_func_arg, dtmp[i]);
}
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
uart_flush_input(hci_uart.port);
xQueueReset(hci_uart.evt_queue);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
uart_flush_input(hci_uart.port);
xQueueReset(hci_uart.evt_queue);
break;
//Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
//Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
//Others
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
hci_uart.rx_task_handler = NULL;
vTaskDelete(NULL);
}
int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits,
uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl)
{
uart_config_t uart_cfg = {
.baud_rate = baud_rate,
.data_bits = data_bits,
.parity = parity,
.stop_bits = stop_bits,
.flow_ctrl = HCI_UART_FLOWCTRL,
.source_clk = UART_SCLK_DEFAULT,
};
hci_uart.port = port_num;
hci_uart.cfg = uart_cfg;
int intr_alloc_flags = 0;
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
printf("set uart pin tx:%d, rx:%d.\n", HCI_UART_TX_PIN, HCI_UART_RX_PIN);
printf("set rts:%d, cts:%d.\n", HCI_UART_RTS_PIN, HCI_UART_RTS_PIN);
printf("set baud_rate:%d.\n", baud_rate);
ESP_ERROR_CHECK(uart_driver_delete(port_num));
ESP_ERROR_CHECK(uart_driver_install(port_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, &hci_uart.evt_queue, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(port_num, &hci_uart.cfg));
ESP_ERROR_CHECK(uart_set_pin(port_num, HCI_UART_TX_PIN, HCI_UART_RX_PIN, HCI_UART_RTS_PIN, HCI_UART_CTS_PIN));
hci_uart.uart_opened = true;
//Create a task to handler UART event from ISR
xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &hci_uart.rx_task_handler);
return 0;
}
void IRAM_ATTR hci_uart_start_tx(int port_num)
{
int data;
uint8_t u8_data = 0;
while (1) {
data = hci_uart.tx_char(hci_uart.u_func_arg);
if (data >= 0) {
u8_data = data;
uart_tx_chars(port_num, (char *)&u8_data, 1);
} else {
break;
}
}
if (hci_uart.tx_done) {
hci_uart.tx_done(hci_uart.u_func_arg);
}
}
int hci_uart_init_cbs(int port_num, hci_uart_tx_char tx_func,
hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg)
{
hci_uart.tx_char = tx_func;
hci_uart.rx_char = rx_func;
hci_uart.tx_done = tx_done;
hci_uart.u_func_arg = arg;
return 0;
}
int hci_uart_close(int port_num)
{
hci_uart.uart_opened = false;
// Stop uart rx task
if (hci_uart.rx_task_handler != NULL) {
ESP_LOGW(TAG, "Waiting for uart task finish...");
}
while (hci_uart.rx_task_handler != NULL);
uart_driver_delete(port_num);
ESP_LOGI(TAG, "hci uart close success.");
return 0;
}
#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART

View File

@ -125,6 +125,8 @@ ignore:
include:
- components/bt/host/nimble/nimble/
- components/bt/common/osi/
- components/bt/porting/ext/
- components/bt/porting/nimble/
- components/http_parser/
- components/wpa_supplicant/src/
- '!components/wpa_supplicant/esp_supplicant/'