Nimble/transport: HAL Support for UART transport

This commit is contained in:
Roshan Bangar
2024-02-29 16:23:47 +05:30
committed by Abhinav Kudnar
parent 396f1e6ebd
commit 0a0eeb985f
17 changed files with 204 additions and 372 deletions
+2 -2
View File
@@ -808,7 +808,7 @@ ble_hs_init(void)
ble_hs_evq_set(nimble_port_get_dflt_eventq()); ble_hs_evq_set(nimble_port_get_dflt_eventq());
#endif #endif
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
/* Configure the HCI transport to communicate with a host. */ /* Configure the HCI transport to communicate with a host. */
ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL);
#endif #endif
@@ -866,7 +866,7 @@ ble_hs_deinit(void)
ble_monitor_deinit(); ble_monitor_deinit();
#endif #endif
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
ble_hci_trans_cfg_hs(NULL, NULL, NULL, NULL); ble_hci_trans_cfg_hs(NULL, NULL, NULL, NULL);
#endif #endif
+1 -1
View File
@@ -265,7 +265,7 @@ ble_hs_flow_startup(void)
/* Flow control successfully enabled. */ /* Flow control successfully enabled. */
ble_hs_flow_num_completed_pkts = 0; ble_hs_flow_num_completed_pkts = 0;
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
ble_hci_trans_set_acl_free_cb(ble_hs_flow_acl_free, NULL); ble_hci_trans_set_acl_free_cb(ble_hs_flow_acl_free, NULL);
#else #else
ble_transport_register_put_acl_from_ll_cb(ble_hs_flow_acl_free); ble_transport_register_put_acl_from_ll_cb(ble_hs_flow_acl_free);
+2 -2
View File
@@ -429,7 +429,7 @@ ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg)
return 0; return 0;
} }
#if !(SOC_ESP_NIMBLE_CONTROLLER) #if !(SOC_ESP_NIMBLE_CONTROLLER) || !(CONFIG_BT_CONTROLLER_ENABLED)
/** /**
* Calculates the largest ACL payload that the controller can accept. * Calculates the largest ACL payload that the controller can accept.
*/ */
@@ -552,7 +552,7 @@ ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om)
/* Send fragments until the entire packet has been sent. */ /* Send fragments until the entire packet has been sent. */
while (txom != NULL && ble_hs_hci_avail_pkts > 0) { while (txom != NULL && ble_hs_hci_avail_pkts > 0) {
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
frag = mem_split_frag(&txom, BLE_ACL_MAX_PKT_SIZE, ble_hs_hci_frag_alloc, NULL); frag = mem_split_frag(&txom, BLE_ACL_MAX_PKT_SIZE, ble_hs_hci_frag_alloc, NULL);
#else #else
frag = mem_split_frag(&txom, ble_hs_hci_max_acl_payload_sz(), ble_hs_hci_frag_alloc, NULL); frag = mem_split_frag(&txom, ble_hs_hci_max_acl_payload_sz(), ble_hs_hci_frag_alloc, NULL);
+2 -2
View File
@@ -65,7 +65,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
BLE_HS_DBG_ASSERT(cmd != NULL); BLE_HS_DBG_ASSERT(cmd != NULL);
buf = (uint8_t *)cmd; buf = (uint8_t *)cmd;
#if !(SOC_ESP_NIMBLE_CONTROLLER) && !CONFIG_BT_CONTROLLER_DISABLED #if !(SOC_ESP_NIMBLE_CONTROLLER) && CONFIG_BT_CONTROLLER_ENABLED
/* Hack for avoiding memcpy while handling tx pkt to VHCI, /* Hack for avoiding memcpy while handling tx pkt to VHCI,
* keep one byte for type field*/ * keep one byte for type field*/
buf++; buf++;
@@ -82,7 +82,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata)
BLE_HS_LOG(DEBUG, "\n"); BLE_HS_LOG(DEBUG, "\n");
#endif #endif
#if !(SOC_ESP_NIMBLE_CONTROLLER) && !CONFIG_BT_CONTROLLER_DISABLED #if !(SOC_ESP_NIMBLE_CONTROLLER) && CONFIG_BT_CONTROLLER_ENABLED
buf--; buf--;
#endif #endif
+2 -2
View File
@@ -21,7 +21,7 @@
#include "host/util/util.h" #include "host/util/util.h"
#include "../src/ble_hs_hci_priv.h" #include "../src/ble_hs_hci_priv.h"
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#endif #endif
@@ -43,7 +43,7 @@ ble_hs_util_load_rand_addr(ble_addr_t *addr)
} }
#endif #endif
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
rc = esp_ble_hw_get_static_addr((esp_ble_addr_t *)addr); rc = esp_ble_hw_get_static_addr((esp_ble_addr_t *)addr);
if (rc == 0) { if (rc == 0) {
return 0; return 0;
@@ -27,6 +27,10 @@
#include <nimble/transport.h> #include <nimble/transport.h>
#include <nimble/transport/hci_h4.h> #include <nimble/transport/hci_h4.h>
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#define HCI_H4_SM_W4_PKT_TYPE 0 #define HCI_H4_SM_W4_PKT_TYPE 0
#define HCI_H4_SM_W4_HEADER 1 #define HCI_H4_SM_W4_HEADER 1
#define HCI_H4_SM_W4_PAYLOAD 2 #define HCI_H4_SM_W4_PAYLOAD 2
+10 -2
View File
@@ -64,11 +64,19 @@ extern "C" {
/* Host-to-controller command. */ /* Host-to-controller command. */
#define BLE_HCI_TRANS_BUF_CMD 3 #define BLE_HCI_TRANS_BUF_CMD 3
void ble_transport_init(void);
esp_err_t ble_buf_alloc(void);
void ble_buf_free(void);
void ble_transport_deinit(void);
/** Callback function types; executed when HCI packets are received. */ /** Callback function types; executed when HCI packets are received. */
typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg); typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg);
typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg); typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg);
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD) #define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD)
#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI) #define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI)
#define ble_transport_free ble_hci_trans_buf_free #define ble_transport_free ble_hci_trans_buf_free
@@ -331,7 +339,7 @@ struct os_mbuf;
void ble_transport_init(void); void ble_transport_init(void);
/* Allocators for supported data types */ /* Allocators for supported data types */
#if !SOC_ESP_NIMBLE_CONTROLLER #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED
void *ble_transport_alloc_cmd(void); void *ble_transport_alloc_cmd(void);
void *ble_transport_alloc_evt(int discardable); void *ble_transport_alloc_evt(int discardable);
struct os_mbuf *ble_transport_alloc_acl_from_hs(void); struct os_mbuf *ble_transport_alloc_acl_from_hs(void);
+1 -1
View File
@@ -19,7 +19,7 @@ extern "C" {
#endif #endif
#include <inttypes.h> #include <inttypes.h>
#include "driver/uart.h"
/** /**
* Function prototype for UART driver to ask for more data to send. * Function prototype for UART driver to ask for more data to send.
+2 -2
View File
@@ -28,7 +28,7 @@ struct os_mempool;
struct os_mbuf_pool; struct os_mbuf_pool;
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, int r_mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks,
uint32_t block_size, char *name, void **out_buf); uint32_t block_size, char *name, void **out_buf);
#define mem_malloc_mempool r_mem_malloc_mempool #define mem_malloc_mempool r_mem_malloc_mempool
@@ -88,7 +88,7 @@ int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg); typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz, struct os_mbuf *r_mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
mem_frag_alloc_fn *alloc_cb, void *cb_arg); mem_frag_alloc_fn *alloc_cb, void *cb_arg);
#define mem_split_frag r_mem_split_frag #define mem_split_frag r_mem_split_frag
+1 -1
View File
@@ -27,7 +27,7 @@
#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE #define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE #define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
#endif #endif
+1 -1
View File
@@ -206,7 +206,7 @@ extern "C" {
#endif #endif
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
void r_put_le16(void *buf, uint16_t x); void r_put_le16(void *buf, uint16_t x);
#define put_le16 r_put_le16 #define put_le16 r_put_le16
+1 -1
View File
@@ -245,7 +245,7 @@ _os_mbuf_trailingspace(struct os_mbuf *om)
#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om) #define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
/** /**
* Initializes an mqueue. An mqueue is a queue of mbufs that ties to a * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a
* particular task's event queue. Mqueues form a helper API around a common * particular task's event queue. Mqueues form a helper API around a common
+1 -1
View File
@@ -170,7 +170,7 @@ typedef __uint128_t os_membuf_t;
#define OS_MEMPOOL_BYTES(n,blksize) \ #define OS_MEMPOOL_BYTES(n,blksize) \
(sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
/** /**
* Initialize a memory pool. * Initialize a memory pool.
* *
+133 -346
View File
@@ -3,382 +3,169 @@
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "os/os.h" #include "freertos/task.h"
#include "hal/hal_uart.h" #include "freertos/queue.h"
#include "soc/soc.h"
#include "soc/system_reg.h"
#include "driver/gpio.h"
#include "esp_intr_alloc.h"
#include "riscv/interrupt.h"
#include "hal/uart_ll.h"
#include "freertos/semphr.h"
#include "rom/ets_sys.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "driver/periph_ctrl.h" #include "hal/hal_uart.h"
#include "esp_log.h"
#include "esp_attr.h"
struct hal_uart { static const char *TAG = "hal_uart";
uint8_t u_open:1;
uint8_t u_rx_stall:1; #define BUF_SIZE (1024)
uint8_t u_tx_started:1; #define RD_BUF_SIZE (BUF_SIZE)
uint8_t u_tx_buf;
hal_uart_rx_char u_rx_func; typedef struct{
hal_uart_tx_char u_tx_func; bool uart_opened;
hal_uart_tx_done u_tx_done; uart_port_t port;
SemaphoreHandle_t u_rx_sem; uart_config_t cfg;
QueueHandle_t evt_queue;
TaskHandle_t rx_task_handler;
hal_uart_tx_char tx_char;
hal_uart_tx_done tx_done;
hal_uart_rx_char rx_char;
void *u_func_arg; void *u_func_arg;
};
static struct hal_uart uart;
#define UART_FIFO_LEN (128) }hci_uart_t;
uint8_t rxbuffer[256]; static hci_uart_t hci_uart;
static uint16_t rd_ptr = 0;
static uint16_t wr_ptr = 0;
#define BUFFER_MASK (0xff)
static TaskHandle_t hci_uart_task_h;
void uart_init(uint32_t baud);
void uart0_init(uint32_t baud);
void uart0_tout_isr(void);
void uart_tout_isr(void);
void
hal_uart_blocking_tx(int port, uint8_t data){
}
int hal_uart_init(int uart_no, void *cfg)
{
// Uart_Init(uart_no, UART_CLK_FREQ_ROM);
return 0;
}
void hal_uart_start_rx(int uart)
{
ets_printf("rx support???\n");
}
int hal_uart_init_cbs(int uart_no, hal_uart_tx_char tx_func, int hal_uart_init_cbs(int uart_no, hal_uart_tx_char tx_func,
hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg) hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg)
{ {
struct hal_uart *u; hci_uart.tx_char=tx_func;
hci_uart.rx_char=rx_func;
u = &uart; hci_uart.tx_done=tx_done;
hci_uart.u_func_arg = arg;
if (u->u_open) {
return -1;
}
u->u_rx_func = rx_func;
u->u_tx_func = tx_func;
u->u_tx_done = tx_done;
u->u_func_arg = arg;
return 0; return 0;
} }
int hal_uart_config(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, static void IRAM_ATTR hci_uart_rx_task(void *pvParameters)
{
uart_event_t event;
uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
while(hci_uart.uart_opened) {
//Waiting for UART event.
if(xQueueReceive(hci_uart.evt_queue, (void * )&event, (TickType_t)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
ESP_LOGD(TAG, "uart[%d] event:", hci_uart.port);
switch(event.type) {
//Event of UART receving data
/*We'd better handler data event fast, there would be much more data events than
other types of events. If we take too much time on data event, the queue might
be full.*/
case UART_DATA:
// ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
uart_read_bytes(hci_uart.port, dtmp, event.size, portMAX_DELAY);
for (int i = 0 ; i < event.size; i++) {
hci_uart.rx_char(hci_uart.u_func_arg, dtmp[i]);
}
break;
//Event of HW FIFO overflow detected
case UART_FIFO_OVF:
ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(hci_uart.port);
xQueueReset(hci_uart.evt_queue);
break;
//Event of UART ring buffer full
case UART_BUFFER_FULL:
ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(hci_uart.port);
xQueueReset(hci_uart.evt_queue);
break;
//Event of UART RX break detected
case UART_BREAK:
ESP_LOGI(TAG, "uart rx break");
break;
//Event of UART parity check error
case UART_PARITY_ERR:
ESP_LOGI(TAG, "uart parity error");
break;
//Event of UART frame error
case UART_FRAME_ERR:
ESP_LOGI(TAG, "uart frame error");
break;
//Others
default:
ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
hci_uart.rx_task_handler = NULL;
vTaskDelete(NULL);
}
int hal_uart_config(int uart, int32_t speed, uint8_t data_bits, uint8_t stop_bits,
enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl) enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl)
{ {
struct hal_uart *u; uart_config_t uart_cfg = {
u = &uart; .baud_rate = speed,
.data_bits = data_bits,
.parity = parity,
.stop_bits = stop_bits,
.flow_ctrl = flow_ctl,
.source_clk = UART_SCLK_DEFAULT,
};
hci_uart.port = uart;
hci_uart.cfg = uart_cfg;
if (u->u_open) { int intr_alloc_flags = 0;
return -1; #if CONFIG_UART_ISR_IN_IRAM
} intr_alloc_flags = ESP_INTR_FLAG_IRAM;
if (uart_no) { #endif
uart_init(speed);
} else { ESP_ERROR_CHECK(uart_driver_install(uart, BUF_SIZE * 2, BUF_SIZE * 2, 20, &hci_uart.evt_queue, intr_alloc_flags));
uart0_init(speed); ESP_ERROR_CHECK(uart_param_config(uart, &hci_uart.cfg));
} ESP_ERROR_CHECK(uart_set_pin(uart, CONFIG_BT_NIMBLE_UART_TX_PIN, CONFIG_BT_NIMBLE_UART_RX_PIN, -1, -1));
u->u_open = 1;
hci_uart.uart_opened=true;
ESP_LOGI(TAG, "set uart pin tx:%d, rx:%d.\n", CONFIG_BT_NIMBLE_UART_TX_PIN, CONFIG_BT_NIMBLE_UART_RX_PIN);
ESP_LOGI(TAG, "set baud_rate:%d.\n", speed);
//Create a task to handler UART event from ISR
xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &hci_uart.rx_task_handler);
return 0; return 0;
} }
static int void IRAM_ATTR hal_uart_start_tx(int uart_no)
IRAM_ATTR_64MCPU hal_uart_tx_fill_buf(struct hal_uart *u, int uart_no)
{ {
int data; int data;
int i; uint8_t u8_data=0;
uart_dev_t *hw = &UART1; while(1){
if(!uart_no){ data = hci_uart.tx_char(hci_uart.u_func_arg);
hw = &UART0;
}
i = 0;
while(hw->status.txfifo_cnt < UART_FIFO_LEN){
data = u->u_tx_func(u->u_func_arg);
if (data >= 0) { if (data >= 0) {
hw->ahb_fifo.rw_byte = data; u8_data = data;
i++; uart_tx_chars(uart_no,(char*)&u8_data,1);
}else{ }else{
break; break;
} }
} }
return i; if(hci_uart.tx_done) {
} hci_uart.tx_done(hci_uart.u_func_arg);
void hal_uart_start_tx(int uart_no)
{
struct hal_uart *u;
os_sr_t sr;
uart_dev_t *hw = &UART1;
if(!uart_no){
hw = &UART0;
} }
u = &uart;
OS_ENTER_CRITICAL(sr);
if (u->u_tx_started == 0) {
u->u_tx_started = 1;
hw->int_ena.tx_done = 1;
hal_uart_tx_fill_buf(u,uart_no);
}
OS_EXIT_CRITICAL(sr);
}
int hal_uart0_close(int uart_no)
{
struct hal_uart *u;
u = &uart;
u->u_open = 0;
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
return 0;
} }
int hal_uart_close(int uart_no) int hal_uart_close(int uart_no)
{ {
struct hal_uart *u; hci_uart.uart_opened=false;
u = &uart; // Stop uart rx task
u->u_open = 0; if(hci_uart.rx_task_handler != NULL) {
ESP_LOGW(TAG,"Waiting for uart task finish...");
}
while (hci_uart.rx_task_handler != NULL);
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART1_CLK_EN); uart_driver_delete(uart_no);
REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST); ESP_LOGI(TAG,"hci uart close success.");
return 0; return 0;
} }
IRAM_ATTR_64MCPU void uart0_tout_isr(void)
{
struct hal_uart *u;
int rc;
uint32_t ch;
uart_dev_t *hw = &UART0;
u = &uart;
uint32_t uart_int_st = hw->int_st.val;
//clear
hw->int_clr.val = uart_int_st;
if (uart_int_st&UART_TX_DONE_INT_ST_M) {
rc = hal_uart_tx_fill_buf(u,0);
if (rc == 0) {
if (u->u_tx_done) {
u->u_tx_done(u->u_func_arg);
}
u->u_tx_started = 0;
hw->int_ena.tx_done = 0;
}
}
while (hw->status.rxfifo_cnt) {
int rd_len = hw->status.rxfifo_cnt;
for (int i = 0; i < rd_len; i++) {
ch = hw->ahb_fifo.rw_byte;
rc = u->u_rx_func(u->u_func_arg, ch);
if (rc < 0) {
u->u_rx_stall = 1;
}
}
}
}
IRAM_ATTR_64MCPU void uart_tout_isr(void)
{
struct hal_uart *u;
int rc;
bool rx_update = false;
uart_dev_t *hw = &UART1;
u = &uart;
uint32_t uart_int_st = hw->int_st.val;
//clear
hw->int_clr.val = uart_int_st;
if (uart_int_st&UART_TX_DONE_INT_ST_M) {
rc = hal_uart_tx_fill_buf(u,1);
if (rc == 0) {
if (u->u_tx_done) {
u->u_tx_done(u->u_func_arg);
}
u->u_tx_started = 0;
hw->int_ena.tx_done = 0;
}
}
while (hw->status.rxfifo_cnt) {
rxbuffer[(wr_ptr++)&BUFFER_MASK] = hw->ahb_fifo.rw_byte;
rx_update = true;
}
if (rx_update) {
xSemaphoreGiveFromISR(u->u_rx_sem, 0);
}
}
void
IRAM_ATTR uart_rx_task(void *arg){
int rc;
struct hal_uart *u;
u = &uart;
while (1) {
xSemaphoreTake(u->u_rx_sem, portMAX_DELAY);
while (rd_ptr != wr_ptr){
rc = u->u_rx_func(u->u_func_arg, rxbuffer[(rd_ptr++)&BUFFER_MASK]);
if (rc < 0) {
u->u_rx_stall = 1;
}
}
}
}
void uart0_init(uint32_t baud)
{
REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART_RST);
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART_CLK_EN_M);
const int sclk_div = 1;
uint32_t sclk_freq = XTAL_CLK_FREQ;
uint32_t clk_div = ((sclk_freq) << 4) / baud;
uart_dev_t *hw = &UART0;
hw->clk_conf.sclk_en = 0;
hw->clk_conf.rx_sclk_en = 0;
hw->clk_conf.tx_sclk_en = 0;
hw->clk_conf.sclk_en = 1;
hw->clk_conf.rx_sclk_en = 1;
hw->clk_conf.tx_sclk_en = 1;
hw->clk_div.div_int = clk_div >> 4;
hw->clk_div.div_frag = clk_div & 0xf;
hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255;
hw->conf0.parity_en = 0;
hw->conf0.irda_en = 0;
hw->rs485_conf.en = 0;
hw->rs485_conf.tx_rx_en = 0;
hw->rs485_conf.rx_busy_tx_en = 0;
hw->conf0.bit_num = 3;
hw->conf0.stop_bit_num = 1;
hw->conf1.rxfifo_full_thrhd = 80;
hw->mem_conf.rx_tout_thrhd = 20;
hw->conf1.rx_tout_en = 1;
hw->conf1.rx_flow_en = 0;
hw->conf0.tx_flow_en = 0;
hw->conf0.rxfifo_rst = 1;
hw->conf0.rxfifo_rst = 0;
hw->conf0.txfifo_rst = 1;
hw->conf0.txfifo_rst = 0;
hw->int_ena.rxfifo_full = 1;
//enable rx fifo timeout interrupt
hw->int_ena.rxfifo_tout = 1;
uint8_t tx_pin = 21, rx_pin = 20, ISR_ID = ETS_UART0_INUM;
ets_isr_mask((1<<ISR_ID)); //ETS_INTR_DISABLE
intr_handler_set(ISR_ID, (intr_handler_t)&uart0_tout_isr, NULL);
intr_matrix_route(ETS_UART0_INTR_SOURCE, ISR_ID);
esprv_intc_int_enable(BIT(ISR_ID));
esprv_intc_int_set_type(ISR_ID, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ISR_ID, 1);
esp_intr_reserve(ISR_ID, xPortGetCoreID());
ESP_ERROR_CHECK(uart_set_pin(0, tx_pin, rx_pin, -1, -1));
}
void uart_init(uint32_t baud)
{
periph_module_enable(PERIPH_UART1_MODULE);
REG_SET_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_UART1_RST);
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART1_CLK_EN_M);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_UART1_CLK_EN_M);
const int sclk_div = 1;
uint32_t sclk_freq = XTAL_CLK_FREQ;
uint32_t clk_div = ((sclk_freq) << 4) / baud;
struct hal_uart *u = &uart;
uart_dev_t *hw = &UART1;
hw->clk_conf.sclk_en = 0;
hw->clk_conf.rx_sclk_en = 0;
hw->clk_conf.tx_sclk_en = 0;
hw->clk_conf.sclk_en = 1;
hw->clk_conf.rx_sclk_en = 1;
hw->clk_conf.tx_sclk_en = 1;
hw->clk_div.div_int = clk_div >> 4;
hw->clk_div.div_frag = clk_div & 0xf;
hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255;
hw->conf0.parity_en = 0;
hw->conf0.irda_en = 0;
hw->rs485_conf.en = 0;
hw->rs485_conf.tx_rx_en = 0;
hw->rs485_conf.rx_busy_tx_en = 0;
hw->conf0.bit_num = 3;
hw->conf0.stop_bit_num = 1;
//set full threshold to (2/3)*FIFO_LEN
hw->conf1.rxfifo_full_thrhd = 80;
hw->mem_conf.rx_tout_thrhd = 20;
hw->conf1.rx_tout_en = 1;
hw->conf0.rxfifo_rst = 1;
hw->conf0.rxfifo_rst = 0;
hw->conf0.txfifo_rst = 1;
hw->conf0.txfifo_rst = 0;
hw->int_ena.rxfifo_full = 1;
//enable rx fifo timeout interrupt
hw->int_ena.rxfifo_tout = 1;
u->u_rx_sem = xSemaphoreCreateBinary();
uint8_t TX_IO = CONFIG_BT_LE_HCI_UART_TX_PIN, RX_IO = CONFIG_BT_LE_HCI_UART_RX_PIN, ISR_ID = ETS_UART1_INUM;
printf("set nimble port tx:%d, rx:%d.\n", TX_IO, RX_IO);
printf("set baud:%d.\n", baud);
intr_handler_set(ISR_ID, (intr_handler_t)&uart_tout_isr, NULL);
intr_matrix_route(ETS_UART1_INTR_SOURCE, ISR_ID);
esprv_intc_int_enable(BIT(ISR_ID));
esprv_intc_int_set_type(ISR_ID, INTR_TYPE_LEVEL);
esprv_intc_int_set_priority(ISR_ID, 1);
// TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure...
esp_intr_reserve(ISR_ID, xPortGetCoreID());
ESP_ERROR_CHECK(uart_set_pin(1, TX_IO, RX_IO, -1, -1));
//Enable hw flow control of UART1 for BQB test, which if not enabled, the tester takes quite long time to send a byte to DUT
// uart_ll_set_hw_flow_ctrl(hw, UART_HW_FLOWCTRL_CTS_RTS, 110);
xTaskCreate(uart_rx_task, "uart_rx", CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE,
NULL, 1, &hci_uart_task_h);
}
+35 -4
View File
@@ -35,10 +35,15 @@
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#if CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#if !SOC_ESP_NIMBLE_CONTROLLER #endif
#if !SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
#include "esp_nimble_hci.h" #include "esp_nimble_hci.h"
#endif #endif
#if !CONFIG_BT_CONTROLLER_ENABLED
#include "nimble/transport.h"
#endif
#define NIMBLE_PORT_LOG_TAG "BLE_INIT" #define NIMBLE_PORT_LOG_TAG "BLE_INIT"
@@ -80,16 +85,31 @@ nimble_port_stop_cb(struct ble_npl_event *ev)
*/ */
esp_err_t esp_nimble_init(void) esp_err_t esp_nimble_init(void)
{ {
#if !SOC_ESP_NIMBLE_CONTROLLER #if CONFIG_BT_CONTROLLER_DISABLED
esp_err_t ret;
#endif
#if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED
/* Initialize the function pointers for OS porting */ /* Initialize the function pointers for OS porting */
npl_freertos_funcs_init(); npl_freertos_funcs_init();
npl_freertos_mempool_init(); npl_freertos_mempool_init();
#if CONFIG_BT_CONTROLLER_ENABLED
if(esp_nimble_hci_init() != ESP_OK) { if(esp_nimble_hci_init() != ESP_OK) {
ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n"); ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci inits failed\n");
return ESP_FAIL; return ESP_FAIL;
} }
#else
ret = ble_buf_alloc();
if (ret != ESP_OK) {
ble_buf_free();
return ESP_FAIL;
}
ble_transport_init();
#if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK)
ble_adv_list_init();
#endif
#endif
/* Initialize default event queue */ /* Initialize default event queue */
ble_npl_eventq_init(&g_eventq_dflt); ble_npl_eventq_init(&g_eventq_dflt);
@@ -100,6 +120,9 @@ esp_err_t esp_nimble_init(void)
#endif #endif
/* Initialize the host */ /* Initialize the host */
ble_transport_hs_init(); ble_transport_hs_init();
#if CONFIG_BT_CONTROLLER_DISABLED && CONFIG_BT_NIMBLE_TRANSPORT_UART
ble_transport_ll_init();
#endif
return ESP_OK; return ESP_OK;
} }
@@ -112,15 +135,23 @@ esp_err_t esp_nimble_init(void)
esp_err_t esp_nimble_deinit(void) esp_err_t esp_nimble_deinit(void)
{ {
#if !SOC_ESP_NIMBLE_CONTROLLER #if !SOC_ESP_NIMBLE_CONTROLLER
#if CONFIG_BT_CONTROLLER_ENABLED
if(esp_nimble_hci_deinit() != ESP_OK) { if(esp_nimble_hci_deinit() != ESP_OK) {
ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci deinit failed\n"); ESP_LOGE(NIMBLE_PORT_LOG_TAG, "hci deinit failed\n");
return ESP_FAIL; return ESP_FAIL;
} }
#else
#if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK)
ble_adv_list_deinit();
#endif
ble_transport_deinit();
ble_buf_free();
#endif
ble_npl_eventq_deinit(&g_eventq_dflt); ble_npl_eventq_deinit(&g_eventq_dflt);
#endif #endif
ble_hs_deinit(); ble_hs_deinit();
#if !SOC_ESP_NIMBLE_CONTROLLER #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED
npl_freertos_funcs_deinit(); npl_freertos_funcs_deinit();
#endif #endif
return ESP_OK; return ESP_OK;
@@ -136,7 +167,7 @@ nimble_port_init(void)
{ {
esp_err_t ret; esp_err_t ret;
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32 && CONFIG_BT_CONTROLLER_ENABLED
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
#endif #endif
#if CONFIG_BT_CONTROLLER_ENABLED #if CONFIG_BT_CONTROLLER_ENABLED
@@ -21,7 +21,9 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "nimble/nimble_port.h" #include "nimble/nimble_port.h"
#if CONFIG_BT_CONTROLLER_ENABLED
#include "esp_bt.h" #include "esp_bt.h"
#endif
static TaskHandle_t host_task_h = NULL; static TaskHandle_t host_task_h = NULL;
+4 -4
View File
@@ -104,7 +104,7 @@ static const char *TAG = "Timer";
#define BLE_TOTAL_MUTEX_COUNT (10) #define BLE_TOTAL_MUTEX_COUNT (10)
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
struct os_mempool ble_freertos_ev_pool; struct os_mempool ble_freertos_ev_pool;
static os_membuf_t *ble_freertos_ev_buf = NULL; static os_membuf_t *ble_freertos_ev_buf = NULL;
@@ -1145,7 +1145,7 @@ int npl_freertos_mempool_init(void)
{ {
int rc = -1; int rc = -1;
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
ble_freertos_ev_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t)); ble_freertos_ev_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t));
if(!ble_freertos_ev_buf) { if(!ble_freertos_ev_buf) {
goto _error; goto _error;
@@ -1205,7 +1205,7 @@ int npl_freertos_mempool_init(void)
} }
_error: _error:
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
if(ble_freertos_ev_buf) { if(ble_freertos_ev_buf) {
free(ble_freertos_ev_buf); free(ble_freertos_ev_buf);
ble_freertos_ev_buf = NULL; ble_freertos_ev_buf = NULL;
@@ -1236,7 +1236,7 @@ _error:
void npl_freertos_mempool_deinit(void) void npl_freertos_mempool_deinit(void)
{ {
#if SOC_ESP_NIMBLE_CONTROLLER #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED
if(ble_freertos_ev_buf) { if(ble_freertos_ev_buf) {
free(ble_freertos_ev_buf); free(ble_freertos_ev_buf);
ble_freertos_ev_buf = NULL; ble_freertos_ev_buf = NULL;