mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-04 08:10:05 +00:00
nimble/transport: Remove da1469x transport
We do not need transport for proprietary controller provided by Dialog since we can run our own controller on CMAC.
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
/src/libble_stack_da1469x.a
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
Integrated BLE Controller (CMAC) requires a binary firmware to be loaded. Such
|
||||
firmware is distributed by Dialog Semiconductor in SDK package which has to be
|
||||
obtained separately, see:
|
||||
https://www.dialog-semiconductor.com/products/da1469x-product-family
|
||||
|
||||
Firmware is available as part of following library in SDK package:
|
||||
sdk/interfaces/ble/binaries/DA1469x-Release/libble_stack_da1469x.a
|
||||
|
||||
By default, CMAC driver will look for this file in its package root directory
|
||||
(i.e. nimble/transport/da1469x/cmac_driver) but this can be changed using
|
||||
CMAC_IMAGE_FILE_NAME syscfg variable.
|
||||
|
||||
Current version of CMAC driver was tested with SDK version 10.0.4.66.
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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 __CMAC_HOST_H_
|
||||
#define __CMAC_HOST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (* cmac_mbox_read_cb)(const uint8_t *, uint16_t len);
|
||||
|
||||
void cmac_host_init(void);
|
||||
void cmac_mbox_write(const uint8_t *buf, size_t len);
|
||||
void cmac_mbox_set_read_cb(cmac_mbox_read_cb cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CMAC_HOST_H_ */
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
pkg.name: nimble/transport/da1469x/cmac_driver
|
||||
pkg.description: Driver for Dialog's BLE controller
|
||||
pkg.author:
|
||||
pkg.homepage:
|
||||
pkg.keywords:
|
||||
|
||||
pkg.pre_link_cmds.BLE_HOST:
|
||||
scripts/build_libcmac.sh: 100
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
if [ ! -f ${MYNEWT_VAL_CMAC_IMAGE_FILE_NAME} ]; then
|
||||
>&2 echo ERROR: BLE stack library not found. Please check nimble/transport/da1469x/README for details.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OBJCOPY=${MYNEWT_OBJCOPY_PATH}
|
||||
AR=${MYNEWT_AR_PATH}
|
||||
LIBBLE_A=$(readlink -e ${MYNEWT_VAL_CMAC_IMAGE_FILE_NAME})
|
||||
LIBCMAC_A=${MYNEWT_USER_SRC_DIR}/libcmac.a
|
||||
|
||||
BASENAME_ROM=cmac.rom
|
||||
BASENAME_RAM=cmac.ram
|
||||
|
||||
cd ${MYNEWT_USER_WORK_DIR}
|
||||
|
||||
# Extract firmware binary from .a since we do not need to link all other
|
||||
# objects with our image.
|
||||
${AR} x ${LIBBLE_A} cmac_fw.c.obj
|
||||
${OBJCOPY} -O binary --only-section=.cmi_fw_area cmac_fw.c.obj cmac.bin
|
||||
|
||||
# We need separate copies for RAM and ROM image since section names are derived
|
||||
# from file names. For now files are the same, but it would be possible to
|
||||
# link ROM image without data and shared sections which contains zeroes anyway.
|
||||
cp cmac.bin ${BASENAME_ROM}.bin
|
||||
cp cmac.bin ${BASENAME_RAM}.bin
|
||||
|
||||
# Convert both binaries to objects and create archive to link
|
||||
${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
|
||||
--rename-section .data=.libcmac.rom ${BASENAME_ROM}.bin ${BASENAME_ROM}.o
|
||||
${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \
|
||||
--rename-section .data=.libcmac.ram ${BASENAME_RAM}.bin ${BASENAME_RAM}.o
|
||||
${AR} -rcs ${LIBCMAC_A} ${BASENAME_ROM}.o ${BASENAME_RAM}.o
|
||||
@@ -1,326 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "os/os.h"
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#include "mcu/da1469x_lpclk.h"
|
||||
#include "mcu/da1469x_hal.h"
|
||||
#include "mcu/da1469x_pdc.h"
|
||||
#include "mcu/mcu.h"
|
||||
#include "cmac_driver/cmac_host.h"
|
||||
|
||||
#define CMAC_SYM_CONFIG ((void *)(0x00818f20 + MEMCTRL->CMI_CODE_BASE_REG))
|
||||
#define CMAC_SYM_CONFIG_DYN ((void *)(0x00821af8 + MEMCTRL->CMI_CODE_BASE_REG))
|
||||
#define CMAC_SYM_MBOX_RX ((void *)(0x008216b0 + MEMCTRL->CMI_CODE_BASE_REG))
|
||||
#define CMAC_SYM_MBOX_TX ((void *)(0x008218b0 + MEMCTRL->CMI_CODE_BASE_REG))
|
||||
|
||||
#define CMAC_MBOX_SIZE 504
|
||||
#define CMAC_MBOX_F_RESET 0x0008
|
||||
#define CMAC_MBOX_F_WRITEPENDING 0x0010
|
||||
|
||||
struct cmac_config {
|
||||
uint8_t bdaddr[6]; /* Device address */
|
||||
|
||||
uint8_t rf_calibration_delay;
|
||||
|
||||
uint8_t lp_clock_freq; /* Sleep clock frequency (0 = 32768Hz, 1 = 32000Hz) */
|
||||
uint16_t lp_clock_sca; /* Sleep clock accuracy [ppm] */
|
||||
|
||||
uint16_t rx_buf_len; /* RX buffer size */
|
||||
uint16_t tx_buf_len; /* TX buffer size */
|
||||
bool initial_length_req;
|
||||
|
||||
/* Channel assessment algorithm settings */
|
||||
uint16_t chan_assess_itvl;
|
||||
uint8_t chan_assess_itvl_mult;
|
||||
int8_t chan_assess_min_rssi;
|
||||
uint16_t chan_assess_pkt_num;
|
||||
uint16_t chan_assess_bad_pkt_num;
|
||||
|
||||
/* Calibration settings */
|
||||
uint8_t system_tcs_length;
|
||||
uint8_t synth_tcs_length;
|
||||
uint8_t rfcu_tcs_length;
|
||||
|
||||
uint8_t default_tx_power; /* Default TX power for connection/advertising */
|
||||
bool filter_dup_ov_discard; /* Discard unknown devices when filter buffer is full */
|
||||
bool use_hp_1m;
|
||||
bool use_hp_2m;
|
||||
};
|
||||
|
||||
struct cmac_config_dynamic {
|
||||
bool enable_sleep; /* Enable sleep */
|
||||
|
||||
/* More options here, don't care now */
|
||||
};
|
||||
|
||||
struct cmac_mbox {
|
||||
volatile uint16_t magic;
|
||||
volatile uint16_t flags;
|
||||
volatile uint16_t wr_off;
|
||||
volatile uint16_t rd_off;
|
||||
uint8_t data[CMAC_MBOX_SIZE];
|
||||
};
|
||||
|
||||
/* CMAC data */
|
||||
extern char _binary_cmac_rom_bin_start[];
|
||||
extern char _binary_cmac_rom_bin_end;
|
||||
extern char _binary_cmac_ram_bin_start[];
|
||||
extern char _binary_cmac_ram_bin_end;
|
||||
|
||||
struct cmac_image_info {
|
||||
uint32_t _dummy1;
|
||||
uint32_t size_rom;
|
||||
uint32_t _dummy2;
|
||||
uint32_t magic;
|
||||
uint32_t _dummy3[5];
|
||||
};
|
||||
|
||||
/* Mailboxes for SYS<->CMAC communication */
|
||||
static struct cmac_mbox *cmac_mbox_rx;
|
||||
static struct cmac_mbox *cmac_mbox_tx;
|
||||
|
||||
/* PDC entry for waking up CMAC */
|
||||
static int8_t g_cmac_host_pdc_sys2cmac;
|
||||
/* PDC entry for waking up M33 */
|
||||
static int8_t g_cmac_host_pdc_cmac2sys;
|
||||
/* Callback for data ready from CMAC */
|
||||
static cmac_mbox_read_cb g_cmac_mbox_read_cb;
|
||||
|
||||
static inline void
|
||||
cmac_host_signal2cmac(void)
|
||||
{
|
||||
da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
|
||||
}
|
||||
|
||||
static void
|
||||
cmac2sys_isr(void)
|
||||
{
|
||||
uint16_t wr_off;
|
||||
uint16_t rd_off;
|
||||
uint16_t chunk;
|
||||
uint16_t len;
|
||||
|
||||
os_trace_isr_enter();
|
||||
|
||||
/* Clear CMAC2SYS interrupt */
|
||||
*(volatile uint32_t *)0x40002000 = 2;
|
||||
|
||||
if (*(volatile uint32_t *)0x40002000 & 0x1c00) {
|
||||
/* XXX CMAC is in error state, need to recover */
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (cmac_mbox_rx->flags & CMAC_MBOX_F_RESET) {
|
||||
cmac_mbox_rx->flags &= ~CMAC_MBOX_F_RESET;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!g_cmac_mbox_read_cb) {
|
||||
cmac_mbox_rx->rd_off = cmac_mbox_rx->wr_off;
|
||||
goto done;
|
||||
}
|
||||
|
||||
do {
|
||||
rd_off = cmac_mbox_rx->rd_off;
|
||||
wr_off = cmac_mbox_rx->wr_off;
|
||||
|
||||
if (rd_off <= wr_off) {
|
||||
chunk = wr_off - rd_off;
|
||||
} else {
|
||||
chunk = CMAC_MBOX_SIZE - rd_off;
|
||||
}
|
||||
|
||||
while (chunk) {
|
||||
len = g_cmac_mbox_read_cb(&cmac_mbox_rx->data[rd_off], chunk);
|
||||
|
||||
rd_off += len;
|
||||
chunk -= len;
|
||||
};
|
||||
|
||||
cmac_mbox_rx->rd_off = rd_off % CMAC_MBOX_SIZE;
|
||||
} while (cmac_mbox_rx->rd_off != cmac_mbox_rx->wr_off);
|
||||
|
||||
done:
|
||||
|
||||
if (cmac_mbox_rx->flags & CMAC_MBOX_F_WRITEPENDING) {
|
||||
cmac_host_signal2cmac();
|
||||
}
|
||||
|
||||
os_trace_isr_exit();
|
||||
}
|
||||
|
||||
static void
|
||||
cmac_host_lpclk_cb(uint32_t freq)
|
||||
{
|
||||
struct cmac_config_dynamic *cmac_config_dyn;
|
||||
|
||||
cmac_config_dyn = CMAC_SYM_CONFIG_DYN;
|
||||
cmac_config_dyn->enable_sleep = freq == 32768;
|
||||
}
|
||||
|
||||
void
|
||||
cmac_mbox_write(const uint8_t *buf, size_t len)
|
||||
{
|
||||
uint16_t wr_off;
|
||||
uint16_t rd_off;
|
||||
uint16_t chunk;
|
||||
uint32_t primask;
|
||||
|
||||
__HAL_DISABLE_INTERRUPTS(primask);
|
||||
|
||||
while (len) {
|
||||
rd_off = cmac_mbox_tx->rd_off;
|
||||
wr_off = cmac_mbox_tx->wr_off;
|
||||
|
||||
if (rd_off > wr_off) {
|
||||
chunk = min(len, rd_off - wr_off);
|
||||
} else {
|
||||
chunk = min(len, CMAC_MBOX_SIZE - wr_off);
|
||||
}
|
||||
|
||||
if (chunk == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(&cmac_mbox_tx->data[wr_off], buf, chunk);
|
||||
|
||||
wr_off += chunk;
|
||||
cmac_mbox_tx->wr_off = wr_off % CMAC_MBOX_SIZE;
|
||||
|
||||
cmac_host_signal2cmac();
|
||||
|
||||
len -= chunk;
|
||||
buf += chunk;
|
||||
}
|
||||
|
||||
__HAL_ENABLE_INTERRUPTS(primask);
|
||||
}
|
||||
|
||||
void
|
||||
cmac_mbox_set_read_cb(cmac_mbox_read_cb cb)
|
||||
{
|
||||
g_cmac_mbox_read_cb = cb;
|
||||
}
|
||||
|
||||
void
|
||||
cmac_host_init(void)
|
||||
{
|
||||
struct cmac_image_info ii;
|
||||
uint32_t cmac_rom_size;
|
||||
uint32_t cmac_ram_size;
|
||||
struct cmac_config *cmac_config;
|
||||
struct cmac_config_dynamic *cmac_config_dyn;
|
||||
|
||||
/* Add PDC entry to wake up CMAC from M33 */
|
||||
g_cmac_host_pdc_sys2cmac = da1469x_pdc_add(MCU_PDC_TRIGGER_MAC_TIMER,
|
||||
MCU_PDC_MASTER_CMAC,
|
||||
MCU_PDC_EN_XTAL);
|
||||
da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
|
||||
da1469x_pdc_ack(g_cmac_host_pdc_sys2cmac);
|
||||
|
||||
/* Add PDC entry to wake up M33 from CMAC, if does not exist yet */
|
||||
g_cmac_host_pdc_cmac2sys = da1469x_pdc_find(MCU_PDC_TRIGGER_COMBO,
|
||||
MCU_PDC_MASTER_M33, 0);
|
||||
if (g_cmac_host_pdc_cmac2sys < 0) {
|
||||
g_cmac_host_pdc_cmac2sys = da1469x_pdc_add(MCU_PDC_TRIGGER_COMBO,
|
||||
MCU_PDC_MASTER_M33,
|
||||
MCU_PDC_EN_XTAL);
|
||||
da1469x_pdc_set(g_cmac_host_pdc_cmac2sys);
|
||||
da1469x_pdc_ack(g_cmac_host_pdc_cmac2sys);
|
||||
}
|
||||
|
||||
/* Enable Radio LDO */
|
||||
CRG_TOP->POWER_CTRL_REG |= CRG_TOP_POWER_CTRL_REG_LDO_RADIO_ENABLE_Msk;
|
||||
|
||||
/* Enable CMAC, but keep it in reset */
|
||||
CRG_TOP->CLK_RADIO_REG = (1 << CRG_TOP_CLK_RADIO_REG_RFCU_ENABLE_Pos) |
|
||||
(1 << CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Pos) |
|
||||
(0 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_SEL_Pos) |
|
||||
(1 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_ENABLE_Pos) |
|
||||
(0 << CRG_TOP_CLK_RADIO_REG_CMAC_DIV_Pos);
|
||||
|
||||
/* Calculate size of ROM and RAM area (for now they should be the same) */
|
||||
cmac_rom_size = &_binary_cmac_rom_bin_end - &_binary_cmac_rom_bin_start[0];
|
||||
cmac_ram_size = &_binary_cmac_ram_bin_end - &_binary_cmac_ram_bin_start[0];
|
||||
assert(cmac_rom_size == cmac_ram_size);
|
||||
|
||||
/* Load image header and check if image can be loaded */
|
||||
memcpy(&ii, &_binary_cmac_rom_bin_start, sizeof(ii));
|
||||
assert(ii.magic == 0x43414d43); /* "CMAC" */
|
||||
|
||||
/* Copy CMAC image to RAM */
|
||||
memset(&_binary_cmac_ram_bin_start, 0, cmac_ram_size);
|
||||
memcpy(&_binary_cmac_ram_bin_start, &_binary_cmac_rom_bin_start[sizeof(ii)],
|
||||
ii.size_rom);
|
||||
|
||||
/*
|
||||
* Setup memory controller for CMAC
|
||||
* Code and data are set to the same address initially since CMAC will
|
||||
* update data address on init. Also shared address is updated on init.
|
||||
*/
|
||||
MEMCTRL->CMI_CODE_BASE_REG = (uint32_t)&_binary_cmac_ram_bin_start;
|
||||
MEMCTRL->CMI_DATA_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG;
|
||||
MEMCTRL->CMI_SHARED_BASE_REG = 0;
|
||||
MEMCTRL->CMI_END_REG = (uint32_t)&_binary_cmac_ram_bin_end;
|
||||
|
||||
/* Symbols below are in shared memory, can update them now */
|
||||
cmac_config = CMAC_SYM_CONFIG;
|
||||
cmac_config_dyn = CMAC_SYM_CONFIG_DYN;
|
||||
cmac_mbox_rx = CMAC_SYM_MBOX_RX;
|
||||
cmac_mbox_tx = CMAC_SYM_MBOX_TX;
|
||||
|
||||
/* Update CMAC configuration */
|
||||
cmac_config->lp_clock_freq = 0;
|
||||
cmac_config->lp_clock_sca = 50;
|
||||
cmac_config->rx_buf_len = 251 + 11;
|
||||
cmac_config->tx_buf_len = 251 + 11;
|
||||
cmac_config->initial_length_req = 0;
|
||||
cmac_config->system_tcs_length = 0;
|
||||
cmac_config->synth_tcs_length = 0;
|
||||
cmac_config->rfcu_tcs_length = 0;
|
||||
cmac_config->default_tx_power = 4;
|
||||
cmac_config_dyn->enable_sleep = false;
|
||||
|
||||
/* Release CMAC from reset */
|
||||
CRG_TOP->CLK_RADIO_REG &= ~CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk;
|
||||
|
||||
/* Wait for CMAC to update registers */
|
||||
while (MEMCTRL->CMI_DATA_BASE_REG == MEMCTRL->CMI_CODE_BASE_REG);
|
||||
while (MEMCTRL->CMI_SHARED_BASE_REG != (MEMCTRL->CMI_END_REG & 0xfffffc00));
|
||||
|
||||
/* Initialize mailboxes and sync with CMAC */
|
||||
cmac_mbox_tx->flags = CMAC_MBOX_F_RESET;
|
||||
cmac_mbox_tx->wr_off = 0;
|
||||
cmac_mbox_tx->rd_off = 0;
|
||||
cmac_mbox_tx->magic = 0xa55a;
|
||||
while (cmac_mbox_rx->magic != 0xa55a);
|
||||
|
||||
NVIC_SetVector(CMAC2SYS_IRQn, (uint32_t)cmac2sys_isr);
|
||||
NVIC_SetPriority(CMAC2SYS_IRQn, 0);
|
||||
NVIC_EnableIRQ(CMAC2SYS_IRQn);
|
||||
|
||||
cmac_host_signal2cmac();
|
||||
|
||||
da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
syscfg.defs:
|
||||
CMAC_IMAGE_FILE_NAME:
|
||||
description: >
|
||||
Path to library with CMAC firmware. See README for details.
|
||||
value: "libble_stack_da1469x.a"
|
||||
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
pkg.name: nimble/transport/da1469x
|
||||
pkg.description: HCI transport for DA1469x
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
|
||||
pkg.deps:
|
||||
- "@apache-mynewt-nimble/nimble"
|
||||
- "@apache-mynewt-nimble/nimble/transport/da1469x/cmac_driver"
|
||||
- "@apache-mynewt-core/kernel/os"
|
||||
|
||||
pkg.apis:
|
||||
- ble_transport
|
||||
|
||||
pkg.init:
|
||||
da1469x_ble_hci_init: 100
|
||||
da1469x_ble_hci_cmac_init: 201
|
||||
@@ -1,368 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "os/mynewt.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/ble_hci_trans.h"
|
||||
#include "nimble/hci_common.h"
|
||||
#include "cmac_driver/cmac_host.h"
|
||||
|
||||
#define HCI_PKT_NONE 0x00
|
||||
#define HCI_PKT_CMD 0x01
|
||||
#define HCI_PKT_ACL 0x02
|
||||
#define HCI_PKT_EVT 0x04
|
||||
|
||||
#define POOL_ACL_BLOCK_SIZE \
|
||||
OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) + \
|
||||
BLE_MBUF_MEMBLOCK_OVERHEAD + \
|
||||
BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
|
||||
|
||||
struct da1469x_ble_hci_host_api {
|
||||
ble_hci_trans_rx_cmd_fn *evt_cb;
|
||||
void *evt_arg;
|
||||
ble_hci_trans_rx_acl_fn *acl_cb;
|
||||
void *acl_arg;
|
||||
};
|
||||
|
||||
struct da1469x_ble_hci_rx_data {
|
||||
uint8_t type;
|
||||
uint8_t hdr[4];
|
||||
uint8_t min_len;
|
||||
uint16_t len;
|
||||
uint16_t expected_len;
|
||||
union {
|
||||
uint8_t *buf;
|
||||
struct os_mbuf *om;
|
||||
};
|
||||
};
|
||||
|
||||
struct da1469x_ble_hci_pool_cmd {
|
||||
uint8_t cmd[BLE_HCI_TRANS_CMD_SZ];
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
/* (Pseudo)pool for HCI commands */
|
||||
static struct da1469x_ble_hci_pool_cmd da1469x_ble_hci_pool_cmd;
|
||||
|
||||
/* Pools for HCI events (high and low priority) */
|
||||
static uint8_t da1469x_ble_hci_pool_evt_hi_buf[ OS_MEMPOOL_BYTES(
|
||||
MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) ];
|
||||
static struct os_mempool da1469x_ble_hci_pool_evt_hi;
|
||||
static uint8_t da1469x_ble_hci_pool_evt_lo_buf[ OS_MEMPOOL_BYTES(
|
||||
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) ];
|
||||
static struct os_mempool da1469x_ble_hci_pool_evt_lo;
|
||||
|
||||
/* Pool for ACL data */
|
||||
static uint8_t da1469x_ble_hci_pool_acl_buf[ OS_MEMPOOL_BYTES(
|
||||
MYNEWT_VAL(BLE_ACL_BUF_COUNT),
|
||||
POOL_ACL_BLOCK_SIZE) ];
|
||||
static struct os_mempool da1469x_ble_hci_pool_acl;
|
||||
static struct os_mbuf_pool da1469x_ble_hci_pool_acl_mbuf;
|
||||
|
||||
/* Interface to host */
|
||||
static struct da1469x_ble_hci_host_api da1469x_ble_hci_host_api;
|
||||
|
||||
/* State of RX currently in progress (needs to reassemble frame) */
|
||||
static struct da1469x_ble_hci_rx_data da1469x_ble_hci_rx_data;
|
||||
|
||||
int
|
||||
ble_hci_trans_reset(void)
|
||||
{
|
||||
/* XXX Should we do something with RF and/or BLE core? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
da1469x_ble_hci_host_api.evt_cb = evt_cb;
|
||||
da1469x_ble_hci_host_api.evt_arg = evt_arg;
|
||||
da1469x_ble_hci_host_api.acl_cb = acl_cb;
|
||||
da1469x_ble_hci_host_api.acl_arg = acl_arg;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
ble_hci_trans_buf_alloc(int type)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
switch (type) {
|
||||
case BLE_HCI_TRANS_BUF_CMD:
|
||||
assert(!da1469x_ble_hci_pool_cmd.allocated);
|
||||
da1469x_ble_hci_pool_cmd.allocated = 1;
|
||||
buf = da1469x_ble_hci_pool_cmd.cmd;
|
||||
break;
|
||||
case BLE_HCI_TRANS_BUF_EVT_HI:
|
||||
buf = os_memblock_get(&da1469x_ble_hci_pool_evt_hi);
|
||||
if (buf) {
|
||||
break;
|
||||
}
|
||||
/* no break */
|
||||
case BLE_HCI_TRANS_BUF_EVT_LO:
|
||||
buf = os_memblock_get(&da1469x_ble_hci_pool_evt_lo);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
ble_hci_trans_buf_free(uint8_t *buf)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (buf == da1469x_ble_hci_pool_cmd.cmd) {
|
||||
assert(da1469x_ble_hci_pool_cmd.allocated);
|
||||
da1469x_ble_hci_pool_cmd.allocated = 0;
|
||||
} else if (os_memblock_from(&da1469x_ble_hci_pool_evt_hi, buf)) {
|
||||
rc = os_memblock_put(&da1469x_ble_hci_pool_evt_hi, buf);
|
||||
assert(rc == 0);
|
||||
} else {
|
||||
assert(os_memblock_from(&da1469x_ble_hci_pool_evt_lo, buf));
|
||||
rc = os_memblock_put(&da1469x_ble_hci_pool_evt_lo, buf);
|
||||
assert(rc == 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
|
||||
{
|
||||
uint8_t ind = HCI_PKT_CMD;
|
||||
int len = 3 + cmd[2];
|
||||
|
||||
cmac_mbox_write(&ind, 1);
|
||||
cmac_mbox_write(cmd, len);
|
||||
|
||||
ble_hci_trans_buf_free(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
|
||||
{
|
||||
uint8_t ind = HCI_PKT_ACL;
|
||||
struct os_mbuf *x;
|
||||
|
||||
cmac_mbox_write(&ind, 1);
|
||||
|
||||
x = om;
|
||||
while (x) {
|
||||
cmac_mbox_write(x->om_data, x->om_len);
|
||||
x = SLIST_NEXT(x, om_next);
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(om);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
da1469x_ble_hci_trans_ll_rx(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
struct da1469x_ble_hci_rx_data *rxd = &da1469x_ble_hci_rx_data;
|
||||
void *data;
|
||||
int pool = BLE_HCI_TRANS_BUF_EVT_HI;
|
||||
int rc;
|
||||
|
||||
assert(len);
|
||||
|
||||
if (rxd->type == HCI_PKT_NONE) {
|
||||
rxd->type = buf[0];
|
||||
rxd->len = 0;
|
||||
rxd->expected_len = 0;
|
||||
|
||||
switch (rxd->type) {
|
||||
case HCI_PKT_ACL:
|
||||
rxd->min_len = 4;
|
||||
break;
|
||||
case HCI_PKT_EVT:
|
||||
rxd->min_len = 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ensure we have minimum length of bytes required to process header */
|
||||
if (rxd->len < rxd->min_len) {
|
||||
len = min(len, rxd->min_len - rxd->len);
|
||||
memcpy(&rxd->hdr[rxd->len], buf, len);
|
||||
rxd->len += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Parse header and allocate proper buffer if not done yet */
|
||||
if (rxd->expected_len == 0) {
|
||||
switch (rxd->type) {
|
||||
case HCI_PKT_ACL:
|
||||
data = os_mbuf_get_pkthdr(&da1469x_ble_hci_pool_acl_mbuf,
|
||||
sizeof(struct ble_mbuf_hdr));
|
||||
if (!data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rxd->om = data;
|
||||
os_mbuf_append(rxd->om, rxd->hdr, rxd->len);
|
||||
rxd->expected_len = get_le16(&rxd->hdr[2]) + 4;
|
||||
break;
|
||||
case HCI_PKT_EVT:
|
||||
if (rxd->hdr[0] == BLE_HCI_EVCODE_LE_META) {
|
||||
/* For LE Meta event we need 3 bytes to parse header */
|
||||
if (rxd->min_len < 3) {
|
||||
rxd->min_len = 3;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Advertising reports shall be allocated from low-prio pool */
|
||||
if ((rxd->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
|
||||
(rxd->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
|
||||
pool = BLE_HCI_TRANS_BUF_EVT_LO;
|
||||
}
|
||||
}
|
||||
|
||||
data = ble_hci_trans_buf_alloc(pool);
|
||||
if (!data) {
|
||||
/*
|
||||
* Only care about valid buffer when shall be allocated from
|
||||
* high-prio pool, otherwise NULL is fine and we'll just skip
|
||||
* this event.
|
||||
*/
|
||||
if (pool != BLE_HCI_TRANS_BUF_EVT_LO) {
|
||||
data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
|
||||
if (!data) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rxd->buf = data;
|
||||
memcpy(rxd->buf, rxd->hdr, rxd->len);
|
||||
rxd->expected_len = rxd->hdr[1] + 2;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
len = min(len, rxd->expected_len - rxd->len);
|
||||
|
||||
switch (rxd->type) {
|
||||
case HCI_PKT_ACL:
|
||||
os_mbuf_append(rxd->om, buf, len);
|
||||
rxd->len += len;
|
||||
|
||||
if (rxd->len == rxd->expected_len) {
|
||||
rc = da1469x_ble_hci_host_api.acl_cb(rxd->om,
|
||||
da1469x_ble_hci_host_api.acl_arg);
|
||||
if (rc != 0) {
|
||||
os_mbuf_free_chain(rxd->om);
|
||||
}
|
||||
rxd->type = HCI_PKT_NONE;
|
||||
}
|
||||
break;
|
||||
case HCI_PKT_EVT:
|
||||
if (rxd->buf) {
|
||||
memcpy(&rxd->buf[rxd->len], buf, len);
|
||||
}
|
||||
rxd->len += len;
|
||||
|
||||
if (rxd->len == rxd->expected_len) {
|
||||
/*
|
||||
* XXX for unknown reason at startup controller sends command
|
||||
* complete for a vendor specific command which we never sent
|
||||
* and this messes up with our ack code - just discard this
|
||||
* event
|
||||
*/
|
||||
if ((rxd->buf[0] == 0x0E) && (get_le16(&rxd->buf[3]) == 0xfc11)) {
|
||||
ble_hci_trans_buf_free(rxd->buf);
|
||||
} else if (rxd->buf) {
|
||||
rc = da1469x_ble_hci_host_api.evt_cb(rxd->buf,
|
||||
da1469x_ble_hci_host_api.evt_arg);
|
||||
if (rc != 0) {
|
||||
ble_hci_trans_buf_free(rxd->buf);
|
||||
}
|
||||
}
|
||||
rxd->type = HCI_PKT_NONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
da1469x_ble_hci_read_cb(const uint8_t *buf, uint16_t len)
|
||||
{
|
||||
return da1469x_ble_hci_trans_ll_rx(buf, len);
|
||||
}
|
||||
|
||||
void
|
||||
da1469x_ble_hci_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
SYSINIT_ASSERT_ACTIVE();
|
||||
|
||||
rc = os_mempool_init(&da1469x_ble_hci_pool_acl, MYNEWT_VAL(BLE_ACL_BUF_COUNT),
|
||||
POOL_ACL_BLOCK_SIZE, da1469x_ble_hci_pool_acl_buf,
|
||||
"da1469x_ble_hci_pool_acl");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mbuf_pool_init(&da1469x_ble_hci_pool_acl_mbuf,
|
||||
&da1469x_ble_hci_pool_acl, POOL_ACL_BLOCK_SIZE,
|
||||
MYNEWT_VAL(BLE_ACL_BUF_COUNT));
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&da1469x_ble_hci_pool_evt_hi,
|
||||
MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
|
||||
da1469x_ble_hci_pool_evt_hi_buf,
|
||||
"da1469x_ble_hci_pool_evt_hi");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&da1469x_ble_hci_pool_evt_lo,
|
||||
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
|
||||
da1469x_ble_hci_pool_evt_lo_buf,
|
||||
"da1469x_ble_hci_pool_evt_lo");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
}
|
||||
|
||||
void
|
||||
da1469x_ble_hci_cmac_init(void)
|
||||
{
|
||||
cmac_mbox_set_read_cb(da1469x_ble_hci_read_cb);
|
||||
cmac_host_init();
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
syscfg.vals.'!BLE_HCI_BRIDGE && !BLE_EXT_ADV':
|
||||
BLE_HCI_EVT_HI_BUF_COUNT: 2
|
||||
BLE_HCI_EVT_LO_BUF_COUNT: 8
|
||||
BLE_HCI_EVT_BUF_SIZE: 70
|
||||
BLE_ACL_BUF_COUNT: 4
|
||||
BLE_ACL_BUF_SIZE: 255
|
||||
|
||||
syscfg.vals.'!BLE_HCI_BRIDGE && BLE_EXT_ADV':
|
||||
BLE_HCI_EVT_BUF_SIZE: 274
|
||||
Reference in New Issue
Block a user