Adds handshaking timeout to UART link manager
Replaces the exiting semaphore with the CHPP condition variable,
to share the timeout logic used.
Bug: 160899751
Test: Send packet and verify timeout occurs
Change-Id: Ia101192b90b3fb1657efaba3442907ceb1803dc7
diff --git a/chpp/platform/aoc/chpp_uart_link_manager.cc b/chpp/platform/aoc/chpp_uart_link_manager.cc
index aab15ea..e300a71 100644
--- a/chpp/platform/aoc/chpp_uart_link_manager.cc
+++ b/chpp/platform/aoc/chpp_uart_link_manager.cc
@@ -53,10 +53,7 @@
manager->getWakeInGpi()->SetTriggerFunction(GPIAoC::GPI_DISABLE);
manager->getWakeInGpi()->ClearInterrupt();
- BaseType_t xHigherPriorityTaskWoken = 0;
- xSemaphoreGiveFromISR(manager->getSemaphoreHandle(),
- &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ chppConditionVariableSignal(manager->getCondVar());
}
} // anonymous namespace
@@ -68,19 +65,16 @@
mUart(uart),
mWakeOutGpio(wakeOutPinNumber, IP_LOCK_GPIO),
mWakeInGpi(wakeInGpiNumber) {
- mSemaphoreHandle = xSemaphoreCreateBinaryStatic(&mStaticSemaphore);
- if (mSemaphoreHandle == nullptr) {
- FATAL_ERROR("Failed to create cv semaphore");
- }
+ chppMutexInit(&mMutex);
+ chppConditionVariableInit(&mCondVar);
mWakeOutGpio.SetDirection(GPIO::DIRECTION::OUTPUT);
mWakeOutGpio.Clear();
}
UartLinkManager::~UartLinkManager() {
- if (mSemaphoreHandle != nullptr) {
- vSemaphoreDelete(mSemaphoreHandle);
- }
+ chppConditionVariableDeinit(&mCondVar);
+ chppMutexDeinit(&mMutex);
}
void UartLinkManager::init() {
@@ -133,8 +127,10 @@
mWakeInGpi.SetInterruptHandler(onTransactionHandshakeInterrupt, this);
mWakeInGpi.SetTriggerFunction(GPIAoC::GPI_LEVEL_ACTIVE_HIGH);
- // TODO: Add timeout
- if (xSemaphoreTake(mSemaphoreHandle, portMAX_DELAY) == pdTRUE) {
+
+ chppMutexLock(&mMutex);
+ if (mWakeInGpi.PadValue() ||
+ chppConditionVariableTimedWait(&mCondVar, &mMutex, kStartTimeoutNs)) {
if (hasTxPacket()) {
int bytesTransmitted = mUart->Tx(mCurrentBuffer, mCurrentBufferLen);
@@ -152,17 +148,20 @@
}
mWakeInGpi.SetTriggerFunction(GPIAoC::GPI_LEVEL_ACTIVE_LOW);
- // TODO: Add timeout
- success &= (xSemaphoreTake(mSemaphoreHandle, portMAX_DELAY) == pdTRUE);
+ success &=
+ (!mWakeInGpi.PadValue() ||
+ chppConditionVariableTimedWait(&mCondVar, &mMutex, kStartTimeoutNs));
} else {
success = false;
mWakeOutGpio.Clear();
}
+ chppMutexUnlock(&mMutex);
mTransactionPending = false;
}
// Re-enable the interrupt to handle transaction requests.
+ mWakeInGpi.SetTriggerFunction(GPIAoC::GPI_DISABLE);
mWakeInGpi.SetInterruptHandler(onTransactionRequestInterrupt, this);
mWakeInGpi.SetTriggerFunction(GPIAoC::GPI_LEVEL_ACTIVE_HIGH);
diff --git a/chpp/platform/aoc/include/chpp/platform/chpp_uart_link_manager.h b/chpp/platform/aoc/include/chpp/platform/chpp_uart_link_manager.h
index 5a30011..4a8187a 100644
--- a/chpp/platform/aoc/include/chpp/platform/chpp_uart_link_manager.h
+++ b/chpp/platform/aoc/include/chpp/platform/chpp_uart_link_manager.h
@@ -18,13 +18,15 @@
#define CHPP_PLATFORM_UART_LINK_MANAGER_H_
#include "FreeRTOS.h"
+#include "chpp/condition_variable.h"
#include "chpp/link.h"
+#include "chpp/mutex.h"
#include "chpp/transport.h"
#include "chre/platform/atomic.h"
#include "chre/util/non_copyable.h"
+#include "chre/util/time.h"
#include "gpi_aoc.h"
#include "gpio_aoc.h"
-#include "semphr.h"
#include "uart.h"
namespace chpp {
@@ -113,8 +115,8 @@
return &mWakeInGpi;
}
- SemaphoreHandle_t getSemaphoreHandle() const {
- return mSemaphoreHandle;
+ struct ChppConditionVariable *getCondVar() {
+ return &mCondVar;
}
void setTransactionPending() {
@@ -155,14 +157,18 @@
uint8_t mRxBuf[kRxBufSize];
size_t mRxBufIndex = 0;
- /**
- * Semaphore to use while waiting for GPI interrupts.
- * NOTE: We use the semaphore directly instead of a condition
- * variable, because there is no need to protect a predicate variable
- * through a mutex.
- */
- SemaphoreHandle_t mSemaphoreHandle;
- StaticSemaphore_t mStaticSemaphore;
+ //! The mutex/condition variable to use while waiting for GPI interrupts.
+ struct ChppMutex mMutex;
+ struct ChppConditionVariable mCondVar;
+
+ //! The timeout for waiting on the remote to indicate transaction readiness
+ //! (t_start per specifications).
+ static constexpr uint64_t kStartTimeoutNs =
+ 100 * chre::kOneMillisecondInNanoseconds;
+
+ //! The timeout for waiting on the remote to indicate transaction ended
+ //! (t_end per specifications).
+ static constexpr uint64_t kEndTimeoutNs = chre::kOneSecondInNanoseconds;
chre::AtomicBool mTransactionPending{false};