diff --git a/drivers/nble/Kconfig b/drivers/nble/Kconfig index 7eb92eaba45..3e0dd668583 100644 --- a/drivers/nble/Kconfig +++ b/drivers/nble/Kconfig @@ -37,6 +37,11 @@ config BLUETOOTH_MAX_PAIRED int default 7 +config BLUETOOTH_DEBUG + bool + default n + select STDOUT_CONSOLE + config NBLE_UART_ON_DEV_NAME string "Device Name of UART Device for Nordic BLE" default "UART_0" @@ -66,7 +71,9 @@ config NBLE select BLUETOOTH_CENTRAL select BLUETOOTH_GATT_CLIENT select BLUETOOTH_SMP + select BLUETOOTH_DEBUG select UART_INTERRUPT_DRIVEN + select NANO_TIMEOUTS select NET_BUF help Enables support for using Nordic Semiconductor nRF51 Bluetooth diff --git a/drivers/nble/gap.c b/drivers/nble/gap.c index 121d561a0ce..5193a231d34 100644 --- a/drivers/nble/gap.c +++ b/drivers/nble/gap.c @@ -16,12 +16,122 @@ #include +#include +#include +#include + #include #include +#include + +#include "uart.h" + +#define NBLE_SWDIO_PIN 6 +#define NBLE_RESET_PIN NBLE_SWDIO_PIN + +#define NBLE_CHANNEL 0 + +static void *channel; + +/** + * Function handling the events from the UART IPC (irq). + * + * @param channel Channel on which the event applies + * @param request IPC_MSG_TYPE_MESSAGE when a new message was received, + * IPC_MSG_TYPE_FREE when the previous message was sent and can be freed. + * @param len Length of the data + * @param p_data Pointer to the data + * @return 0 + */ +static int recv_cb(int channel, int request, int len, void *p_data) +{ + BT_DBG("channel %d request %d len %d", channel, request, len); + + switch (request) { + case IPC_MSG_TYPE_MESSAGE: + break; + case IPC_MSG_TYPE_FREE: + /* TODO: Try to send another message immediately */ + break; + default: + /* Free the message */ + BT_ERR("Unsupported RPC request"); + break; + } + + return 0; +} int bt_enable(bt_ready_cb_t cb) { - return -ENOSYS; + struct device *gpio; + int ret; + + BT_DBG(""); + + gpio = device_get_binding(CONFIG_GPIO_DW_0_NAME); + if (!gpio) { + BT_ERR("Cannot find %", CONFIG_GPIO_DW_0_NAME); + return -ENODEV; + } + + ret = gpio_pin_configure(gpio, NBLE_RESET_PIN, GPIO_DIR_OUT); + if (ret) { + BT_ERR("Error configuring pin %d", NBLE_RESET_PIN); + return -ENODEV; + } + + /* Reset hold time is 0.2us (normal) or 100us (SWD debug) */ + ret = gpio_pin_write(gpio, NBLE_RESET_PIN, 0); + if (ret) { + BT_ERR("Error pin write %d", NBLE_RESET_PIN); + return -EINVAL; + } + + /** + * NBLE reset is achieved by asserting low the SWDIO pin. + * However, the BLE Core chip can be in SWD debug mode, + * and NRF_POWER->RESET = 0 due to, other constraints: therefore, + * this reset might not work everytime, especially after + * flashing or debugging. + */ + + /* sleep 1ms depending on context */ + switch (sys_execution_context_type_get()) { + case NANO_CTX_FIBER: + fiber_sleep(MSEC(1)); + break; + case NANO_CTX_TASK: + task_sleep(MSEC(1)); + break; + default: + BT_ERR("ISR context is not supported"); + return -EINVAL; + } + + /* Open the UART channel for RPC while Nordic is in reset */ + channel = ipc_uart_channel_open(NBLE_CHANNEL, recv_cb); + BT_DBG("channel %p", channel); + + ret = nble_open(); + if (ret) { + return ret; + } + + ret = gpio_pin_write(gpio, NBLE_RESET_PIN, 1); + if (ret) { + BT_ERR("Error pin write %d", NBLE_RESET_PIN); + return -EINVAL; + } + + /* Set back GPIO to input to avoid interfering with external debugger */ + ret = gpio_pin_configure(gpio, NBLE_RESET_PIN, GPIO_DIR_IN); + if (ret) { + BT_ERR("Error configuring pin %d", NBLE_RESET_PIN); + return -ENODEV; + } + + return 0; } int bt_le_adv_start(const struct bt_le_adv_param *param, diff --git a/drivers/nble/uart.h b/drivers/nble/uart.h index 3898292596d..1389d42aa43 100644 --- a/drivers/nble/uart.h +++ b/drivers/nble/uart.h @@ -54,6 +54,7 @@ struct ipc_uart_channels { void ipc_uart_isr(void); void ipc_uart_ns16550_disable(struct device *dev); +int nble_open(void); /** * This function triggers the sending of PDU buffer over UART.