Fix BluetoothSerial TX Stall
Fixes: https://github.com/espressif/arduino-esp32/issues/4949
This commit is contained in:
parent
5da4a47bdf
commit
5b845272ed
@ -42,6 +42,10 @@ const char * _spp_server_name = "ESP32SPP";
|
|||||||
|
|
||||||
#define RX_QUEUE_SIZE 512
|
#define RX_QUEUE_SIZE 512
|
||||||
#define TX_QUEUE_SIZE 32
|
#define TX_QUEUE_SIZE 32
|
||||||
|
#define SPP_TX_QUEUE_TIMEOUT 1000
|
||||||
|
#define SPP_TX_DONE_TIMEOUT 1000
|
||||||
|
#define SPP_CONGESTED_TIMEOUT 1000
|
||||||
|
|
||||||
static uint32_t _spp_client = 0;
|
static uint32_t _spp_client = 0;
|
||||||
static xQueueHandle _spp_rx_queue = NULL;
|
static xQueueHandle _spp_rx_queue = NULL;
|
||||||
static xQueueHandle _spp_tx_queue = NULL;
|
static xQueueHandle _spp_tx_queue = NULL;
|
||||||
@ -143,7 +147,7 @@ static esp_err_t _spp_queue_packet(uint8_t *data, size_t len){
|
|||||||
}
|
}
|
||||||
packet->len = len;
|
packet->len = len;
|
||||||
memcpy(packet->data, data, len);
|
memcpy(packet->data, data, len);
|
||||||
if (xQueueSend(_spp_tx_queue, &packet, portMAX_DELAY) != pdPASS) {
|
if (!_spp_tx_queue || xQueueSend(_spp_tx_queue, &packet, SPP_TX_QUEUE_TIMEOUT) != pdPASS) {
|
||||||
log_e("SPP TX Queue Send Failed!");
|
log_e("SPP TX Queue Send Failed!");
|
||||||
free(packet);
|
free(packet);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
@ -156,19 +160,25 @@ static uint8_t _spp_tx_buffer[SPP_TX_MAX];
|
|||||||
static uint16_t _spp_tx_buffer_len = 0;
|
static uint16_t _spp_tx_buffer_len = 0;
|
||||||
|
|
||||||
static bool _spp_send_buffer(){
|
static bool _spp_send_buffer(){
|
||||||
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, portMAX_DELAY) & SPP_CONGESTED) != 0){
|
if((xEventGroupWaitBits(_spp_event_group, SPP_CONGESTED, pdFALSE, pdTRUE, SPP_CONGESTED_TIMEOUT) & SPP_CONGESTED) != 0){
|
||||||
|
if(!_spp_client){
|
||||||
|
log_v("SPP Client Gone!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_v("SPP Write %u", _spp_tx_buffer_len);
|
||||||
esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer);
|
esp_err_t err = esp_spp_write(_spp_client, _spp_tx_buffer_len, _spp_tx_buffer);
|
||||||
if(err != ESP_OK){
|
if(err != ESP_OK){
|
||||||
log_e("SPP Write Failed! [0x%X]", err);
|
log_e("SPP Write Failed! [0x%X]", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_spp_tx_buffer_len = 0;
|
_spp_tx_buffer_len = 0;
|
||||||
if(xSemaphoreTake(_spp_tx_done, portMAX_DELAY) != pdTRUE){
|
if(xSemaphoreTake(_spp_tx_done, SPP_TX_DONE_TIMEOUT) != pdTRUE){
|
||||||
log_e("SPP Ack Failed!");
|
log_e("SPP Ack Failed!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
log_e("SPP Write Congested!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,13 +204,18 @@ static void _spp_tx_task(void * arg){
|
|||||||
_spp_tx_buffer_len = SPP_TX_MAX;
|
_spp_tx_buffer_len = SPP_TX_MAX;
|
||||||
data += to_send;
|
data += to_send;
|
||||||
len -= to_send;
|
len -= to_send;
|
||||||
_spp_send_buffer();
|
if(!_spp_send_buffer()){
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
while(len >= SPP_TX_MAX){
|
while(len >= SPP_TX_MAX){
|
||||||
memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
|
memcpy(_spp_tx_buffer, data, SPP_TX_MAX);
|
||||||
_spp_tx_buffer_len = SPP_TX_MAX;
|
_spp_tx_buffer_len = SPP_TX_MAX;
|
||||||
data += SPP_TX_MAX;
|
data += SPP_TX_MAX;
|
||||||
len -= SPP_TX_MAX;
|
len -= SPP_TX_MAX;
|
||||||
_spp_send_buffer();
|
if(!_spp_send_buffer()){
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(len){
|
if(len){
|
||||||
memcpy(_spp_tx_buffer, data, len);
|
memcpy(_spp_tx_buffer, data, len);
|
||||||
@ -236,9 +251,10 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
|
|
||||||
case ESP_SPP_SRV_OPEN_EVT://Server connection open
|
case ESP_SPP_SRV_OPEN_EVT://Server connection open
|
||||||
if (param->srv_open.status == ESP_SPP_SUCCESS) {
|
if (param->srv_open.status == ESP_SPP_SUCCESS) {
|
||||||
log_i("ESP_SPP_SRV_OPEN_EVT");
|
log_i("ESP_SPP_SRV_OPEN_EVT: %u", _spp_client);
|
||||||
if (!_spp_client){
|
if (!_spp_client){
|
||||||
_spp_client = param->srv_open.handle;
|
_spp_client = param->srv_open.handle;
|
||||||
|
_spp_tx_buffer_len = 0;
|
||||||
} else {
|
} else {
|
||||||
secondConnectionAttempt = true;
|
secondConnectionAttempt = true;
|
||||||
esp_spp_disconnect(param->srv_open.handle);
|
esp_spp_disconnect(param->srv_open.handle);
|
||||||
@ -252,12 +268,13 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
|
|
||||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||||
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
|
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
|
||||||
log_i("ESP_SPP_CLOSE_EVT");
|
log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
|
||||||
if(secondConnectionAttempt) {
|
if(secondConnectionAttempt) {
|
||||||
secondConnectionAttempt = false;
|
secondConnectionAttempt = false;
|
||||||
} else {
|
} else {
|
||||||
_spp_client = 0;
|
_spp_client = 0;
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||||
}
|
}
|
||||||
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
||||||
} else {
|
} else {
|
||||||
@ -279,11 +296,11 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
if(param->write.cong){
|
if(param->write.cong){
|
||||||
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
|
xEventGroupClearBits(_spp_event_group, SPP_CONGESTED);
|
||||||
}
|
}
|
||||||
xSemaphoreGive(_spp_tx_done);//we can try to send another packet
|
|
||||||
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"");
|
log_v("ESP_SPP_WRITE_EVT: %u %s", param->write.len, param->write.cong?"CONGESTED":"");
|
||||||
} else {
|
} else {
|
||||||
log_e("ESP_SPP_WRITE_EVT failed!, status:%d", param->write.status);
|
log_e("ESP_SPP_WRITE_EVT failed!, status:%d", param->write.status);
|
||||||
}
|
}
|
||||||
|
xSemaphoreGive(_spp_tx_done);//we can try to send another packet
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_SPP_DATA_IND_EVT://connection received data
|
case ESP_SPP_DATA_IND_EVT://connection received data
|
||||||
@ -323,6 +340,7 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
}
|
}
|
||||||
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
|
xEventGroupClearBits(_spp_event_group, SPP_DISCONNECTED);
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
|
xEventGroupSetBits(_spp_event_group, SPP_CONNECTED);
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_SPP_START_EVT://server started
|
case ESP_SPP_START_EVT://server started
|
||||||
@ -693,7 +711,7 @@ void BluetoothSerial::flush()
|
|||||||
{
|
{
|
||||||
if (_spp_tx_queue != NULL){
|
if (_spp_tx_queue != NULL){
|
||||||
while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){
|
while(uxQueueMessagesWaiting(_spp_tx_queue) > 0){
|
||||||
delay(5);
|
delay(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user