nimble/transport: Add HCI transport for Dialog CMAC

This adds transport for Dialog CMAC. It uses HCI H4 protocol over shared
memory buffers. Included driver takes care of CMAC initialization.

Once host build is switched to "dialog_cmac" transport, proper image for
CMAC is automatically built and integrated with host image. A sample
target will be provided separatety.
This commit is contained in:
Andrzej Kaczmarek
2020-09-21 13:53:51 +02:00
parent e69a66d715
commit 87599473e0
24 changed files with 2243 additions and 8 deletions
+2
View File
@@ -0,0 +1,2 @@
/src/libble_stack_da1469x.a
@@ -0,0 +1,28 @@
#
# 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/dialog_cmac/cmac_driver/diag
pkg.description: Default diag configuration for CMAC
pkg.author: "Apache Mynewt <[email protected]>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- dialog
- da1469x
- cmac
pkg.apis: dialog_cmac_diag
@@ -0,0 +1,68 @@
/*
* 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 "syscfg/syscfg.h"
#include "mcu/mcu.h"
#if MYNEWT_VAL(BLE_HOST)
void
cmac_diag_setup_host(void)
{
/* Setup pins for diagnostic signals */
mcu_gpio_set_pin_function(42, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG0); /* DIAG_0 @ P1.10 */
mcu_gpio_set_pin_function(43, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG1); /* DIAG_1 @ P1.11 */
mcu_gpio_set_pin_function(44, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG2); /* DIAG_2 @ P1.12 */
mcu_gpio_set_pin_function(24, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_3 @ P0.24 */
mcu_gpio_set_pin_function(21, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_4 @ P0.21 */
mcu_gpio_set_pin_function(20, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_5 @ P0.20 */
mcu_gpio_set_pin_function(19, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_6 @ P0.19 */
mcu_gpio_set_pin_function(18, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_7 @ P0.18 */
mcu_gpio_set_pin_function(31, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_8 @ P0.31 */
mcu_gpio_set_pin_function(30, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_9 @ P0.30 */
mcu_gpio_set_pin_function(29, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_10 @ P0.29 */
mcu_gpio_set_pin_function(28, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_11 @ P0.28 */
mcu_gpio_set_pin_function(27, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_12 @ P0.27 */
mcu_gpio_set_pin_function(26, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_13 @ P0.26 */
mcu_gpio_set_pin_function(38, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_14 @ P1.06 */
mcu_gpio_set_pin_function(41, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_15 @ P1.09 */
}
#endif
#if MYNEWT_VAL(BLE_CONTROLLER)
void
cmac_diag_setup_cmac(void)
{
MCU_DIAG_MAP( 0, 4, DSER);
MCU_DIAG_MAP( 1, 6, CMAC_ON_ERROR);
MCU_DIAG_MAP( 2, 2, PHY_TX_EN);
MCU_DIAG_MAP( 3, 2, PHY_RX_EN);
MCU_DIAG_MAP( 4, 2, PHY_TXRX_DATA_COMB);
MCU_DIAG_MAP( 5, 2, PHY_TXRX_DATA_EN_COMB);
MCU_DIAG_MAP( 6, 5, EV1US_FRAME_START);
MCU_DIAG_MAP( 7, 5, EV_BS_START);
MCU_DIAG_MAP( 8, 5, EV1C_BS_STOP);
MCU_DIAG_MAP( 9, 5, EV1US_PHY_TO_IDLE);
MCU_DIAG_MAP(10, 9, CALLBACK_IRQ);
MCU_DIAG_MAP(11, 9, FIELD_IRQ);
MCU_DIAG_MAP(12, 9, FRAME_IRQ);
MCU_DIAG_MAP(13, 3, SLP_TIMER_ACTIVE);
MCU_DIAG_MAP(14, 4, SLEEPING);
MCU_DIAG_MAP(15, 8, LL_TIMER1_00);
}
#endif
@@ -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 __MCU_CMAC_DIAG_H_
#define __MCU_CMAC_DIAG_H_
#ifdef __cplusplus
extern "C" {
#endif
void cmac_diag_setup_host(void);
void cmac_diag_setup_cmac(void);
#ifdef __cplusplus
}
#endif
#endif /* __MCU_CMAC_DIAG_H_ */
@@ -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 __DA1469X_CMAC_V2_H_
#define __DA1469X_CMAC_V2_H_
#ifdef __cplusplus
extern "C" {
#endif
void cmac_host_init(void);
void cmac_host_signal2cmac(void);
#ifdef __cplusplus
}
#endif
#endif /* __DA1469X_CMAC_V2_H_ */
@@ -0,0 +1,164 @@
/*
* 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 __MCU_CMAC_SHARED_H_
#define __MCU_CMAC_SHARED_H_
#include <stdint.h>
#include "syscfg/syscfg.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CMAC_SHARED_MAGIC_CMAC (0x4C6C) /* "lL" */
#define CMAC_SHARED_MAGIC_SYS (0x5368) /* "hS" */
#define CMAC_SHARED_F_SYS_LPCLK_AVAILABLE (0x0001)
/*
* Simple circular buffer for storing random numbers generated by M33
* Empty: cmr_in = cmr_out = 0;
* Full: cmr_in + 1 = cmr_out
*
* cmr_in: used by the M33 to add random numbers to the circular buffer.
* cmr_out: used by CMAC to retrieve random numbers
*
* NOTE: cmr_in and cmr_out are indices.
*/
#define CMAC_RAND_BUF_ELEMS (16)
struct cmac_rand {
int cmr_active;
int cmr_in;
int cmr_out;
uint32_t cmr_buf[CMAC_RAND_BUF_ELEMS];
};
struct cmac_mbox {
uint16_t rd_off;
uint16_t wr_off;
};
struct cmac_dcdc {
uint8_t enabled;
uint32_t v18;
uint32_t v18p;
uint32_t vdd;
uint32_t v14;
uint32_t ctrl1;
};
struct cmac_trim {
uint8_t rfcu_len;
uint8_t rfcu_mode1_len;
uint8_t rfcu_mode2_len;
uint8_t synth_len;
uint32_t rfcu[ MYNEWT_VAL(CMAC_TRIM_SIZE_RFCU) ];
uint32_t rfcu_mode1[2];
uint32_t rfcu_mode2[2];
uint32_t synth[ MYNEWT_VAL(CMAC_TRIM_SIZE_SYNTH) ];
};
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
struct cmac_debug {
int8_t last_rx_rssi;
int8_t tx_power_override;
uint32_t cal_res_1;
uint32_t cal_res_2;
uint32_t trim_val1_tx_1;
uint32_t trim_val1_tx_2;
uint32_t trim_val2_tx;
uint32_t trim_val2_rx;
};
#endif
#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
struct cmac_coredump {
uint32_t lr;
uint32_t pc;
uint32_t assert;
const char *assert_file;
uint32_t assert_line;
uint32_t CM_STAT_REG;
uint32_t CM_LL_TIMER1_36_10_REG;
uint32_t CM_LL_TIMER1_9_0_REG;
uint32_t CM_ERROR_REG;
uint32_t CM_EXC_STAT_REG;
};
#endif
struct cmac_shared_data {
uint16_t magic_cmac;
uint16_t magic_sys;
uint32_t lp_clock_freq; /* LP clock frequency */
uint32_t xtal32m_settle_us;/* XTAL32M settling time */
struct cmac_mbox mbox_s2c; /* SYS2CMAC mailbox */
struct cmac_mbox mbox_c2s; /* CMAC2SYS mailbox */
struct cmac_dcdc dcdc; /* DCDC settings */
struct cmac_trim trim; /* Trim data */
struct cmac_rand rand; /* Random numbers */
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
struct cmac_debug debug; /* Extra debug data */
#endif
#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
struct cmac_coredump coredump;
#endif
uint8_t mbox_s2c_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_S2C) ];
uint8_t mbox_c2s_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_C2S) ];
};
#if MYNEWT_VAL(BLE_HOST)
extern volatile struct cmac_shared_data *g_cmac_shared_data;
#elif MYNEWT_VAL(BLE_CONTROLLER)
extern volatile struct cmac_shared_data g_cmac_shared_data;
#endif
/* cmac_mbox */
typedef int (cmac_mbox_read_cb)(const void *data, uint16_t len);
typedef void (cmac_mbox_write_notif_cb)(void);
void cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb);
void cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb);
int cmac_mbox_read(void);
int cmac_mbox_write(const void *data, uint16_t len);
/* cmac_rand */
typedef void (*cmac_rand_isr_cb_t)(uint8_t rnum);
void cmac_rand_start(void);
void cmac_rand_stop(void);
void cmac_rand_read(void);
void cmac_rand_write(void);
void cmac_rand_chk_fill(void);
int cmac_rand_get_next(void);
int cmac_rand_is_active(void);
int cmac_rand_is_full(void);
void cmac_rand_fill(uint32_t *buf, int num_words);
void cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb);
void cmac_shared_init(void);
void cmac_shared_sync(void);
#ifdef __cplusplus
}
#endif
#endif /* __MCU_CMAC_SHARED_H_ */
@@ -0,0 +1,39 @@
#
# 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/dialog_cmac/cmac_driver
pkg.description: Driver for Dialog CMAC IPC
pkg.author: "Apache Mynewt <[email protected]>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- dialog
- da1469x
- cmac
pkg.req_apis.CMAC_DEBUG_DIAG_ENABLE:
- dialog_cmac_diag
pkg.ign_files.BLE_CONTROLLER:
- cmac_host.c
pkg.post_link_cmds.BLE_CONTROLLER:
scripts/create_cmac_bin.sh: 100
pkg.pre_link_cmds.BLE_HOST:
scripts/build_libcmac.sh: 100
@@ -0,0 +1,45 @@
#!/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.
NEWT=${MYNEWT_NEWT_PATH}
OBJCOPY=${MYNEWT_OBJCOPY_PATH}
AR=${MYNEWT_AR_PATH}
LIBCMAC_A=${MYNEWT_USER_SRC_DIR}/libcmac.a
export WORK_DIR=${MYNEWT_USER_WORK_DIR}
export BASENAME_ROM=cmac.rom
export BASENAME_RAM=cmac.ram
if [ ${MYNEWT_VAL_CMAC_IMAGE_SINGLE} -eq 0 ]; then
# Create empty binary for ROM image (1 byte required for objcopy)
truncate -s 1 ${WORK_DIR}/${BASENAME_ROM}.bin
# Create fixed size RAM image
truncate -s ${MYNEWT_VAL_CMAC_IMAGE_RAM_SIZE} ${WORK_DIR}/${BASENAME_RAM}.bin
else
${NEWT} build ${MYNEWT_VAL_CMAC_IMAGE_TARGET_NAME}
fi
cd ${WORK_DIR}
# 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
@@ -0,0 +1,31 @@
#!/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.
OBJCOPY=${MYNEWT_OBJCOPY_PATH}
ELF=${MYNEWT_APP_BIN_DIR}/blehci.elf
cd ${WORK_DIR}
# Strip .ram section from ROM image
${OBJCOPY} -R .ram -O binary ${ELF} ${BASENAME_ROM}.bin
# RAM image is the same as binary created by newt
cp ${ELF}.bin ${BASENAME_RAM}.bin
# Create a copy of ROM image to flash to partition, if required
cp ${BASENAME_ROM}.bin ${ELF}.rom.bin
@@ -0,0 +1,306 @@
/*
* 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 "syscfg/syscfg.h"
#include "sysflash/sysflash.h"
#include "os/os.h"
#include "mcu/mcu.h"
#include "mcu/cmsis_nvic.h"
#include "mcu/da1469x_hal.h"
#include "mcu/da1469x_lpclk.h"
#include "mcu/da1469x_clock.h"
#include "mcu/da1469x_trimv.h"
#include "mcu/da1469x_pdc.h"
#include "cmac_driver/cmac_host.h"
#include "cmac_driver/cmac_shared.h"
#include "cmac_driver/cmac_diag.h"
#include "trng/trng.h"
#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
#include "console/console.h"
#endif
/* 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 magic;
uint32_t size_rom;
uint32_t size_ram;
uint32_t offset_data;
uint32_t offset_shared;
};
/* 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;
static void cmac_host_rand_fill(struct os_event *ev);
static struct os_event g_cmac_host_rand_ev = {
.ev_cb = cmac_host_rand_fill
};
static void cmac_host_rand_chk_fill(void);
static void
cmac2sys_isr(void)
{
#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
volatile struct cmac_coredump *cd = &g_cmac_shared_data->coredump;
const char *assert_file;
#endif
os_trace_isr_enter();
/* Clear CMAC2SYS interrupt */
*(volatile uint32_t *)0x40002000 = 2;
cmac_mbox_read();
if (*(volatile uint32_t *)0x40002000 & 0x1c00) {
#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE)
console_blocking_mode();
console_printf("CMAC error (0x%08lx)\n", *(volatile uint32_t *)0x40002000);
console_printf(" lr:0x%08lx pc:0x%08lx\n", cd->lr, cd->pc);
if (cd->assert) {
console_printf(" assert:0x%08lx\n", cd->assert);
if (cd->assert_file) {
/* Need to translate pointer from M0 code segment to M33 data */
assert_file = cd->assert_file + MCU_MEM_SYSRAM_START_ADDRESS +
MEMCTRL->CMI_CODE_BASE_REG;
console_printf(" %s:%d\n",
assert_file, (unsigned)cd->assert_line);
}
}
console_printf(" 0x%08lx CM_ERROR_REG\n", cd->CM_ERROR_REG);
console_printf(" 0x%08lx CM_EXC_STAT_REG\n", cd->CM_EXC_STAT_REG);
console_printf(" 0x%08lx CM_LL_TIMER1_36_10_REG\n", cd->CM_LL_TIMER1_36_10_REG);
console_printf(" 0x%08lx CM_LL_TIMER1_9_0_REG\n", cd->CM_LL_TIMER1_9_0_REG);
/* Spin if debugger is connected to CMAC to avoid resetting it */
if (cd->CM_STAT_REG & 0x20) {
for (;;);
}
#endif
/* XXX CMAC is in error state, need to recover */
assert(0);
return;
}
cmac_host_rand_chk_fill();
os_trace_isr_exit();
}
static void
cmac_host_rand_fill(struct os_event *ev)
{
size_t num_bytes;
struct trng_dev *trng;
uint32_t *rnum;
uint32_t rnums[CMAC_RAND_BUF_ELEMS];
/* Check if full */
if (!cmac_rand_is_active() || cmac_rand_is_full()) {
return;
}
assert(ev->ev_arg != NULL);
/* Fill buffer with random numbers even though we may not use all of them */
trng = ev->ev_arg;
rnum = &rnums[0];
num_bytes = trng_read(trng, rnum, CMAC_RAND_BUF_ELEMS * sizeof(uint32_t));
cmac_rand_fill(rnum, num_bytes / 4);
cmac_host_signal2cmac();
}
static void
cmac_host_rand_chk_fill(void)
{
if (cmac_rand_is_active() && !cmac_rand_is_full()) {
os_eventq_put(os_eventq_dflt_get(), &g_cmac_host_rand_ev);
}
}
void
cmac_host_signal2cmac(void)
{
da1469x_pdc_set(g_cmac_host_pdc_sys2cmac);
}
static void
cmac_host_lpclk_cb(uint32_t freq)
{
g_cmac_shared_data->lp_clock_freq = freq;
}
#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
static void
cmac_host_print_trim(const char *name, const uint32_t *tv, unsigned len)
{
console_printf("[CMAC] Trim values for '%s'\n", name);
while (len) {
console_printf(" 0x%08x = 0x%08x\n", (unsigned)tv[0], (unsigned)tv[1]);
len -= 2;
tv += 2;
}
}
#endif
void
cmac_host_init(void)
{
struct trng_dev *trng;
struct cmac_image_info ii;
uint32_t cmac_rom_size;
uint32_t cmac_ram_size;
#if !MYNEWT_VAL(CMAC_IMAGE_SINGLE)
const struct flash_area *fa;
int rc;
#endif
struct cmac_trim *trim;
/* Get trng os device */
trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL);
assert(trng);
g_cmac_host_rand_ev.ev_arg = trng;
#if MYNEWT_VAL(CMAC_DEBUG_DIAG_ENABLE)
cmac_diag_setup_host();
#endif
#if MYNEWT_VAL(CMAC_DEBUG_SWD_ENABLE)
/* Enable CMAC debugger */
CRG_TOP->SYS_CTRL_REG |= 0x40; /* CRG_TOP_SYS_CTRL_REG_CMAC_DEBUGGER_ENABLE_Msk */
#endif
/*
* Add PDC entry to wake up CMAC from M33
*
* XXX if MCU_DEBUG_GPIO_DEEP_SLEEP is enabled on CMAC, this should also
* enable PD_COM so CMAC can access GPIOs after wake up
*/
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);
}
/* Setup CMAC2SYS interrupt */
NVIC_SetVector(CMAC2SYS_IRQn, (uint32_t)cmac2sys_isr);
NVIC_SetPriority(CMAC2SYS_IRQn, 0);
NVIC_DisableIRQ(CMAC2SYS_IRQn);
/* 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 */
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];
/* Load image header and check if image can be loaded */
#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
memcpy(&ii, &_binary_cmac_rom_bin_start[128], sizeof(ii));
#else
rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa);
assert(rc == 0);
rc = flash_area_read(fa, 128, &ii, sizeof(ii));
assert(rc == 0);
#endif
assert(ii.magic == 0xC3ACC3AC);
assert(ii.size_rom == cmac_rom_size);
assert(ii.size_ram <= cmac_ram_size);
/* Copy CMAC image to RAM */
#if MYNEWT_VAL(CMAC_IMAGE_SINGLE)
memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
memcpy(&_binary_cmac_ram_bin_start, &_binary_cmac_rom_bin_start, ii.size_rom);
#else
memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size);
rc = flash_area_read(fa, 0, &_binary_cmac_ram_bin_start, ii.size_rom);
assert(rc == 0);
#endif
/* Setup CMAC memory addresses */
MEMCTRL->CMI_CODE_BASE_REG = (uint32_t)&_binary_cmac_ram_bin_start;
MEMCTRL->CMI_DATA_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_data;
MEMCTRL->CMI_SHARED_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_shared;
MEMCTRL->CMI_END_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.size_ram - 1;
/* Initialize shared memory */
cmac_shared_init();
trim = (struct cmac_trim *)&g_cmac_shared_data->trim;
trim->rfcu_len = da1469x_trimv_group_read(6, trim->rfcu, ARRAY_SIZE(trim->rfcu));
trim->rfcu_mode1_len = da1469x_trimv_group_read(8, trim->rfcu_mode1, ARRAY_SIZE(trim->rfcu_mode1));
trim->rfcu_mode2_len = da1469x_trimv_group_read(10, trim->rfcu_mode2, ARRAY_SIZE(trim->rfcu_mode2));
trim->synth_len = da1469x_trimv_group_read(7, trim->synth, ARRAY_SIZE(trim->synth));
#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE)
cmac_host_print_trim("rfcu", trim->rfcu, trim->rfcu_len);
cmac_host_print_trim("rfcu_mode1", trim->rfcu_mode1, trim->rfcu_mode1_len);
cmac_host_print_trim("rfcu_mode2", trim->rfcu_mode2, trim->rfcu_mode2_len);
cmac_host_print_trim("synth", trim->synth, trim->synth_len);
#endif
/* Release CMAC from reset and sync */
CRG_TOP->CLK_RADIO_REG &= ~CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk;
cmac_shared_sync();
da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb);
#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) && MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
/* Trim values are calculated on RF init, so are valid after synced with CMAC */
console_printf("[CMAC] Calculated trim_val1: 1=0x%08x 2=0x%08x\n",
(unsigned)g_cmac_shared_data->debug.trim_val1_tx_1,
(unsigned)g_cmac_shared_data->debug.trim_val1_tx_2);
console_printf("[CMAC] Calculated trim_val2: tx=0x%08x rx=0x%08x\n",
(unsigned)g_cmac_shared_data->debug.trim_val2_tx,
(unsigned)g_cmac_shared_data->debug.trim_val2_rx);
#endif
}
@@ -0,0 +1,162 @@
/*
* 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 <cmac_driver/cmac_shared.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "syscfg/syscfg.h"
#include "mcu/mcu.h"
#include "os/os_arch.h"
#include "os/os.h"
#ifndef min
#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
static cmac_mbox_read_cb *g_cmac_mbox_read_cb;
static cmac_mbox_write_notif_cb *g_cmac_mbox_write_notif_cb;
void
cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb)
{
g_cmac_mbox_read_cb = cb;
}
void
cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb)
{
g_cmac_mbox_write_notif_cb = cb;
}
int
cmac_mbox_read(void)
{
#if MYNEWT_VAL(BLE_HOST)
volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s;
uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_c2s_buf;
const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
#else
volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_s2c;
uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_s2c_buf;
const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
#endif
uint16_t rd_off;
uint16_t wr_off;
uint16_t chunk;
int len = 0;
if (!g_cmac_mbox_read_cb) {
return 0;
}
do {
rd_off = mbox->rd_off;
wr_off = mbox->wr_off;
if (rd_off <= wr_off) {
chunk = wr_off - rd_off;
} else {
chunk = mbox_size - rd_off;
}
while (chunk) {
len = g_cmac_mbox_read_cb(&mbox_buf[rd_off], chunk);
if (len < 0) {
break;
}
rd_off += len;
chunk -= len;
}
mbox->rd_off = rd_off == mbox_size ? 0 : rd_off;
} while ((mbox->rd_off != mbox->wr_off) && (len >= 0));
return 0;
}
int
cmac_mbox_write(const void *data, uint16_t len)
{
#if MYNEWT_VAL(BLE_HOST)
volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_s2c;
uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_s2c_buf;
const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C);
#else
volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_c2s;
uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_c2s_buf;
const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S);
#endif
uint16_t rd_off;
uint16_t wr_off;
uint16_t max_wr;
uint16_t chunk;
while (len) {
rd_off = mbox->rd_off;
wr_off = mbox->wr_off;
/*
* Calculate maximum length to write, i.e. up to end of buffer or stop
* before rd_off to be able to detect full queue.
*/
if (rd_off > wr_off) {
/*
* |0|1|2|3|4|5|6|7|
* | | | |W| | |R| |
* `---^
*/
max_wr = rd_off - wr_off - 1;
} else if (rd_off == 0) {
/*
* |0|1|2|3|4|5|6|7|
* |R| | |W| | | | |
* `-------^
*/
max_wr = mbox_size - wr_off - 1;
} else {
/*
* |0|1|2|3|4|5|6|7|
* | |R| |W| | | | |
* `---------^
*/
max_wr = mbox_size - wr_off;
}
chunk = min(len, max_wr);
if (chunk == 0) {
continue;
}
memcpy(&mbox_buf[wr_off], data, chunk);
wr_off += chunk;
mbox->wr_off = wr_off == mbox_size ? 0 : wr_off;
g_cmac_mbox_write_notif_cb();
len -= chunk;
data = (uint8_t *)data + chunk;
}
return 0;
}
@@ -0,0 +1,145 @@
/*
* 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 <cmac_driver/cmac_shared.h>
#include <string.h>
#include <stdbool.h>
#include "syscfg/syscfg.h"
#include "mcu/mcu.h"
#include "os/os_arch.h"
#include "os/os.h"
#if MYNEWT_VAL(BLE_HOST)
int
cmac_rand_is_active(void)
{
return g_cmac_shared_data->rand.cmr_active;
}
int
cmac_rand_is_full(void)
{
int next;
bool rc;
next = cmac_rand_get_next();
if (next == g_cmac_shared_data->rand.cmr_out) {
rc = 1;
} else {
rc = 0;
}
return rc;
}
int
cmac_rand_get_next(void)
{
int next;
/* If active and not full, put event on queue to get random numbers */
next = g_cmac_shared_data->rand.cmr_in + 1;
if (next == CMAC_RAND_BUF_ELEMS) {
next = 0;
}
return next;
}
void
cmac_rand_fill(uint32_t *buf, int num_words)
{
int next;
/* XXX: if words is 0, is it possible we could get into a state
where we are waiting for random numbers but M33 does not know it
has to fill any? */
/* NOTE: we already know the buffer is not full first time through */
next = g_cmac_shared_data->rand.cmr_in;
while (num_words) {
g_cmac_shared_data->rand.cmr_buf[next] = buf[0];
next = cmac_rand_get_next();
g_cmac_shared_data->rand.cmr_in = next;
next = cmac_rand_get_next();
if (next == g_cmac_shared_data->rand.cmr_out) {
break;
}
--num_words;
++buf;
}
}
#endif
#if MYNEWT_VAL(BLE_CONTROLLER)
static cmac_rand_isr_cb_t g_cmac_rand_isr_cb;
void
cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb)
{
g_cmac_rand_isr_cb = cb;
}
void
cmac_rand_start(void)
{
g_cmac_shared_data.rand.cmr_active = 1;
}
void
cmac_rand_stop(void)
{
g_cmac_shared_data.rand.cmr_active = 0;
}
/**
* cmac rnum read
*
* Called during the system to cmac isr to take random numbers
* from shared memory into the BLE stack.
*/
void
cmac_rand_read(void)
{
uint8_t bytes_left;
uint32_t rnum;
/* Just leave if no callback. */
if (g_cmac_rand_isr_cb == NULL) {
return;
}
bytes_left = 0;
while (g_cmac_shared_data.rand.cmr_active) {
if (bytes_left) {
--bytes_left;
rnum >>= 8;
} else if (g_cmac_shared_data.rand.cmr_out != g_cmac_shared_data.rand.cmr_in) {
bytes_left = 3;
rnum = g_cmac_shared_data.rand.cmr_buf[g_cmac_shared_data.rand.cmr_out];
++g_cmac_shared_data.rand.cmr_out;
if (g_cmac_shared_data.rand.cmr_out == CMAC_RAND_BUF_ELEMS) {
g_cmac_shared_data.rand.cmr_out = 0;
}
} else {
break;
}
(*g_cmac_rand_isr_cb)((uint8_t)rnum);
}
}
#endif
@@ -0,0 +1,98 @@
/*
* 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 "syscfg/syscfg.h"
#if MYNEWT_VAL(BLE_CONTROLLER) && !MYNEWT_VAL(MCU_DEBUG_DSER_CMAC_SHARED)
#define MCU_DIAG_SER_DISABLE
#endif
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#include "mcu/mcu.h"
#include <cmac_driver/cmac_shared.h>
#include "os/os_arch.h"
#include "os/os.h"
#ifndef min
#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#endif
#if MYNEWT_VAL(BLE_HOST)
volatile struct cmac_shared_data *g_cmac_shared_data;
#include "mcu/da1469x_clock.h"
#define MCU_DIAG_SER(_x)
#elif MYNEWT_VAL(BLE_CONTROLLER)
volatile struct cmac_shared_data g_cmac_shared_data __attribute__((section(".shdata")));
#endif
void
cmac_shared_init(void)
{
#if MYNEWT_VAL(BLE_HOST)
g_cmac_shared_data = (void *)(MCU_MEM_SYSRAM_START_ADDRESS +
MEMCTRL->CMI_SHARED_BASE_REG);
memset((void *)g_cmac_shared_data, 0, sizeof(*g_cmac_shared_data));
g_cmac_shared_data->xtal32m_settle_us = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US);
g_cmac_shared_data->dcdc.enabled = DCDC->DCDC_CTRL1_REG & DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk;
if (g_cmac_shared_data->dcdc.enabled) {
g_cmac_shared_data->dcdc.v18 = DCDC->DCDC_V18_REG;
g_cmac_shared_data->dcdc.v18p = DCDC->DCDC_V18P_REG;
g_cmac_shared_data->dcdc.vdd = DCDC->DCDC_VDD_REG;
g_cmac_shared_data->dcdc.v14 = DCDC->DCDC_V14_REG;
g_cmac_shared_data->dcdc.ctrl1 = DCDC->DCDC_CTRL1_REG;
}
#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE)
g_cmac_shared_data->debug.tx_power_override = INT8_MAX;
#endif
#endif
}
void
cmac_shared_sync(void)
{
/*
* We need to guarantee proper order of initialization here, i.e. SYS has
* to wait until CMAC finished initialization as otherwise host may start
* sending HCI packets which will timeout as there is no one to read them.
*/
#if MYNEWT_VAL(BLE_HOST)
assert(g_cmac_shared_data->magic_sys == 0);
while (g_cmac_shared_data->magic_cmac != CMAC_SHARED_MAGIC_CMAC);
g_cmac_shared_data->magic_sys = CMAC_SHARED_MAGIC_SYS;
NVIC_EnableIRQ(CMAC2SYS_IRQn);
#endif
#if MYNEWT_VAL(BLE_CONTROLLER)
assert(g_cmac_shared_data.magic_cmac == 0);
g_cmac_shared_data.magic_cmac = CMAC_SHARED_MAGIC_CMAC;
while (g_cmac_shared_data.magic_sys != CMAC_SHARED_MAGIC_SYS);
NVIC_SetPriority(SYS2CMAC_IRQn, 3);
NVIC_EnableIRQ(SYS2CMAC_IRQn);
#endif
}
@@ -0,0 +1,98 @@
# 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_MBOX_SIZE_S2C:
description: >
Size of mailbox for SYS to CMAC data. The size
value should be power of 2 to allow for better
code optimization.
value: 128
CMAC_MBOX_SIZE_C2S:
description: >
Size of mailbox for CMAC to SYS data. The size
value should be power of 2 to allow for better
code optimization.
value: 128
CMAC_TRIM_SIZE_RFCU:
description: >
Size of trim values for RFCU. This is maximum
number of trim values that can be read from
OTP and applied, all excessive values will be
discarded.
value: 10
CMAC_TRIM_SIZE_SYNTH:
description: >
Size of trim values for RFCU. This is maximum
number of trim values that can be read from
OTP and applied, all excessive values will be
discarded.
value: 10
CMAC_DEBUG_SWD_ENABLE:
description: >
Enable CMAC SWD interface.
value: 0
CMAC_DEBUG_DIAG_ENABLE:
description: >
Enable CMAC diagnostic lines.
value: 0
CMAC_DEBUG_DATA_ENABLE:
description: >
Enable extra debugging data in shared segment.
value: 0
CMAC_DEBUG_COREDUMP_ENABLE:
description: >
Enable dumping CMAC registers to shared segment
on fault.
value: 1
CMAC_DEBUG_HOST_PRINT_ENABLE:
description: >
Enable some debug printouts to console from host side.
This will dump some settings during startup, useful to
check what is loaded to CMAC via shared data.
value: 0
CMAC_IMAGE_SINGLE:
description: >
When enable, CMAC binary is linked with application image
creating a single image build. See CMAC_IMAGE_TARGET_NAME.
When disabled, CMAC binary is built and flashed separately
to flash partition. See CMAC_IMAGE_PARTITION.
value: 1
CMAC_IMAGE_TARGET_NAME:
description: >
Target name to build for CMAC binary for single image build.
value: "@apache-mynewt-nimble/targets/dialog_cmac"
CMAC_IMAGE_PARTITION:
description: >
Flash partition to load CMAC binary from if single image build
is disabled.
value: FLASH_AREA_IMAGE_1
CMAC_IMAGE_RAM_SIZE:
description: >
Size of RAM area in bytes reserved for CMAC if single image
build is disabled. Unit suffix (K, M) is allowed.
Note: for single image build this setting is not applicable
since proper RAM area size is automatically calculated from
CMAC binary.
value: 128K
syscfg.restrictions.BLE_HOST:
- TRNG
+36
View File
@@ -0,0 +1,36 @@
#
# 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/dialog_cmac
pkg.description: HCI H4 transport for Dialog CMAC
pkg.author: "Apache Mynewt <[email protected]>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- ble
- bluetooth
pkg.deps:
- nimble
- nimble/transport/dialog_cmac/cmac_driver
pkg.apis:
- ble_transport
pkg.init:
ble_hci_cmac_init: 100
@@ -0,0 +1,194 @@
/*
* 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 "syscfg/syscfg.h"
#include "os/mynewt.h"
#include "nimble/ble.h"
#include "nimble/ble_hci_trans.h"
#include "nimble/hci_common.h"
#include "ble_hci_cmac_priv.h"
/*
* If controller-to-host flow control is enabled we need to hold an extra command
* buffer for HCI_Host_Number_Of_Completed_Packets which can be sent at any time.
*/
#if MYNEWT_VAL(BLE_HS_FLOW_CTRL) || MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL)
#define HCI_CMD_COUNT 2
#else
#define HCI_CMD_COUNT 1
#endif
#define POOL_ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) + \
BLE_MBUF_MEMBLOCK_OVERHEAD + \
BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
static uint8_t ble_hci_pool_cmd_mempool_buf[
OS_MEMPOOL_BYTES(HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ)];
static struct os_mempool ble_hci_pool_cmd_mempool;
static uint8_t ble_hci_pool_evt_hi_mempool_buf[
OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
static struct os_mempool ble_hci_pool_evt_hi_mempool;
static uint8_t ble_hci_pool_evt_lo_mempool_buf[
OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))];
static struct os_mempool ble_hci_pool_evt_lo_mempool;
static uint8_t ble_hci_pool_acl_mempool_buf[
OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
POOL_ACL_BLOCK_SIZE)];
static struct os_mempool_ext ble_hci_pool_acl_mempool;
static struct os_mbuf_pool ble_hci_pool_acl_mbuf_pool;
__attribute__((weak)) void ble_hci_trans_notify_free(void);
static os_mempool_put_fn *g_ble_hci_pool_acl_mempool_put_cb;
static void *g_ble_hci_pool_acl_mempool_put_arg;
int
ble_hci_trans_reset(void)
{
return 0;
}
uint8_t *
ble_hci_trans_buf_alloc(int type)
{
uint8_t *buf;
switch (type) {
case BLE_HCI_TRANS_BUF_CMD:
buf = os_memblock_get(&ble_hci_pool_cmd_mempool);
break;
case BLE_HCI_TRANS_BUF_EVT_HI:
buf = os_memblock_get(&ble_hci_pool_evt_hi_mempool);
if (buf) {
break;
}
/* no break */
case BLE_HCI_TRANS_BUF_EVT_LO:
buf = os_memblock_get(&ble_hci_pool_evt_lo_mempool);
break;
default:
assert(0);
buf = NULL;
}
return buf;
}
void
ble_hci_trans_buf_free(uint8_t *buf)
{
int rc;
if (os_memblock_from(&ble_hci_pool_cmd_mempool, buf)) {
rc = os_memblock_put(&ble_hci_pool_cmd_mempool, buf);
assert(rc == 0);
} else if (os_memblock_from(&ble_hci_pool_evt_hi_mempool, buf)) {
rc = os_memblock_put(&ble_hci_pool_evt_hi_mempool, buf);
assert(rc == 0);
} else {
assert(os_memblock_from(&ble_hci_pool_evt_lo_mempool, buf));
rc = os_memblock_put(&ble_hci_pool_evt_lo_mempool, buf);
assert(rc == 0);
}
ble_hci_trans_notify_free();
}
struct os_mbuf *
ble_hci_cmac_alloc_acl_mbuf(void)
{
return os_mbuf_get_pkthdr(&ble_hci_pool_acl_mbuf_pool,
sizeof(struct ble_mbuf_hdr));
}
static os_error_t
ble_hci_cmac_free_acl_cb(struct os_mempool_ext *mpe, void *data, void *arg)
{
int rc;
if (g_ble_hci_pool_acl_mempool_put_cb) {
rc = g_ble_hci_pool_acl_mempool_put_cb(mpe, data,
g_ble_hci_pool_acl_mempool_put_arg);
} else {
rc = os_memblock_put_from_cb(&mpe->mpe_mp, data);
}
if (rc != 0) {
return rc;
}
ble_hci_trans_notify_free();
return 0;
}
int
ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
{
g_ble_hci_pool_acl_mempool_put_cb = cb;
g_ble_hci_pool_acl_mempool_put_arg = arg;
return 0;
}
void
ble_hci_cmac_init(void)
{
int rc;
SYSINIT_ASSERT_ACTIVE();
rc = os_mempool_init(&ble_hci_pool_cmd_mempool,
HCI_CMD_COUNT, BLE_HCI_TRANS_CMD_SZ,
ble_hci_pool_cmd_mempool_buf, "ble_hci_cmd");
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_mempool_init(&ble_hci_pool_evt_hi_mempool,
MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
ble_hci_pool_evt_hi_mempool_buf, "ble_hci_evt_hi");
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_mempool_init(&ble_hci_pool_evt_lo_mempool,
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
ble_hci_pool_evt_lo_mempool_buf, "ble_hci_evt_lo");
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_mempool_ext_init(&ble_hci_pool_acl_mempool,
MYNEWT_VAL(BLE_ACL_BUF_COUNT), POOL_ACL_BLOCK_SIZE,
ble_hci_pool_acl_mempool_buf, "ble_hci_acl");
SYSINIT_PANIC_ASSERT(rc == 0);
rc = os_mbuf_pool_init(&ble_hci_pool_acl_mbuf_pool,
&ble_hci_pool_acl_mempool.mpe_mp, POOL_ACL_BLOCK_SIZE,
MYNEWT_VAL(BLE_ACL_BUF_COUNT));
SYSINIT_PANIC_ASSERT(rc == 0);
ble_hci_pool_acl_mempool.mpe_put_cb = ble_hci_cmac_free_acl_cb;
}
@@ -0,0 +1,153 @@
/*
* 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 "syscfg/syscfg.h"
#if MYNEWT_VAL(BLE_HOST)
#include "cmac_driver/cmac_shared.h"
#include "cmac_driver/cmac_host.h"
#include "nimble/ble_hci_trans.h"
#include "os/os_mbuf.h"
#include "ble_hci_trans_h4.h"
#include "ble_hci_cmac_priv.h"
struct ble_hci_cmac_hs_api {
ble_hci_trans_rx_cmd_fn *evt_cb;
void *evt_arg;
ble_hci_trans_rx_acl_fn *acl_cb;
void *acl_arg;
};
static struct ble_hci_cmac_hs_api g_ble_hci_cmac_hs_api;
static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_hs_rx_state;
static bool g_ble_hci_cmac_hs_read_err;
static int
ble_hci_cmac_hs_frame_cb(uint8_t pkt_type, void *data)
{
int rc;
switch (pkt_type) {
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
rc = g_ble_hci_cmac_hs_api.acl_cb(data, g_ble_hci_cmac_hs_api.acl_arg);
break;
case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
rc = g_ble_hci_cmac_hs_api.evt_cb(data, g_ble_hci_cmac_hs_api.evt_arg);
break;
default:
assert(0);
break;
}
return rc;
}
static int
ble_hci_cmac_hs_mbox_read_cb(const void *data, uint16_t len)
{
int rlen;
os_sr_t sr;
rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_hs_rx_state, data, len,
ble_hci_cmac_hs_frame_cb);
if (rlen < 0) {
/*
* There was oom error, we need to wait for buffer to be freed and
* trigger another read.
*/
OS_ENTER_CRITICAL(sr);
g_ble_hci_cmac_hs_read_err = true;
OS_EXIT_CRITICAL(sr);
}
return rlen;
}
static void
ble_hci_cmac_hs_mbox_write_notif_cb(void)
{
cmac_host_signal2cmac();
}
int
ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
{
uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_CMD;
cmac_mbox_write(&pkt_type, sizeof(pkt_type));
cmac_mbox_write(cmd, cmd[2] + 3);
ble_hci_trans_buf_free(cmd);
return 0;
}
int
ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
{
uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
struct os_mbuf *om_next;
cmac_mbox_write(&pkt_type, sizeof(pkt_type));
while (om) {
om_next = SLIST_NEXT(om, om_next);
cmac_mbox_write(om->om_data, om->om_len);
os_mbuf_free(om);
om = om_next;
}
return 0;
}
void
ble_hci_trans_notify_free(void)
{
os_sr_t sr;
OS_ENTER_CRITICAL(sr);
if (g_ble_hci_cmac_hs_read_err) {
g_ble_hci_cmac_hs_read_err = false;
/* Just trigger an interrupt, it will trigger read */
NVIC_SetPendingIRQ(CMAC2SYS_IRQn);
}
OS_EXIT_CRITICAL(sr);
}
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)
{
g_ble_hci_cmac_hs_api.evt_cb = evt_cb;
g_ble_hci_cmac_hs_api.evt_arg = evt_arg;
g_ble_hci_cmac_hs_api.acl_cb = acl_cb;
g_ble_hci_cmac_hs_api.acl_arg = acl_arg;
/* We can now handle data from CMAC, initialize it */
cmac_mbox_set_read_cb(ble_hci_cmac_hs_mbox_read_cb);
cmac_mbox_set_write_notif_cb(ble_hci_cmac_hs_mbox_write_notif_cb);
cmac_host_init();
}
#endif
@@ -0,0 +1,141 @@
/*
* 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 "syscfg/syscfg.h"
#if MYNEWT_VAL(BLE_CONTROLLER)
#if !MYNEWT_VAL(MCU_DEBUG_DSER_BLE_HCI_CMAC_LL)
#define MCU_DIAG_SER_DISABLE
#endif
#include <assert.h>
#include <string.h>
#include "mcu/mcu.h"
#include "cmac_driver/cmac_shared.h"
#include "nimble/ble_hci_trans.h"
#include "os/os_mbuf.h"
#include "ble_hci_trans_h4.h"
#include "ble_hci_cmac_priv.h"
struct ble_hci_cmac_ll_api {
ble_hci_trans_rx_cmd_fn *cmd_cb;
void *cmd_arg;
ble_hci_trans_rx_acl_fn *acl_cb;
void *acl_arg;
};
static struct ble_hci_cmac_ll_api g_ble_hci_cmac_ll_api;
static struct ble_hci_trans_h4_rx_state g_ble_hci_cmac_ll_rx_state;
static int
ble_hci_cmac_ll_frame_cb(uint8_t pkt_type, void *data)
{
int rc;
MCU_DIAG_SER('F');
switch (pkt_type) {
case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
rc = g_ble_hci_cmac_ll_api.cmd_cb(data, g_ble_hci_cmac_ll_api.cmd_arg);
break;
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
rc = g_ble_hci_cmac_ll_api.acl_cb(data, g_ble_hci_cmac_ll_api.acl_arg);
break;
default:
assert(0);
break;
}
return rc;
}
static int
ble_hci_cmac_ll_mbox_read_cb(const void *data, uint16_t len)
{
int rlen;
MCU_DIAG_SER('R');
rlen = ble_hci_trans_h4_rx(&g_ble_hci_cmac_ll_rx_state, data, len,
ble_hci_cmac_ll_frame_cb);
/* There should be no oom on LL side due to flow control used */
assert(rlen >= 0);
return rlen;
}
static void
ble_hci_cmac_ll_mbox_write_notif_cb(void)
{
MCU_DIAG_SER('W');
CMAC->CM_EV_SET_REG = CMAC_CM_EV_SET_REG_EV1C_CMAC2SYS_IRQ_SET_Msk;
}
int
ble_hci_trans_ll_evt_tx(uint8_t *evt)
{
uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_EVT;
cmac_mbox_write(&pkt_type, sizeof(pkt_type));
cmac_mbox_write(evt, evt[1] + 2);
ble_hci_trans_buf_free(evt);
return 0;
}
int
ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
{
uint8_t pkt_type = BLE_HCI_TRANS_H4_PKT_TYPE_ACL;
struct os_mbuf *om_next;
cmac_mbox_write(&pkt_type, sizeof(pkt_type));
while (om) {
om_next = SLIST_NEXT(om, om_next);
cmac_mbox_write(om->om_data, om->om_len);
os_mbuf_free(om);
om = om_next;
}
return 0;
}
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)
{
g_ble_hci_cmac_ll_api.cmd_cb = cmd_cb;
g_ble_hci_cmac_ll_api.cmd_arg = cmd_arg;
g_ble_hci_cmac_ll_api.acl_cb = acl_cb;
g_ble_hci_cmac_ll_api.acl_arg = acl_arg;
/* Setup callbacks for mailboxes */
cmac_mbox_set_read_cb(ble_hci_cmac_ll_mbox_read_cb);
cmac_mbox_set_write_notif_cb(ble_hci_cmac_ll_mbox_write_notif_cb);
/* Synchronize with SYS */
cmac_shared_sync();
}
#endif
@@ -0,0 +1,29 @@
/*
* 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 _BLE_HCI_CMAC_PRIV_H_
#define _BLE_HCI_CMAC_PRIV_H_
#include "os/os_mbuf.h"
struct os_mbuf *ble_hci_cmac_alloc_acl_mbuf(void);
void ble_hci_trans_notify_free(void);
#endif /* _BLE_HCI_CMAC_PRIV_H_ */
@@ -0,0 +1,332 @@
/*
* 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 <string.h>
#include "syscfg/syscfg.h"
#include "os/os_mbuf.h"
#include "nimble/ble_hci_trans.h"
#include "nimble/hci_common.h"
#include "ble_hci_trans_h4.h"
#include "ble_hci_cmac_priv.h"
#define RXS_STATE_W4_PKT_TYPE 0
#define RXS_STATE_W4_HEADER 1
#define RXS_STATE_W4_PAYLOAD 2
#define RXS_STATE_COMPLETED 3
struct input_buffer {
const uint8_t *buf;
uint16_t len;
};
static int
ble_hci_trans_h4_ib_adjust(struct input_buffer *ib, uint16_t len)
{
assert(ib->len >= len);
ib->buf += len;
ib->len -= len;
return len;
}
static void
ble_hci_trans_h4_rxs_start(struct ble_hci_trans_h4_rx_state *rxs, uint8_t pkt_type)
{
rxs->pkt_type = pkt_type;
rxs->len = 0;
rxs->expected_len = 0;
switch (rxs->pkt_type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
rxs->min_len = 3;
break;
#endif
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
rxs->min_len = 4;
break;
#if MYNEWT_VAL(BLE_HOST)
case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
rxs->min_len = 2;
break;
#endif
default:
/* XXX sync loss */
assert(0);
break;
}
}
static int
ble_hci_trans_h4_pull_min_len(struct ble_hci_trans_h4_rx_state *rxs,
struct input_buffer *ib)
{
uint16_t len;
len = min(ib->len, rxs->min_len - rxs->len);
memcpy(&rxs->hdr[rxs->len], ib->buf, len);
rxs->len += len;
ble_hci_trans_h4_ib_adjust(ib, len);
return rxs->len != rxs->min_len;
}
static int
ble_hci_trans_h4_rx_state_w4_header(struct ble_hci_trans_h4_rx_state *rxs,
struct input_buffer *ib)
{
#if MYNEWT_VAL(BLE_HOST)
int pool;
#endif
int rc;
rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
if (rc) {
/* need more data */
return 1;
}
switch (rxs->pkt_type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
if (!rxs->buf) {
return -1;
}
memcpy(rxs->buf, rxs->hdr, rxs->len);
rxs->expected_len = rxs->hdr[2] + 3;
break;
#endif
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
rxs->om = ble_hci_cmac_alloc_acl_mbuf();
if (!rxs->om) {
return -1;
}
os_mbuf_append(rxs->om, rxs->hdr, rxs->len);
rxs->expected_len = get_le16(&rxs->hdr[2]) + 4;
break;
#if MYNEWT_VAL(BLE_HOST)
case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
pool = BLE_HCI_TRANS_BUF_EVT_HI;
if (rxs->hdr[0] == BLE_HCI_EVCODE_LE_META) {
/* For LE Meta event we need 3 bytes to parse header */
rxs->min_len = 3;
rc = ble_hci_trans_h4_pull_min_len(rxs, ib);
if (rc) {
/* need more data */
return 1;
}
/* Advertising reports shall be allocated from low-prio pool */
if ((rxs->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) ||
(rxs->hdr[2] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) {
pool = BLE_HCI_TRANS_BUF_EVT_LO;
}
}
/*
* XXX Events originally allocated from hi-pool can use lo-pool as
* fallback and cannot be dropped. Events allocated from lo-pool
* can be dropped to avoid oom while scanning which means that
* any advertising or extended advertising report can be silently
* discarded by transport. While this is perfectly fine for legacy
* advertising, for extended advertising it means we can drop start
* or end of chain report and host won't be able to reassemble
* chain properly... so just need to make sure pool on host side is
* large enough to catch up with controller.
*/
rxs->buf = ble_hci_trans_buf_alloc(pool);
if (!rxs->buf && pool == BLE_HCI_TRANS_BUF_EVT_HI) {
rxs->buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
if (!rxs->buf) {
return -1;
}
}
if (rxs->buf) {
memcpy(rxs->buf, rxs->hdr, rxs->len);
}
rxs->expected_len = rxs->hdr[1] + 2;
break;
#endif
default:
assert(0);
break;
}
return 0;
}
static int
ble_hci_trans_h4_rx_state_w4_payload(struct ble_hci_trans_h4_rx_state *rxs,
struct input_buffer *ib)
{
uint16_t mbuf_len;
uint16_t len;
int rc;
len = min(ib->len, rxs->expected_len - rxs->len);
switch (rxs->pkt_type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
#endif
#if MYNEWT_VAL(BLE_HOST)
case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
#endif
if (rxs->buf) {
memcpy(&rxs->buf[rxs->len], ib->buf, len);
}
break;
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
assert(rxs->om);
mbuf_len = OS_MBUF_PKTLEN(rxs->om);
rc = os_mbuf_append(rxs->om, ib->buf, len);
if (rc) {
/*
* Some data may already be appended so need to adjust rxs only by
* the size of appended data.
*/
len = OS_MBUF_PKTLEN(rxs->om) - mbuf_len;
rxs->len += len;
ble_hci_trans_h4_ib_adjust(ib, len);
return -1;
}
break;
default:
assert(0);
break;
}
rxs->len += len;
ble_hci_trans_h4_ib_adjust(ib, len);
/* return 1 if need more data */
return rxs->len != rxs->expected_len;
}
static void
ble_hci_trans_h4_rx_state_completed(struct ble_hci_trans_h4_rx_state *rxs,
ble_hci_trans_h4_frame_cb *frame_cb)
{
int rc;
switch (rxs->pkt_type) {
#if MYNEWT_VAL(BLE_CONTROLLER)
case BLE_HCI_TRANS_H4_PKT_TYPE_CMD:
#endif
#if MYNEWT_VAL(BLE_HOST)
case BLE_HCI_TRANS_H4_PKT_TYPE_EVT:
#endif
if (rxs->buf) {
rc = frame_cb(rxs->pkt_type, rxs->buf);
if (rc != 0) {
ble_hci_trans_buf_free(rxs->buf);
}
rxs->buf = NULL;
}
break;
case BLE_HCI_TRANS_H4_PKT_TYPE_ACL:
if (rxs->om) {
rc = frame_cb(rxs->pkt_type, rxs->om);
if (rc != 0) {
os_mbuf_free_chain(rxs->om);
}
rxs->om = NULL;
}
break;
default:
assert(0);
break;
}
}
int
ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs, const uint8_t *buf,
uint16_t len, ble_hci_trans_h4_frame_cb *frame_cb)
{
struct input_buffer ib = {
.buf = buf,
.len = len,
};
int rc = 0;
while (ib.len && (rc >= 0)) {
rc = 0;
switch (rxs->state) {
case RXS_STATE_W4_PKT_TYPE:
ble_hci_trans_h4_rxs_start(rxs, ib.buf[0]);
ble_hci_trans_h4_ib_adjust(&ib, 1);
rxs->state = RXS_STATE_W4_HEADER;
/* no break */
case RXS_STATE_W4_HEADER:
rc = ble_hci_trans_h4_rx_state_w4_header(rxs, &ib);
if (rc) {
break;
}
rxs->state = RXS_STATE_W4_PAYLOAD;
/* no break */
case RXS_STATE_W4_PAYLOAD:
rc = ble_hci_trans_h4_rx_state_w4_payload(rxs, &ib);
if (rc) {
break;
}
rxs->state = RXS_STATE_COMPLETED;
/* no break */
case RXS_STATE_COMPLETED:
ble_hci_trans_h4_rx_state_completed(rxs, frame_cb);
rxs->state = RXS_STATE_W4_PKT_TYPE;
break;
default:
assert(0);
/* consume all remaining data */
ble_hci_trans_h4_ib_adjust(&ib, ib.len);
break;
}
}
/*
* Calculate consumed bytes
*
* Note: we should always consume some bytes unless there is an oom error.
* It's also possible that we have an oom error but already consumed some
* data, in such case just return success and error will be returned on next
* pass.
*/
len = len - ib.len;
if (len == 0) {
assert(rc < 0);
return -1;
}
return len;
}
@@ -0,0 +1,49 @@
/*
* 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 _BLE_HCI_TRANS_H4_H_
#define _BLE_HCI_TRANS_H4_H_
#include <stdint.h>
#define BLE_HCI_TRANS_H4_PKT_TYPE_NONE 0x00
#define BLE_HCI_TRANS_H4_PKT_TYPE_CMD 0x01
#define BLE_HCI_TRANS_H4_PKT_TYPE_ACL 0x02
#define BLE_HCI_TRANS_H4_PKT_TYPE_EVT 0x04
struct ble_hci_trans_h4_rx_state {
uint8_t state;
uint8_t pkt_type;
uint8_t min_len;
uint16_t len;
uint16_t expected_len;
uint8_t hdr[4];
union {
uint8_t *buf;
struct os_mbuf *om;
};
};
typedef int (ble_hci_trans_h4_frame_cb)(uint8_t pkt_type, void *data);
int ble_hci_trans_h4_rx(struct ble_hci_trans_h4_rx_state *rxs,
const uint8_t *buf, uint16_t len,
ble_hci_trans_h4_frame_cb *frame_cb);
#endif /* _BLE_HCI_TRANS_H4_H_ */
+43
View File
@@ -0,0 +1,43 @@
# 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:
BLE_HCI_EVT_HI_BUF_COUNT:
description: 'Number of high-priority event buffers.'
value: 2
BLE_HCI_EVT_LO_BUF_COUNT:
description: 'Number of low-priority event buffers.'
value: 8
BLE_HCI_EVT_BUF_SIZE:
description: 'Size of each event buffer, in bytes.'
value: 70
BLE_ACL_BUF_COUNT:
description: 'The number of ACL data buffers'
value: 4
BLE_ACL_BUF_SIZE:
description: >
This is the maximum size of the data portion of HCI ACL data
packets. It does not include the HCI data header (of 4 bytes).
value: 255
syscfg.vals.'BLE_EXT_ADV || BLE_LL_CFG_FEAT_LL_EXT_ADV':
BLE_HCI_EVT_BUF_SIZE: 257
+3
View File
@@ -44,5 +44,8 @@ pkg.deps.'BLE_HCI_TRANSPORT == "uart"':
pkg.deps.'BLE_HCI_TRANSPORT == "da1469x"':
- nimble/transport/da1469x
pkg.deps.'BLE_HCI_TRANSPORT == "dialog_cmac"':
- nimble/transport/dialog_cmac
pkg.deps.'BLE_HCI_TRANSPORT == "usb"':
- nimble/transport/usb
+9 -8
View File
@@ -26,14 +26,15 @@ syscfg.defs:
value: builtin
restrictions: $notnull
choices:
- builtin # Built-in NimBLE controller and RAM transport
- custom # Custom transport, has to be included manually by user
- ram # RAM transport
- uart # UART HCI H4 transport
- socket # Socket transport (for native builds)
- emspi # SPI transport for EM Microelectionic controllers
- da1469x # Dialog DA1469x integrated controller
- usb # USB
- builtin # Built-in NimBLE controller and RAM transport
- custom # Custom transport, has to be included manually by user
- ram # RAM transport
- uart # UART HCI H4 transport
- socket # Socket transport (for native builds)
- emspi # SPI transport for EM Microelectionic controllers
- da1469x # Dialog DA1469x integrated controller
- dialog_cmac # Dialog CMAC via shared memory
- usb # USB
# Deprecated settings
BLE_HCI_TRANSPORT_NIMBLE_BUILTIN: