M enabled_unittests => enabled_unittests +5 -0
@@ 473,4 473,9 @@ TESTS_LIST["catch2-audio-volume-scaler"]="
Scenario: Scale volume levels between system and bluetooth;
"
#---------
+TESTS_LIST["catch2-unittest_CellularResult"]="
+ CellularResult;
+"
+#---------
+
M module-bsp/board/linux/cellular/linux_cellular.cpp => module-bsp/board/linux/cellular/linux_cellular.cpp +21 -24
@@ 12,10 12,8 @@
#include <errno.h>
#include <fcntl.h>
#include <map>
-#include <sys/stat.h>
#include <sys/types.h>
#include <ticks.hpp>
-#include <time.h>
#include <unistd.h>
#define _LINUX_UART_DEBUG 0
@@ 68,8 66,6 @@ namespace bsp
LOG_FATAL("Failed to create epoll file descriptor");
}
- struct epoll_event event;
-
event.events = EPOLLIN;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event)) {
@@ 91,23 87,23 @@ namespace bsp
}
}
- void LinuxCellular::PowerUp()
+ void LinuxCellular::powerUp()
{}
- void LinuxCellular::PowerDown()
+ void LinuxCellular::powerDown()
{}
- void LinuxCellular::Restart()
+ void LinuxCellular::restart()
{}
- ssize_t LinuxCellular::Read(void *buf, size_t nbytes)
+ ssize_t LinuxCellular::read(void *buf, size_t nbytes, std::chrono::milliseconds timeoutMs)
{
cpp_freertos::LockGuard lock(serOutMutex);
int ret;
for (;;) {
- ret = read(fd, buf, nbytes);
+ ret = ::read(fd, buf, nbytes);
if (ret != -1 || errno != EINTR)
break;
}
@@ 124,7 120,7 @@ namespace bsp
return ret;
}
- ssize_t LinuxCellular::Write(void *buf, size_t nbytes)
+ ssize_t LinuxCellular::write(void *buf, size_t nbytes)
{
cpp_freertos::LockGuard lock(serOutMutex);
#if _LINUX_UART_DEBUG
@@ 136,30 132,31 @@ namespace bsp
#endif
int ret;
for (;;) {
- ret = write(fd, buf, nbytes);
+ ret = ::write(fd, buf, nbytes);
if (ret != -1 || errno != EINTR)
break;
}
return ret;
}
- void LinuxCellular::InformModemHostAsleep(void)
+ void LinuxCellular::informModemHostAsleep(void)
{}
- void LinuxCellular::InformModemHostWakeup(void)
+ void LinuxCellular::informModemHostWakeup(void)
{}
- void LinuxCellular::EnterSleep()
+ void LinuxCellular::enterSleep()
{}
- void LinuxCellular::ExitSleep()
+ void LinuxCellular::exitSleep()
{}
- uint32_t LinuxCellular::Wait(uint32_t timeout)
+ uint32_t LinuxCellular::wait(std::chrono::milliseconds timeoutMs)
{
+ auto timeoutTicks = pdMS_TO_TICKS(timeoutMs.count());
uint32_t currentTime = cpp_freertos::Ticks::GetTicks();
- uint32_t timeoutNeeded = timeout == UINT32_MAX ? UINT32_MAX : currentTime + timeout;
+ uint32_t timeoutNeeded = currentTime + timeoutTicks;
uint32_t timeElapsed = currentTime;
for (;;) {
@@ 182,7 179,7 @@ namespace bsp
}
}
- void LinuxCellular::SetSpeed(uint32_t portSpeed)
+ void LinuxCellular::setSpeed(uint32_t portSpeed)
{
struct termios t;
memset(&t, 0, sizeof(t));
@@ 201,10 198,10 @@ namespace bsp
ioctl(fd, TIOCMBIS, &status);
}
- void LinuxCellular::SelectAntenna(bsp::cellular::antenna antenna)
+ void LinuxCellular::selectAntenna(bsp::cellular::antenna antenna)
{}
- bsp::cellular::antenna LinuxCellular::GetAntenna()
+ bsp::cellular::antenna LinuxCellular::getAntenna()
{
return bsp::cellular::antenna::lowBand;
}
@@ 248,7 245,7 @@ namespace bsp
namespace sim
{
- auto trayIRQ_handler() -> BaseType_t
+ auto trayIRQHandler() -> BaseType_t
{
return BaseType_t();
}
@@ 258,15 255,15 @@ namespace bsp
return Store::GSM::Tray::IN;
}
- void hotswap_trigger()
+ void hotSwapTrigger()
{}
- void sim_sel()
+ void simSelect()
{}
} // namespace sim
namespace ringIndicator
{
- auto riIRQ_handler() -> BaseType_t
+ auto riIRQHandler() -> BaseType_t
{
return BaseType_t();
}
M module-bsp/board/linux/cellular/linux_cellular.hpp => module-bsp/board/linux/cellular/linux_cellular.hpp +15 -18
@@ 14,7 14,6 @@
namespace bsp
{
-
class LinuxCellular : public Cellular
{
private:
@@ 24,40 23,40 @@ namespace bsp
LinuxCellular(const char *term, uint32_t portSpeed);
~LinuxCellular();
- void PowerUp() override final;
+ void powerUp() override final;
- void PowerDown() override final;
+ void powerDown() override final;
- void Restart() override final;
+ void restart() override final;
- uint32_t Wait(uint32_t timeout) override final;
+ uint32_t wait(std::chrono::milliseconds timeoutMs) override final;
- ssize_t Read(void *buf, size_t nbytes) override final;
+ ssize_t read(void *buf, size_t nbytes, std::chrono::milliseconds timeoutMs) override final;
- ssize_t Write(void *buf, size_t nbytes) override final;
+ ssize_t write(void *buf, size_t nbytes) override final;
- void InformModemHostAsleep() override final;
+ void informModemHostAsleep() override final;
- void InformModemHostWakeup() override final;
+ void informModemHostWakeup() override final;
- void EnterSleep() override final;
+ void enterSleep() override final;
- void ExitSleep() override final;
+ void exitSleep() override final;
- void SetSpeed(uint32_t portSpeed);
+ void setSpeed(uint32_t portSpeed) override final;
- void SetSendingAllowed(bool state) override final
+ void setSendingAllowed(bool state) override final
{
pv_SendingAllowed = state;
}
- bool GetSendingAllowed() override final
+ bool getSendingAllowed() const noexcept override final
{
return pv_SendingAllowed;
}
- void SelectAntenna(bsp::cellular::antenna antenna) override final;
+ void selectAntenna(bsp::cellular::antenna antenna) override final;
- bsp::cellular::antenna GetAntenna() override final;
+ bsp::cellular::antenna getAntenna() override final;
private:
static constexpr speed_t baud_bits[] = {0,
@@ 74,8 73,6 @@ namespace bsp
B3000000,
B4000000};
- static const uint32_t portBaudRate = 115200;
-
static const uint32_t MAX_EVENTS = 1;
int fd = -1;
M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.cpp +176 -194
@@ 2,93 2,81 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "rt1051_cellular.hpp"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "stream_buffer.h"
-
-#include "dma_config.h"
#include "fsl_cache.h"
+
#include <common_data/EventStore.hpp>
+#include <task.h>
#include <ticks.hpp>
#include <algorithm>
-#if _RT1051_UART_DEBUG == 1
+static bsp::cellular::CellularDMAResultStruct RXfer;
+
+#if DEBUG_CELLULAR_UART == 1
#define logUARTdebug(...) LOG_DEBUG(__VA_ARGS__)
#else
#define logUARTdebug(...)
#endif
-namespace bsp::cellular
-{
- void notifyReceivedNew()
- {
- BaseType_t hp = pdFALSE;
- if (bsp::RT1051Cellular::untilReceivedNewHandle != nullptr) {
- vTaskNotifyGiveFromISR(bsp::RT1051Cellular::untilReceivedNewHandle, &hp);
- }
- portEND_SWITCHING_ISR(hp);
- }
-}; // namespace bsp::cellular
-
extern "C"
{
void LPUART1_IRQHandler(void)
{
- uint32_t isrReg = LPUART_GetStatusFlags(CELLULAR_UART_BASE);
+ std::uint32_t isrReg = LPUART_GetStatusFlags(CELLULAR_UART_BASE);
- if (bsp::RT1051Cellular::uartRxStreamBuffer != NULL) {
- auto RxDmaStatus = LPUART_TransferGetReceiveCountEDMA(
- CELLULAR_UART_BASE,
- &bsp::RT1051Cellular::uartDmaHandle,
- reinterpret_cast<uint32_t *>(&bsp::RT1051Cellular::RXdmaReceivedCount));
+ if (bsp::RT1051Cellular::uartRxBuffer != NULL) {
+ std::uint32_t count = 0;
- if (isrReg & bsp::RT1051Cellular::startIRQMask) {
+ auto RxDmaStatus =
+ LPUART_TransferGetReceiveCountEDMA(CELLULAR_UART_BASE, &bsp::RT1051Cellular::uartDmaHandle, &count);
+
+ RXfer.dataSize = count;
+
+ if ((isrReg & bsp::RT1051Cellular::edgeIRQMask) != 0u ||
+ (isrReg & bsp::RT1051Cellular::dataRegFullIRQMask) != 0) {
+ // logUARTdebug("[RX] edgeIRQ");
if (RxDmaStatus == kStatus_NoTransferInProgress) {
- LPUART_DisableInterrupts(CELLULAR_UART_BASE, bsp::RT1051Cellular::startIRQMaskEnable);
- bsp::RT1051Cellular::RXdmaReceivedCount = -1;
- if (not bsp::RT1051Cellular::StartReceive(bsp::RT1051Cellular::GetFreeStreamBufferSize())) {
+ // logUARTdebug("[RX] No transfer in progress");
+ LPUART_DisableInterrupts(CELLULAR_UART_BASE, bsp::RT1051Cellular::edgeIRQMaskEnable);
+
+ if (not bsp::RT1051Cellular::startReceive(bsp::RT1051Cellular::getMaxBufferDataSize())) {
bsp::RT1051Cellular::RestartReceivingManually = true;
- bsp::RT1051Cellular::FinishReceive();
}
- logUARTdebug("[RX] on Incoming data");
}
}
- if (isrReg & bsp::RT1051Cellular::finishIRQMask) {
+
+ if ((isrReg & bsp::RT1051Cellular::idleIRQMask) != 0u &&
+ (isrReg & bsp::RT1051Cellular::dataRegFullIRQMask) == 0u) {
+ // logUARTdebug("[RX] idleIRQ");
if (RxDmaStatus != kStatus_NoTransferInProgress) {
+ // logUARTdebug("[RX] Transfer in progress. Stopping engine");
LPUART_TransferAbortReceiveEDMA(CELLULAR_UART_BASE, &bsp::RT1051Cellular::uartDmaHandle);
- logUARTdebug("[RX idle] stopped engine");
- }
- logUARTdebug("[RX idle], received %d bytes", bsp::RT1051Cellular::RXdmaReceivedCount);
- // the main exit path on transmission done
- if (bsp::RT1051Cellular::RXdmaReceivedCount >= 0) {
- if (bsp::RT1051Cellular::RXdmaReceivedCount > 0) {
- bsp::RT1051Cellular::MoveRxDMAtoStreamBuf(bsp::RT1051Cellular::RXdmaReceivedCount);
- bsp::RT1051Cellular::RXdmaReceivedCount = -1;
- }
- if (not bsp::RT1051Cellular::RestartReceivingManually) {
- bsp::RT1051Cellular::FinishReceive();
+
+ if (count > 0) {
+ bsp::RT1051Cellular::sendRxDmaResult(bsp::cellular::CellularResultCode::ReceivedAndIdle);
}
}
}
- LPUART_ClearStatusFlags(CELLULAR_UART_BASE, isrReg);
+ if (isrReg & kLPUART_RxOverrunFlag) {
+ LOG_WARN("IRQ RX overrun");
+ }
}
+
+ LPUART_ClearStatusFlags(CELLULAR_UART_BASE, isrReg);
}
};
namespace bsp
{
- uint8_t RT1051Cellular::RXdmaBuffer[RXdmaBufferSize] = {0};
- ssize_t RT1051Cellular::RXdmaReceivedCount = -1;
- size_t RT1051Cellular::RXdmaMaxReceivedCount = -1;
- bool RT1051Cellular::RestartReceivingManually = false;
+ std::size_t RT1051Cellular::RXdmaMaxReceivedCount = 0;
+ bool RT1051Cellular::RestartReceivingManually = false;
using namespace drivers;
- lpuart_edma_handle_t RT1051Cellular::uartDmaHandle = {};
- TaskHandle_t RT1051Cellular::untilReceivedNewHandle = nullptr;
- StreamBufferHandle_t RT1051Cellular::uartRxStreamBuffer = nullptr;
+ lpuart_edma_handle_t RT1051Cellular::uartDmaHandle = {};
+ TaskHandle_t RT1051Cellular::untilReceivedNewHandle = nullptr;
+ MessageBufferHandle_t RT1051Cellular::uartRxBuffer = nullptr;
RT1051Cellular::RT1051Cellular()
{
@@ 98,9 86,9 @@ namespace bsp
GPIO_PinRead(GPIO2, BSP_CELLULAR_SIM_TRAY_INSERTED_PIN) == 0 ? Store::GSM::Tray::IN : Store::GSM::Tray::OUT;
DMAInit();
- uartRxStreamBuffer = xStreamBufferCreate(rxStreamBufferLength, rxStreamBufferNotifyWatermark);
- if (uartRxStreamBuffer == NULL) {
- LOG_ERROR("Could not create the RX stream buffer!");
+ uartRxBuffer = xMessageBufferCreate(rxMessageBufferLength);
+ if (uartRxBuffer == nullptr) {
+ LOG_ERROR("Could not create the RX message buffer!");
return;
}
@@ 116,7 104,7 @@ namespace bsp
s_cellularConfig.parityMode = kLPUART_ParityDisabled;
s_cellularConfig.isMsb = false;
s_cellularConfig.rxIdleType = kLPUART_IdleTypeStartBit;
-#if _RT1051_UART_DEBUG
+#if DEBUG_CELLULAR_UART
s_cellularConfig.rxIdleConfig = kLPUART_IdleCharacter4; // Logs take time
#else
s_cellularConfig.rxIdleConfig = kLPUART_IdleCharacter1;
@@ 133,36 121,36 @@ namespace bsp
return;
}
- static_assert(rxStreamBufferLength >= 6, "Minimum buffer size (i.e. sufficient to enable flow control)");
- static_assert(rxStreamBufferLength >= 1024, "To be able to fit entire response");
-
- // CANNOT disable FIFO, dma *needs* it :o
- // CELLULAR_UART_BASE->FIFO &= ~LPUART_FIFO_RXFE_MASK;
+ static_assert(rxMessageBufferLength >= RXfer.getMaxSize() + messageBufferOverheadSize,
+ "Minimum buffer size to hold one full DMA rxfer");
LPUART_ClearStatusFlags(CELLULAR_UART_BASE, 0xFFFFFFFF);
NVIC_ClearPendingIRQ(LPUART1_IRQn);
NVIC_SetPriority(LPUART1_IRQn, configLIBRARY_LOWEST_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(LPUART1_IRQn);
+ enableRx();
isInitialized = true;
}
- void RT1051Cellular::SetSpeed(uint32_t portSpeed)
+ void RT1051Cellular::setSpeed(uint32_t portSpeed)
{
LOG_DEBUG("[RT1051] Setting %" PRIu32 " baudrate", portSpeed);
+
+ disableRx();
LPUART_SetBaudRate(CELLULAR_UART_BASE, portSpeed, GetPerphSourceClock(PerphClock_LPUART));
+ enableRx();
}
RT1051Cellular::~RT1051Cellular()
{
-
- if (uartRxStreamBuffer) {
- vStreamBufferDelete(uartRxStreamBuffer);
- uartRxStreamBuffer = nullptr;
+ if (uartRxBuffer) {
+ vMessageBufferDelete(uartRxBuffer);
+ uartRxBuffer = nullptr;
}
- DisableRx();
- DisableTx();
+ disableRx();
+ disableTx();
NVIC_DisableIRQ(LPUART1_IRQn);
LPUART_DisableInterrupts(CELLULAR_UART_BASE,
@@ 179,83 167,67 @@ namespace bsp
untilReceivedNewHandle = nullptr;
}
- void RT1051Cellular::PowerUp()
+ void RT1051Cellular::powerUp()
{
- const TickType_t POWER_UP_DELAY_MS = 500;
+ constexpr TickType_t POWER_UP_DELAY_MS = 500;
- DisableRx();
+ disableRx();
- ExitSleep();
+ exitSleep();
TickType_t tick = xTaskGetTickCount();
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_POWER_PIN), 1);
vTaskDelayUntil(&tick, POWER_UP_DELAY_MS);
- // BSP_CellularSetPowerState(CellularPowerStateTurningOn);
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_POWER_PIN), 0);
- EnableRx();
+ enableRx();
}
- void RT1051Cellular::PowerDown()
+ void RT1051Cellular::powerDown()
{
- const uint16_t POWER_DOWN_DELAY_MS = 700;
+ constexpr std::uint16_t POWER_DOWN_DELAY_MS = 700;
- ExitSleep();
+ exitSleep();
TickType_t tick = xTaskGetTickCount();
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_POWER_PIN), 1);
vTaskDelayUntil(&tick, POWER_DOWN_DELAY_MS);
- // BSP_CellularSetPowerState(CellularPowerStateTurningOff);
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_POWER_PIN), 0);
- // vTaskDelay(pdMS_TO_TICKS(POWER_DOWN_IN_PROGRESS_DELAY_MS));
-
- /* while (s_cellularPowerState != CellularPowerStatePoweredDown)
- {
- vTaskDelay(pdMS_TO_TICKS(200));
- }*/
- DisableRx();
+ disableRx();
}
- void RT1051Cellular::Restart()
+ void RT1051Cellular::restart()
{
- const uint16_t RESET_DELAY_MS = 460;
+ constexpr std::uint16_t RESET_DELAY_MS = 460;
- ExitSleep();
+ exitSleep();
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_RESET_PIN), 1);
vTaskDelay(pdMS_TO_TICKS(RESET_DELAY_MS));
gpio_2->WritePin(static_cast<uint32_t>(BoardDefinitions::CELLULAR_GPIO_2_RESET_PIN), 0);
}
- ssize_t RT1051Cellular::Write(void *buf, size_t nbytes)
+ ssize_t RT1051Cellular::write(void *buf, size_t nbytes)
{
+ static uint8_t txBuffer[128];
+ memcpy(txBuffer, buf, nbytes);
+
lpuart_transfer_t sendXfer;
-#if _RT1051_UART_DEBUG
- LOG_PRINTF("[TX: %d]", nbytes);
- uint8_t *ptr = (uint8_t *)buf;
- LOG_PRINTF("\n{");
- for (size_t i = 0; i < nbytes; i++)
- LOG_PRINTF("%02X ", (uint8_t)*ptr++);
- LOG_PRINTF("}\n<");
- ptr = (uint8_t *)buf;
- for (size_t i = 0; i < nbytes; i++)
- LOG_PRINTF("%c", (uint8_t)*ptr++);
- LOG_PRINTF(">");
- LOG_PRINTF("\n");
-#endif
- sendXfer.data = static_cast<uint8_t *>(buf);
+ logData("TX", static_cast<uint8_t *>(buf), nbytes);
+ sendXfer.data = txBuffer;
sendXfer.dataSize = nbytes;
- ExitSleep();
+ exitSleep();
uartDmaHandle.userData = xTaskGetCurrentTaskHandle();
SCB_CleanInvalidateDCache();
- EnableTx();
+ enableTx();
+
if (LPUART_SendEDMA(CELLULAR_UART_BASE, &uartDmaHandle, &sendXfer) != kStatus_Success) {
LOG_ERROR("Cellular: TX Failed!");
- DisableTx();
+ disableTx();
return -1;
}
@@ 264,58 236,63 @@ namespace bsp
if (ulNotificationValue == 0) {
LOG_ERROR("Cellular Uart error: TX Transmission timeout");
- DisableTx();
+ disableTx();
return -1;
}
- DisableTx();
+ disableTx();
return nbytes;
}
- bool RT1051Cellular::MoveRxDMAtoStreamBuf(size_t nbytes)
+ bool RT1051Cellular::sendRxDmaResult(bsp::cellular::CellularResultCode reason)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- assert(nbytes > 0);
-
- if (nbytes > GetFreeStreamBufferSize()) {
- LOG_ERROR("Cannot dump DMA buffer. Data is lost (%d>%d)", nbytes, GetFreeStreamBufferSize());
+ if (RXfer.getSize() > getMaxBufferDataSize()) {
+ LOG_ERROR("Cannot dump DMA buffer (%d>%d)", RXfer.getSize(), getMaxBufferDataSize());
+ RestartReceivingManually = true;
return false;
}
-#if _RT1051_UART_DEBUG
- auto ret =
-#endif
- xStreamBufferSendFromISR(uartRxStreamBuffer, (void *)&RXdmaBuffer, nbytes, &xHigherPriorityTaskWoken);
- logUARTdebug("[RX] moved %d bytes to streambuf", ret);
+ RXfer.resultCode = reason;
+ logUARTdebug("[RX reason] %s", c_str(reason));
+
+ xMessageBufferSendFromISR(uartRxBuffer, (void *)&RXfer, RXfer.getSize(), &xHigherPriorityTaskWoken);
+
+ // logUARTdebug("Added to queue");
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
return true;
}
- size_t RT1051Cellular::GetFreeStreamBufferSize()
+ size_t RT1051Cellular::getMaxBufferDataSize()
{
- return xStreamBufferSpacesAvailable(bsp::RT1051Cellular::uartRxStreamBuffer);
+ const auto messageOverhead = messageBufferOverheadSize + bsp::cellular::CellularDMAResultStruct::getEmptySize();
+
+ if (const auto bytesFree = xMessageBufferSpaceAvailable(uartRxBuffer); bytesFree > messageOverhead) {
+ return bytesFree - messageOverhead;
+ }
+
+ return 0;
}
- bool RT1051Cellular::StartReceive(size_t nbytes)
+ bool RT1051Cellular::startReceive(size_t nbytes)
{
- if (!(GetFreeStreamBufferSize() > 0)) {
- logUARTdebug("Not starting RX DMA, stream buffer is full. Be aware");
+ if (getMaxBufferDataSize() <= 0) {
+ logUARTdebug("Not starting RX DMA, message buffer is full. Be aware");
return false;
}
-
else {
// sanitize input
RXdmaMaxReceivedCount = std::min(nbytes, static_cast<size_t>(RXdmaBufferSize));
- logUARTdebug("Starting DMA RX, max %d bytes", RXdmaMaxReceivedCount);
+ // logUARTdebug("Starting DMA RX, max %d bytes", RXdmaMaxReceivedCount);
}
- assert(RXdmaMaxReceivedCount <= RXdmaBufferSize);
+ RXfer.dataSize = 0;
// start RXfer if there is a byte incoming and no pending RXfer
lpuart_transfer_t receiveXfer;
- receiveXfer.data = RXdmaBuffer;
+ receiveXfer.data = RXfer.data;
receiveXfer.dataSize = RXdmaMaxReceivedCount;
// rx config
@@ 333,50 310,43 @@ namespace bsp
return true;
}
- void RT1051Cellular::FinishReceive()
+ ssize_t RT1051Cellular::read(void *buffer,
+ size_t nbytes,
+ std::chrono::milliseconds timeoutMs = std::chrono::milliseconds{0})
{
- logUARTdebug("[RX] finish");
- bsp::cellular::notifyReceivedNew();
- }
+ logUARTdebug("[RX] Read");
+ exitSleep();
- ssize_t RT1051Cellular::Read(void *buf, size_t nbytes)
- {
- ExitSleep();
- ssize_t ret = xStreamBufferReceive(uartRxStreamBuffer, buf, nbytes, 0);
-#if _RT1051_UART_DEBUG
- if (ret > 0) {
- LOG_PRINTF("[RX: %d]", ret);
- uint8_t *ptr = (uint8_t *)buf;
- LOG_PRINTF("\n{");
- for (ssize_t i = 0; i < ret; i++)
- LOG_PRINTF("%02X ", (uint8_t)*ptr++);
- LOG_PRINTF("}\n<");
- ptr = (uint8_t *)buf;
- for (ssize_t i = 0; i < ret; i++)
- LOG_PRINTF("%c", (uint8_t)*ptr++);
- LOG_PRINTF(">");
- }
- else {
- LOG_PRINTF("[RX] GOT NOTHING (requested %d)", nbytes);
+ auto timeoutTicks = pdMS_TO_TICKS(timeoutMs.count());
+ if (timeoutTicks > portMAX_DELAY) {
+ timeoutTicks = portMAX_DELAY;
}
- LOG_PRINTF("\n");
-#endif
- if (RestartReceivingManually) {
- logUARTdebug("[RX] resume on Paused");
- // need to start manually, as RegBuf might be already full, therefore no Active Edge Interrupt
- if (StartReceive(GetFreeStreamBufferSize())) {
- RestartReceivingManually = false;
- }
- else {
- // do not lose information as whether manual start needs to be initiated and schedule next poke on Read
- LOG_WARN("Modem is waiting to send data. Stream buffer likely too small");
- FinishReceive();
+
+ size_t ret = xMessageBufferReceive(uartRxBuffer, buffer, nbytes, timeoutTicks);
+
+ if (ret > bsp::cellular::CellularDMAResultStruct::getEmptySize()) {
+ logData("RX",
+ static_cast<uint8_t *>(buffer) + bsp::cellular::CellularResultStructEmptySize,
+ ret - bsp::cellular::CellularResultStructEmptySize);
+
+ if (RestartReceivingManually) {
+ logUARTdebug("[RX] resume on Paused");
+ // need to start manually, as RegBuf might be already full, therefore no Active Edge Interrupt
+ if (startReceive(getMaxBufferDataSize())) {
+ RestartReceivingManually = false;
+ }
+ else {
+ // do not lose information as whether manual start needs to be initiated and schedule next poke on
+ // Read
+ LOG_WARN("Modem is waiting to send data. Stream buffer likely too small");
+ }
}
}
+
return ret;
}
- uint32_t RT1051Cellular::Wait(uint32_t timeout)
+ uint32_t RT1051Cellular::wait(std::chrono::milliseconds timeoutMs)
{
logUARTdebug("[WAIT]");
if (untilReceivedNewHandle != nullptr) {
@@ 385,54 355,55 @@ namespace bsp
}
// no need to wait: buffer already contains something
- if (xStreamBufferBytesAvailable(uartRxStreamBuffer)) {
+ if (!xMessageBufferIsEmpty(uartRxBuffer)) {
return 1;
}
- EnableRx();
+ enableRx();
- // …start waiting for [timeout] until a new xfer from modem is received
+ // start waiting for [timeout] until a new xfer from modem is received
untilReceivedNewHandle = xTaskGetCurrentTaskHandle();
- auto ret = ulTaskNotifyTake(pdTRUE, timeout);
+ auto ret = ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(timeoutMs.count()));
untilReceivedNewHandle = nullptr;
return ret;
}
- void RT1051Cellular::InformModemHostAsleep()
+ void RT1051Cellular::informModemHostAsleep()
{
gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_APRDY_PIN),
!CELLULAR_BSP_AP_READY_PIN_ACTIVE_STATE);
}
- void RT1051Cellular::InformModemHostWakeup()
+ void RT1051Cellular::informModemHostWakeup()
{
gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_APRDY_PIN),
CELLULAR_BSP_AP_READY_PIN_ACTIVE_STATE);
}
- void RT1051Cellular::EnterSleep()
+ void RT1051Cellular::enterSleep()
{
if (!isInSleepMode) {
+ logUARTdebug("Enter sleep");
isInSleepMode = true;
gpio_3->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_3_DTR_PIN), 1);
gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_WAKEUP_PIN), 1);
// Host sleep information must be before UART disable
- InformModemHostAsleep();
-
+ informModemHostAsleep();
if (driverLPUART) {
driverLPUART->Disable();
}
}
}
- void RT1051Cellular::ExitSleep()
+ void RT1051Cellular::exitSleep()
{
// reset sleep timer countdown
lastCommunicationTimestamp = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
if (isInSleepMode) {
+ logUARTdebug("Exit sleep");
isInSleepMode = false;
if (driverLPUART) {
@@ 444,7 415,7 @@ namespace bsp
vTaskDelay(pdMS_TO_TICKS(15));
// Host wake up information must be after UART enable
- InformModemHostWakeup();
+ informModemHostWakeup();
}
}
@@ 561,10 532,6 @@ namespace bsp
void RT1051Cellular::DMAInit()
{
-
- // TODO:M.P add PLL support
- // pll = DriverInterface<DriverPLL>::Create(static_cast<PLLInstances >(BoardDefinitions
- // ::AUDIO_PLL),DriverPLLParams{});
dmamux =
DriverDMAMux::Create(static_cast<DMAMuxInstances>(BoardDefinitions::CELLULAR_DMAMUX), DriverDMAMuxParams{});
dma = DriverDMA::Create(static_cast<DMAInstances>(BoardDefinitions::CELLULAR_DMA), DriverDMAParams{});
@@ 598,39 565,42 @@ namespace bsp
switch (status) {
case kStatus_LPUART_TxIdle: {
- logUARTdebug("[TX done]");
+ logUARTdebug("[TX] Done");
// task handle to be released in userData
vTaskNotifyGiveFromISR((TaskHandle_t)userData, &higherPriorTaskWoken);
portEND_SWITCHING_ISR(higherPriorTaskWoken);
-
break;
}
case kStatus_LPUART_RxIdle:
logUARTdebug("[RX] Chunk done. Flow control must hold the gate from now on");
- if (MoveRxDMAtoStreamBuf(RXdmaMaxReceivedCount) and StartReceive(GetFreeStreamBufferSize())) {
+ RXfer.dataSize = RXdmaMaxReceivedCount;
+ if (sendRxDmaResult(cellular::CellularResultCode::ReceivedAndFull) and
+ startReceive(getMaxBufferDataSize())) {
// usual mode: append a chunk and wait for line idle to finish receive
}
else {
// the auxiliary exit path on stream buffer full
RestartReceivingManually = true;
- FinishReceive();
}
- RXdmaReceivedCount = -1;
+
+ break;
+ default:
+ logUARTdebug("uartDMACallback status %ld", status);
break;
}
}
- void RT1051Cellular::SetSendingAllowed(bool state)
+ void RT1051Cellular::setSendingAllowed(bool state)
{
pv_SendingAllowed = state;
}
- bool RT1051Cellular::GetSendingAllowed()
+ bool RT1051Cellular::getSendingAllowed() const noexcept
{
return pv_SendingAllowed;
}
- void RT1051Cellular::SelectAntenna(bsp::cellular::antenna antenna)
+ void RT1051Cellular::selectAntenna(bsp::cellular::antenna antenna)
{
if (antenna == bsp::cellular::antenna::lowBand) {
gpio_2->WritePin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_ANTSEL_PIN),
@@ 644,7 614,7 @@ namespace bsp
}
}
- bsp::cellular::antenna RT1051Cellular::GetAntenna()
+ bsp::cellular::antenna RT1051Cellular::getAntenna()
{
// make sure ANTSEL pin has Software Input On Field set
bool whichAntenna = gpio_2->ReadPin(magic_enum::enum_integer(BoardDefinitions::CELLULAR_GPIO_2_ANTSEL_PIN));
@@ 652,6 622,19 @@ namespace bsp
: bsp::cellular::antenna::highBand);
}
+ void RT1051Cellular::logData(const std::string &title, uint8_t *buffer, size_t nbytes)
+ {
+#if DEBUG_CELLULAR_UART == 1
+ LOG_PRINTF("[%s: %d]", title.c_str(), nbytes);
+ uint8_t *ptr = buffer;
+ LOG_PRINTF("\n{");
+ for (size_t i = 0; i < nbytes; i++) {
+ LOG_PRINTF("%02X ", ptr[i]);
+ }
+ LOG_PRINTF("}\n");
+#endif
+ }
+
namespace cellular
{
static xQueueHandle qhandle = nullptr;
@@ 716,7 699,7 @@ namespace bsp
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (qhandle != NULL) {
- uint8_t val = static_cast<uint8_t>(IRQsource::statusPin);
+ std::uint8_t val = static_cast<std::uint8_t>(IRQsource::statusPin);
xQueueSendFromISR(qhandle, &val, &xHigherPriorityTaskWoken);
}
return xHigherPriorityTaskWoken;
@@ 727,12 710,12 @@ namespace bsp
namespace sim
{
- auto trayIRQ_handler() -> BaseType_t
+ auto trayIRQHandler() -> BaseType_t
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (qhandle) {
- uint8_t val = static_cast<uint8_t>(IRQsource::trayPin);
+ std::uint8_t val = static_cast<std::uint8_t>(IRQsource::trayPin);
xQueueSendFromISR(qhandle, &val, &xHigherPriorityTaskWoken);
}
return xHigherPriorityTaskWoken;
@@ 745,14 728,14 @@ namespace bsp
return state;
}
- void hotswap_trigger()
+ void hotSwapTrigger()
{
GPIO_PinWrite(BSP_CELLULAR_SIM_CARD_PRESENCE_PORT, BSP_CELLULAR_SIM_CARD_PRESENCE_PIN, 1);
vTaskDelay(100); // sleep for 100 ms...
GPIO_PinWrite(BSP_CELLULAR_SIM_CARD_PRESENCE_PORT, BSP_CELLULAR_SIM_CARD_PRESENCE_PIN, 0);
}
- void sim_sel()
+ void simSelect()
{
if (Store::GSM::get()->selected == Store::GSM::SIM::SIM2) {
GPIO_PinWrite(BSP_CELLULAR_SIM_CARD_PRESENCE_PORT, BSP_CELLULAR_SIMSEL_PIN, 1);
@@ 765,16 748,15 @@ namespace bsp
namespace ringIndicator
{
- auto riIRQ_handler() -> BaseType_t
+ auto riIRQHandler() -> BaseType_t
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (qhandle != NULL) {
- uint8_t val = static_cast<uint8_t>(IRQsource::ringIndicatorPin);
+ std::uint8_t val = static_cast<std::uint8_t>(IRQsource::ringIndicatorPin);
xQueueSendFromISR(qhandle, &val, &xHigherPriorityTaskWoken);
}
return xHigherPriorityTaskWoken;
}
} // namespace ringIndicator
-
- } // namespace cellular
+ } // namespace cellular
} // namespace bsp
M module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp => module-bsp/board/rt1051/bsp/cellular/rt1051_cellular.hpp +49 -83
@@ 1,18 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#ifndef PUREPHONE_RT1501_CELLULAR_HPP
-#define PUREPHONE_RT1501_CELLULAR_HPP
+#pragma once
-#include "bsp/cellular/bsp_cellular.hpp"
+#include <FreeRTOS.h>
+#include <message_buffer.h>
+#include <timers.h>
-#include "FreeRTOS.h"
-#include "stream_buffer.h"
-#include "timers.h"
#include "board.h"
#include "fsl_lpuart.h"
#include "fsl_lpuart_edma.h"
+#include "bsp/cellular/bsp_cellular.hpp"
+#include "bsp/cellular/CellularResult.hpp"
#include "bsp/BoardDefinitions.hpp"
#include "drivers/pll/DriverPLL.hpp"
@@ 22,97 22,84 @@
namespace bsp
{
-
class RT1051Cellular : public Cellular
{
private:
bool pv_SendingAllowed = true;
+ void logData(const std::string &title, uint8_t *buffer, size_t nbytes);
+
public:
RT1051Cellular();
~RT1051Cellular();
- void PowerUp() override final;
-
- void PowerDown() override final;
-
- void Restart() override final;
-
- uint32_t Wait(uint32_t timeout) override final;
-
- ssize_t Read(void *buf, size_t nbytes) override final;
-
- ssize_t Write(void *buf, size_t nbytes) override final;
-
- void InformModemHostAsleep() override final;
-
- void InformModemHostWakeup() override final;
-
- void EnterSleep() override final;
-
- void ExitSleep() override final;
-
- void SetSpeed(uint32_t portSpeed) override final;
-
- void SetSendingAllowed(bool state) override final;
- bool GetSendingAllowed() override final;
-
- static StreamBufferHandle_t uartRxStreamBuffer;
- static TimerHandle_t rxTimeoutTimer;
-
- void SelectAntenna(bsp::cellular::antenna antenna) override final;
- bsp::cellular::antenna GetAntenna() override final;
-
+ void powerUp() override final;
+ void powerDown() override final;
+ void restart() override final;
+ uint32_t wait(std::chrono::milliseconds timeoutMs) override final;
+ ssize_t read(void *buffer, size_t nbytes, std::chrono::milliseconds timeoutMs) override final;
+ ssize_t write(void *buf, size_t nbytes) override final;
+ void informModemHostAsleep() override final;
+ void informModemHostWakeup() override final;
+ void enterSleep() override final;
+ void exitSleep() override final;
+ void setSpeed(uint32_t portSpeed) override final;
+ void setSendingAllowed(bool state) override final;
+ bool getSendingAllowed() const noexcept override final;
+ void selectAntenna(bsp::cellular::antenna antenna) override final;
+ bsp::cellular::antenna getAntenna() override final;
+
+ static MessageBufferHandle_t uartRxBuffer;
static lpuart_edma_handle_t uartDmaHandle;
+ static bool RestartReceivingManually;
+ static constexpr std::size_t RXdmaBufferSize = bsp::cellular::CellularResultStructMaxDataSize;
+ static std::size_t RXdmaMaxReceivedCount;
- static void FinishReceive();
+ static constexpr std::uint32_t edgeIRQMaskEnable = kLPUART_RxActiveEdgeInterruptEnable;
+ static constexpr std::uint32_t idleIRQMaskEnable = kLPUART_IdleLineInterruptEnable;
+ static constexpr std::uint32_t edgeIRQMask = kLPUART_RxActiveEdgeFlag;
+ static constexpr std::uint32_t idleIRQMask = kLPUART_IdleLineFlag;
+ static constexpr std::uint32_t dataRegFullIRQMask = kLPUART_RxDataRegFullFlag;
- static bool RestartReceivingManually;
+ static bool sendRxDmaResult(bsp::cellular::CellularResultCode reason);
+ static std::size_t getMaxBufferDataSize();
+ static bool startReceive(std::size_t nbytes);
+
+ static TaskHandle_t untilReceivedNewHandle;
private:
void MSPInit();
-
void MSPDeinit();
-
void DMAInit();
-
void DMADeinit();
- public:
- static constexpr uint32_t startIRQMaskEnable =
- kLPUART_RxActiveEdgeInterruptEnable | kLPUART_RxDataRegFullInterruptEnable;
- static constexpr uint32_t finishIRQMaskEnable = kLPUART_IdleLineInterruptEnable;
-
- static constexpr uint32_t startIRQMask = kLPUART_RxActiveEdgeFlag | kLPUART_RxDataRegFullFlag;
- static constexpr uint32_t finishIRQMask = kLPUART_IdleLineFlag;
+ static void uartDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData);
- private:
- static inline void EnableRx(uint32_t irqMask = startIRQMaskEnable | finishIRQMaskEnable)
+ static inline void enableRx(uint32_t irqMask = edgeIRQMaskEnable | idleIRQMaskEnable | dataRegFullIRQMask)
{
LPUART_ClearStatusFlags(CELLULAR_UART_BASE, 0xFFFFFFFF);
LPUART_EnableInterrupts(CELLULAR_UART_BASE, irqMask);
LPUART_EnableRx(CELLULAR_UART_BASE, true);
}
- static inline void DisableRx(uint32_t irqMask = startIRQMaskEnable | finishIRQMaskEnable)
+ static inline void disableRx(uint32_t irqMask = edgeIRQMaskEnable | idleIRQMaskEnable | dataRegFullIRQMask)
{
LPUART_DisableInterrupts(CELLULAR_UART_BASE, irqMask);
LPUART_ClearStatusFlags(CELLULAR_UART_BASE, irqMask);
LPUART_EnableRx(CELLULAR_UART_BASE, false);
}
- inline void EnableTx()
+ inline void enableTx()
{
LPUART_EnableTx(CELLULAR_UART_BASE, true);
}
- inline void DisableTx()
+ inline void disableTx()
{
LPUART_EnableTx(CELLULAR_UART_BASE, false);
}
- // M.P: It is important to destroy these drivers in specific order
std::shared_ptr<drivers::DriverPLL> pll;
std::shared_ptr<drivers::DriverGPIO> gpio_1;
std::shared_ptr<drivers::DriverGPIO> gpio_2;
@@ 122,32 109,11 @@ namespace bsp
std::unique_ptr<drivers::DriverDMAHandle> txDMAHandle;
std::unique_ptr<drivers::DriverDMAHandle> rxDMAHandle;
- static void uartDMACallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData);
-
- public:
- static TaskHandle_t blockedTaskHandle;
-
- private:
- // Constants
- const static uint32_t baudrate = 115200;
- const static uint32_t rxStreamBufferLength = 1024;
- const static uint32_t rxStreamBufferNotifyWatermark = 1;
- const static uint32_t CELLULAR_BSP_AP_READY_PIN_ACTIVE_STATE = 1;
- const static uint32_t CELLULAR_BSP_ANTSEL_PIN_A_STATE = 0;
- const static uint32_t CELLULAR_BSP_ANTSEL_PIN_B_STATE = 1;
-
- public:
- static constexpr size_t RXdmaBufferSize = 16;
- static uint8_t RXdmaBuffer[RXdmaBufferSize];
- static ssize_t RXdmaReceivedCount;
- static size_t RXdmaMaxReceivedCount;
- static bool MoveRxDMAtoStreamBuf(size_t nbytes);
- static size_t GetFreeStreamBufferSize();
- static bool StartReceive(size_t nbytes);
-
- static TaskHandle_t untilReceivedNewHandle;
+ static constexpr std::uint32_t baudrate = 115200;
+ static constexpr std::uint32_t rxMessageBufferLength = 1024;
+ static constexpr std::uint16_t messageBufferOverheadSize = 4;
+ static constexpr std::uint32_t CELLULAR_BSP_AP_READY_PIN_ACTIVE_STATE = 1;
+ static constexpr std::uint32_t CELLULAR_BSP_ANTSEL_PIN_A_STATE = 0;
+ static constexpr std::uint32_t CELLULAR_BSP_ANTSEL_PIN_B_STATE = 1;
};
-
} // namespace bsp
-
-#endif // PUREPHONE_RT1501_CELLULAR_HPP
M module-bsp/board/rt1051/common/irq/irq_gpio.cpp => module-bsp/board/rt1051/common/irq/irq_gpio.cpp +2 -2
@@ 122,7 122,7 @@ namespace bsp
}
if (irq_mask & (1 << BSP_CELLULAR_SIM_TRAY_INSERTED_PIN)) {
- xHigherPriorityTaskWoken |= bsp::cellular::sim::trayIRQ_handler();
+ xHigherPriorityTaskWoken |= bsp::cellular::sim::trayIRQHandler();
}
if (irq_mask & (1 << static_cast<uint32_t>(BoardDefinitions::LIGHT_SENSOR_IRQ))) {
@@ 154,7 154,7 @@ namespace bsp
}
if (irq_mask & (1 << BSP_CELLULAR_RI_PIN)) {
- bsp::cellular::ringIndicator::riIRQ_handler();
+ bsp::cellular::ringIndicator::riIRQHandler();
}
// Clear all IRQs
A module-bsp/bsp/cellular/CellularResult.hpp => module-bsp/bsp/cellular/CellularResult.hpp +157 -0
@@ 0,0 1,157 @@
+#pragma once
+
+#include <memory>
+#include <module-utils/Utils.hpp>
+#include <utility>
+
+namespace bsp::cellular
+{
+ enum class CellularResultCode : std::uint8_t
+ {
+ Uninitialized,
+ ReceivedAndIdle,
+ ReceivedAndFull,
+ ReceivedAfterFull,
+ ReceivingNotStarted,
+ ReceivedNoData,
+ TransmittingNotStarted,
+ CMUXFrameError,
+ };
+
+ constexpr size_t CellularResultStructMaxDataSize = 128;
+ constexpr size_t CellularResultStructEmptySize = 5;
+
+ struct __attribute__((__packed__)) CellularDMAResultStruct
+ {
+ CellularResultCode resultCode = CellularResultCode::ReceivedNoData;
+ size_t dataSize = 0;
+ std::uint8_t data[CellularResultStructMaxDataSize];
+
+ constexpr static size_t getEmptySize()
+ {
+ return sizeof(CellularDMAResultStruct) - CellularResultStructMaxDataSize;
+ }
+
+ constexpr static size_t getMaxSize()
+ {
+ return getEmptySize() + sizeof(data);
+ }
+
+ size_t getSize() const noexcept
+ {
+ return getEmptySize() + dataSize;
+ }
+ };
+
+ struct CellularResultStruct
+ {
+ CellularResultCode resultCode = CellularResultCode::Uninitialized;
+ std::vector<uint8_t> data;
+
+ [[nodiscard]] auto serialize() const -> std::unique_ptr<uint8_t>
+ {
+ auto serialized = std::unique_ptr<uint8_t>(new uint8_t[data.size() + sizeof(resultCode)]);
+ serialized.get()[0] = static_cast<unsigned char>(resultCode);
+
+ if (data.size() > 0) {
+ memcpy(serialized.get() + 1, data.data(), data.size());
+ }
+
+ return serialized;
+ }
+
+ auto deserialize(const uint8_t *serialized, const size_t size) -> void
+ {
+ if (size > 0) {
+ resultCode = static_cast<CellularResultCode>(*serialized);
+ if (size > 1) {
+ data = {serialized + 1, serialized + size};
+ }
+ }
+ }
+
+ [[nodiscard]] auto getSerializedSize() const noexcept -> size_t
+ {
+ return (sizeof(resultCode) + data.size());
+ }
+ };
+
+ class CellularResult
+ {
+ CellularResultStruct result;
+
+ public:
+ CellularResult() : result{CellularResultCode::Uninitialized, {}}
+ {}
+
+ explicit CellularResult(CellularDMAResultStruct &result)
+ : result{result.resultCode, {result.data, result.data + result.dataSize}}
+ {}
+
+ explicit CellularResult(CellularResultStruct result) : result{std::move(result)}
+ {}
+
+ explicit CellularResult(const uint8_t *serialized, const size_t size)
+ {
+ result.deserialize(serialized, size);
+ }
+
+ auto getResultCode() const noexcept -> CellularResultCode
+ {
+ return result.resultCode;
+ }
+
+ auto setResultCode(CellularResultCode code) -> void
+ {
+ result.resultCode = code;
+ }
+
+ auto getData() const noexcept -> std::vector<uint8_t> const &
+ {
+ return result.data;
+ }
+
+ auto setData(const std::vector<uint8_t> &data) -> void
+ {
+ result.data = data;
+ }
+
+ auto getDataAsString() const -> std::string
+ {
+ return std::string{result.data.begin(), result.data.end()};
+ }
+
+ auto getStruct() const -> CellularResultStruct const *
+ {
+ return &result;
+ }
+
+ auto getSerialized() const -> std::unique_ptr<uint8_t>
+ {
+ return result.serialize();
+ }
+
+ auto getSerializedSize() const noexcept -> size_t
+ {
+ return result.getSerializedSize();
+ }
+ };
+} // namespace bsp::cellular
+
+inline const char *c_str(bsp::cellular::CellularResultCode result)
+{
+ switch (result) {
+ case bsp::cellular::CellularResultCode::ReceivedAndIdle:
+ return "ReceivedAndIdle";
+ case bsp::cellular::CellularResultCode::ReceivedAndFull:
+ return "ReceivedAndFull";
+ case bsp::cellular::CellularResultCode::ReceivedAfterFull:
+ return "ReceivedAfterFull";
+ case bsp::cellular::CellularResultCode::ReceivingNotStarted:
+ return "ReceivingNotStarted";
+ case bsp::cellular::CellularResultCode::TransmittingNotStarted:
+ return "TransmittingNotStarted";
+ default:
+ return "Unknown";
+ }
+}
M module-bsp/bsp/cellular/bsp_cellular.cpp => module-bsp/bsp/cellular/bsp_cellular.cpp +11 -12
@@ 8,11 8,10 @@
#error "Unsupported target"
#endif
-
-namespace bsp{
-
- std::optional<std::unique_ptr<Cellular>> Cellular::Create(
- [[maybe_unused]] const char* term, uint32_t portSpeed) {
+namespace bsp
+{
+ std::optional<std::unique_ptr<Cellular>> Cellular::create([[maybe_unused]] const char *term, uint32_t portSpeed)
+ {
std::unique_ptr<Cellular> inst;
@@ 24,26 23,26 @@ namespace bsp{
#error "Unsupported target"
#endif
- if(inst->isInitialized){
+ if (inst->isInitialized) {
return inst;
}
return {};
}
- [[nodiscard]] auto Cellular::GetCellularDevice() const noexcept -> std::shared_ptr<devices::Device>
+ [[nodiscard]] auto Cellular::getCellularDevice() const noexcept -> std::shared_ptr<devices::Device>
{
return driverLPUART;
}
- [[nodiscard]] auto Cellular::GetLastCommunicationTimestamp() const noexcept -> TickType_t
+ [[nodiscard]] auto Cellular::getLastCommunicationTimestamp() const noexcept -> TickType_t
{
- return lastCommunicationTimestamp;
+ return lastCommunicationTimestamp;
}
- [[nodiscard]] auto Cellular::IsCellularInSleepMode() const noexcept -> bool
+ [[nodiscard]] auto Cellular::isCellularInSleepMode() const noexcept -> bool
{
- return isInSleepMode;
+ return isInSleepMode;
}
-}
+} // namespace bsp
M module-bsp/bsp/cellular/bsp_cellular.hpp => module-bsp/bsp/cellular/bsp_cellular.hpp +61 -51
@@ 5,61 5,65 @@
#include <stdint.h>
#include <stddef.h>
#include <memory>
+#include <chrono>
#include <FreeRTOS.h>
#include <FreeRTOS/include/queue.h>
#include "drivers/lpuart/DriverLPUART.hpp"
#include <common_data/EventStore.hpp>
-namespace bsp {
-namespace cellular
+namespace bsp
+{
+ namespace cellular
{
- enum class antenna{
- lowBand,
- highBand
- };
+ enum class antenna
+ {
+ lowBand,
+ highBand
+ };
}
- class Cellular {
- public:
-
- static std::optional<std::unique_ptr<Cellular>> Create(const char* term = "/dev/ttyUSB0", uint32_t portSpeed = 115200);
+ class Cellular
+ {
+ public:
+ static std::optional<std::unique_ptr<Cellular>> create(const char *term = "/dev/ttyUSB0",
+ uint32_t portSpeed = 115200);
- Cellular() {}
- virtual ~Cellular() {}
+ Cellular() = default;
+ virtual ~Cellular() = default;
+ virtual void powerUp() = 0;
- virtual void PowerUp() = 0;
+ virtual void powerDown() = 0;
- virtual void PowerDown() = 0;
+ virtual void restart() = 0;
- virtual void Restart() = 0;
+ virtual uint32_t wait(std::chrono::milliseconds timeoutMs) = 0;
- virtual uint32_t Wait(uint32_t timeout) = 0;
+ virtual ssize_t read(void *buf, size_t nbytes, std::chrono::milliseconds timeoutMs) = 0;
- virtual ssize_t Read(void *buf, size_t nbytes) = 0;
+ virtual ssize_t write(void *buf, size_t nbytes) = 0;
- virtual ssize_t Write(void *buf, size_t nbytes) = 0;
+ virtual void informModemHostAsleep() = 0;
- virtual void InformModemHostAsleep() = 0;
+ virtual void informModemHostWakeup() = 0;
- virtual void InformModemHostWakeup() = 0;
+ virtual void enterSleep() = 0;
- virtual void EnterSleep() = 0;
+ virtual void exitSleep() = 0;
- virtual void ExitSleep() = 0;
+ virtual void setSpeed(uint32_t portSpeed) = 0;
- virtual void SetSpeed(uint32_t portSpeed) = 0;
+ virtual void setSendingAllowed(bool state) = 0;
- virtual void SetSendingAllowed(bool state) = 0;
- virtual bool GetSendingAllowed() = 0;
+ virtual bool getSendingAllowed() const noexcept = 0;
- virtual void SelectAntenna(bsp::cellular::antenna antenna) = 0;
- virtual bsp::cellular::antenna GetAntenna() = 0;
+ virtual void selectAntenna(bsp::cellular::antenna antenna) = 0;
+ virtual bsp::cellular::antenna getAntenna() = 0;
- [[nodiscard]] auto GetCellularDevice() const noexcept -> std::shared_ptr<devices::Device>;
- [[nodiscard]] auto GetLastCommunicationTimestamp() const noexcept -> TickType_t;
- [[nodiscard]] auto IsCellularInSleepMode() const noexcept -> bool;
+ [[nodiscard]] auto getCellularDevice() const noexcept -> std::shared_ptr<devices::Device>;
+ [[nodiscard]] auto getLastCommunicationTimestamp() const noexcept -> TickType_t;
+ [[nodiscard]] auto isCellularInSleepMode() const noexcept -> bool;
- protected:
+ protected:
bool isInitialized = false;
bool isInSleepMode{false};
TickType_t lastCommunicationTimestamp;
@@ 67,36 71,42 @@ namespace cellular
std::shared_ptr<drivers::DriverLPUART> driverLPUART;
};
namespace cellular
+ {
+ enum IRQsource
{
- enum IRQsource{
statusPin,
trayPin,
- ringIndicatorPin,
+ ringIndicatorPin,
};
/// initialize SIM queue directed to EventWorker
int init(xQueueHandle qHandle);
- namespace USB {
- enum class PassthroughState {
+ namespace USB
+ {
+ enum class PassthroughState
+ {
ENABLED,
DISABLED,
};
- enum class BootPinState {
+ enum class BootPinState
+ {
FIRMWARE_UPGRADE,
NORMAL_BOOT,
};
- BootPinState getBootPin() ;
- PassthroughState getPassthrough() ;
+ BootPinState getBootPin();
+ PassthroughState getPassthrough();
void setBootPin(BootPinState bootPin);
void setPassthrough(PassthroughState pass);
- }
+ } // namespace USB
- namespace status{
- enum class value {
+ namespace status
+ {
+ enum class value
+ {
/// from the docs: When the module is turned on normally, the STATUS will present the low state.
ACTIVE,
INACTIVE,
@@ 104,27 114,27 @@ namespace cellular
/// returns true if status OK. Open drain pulled up; ground is OK.
bsp::cellular::status::value getStatus();
BaseType_t statusIRQhandler();
- }
+ } // namespace status
namespace sim
{
/// handler for SIM tray which is connected to phone, not GSM
- BaseType_t trayIRQ_handler();
+ BaseType_t trayIRQHandler();
Store::GSM::Tray getTray();
/// trigger swap pin on gsm so that it would reload sim card in tray
/// after that +QPIN urc should come
- void hotswap_trigger();
- void sim_sel();
+ void hotSwapTrigger();
+ void simSelect();
} // namespace sim
namespace ringIndicator
- {
- // handling incoming calls and sms - RI pin
- BaseType_t riIRQ_handler();
- } // namespace RingIndicator
+ {
+ // handling incoming calls and sms - RI pin
+ BaseType_t riIRQHandler();
+ } // namespace ringIndicator
- } // namespace cellular
-}; // namespace bsp
+ } // namespace cellular
+}; // namespace bsp
#endif // PUREPHONE_BSP_CELLULAR_HPP
M module-cellular/Modem/ATCommon.cpp => module-cellular/Modem/ATCommon.cpp +44 -22
@@ 8,7 8,6 @@
#include <log/log.hpp>
#include <string>
#include <ticks.hpp>
-#include <vector>
#include <inttypes.h> // for PRIu32
#include <Utils.hpp>
#include "ATStream.hpp"
@@ 27,22 26,21 @@ const std::string Channel::CMS_ERROR = "+CMS ERROR:";
// const std::string Channel::RING = "RING";
// const std::string Channel::NO_DIALTONE = "NO DIALTONE";
-void Channel::cmd_log(std::string cmd, const Result &result, uint32_t timeout)
+void Channel::cmdLog(std::string cmd, const Result &result, std::chrono::milliseconds timeout)
{
cmd.erase(std::remove(cmd.begin(), cmd.end(), '\r'), cmd.end());
cmd.erase(std::remove(cmd.begin(), cmd.end(), '\n'), cmd.end());
switch (result.code) {
case Result::Code::TIMEOUT: {
- LOG_INFO("[AT]: >%s<, timeout %" PRIu32
- " - please check the value with Quectel_EC25&EC21_AT_Commands_Manual_V1.3.pdf",
- cmd.c_str(),
- timeout);
+ LOG_ERROR("[AT]: >%s<, timeout %s - please check the value with Quectel_EC25&EC21_AT_Commands_Manual_V1.3.pdf",
+ cmd.c_str(),
+ utils::to_string(timeout.count()).c_str());
} break;
case Result::Code::ERROR: {
- LOG_INFO("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
+ LOG_ERROR("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
} break;
default:
- LOG_INFO("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
+ LOG_DEBUG("[AT]: >%s<, >%s<", cmd.c_str(), result.response.size() ? result.response.back().c_str() : "");
break;
}
#if DEBUG_MODEM_OUTPUT_RESPONSE
@@ 64,30 62,31 @@ std::string Channel::formatCommand(const std::string &cmd) const
Result Channel::cmd(const std::string &cmd, std::chrono::milliseconds timeout, size_t rxCount)
{
Result result;
- blockedTaskHandle = xTaskGetCurrentTaskHandle();
+ ATStream atStream(rxCount);
+
+ awaitingResponseFlag.set();
cmd_init();
std::string cmdFixed = formatCommand(cmd);
-
cmd_send(cmdFixed);
- uint32_t currentTime = cpp_freertos::Ticks::GetTicks();
- uint32_t timeoutNeeded = ((timeout.count() == UINT32_MAX) ? UINT32_MAX : currentTime + timeout.count());
- uint32_t timeElapsed = currentTime;
-
- ATStream atStream(rxCount);
+ auto startTime = std::chrono::steady_clock::now();
+ auto endTime = startTime + timeout;
while (true) {
- if (timeoutNeeded != UINT32_MAX && timeElapsed >= timeoutNeeded) {
+ if (std::chrono::steady_clock::now() > endTime) {
result.code = Result::Code::TIMEOUT;
break;
}
- auto taskUnlocked = ulTaskNotifyTake(pdTRUE, timeoutNeeded - timeElapsed);
- timeElapsed = cpp_freertos::Ticks::GetTicks();
+ if (size_t bytesRead = cmd_receive(receiveBuffer.get(), std::chrono::milliseconds{0}); bytesRead > 0) {
+ auto cellularResult = bsp::cellular::CellularResult{receiveBuffer.get(), bytesRead};
- if (taskUnlocked) {
- atStream.write(cmd_receive());
+ if (result = checkResult(cellularResult.getResultCode()); result.code != at::Result::Code::OK) {
+ break;
+ }
+
+ atStream.write(cellularResult.getDataAsString());
if (atStream.isReady()) {
result = atStream.getResult();
@@ 96,9 95,10 @@ Result Channel::cmd(const std::string &cmd, std::chrono::milliseconds timeout, s
}
}
- blockedTaskHandle = nullptr;
+ awaitingResponseFlag.clear();
+
cmd_post();
- cmd_log(cmdFixed, result, timeout.count());
+ cmdLog(cmdFixed, result, timeout);
return result;
}
@@ 115,3 115,25 @@ auto Channel::cmd(const at::AT &at) -> Result
auto time = utils::time::Scoped("Time to run at command" + cmd.getCmd());
return this->cmd(cmd);
}
+
+Result Channel::checkResult(bsp::cellular::CellularResultCode cellularResult)
+{
+ Result result;
+
+ switch (cellularResult) {
+ case bsp::cellular::CellularResultCode::ReceivingNotStarted:
+ result.code = Result::Code::RECEIVING_NOT_STARTED;
+ break;
+ case bsp::cellular::CellularResultCode::TransmittingNotStarted:
+ result.code = Result::Code::TRANSMISSION_NOT_STARTED;
+ break;
+ case bsp::cellular::CellularResultCode::CMUXFrameError:
+ result.code = Result::Code::CMUX_FRAME_ERROR;
+ break;
+ default:
+ result.code = Result::Code::OK;
+ break;
+ }
+
+ return result;
+}
M module-cellular/Modem/ATCommon.hpp => module-cellular/Modem/ATCommon.hpp +44 -9
@@ 7,6 7,7 @@
#include <at/ErrorCode.hpp>
#include <mutex.hpp>
#include <task.h>
+#include <message_buffer.h>
#include "BaseChannel.hpp"
namespace sys
@@ 16,7 17,37 @@ namespace sys
namespace at
{
- constexpr auto delimiter = "\r\n"; /// use std::strlen()
+ constexpr auto delimiter = "\r\n"; /// use std::strlen()
+ constexpr auto defaultBufferTimeoutMs = std::chrono::milliseconds{50};
+ inline constexpr size_t defaultReceiveBufferSize = 128; // receiveBuffer size used for single message processing
+ inline constexpr size_t defaultMessageBufferSize =
+ defaultReceiveBufferSize * 2; // MessageBuffer size for passing data between tasks
+
+ struct AwaitingResponseFlag
+ {
+ private:
+ cpp_freertos::MutexStandard mutex;
+ bool isWaiting = false;
+
+ public:
+ void set()
+ {
+ cpp_freertos::LockGuard lock{mutex};
+ isWaiting = true;
+ }
+
+ void clear()
+ {
+ cpp_freertos::LockGuard lock{mutex};
+ isWaiting = false;
+ }
+
+ bool state()
+ {
+ cpp_freertos::LockGuard lock{mutex};
+ return isWaiting;
+ }
+ };
class Channel : public BaseChannel
{
@@ 25,8 56,10 @@ namespace at
const std::array<char, 3> validTerm = {cmdSeparator, ',', '='};
[[nodiscard]] auto formatCommand(const std::string &cmd) const -> std::string;
+ MessageBufferHandle_t responseBuffer = nullptr;
+ std::unique_ptr<uint8_t> receiveBuffer;
+ AwaitingResponseFlag awaitingResponseFlag;
cpp_freertos::MutexStandard mutex;
- TaskHandle_t blockedTaskHandle = nullptr;
public:
static const std::string OK;
@@ 41,17 74,19 @@ namespace at
// const std::string Channel::RING = "RING";
// const std::string Channel::NO_DIALTONE = "NO DIALTONE";
+ explicit Channel(uint8_t *receiveBuffer)
+ : receiveBuffer{receiveBuffer} {
+
+ };
+
/// waits till ok or timeout
virtual auto cmd(const std::string &cmd,
std::chrono::milliseconds timeout = at::default_timeout,
size_t rxCount = 0) -> Result final;
virtual auto cmd(const at::AT &at) -> Result final;
virtual auto cmd(const at::Cmd &at) -> Result final;
- virtual void cmd_log(std::string cmd, const Result &result, uint32_t timeout) final;
- virtual auto ProcessNewData(sys::Service *service) -> int
- {
- return 0;
- }
- };
+ virtual void cmdLog(std::string cmd, const Result &result, std::chrono::milliseconds timeout) final;
-}; // namespace at
+ Result checkResult(bsp::cellular::CellularResultCode cellularResult);
+ };
+} // namespace at
M module-cellular/Modem/ATParser.cpp => module-cellular/Modem/ATParser.cpp +46 -38
@@ 10,27 10,27 @@
#include <utility>
#include <vector>
-ATParser::ATParser(bsp::Cellular *cellular) : cellular(cellular)
+ATParser::ATParser(bsp::Cellular *cellular) : Channel{new uint8_t[at::defaultReceiveBufferSize]}, cellular(cellular)
{
- isInitialized = true;
+ responseBuffer = xMessageBufferCreate(at::defaultMessageBufferSize);
}
/// plz see 12.7 summary of urc in documentation
std::vector<ATParser::Urc> ATParser::ParseURC()
{
-
- std::vector<ATParser::Urc> resp;
size_t maxPos = 0, pos = 0;
- cpp_freertos::LockGuard lock(mutex);
-
std::vector<std::pair<std::string, ATParser::Urc>> vals = {
{"RDY", ATParser::Urc::MeInitializationSuccessful},
{"+CFUN: 1", ATParser::Urc::FullFuncionalityAvailable},
};
+ std::vector<ATParser::Urc> resp;
+ resp.reserve(vals.size() + 1);
+ cpp_freertos::LockGuard lock(mutex);
+
for (const auto &el : vals) {
- pos = responseBuffer.find(el.first);
+ pos = urcBuffer.find(el.first);
if (pos != std::string::npos) {
resp.push_back(el.second);
maxPos = std::max(pos + el.first.length(), maxPos);
@@ 38,50 38,54 @@ std::vector<ATParser::Urc> ATParser::ParseURC()
}
}
- if (responseBuffer.find("+QIND: \"FOTA\"") != std::string::npos) {
- LOG_DEBUG("%s", responseBuffer.c_str());
+ if (urcBuffer.find("+QIND: \"FOTA\"") != std::string::npos) {
+ LOG_DEBUG("%s", urcBuffer.c_str());
resp.push_back(ATParser::Urc::Fota);
return resp;
}
// manage string buffer
if (maxPos == 0) {}
- else if (responseBuffer.size() >= maxPos) {
- responseBuffer.erase();
+ else if (urcBuffer.size() >= maxPos) {
+ urcBuffer.erase();
}
else {
- responseBuffer = responseBuffer.substr(maxPos);
+ urcBuffer = urcBuffer.substr(maxPos);
}
return resp;
}
-int ATParser::ProcessNewData(sys::Service *service)
+at::Result ATParser::ProcessNewData(sys::Service *service, bsp::cellular::CellularResult &cellularResult)
{
- char rawBuffer[256] = {0};
-
- LOG_DEBUG("Receiving data from ProcessNewData");
- auto length = cellular->Read(rawBuffer, sizeof(rawBuffer));
+ at::Result result;
{
cpp_freertos::LockGuard lock(mutex);
- responseBuffer.append(reinterpret_cast<char *>(rawBuffer), length);
- LOG_DEBUG("Appending %d bytes to responseBuffer[%u]: %s",
- static_cast<int>(length),
- static_cast<unsigned int>(responseBuffer.size()),
- utils::removeNewLines(responseBuffer).c_str());
+ urcBuffer.append(cellularResult.getDataAsString());
}
auto ret = ParseURC();
- if (blockedTaskHandle) {
- xTaskNotifyGive(blockedTaskHandle);
+
+ if (awaitingResponseFlag.state()) {
+ if (!xMessageBufferSend(responseBuffer,
+ cellularResult.getSerialized().get(),
+ cellularResult.getSerializedSize(),
+ pdMS_TO_TICKS(at::defaultBufferTimeoutMs.count()))) {
+ LOG_DEBUG("[AT] Message buffer full!");
+ result.code = at::Result::Code::FULL_MSG_BUFFER;
+ }
}
- else if (ret.size()) {
+ else if (!ret.empty()) {
if (ret.size() == 1 && ret[0] == ATParser::Urc::Fota) {
- std::string fotaData(responseBuffer);
+ std::string fotaData;
+ {
+ cpp_freertos::LockGuard lock(mutex);
+ fotaData = std::string(urcBuffer);
+ urcBuffer.erase();
+ }
LOG_DEBUG("parsing FOTA:\"%s\"", fotaData.c_str());
FotaService::API::sendRawProgress(service, fotaData);
- responseBuffer.erase();
}
else {
urcs.insert(std::end(urcs), std::begin(ret), std::end(ret));
@@ 90,36 94,40 @@ int ATParser::ProcessNewData(sys::Service *service)
// 1) RDY
// 2) +CFUN: 1
if (urcs.size() == 2) {
- cpp_freertos::LockGuard lock(mutex);
auto msg = std::make_shared<CellularPowerUpProcedureCompleteNotification>();
- service->bus.sendMulticast(msg, sys::BusChannel::ServiceCellularNotifications);
- LOG_DEBUG("[!!!] Fucking away data");
- responseBuffer.erase();
+ service->bus.sendMulticast(std::move(msg), sys::BusChannel::ServiceCellularNotifications);
urcs.clear();
+
+ cpp_freertos::LockGuard lock(mutex);
+ urcBuffer.erase();
}
}
- return 1;
+ else {
+ result.code = at::Result::Code::DATA_NOT_USED;
+ }
+
+ return result;
}
void ATParser::cmd_init()
{
cpp_freertos::LockGuard lock(mutex);
- responseBuffer.erase();
+ urcBuffer.erase();
}
void ATParser::cmd_send(std::string cmd)
{
- cellular->Write(const_cast<char *>(cmd.c_str()), cmd.size());
+ cellular->write(const_cast<char *>(cmd.c_str()), cmd.size());
}
-std::string ATParser::cmd_receive()
+size_t ATParser::cmd_receive(std::uint8_t *buffer, std::chrono::milliseconds timeout = std::chrono::milliseconds{0})
{
- cpp_freertos::LockGuard lock(mutex);
- return responseBuffer;
+ return xMessageBufferReceive(responseBuffer, buffer, 256, pdMS_TO_TICKS(timeout.count()));
}
void ATParser::cmd_post()
{
cpp_freertos::LockGuard lock(mutex);
- responseBuffer.erase(); // TODO:M.P is it okay to flush buffer here ?
+ urcBuffer.erase();
+ xMessageBufferReset(responseBuffer);
}
M module-cellular/Modem/ATParser.hpp => module-cellular/Modem/ATParser.hpp +9 -6
@@ 11,6 11,9 @@
#include <optional>
#include <task.h>
#include <vector>
+#include <message_buffer.h>
+
+#include <bsp/cellular/CellularResult.hpp>
namespace bsp
{
@@ 34,19 37,19 @@ class ATParser : public at::Channel
ATParser(bsp::Cellular *cellular);
virtual ~ATParser() = default;
- int ProcessNewData(sys::Service *service);
+ at::Result ProcessNewData(sys::Service *service, bsp::cellular::CellularResult &cellularResult);
virtual void cmd_init() override final;
virtual void cmd_send(std::string cmd) override final;
- virtual std::string cmd_receive() override final;
+ virtual size_t cmd_receive(std::uint8_t *buffer, std::chrono::milliseconds timeout) override final;
virtual void cmd_post() override final;
private:
std::vector<Urc> ParseURC();
- bsp::Cellular *cellular = nullptr;
- std::string responseBuffer;
- std::vector<ATParser::Urc> urcs;
- bool isInitialized = false;
+ bsp::Cellular *cellular = nullptr;
+ MessageBufferHandle_t responseBuffer = nullptr;
+ std::string urcBuffer = {};
+ std::vector<ATParser::Urc> urcs = {};
};
#endif // PUREPHONE_ATPARSER_HPP
M module-cellular/Modem/BaseChannel.hpp => module-cellular/Modem/BaseChannel.hpp +6 -6
@@ 7,7 7,7 @@
#include <vector>
#include <at/Commands.hpp>
#include <at/Result.hpp>
-#include <at/Constants.hpp>
+#include <bsp/cellular/CellularResult.hpp>
namespace at
{
@@ 29,12 29,12 @@ namespace at
/// @defgroup Channel Platform independent methods
/// {
- virtual void cmd_log(std::string cmd, const Result &result, uint32_t timeout)
+ virtual void cmdLog(std::string cmd, const Result &result, std::chrono::milliseconds timeout)
{}
- virtual void cmd_init() = 0;
- virtual void cmd_send(std::string cmd) = 0;
- virtual std::string cmd_receive() = 0;
- virtual void cmd_post() = 0;
+ virtual void cmd_init() = 0;
+ virtual void cmd_send(std::string cmd) = 0;
+ virtual size_t cmd_receive(std::uint8_t *buffer, std::chrono::milliseconds timeoutMs) = 0;
+ virtual void cmd_post() = 0;
/// }
};
} // namespace at
A module-cellular/Modem/README.md => module-cellular/Modem/README.md +98 -0
@@ 0,0 1,98 @@
+
+
+# Cellular Multiplexer
+
+## Table of contents
+1. [History](#history)
+2. [Modes](#modes)
+3. [Single command data flow](#singlecmd)
+5. [Cellular result structures](#result)
+6. [Error codes](#errors)
+
+## History <a name="history"></a>
+| Authors | Change description | Status | Modification date |
+| ----------------- | ------------------------- | ------ | ----------------- |
+| Maciej Janicki | Initial version | Draft | 2021.03.24 |
+
+## Modes <a name="modes"></a>
+Cellular operates in three modes:
+ - AT,
+ - CMUX setup,
+ - CMUX
+
+The AT mode is used for communication setup and modem configuration.
+
+
+
+The CMUX setup is an intermidiate state starting a CMUX communication:
+ - It configures CMUX mode's transmission parameters.
+ - It creates channels for a frame multiplexing (Commands, Notifications, Data).
+Data flow for both CMUX and CMUX setup in current implementation is identical.
+
+
+
+## Single command data flow <a name="singlecmd"></a>
+
+
+A single command sequence starts with a call from the Service and can end in one of three ways:
+ - Command response timeout (timeout depends on command issued).
+ - Service receives an error in result and handles it accordingly.
+ - Command response is successfully parsed before timeout and passed to service layer.
+
+## Result structs <a name="result"></a>
+
+Currently, there are two types of structs used to pass data between contexts.
+
+DMA result struct is used to directly store data from DMA engine as well as pass these through
+MessageBuffer to Worker. This struct has static data buffer maximum size.
+
+
+
+Cellular Result is used to pass complete frames serialized in vector together with
+result code. This struct has variable size.
+
+
+
+## Error codes <a name="errors"></a>
+
+
+
+
+Currently there are different errors/results codes for different layers.
+
+ 1. CellularResultCode
+ This code is used to pass information from bsp layer up to channel.
+ It can be either used to handle flow control messages from DMA or
+ to pass failures to upper layer (transmission/receiving not starter,
+ cmux frame error).
+
+ ```
+ Uninitialized,
+ ReceivedAndIdle,
+ ReceivedAndFull,
+ ReceivedAfterFull,
+ ReceivedNoData,
+ ReceivingNotStarted,
+ TransmittingNotStarted,
+ CMUXFrameError,
+ ```
+
+ 2. AtResult
+ This result code is passed to service layer.
+
+ ```
+ OK, /// at OK
+ ERROR, /// at ERROR For compatibility also for CME_ERROR and CMS_ERROR (details in errorCode)
+ CME_ERROR, /// In case CME error see errorCode
+ CMS_ERROR, /// In case CMS error see errorCode
+ TIMEOUT, /// at Timeout
+ TOKENS, /// at numbers of tokens needed met
+ NONE, /// no code
+ UNDEFINED, /// undefined result - usage of Undefined result, define and pin result to use it
+ PARSING_ERROR, /// parser error
+ FULL_MSG_BUFFER, /// at not enough space left in message buffer for new message
+ TRANSMISSION_NOT_STARTED, /// at dma not starting transmission
+ RECEIVING_NOT_STARTED, /// at dma not starting requested receiving
+ DATA_NOT_USED, /// at received data not being used
+ CMUX_FRAME_ERROR, /// at cmux deserialize error
+ ```
M module-cellular/Modem/TS0710/DLC_channel.cpp => module-cellular/Modem/TS0710/DLC_channel.cpp +113 -125
@@ 1,50 1,44 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-/**
- * Project Untitled
- */
-
#include "DLC_channel.h"
-#include "TS0710.h"
+
#include "TS0710_DATA.h"
-#include "TS0710_DLC_ESTABL.h"
#include "TS0710_DLC_RELEASE.h"
#include "TS0710_Frame.h"
-#include "log/log.hpp"
-#include "ticks.hpp"
+
+#include <module-utils/log/log.hpp>
+#include <ticks.hpp>
#include <Utils.hpp>
-#include <cstdlib>
-/**
- * DLC_channel implementation
- */
+#include <magic_enum.hpp>
-DLC_channel::DLC_channel(DLCI_t DLCI, std::string name, bsp::Cellular *cellular, Callback_t callback)
+DLC_channel::DLC_channel(DLCI_t DLCI, const std::string &name, bsp::Cellular *cellular, const Callback_t &callback)
+ : Channel{new uint8_t[at::defaultReceiveBufferSize]}, pv_name{name}, pv_DLCI{DLCI}, pv_cellular{cellular}
{
LOG_DEBUG("Creating DLCI %i channel \"%s\"", DLCI, name.c_str());
- pv_name = name;
- pv_DLCI = DLCI;
- pv_cellular = cellular;
- if (callback != nullptr)
+ if (callback != nullptr) {
pv_callback = callback;
+ }
+
+ chanParams.TypeOfFrame = TypeOfFrame_e::SABM;
+ chanParams.ConvergenceLayer = 1;
+ chanParams.Priority = 1;
+ chanParams.AckTime = 100; // 100ms default
+ chanParams.MaxFrameSize = 128;
+ chanParams.MaxNumOfRetransmissions = 3; // default 3
+ chanParams.ErrRecovWindowSize = 2; // default 2
- DLC_ESTABL_SystemParameters_t system_parameters;
- system_parameters.TypeOfFrame = TypeOfFrame_e::SABM;
- system_parameters.ConvergenceLayer = 1;
- system_parameters.Priority = 1;
- system_parameters.AckTime = 100; // 100ms default
- system_parameters.MaxFrameSize = 128;
- system_parameters.MaxNumOfRetransmissions = 3; // default 3
- system_parameters.ErrRecovWindowSize = 2; // default 2
-
- TS0710_DLC_ESTABL establ = TS0710_DLC_ESTABL(DLCI, system_parameters, cellular);
- pv_chanParams = establ.getParams();
-
- // wait for return & set active
- active = establ.getResponse();
- LOG_DEBUG("Create channel %s: %s", pv_name.c_str(), active ? "TRUE" : "FALSE");
+ responseBuffer = xMessageBufferCreate(at::defaultMessageBufferSize);
+}
+
+bool DLC_channel::init()
+{
+ active = establish();
+ LOG_INFO("create channel %s: %s", pv_name.c_str(), active ? "TRUE" : "FALSE");
+
+ return active;
}
DLC_channel::~DLC_channel()
@@ 54,41 48,46 @@ DLC_channel::~DLC_channel()
void DLC_channel::SendData(std::vector<uint8_t> &data)
{
- TS0710_DATA _data = TS0710_DATA(pv_DLCI, pv_chanParams, data, pv_cellular);
+ TS0710_DATA _data = TS0710_DATA(pv_DLCI, chanParams, data, pv_cellular);
}
-#if 0 // left here for reference
-ssize_t DLC_channel::ReceiveData(std::vector<uint8_t> &data, uint32_t timeout) {
- ssize_t ret = -1;
- static uint8_t *buf = nullptr;
- buf = reinterpret_cast<uint8_t*>(malloc(pv_chanParams.MaxFrameSize));
- bool complete = false;
-
- while((!complete) && (timeout--)) { //TODO: add timeout control
- ret = pv_cellular->Read(reinterpret_cast<void *>(buf), pv_chanParams.MaxFrameSize);
- if (ret > 0) {
- LOG_DEBUG("Received %i bytes", ret);
- for (int i = 0; i < ret; i++)
- data.push_back(buf[i]);
- complete = TS0710_Frame::isComplete(data);
+bool DLC_channel::establish()
+{
+ LOG_DEBUG("Sending %s frame to DLCI %i", TypeOfFrame_text[chanParams.TypeOfFrame].c_str(), pv_DLCI);
+
+ TS0710_Frame frame_c(TS0710_Frame::frame_t(static_cast<uint8_t>(pv_DLCI << 2) | (1 << 1),
+ static_cast<uint8_t>(chanParams.TypeOfFrame)));
+
+ awaitingResponseFlag.set();
+
+ bool result = false;
+
+ for (int retries = 0; retries < chanParams.MaxNumOfRetransmissions; ++retries) {
+ pv_cellular->write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
+
+ auto startTime = std::chrono::steady_clock::now();
+ auto endTime = startTime + std::chrono::milliseconds{300};
+
+ // Wait for response:
+ while (true) {
+ if (std::chrono::steady_clock::now() > endTime) {
+ break;
+ }
+
+ if (size_t bytesRead = cmd_receive(receiveBuffer.get(), std::chrono::milliseconds{0}); bytesRead > 0) {
+ auto cellularResult = bsp::cellular::CellularResult{receiveBuffer.get(), bytesRead};
+ if (evaluateEstablishResponse(cellularResult)) {
+ result = true;
+ break;
+ }
+ }
}
- sleep_ms(1);
- }
- if (!complete)
- LOG_ERROR("Incomplete frame received");
- if (timeout == 0)
- LOG_ERROR("Timeout occured");
-
- free(buf);
-
- if (!TS0710_Frame::isMyChannel(data, pv_DLCI)) {
- data.clear();
- ret = -1;
}
- return ret;
+ awaitingResponseFlag.clear();
+
+ return result;
}
-#endif
void DLC_channel::cmd_init()
{}
@@ 99,78 98,56 @@ void DLC_channel::cmd_send(std::string cmd)
SendData(data);
}
-std::string DLC_channel::cmd_receive()
+size_t DLC_channel::cmd_receive(uint8_t *result, std::chrono::milliseconds timeout)
{
- cpp_freertos::LockGuard lock(mutex);
- TS0710_Frame::frame_t frame;
- std::vector<uint8_t> v(responseBuffer.begin(), responseBuffer.end());
-
- responseBuffer.clear();
- std::vector<std::vector<uint8_t>> mFrames;
- std::vector<uint8_t> rawBuffer;
-
- // get frames from buffer
- for (size_t i = 0; i < v.size(); i++) {
- rawBuffer.push_back(v[i]);
- if (/*TS0710_Frame::isComplete(rawBuffer)*/ (rawBuffer.size() > 1) && (rawBuffer[0] == 0xF9) &&
- (rawBuffer[rawBuffer.size() - 1] == 0xF9)) {
- // LOGrawBufferEBUG("Pushing back FRAME");
- mFrames.push_back(rawBuffer);
- rawBuffer.clear();
- }
- }
- // deseriaise data from received frames
- std::string deserialisedData;
- for (std::vector<uint8_t> vv : mFrames) {
- frame.deserialize(vv);
- std::string str(frame.data.begin(), frame.data.end());
- // append deserialised buffer
- deserialisedData += str;
- }
- mFrames.clear();
- return deserialisedData;
+ return xMessageBufferReceive(responseBuffer, result, 2 * chanParams.MaxFrameSize, pdMS_TO_TICKS(timeout.count()));
}
void DLC_channel::cmd_post()
{}
-std::vector<std::string> DLC_channel::SendCommandPrompt(const char *cmd, size_t rxCount, uint32_t timeout)
+std::vector<std::string> DLC_channel::SendCommandPrompt(const char *cmd,
+ size_t rxCount,
+ std::chrono::milliseconds timeout)
{
std::vector<std::string> tokens;
- blockedTaskHandle = xTaskGetCurrentTaskHandle();
+ LOG_DEBUG("SendCommandPrompt start");
+
+ awaitingResponseFlag.set();
+
at::Result result;
cmd_init();
std::string cmdFixed = formatCommand(cmd);
cmd_send(cmdFixed);
- uint32_t currentTime = cpp_freertos::Ticks::GetTicks();
- uint32_t timeoutNeeded = timeout == UINT32_MAX ? UINT32_MAX : currentTime + timeout;
- uint32_t timeElapsed = currentTime;
-
- // wait_for_data:
- while (1) {
+ auto startTime = std::chrono::steady_clock::now();
+ auto endTime = startTime + timeout;
- if (timeElapsed >= timeoutNeeded) {
+ LOG_DEBUG("SendCommandPrompt cmd sent");
+ // Wait for response:
+ while (true) {
+ if (std::chrono::steady_clock::now() > endTime) {
result.code = at::Result::Code::TIMEOUT;
+ LOG_DEBUG("SendCommandPrompt cmd timeout");
break;
}
- auto ret = ulTaskNotifyTake(pdTRUE, timeoutNeeded - timeElapsed);
- timeElapsed = cpp_freertos::Ticks::GetTicks();
- if (ret) {
+ if (size_t bytesRead = cmd_receive(receiveBuffer.get(), std::chrono::milliseconds{0}); bytesRead > 0) {
+ auto cellularResult = bsp::cellular::CellularResult{receiveBuffer.get(), bytesRead};
+ auto str = cellularResult.getDataAsString();
+ LOG_DEBUG("SendCommandPrompt got response");
- std::vector<std::string> strings;
+ auto cellResult = checkResult(cellularResult.getResultCode());
+ if (cellResult.code != at::Result::Code::OK) {
+ LOG_DEBUG("SendCommandPrompt cmd response code: %s",
+ std::string(magic_enum::enum_name(cellResult.code)).c_str());
+ break;
+ }
- cpp_freertos::LockGuard lock(mutex);
- TS0710_Frame::frame_t frame;
- std::vector<uint8_t> v(responseBuffer.begin(), responseBuffer.end());
- responseBuffer.clear();
- frame.deserialize(v);
- std::string str(frame.data.begin(), frame.data.end());
// tokenize responseBuffer
- auto pos = str.find(">");
+ auto pos = str.find('>');
if (pos != std::string::npos) {
tokens.push_back(str.substr(pos, strlen(">")));
break;
@@ 181,31 158,42 @@ std::vector<std::string> DLC_channel::SendCommandPrompt(const char *cmd, size_t
}
}
- cmd_log(cmdFixed, result, timeout);
+ LOG_DEBUG("SendCommandPrompt end");
+ cmdLog(cmdFixed, result, timeout);
cmd_post();
- blockedTaskHandle = nullptr;
+
+ awaitingResponseFlag.clear();
return tokens;
}
-int DLC_channel::ParseInputData(std::vector<uint8_t> &data)
+at::Result DLC_channel::ParseInputData(bsp::cellular::CellularResult *cellularResult)
{
+ at::Result result;
- cpp_freertos::LockGuard lock(mutex);
-
- if (blockedTaskHandle) {
- responseBuffer.append(reinterpret_cast<char *>(data.data()), data.size());
- xTaskNotifyGive(blockedTaskHandle);
+ if (awaitingResponseFlag.state()) {
+ if (!xMessageBufferSend(responseBuffer,
+ (void *)cellularResult->getSerialized().get(),
+ cellularResult->getSerializedSize(),
+ pdMS_TO_TICKS(at::defaultBufferTimeoutMs.count()))) {
+ LOG_DEBUG("[DLC] Message buffer full!");
+ result.code = at::Result::Code::FULL_MSG_BUFFER;
+ }
}
else if (pv_callback != nullptr) {
-
- TS0710_Frame frame(data);
- auto deserialised = frame.getFrame().data;
-
- std::string receivedData = std::string(deserialised.begin(), deserialised.end());
-
+ std::string receivedData = cellularResult->getDataAsString();
pv_callback(receivedData);
}
+ else {
+ result.code = at::Result::Code::DATA_NOT_USED;
+ }
- return 1;
+ return result;
+}
+
+bool DLC_channel::evaluateEstablishResponse(bsp::cellular::CellularResult &response) const
+{
+ auto frame = TS0710_Frame{response.getData()};
+ return (frame.getFrameDLCI() == pv_DLCI &&
+ (frame.getFrame().Control == (static_cast<uint8_t>(TypeOfFrame_e::UA) & ~(1 << 4))));
}
M module-cellular/Modem/TS0710/DLC_channel.h => module-cellular/Modem/TS0710/DLC_channel.h +19 -16
@@ 12,10 12,12 @@
#include <vector>
#include <functional>
-#include "../ATCommon.hpp"
+#include "Modem/ATCommon.hpp"
#include "TS0710_types.h"
+#include <bsp/cellular/CellularResult.hpp>
#include <FreeRTOS.h>
#include <task.h>
+#include <message_buffer.h>
class DLC_channel : public at::Channel
{
@@ 26,23 28,20 @@ class DLC_channel : public at::Channel
std::string pv_name;
DLCI_t pv_DLCI;
bool active = false;
- DLC_ESTABL_SystemParameters_t pv_chanParams;
+ DLC_ESTABL_SystemParameters_t chanParams{};
Callback_t pv_callback;
-
- std::string responseBuffer;
- bsp::Cellular *pv_cellular;
+ bsp::Cellular *pv_cellular{};
public:
- // TS0710_DLC_ESTABL ctrlChanEstabl = TS0710_DLC_ESTABL(0); //use default values to create control channel DLCI0
+ DLC_channel(DLCI_t DLCI, const std::string &name, bsp::Cellular *cellular, const Callback_t &callback = nullptr);
+ DLC_channel() : Channel{nullptr}, pv_name{"none"}, pv_DLCI{-1}
+ {}
- DLC_channel(DLCI_t DLCI, std::string name, bsp::Cellular *cellular, Callback_t callback = nullptr);
- DLC_channel()
- {
- pv_DLCI = -1;
- pv_name = "none";
- } // default constructor creates empty channel
virtual ~DLC_channel();
+ bool init();
+ bool establish();
+
void SendData(std::vector<uint8_t> &data);
DLCI_t getDLCI()
@@ 58,7 57,6 @@ class DLC_channel : public at::Channel
return active;
}
- // ssize_t ReceiveData(std::vector<uint8_t> &data, uint32_t timeout);
void setCallback(Callback_t callback)
{
LOG_DEBUG("[%s] Setting up callback for channel", pv_name.c_str());
@@ 67,12 65,17 @@ class DLC_channel : public at::Channel
virtual void cmd_init() override final;
virtual void cmd_send(std::string cmd) override final;
- virtual std::string cmd_receive() override final;
+ virtual size_t cmd_receive(std::uint8_t *result,
+ std::chrono::milliseconds timeout = std::chrono::milliseconds{300}) override final;
virtual void cmd_post() override final;
- std::vector<std::string> SendCommandPrompt(const char *cmd, size_t rxCount, uint32_t timeout = 300);
+ std::vector<std::string> SendCommandPrompt(const char *cmd,
+ size_t rxCount,
+ std::chrono::milliseconds timeout = std::chrono::milliseconds{300});
+
+ at::Result ParseInputData(bsp::cellular::CellularResult *cellularResult);
- int ParseInputData(std::vector<uint8_t> &data);
+ bool evaluateEstablishResponse(bsp::cellular::CellularResult &response) const;
void callback(std::string &data)
{
M module-cellular/Modem/TS0710/TS0710.cpp => module-cellular/Modem/TS0710/TS0710.cpp +187 -157
@@ 5,6 5,7 @@
#include <at/ATFactory.hpp>
#include <at/Cmd.hpp>
#include "bsp/cellular/bsp_cellular.hpp"
+#include "bsp/cellular/CellularResult.hpp"
#include "projdefs.h"
#include <service-cellular/ServiceCellular.hpp>
#include <service-cellular/SignalStrength.hpp>
@@ 44,39 45,11 @@ std::map<PortSpeed_e, int> ATPortSpeeds_text = {{PortSpeed_e::PS9600, 9
#define SERIAL_PORT "/dev/null"
#endif
-#define USE_DAEFAULT_BAUDRATE 1
-
-static const std::uint16_t threadSizeWords = 2048;
+static constexpr std::uint16_t threadSizeWords = 2048;
TS0710::TS0710(PortSpeed_e portSpeed, sys::Service *parent)
{
- LOG_INFO("Serial port: '%s'", SERIAL_PORT);
- pv_portSpeed = portSpeed;
- pv_cellular = bsp::Cellular::Create(SERIAL_PORT, 115200).value_or(nullptr);
- parser = new ATParser(pv_cellular.get());
- pv_parent = parent;
-
- // start connection
- startParams.PortSpeed = pv_portSpeed;
- startParams.MaxFrameSize = 127; // maximum for Basic mode
- startParams.AckTimer = 10; // 100ms default
- startParams.MaxNumOfRetransmissions = 3; // default
- startParams.MaxCtrlRespTime = 30; // 300ms default
- startParams.WakeUpRespTime = 10; // 10s default
- startParams.ErrRecovWindowSize = 2; // 2 default
-
- if (auto flushed = FlushReceiveData(); flushed > 0) {
- LOG_INFO("Discarded initial %" PRIu32 " bytes sent by modem",
- static_cast<uint32_t>(flushed)); // not baud-accurate. Might be 460800÷115200 times more
- }
-
- constexpr auto workerName = "TS0710SerialRxWorker";
- BaseType_t task_error =
- xTaskCreate(workerTaskFunction, workerName, threadSizeWords, this, taskPriority, &taskHandle);
- if (task_error != pdPASS) {
- LOG_ERROR("Failed to start %s task", workerName);
- return;
- }
+ Init(portSpeed, parent);
}
TS0710::~TS0710()
@@ 90,9 63,47 @@ TS0710::~TS0710()
if (taskHandle) {
vTaskDelete(taskHandle);
}
+
delete parser;
}
+void TS0710::Init(PortSpeed_e portSpeed, sys::Service *parent)
+{
+ SetStartParams(portSpeed);
+
+ pv_cellular = bsp::Cellular::create(SERIAL_PORT, portSpeed).value_or(nullptr);
+ parser = new ATParser(pv_cellular.get());
+ pv_parent = parent;
+
+ if (auto flushed = flushReceiveData(); flushed > 0) {
+ LOG_INFO("Discarded initial %lu bytes sent by modem",
+ static_cast<unsigned long>(flushed)); // not baud-accurate. Might be 460800÷115200 times more
+ }
+ else {
+ LOG_DEBUG("Nothing to discard");
+ }
+
+ constexpr auto workerName = "TS0710Worker";
+
+ BaseType_t task_error =
+ xTaskCreate(workerTaskFunction, workerName, threadSizeWords, this, taskPriority, &taskHandle);
+ if (task_error != pdPASS) {
+ LOG_ERROR("Failed to start %s task", workerName);
+ return;
+ }
+}
+
+void TS0710::SetStartParams(PortSpeed_e portSpeed)
+{
+ startParams.PortSpeed = portSpeed;
+ startParams.MaxFrameSize = 127; // maximum for Basic mode
+ startParams.AckTimer = 10; // 100ms default
+ startParams.MaxNumOfRetransmissions = 3; // default
+ startParams.MaxCtrlRespTime = 30; // 300ms default
+ startParams.WakeUpRespTime = 10; // 10s default
+ startParams.ErrRecovWindowSize = 2; // 2 default
+}
+
TS0710_Frame::frame_t createCMUXExitFrame()
{
TS0710_Frame::frame_t frame;
@@ 145,7 156,7 @@ void CloseCmux(std::unique_ptr<bsp::Cellular> &pv_cellular)
{
LOG_INFO("Closing mux mode");
TS0710_Frame::frame_t frame = createCMUXExitFrame();
- pv_cellular->Write((void *)frame.serialize().data(), frame.serialize().size());
+ pv_cellular->write((void *)frame.serialize().data(), frame.serialize().size());
vTaskDelay(1000); // GSM module needs some time to close multiplexer
}
@@ 163,7 174,7 @@ TS0710::ConfState TS0710::BaudDetectOnce()
while (!result) {
switch (step) {
case BaudTestStep::baud460800_NoCmux:
- pv_cellular->SetSpeed(ATPortSpeeds_text[PortSpeed_e::PS460800]);
+ pv_cellular->setSpeed(ATPortSpeeds_text[PortSpeed_e::PS460800]);
lastStep = step;
result = BaudDetectTestAT(parser, step, BaudTestStep::baud460800_Cmux);
break;
@@ 173,7 184,7 @@ TS0710::ConfState TS0710::BaudDetectOnce()
result = BaudDetectTestAT(parser, step, BaudTestStep::baud115200_NoCmux);
break;
case BaudTestStep::baud115200_NoCmux:
- pv_cellular->SetSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]);
+ pv_cellular->setSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]);
lastStep = step;
result = BaudDetectTestAT(parser, step, BaudTestStep::baud115200_Cmux);
break;
@@ 183,8 194,8 @@ TS0710::ConfState TS0710::BaudDetectOnce()
result = BaudDetectTestAT(parser, step, BaudTestStep::baud_NotFound);
break;
case BaudTestStep::baud_NotFound:
- pv_cellular->SetSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]); // set port speed to default 115200
- LOG_DEBUG("No Baud found for modem.");
+ pv_cellular->setSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]); // set port speed to default 115200
+ LOG_ERROR("No Baud found for modem.");
return ConfState::Failure;
break;
}
@@ 206,31 217,25 @@ TS0710::ConfState TS0710::BaudDetectProcedure(uint16_t timeout_s)
return ConfState::Success;
}
}
- pv_cellular->SetSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]); // set port speed to default 115200
+ pv_cellular->setSpeed(ATPortSpeeds_text[PortSpeed_e::PS115200]); // set port speed to default 115200
LOG_ERROR("No Baud found.");
return ConfState::Failure;
}
-// TODO:M.P Fetch configuration from JSON/XML file
TS0710::ConfState TS0710::ConfProcedure()
{
LOG_DEBUG("Configuring modem...");
- if (!parser->cmd(at::AT::FACTORY_RESET)) {
+ auto flowCmd = hardwareControlFlowEnable ? (at::AT::FLOW_CTRL_ON) : (at::AT::FLOW_CTRL_OFF);
+ if (!parser->cmd(flowCmd)) {
return ConfState::Failure;
}
- if (!parser->cmd(at::AT::ECHO_OFF)) {
+
+ if (!parser->cmd(at::AT::FACTORY_RESET)) {
return ConfState::Failure;
}
- at::AT flowCmd;
- if (hardwareControlFlowEnable) {
- flowCmd = (at::AT::FLOW_CTRL_ON);
- }
- else {
- flowCmd = (at::AT::FLOW_CTRL_OFF);
- }
- if (!parser->cmd(flowCmd)) {
+ if (!parser->cmd(at::AT::ECHO_OFF)) {
return ConfState::Failure;
}
@@ 292,14 297,14 @@ TS0710::ConfState TS0710::AudioConfProcedure()
if (!parser->cmd(at::AT::QMIC)) {
return ConfState::Failure;
}
- return SetupEchoCanceller(EchoCancellerStrength::Tuned);
+ return setupEchoCanceller(EchoCancellerStrength::Tuned);
}
else {
if (!parser->cmd(at::AT::QDAI_INIT)) {
return ConfState::Failure;
}
else {
- pv_cellular->Restart();
+ pv_cellular->restart();
LOG_DEBUG("GSM module first run, performing reset...");
return ConfState::ModemNeedsReset;
}
@@ 359,13 364,13 @@ TS0710::ConfState TS0710::StartMultiplexer()
return ConfState::Failure;
}
- mode = Mode::CMUX_SETUP;
- TS0710_START *pv_TS0710_Start = new TS0710_START(TS0710_START::Mode_e::Basic, startParams, pv_cellular.get());
+ mode = Mode::CMUX_SETUP;
+
+ TS0710_START TS0710_Start{TS0710_START::Mode_e::Basic, startParams, pv_cellular.get()};
// wait for confirmation
- if (pv_TS0710_Start->ConnectionStatus()) {
- channels.push_back(pv_TS0710_Start->getCtrlChannel()); // store control channel
+ if (TS0710_Start.ConnectionStatus()) {
+ channels.push_back(TS0710_Start.getCtrlChannel()); // store control channel
}
- delete pv_TS0710_Start;
controlCallback = [this](std::string &data) {
auto frameData = data;
@@ 385,10 390,10 @@ TS0710::ConfState TS0710::StartMultiplexer()
LOG_PRINTF("RTR ");
if (frameData[3] & 0x04) {
LOG_PRINTF("RTC ");
- this->getCellular()->SetSendingAllowed(true);
+ this->getCellular()->setSendingAllowed(true);
}
else
- this->getCellular()->SetSendingAllowed(false);
+ this->getCellular()->setSendingAllowed(false);
if (frameData[3] & 0x02)
LOG_PRINTF("FC ");
@@ 397,24 402,23 @@ TS0710::ConfState TS0710::StartMultiplexer()
}
};
- // channels[0]->setCallback(controlCallback);
-
- // TODO: Open remaining channels
OpenChannel(Channel::Commands);
OpenChannel(Channel::Notifications);
OpenChannel(Channel::Data);
+ LOG_DEBUG("[TS0710] Channels open");
+
+ mode = Mode::CMUX;
- mode = Mode::CMUX;
- DLC_channel *c = get(Channel::Commands);
- if (c != nullptr) {
+ if (auto channel = get(Channel::Commands); channel != nullptr) {
// Route URCs to second (Notifications) MUX channel
- c->cmd(at::AT::SET_URC_CHANNEL);
+ LOG_DEBUG("[TS0710] Setting URC Channel");
+ channel->cmd(at::AT::SET_URC_CHANNEL);
LOG_DEBUG("Sending test ATI");
- auto res = c->cmd(at::AT::SW_INFO);
+ auto res = channel->cmd(at::AT::SW_INFO);
if (!res) {
LOG_ERROR("Sending test ATI command failed");
}
- res = c->cmd(at::AT::CSQ);
+ res = channel->cmd(at::AT::CSQ);
if (res) {
auto beg = res.response[0].find(" ");
auto end = res.response[0].find(",", 1);
@@ 443,123 447,149 @@ TS0710::ConfState TS0710::StartMultiplexer()
return ConfState::Failure;
}
+ LOG_DEBUG("[TS0710] Mux started");
return ConfState::Success;
}
-void workerTaskFunction(void *ptr)
+void TS0710::sendFrameToChannel(bsp::cellular::CellularResult &resultStruct)
{
- TS0710 *inst = reinterpret_cast<TS0710 *>(ptr);
+ auto frame = TS0710_Frame{resultStruct.getData()};
- while (1) {
- auto ret = inst->pv_cellular->Wait(UINT32_MAX);
- if (ret == 0) {
- continue;
- }
-
- // AT mode is used only during initialization phase
- if (inst->mode == TS0710::Mode::AT) {
- // inst->atParser->ProcessNewData();
- // TODO: add AT command processing
- LOG_DEBUG("[Worker] Processing AT response");
- inst->parser->ProcessNewData(inst->pv_parent);
- }
- // CMUX mode is default operation mode
- else if (inst->mode == TS0710::Mode::CMUX) {
- // LOG_DEBUG("[Worker] Processing CMUX response");
- std::vector<uint8_t> data;
- inst->ReceiveData(data, static_cast<uint32_t>(inst->startParams.MaxCtrlRespTime));
- // send data to fifo
- for (uint8_t c : data) {
- inst->RXFifo.push(c);
+ for (auto chan : getChannels()) {
+ if (frame.getFrameDLCI() == chan->getDLCI()) {
+ if (frame.getData().empty()) {
+ // Control frame contains no data
+ resultStruct.setData(frame.getSerData());
}
- data.clear();
- // divide message to different frames as Quectel may send them one after another
- std::vector<std::vector<uint8_t>> multipleFrames;
- std::vector<uint8_t> _d;
- int fifoLen = inst->RXFifo.size();
- // LOG_DEBUG("[RXFifo] %i elements", fifoLen);
-
- for (int i = 0; i < fifoLen; i++) {
- _d.push_back(inst->RXFifo.front());
- inst->RXFifo.pop();
- if (/*TS0710_Frame::isComplete(_d)*/ (_d.size() > 1) && (_d[0] == 0xF9) &&
- (_d[_d.size() - 1] == 0xF9)) {
- // LOG_DEBUG("Pushing back FRAME");
- multipleFrames.push_back(_d);
- _d.clear();
- }
- }
- // if some data stored @_d then push it back to queue as incomplete packet
- if (!_d.empty() && (_d[0] == 0xF9)) {
- // LOG_DEBUG("Pushing back [%i] incomplete frame", _d.size());
- for (uint8_t c : _d)
- inst->RXFifo.push(c);
+ else {
+ resultStruct.setData(frame.getData());
}
- _d.clear();
- // LOG_DEBUG("Received %i frames", multipleFrames.size());
- for (auto *chan : inst->channels) {
- for (std::vector<uint8_t> v : multipleFrames) {
- if (TS0710_Frame::isMyChannel(v, chan->getDLCI()))
- chan->ParseInputData(v);
- }
+ if (frame.getFrameStatus() != TS0710_Frame::OK) {
+ resultStruct.setResultCode(bsp::cellular::CellularResultCode::CMUXFrameError);
}
- multipleFrames.clear();
+
+ chan->ParseInputData(&resultStruct);
+ return;
}
}
}
-size_t TS0710::FlushReceiveData()
+void TS0710::parseCellularResultCMUX(bsp::cellular::CellularDMAResultStruct &result)
{
- using namespace std::chrono_literals;
+ static std::vector<uint8_t> currentFrame;
+ static bool frameStartDetected = false;
+
+ for (auto i = 0U; i < result.dataSize; ++i) {
+ uint8_t character = result.data[i];
+ if (frameStartDetected || character == TS0710_FLAG) {
+ currentFrame.push_back(character);
+
+ // Check if frame is complete only in case of TS0710_FLAG
+ if (frameStartDetected && character == TS0710_FLAG) {
+ if (currentFrame.size() == 2) {
+ currentFrame.erase(currentFrame.begin());
+ }
+ if (TS0710_Frame::isComplete(currentFrame)) {
+ frameStartDetected = false;
+ bsp::cellular::CellularResult cellularResult{{result.resultCode, currentFrame}};
+ sendFrameToChannel(cellularResult);
+ currentFrame.clear();
+ continue;
+ }
+ }
- auto flushed = 0U;
- constexpr auto flushInactivityTimeout = 20ms;
- std::uint8_t dummyRead[50];
- while (pv_cellular->Wait(flushInactivityTimeout.count())) {
- flushed += pv_cellular->Read(dummyRead, sizeof(dummyRead));
+ frameStartDetected = true;
+ }
}
+}
+
+size_t TS0710::flushReceiveData()
+{
+ auto flushed = 0U;
+ constexpr auto flushTimeout = std::chrono::milliseconds{20};
+ bsp::cellular::CellularDMAResultStruct dummyResult;
+ do {
+ flushed += pv_cellular->read(&dummyResult, dummyResult.getMaxSize(), flushTimeout);
+ } while (dummyResult.resultCode == bsp::cellular::CellularResultCode::ReceivedAndFull);
return flushed;
}
-ssize_t TS0710::ReceiveData(std::vector<uint8_t> &data, uint32_t timeout)
+void TS0710::processError(bsp::cellular::CellularDMAResultStruct &result)
{
- ssize_t ret = -1;
- std::unique_ptr<uint8_t[]> buf(new uint8_t[startParams.MaxFrameSize]);
- bool complete = false;
- uint32_t _timeout = timeout;
+ bsp::cellular::CellularResult cellularResult{{result.resultCode, {}}};
- while ((!complete) && (--_timeout)) {
- ret = pv_cellular->Read(reinterpret_cast<void *>(buf.get()), startParams.MaxFrameSize);
- if (ret > 0) {
- // LOG_DEBUG("Received %i bytes", ret);
- for (int i = 0; i < ret; i++) {
- data.push_back(buf[i]);
- }
- complete = TS0710_Frame::isComplete(data);
- }
- vTaskDelay(pdMS_TO_TICKS(1));
+ if (mode == TS0710::Mode::AT) {
+ parser->ProcessNewData(pv_parent, cellularResult);
+ }
+ else if (mode == TS0710::Mode::CMUX || mode == TS0710::Mode::CMUX_SETUP) {
+ sendFrameToChannel(cellularResult);
+ }
+}
+
+void TS0710::processData(bsp::cellular::CellularDMAResultStruct &result)
+{
+ if (mode == TS0710::Mode::AT) {
+ bsp::cellular::CellularResult cellularResult{result};
+ parser->ProcessNewData(pv_parent, cellularResult);
}
- if ((!complete) && (_timeout)) {
- LOG_ERROR("Incomplete frame received");
+ else if (mode == TS0710::Mode::CMUX || mode == TS0710::Mode::CMUX_SETUP) {
+ parseCellularResultCMUX(result);
}
+}
+
+[[noreturn]] void workerTaskFunction(void *ptr)
+{
+ LOG_DEBUG("Worker start");
+
+ constexpr auto readTimeout = std::chrono::minutes{3600};
+ TS0710 *inst = static_cast<TS0710 *>(ptr);
+ bsp::cellular::CellularDMAResultStruct result{};
+
+ while (true) {
+ result.resultCode = bsp::cellular::CellularResultCode::ReceivedNoData;
+
+ inst->pv_cellular->read(&result, bsp::cellular::CellularDMAResultStruct::getMaxSize(), readTimeout);
- return ret;
+ switch (result.resultCode) {
+ case bsp::cellular::CellularResultCode::ReceivedAndFull:
+ LOG_DEBUG("DMA buffer full");
+ [[fallthrough]];
+ case bsp::cellular::CellularResultCode::ReceivedAfterFull:
+ [[fallthrough]];
+ case bsp::cellular::CellularResultCode::ReceivedAndIdle:
+ inst->processData(result);
+ break;
+ case bsp::cellular::CellularResultCode::Uninitialized:
+ LOG_DEBUG("DMA uninitialized");
+ [[fallthrough]];
+ case bsp::cellular::CellularResultCode::ReceivingNotStarted:
+ [[fallthrough]];
+ case bsp::cellular::CellularResultCode::TransmittingNotStarted:
+ [[fallthrough]];
+ case bsp::cellular::CellularResultCode::CMUXFrameError:
+ LOG_DEBUG("CellularResult Error: %s", c_str(result.resultCode));
+ inst->processError(result);
+ break;
+ case bsp::cellular::CellularResultCode::ReceivedNoData:
+ break;
+ }
+ }
}
void TS0710::SelectAntenna(bsp::cellular::antenna antenna)
{
- pv_cellular->SelectAntenna(antenna);
+ pv_cellular->selectAntenna(antenna);
}
bsp::cellular::antenna TS0710::GetAntenna()
{
- return pv_cellular->GetAntenna();
+ return pv_cellular->getAntenna();
}
void TS0710::InformModemHostWakeup(void)
{
- return pv_cellular->InformModemHostWakeup();
+ return pv_cellular->informModemHostWakeup();
}
bool TS0710::IsModemActive(void)
@@ 569,46 599,46 @@ bool TS0710::IsModemActive(void)
void TS0710::TurnOnModem(void)
{
- return pv_cellular->PowerUp();
+ return pv_cellular->powerUp();
}
void TS0710::ResetModem(void)
{
- return pv_cellular->Restart();
+ return pv_cellular->restart();
}
void TS0710::TurnOffModem(void)
{
- return pv_cellular->PowerDown();
+ return pv_cellular->powerDown();
}
void TS0710::EnterSleepMode(void)
{
- return pv_cellular->EnterSleep();
+ return pv_cellular->enterSleep();
}
void TS0710::ExitSleepMode(void)
{
- return pv_cellular->ExitSleep();
+ return pv_cellular->exitSleep();
}
void TS0710::RegisterCellularDevice(void)
{
- auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(pv_cellular->GetCellularDevice());
+ auto deviceRegistrationMsg = std::make_shared<sys::DeviceRegistrationMessage>(pv_cellular->getCellularDevice());
pv_parent->bus.sendUnicast(std::move(deviceRegistrationMsg), service::name::system_manager);
}
-[[nodiscard]] auto TS0710::GetLastCommunicationTimestamp() const noexcept -> TickType_t
+[[nodiscard]] auto TS0710::getLastCommunicationTimestamp() const noexcept -> TickType_t
{
- return pv_cellular->GetLastCommunicationTimestamp();
+ return pv_cellular->getLastCommunicationTimestamp();
}
-[[nodiscard]] auto TS0710::IsCellularInSleepMode() const noexcept -> bool
+[[nodiscard]] auto TS0710::isCellularInSleepMode() const noexcept -> bool
{
- return pv_cellular->IsCellularInSleepMode();
+ return pv_cellular->isCellularInSleepMode();
}
-TS0710::ConfState TS0710::SetupEchoCanceller(EchoCancellerStrength strength)
+TS0710::ConfState TS0710::setupEchoCanceller(EchoCancellerStrength strength)
{
switch (strength) {
M module-cellular/Modem/TS0710/TS0710.h => module-cellular/Modem/TS0710/TS0710.h +38 -40
@@ 1,8 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#ifndef _TS0710_H
-#define _TS0710_H
+#pragma once
/*
5.2.6 Basic Option
@@ 190,6 189,9 @@ repeated until a response is obtained or action is taken by a higher layer.
*/
#include <vector>
+#include <queue>
+#include <string>
+#include <module-bsp/bsp/cellular/bsp_cellular.hpp>
#include "TS0710_START.h"
#include "TS0710_CLOSE.h"
@@ 197,14 199,13 @@ repeated until a response is obtained or action is taken by a higher layer.
#include "TS0710_TEST.h"
#include "TS0710_WAKEUP.h"
#include "TS0710_types.h"
-#include "DLC_channel.h"
#include "TS0710_Frame.h"
+
+#include "DLC_channel.h"
#include "Modem/ATParser.hpp"
#include "Service/Service.hpp"
-#include <queue>
-#include <string>
-#include "module-bsp/bsp/cellular/bsp_cellular.hpp"
+#include <message_buffer.h>
#if defined(__cplusplus)
extern "C"
@@ 221,7 222,7 @@ namespace bsp
class Cellular;
}
-void workerTaskFunction(void *ptr);
+[[noreturn]] void workerTaskFunction(void *ptr);
class TS0710
{
@@ 233,6 234,7 @@ class TS0710
Notifications = 2,
Data = 3,
};
+
static std::string name(enum Channel name)
{
switch (name) {
@@ 247,13 249,13 @@ class TS0710
}
return "";
}
+
enum class Mode
{
AT, /// AT raw text mode
CMUX_SETUP, /// Modem is switching from AT to CMUX
CMUX /// multiplexer mode enabled
};
- void setMode(Mode mode);
enum class ConfState
{
@@ 263,15 265,16 @@ class TS0710
PowerUp
};
+ void setMode(Mode mode);
+
private:
Mode mode = Mode::AT;
std::vector<DLC_channel *> channels;
- friend void workerTaskFunction(void *ptr);
- // worker's task handle
- xTaskHandle taskHandle = nullptr;
+
const uint32_t taskPriority = 0;
+ xTaskHandle taskHandle = nullptr;
+
std::unique_ptr<bsp::Cellular> pv_cellular;
- PortSpeed_e pv_portSpeed;
ATParser *parser;
int CloseMultiplexer();
@@ 290,7 293,6 @@ class TS0710
sys::Service *pv_parent;
DLC_channel::Callback_t controlCallback = nullptr;
- std::queue<uint8_t> RXFifo;
enum class EchoCancellerStrength
{
@@ 299,7 301,14 @@ class TS0710
Aggressive,
Tuned
};
- TS0710::ConfState SetupEchoCanceller(EchoCancellerStrength strength);
+
+ friend void workerTaskFunction(void *ptr);
+ ConfState setupEchoCanceller(EchoCancellerStrength strength);
+ void parseCellularResultCMUX(bsp::cellular::CellularDMAResultStruct &result);
+ size_t flushReceiveData();
+ void processData(bsp::cellular::CellularDMAResultStruct &result);
+ void processError(bsp::cellular::CellularDMAResultStruct &result);
+ void sendFrameToChannel(bsp::cellular::CellularResult &resultStruct);
public:
/// @brief get Channel by index
@@ 316,31 325,22 @@ class TS0710
return nullptr;
}
- DLC_channel *OpenChannel(Channel chanel_val)
+ std::vector<DLC_channel *> &getChannels()
{
- DLC_channel *channel = new DLC_channel(static_cast<DLCI_t>(chanel_val), name(chanel_val), pv_cellular.get());
- channels.push_back(channel);
- return channels.back();
+ return channels;
}
- void CloseChannel(unsigned index)
+ DLC_channel *OpenChannel(Channel channelIndex)
{
- if (index >= channels.size()) {
- LOG_ERROR("Wrong channel index");
- return;
- }
- delete channels[index];
- channels.erase(channels.begin() + index);
- }
+ auto *channel = new DLC_channel(static_cast<DLCI_t>(channelIndex), name(channelIndex), pv_cellular.get());
+ channels.push_back(channel);
- void CloseChannel(const std::string &name)
- {
- for (size_t i = 0; i < channels.size(); i++) {
- if (channels[i]->getName() == name) {
- delete channels[i];
- channels.erase(channels.begin() + 1);
- }
+ if (!channel->init()) {
+ channels.pop_back();
+ delete channel;
}
+
+ return channels.back();
}
void CloseChannels()
@@ 357,15 357,13 @@ class TS0710
{
return static_cast<DLCI_t>(channels.size() == 0 ? 0 : channels.size() - 1);
}
+
ConfState BaudDetectOnce();
ConfState BaudDetectProcedure(uint16_t timeout_s = 30);
ConfState ConfProcedure();
ConfState AudioConfProcedure();
ConfState StartMultiplexer();
- size_t FlushReceiveData();
- ssize_t ReceiveData(std::vector<uint8_t> &data, uint32_t timeout);
-
bsp::Cellular *getCellular()
{
return pv_cellular.get();
@@ 427,6 425,8 @@ class TS0710
TS0710(PortSpeed_e portSpeed, sys::Service *parent);
TS0710() = delete;
~TS0710();
+ void Init(PortSpeed_e portSpeed, sys::Service *parent);
+ void SetStartParams(PortSpeed_e portSpeed);
void SelectAntenna(bsp::cellular::antenna antenna);
bsp::cellular::antenna GetAntenna();
// Add error handling - only for Advanced mode. Leave for now
@@ 441,8 441,6 @@ class TS0710
void EnterSleepMode(void);
void ExitSleepMode(void);
void RegisterCellularDevice(void);
- [[nodiscard]] auto GetLastCommunicationTimestamp() const noexcept -> TickType_t;
- [[nodiscard]] auto IsCellularInSleepMode() const noexcept -> bool;
+ [[nodiscard]] auto getLastCommunicationTimestamp() const noexcept -> TickType_t;
+ [[nodiscard]] auto isCellularInSleepMode() const noexcept -> bool;
};
-
-#endif //_TS0710_H
M module-cellular/Modem/TS0710/TS0710_DATA.cpp => module-cellular/Modem/TS0710/TS0710_DATA.cpp +3 -3
@@ 61,7 61,7 @@ void TS0710_DATA::request(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t sysParams,
frame.data = User_data;
TS0710_Frame frame_c(frame);
// UartSend(frame_c.getSerData().data(), frame_c.getSerData().size());
- pv_cellular->Write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
+ pv_cellular->write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
}
else { // if data size > max frame size
int dataLeft = User_data.size();
@@ 76,7 76,7 @@ void TS0710_DATA::request(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t sysParams,
TS0710_Frame frame_c(frame);
// UartSend(frame_c.getSerData().data(), frame_c.getSerData().size());
// while(!pv_cellular->GetSendingAllowed());
- pv_cellular->Write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
+ pv_cellular->write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
// vTaskDelay(1);
dataLeft -= (dataLeft <= maximumFrameLength ? dataLeft : maximumFrameLength);
}
@@ 88,4 88,4 @@ void TS0710_DATA::request(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t sysParams,
* @param User_data
*/
void TS0710_DATA::indication(DLCI_t DLCI, std::vector<uint8_t> User_data)
-{}>
\ No newline at end of file
+{}
M module-cellular/Modem/TS0710/TS0710_DLC_ESTABL.cpp => module-cellular/Modem/TS0710/TS0710_DLC_ESTABL.cpp +7 -6
@@ 21,6 21,8 @@ extern "C"
#include "log/log.hpp"
#include "FreeRTOS.h"
+#include <bsp/cellular/CellularResult.hpp>
+
/**
* TS0710_DLC_ESTABL implementation
*/
@@ 81,12 83,12 @@ bool TS0710_DLC_ESTABL::request(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t syste
frame.Address = static_cast<uint8_t>(DLCI << 2) | (1 << 1); // set C/R = 1 - command
frame.Control = static_cast<uint8_t>(system_parameters.TypeOfFrame);
TS0710_Frame frame_c(frame);
- pv_cellular->Write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
+ pv_cellular->write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
// return true;
int retries = system_parameters.MaxNumOfRetransmissions;
while (retries--) {
// UartSend(frame_c.getSerData().data(), frame_c.getSerData().size());
- pv_cellular->Write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
+ pv_cellular->write(static_cast<void *>(frame_c.getSerData().data()), frame_c.getSerData().size());
vTaskDelay(system_parameters.AckTime);
if (response(DLCI, system_parameters)) {
LOG_DEBUG("Got response");
@@ 113,14 115,13 @@ void TS0710_DLC_ESTABL::indication(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t sy
bool TS0710_DLC_ESTABL::response(DLCI_t DLCI, DLC_ESTABL_SystemParameters_t system_parameters)
{
constexpr size_t size = 256;
- std::unique_ptr<uint8_t[]> data(new uint8_t[size]);
+ bsp::cellular::CellularDMAResultStruct result{};
- // uint32_t len = UartReceive(data);
- ssize_t len = pv_cellular->Read(reinterpret_cast<void *>(data.get()), size);
+ ssize_t len = pv_cellular->read(&result, size, std::chrono::milliseconds{0});
LOG_DEBUG("RX length = %d", static_cast<int>(len));
if (len > 0) {
- std::vector<uint8_t> v(data.get(), data.get() + len);
+ std::vector<uint8_t> v(result.data, result.data + result.dataSize);
TS0710_Frame frame_c(v);
TS0710_Frame::frame_t frame = frame_c.getFrame();
M module-cellular/Modem/TS0710/TS0710_Frame.h => module-cellular/Modem/TS0710/TS0710_Frame.h +65 -19
@@ 34,12 34,26 @@ class TS0710_Frame
0xBD, 0x2C, 0x5E, 0xCF};
public:
+ enum TS0710FrameStatus : std::uint8_t
+ {
+ OK,
+ EmptyFrame,
+ IncorrectStartStopFlags,
+ CRCError,
+ };
+
struct frame_t
{
+ TS0710FrameStatus frameStatus = OK;
uint8_t Address;
uint8_t Control;
std::vector<uint8_t> data;
+ frame_t() = default;
+
+ explicit frame_t(uint8_t address, uint8_t control) : frameStatus{OK}, Address{address}, Control{control}
+ {}
+
std::vector<uint8_t> serialize()
{
std::vector<uint8_t> ret;
@@ 65,7 79,7 @@ class TS0710_Frame
unsigned char i = 1;
if (Control == static_cast<uint8_t>(TypeOfFrame_e::UIH)) {
len = 3; // par. 5.3.6 of GSM0710 document states that for UIH frames, the FCS shall be calculated over
- // only the address, control and length fields TODO: include 2-byte address
+ // only the address, control and length fields TODO: include 2-byte address
// if (Length > 127)
// len += 1;
}
@@ 85,8 99,9 @@ class TS0710_Frame
{
if (serData.size() < 4) {
LOG_ERROR("Trying to deserialize empty frame");
- Address = 0;
- Control = 0;
+ Address = 0;
+ Control = 0;
+ frameStatus = EmptyFrame;
return;
}
// iterate through frame to get correct trailing flag. In case multiple-frame stream provided
@@ 104,8 119,9 @@ class TS0710_Frame
}
if ((serData[0] != TS0710_FLAG) || (serData[myLen - 1] != TS0710_FLAG)) {
- Address = 0;
- Control = 0;
+ Address = 0;
+ Control = 0;
+ frameStatus = IncorrectStartStopFlags;
LOG_ERROR("Received frame has incorrect leading/trailing flags. Dropping.");
return; // return empty frame. Discard frame witout proper leading & trailing flag
}
@@ 135,7 151,7 @@ class TS0710_Frame
unsigned char i = 1;
if (Control == static_cast<uint8_t>(TypeOfFrame_e::UIH)) {
len = 3; // par. 5.3.6 of GSM0710 document states that for UIH frames, the FCS shall be calculated over
- // only the address, control and length fields: include 2-byte address
+ // only the address, control and length fields
// if (Length > 127)
// len += 1;
}
@@ 150,8 166,15 @@ class TS0710_Frame
(Control !=
static_cast<uint8_t>(
TypeOfFrame_e::UA))) { // error - but fuck FCS check if it's faulty Quectel UIH frame or UA frame
- Address = 0;
- Control = 0;
+ LOG_PRINTF("\n{");
+ for (auto el : serData) {
+ LOG_PRINTF("%02X ", el);
+ }
+ LOG_PRINTF("}\n");
+
+ Address = 0;
+ Control = 0;
+ frameStatus = CRCError;
data.clear();
LOG_ERROR("Received frame FCS [0x%02X] != 0xCF error. Dropping.", FCS);
return; // return empty frame. Discard frame witout proper leading & trailing flag
@@ 164,33 187,42 @@ class TS0710_Frame
std::vector<uint8_t> pv_serData;
public:
- TS0710_Frame(frame_t frame)
+ explicit TS0710_Frame(frame_t frame)
{
// LOG_DEBUG("Serializing given frame");
pv_serData = frame.serialize();
pv_frame = frame;
}
- TS0710_Frame(std::vector<uint8_t> &serData)
+
+ explicit TS0710_Frame(const std::vector<uint8_t> &serData)
{
// LOG_DEBUG("Deserializing serData");
pv_frame.deserialize(serData);
pv_serData = serData;
}
+
TS0710_Frame()
{
LOG_DEBUG("Deserializing pv_serData");
pv_frame.deserialize(pv_serData);
}
+
~TS0710_Frame()
{
pv_serData.clear();
pv_frame.data.clear();
}
- frame_t getFrame()
+ frame_t &getFrame()
{
return pv_frame;
}
+
+ const std::vector<uint8_t> &getData() const noexcept
+ {
+ return pv_frame.data;
+ }
+
std::vector<uint8_t> getSerData()
{
return pv_serData;
@@ 199,11 231,13 @@ class TS0710_Frame
/* F9 03 3F 01 1C F9 */
static bool isComplete(const std::vector<uint8_t> &serData)
{
- if (serData.size() < 4)
+ if (serData.size() < 4) {
return false; // check if buffer has enough data to get length
+ }
- if ((serData[0] != TS0710_FLAG) || (serData[serData.size() - 1] != TS0710_FLAG))
+ if ((serData[0] != TS0710_FLAG) || (serData[serData.size() - 1] != TS0710_FLAG)) {
return false;
+ }
int Length = 0;
if (serData[3] & 0x01) { // short length
@@ 212,22 246,22 @@ class TS0710_Frame
else if (serData.size() > 4) { // long length - another check if enough bytes in buffer
Length = static_cast<uint16_t>(serData[3] >> 1) + (static_cast<uint16_t>(serData[4]) << 7);
}
- else
+ else {
return false;
+ }
if (serData.size() >=
static_cast<size_t>(TS0710_FRAME_HDR_LEN + Length +
- (serData[3] & 0x01 ? 0 : 1))) // include extended address byte if present
+ (serData[3] & 0x01 ? 0 : 1))) { // include extended address byte if present
return true;
+ }
return false;
}
- static bool isMyChannel(const std::vector<uint8_t> &serData, DLCI_t DLCI)
+ bool isMyChannel(DLCI_t DLCI) const
{
- if ((serData.size() > 1) && ((serData[1] >> 2) == DLCI))
- return true;
- return false;
+ return (pv_serData.size() > 1) && ((pv_serData[1] >> 2) == DLCI);
}
static DLCI_t getFrameDLCI(const std::vector<uint8_t> &serData)
@@ 236,6 270,18 @@ class TS0710_Frame
return (serData[1] >> 2);
return -1;
}
+
+ DLCI_t getFrameDLCI() const
+ {
+ if (pv_serData.size() > 1)
+ return (pv_serData[1] >> 2);
+ return -1;
+ }
+
+ TS0710FrameStatus getFrameStatus() const
+ {
+ return pv_frame.frameStatus;
+ }
};
#endif /*_TS0710_FRAME_H*/
A module-cellular/Modem/doc/Images/at_mode.svg => module-cellular/Modem/doc/Images/at_mode.svg +72 -0
@@ 0,0 1,72 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1324px" preserveAspectRatio="none" style="width:405px;height:1324px;" version="1.1" viewBox="0 0 405 1324" width="405px" zoomAndPan="magnify"><defs><filter height="300%" id="f1cg90pa4di60m" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacing" textLength="78" x="157" y="16.708">AT Mode</text><!--MD5=[36105e52843f3f28080f43ce369346ca]
+cluster CellularBSP--><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="277" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="350" x="7" y="27.9531"/><rect fill="#FFFFFF" height="244.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="344" x="10" y="57.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="7" x2="357" y1="54.25" y2="54.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="81" x="141.5" y="45.9482">CellularBSP</text><!--MD5=[4feec3315c2ae8fe0f31fdbe0936cbea]
+cluster CellularWorker--><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="554" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="295" x="29" y="377.9531"/><rect fill="#FFFFFF" height="521.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="289" x="32" y="407.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="29" x2="324" y1="404.25" y2="404.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="106" x="123.5" y="395.9482">CellularWorker</text><!--MD5=[df0b49b3bcea4a1034e7e56a9608b471]
+cluster Channel--><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="189" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="174" x="219" y="1004.9531"/><rect fill="#FFFFFF" height="156.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="168" x="222" y="1034.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="219" x2="393" y1="1031.25" y2="1031.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="58" x="277" y="1022.9482">Channel</text><g id="CellularBSP.UartIrq"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="64.2344" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="284" x="40" y="62.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="40" x2="324" y1="89.25" y2="89.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="157.5" y="80.9482">UartIrq</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="218" x="45" y="105.3887">Reads data with DMA to static buffer</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="264" x="45" y="119.3574">and packs them into struct with result code.</text></g><g id="CellularBSP.SendToWorker"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50.2656" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="318" x="23" y="187.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="23" x2="341" y1="214.25" y2="214.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="107" x="128.5" y="205.9482">SendToWorker</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="298" x="28" y="230.3887">Puts structured data into workers MessageBuffer.</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="157.5" y="323.9482">output</text><ellipse cx="182" cy="304.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="186.3891" x2="178.6109" y1="309.3422" y2="301.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="186.3891" x2="178.6109" y1="301.564" y2="309.3422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="94.5" y="356.6514">DMAMessageBuffer</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="158" y="371.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="170" x2="170" y1="371.9531" y2="383.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="182" x2="182" y1="371.9531" y2="383.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="194" x2="194" y1="371.9531" y2="383.9531"/><g id="CellularWorker.ATParser"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50.2656" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="154" x="105" y="449.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="105" x2="259" y1="476.25" y2="476.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64" x="150" y="467.9482">ATParser</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="134" x="110" y="492.3887">Parses URC packages.</text></g><g id="CellularWorker.CmdAwaitingResponse"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="185" x="89.5" y="560.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="89.5" x2="274.5" y1="587.25" y2="587.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="165" x="99.5" y="578.9482">CmdAwaitingResponse</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="102" x="255" y="950.9482">outputWorker</text><ellipse cx="306" cy="931.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="310.3891" x2="302.6109" y1="936.3422" y2="928.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="310.3891" x2="302.6109" y1="928.564" y2="936.3422"/><g id="CellularWorker.CheckIfFOTA"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="113" x="125.5" y="687.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="125.5" x2="238.5" y1="714.25" y2="714.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="93" x="135.5" y="705.9482">CheckIfFOTA</text></g><g id="CellularWorker.StoreURC"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="89" x="45.5" y="814.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="45.5" x2="134.5" y1="841.25" y2="841.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="69" x="55.5" y="832.9482">StoreURC</text></g><g id="CellularWorker.FotaService"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="105" x="169.5" y="814.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="169.5" x2="274.5" y1="841.25" y2="841.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="85" x="179.5" y="832.9482">FotaService</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64" x="256" y="983.6514">ATBuffer</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="282" y="998.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="294" x2="294" y1="998.9531" y2="1010.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="306" x2="306" y1="998.9531" y2="1010.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="318" x2="318" y1="998.9531" y2="1010.9531"/><g id="Channel.ATStream"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50.2656" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="141" x="235.5" y="1076.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="235.5" x2="376.5" y1="1103.25" y2="1103.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="72" x="270" y="1094.9482">ATStream</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="121" x="240.5" y="1119.3887">parses AT message</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="107" x="252.5" y="1212.9482">channelOutput</text><ellipse cx="306" cy="1193.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="310.3891" x2="302.6109" y1="1198.3422" y2="1190.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="310.3891" x2="302.6109" y1="1190.564" y2="1198.3422"/><g id="ServiceCellular"><rect fill="#FEFECE" filter="url(#f1cg90pa4di60m)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="126" x="243" y="1260.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="243" x2="369" y1="1287.25" y2="1287.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="106" x="253" y="1278.9482">ServiceCellular</text></g><!--MD5=[a57b3170d04d2bd212a327163f4c8137]
+link UartIrq to SendToWorker--><path d="M182,127.0431 C182,144.3131 182,165.6731 182,182.6531 " fill="none" id="UartIrq-to-SendToWorker" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="182,187.7731,186,178.7731,182,182.7731,178,178.7731,182,187.7731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[12c5ee31291134eacafef3eedf3c1f48]
+link SendToWorker to output--><path d="M182,238.0731 C182,256.2931 182,280.3931 182,293.8131 " fill="none" id="SendToWorker-to-output" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="182,298.8631,186,289.8631,182,293.8631,178,289.8631,182,298.8631" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[e932264d0d3e1dc4eecdd1ce9c7fd236]
+link DMAMessageBuffer to ATParser--><path d="M182,384.0611 C182,395.3351 182,423.0731 182,444.7801 " fill="none" id="DMAMessageBuffer-to-ATParser" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="182,449.8731,186,440.8731,182,444.8731,178,440.8731,182,449.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[13a40670c7eb8b170560bd331fd78e1e]
+link ATParser to CmdAwaitingResponse--><path d="M182,500.1441 C182,516.5131 182,538.2321 182,555.5931 " fill="none" id="ATParser-to-CmdAwaitingResponse" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="182,560.8301,186,551.8301,182,555.8301,178,551.8301,182,560.8301" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[777abd894339136b04c29cf487b6773b]
+link CmdAwaitingResponse to outputWorker--><path d="M203.533,611.0751 C219.963,630.5941 242.074,659.4351 256,687.9531 C296.557,771.0041 304.253,885.5621 305.682,920.4531 " fill="none" id="CmdAwaitingResponse-to-outputWorker" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="305.872,925.6871,309.5401,916.5468,305.6891,920.6905,301.5455,916.8395,305.872,925.6871" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="289" y="781.02">True</text><!--MD5=[8a7a058cbacea9da7579bb2851695ae5]
+link CmdAwaitingResponse to CheckIfFOTA--><path d="M168.072,611.1631 C163.609,620.2081 159.244,630.7631 157,640.9531 C153.871,655.1611 158.191,670.4391 164.073,683.1691 " fill="none" id="CmdAwaitingResponse-to-CheckIfFOTA" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="166.3,687.7371,165.9509,677.8945,164.1086,683.2429,158.7601,681.4007,166.3,687.7371" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="33" x="158" y="654.02">False</text><!--MD5=[fd94f81ce2f3862349c63c5a12cf90a3]
+link CheckIfFOTA to StoreURC--><path d="M155.402,738.1951 C146.442,747.0751 136.758,757.5161 129,767.9531 C119.287,781.0221 110.382,796.7921 103.541,810.1471 " fill="none" id="CheckIfFOTA-to-StoreURC" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="101.117,814.9491,108.7436,808.7173,103.3702,810.4856,101.6019,805.1122,101.117,814.9491" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="33" x="130" y="781.02">False</text><!--MD5=[2bf7f23f6b2f1fdfd1cbf2b79eff56c5]
+link CheckIfFOTA to FotaService--><path d="M174.406,737.9881 C171.221,752.0771 169.4,769.9881 175,784.9531 C178.492,794.2831 184.405,803.0651 190.88,810.7271 " fill="none" id="CheckIfFOTA-to-FotaService" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="194.524,814.8641,191.5787,805.466,191.2199,811.1114,185.5744,810.7526,194.524,814.8641" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="176" y="781.02">True</text><!--MD5=[460a876a9029e334c616b58fb8501c7e]
+link output to DMAMessageBuffer--><path d="M182,311.0591 C182,322.7261 182,351.5151 182,366.8911 " fill="none" id="output-to-DMAMessageBuffer" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="182,371.8931,186,362.8931,182,366.8931,178,362.8931,182,371.8931" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[f66c76729024c907a3d48f760668579d]
+link ATBuffer to ATStream--><path d="M306,1011.0611 C306,1022.3351 306,1050.0731 306,1071.7801 " fill="none" id="ATBuffer-to-ATStream" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="306,1076.8731,310,1067.8731,306,1071.8731,302,1067.8731,306,1076.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[dd80df3ee72f240316d7675a269eb8c4]
+link ATStream to channelOutput--><path d="M306,1127.0711 C306,1145.2951 306,1169.3901 306,1182.8131 " fill="none" id="ATStream-to-channelOutput" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="306,1187.8641,310,1178.8641,306,1182.8641,302,1178.8641,306,1187.8641" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[8fe72049e9716dbce24d7677e0dd4d3e]
+link outputWorker to ATBuffer--><path d="M306,938.0591 C306,949.7261 306,978.5151 306,993.8911 " fill="none" id="outputWorker-to-ATBuffer" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="306,998.8931,310,989.8931,306,993.8931,302,989.8931,306,998.8931" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[4663c35d14db62ee482ccec530d01964]
+link channelOutput to ServiceCellular--><path d="M306,1200.0501 C306,1210.6081 306,1235.5673 306,1255.7077 " fill="none" id="channelOutput-to-ServiceCellular" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="306,1260.7127,310,1251.7127,306,1255.7127,302,1251.7127,306,1260.7127" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[8213d0f92b754f55ac336ef108bd4edb]
+@startuml
+Title AT Mode
+
+state CellularBSP {
+ UartIrq: Reads data with DMA to static buffer
+ UartIrq: and packs them into struct with result code.
+ UartIrq - -> SendToWorker
+ SendToWorker: Puts structured data into workers MessageBuffer.
+ SendToWorker - -> output
+
+ state output <<exitPoint>>
+}
+
+state CellularWorker{
+ state DMAMessageBuffer <<expansionInput>>
+
+ DMAMessageBuffer - -> ATParser
+ ATParser: Parses URC packages.
+ ATParser - -> CmdAwaitingResponse
+
+ state CmdAwaitingResponse <<choice>>
+ CmdAwaitingResponse - - - -> outputWorker : True
+ CmdAwaitingResponse - -> CheckIfFOTA : False
+
+ CheckIfFOTA - -> StoreURC : False
+ CheckIfFOTA - -> FotaService : True
+
+ state outputWorker <<exitPoint>>
+}
+
+output - -> DMAMessageBuffer
+
+state Channel {
+ state ATBuffer <<expansionInput>>
+
+ ATBuffer - -> ATStream
+ ATStream: parses AT message
+
+ ATStream - -> channelOutput
+
+ state channelOutput <<exitPoint>>
+}
+
+outputWorker - -> ATBuffer
+channelOutput - -> ServiceCellular
+@enduml
+
+PlantUML version 1.2021.4beta1(Unknown compile time)
+(GPL source distribution)
+Java Runtime: Java(TM) SE Runtime Environment
+JVM: Java HotSpot(TM) 64-Bit Server VM
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg><
\ No newline at end of file
A module-cellular/Modem/doc/Images/at_mode.uml => module-cellular/Modem/doc/Images/at_mode.uml +46 -0
@@ 0,0 1,46 @@
+@startuml
+Title AT Mode
+
+state CellularBSP {
+ UartIrq: Reads data with DMA to static buffer
+ UartIrq: and packs them into struct with result code.
+ UartIrq --> SendToWorker
+ SendToWorker: Puts structured data into workers MessageBuffer.
+ SendToWorker --> output
+
+ state output <<exitPoint>>
+}
+
+state CellularWorker{
+ state DMAMessageBuffer <<expansionInput>>
+
+ DMAMessageBuffer --> ATParser
+ ATParser: Parses URC packages.
+ ATParser --> CmdAwaitingResponse
+
+ state CmdAwaitingResponse <<choice>>
+ CmdAwaitingResponse ----> outputWorker : True
+ CmdAwaitingResponse --> CheckIfFOTA : False
+
+ CheckIfFOTA --> StoreURC : False
+ CheckIfFOTA --> FotaService : True
+
+ state outputWorker <<exitPoint>>
+}
+
+output --> DMAMessageBuffer
+
+state Channel {
+ state ATBuffer <<expansionInput>>
+
+ ATBuffer --> ATStream
+ ATStream: parses AT message
+
+ ATStream --> channelOutput
+
+ state channelOutput <<exitPoint>>
+}
+
+outputWorker --> ATBuffer
+channelOutput --> ServiceCellular
+@enduml
A module-cellular/Modem/doc/Images/cellular_mux_read.png => module-cellular/Modem/doc/Images/cellular_mux_read.png +0 -0
A module-cellular/Modem/doc/Images/cellular_result_struct.png => module-cellular/Modem/doc/Images/cellular_result_struct.png +0 -0
A module-cellular/Modem/doc/Images/cellular_result_struct.uml => module-cellular/Modem/doc/Images/cellular_result_struct.uml +9 -0
@@ 0,0 1,9 @@
+@startuml
+object CellularResultStruct {
+ CellularResultCode resultCode
+ vector<uint8_t> data
+
+ +std::shared_ptr<uint8_t> serialize()
+ +void deserialize(serialized, size)
+}
+@enduml
A module-cellular/Modem/doc/Images/cmx_mode.uml => module-cellular/Modem/doc/Images/cmx_mode.uml +70 -0
@@ 0,0 1,70 @@
+@startuml
+Title CMUX Mode
+
+state CellularBSP {
+ UartIrq: Reads data with DMA to static buffer
+ UartIrq: and packs them into struct with result code.
+ UartIrq --> SendToWorker
+ SendToWorker: Puts structured data into workers MessageBuffer.
+ SendToWorker --> output
+
+ state output <<exitPoint>>
+}
+
+state CellularWorker{
+ state DMAMessageBuffer <<expansionInput>>
+
+ DMAMessageBuffer --> ATParser
+ ATParser: Parses URC packages.
+ ATParser --> CmdAwaitingResponse
+
+ state CmdAwaitingResponse <<choice>>
+ CmdAwaitingResponse ----> workerOutput : True
+ CmdAwaitingResponse --> callback : False
+
+ state workerOutput <<exitPoint>>
+}
+
+state Notifications {
+ state input1 <<expansionInput>>
+
+ input1 --> ATStream1
+
+ ATStream1 --> output1
+
+ state output1 <<exitPoint>>
+}
+
+state Commands {
+ state input2 <<expansionInput>>
+
+ input2 --> ATStream2
+
+ ATStream2 --> output2
+
+ state output2 <<exitPoint>>
+}
+
+state Data {
+ state input3 <<expansionInput>>
+
+ input3 --> ATStream3
+
+ ATStream3 --> output3
+
+ state output3 <<exitPoint>>
+}
+
+state channelsFork <<fork>>
+state channelsJoin <<join>>
+
+output --> DMAMessageBuffer : Result{data,resultCode}
+workerOutput --> channelsFork
+channelsFork --> input1
+channelsFork --> input2
+channelsFork --> input3
+output1 --> channelsJoin
+output2 --> channelsJoin
+output3 --> channelsJoin
+channelsJoin --> ServiceCellular : Result{parsedData,resultCode}
+@enduml
A module-cellular/Modem/doc/Images/dma_result_struct.png => module-cellular/Modem/doc/Images/dma_result_struct.png +0 -0
A module-cellular/Modem/doc/Images/dma_result_struct.uml => module-cellular/Modem/doc/Images/dma_result_struct.uml +7 -0
@@ 0,0 1,7 @@
+@startuml
+object CellularDMAResultStruct {
+ CellularResultCode resultCode
+ size_t dataSize
+ uint8_t data[CellularResultStructMaxDataSize]
+}
+@enduml
A module-cellular/Modem/doc/Images/mux_mode.svg => module-cellular/Modem/doc/Images/mux_mode.svg +106 -0
@@ 0,0 1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="application/ecmascript" contentStyleType="text/css" height="1445px" preserveAspectRatio="none" style="width:435px;height:1445px;" version="1.1" viewBox="0 0 435 1445" width="435px" zoomAndPan="magnify"><defs><filter height="300%" id="f342a3rt0b12s" width="300%" x="-1" y="-1"><feGaussianBlur result="blurOut" stdDeviation="2.0"/><feColorMatrix in="blurOut" result="blurOut2" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .4 0"/><feOffset dx="4.0" dy="4.0" in="blurOut2" result="blurOut3"/><feBlend in="SourceGraphic" in2="blurOut3" mode="normal"/></filter></defs><g><text fill="#000000" font-family="sans-serif" font-size="18" lengthAdjust="spacing" textLength="109" x="156.5" y="16.708">CMUX Mode</text><!--MD5=[36105e52843f3f28080f43ce369346ca]
+cluster CellularBSP--><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="277" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="350" x="12" y="27.9531"/><rect fill="#FFFFFF" height="244.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="344" x="15" y="57.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="12" x2="362" y1="54.25" y2="54.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="81" x="146.5" y="45.9482">CellularBSP</text><!--MD5=[4feec3315c2ae8fe0f31fdbe0936cbea]
+cluster CellularWorker--><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="505" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="218" x="78" y="393.9531"/><rect fill="#FFFFFF" height="472.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="212" x="81" y="423.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="78" x2="296" y1="420.25" y2="420.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="106" x="134" y="411.9482">CellularWorker</text><!--MD5=[a878dacc166bb130104221e452026b76]
+cluster Notifications--><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="189" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="134" x="7" y="1040.9531"/><rect fill="#FFFFFF" height="156.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="128" x="10" y="1070.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="7" x2="141" y1="1067.25" y2="1067.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="92" x="28" y="1058.9482">Notifications</text><!--MD5=[7c76d2c3a8a2b6b7f38b9d3310256c36]
+cluster Commands--><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="189" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="132" x="149" y="1040.9531"/><rect fill="#FFFFFF" height="156.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="126" x="152" y="1070.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="149" x2="281" y1="1067.25" y2="1067.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="175" y="1058.9482">Commands</text><!--MD5=[f21b1f164e99c6b37934f23ad048ad54]
+cluster Data--><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="189" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="134" x="289" y="1040.9531"/><rect fill="#FFFFFF" height="156.7031" rx="12.5" ry="12.5" style="stroke:#FFFFFF;stroke-width:1.0;" width="128" x="292" y="1070.25"/><line style="stroke:#A80036;stroke-width:1.5;" x1="289" x2="423" y1="1067.25" y2="1067.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="34" x="339" y="1058.9482">Data</text><g id="CellularBSP.UartIrq"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="64.2344" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="284" x="45" y="62.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="45" x2="329" y1="89.25" y2="89.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="162.5" y="80.9482">UartIrq</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="218" x="50" y="105.3887">Reads data with DMA to static buffer</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="264" x="50" y="119.3574">and packs them into struct with result code.</text></g><g id="CellularBSP.SendToWorker"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50.2656" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="318" x="28" y="187.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="28" x2="346" y1="214.25" y2="214.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="107" x="133.5" y="205.9482">SendToWorker</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="298" x="33" y="230.3887">Puts structured data into workers MessageBuffer.</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="49" x="162.5" y="323.9482">output</text><ellipse cx="187" cy="304.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="191.3891" x2="183.6109" y1="309.3422" y2="301.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="191.3891" x2="183.6109" y1="301.564" y2="309.3422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="139" x="99.5" y="372.6514">DMAMessageBuffer</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="163" y="387.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="175" x2="175" y1="387.9531" y2="399.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="187" x2="187" y1="387.9531" y2="399.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="199" x2="199" y1="387.9531" y2="399.9531"/><g id="CellularWorker.ATParser"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50.2656" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="154" x="110" y="465.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="110" x2="264" y1="492.25" y2="492.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="64" x="155" y="483.9482">ATParser</text><text fill="#000000" font-family="sans-serif" font-size="12" lengthAdjust="spacing" textLength="134" x="115" y="508.3887">Parses URC packages.</text></g><g id="CellularWorker.CmdAwaitingResponse"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="185" x="94.5" y="576.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="94.5" x2="279.5" y1="603.25" y2="603.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="165" x="104.5" y="594.9482">CmdAwaitingResponse</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="101" x="164.5" y="917.9482">workerOutput</text><ellipse cx="215" cy="898.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="219.3891" x2="211.6109" y1="903.3422" y2="895.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="219.3891" x2="211.6109" y1="895.564" y2="903.3422"/><g id="CellularWorker.callback"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="79" x="99.5" y="703.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="99.5" x2="178.5" y1="730.25" y2="730.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="59" x="109.5" y="721.9482">callback</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="47" x="50.5" y="1019.6514">input1</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="68" y="1034.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="80" x2="80" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="92" x2="92" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="104" x2="104" y1="1034.9531" y2="1046.9531"/><g id="Notifications.ATStream1"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="101" x="23.5" y="1112.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="23.5" x2="124.5" y1="1139.25" y2="1139.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="81" x="33.5" y="1130.9482">ATStream1</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="58" x="72" y="1248.9482">output1</text><ellipse cx="101" cy="1229.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="105.3891" x2="97.6109" y1="1234.3422" y2="1226.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="105.3891" x2="97.6109" y1="1226.564" y2="1234.3422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="46" x="174" y="1019.6514">input2</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="191" y="1034.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="203" x2="203" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="215" x2="215" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="227" x2="227" y1="1034.9531" y2="1046.9531"/><g id="Commands.ATStream2"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="100" x="165" y="1112.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="165" x2="265" y1="1139.25" y2="1139.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="80" x="175" y="1130.9482">ATStream2</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="57" x="186.5" y="1248.9482">output2</text><ellipse cx="215" cy="1229.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="219.3891" x2="211.6109" y1="1234.3422" y2="1226.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="219.3891" x2="211.6109" y1="1226.564" y2="1234.3422"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="47" x="296.5" y="1019.6514">input3</text><rect fill="#FEFECE" height="12" style="stroke:#A80036;stroke-width:1.5;" width="48" x="314" y="1034.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="326" x2="326" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="338" x2="338" y1="1034.9531" y2="1046.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="350" x2="350" y1="1034.9531" y2="1046.9531"/><g id="Data.ATStream3"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="101" x="305.5" y="1112.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="305.5" x2="406.5" y1="1139.25" y2="1139.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="81" x="315.5" y="1130.9482">ATStream3</text></g><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="58" x="287" y="1248.9482">output3</text><ellipse cx="316" cy="1229.9531" fill="#FEFECE" rx="6" ry="6" style="stroke:#A80036;stroke-width:1.5;"/><line style="stroke:#A80036;stroke-width:1.5;" x1="320.3891" x2="312.6109" y1="1234.3422" y2="1226.564"/><line style="stroke:#A80036;stroke-width:1.5;" x1="320.3891" x2="312.6109" y1="1226.564" y2="1234.3422"/><rect fill="#000000" filter="url(#f342a3rt0b12s)" height="8" style="stroke:none;stroke-width:1.0;" width="80" x="175" y="965.9531"/><rect fill="#000000" filter="url(#f342a3rt0b12s)" height="8" style="stroke:none;stroke-width:1.0;" width="80" x="175" y="1296.9531"/><g id="ServiceCellular"><rect fill="#FEFECE" filter="url(#f342a3rt0b12s)" height="50" rx="12.5" ry="12.5" style="stroke:#A80036;stroke-width:1.5;" width="126" x="152" y="1381.9531"/><line style="stroke:#A80036;stroke-width:1.5;" x1="152" x2="278" y1="1408.25" y2="1408.25"/><text fill="#000000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="106" x="162" y="1399.9482">ServiceCellular</text></g><!--MD5=[a57b3170d04d2bd212a327163f4c8137]
+link UartIrq to SendToWorker--><path d="M187,127.0431 C187,144.3131 187,165.6731 187,182.6531 " fill="none" id="UartIrq-to-SendToWorker" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="187,187.7731,191,178.7731,187,182.7731,183,178.7731,187,187.7731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[12c5ee31291134eacafef3eedf3c1f48]
+link SendToWorker to output--><path d="M187,238.0731 C187,256.2931 187,280.3931 187,293.8131 " fill="none" id="SendToWorker-to-output" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="187,298.8631,191,289.8631,187,293.8631,183,289.8631,187,298.8631" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[e932264d0d3e1dc4eecdd1ce9c7fd236]
+link DMAMessageBuffer to ATParser--><path d="M187,400.0631 C187,411.3331 187,439.0731 187,460.7801 " fill="none" id="DMAMessageBuffer-to-ATParser" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="187,465.8731,191,456.8731,187,460.8731,183,456.8731,187,465.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[13a40670c7eb8b170560bd331fd78e1e]
+link ATParser to CmdAwaitingResponse--><path d="M187,516.1441 C187,532.5131 187,554.2321 187,571.5931 " fill="none" id="ATParser-to-CmdAwaitingResponse" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="187,576.8301,191,567.8301,187,571.8301,183,567.8301,187,576.8301" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[9a2733e9d3d9be03a03451908a1ba3d9]
+link CmdAwaitingResponse to workerOutput--><path d="M189.291,627.0941 C195.068,687.9511 210.046,845.7621 214.02,887.6301 " fill="none" id="CmdAwaitingResponse-to-workerOutput" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="214.524,892.9411,217.6549,883.6032,214.0511,887.9635,209.6907,884.3598,214.524,892.9411" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="29" x="207" y="797.02">True</text><!--MD5=[d46098a13406a974ef8f13d074dfa6c4]
+link CmdAwaitingResponse to callback--><path d="M153.482,626.9631 C144.458,635.3271 135.859,645.5171 131,656.9531 C125.476,669.9541 126.45,685.4391 129.233,698.6241 " fill="none" id="CmdAwaitingResponse-to-callback" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="130.427,703.7431,132.2785,694.0699,129.2914,698.8738,124.4875,695.8868,130.427,703.7431" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="33" x="132" y="670.02">False</text><!--MD5=[5af6ce0d04d61de9b9e76368ba5a826e]
+link input1 to ATStream1--><path d="M91.0322,1047.0611 C88.896,1058.3351 83.6403,1086.0731 79.5275,1107.7801 " fill="none" id="input1-to-ATStream1" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="78.5625,1112.8731,84.1668,1104.7742,79.4925,1107.9604,76.3064,1103.2862,78.5625,1112.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[8f490082540074d4ee2ef1a6e118265e]
+link ATStream1 to output1--><path d="M81.2355,1163.0711 C86.7027,1181.2951 93.9312,1205.3901 97.9581,1218.8131 " fill="none" id="ATStream1-to-output1" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="99.473,1223.8641,100.7176,1214.0942,98.036,1219.0751,93.0551,1216.3935,99.473,1223.8641" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[0988824bf8ec7c59907bef1cbce29abd]
+link input2 to ATStream2--><path d="M215,1047.0611 C215,1058.3351 215,1086.0731 215,1107.7801 " fill="none" id="input2-to-ATStream2" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,1112.8731,219,1103.8731,215,1107.8731,211,1103.8731,215,1112.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[6ea5f7ac2ff21e3e6e6f599ed58b1881]
+link ATStream2 to output2--><path d="M215,1163.0711 C215,1181.2951 215,1205.3901 215,1218.8131 " fill="none" id="ATStream2-to-output2" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,1223.8641,219,1214.8641,215,1218.8641,211,1214.8641,215,1223.8641" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[c8610ed9c90908ab582e2197c703e61b]
+link input3 to ATStream3--><path d="M338.968,1047.0611 C341.104,1058.3351 346.36,1086.0731 350.473,1107.7801 " fill="none" id="input3-to-ATStream3" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="351.437,1112.8731,353.6932,1103.2862,350.507,1107.9604,345.8328,1104.7742,351.437,1112.8731" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[d41c41dd4852fd322b9dd1ba5228125c]
+link ATStream3 to output3--><path d="M345.281,1163.0711 C337.027,1181.6421 326.064,1206.3091 320.171,1219.5671 " fill="none" id="ATStream3-to-output3" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="318.111,1224.2031,325.4202,1217.6019,320.1408,1219.6337,318.109,1214.3543,318.111,1224.2031" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[460a876a9029e334c616b58fb8501c7e]
+link output to DMAMessageBuffer--><path d="M187,311.1331 C187,325.1931 187,364.2331 187,382.8431 " fill="none" id="output-to-DMAMessageBuffer" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="187,387.9031,191,378.9031,187,382.9031,183,378.9031,187,387.9031" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="160" x="188" y="354.02">Result{data,resultCode}</text><!--MD5=[613d73f2a6b0064d130614cb72f0ee69]
+link workerOutput to channelsFork--><path d="M215,905.3671 C215,917.3761 215,946.3111 215,960.6341 " fill="none" id="workerOutput-to-channelsFork" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,965.7861,219,956.7861,215,960.7861,211,956.7861,215,965.7861" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[2d19209ccd932d018b2d06ef9fb86c8f]
+link channelsFork to input1--><path d="M209.395,974.0971 C191.079,984.3721 132.623,1017.1641 105.751,1032.2391 " fill="none" id="channelsFork-to-input1" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="101.118,1034.8381,110.9241,1033.9212,105.4782,1032.3909,107.0085,1026.945,101.118,1034.8381" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[5fac8884c6f6b68b192a3cbb904f8716]
+link channelsFork to input2--><path d="M215,974.2811 C215,984.1591 215,1013.6091 215,1029.5041 " fill="none" id="channelsFork-to-input2" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,1034.6851,219,1025.6851,215,1029.6851,211,1025.6851,215,1034.6851" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[3c5d7806c110bbdbc69ac9b51157b004]
+link channelsFork to input3--><path d="M220.605,974.0971 C238.921,984.3721 297.377,1017.1641 324.249,1032.2391 " fill="none" id="channelsFork-to-input3" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="328.882,1034.8381,322.9915,1026.945,324.5218,1032.3909,319.0759,1033.9212,328.882,1034.8381" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[11b55a60e505a1d49558f29f7757b5a7]
+link output1 to channelsJoin--><path d="M105.898,1233.9181 C123.325,1244.4661 182.507,1280.2861 205.632,1294.2831 " fill="none" id="output1-to-channelsJoin" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="209.991,1296.9211,204.3612,1288.84,205.713,1294.3329,200.2201,1295.6847,209.991,1296.9211" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[920d51171ddf142c6b023bfa2e85b080]
+link output2 to channelsJoin--><path d="M215,1236.3671 C215,1248.3761 215,1277.3111 215,1291.6341 " fill="none" id="output2-to-channelsJoin" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,1296.7861,219,1287.7861,215,1291.7861,211,1287.7861,215,1296.7861" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[78d2c976a325450ffc8758782f6c5ecd]
+link output3 to channelsJoin--><path d="M311.398,1234.0971 C295.755,1244.7841 244.462,1279.8261 223.77,1293.9621 " fill="none" id="output3-to-channelsJoin" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="219.629,1296.7901,229.3169,1295.0169,223.7578,1293.97,224.8047,1288.4108,219.629,1296.7901" style="stroke:#A80036;stroke-width:1.0;"/><!--MD5=[a54a1b5c1c5e133ff80d5fe379df8844]
+link channelsJoin to ServiceCellular--><path d="M215,1304.9531 C215,1315.3821 215,1350.8308 215,1376.7961 " fill="none" id="channelsJoin-to-ServiceCellular" style="stroke:#A80036;stroke-width:1.0;"/><polygon fill="#A80036" points="215,1381.8525,219,1372.8525,215,1376.8525,211,1372.8525,215,1381.8525" style="stroke:#A80036;stroke-width:1.0;"/><text fill="#000000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="206" x="216" y="1348.02">Result{parsedData,resultCode}</text><!--MD5=[1ca860d6e5dd9ee4bdeadd232ce293fa]
+@startuml
+Title CMUX Mode
+
+state CellularBSP {
+ UartIrq: Reads data with DMA to static buffer
+ UartIrq: and packs them into struct with result code.
+ UartIrq - -> SendToWorker
+ SendToWorker: Puts structured data into workers MessageBuffer.
+ SendToWorker - -> output
+
+ state output <<exitPoint>>
+}
+
+state CellularWorker{
+ state DMAMessageBuffer <<expansionInput>>
+
+ DMAMessageBuffer - -> ATParser
+ ATParser: Parses URC packages.
+ ATParser - -> CmdAwaitingResponse
+
+ state CmdAwaitingResponse <<choice>>
+ CmdAwaitingResponse - - - -> workerOutput : True
+ CmdAwaitingResponse - -> callback : False
+
+ state workerOutput <<exitPoint>>
+}
+
+state Notifications {
+ state input1 <<expansionInput>>
+
+ input1 - -> ATStream1
+
+ ATStream1 - -> output1
+
+ state output1 <<exitPoint>>
+}
+
+state Commands {
+ state input2 <<expansionInput>>
+
+ input2 - -> ATStream2
+
+ ATStream2 - -> output2
+
+ state output2 <<exitPoint>>
+}
+
+state Data {
+ state input3 <<expansionInput>>
+
+ input3 - -> ATStream3
+
+ ATStream3 - -> output3
+
+ state output3 <<exitPoint>>
+}
+
+state channelsFork <<fork>>
+state channelsJoin <<join>>
+
+output - -> DMAMessageBuffer : Result{data,resultCode}
+workerOutput - -> channelsFork
+channelsFork - -> input1
+channelsFork - -> input2
+channelsFork - -> input3
+output1 - -> channelsJoin
+output2 - -> channelsJoin
+output3 - -> channelsJoin
+channelsJoin - -> ServiceCellular : Result{parsedData,resultCode}
+@enduml
+
+PlantUML version 1.2021.4beta1(Unknown compile time)
+(GPL source distribution)
+Java Runtime: Java(TM) SE Runtime Environment
+JVM: Java HotSpot(TM) 64-Bit Server VM
+Default Encoding: UTF-8
+Language: en
+Country: US
+--></g></svg><
\ No newline at end of file
A module-cellular/Modem/doc/Images/single_cmd.uml => module-cellular/Modem/doc/Images/single_cmd.uml +24 -0
@@ 0,0 1,24 @@
+@startuml
+title Single cmd processing
+
+participant IRQ order 1
+participant BSP order 2
+participant CellularWorker order 3
+participant Channel order 4
+participant Service order 5
+
+CellularWorker -> BSP: Read()
+rnote over CellularWorker: Wait for data in MessageBuffer
+Service -> Channel: cmd()
+activate CellularWorker
+Channel -> BSP : Write()
+rnote over Channel: Wait for cmd response in MessageBuffer
+activate Channel
+rnote over IRQ: DMA received data
+IRQ -> CellularWorker: MessageBufferSendFromISR()
+rnote over CellularWorker: processData()
+CellularWorker -> Channel: MessageBufferSend()
+rnote over Channel: Parse response
+deactivate Channel
+Channel -> Service: Result
+@enduml
A module-cellular/Modem/doc/Images/single_cmd_transmission.png => module-cellular/Modem/doc/Images/single_cmd_transmission.png +0 -0
M module-cellular/at/Result.hpp => module-cellular/at/Result.hpp +14 -9
@@ 16,15 16,20 @@ namespace at
/// result class for AT send -> receive command, could return promise :p
enum class Code
{
- OK, /// at OK
- ERROR, /// at ERROR For compatibility also for CME_ERROR and CMS_ERROR (details in errorCode)
- CME_ERROR, /// In case CME error see errorCode
- CMS_ERROR, /// In case CMS error see errorCode
- TIMEOUT, /// at Timeout
- TOKENS, /// at numbers of tokens needed met
- NONE, /// no code
- UNDEFINED, /// undefined result - usage of Undefined result, define and pin result to use it
- PARSING_ERROR, /// parser error
+ OK, /// at OK
+ ERROR, /// at ERROR For compatibility also for CME_ERROR and CMS_ERROR (details in errorCode)
+ CME_ERROR, /// In case CME error see errorCode
+ CMS_ERROR, /// In case CMS error see errorCode
+ TIMEOUT, /// at Timeout
+ TOKENS, /// at numbers of tokens needed met
+ NONE, /// no code
+ UNDEFINED, /// undefined result - usage of Undefined result, define and pin result to use it
+ PARSING_ERROR, /// parser error
+ FULL_MSG_BUFFER, /// at not enough space left in message buffer for new message
+ TRANSMISSION_NOT_STARTED, /// at dma not starting transmission
+ RECEIVING_NOT_STARTED, /// at dma not starting requested receiving
+ DATA_NOT_USED, /// at received data not being used
+ CMUX_FRAME_ERROR, /// at cmux deserialize error
} code = Code::UNDEFINED;
Result() = default;
M module-cellular/at/src/ATFactory.cpp => module-cellular/at/src/ATFactory.cpp +1 -1
@@ 28,7 28,7 @@ namespace at
{AT::CRC_ON, {"AT+CRC=1"}},
{AT::CALLER_NUMBER_PRESENTATION, {"AT+CLIP=1", default_long_timeout}},
{AT::SMS_TEXT_FORMAT, {"AT+CMGF=1"}},
- {AT::SMS_UCSC2, {"AT+CSCS=\"UCS2\""}},
+ {AT::SMS_UCSC2, {"AT+CSCS=\"UCS2\"", 1s}},
{AT::SMS_GSM, {"AT+CSCS=\"GSM\""}},
{AT::QSCLK_ON, {"AT+QSCLK=1"}},
{AT::QDAI, {"AT+QDAI?"}},
M module-cellular/test/CMakeLists.txt => module-cellular/test/CMakeLists.txt +10 -1
@@ 46,7 46,6 @@ add_catch2_executable(
module-cellular
)
-
add_catch2_executable(
NAME
unittest_ATURCStream
@@ 55,3 54,13 @@ add_catch2_executable(
LIBS
module-cellular
)
+
+add_catch2_executable(
+ NAME
+ unittest_CellularResult
+ SRCS
+ unittest_CellularResult.cpp
+ LIBS
+ module-cellular
+ module-bsp
+)
M module-cellular/test/mock/AtCommon_channel.hpp => module-cellular/test/mock/AtCommon_channel.hpp +4 -4
@@ 41,7 41,7 @@ namespace at
void cmd_post() override
{}
- std::string cmd_receive() override
+ size_t cmd_receive(std::uint8_t *buffer, std::chrono::milliseconds timeoutMs) override
{
return {};
}
@@ 49,7 49,7 @@ namespace at
class FailingChannel : public ChannelMock
{
- virtual Result ResultMock()
+ auto ResultMock() -> Result override
{
auto r = Result();
r.code = Result::Code::ERROR;
@@ 75,7 75,7 @@ namespace at
/// provides CSCS bad response
class CSCS_badChannel : public ChannelMock
{
- virtual Result ResultMock()
+ auto ResultMock() -> Result override
{
auto r = Result();
r.code = Result::Code::ERROR;
@@ 87,7 87,7 @@ namespace at
/// standard bad CSCA values I get from modem (with result OK)
class CSCA_emptyData : public ChannelMock
{
- virtual Result ResultMock()
+ auto ResultMock() -> Result override
{
auto r = Result();
r.code = Result::Code::OK;
A module-cellular/test/unittest_CellularResult.cpp => module-cellular/test/unittest_CellularResult.cpp +72 -0
@@ 0,0 1,72 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#define CATCH_CONFIG_MAIN
+
+#include <catch2/catch.hpp>
+#include <module-bsp/bsp/cellular/CellularResult.hpp>
+
+TEST_CASE("CellularResult")
+{
+ SECTION("CellularDMAResultStruct")
+ {
+ bsp::cellular::CellularDMAResultStruct cellularDmaResultStruct;
+
+ auto maxSize = bsp::cellular::CellularResultStructMaxDataSize + sizeof(cellularDmaResultStruct.resultCode) +
+ sizeof(cellularDmaResultStruct.dataSize);
+
+ REQUIRE(cellularDmaResultStruct.getMaxSize() == maxSize);
+ REQUIRE(cellularDmaResultStruct.resultCode == bsp::cellular::CellularResultCode::ReceivedNoData);
+ REQUIRE(cellularDmaResultStruct.getEmptySize() == maxSize - bsp::cellular::CellularResultStructMaxDataSize);
+ REQUIRE(cellularDmaResultStruct.getSize() == cellularDmaResultStruct.getEmptySize());
+ }
+
+ SECTION("Create CellularResultStruct")
+ {
+ bsp::cellular::CellularResultStruct cellularResultStruct;
+
+ REQUIRE(cellularResultStruct.resultCode == bsp::cellular::CellularResultCode::Uninitialized);
+ REQUIRE(cellularResultStruct.data.empty());
+ }
+
+ SECTION("Serialize empty CellularResultStruct")
+ {
+ bsp::cellular::CellularResultStruct cellularResultStruct;
+
+ auto serialized = cellularResultStruct.serialize();
+ auto serializedResult = serialized.get()[0];
+
+ delete[] serialized.release();
+
+ REQUIRE(cellularResultStruct.getSerializedSize() == sizeof(cellularResultStruct.resultCode));
+ REQUIRE(serializedResult == static_cast<unsigned char>(bsp::cellular::CellularResultCode::Uninitialized));
+ }
+
+ SECTION("Deserialize empty buffer")
+ {
+ bsp::cellular::CellularResultStruct cellularResultStruct;
+
+ uint8_t serialized[0] = {};
+ cellularResultStruct.deserialize(serialized, 0);
+
+ REQUIRE(cellularResultStruct.resultCode == bsp::cellular::CellularResultCode::Uninitialized);
+ REQUIRE(cellularResultStruct.data.empty());
+ }
+
+ SECTION("Serialize and deserialize CellularResultStruct")
+ {
+ bsp::cellular::CellularResultStruct cellularResultStruct;
+ cellularResultStruct.resultCode = bsp::cellular::CellularResultCode::ReceivedAndFull;
+ cellularResultStruct.data = {1, 2, 3, 4, 5, 10};
+
+ auto serialized = cellularResultStruct.serialize();
+
+ bsp::cellular::CellularResultStruct cellularResultStructDeserialized;
+ cellularResultStructDeserialized.deserialize(serialized.get(), cellularResultStruct.getSerializedSize());
+
+ delete[] serialized.release();
+
+ REQUIRE(cellularResultStructDeserialized.resultCode == cellularResultStruct.resultCode);
+ REQUIRE(cellularResultStructDeserialized.data == cellularResultStruct.data);
+ }
+}
M module-cellular/test/unittest_cmux.cpp => module-cellular/test/unittest_cmux.cpp +1 -1
@@ 27,7 27,7 @@ TEST_CASE("TS0170 frame")
TS0710_Frame frame(tempFrame);
REQUIRE(frame.isComplete(frame.getSerData()) == true);
- REQUIRE(frame.isMyChannel(frame.getSerData(), DLCI) == true);
+ REQUIRE(frame.isMyChannel(DLCI) == true);
REQUIRE(frame.getFrameDLCI(frame.getSerData()) == DLCI);
REQUIRE(frame.getSerData().size() == cmuxMinimumFrameLength + command.length());
}
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +21 -14
@@ 263,7 263,7 @@ static bool isSettingsAutomaticTimeSyncEnabled()
void ServiceCellular::SleepTimerHandler()
{
auto currentTime = cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks());
- auto lastCommunicationTimestamp = cmux->GetLastCommunicationTimestamp();
+ auto lastCommunicationTimestamp = cmux->getLastCommunicationTimestamp();
auto timeOfInactivity = currentTime >= lastCommunicationTimestamp
? currentTime - lastCommunicationTimestamp
: std::numeric_limits<TickType_t>::max() - lastCommunicationTimestamp + currentTime;
@@ 372,8 372,8 @@ void ServiceCellular::registerMessageHandlers()
connect(typeid(CellularChangeSimDataMessage), [&](sys::Message *request) -> sys::MessagePointer {
auto msg = static_cast<CellularChangeSimDataMessage *>(request);
Store::GSM::get()->selected = msg->getSim();
- bsp::cellular::sim::sim_sel();
- bsp::cellular::sim::hotswap_trigger();
+ bsp::cellular::sim::simSelect();
+ bsp::cellular::sim::hotSwapTrigger();
return std::make_shared<CellularResponseMessage>(true);
});
@@ 470,7 470,7 @@ void ServiceCellular::registerMessageHandlers()
}
if (typeid(*msg->event.get()) == typeid(sdesktop::developerMode::CellularSleepModeInfoRequestEvent)) {
auto event = std::make_unique<sdesktop::developerMode::CellularSleepModeInfoRequestEvent>(
- cmux->IsCellularInSleepMode());
+ cmux->isCellularInSleepMode());
auto message = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
bus.sendUnicast(std::move(message), service::name::service_desktop);
}
@@ 937,7 937,7 @@ bool ServiceCellular::handle_audio_conf_procedure()
state.set(this, State::ST::Failed);
return false;
}
- cmux->getCellular()->SetSpeed(ATPortSpeeds_text[cmux->getStartParams().PortSpeed]);
+ cmux->getCellular()->setSpeed(ATPortSpeeds_text[cmux->getStartParams().PortSpeed]);
vTaskDelay(1000);
if (cmux->StartMultiplexer() == TS0710::ConfState::Success) {
@@ 1316,8 1316,7 @@ auto ServiceCellular::sendSMS(SMSRecord record) -> bool
std::string body = UCS2(UTF8(receiver)).str();
std::string suffix = "\"";
std::string command_data = command + body + suffix;
- if (cmux->CheckATCommandPrompt(
- channel->SendCommandPrompt(command_data.c_str(), 1, commandTimeout.count()))) {
+ if (cmux->CheckATCommandPrompt(channel->SendCommandPrompt(command_data.c_str(), 1, commandTimeout))) {
if (channel->cmd((UCS2(record.body).str() + "\032").c_str(), commandTimeout)) {
result = true;
@@ 1355,8 1354,7 @@ auto ServiceCellular::sendSMS(SMSRecord record) -> bool
std::string command(at::factory(at::AT::QCMGS) + UCS2(UTF8(receiver)).str() + "\",120," +
std::to_string(i + 1) + "," + std::to_string(messagePartsCount));
- if (cmux->CheckATCommandPrompt(
- channel->SendCommandPrompt(command.c_str(), 1, commandTimeout.count()))) {
+ if (cmux->CheckATCommandPrompt(channel->SendCommandPrompt(command.c_str(), 1, commandTimeout))) {
// prompt sign received, send data ended by "Ctrl+Z"
if (channel->cmd(UCS2(messagePart).str() + "\032", commandTimeout, 2)) {
result = true;
@@ 1398,6 1396,8 @@ auto ServiceCellular::sendSMS(SMSRecord record) -> bool
auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
{
+ constexpr auto ucscSetMaxRetries = 3;
+
auto retVal = true;
auto channel = cmux->get(TS0710::Channel::Commands);
@@ 1406,8 1406,15 @@ auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
return retVal;
}
- if (!channel->cmd(at::AT::SMS_UCSC2)) {
- LOG_ERROR("Could not set UCS2 charset mode for TE");
+ auto ucscSetRetries = 0;
+ while (ucscSetRetries < ucscSetMaxRetries) {
+ if (!channel->cmd(at::AT::SMS_UCSC2)) {
+ ++ucscSetRetries;
+ LOG_ERROR("Could not set UCS2 charset mode for TE. Retry %d", ucscSetRetries);
+ }
+ else {
+ break;
+ }
}
auto _ = gsl::finally([&channel, &retVal, &messageNumber] {
if (!channel->cmd(at::AT::SMS_GSM)) {
@@ 1706,7 1713,7 @@ bool ServiceCellular::handle_sim_sanity_check()
auto ret = sim_check_hot_swap(cmux->get(TS0710::Channel::Commands));
if (ret) {
state.set(this, State::ST::ModemOn);
- bsp::cellular::sim::sim_sel();
+ bsp::cellular::sim::simSelect();
}
else {
LOG_ERROR("Sanity check failure - user will be promped about full shutdown");
@@ 1718,8 1725,8 @@ bool ServiceCellular::handle_sim_sanity_check()
bool ServiceCellular::handle_select_sim()
{
- bsp::cellular::sim::sim_sel();
- bsp::cellular::sim::hotswap_trigger();
+ bsp::cellular::sim::simSelect();
+ bsp::cellular::sim::hotSwapTrigger();
#if defined(TARGET_Linux)
DLC_channel *channel = cmux->get(TS0710::Channel::Commands);
auto ret = channel->cmd(at::AT::QSIMSTAT);
M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +1 -1
@@ 170,7 170,7 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
if (notification == bsp::cellular::trayPin) {
Store::GSM::Tray pinstate = bsp::cellular::sim::getTray();
LOG_DEBUG("SIM state change: %d", static_cast<int>(pinstate));
- bsp::cellular::sim::hotswap_trigger();
+ bsp::cellular::sim::hotSwapTrigger();
}
if (notification == bsp::cellular::ringIndicatorPin) {
M module-utils/log/Logger.cpp => module-utils/log/Logger.cpp +2 -2
@@ 11,8 11,8 @@
namespace Log
{
std::map<std::string, logger_level> Logger::filtered = {{"ApplicationManager", logger_level::LOGINFO},
- {"TS0710Worker", logger_level::LOGINFO},
- {"ServiceCellular", logger_level::LOGINFO},
+ {"TS0710Worker", logger_level::LOGTRACE},
+ {"ServiceCellular", logger_level::LOGTRACE},
{"ServiceAntenna", logger_level::LOGINFO},
{"ServiceAudio", logger_level::LOGINFO},
{"ServiceBluetooth", logger_level::LOGINFO},
M module-utils/log/debug.hpp => module-utils/log/debug.hpp +2 -2
@@ 5,10 5,10 @@
#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_CELLULAR_UART 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 1 /// show full modem output
+#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
#define DEBUG_FONT 0 /// show Font debug messages