M changelog.md => changelog.md +3 -0
@@ 6,6 6,9 @@
### Added
* `[utils]` Dump logs to a file on RT1051 after reaching 80% of log buffer utilization.
+### Changed
+* `[bluetooth]` Underlying communication with the Bluetooth module over DMA (direct access)
+
[Current release]
### Added
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +36 -29
@@ 11,6 11,19 @@ extern "C"
#include "module-bluetooth/lib/btstack/src/btstack_util.h"
};
+#if DEBUG_BLUETOOTH_HCI_COMS == 1
+#define logHciComs(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define logHciComs(...)
+#endif
+
+#if DEBUG_BLUETOOTH_HCI_BYTES == 1
+#include <sstream>
+#define logHciBytes(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define logHciBytes(...)
+#endif
+
using namespace bsp;
const char *c_str(Bt::Error::Code code)
@@ 110,8 123,6 @@ bool BluetoothWorker::start_pan()
return false;
}
-#include <sstream>
-
bool BluetoothWorker::handleMessage(uint32_t queueID)
{
@@ 127,51 138,47 @@ bool BluetoothWorker::handleMessage(uint32_t queueID)
Bt::Message notification = Bt::Message::EvtErrorRec;
if (xQueueReceive(queue, ¬ification, 0) != pdTRUE) {
- LOG_ERROR("Receive failure!");
+ LOG_ERROR("Queue receive failure!");
return false;
}
auto bt = BlueKitchen::getInstance();
switch (notification) {
+ case Bt::Message::EvtSending:
+ logHciComs("[evt] sending");
+ break;
case Bt::Message::EvtSent:
-#ifdef DO_DEBUG_HCI_COMS
- LOG_INFO("[evt] sent");
-#endif
+ logHciComs("[evt] sent");
if (bt->write_done_cb) {
bt->write_done_cb();
}
break;
+ case Bt::Message::EvtReceiving:
+ logHciComs("[evt] receiving");
+ break;
case Bt::Message::EvtReceived: {
- if (bt->to_read_req > bt->in.len) {
- // LOG_ERROR("%d vs %d", bt->to_read_req, bt->in.len);
- break;
- }
- for (int i = 0; i < bt->to_read_req; ++i) {
- // error in pop should never happen
- if (int ret = bt->in.pop((char *)bt->read_buff + i)) {
- LOG_ERROR("This shall never happen: %d", ret);
- }
- }
- // LOG_DEBUG(">> %d",bt->in.len);
-#ifdef DO_DEBUG_HCI_COMS
- std::stringstream ss;
- for (int i = 0; i < bt->to_read_req; ++i) {
- ss << " 0x" << std::hex << (int)*(bt->read_buff + i);
- }
- LOG_DEBUG("[evt] recieved <-- [%d]>%s<", bt->to_read_req, ss.str().c_str());
-#endif
- bt->to_read_req = 0;
+ logHciBytes("[evt] BT DMA received <-- [%ld]>%s<",
+ bt->read_len,
+ [&]() -> std::string {
+ std::stringstream ss;
+ for (int i = 0; i < bt->read_len; ++i) {
+ ss << " 0x" << std::hex << (int)*(bt->read_buff + i);
+ }
+ return ss.str();
+ }()
+ .c_str());
+
+ bt->read_len = 0;
if (bt->read_ready_cb) {
bt->read_ready_cb();
}
} break;
- case Bt::Message::EvtSentError:
- case Bt::Message::EvtRecError:
+ case Bt::Message::EvtSendingError:
+ case Bt::Message::EvtReceivingError:
case Bt::Message::EvtUartError:
- case Bt::Message::EvtRecUnwanted: {
+ case Bt::Message::EvtRecUnwanted:
LOG_ERROR("Uart error [%d]: %s", notification, Bt::MessageCstr(notification));
break;
- } break;
default:
LOG_ERROR("ERROR");
}
M module-bluetooth/Bluetooth/BluetoothWorker.hpp => module-bluetooth/Bluetooth/BluetoothWorker.hpp +13 -11
@@ 22,13 22,15 @@ namespace Bt
enum Message : uint8_t
{
/// asynchronous messages to use on event from irq
- EvtSent, /// trigger Bt stack wrote, enable writting in HCI in BluetoothWorker task
- EvtRecUnwanted, /// not requested recieve - probably receive came to fast from sent...
- EvtRecError, /// bsp error on receive
- EvtSentError, /// bsp error on send
- EvtUartError, /// generic uart error
- EvtReceived, /// trigger Bt stack received, start processing HCI in BluetoothWorker task
- EvtErrorRec, /// there was error o queue receive
+ EvtSending, /// Bt stack ordered a write transaction and it is pending
+ EvtSent, /// trigger Bt stack wrote, enable writting in HCI in BluetoothWorker task
+ EvtSendingError, /// bsp error on send
+ EvtReceiving, /// Bt stack requested a receive transaction and it is pending
+ EvtReceived, /// trigger Bt stack received, start processing HCI in BluetoothWorker task
+ EvtRecUnwanted, /// not requested recieve - probably receive came to fast from sent...
+ EvtReceivingError, /// bsp error on receive
+ EvtUartError, /// generic uart error
+ EvtErrorRec, /// there was error o queue receive
};
inline const char *MessageCstr(Message what)
@@ 40,10 42,10 @@ namespace Bt
return "EvtSent";
case EvtRecUnwanted:
return "EvtRecUnwanted";
- case EvtRecError:
- return "EvtRecError";
- case EvtSentError:
- return "EvtSentError";
+ case EvtReceivingError:
+ return "EvtReceivingError";
+ case EvtSendingError:
+ return "EvtSendingError";
case EvtUartError:
return "EvtUartError";
case EvtErrorRec:
M module-bluetooth/Bluetooth/glucode/btstack_uart_block_rt1051.cpp => module-bluetooth/Bluetooth/glucode/btstack_uart_block_rt1051.cpp +1 -1
@@ 83,7 83,7 @@ extern "C"
#ifdef DEBUG_UART
LOG_INFO("--> write: %d", length);
#endif
- BlueKitchen::getInstance()->write_blocking((char *)buffer, length);
+ BlueKitchen::getInstance()->write(buffer, length);
}
static const btstack_uart_block_t btstack_uart_posix = {
M module-bsp/board/linux/bluetooth/Bluetooth.cpp => module-bsp/board/linux/bluetooth/Bluetooth.cpp +13 -42
@@ 9,22 9,7 @@
using namespace bsp;
-void BTdev::_circ::sem_take()
-{}
-void BTdev::_circ::sem_give()
-{}
-
-BTdev::_circ::_circ(unsigned int size, int threshold) : head(0), tail(0), threshold(threshold), size(size), len(0)
-{
- buff = new char[size];
-}
-BTdev::_circ::~_circ()
-{
- delete[] buff;
-}
-
-BlueKitchen::BlueKitchen(unsigned int in_size, unsigned int out_size) : BluetoothCommon(in_size, out_size)
-{}
+BlueKitchen::BlueKitchen() = default;
BlueKitchen *BlueKitchen::getInstance()
{
@@ 35,14 20,7 @@ BlueKitchen *BlueKitchen::getInstance()
return k;
}
-ssize_t BlueKitchen::write_blocking(char *buf, ssize_t len)
-{
- return 0;
-}
-
-BluetoothCommon::BluetoothCommon(unsigned int in_size, unsigned int out_size, int threshold)
- : BTdev(in_size, out_size, threshold)
-{}
+BluetoothCommon::BluetoothCommon() = default;
BlueKitchen::~BlueKitchen()
{}
@@ 61,40 39,39 @@ void BluetoothCommon::sleep_ms(ssize_t ms)
ulTaskNotifyTake(pdTRUE, ms);
}
-BTdev::Error BluetoothCommon::flush()
+BTdev::Error BlueKitchen::read(uint8_t *buf, size_t nbytes)
{
return Success;
}
-ssize_t BluetoothCommon::write(char *buf, size_t nbytes)
+BTdev::Error BluetoothCommon::read(uint8_t *buf, size_t nbytes)
{
- return 0;
+ return Success;
}
-ssize_t BluetoothCommon::write_blocking(char *buf, ssize_t len)
+BTdev::Error BlueKitchen::write(const uint8_t *buf, size_t nbytes)
{
- return 0;
+ return Success;
}
-BTdev::Error BluetoothCommon::set_baudrate(uint32_t bd)
+BTdev::Error BluetoothCommon::write(const uint8_t *buf, size_t nbytes)
{
return Success;
}
-// set flow on -> true, set flow off -> false
-BTdev::Error BluetoothCommon::set_rts(bool on)
+ssize_t BluetoothCommon::write_blocking(const uint8_t *buf, ssize_t nbytes)
{
- return Success;
+ return 0;
}
-BTdev::Error BluetoothCommon::set_reset(bool on)
+BTdev::Error BluetoothCommon::set_baudrate(uint32_t bd)
{
return Success;
}
-int BluetoothCommon::read_cts()
+BTdev::Error BluetoothCommon::set_reset(bool on)
{
- return 0;
+ return Success;
}
void BluetoothCommon::configure_uart_io()
@@ 108,9 85,3 @@ void BluetoothCommon::configure_cts_irq()
void BluetoothCommon::set_irq(bool enable)
{}
-
-ssize_t BlueKitchen::read(void *buf, size_t nbytes)
-{
- return 0;
-}
-
M module-bsp/board/rt1051/bluetooth/BlueKitchen.cpp => module-bsp/board/rt1051/bluetooth/BlueKitchen.cpp +37 -80
@@ 8,15 8,19 @@
#include "fsl_lpuart.h"
#include "board.h"
+#if DEBUG_BLUETOOTH_HCI_COMS == 1
+#define logHciStack(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define logHciStack(...)
+#endif
+
using namespace bsp;
-BlueKitchen::BlueKitchen(unsigned int in_size, unsigned int out_size) : BluetoothCommon(in_size, out_size)
+BlueKitchen::BlueKitchen()
{
- to_read = 0;
read_buff = NULL;
read_ready_cb = NULL;
write_done_cb = NULL;
- in.threshold = 128;
}
BlueKitchen::~BlueKitchen()
@@ 28,96 32,49 @@ BlueKitchen *BlueKitchen::getInstance()
if (k == NULL) {
/// outcomming & incomming heap allocated buffers sizes
/// packet on IP network cna have MTU 1500, so big enough buffers were added to not throttle comms
- k = new BlueKitchen(2048, 8000);
+ k = new BlueKitchen();
}
return k;
}
-// request... from circ buffer
-ssize_t BlueKitchen::read(void *buf, size_t nbytes)
-{
- set_rts(false);
- to_read = nbytes;
- to_read_req = nbytes;
- read_buff = reinterpret_cast<char *>(buf);
- // set bt ptr to 0, len to 0, to read to nbytes
- // bt->to_read
- BaseType_t taskwoken = 0;
- uint8_t val = Bt::Message::EvtReceived;
- if ((to_read != 0) && (in.len >= to_read)) {
- to_read = 0;
- if (qHandle) {
- xQueueSendFromISR(qHandle, &val, &taskwoken);
- portEND_SWITCHING_ISR(taskwoken);
- }
- }
- set_rts(true);
- return 0;
-}
-
-void BlueKitchen::set_flowcontrol(int on)
+BTdev::Error BlueKitchen::read(uint8_t *buf, size_t nbytes)
{
- // TODO
-}
+ logHciStack("BlueKitchen requested to read %d bytes", nbytes);
-#include <sstream>
+ uint8_t val;
-ssize_t BlueKitchen::write_blocking(char *buf, ssize_t size)
-{
- ssize_t i = 0;
- BaseType_t taskwoken = 0;
- uint8_t val = Bt::Message::EvtSent;
+ read_buff = buf; // point at the Bt stack read buffer
+ read_len = nbytes;
-#ifdef DO_DEBUG_HCI_COMS
- std::stringstream ss;
- for (int i = 0; i < size; ++i) {
- ss << " 0x" << std::hex << (int)buf[i];
- }
- LOG_DEBUG("--> [%d]>%s<", size, ss.str().c_str());
-#endif
- if (BluetoothCommon::write_blocking(buf, size) == size) {
- xQueueSendFromISR(qHandle, &val, &taskwoken);
- portEND_SWITCHING_ISR(taskwoken);
+ if (BluetoothCommon::read(buf, nbytes) == Success) {
+ val = Bt::Message::EvtReceiving;
+ xQueueSend(qHandle, &val, portMAX_DELAY);
+ return BTdev::Success;
}
else {
- val = Bt::Message::EvtSentError;
- xQueueSendFromISR(qHandle, &val, &taskwoken);
+ val = Bt::Message::EvtReceivingError;
+ xQueueSend(qHandle, &val, portMAX_DELAY);
+ return BTdev::ErrorBSP;
}
-
- return i;
}
-extern "C"
+BTdev::Error BlueKitchen::write(const uint8_t *buf, size_t size)
{
- void LPUART2_IRQHandler(void)
- {
- uint32_t isrReg = LPUART_GetStatusFlags(BSP_BLUETOOTH_UART_BASE);
- static char characterReceived = 0;
- BaseType_t taskwoken = 0;
- uint8_t val = Bt::Message::EvtReceived;
- bsp::BlueKitchen *bt = bsp::BlueKitchen::getInstance();
+ uint8_t val;
+
+ logHciStack("BlueKitchen sends %d bytes", size);
- if (isrReg & kLPUART_RxDataRegFullFlag) {
- characterReceived = LPUART_ReadByte(BSP_BLUETOOTH_UART_BASE);
- if (bt->in.push(characterReceived)) {
- val = Bt::Message::EvtRecUnwanted;
- xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
- }
- if (bt->to_read != 0 && (bt->in.len >= bt->to_read)) {
- bt->to_read = 0;
- assert(bt->qHandle);
- val = Bt::Message::EvtReceived;
- xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
- portEND_SWITCHING_ISR(taskwoken);
- }
- if (bt->in.threshold_guard()) {
- bt->set_rts(false);
- }
- }
- if (isrReg & kLPUART_RxOverrunFlag) {
- val = Bt::Message::EvtUartError;
- xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
- }
- LPUART_ClearStatusFlags(BSP_BLUETOOTH_UART_BASE, isrReg);
+ if (BluetoothCommon::write(buf, size) == Success) {
+ val = Bt::Message::EvtSending;
+ xQueueSend(qHandle, &val, portMAX_DELAY);
+ return BTdev::Success;
+ }
+ else {
+ val = Bt::Message::EvtSendingError;
+ xQueueSend(qHandle, &val, portMAX_DELAY);
+ return BTdev::ErrorBSP;
}
-};
+}
+
+void BlueKitchen::set_flowcontrol(int on)
+{}
M module-bsp/board/rt1051/bluetooth/BluetoothCommon.cpp => module-bsp/board/rt1051/bluetooth/BluetoothCommon.cpp +182 -109
@@ 1,53 1,34 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "BluetoothWorker.hpp"
#include "bsp/bluetooth/Bluetooth.hpp"
#include "log/log.hpp"
#include "FreeRTOS.h"
-#include "fsl_lpuart.h"
#include "board.h"
+#include "fsl_lpuart_edma.h"
+#include <bsp/BoardDefinitions.hpp>
-using namespace bsp;
-
-// TODO it's plain copy same as in cellular - this is kind of wrong
-uint32_t UartGetPeripheralClock();
+#if DEBUG_BLUETOOTH_HCI_COMS == 1
+#define logHciComs(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define logHciComs(...)
+#endif
-void BTdev::_circ::sem_take()
-{
- if (!(SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)) {
- xSemaphoreTake(sem, 0);
- }
- else {
- BaseType_t px;
- xSemaphoreTakeFromISR(sem, &px);
- }
-}
+#if DEBUG_BLUETOOTH_HCI_BYTES == 1
+#include <sstream>
+#define logHciBytes(...) LOG_DEBUG(__VA_ARGS__)
+#else
+#define logHciBytes(...)
+#endif
-void BTdev::_circ::sem_give()
-{
- if (!(SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)) {
- xSemaphoreGive(sem);
- }
- else {
- BaseType_t px;
- xSemaphoreGiveFromISR(sem, &px);
- }
-}
+using namespace bsp;
-BTdev::_circ::_circ(unsigned int size, int threshold) : head(0), tail(0), threshold(threshold), size(size), len(0)
-{
- buff = new char[size];
- sem = xSemaphoreCreateBinary();
-}
+lpuart_edma_handle_t BluetoothCommon::uartDmaHandle = {};
-BTdev::_circ::~_circ()
-{
- vSemaphoreDelete(sem);
- delete[] buff;
-}
+uint32_t UartGetPeripheralClock();
-BluetoothCommon::BluetoothCommon(unsigned int in_size, unsigned int out_size, int threshold)
- : BTdev(in_size, out_size, threshold)
+BluetoothCommon::BluetoothCommon()
{
configure_uart_io();
configure_lpuart();
@@ 61,17 42,14 @@ BluetoothCommon::~BluetoothCommon()
void BluetoothCommon::open()
{
LOG_INFO("Bluetooth HW open!");
- set_reset(true);
set_irq(true);
+ set_reset(true);
is_open = true;
- set_rts(true);
}
void BluetoothCommon::close()
{
- LOG_INFO("close!");
- // TODO destroy semaphore
- set_rts(false);
+ LOG_INFO("Bluetooth HW close!");
set_irq(false);
is_open = false;
set_reset(false);
@@ 82,59 60,103 @@ void BluetoothCommon::sleep_ms(ssize_t ms)
ulTaskNotifyTake(pdTRUE, ms);
}
-BTdev::Error BluetoothCommon::flush()
+BTdev::Error BluetoothCommon::read(uint8_t *buf, size_t nbytes)
{
- // LOG_INFO("flush [%d] %s", out.len, out.tail<out.head?"reverse":"normal");
- Error err = Success;
- int len = out.len;
- char *from = new char[out.len];
- for (int i = 0; i < len; ++i) {
- out.pop(from + i);
- }
- int to_write = len;
- char *fromp = from;
- while (to_write) {
- while (1) {
- if (read_cts() == 0) {
- break;
- }
- else {
- sleep_ms(1);
- }
- }
- LPUART_WriteBlocking(BSP_BLUETOOTH_UART_BASE, reinterpret_cast<uint8_t *>(fromp), 1);
- --to_write;
- ++fromp;
+ auto ret = ErrorUndefined;
+
+ // start RXfer if there is a byte incoming and no pending RXfer
+ lpuart_transfer_t receiveXfer;
+ receiveXfer.data = buf;
+ receiveXfer.dataSize = nbytes;
+
+ // rx config
+ SCB_CleanInvalidateDCache();
+ LPUART_EnableRx(BSP_BLUETOOTH_UART_BASE, true);
+
+ auto status = LPUART_ReceiveEDMA(BSP_BLUETOOTH_UART_BASE, &uartDmaHandle, &receiveXfer);
+ switch (status) {
+ case kStatus_Success:
+ ret = Success;
+ break;
+ case kStatus_LPUART_RxBusy:
+ ret = ErrorBSP;
+ LOG_WARN("BT UART RX DMA already busy");
+ break;
+ case kStatus_InvalidArgument:
+ LOG_WARN("BT UART RX DMA invalid argument");
+ ret = ErrorBSP;
+ break;
}
- delete[] from;
- return err;
+ return ret;
}
-ssize_t BluetoothCommon::write(char *buf, size_t nbytes)
+BTdev::Error BluetoothCommon::write(const uint8_t *buf, size_t size)
{
- // LOG_INFO( "write -> [%.*s]",nbytes, buf);
- ssize_t i = 0;
- // if CTS set -> ignore return 0, can use threshold_guard here too
- for (i = 0; i < nbytes; ++i) {
- if (out.push(*(buf + i)) != 0) {
- LOG_ERROR("Cant push!");
- break;
- }
+ logHciBytes("BT DMA to write --> [%d]>%s<",
+ size,
+ [&]() -> std::string {
+ std::stringstream ss;
+ for (int i = 0; i < size; ++i) {
+ ss << " 0x" << std::hex << (int)buf[i];
+ }
+ return ss.str();
+ }()
+ .c_str());
+ auto ret = ErrorUndefined;
+
+ lpuart_transfer_t sendXfer;
+ sendXfer.data = const_cast<uint8_t *>(buf);
+ sendXfer.dataSize = size;
+
+ uartDmaHandle.userData = xTaskGetCurrentTaskHandle();
+
+ // tx config
+ SCB_CleanInvalidateDCache();
+ LPUART_EnableTx(BSP_BLUETOOTH_UART_BASE, true);
+
+ auto sent = LPUART_SendEDMA(BSP_BLUETOOTH_UART_BASE, &uartDmaHandle, &sendXfer);
+ switch (sent) {
+ case kStatus_Success:
+ // orchestrate a DMA Tx
+ logHciComs("DMA Tx started (%d)", size);
+ ret = Success;
+ break;
+ case kStatus_LPUART_TxBusy:
+ // could've checked beforehand
+ LOG_WARN("Previous DMA Tx is still pending");
+ ret = ErrorBSP;
+ break;
+ case kStatus_InvalidArgument:
+ LPUART_EnableTx(BSP_BLUETOOTH_UART_BASE, false);
+ LOG_ERROR("DMA Tx invalid arg");
+ ret = ErrorBSP;
+ break;
}
- return i;
+ return ret;
}
-ssize_t BluetoothCommon::write_blocking(char *buf, ssize_t len)
+ssize_t BluetoothCommon::write_blocking(const uint8_t *buf, ssize_t nbytes)
{
- int yet_to_write = len;
- if (len > out.size) {
- LOG_WARN("WRITE: %d vs %d", len, out.size);
+ ssize_t ret = -1;
+
+ auto wrote = write(const_cast<uint8_t *>(buf), nbytes);
+
+ if (wrote == nbytes) { // success orchestrating a transfer
+ constexpr auto writeBlockingTimeout = pdMS_TO_TICKS(100);
+ auto ulNotificationValue = ulTaskNotifyTake(pdFALSE, writeBlockingTimeout);
+ if (ulNotificationValue != 0) { // success completing a transfer
+ logHciComs("DMA Tx wrote");
+ ret = nbytes;
+ }
+ else {
+ LOG_ERROR("DMA Tx timeout");
+ ret = -1;
+ }
}
- while (yet_to_write != 0) {
- yet_to_write -= write(buf + len - yet_to_write, yet_to_write < out.size ? yet_to_write : (out.size - 1));
- flush();
+ else {
+ LOG_WARN("DMA Tx not wrote (%d/%d)", wrote, nbytes);
}
- return len;
+ return ret;
}
BTdev::Error BluetoothCommon::set_baudrate(uint32_t bd)
@@ 149,25 171,18 @@ BTdev::Error BluetoothCommon::set_baudrate(uint32_t bd)
return ret;
}
-// set flow on -> true, set flow off -> false
-BTdev::Error BluetoothCommon::set_rts(bool on)
-{
- GPIO_PinWrite(BSP_BLUETOOTH_UART_RTS_PORT, BSP_BLUETOOTH_UART_RTS_PIN, on ? 0U : 1U);
- return Success;
-}
-
BTdev::Error BluetoothCommon::set_reset(bool on)
{
+ if (on) {
+ GPIO_PinWrite(BSP_BLUETOOTH_SHUTDOWN_PORT, BSP_BLUETOOTH_SHUTDOWN_PIN, 0);
+ // docs: "nSHUTD must be low for a minimum of 5 ms."
+ sleep_ms(5 + 2);
+ }
LOG_INFO("reset %s", on ? "on" : "off");
GPIO_PinWrite(BSP_BLUETOOTH_SHUTDOWN_PORT, BSP_BLUETOOTH_SHUTDOWN_PIN, on ? 1U : 0U);
return Success;
}
-int BluetoothCommon::read_cts()
-{
- return GPIO_PinRead(BSP_BLUETOOTH_UART_CTS_PORT, BSP_BLUETOOTH_UART_CTS_PIN);
-}
-
uint32_t UartGetPeripheralClock()
{
const int UART_PERIPHERAL_PLL_DIVIDER = 6;
@@ 198,9 213,7 @@ void BluetoothCommon::configure_uart_io()
GPIO_PinInit(BSP_BLUETOOTH_UART_CTS_PORT, BSP_BLUETOOTH_UART_CTS_PIN, &gpio_init_structure);
gpio_init_structure.direction = kGPIO_DigitalOutput;
gpio_init_structure.interruptMode = kGPIO_NoIntmode;
- GPIO_PinInit(BSP_BLUETOOTH_OSC_EN_PORT, BSP_BLUETOOTH_OSC_EN_PIN, &gpio_init_structure);
- GPIO_PinWrite(BSP_BLUETOOTH_OSC_EN_PORT, BSP_BLUETOOTH_OSC_EN_PIN, 1U);
- gpio_init_structure.direction = kGPIO_DigitalOutput;
+ gpio_init_structure.outputLogic = 0;
GPIO_PinInit(BSP_BLUETOOTH_SHUTDOWN_PORT, BSP_BLUETOOTH_SHUTDOWN_PIN, &gpio_init_structure);
}
@@ 216,16 229,63 @@ void BluetoothCommon::configure_lpuart()
bt_c.rxIdleConfig = kLPUART_IdleCharacter1;
bt_c.enableTx = false;
bt_c.enableRx = false;
+ bt_c.enableTxCTS = true;
+ bt_c.txCtsConfig = kLPUART_CtsSampleAtStart; // to be able to stop TX mid-transfer
+ bt_c.enableRxRTS = true; // == BSP_BLUETOOTH_UART_BASE->MODIR |= LPUART_MODIR_RXRTSE_MASK;
if (LPUART_Init(BSP_BLUETOOTH_UART_BASE, &bt_c, UartGetPeripheralClock()) != kStatus_Success) {
LOG_ERROR("BT: UART config error Could not initialize the uart!");
return;
}
+ BSP_BLUETOOTH_UART_BASE->MODIR |= LPUART_MODIR_TXRTSPOL_MASK; // apparently docs are not clear here. HIGH during TX
LPUART_ClearStatusFlags(BSP_BLUETOOTH_UART_BASE, 0xFFFFFFFF);
NVIC_ClearPendingIRQ(LPUART2_IRQn);
NVIC_SetPriority(LPUART2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(LPUART2_IRQn);
+
+ dmamux = drivers::DriverDMAMux::Create(static_cast<drivers::DMAMuxInstances>(BoardDefinitions::BLUETOOTH_DMAMUX),
+ drivers::DriverDMAMuxParams{});
+ dma = drivers::DriverDMA::Create(static_cast<drivers::DMAInstances>(BoardDefinitions::BLUETOOTH_DMA),
+ drivers::DriverDMAParams{});
+
+ uartTxDmaHandle = dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions::BLUETOOTH_TX_DMA_CHANNEL));
+ uartRxDmaHandle = dma->CreateHandle(static_cast<uint32_t>(BoardDefinitions::BLUETOOTH_RX_DMA_CHANNEL));
+
+ dmamux->Enable(static_cast<uint32_t>(BoardDefinitions::BLUETOOTH_TX_DMA_CHANNEL), kDmaRequestMuxLPUART2Tx);
+ dmamux->Enable(static_cast<uint32_t>(BoardDefinitions::BLUETOOTH_RX_DMA_CHANNEL), kDmaRequestMuxLPUART2Rx);
+
+ LPUART_TransferCreateHandleEDMA(BSP_BLUETOOTH_UART_BASE,
+ &uartDmaHandle,
+ uartDmaCallback,
+ nullptr,
+ reinterpret_cast<edma_handle_t *>(uartTxDmaHandle->GetHandle()),
+ reinterpret_cast<edma_handle_t *>(uartRxDmaHandle->GetHandle()));
+}
+
+void BluetoothCommon::uartDmaCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData)
+{
+ BaseType_t taskwoken = 0;
+ uint8_t val;
+ bsp::BlueKitchen *bt = bsp::BlueKitchen::getInstance();
+
+ switch (status) {
+ case kStatus_LPUART_TxIdle: {
+ logHciComs("DMA irq: TX done");
+ LPUART_EnableTx(BSP_BLUETOOTH_UART_BASE, false);
+ val = Bt::Message::EvtSent;
+ xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
+ portEND_SWITCHING_ISR(taskwoken);
+ break;
+ }
+ case kStatus_LPUART_RxIdle:
+ logHciComs("DMA irq: RX done");
+ LPUART_EnableRx(BSP_BLUETOOTH_UART_BASE, false);
+ val = Bt::Message::EvtReceived;
+ xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
+ portEND_SWITCHING_ISR(taskwoken);
+ break;
+ }
}
void BluetoothCommon::configure_cts_irq()
@@ 236,7 296,6 @@ void BluetoothCommon::configure_cts_irq()
EnableIRQ(GPIO1_Combined_16_31_IRQn);
NVIC_SetPriority(GPIO1_Combined_16_31_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);
}
-
void BluetoothCommon::set_irq(bool enable)
{
// printf("%s\n", __FUNCTION__);
@@ 244,16 303,30 @@ void BluetoothCommon::set_irq(bool enable)
LPUART_EnableTx(BSP_BLUETOOTH_UART_BASE, false);
LPUART_ClearStatusFlags(BSP_BLUETOOTH_UART_BASE, 0xFFFFFFFF);
if (enable) {
- LPUART_EnableInterrupts(BSP_BLUETOOTH_UART_BASE,
- kLPUART_RxDataRegFullInterruptEnable | kLPUART_IdleLineInterruptEnable);
+ LPUART_EnableInterrupts(BSP_BLUETOOTH_UART_BASE, kLPUART_RxOverrunInterruptEnable);
}
else {
- LPUART_DisableInterrupts(BSP_BLUETOOTH_UART_BASE,
- kLPUART_RxDataRegFullInterruptEnable | kLPUART_IdleLineInterruptEnable);
+ LPUART_DisableInterrupts(BSP_BLUETOOTH_UART_BASE, kLPUART_RxOverrunInterruptEnable);
+ }
+}
+
+extern "C"
+{
+ void LPUART2_IRQHandler(void)
+ {
+ uint32_t isrReg = LPUART_GetStatusFlags(BSP_BLUETOOTH_UART_BASE);
+ BaseType_t taskwoken = 0;
+ uint8_t val = Bt::Message::EvtReceived;
+ bsp::BlueKitchen *bt = bsp::BlueKitchen::getInstance();
+
+ if (isrReg & kLPUART_RxDataRegFullFlag) {
+ LOG_WARN("LPUART IRQ RX full");
+ }
+ if (isrReg & kLPUART_RxOverrunFlag) {
+ LOG_WARN("LPUART IRQ RX overrun");
+ val = Bt::Message::EvtUartError;
+ xQueueSendFromISR(bt->qHandle, &val, &taskwoken);
+ }
+ LPUART_ClearStatusFlags(BSP_BLUETOOTH_UART_BASE, isrReg);
}
- // LPUART_EnableInterrupts(BSP_BLUETOOTH_UART_BASE,
- // kLPUART_RxDataRegFullInterruptEnable|kLPUART_TxDataRegEmptyInterruptEnable|kLPUART_TransmissionCompleteInterruptEnable|kLPUART_RxOverrunInterruptEnable
- // );
- LPUART_EnableRx(BSP_BLUETOOTH_UART_BASE, true);
- LPUART_EnableTx(BSP_BLUETOOTH_UART_BASE, true);
}
M module-bsp/board/rt1051/common/board.h => module-bsp/board/rt1051/common/board.h +2 -6
@@ 238,13 238,9 @@
#define BSP_BLUETOOTH_UART_CTS_PIN 16
#define BSP_BLUETOOTH_UART_CTS_PAD GPIO_AD_B1_00
-#define BSP_BLUETOOTH_OSC_EN_PIN 0
-#define BSP_BLUETOOTH_OSC_EN_PORT GPIO2
-#define BSP_BLUETOOTH_OSC_EN_PAD GPIO_B0_00
-
-#define BSP_BLUETOOTH_SHUTDOWN_PIN 1
#define BSP_BLUETOOTH_SHUTDOWN_PORT GPIO2
-#define BSP_BLUETOOTH_SHUTDOWN_PAD GPIO_B0_01
+#define BSP_BLUETOOTH_SHUTDOWN_PIN 1
+#define BSP_BLUETOOTH_SHUTDOWN_PAD GPIO_B0_01 // active low
/**
* BOARD KEYBOARD DEFINITIONS
M module-bsp/board/rt1051/common/pin_mux.c => module-bsp/board/rt1051/common/pin_mux.c +2 -3
@@ 1359,9 1359,8 @@ void PINMUX_InitBluetoothPins(void)
IOMUXC_SetPinConfig(PINMUX_BLUETOOTH_UART_CTS,
- PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_STRENGTH_LVL_1 | PAD_CONFIG_SPEED_SLOW_50MHz |
- PAD_CONFIG_PULL_KEEPER_ENABLED | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_DOWN_100kOhm |
- PAD_CONFIG_HYSTERESIS_DISABLED);
+ PAD_CONFIG_SLEW_RATE_SLOW | PAD_CONFIG_DRIVER_DISABLED | PAD_CONFIG_SPEED_SLOW_50MHz |
+ PAD_CONFIG_PULL_KEEPER_ENABLED | PAD_CONFIG_SELECT_PULL | PAD_CONFIG_PULL_DOWN_100kOhm);
IOMUXC_SetPinConfig(PINMUX_BLUETOOTH_UART_RTS,
M module-bsp/board/rt1051/common/pin_mux.h => module-bsp/board/rt1051/common/pin_mux.h +2 -2
@@ 159,8 159,8 @@ extern "C"
*/
#define PINMUX_BLUETOOTH_UART_TX IOMUXC_GPIO_AD_B1_02_LPUART2_TX
#define PINMUX_BLUETOOTH_UART_RX IOMUXC_GPIO_AD_B1_03_LPUART2_RX
-#define PINMUX_BLUETOOTH_UART_CTS IOMUXC_GPIO_AD_B1_00_GPIO1_IO16
-#define PINMUX_BLUETOOTH_UART_RTS IOMUXC_GPIO_AD_B1_01_GPIO1_IO17
+#define PINMUX_BLUETOOTH_UART_CTS IOMUXC_GPIO_AD_B1_00_LPUART2_CTS_B
+#define PINMUX_BLUETOOTH_UART_RTS IOMUXC_GPIO_AD_B1_01_LPUART2_RTS_B
#define PINMUX_BLUETOOTH_OSC_EN IOMUXC_GPIO_B0_00_GPIO2_IO00
#define PINMUX_BLUETOOTH_NSHUTDOWN IOMUXC_GPIO_B0_01_GPIO2_IO01
M module-bsp/board/rt1051/drivers/RT1051DriverDMA.cpp => module-bsp/board/rt1051/drivers/RT1051DriverDMA.cpp +5 -2
@@ 40,8 40,11 @@ namespace drivers
RT1051DriverDMA::~RT1051DriverDMA()
{
- EDMA_Deinit(base);
- LOG_DEBUG("Deinit: DMA_0");
+ switch (instance) {
+ case DMAInstances::DMA_0:
+ EDMA_Deinit(base);
+ LOG_DEBUG("Deinit: DMA_0");
+ }
}
std::unique_ptr<DriverDMAHandle> RT1051DriverDMA::CreateHandle(const uint32_t channel,
M module-bsp/bsp/BoardDefinitions.hpp => module-bsp/bsp/BoardDefinitions.hpp +11 -6
@@ 20,8 20,8 @@ enum class BoardDefinitions
AUDIOCODEC_I2C = static_cast<int>(drivers::I2CInstances ::I2C2),
AUDIOCODEC_DMAMUX = static_cast<int>(drivers::DMAMuxInstances ::DMAMUX0),
AUDIOCODEC_DMA = static_cast<int>(drivers::DMAInstances ::DMA_0),
- AUDIOCODEC_TX_DMA_CHANNEL = 6,
- AUDIOCODEC_RX_DMA_CHANNEL = 7,
+ AUDIOCODEC_TX_DMA_CHANNEL = 5,
+ AUDIOCODEC_RX_DMA_CHANNEL = 6,
AUDIOCODEC_IRQ = 31, // GPIO_B1_15 requires pull-up 10kΩ
AUDIOCODEC_IRQ_GPIO = static_cast<int>(drivers::GPIOInstances ::GPIO_2),
@@ 30,8 30,8 @@ enum class BoardDefinitions
CELLULAR_AUDIO_DMAMUX = AUDIOCODEC_DMAMUX,
CELLULAR_AUDIO_DMA = AUDIOCODEC_DMA,
- CELLULAR_AUDIO_TX_DMA_CHANNEL = 3,
- CELLULAR_AUDIO_RX_DMA_CHANNEL = 4,
+ CELLULAR_AUDIO_TX_DMA_CHANNEL = 2,
+ CELLULAR_AUDIO_RX_DMA_CHANNEL = 3,
KEYBOARD_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
KEYBOARD_I2C = AUDIOCODEC_I2C,
@@ 54,7 54,7 @@ enum class BoardDefinitions
CELLULAR_DMA = static_cast<int >(drivers::DMAInstances ::DMA_0),
CELLULAR_DMAMUX = static_cast<int >(drivers::DMAMuxInstances ::DMAMUX0),
- CELLULAR_TX_DMA_CHANNEL = 5,
+ CELLULAR_TX_DMA_CHANNEL = 4,
CELLULAR_GPIO_1 = static_cast<int >(drivers::GPIOInstances ::GPIO_1),
CELLULAR_GPIO_2 = static_cast<int >(drivers::GPIOInstances ::GPIO_2),
CELLULAR_GPIO_3 = static_cast<int >(drivers::GPIOInstances ::GPIO_3),
@@ 84,6 84,11 @@ enum class BoardDefinitions
EINK_BUSY_PIN=17,
EINK_PLL = static_cast<int >(drivers::PLLInstances::PLL2_PFD2),
+ BLUETOOTH_DMA = static_cast<int >(drivers::DMAInstances ::DMA_0),
+ BLUETOOTH_DMAMUX = static_cast<int >(drivers::DMAMuxInstances ::DMAMUX0),
+ BLUETOOTH_TX_DMA_CHANNEL = 7,
+ BLUETOOTH_RX_DMA_CHANNEL = 8,
+
EMMC_PLL = static_cast<int >(drivers::PLLInstances::PLL2_PFD2),
AUDIO_PLL = static_cast<int >(drivers::PLLInstances::PLL4_Audio),
@@ 107,7 112,7 @@ enum class BoardDefinitions
KEYPAD_BACKLIGHT_DRIVER_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
KEYPAD_BACKLIGHT_DRIVER_I2C = AUDIOCODEC_I2C,
KEYPAD_BACKLIGHT_DRIVER_GPIO = static_cast<int>(drivers::GPIOInstances::GPIO_1),
- KEYPAD_BACKLIGHT_DRIVER_NRST = 3, // GPIO_AD_B0_03 Active LOW. External pulldown resistor of 10Ω between NRST and GND.
+ KEYPAD_BACKLIGHT_DRIVER_NRST = 3, // GPIO_AD_B0_03 Active LOW. External pulldown resistor of 10kΩ between NRST and GND.
EINK_FRONTLIGHT_PWM_INSTANCE = 2, // GPIO_AD_B0_01 = FLEXPWM2_PWM3_B
EINK_FRONTLIGHT_PWM_MODULE = 3,
M module-bsp/bsp/bluetooth/Bluetooth.cpp => module-bsp/bsp/bluetooth/Bluetooth.cpp +1 -1
@@ 3,7 3,7 @@
namespace bsp {
- BTdev::BTdev(unsigned int in_size, unsigned int out_size, int threshold) : flog(nullptr), in(in_size, threshold), out(out_size, threshold)
+ BTdev::BTdev() : flog(nullptr)
{
is_open = false;
}
M module-bsp/bsp/bluetooth/Bluetooth.hpp => module-bsp/bsp/bluetooth/Bluetooth.hpp +29 -75
@@ 7,6 7,12 @@
#include <thread.hpp>
#include <board.h>
+#if defined(TARGET_RT1051)
+#include "board/rt1051/common/fsl_drivers/fsl_lpuart_edma.h"
+#include "drivers/dmamux/DriverDMAMux.hpp"
+#include "drivers/dma/DriverDMA.hpp"
+#endif
+
/// c++ low level driver overlay
namespace bsp {
@@ 34,116 40,64 @@ namespace bsp {
static const unsigned int default_timeout_ms = 1000;
static const unsigned int default_buff_size = 1024;
static const unsigned int default_baudrate = 115200;
- struct _circ {
- SemaphoreHandle_t sem = 0;
- void sem_take();
- void sem_give();
- char* buff;
- volatile unsigned int head, tail, threshold;
- const unsigned int size;
- volatile unsigned int len;
- _circ(unsigned int size, int threshold=0);
- ~_circ();
- inline int push(char val) {
- sem_take();
- int ret=0;
- if(len<size) {
- buff[tail]=val;
- ++tail;
- ++len;
- if(tail==size) tail=0;
- } else {
- ret=-1;
- }
- sem_give();
- return ret;
- }
- inline int pop(char* val) {
- sem_take();
- int ret=0;
- if(val!=nullptr) {
- if(len) {
- *val = buff[head];
- --len;
- ++head;
- if(head == size) head=0;
- } else {
- ret =-1;
- }
- } else {
- ret=-2;
- }
- sem_give();
- return ret;
- }
- // reached => 1, safe => 0
- inline bool threshold_guard() {
- return len+threshold > size;
- }
- inline void flush() {
- sem_take();
- len=0;
- head=0;
- tail=0;
- sem_give();
- }
- } in, out;
- BTdev(unsigned int in_size=default_buff_size, unsigned int out_size=default_buff_size, int threshold=0);
+ BTdev();
virtual ~BTdev();
- // generall
+ // general
virtual void open() = 0; // enable device -> irq enable
virtual void close() = 0; // disable device -> irq disable
- virtual ssize_t read(void *buf, size_t nbytes) = 0; // read from internal in buffor
+ virtual BTdev::Error read(uint8_t *buf, size_t nbytes) = 0;
void log(LogLvl lvl,const char* val, ...);
- // uart specyfic
+ // uart specific
};
- // Common stuff for Bluetopia and profiles +clean listing for overrrides
class BluetoothCommon : public BTdev
{
public:
static const ssize_t baudrate =115200;
static const ssize_t off_threshold =16;
static const ssize_t on_threshold =32;
- public:
- BluetoothCommon(unsigned int in_size=default_buff_size, unsigned int out_size=default_buff_size, int threshold=0);
+
+ BluetoothCommon();
virtual ~BluetoothCommon();
- // uart specyfic Common part
+ // uart specific Common part
virtual void open() override;
virtual void close() override;
- virtual ssize_t write(char *buf, size_t nbytes);
- virtual ssize_t write_blocking(char *buf, ssize_t len);
- Error flush();
+ virtual BTdev::Error read(uint8_t *buf, size_t nbytes) override;
+ virtual BTdev::Error write(const uint8_t *buf, size_t nbytes);
+ virtual ssize_t write_blocking(const uint8_t *buf, ssize_t nbytes);
Error set_baudrate(uint32_t bd);
- Error set_rts(bool on);
Error set_reset(bool on);
- int read_cts();
void sleep_ms(ssize_t ms);
void set_irq(bool enable);
- // Part to override
- virtual ssize_t read(void *buf, size_t nbytes) override = 0;
private:
void configure_uart_io();
void configure_lpuart();
void configure_cts_irq();
+#if defined(TARGET_RT1051)
+ std::shared_ptr<drivers::DriverDMAMux> dmamux;
+ std::shared_ptr<drivers::DriverDMA> dma;
+ std::unique_ptr<drivers::DriverDMAHandle> uartRxDmaHandle;
+ std::unique_ptr<drivers::DriverDMAHandle> uartTxDmaHandle;
+ static AT_NONCACHEABLE_SECTION_INIT(lpuart_edma_handle_t uartDmaHandle);
+ static void uartDmaCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData);
+#endif
};
/// definitions needed by BT stack
class BlueKitchen : public BluetoothCommon {
public:
- BlueKitchen(unsigned int in_size=default_buff_size, unsigned int out_size=default_buff_size);
+ BlueKitchen();
virtual ~BlueKitchen();
static BlueKitchen *getInstance();
- virtual ssize_t read(void *buf, size_t nbytes) override;
- virtual ssize_t write_blocking(char *buf, ssize_t len) override;
- volatile uint32_t to_read_req = 0;
- volatile uint32_t to_read =0;
- volatile char* read_buff;
+ virtual BTdev::Error read(uint8_t *buf, size_t nbytes) override;
+ virtual BTdev::Error write(const uint8_t *buf, size_t size) override;
+ uint32_t read_len = 0;
+ uint8_t* read_buff;
void set_flowcontrol(int on);
M module-utils/log/debug.hpp => module-utils/log/debug.hpp +2 -0
@@ 6,6 6,8 @@
#define DEBUG_APPLICATION_MANAGEMENT 0 /// show verbose logs in ApplicationManager
#define DEBUG_SCOPED_TIMINGS 0 /// show timings in measured functions
#define _RT1051_UART_DEBUG 0 /// show full modem uart communication
+#define DEBUG_BLUETOOTH_HCI_COMS 0 /// show communication with BT module - transactions
+#define DEBUG_BLUETOOTH_HCI_BYTES 0 /// show communication with BT module - all the HCI bytes
#define DEBUG_MODEM_OUTPUT_RESPONSE 0 /// show full modem output
#define DEBUG_SERVICE_MESSAGES 0 /// show messages prior to handling in service
#define DEBUG_DB_MODEL_DATA 0 /// show messages prior to handling in service