This commit is contained in:
Bartosz Wieczorek 2025-04-22 12:09:17 +02:00
parent 31ecbc1bda
commit 76bdb965b4
4 changed files with 70 additions and 48 deletions

View File

@ -50,7 +50,7 @@ CONFIG_LOG_BACKEND_UART=n # Use UART for log output
CONFIG_MAIN_STACK_SIZE=1500
#
CONFIG_CRC=y
CONFIG_ASSERT=y
CONFIG_ASSERT=n
#CONFIG_NUM_PREEMPT_PRIORITIES=0

View File

@ -95,7 +95,7 @@ template <typename T> void PB_encode_egress(const T &tempresp) {
}
void TemperatureSampler::take_sample() {
ULOG_DEBUG("Samples on ch %d, size %d", this->_channel, this->_samples.size());
// ULOG_DEBUG("Samples on ch %d, size %d", this->_channel, this->_samples.size());
_samples.push_back(adc_take_sample());
}

View File

@ -60,50 +60,73 @@ void log_worker(struct k_work *work) {
}
// Global log work item
static struct k_work_log_data uart_log_work;
#ifdef RIMS_UART_PERF_COUNTERS
static std::size_t buffer_copy_wait{};
static std::size_t isr_execution{};
static std::chrono::nanoseconds tx_total{};
static std::chrono::nanoseconds tx_crit{};
#endif
AsyncUART::AsyncUART() {
_dev = DEVICE_DT_GET(DT_NODELABEL(usart1));
__ASSERT(device_is_ready(_dev), "device needs to be ready");
auto ret = uart_irq_callback_user_data_set(_dev, AsyncUART::uartCallback, this);
if (ret < 0) {
throw uart_not_ready_error{}; // catch this somewhere??
}
[[maybe_unused]] auto ret = uart_irq_callback_user_data_set(_dev, AsyncUART::uartCallback, this);
__ASSERT(ret >= 0, "");
uart_irq_rx_enable(_dev);
}
void AsyncUART::loop() {
if (!device_is_ready(_dev)) {
/// TODO throw?
return; // Exit if the UART device is not ready
}
__ASSERT(device_is_ready(_dev), "device needs to be ready");
while (1) {
std::this_thread::sleep_for(std::chrono::seconds{2});
std::this_thread::sleep_for(std::chrono::seconds{10});
#ifdef RIMS_UART_PERF_COUNTERS
ULOG_DEBUG(R"log(buffer_copy_wait : %d)log", buffer_copy_wait);
ULOG_DEBUG(R"log(tx_total : %lldus)log", tx_total.count() / 1000);
ULOG_DEBUG(R"log(tx_critical : %lldus)log", tx_crit.count() / 1000);
ULOG_DEBUG(R"log(isr number : %zu)log", isr_execution);
#endif
}
}
static std::size_t buffer_copy_wait {};
// free function, only need to copy data to uart's TX_BUFFER and that's it
void AsyncUART::transmit(AsyncUART *dev, std::span<std::uint8_t> bytes) {
#ifdef RIMS_UART_PERF_COUNTERS
auto isr_start = std::chrono::high_resolution_clock::now();
isr_execution++;
#endif
if (bytes.empty()) return;
__ASSERT(bytes.size_bytes() <= dev->tx_buffer.capacity(), "for now, all bytes needs to fir in tx buffer");
while (dev->tx_buffer.free() < bytes.size_bytes()) {
#ifdef RIMS_UART_PERF_COUNTERS
buffer_copy_wait++;
#endif
std::this_thread::sleep_for(std::chrono::microseconds{20});
}
#ifdef RIMS_UART_PERF_COUNTERS
auto crit_start = std::chrono::high_resolution_clock::now();
#endif
k_spinlock_key_t key = k_spin_lock(&dev->tx_lock);
__ASSERT(dev->no_copyInProgress(), "multiple copies at the same time are not allowed");
// copy all data to TX
dev->tx_buffer.put_n(bytes.data(), bytes.size());
// if disabled, enable tx interrupts
if (not dev->tx_irq_enabled()) dev->tx_irq_enable();
k_spin_unlock(&dev->tx_lock, key);
#ifdef RIMS_UART_PERF_COUNTERS
auto crit_stop = std::chrono::high_resolution_clock::now();
auto isr_stop = std::chrono::high_resolution_clock::now();
tx_total += isr_stop - isr_start;
tx_crit += crit_stop - crit_start;
#endif
}
void AsyncUART::uartCallback(const device *dev, void *user_data) {
@ -144,11 +167,11 @@ void AsyncUART::readByteUart() {
}
// push_back returns last placed byte, if the byte is 0x00 we got end of frame
else if (rxBuffer().push_back(rxByte()) == 0) {
if(rxBuffer().size()>1){
processMessage();
}else{
rxBuffer().clean();
}
if (rxBuffer().size() > 1) {
processMessage();
} else {
rxBuffer().clean();
}
}
}

View File

@ -26,38 +26,12 @@ class AsyncUART {
void loop();
static void transmit(AsyncUART *dev, std::span<uint8_t> bytes);
static void workHandler(k_work *work);
static void uartCallback(const struct device *dev, void *user_data);
void uartISR();
bool tx_irq_enabled() const {
return _txIrqEnabled;
}
void tx_irq_enable() {
_txIrqEnabled = true;
uart_irq_tx_enable(_dev);
}
void tx_irq_disable() {
_txIrqEnabled = false;
uart_irq_tx_disable(_dev);
}
void beginCopy() {
_copyInProgress = true;
}
void endCopy() {
_copyInProgress = false;
}
constexpr bool copyInProgress() const {
return _copyInProgress;
}
constexpr bool no_copyInProgress() const {
return not _copyInProgress;
}
const device *_dev;
private:
const device *_dev;
std::array<rx_buffer_t, 2> rx_buffers;
uint8_t _currentBufferIndex{};
bool _faultFlag = false;
@ -79,6 +53,31 @@ class AsyncUART {
inline bool txHasByte() const;
inline void txByte(uint8_t byte); // low level write byte to device
constexpr bool tx_irq_enabled() const {
return _txIrqEnabled;
}
void tx_irq_enable() {
_txIrqEnabled = true;
uart_irq_tx_enable(_dev);
}
void tx_irq_disable() {
uart_irq_tx_disable(_dev);
_txIrqEnabled = false;
}
void beginCopy() {
_copyInProgress = true;
}
void endCopy() {
_copyInProgress = false;
}
constexpr bool copyInProgress() const {
return _copyInProgress;
}
constexpr bool no_copyInProgress() const {
return not _copyInProgress;
}
// exception handlers
inline void handleRxNotReadyError(const uart_rx_not_ready_error &e);
inline void handleRxBufferOverflowError(const uart_rx_buffer_overflow &e);