mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-07-31 15:17:54 +00:00
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:
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user