Page 1 of 1

BT SPP -> where am I losing bytes?

Posted: Mon Oct 08, 2018 8:21 pm
by vinci1989
Hello there

I've recently bought a couple of PicoKits and would like to establish a robust SPP connection which is able to handle at least 1MBaud throughput. Sadly I'm currently nowhere near that and seem to be struggling with losing some bytes in the process... I've tested my application by sending rather large files (~2-3MB) with 115kBaud around and there are always a couple of hundred bytes missing.

The application is rather simple. There is a UART RX task which reads data, puts it into a ringbuffer and sends the ringbuffer handle to a queue. Then there is a BT TX task which receives from that queue, takes the ringbuffer handle, reads the data and writes it with the "esp_spp_write" function.

// UART RX task

Code: Select all

static void uart_rx_task(void* pvParameter) {
  std::unique_ptr<uint8_t[]> rx{new (std::nothrow) uint8_t[uart_chunk_size]};

  for (;;) {
    esp_task_wdt_reset();

    // Read data from UART
    size_t buffered_len{0};
    uart_get_buffered_data_len(uart_num, &buffered_len);
    if (!buffered_len)
      continue;

    auto len{uart_read_bytes(
        uart_num,
        &rx[0],
        buffered_len > uart_chunk_size ? uart_chunk_size : buffered_len,
        pdMS_TO_TICKS(10))};
    if (len <= 0)
      continue;

    // Send data to ring buffer
    while (!xRingbufferSend(uart2bt_buf, &rx[0], len, pdMS_TO_TICKS(10)))
      vTaskDelay(pdMS_TO_TICKS(10));

    // Send ring buffer handle to queue
    while (!xQueueSend(uart2bt_queue, &uart2bt_buf, pdMS_TO_TICKS(10)))
      vTaskDelay(pdMS_TO_TICKS(10));
  }
}
// BT TX task

Code: Select all

static void bt_tx_task(void* pvParameter) {
  uint32_t const handle{(uint32_t const)pvParameter};

  for (;;) {
    esp_task_wdt_reset();

    // Receive handle from queue
    RingbufHandle_t uart2bt_buf{nullptr};
    if (!xQueueReceive(uart2bt_queue, &uart2bt_buf, portMAX_DELAY))
      continue;

    // Receive data from ring buffer
    size_t len{};
    vRingbufferGetInfo(uart2bt_buf, nullptr, nullptr, nullptr, &len);
    if (!len)
      continue;

    uint8_t* data{(uint8_t*)xRingbufferReceiveUpTo(
        uart2bt_buf, &len, pdMS_TO_TICKS(10), len)};
    if (!data)
      continue;

    // Write data to SPP
    esp_spp_write(handle, len, data);

    // Return item from ring buffer
    vRingbufferReturnItem(uart2bt_buf, (void*)data);
  }
}
On the "SPP" receiving side I use the ESP_SPP_DATA_IND_EVT event inside my SPP callback and do basically the same thing I did with UART. Putting the data into a ringbuffer and shipping the handle of by queue... This is actually the part I believe is wrong. I'm not sure if I'm supposed to stall the SPP callback in case the buffer or queue blocks? Any suggestions how this could be handled any better?

Code: Select all

...

case ESP_SPP_DATA_IND_EVT:

  // Send data to ring buffer
  while (!xRingbufferSend(bt2uart_buf,
                          param->data_ind.data,
                          param->data_ind.len,
                          pdMS_TO_TICKS(10)))
    vTaskDelay(pdMS_TO_TICKS(10));

  // Send ring buffer handle to queue
  while (!xQueueSend(bt2uart_queue, &bt2uart_buf, pdMS_TO_TICKS(10)))
    vTaskDelay(pdMS_TO_TICKS(10));
    
 ...

I guess by now you could probably have guessed how the UART TX task looks, but here it is for completeness. Again it uses the same ringbuffer/queue pattern seen before.

Code: Select all

static void uart_tx_task(void* pvParameter) {
  for (;;) {
    esp_task_wdt_reset();

    // Receive handle from queue
    RingbufHandle_t bt2uart_buf{nullptr};
    if (!xQueueReceive(bt2uart_queue, &bt2uart_buf, portMAX_DELAY))
      continue;

    // Receive data from ring buffer
    size_t len{};
    vRingbufferGetInfo(bt2uart_buf, nullptr, nullptr, nullptr, &len);
    if (!len)
      continue;

    uint8_t* data{(uint8_t*)xRingbufferReceiveUpTo(
        bt2uart_buf, &len, pdMS_TO_TICKS(10), len)};
    if (!data)
      continue;

    // Write data to UART
    uart_write_bytes(uart_num, (const char*)data, len);

    // Return item from ring buffer
    vRingbufferReturnItem(bt2uart_buf, (void*)data);
  }
}

Am I doing something horribly wrong? Is this "ringbuffer/queue" pattern the right one for this task?

Re: BT SPP -> where am I losing bytes?

Posted: Wed Oct 10, 2018 3:48 pm
by vinci1989
Ok, I've found the issue. It was already reported back in may:
viewtopic.php?f=13&t=5613&p=30097&hilit ... oug#p24399

/edit
link fixed