This commit is contained in:
Bartosz Wieczorek 2025-06-16 14:56:20 +02:00
parent 769aa38a96
commit 5edbfb63bc
7 changed files with 35 additions and 45 deletions

View File

@ -51,5 +51,7 @@ CONFIG_UART_INTERRUPT_DRIVEN=y
# subsystems
CONFIG_ADC=y
CONFIG_MAIN_STACK_SIZE=800
CONFIG_MAIN_STACK_SIZE=1024
#CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=1500
CONFIG_IDLE_STACK_SIZE=128
CONFIG_ISR_STACK_SIZE=1024

View File

@ -1,8 +1,6 @@
#include "gpio.hpp"
#include "gpio_pb_helpers.hpp"
#include "log.hpp"
#include "zephyr.hpp"
#include <exception>
#include <expected>
namespace rims {

View File

@ -26,13 +26,12 @@ template <typename RequestT> struct global_ipc_request<RequestT, std::enable_if_
}
};
class GPIO {
public:
GPIO();
void loop();
[[nodiscard]] std::expected<void, gpio::error> handle_gpioRequest(const GpioRequest &req, GpioResponse &resp) ;
NDIS std::expected<void, gpio::error> handle_gpioRequest(const GpioRequest &req, GpioResponse &resp) ;
private:
void event_gpioMessageArrived();

View File

@ -8,19 +8,13 @@
#include "temperature_measurements.hpp"
#include "thread_analyzer.hpp"
#include "uart.hpp"
#include "zephyr.hpp"
#include "zero_cross_detection.hpp"
#include <chrono>
#include <thread>
#include <cstdio>
#include <cstdlib>
#include <thread>
#include <zephyr/kernel.h>
#include <zephyr/kernel/thread.h>
#include <zephyr/kernel/thread_stack.h>
#include <zephyr/drivers/gpio.h>
extern "C" unsigned int sleep(unsigned int seconds) {
k_sleep(K_SECONDS(seconds));
@ -32,7 +26,7 @@ using namespace rims;
/// exception handling takes ~800 bytes from the stack when thrown, we need to make sure there is at least this much stack left for each thread
/// We need to drop exceptions ;( most of the stack space seems to be used for stack unwinding and other stuff
///
static K_THREAD_STACK_DEFINE(k_messengerStack, 2000);
static K_THREAD_STACK_DEFINE(k_messengerStack, 1500);
TStack messengerStack{k_messengerStack, K_THREAD_STACK_SIZEOF(k_messengerStack)};
static K_THREAD_STACK_DEFINE(k_uartStack, 1300);
@ -53,7 +47,7 @@ TStack gpioStack{k_gpioStack, K_THREAD_STACK_SIZEOF(k_gpioStack)};
static K_THREAD_STACK_DEFINE(k_threadAnalyzerStack, 800);
TStack threadAnalyzerStack{k_threadAnalyzerStack, K_THREAD_STACK_SIZEOF(k_threadAnalyzerStack)};
static K_THREAD_STACK_DEFINE(k_operationStack, 2500);
static K_THREAD_STACK_DEFINE(k_operationStack, 2000);
TStack operationStack{k_operationStack, K_THREAD_STACK_SIZEOF(k_operationStack)};
template <typename T> class LazyInit {

View File

@ -63,6 +63,7 @@ std::expected<void, cobs::error> translate_error(int e) {
}
return {};
}
std::expected<std::size_t, cobs::error> decode(const std::span<uint8_t> in, std::span<uint8_t> out) {
size_t out_dec_len{0};
auto ret = cobs_decode(in.data(), in.size(), out.data(), out.size(), &out_dec_len);
@ -235,32 +236,31 @@ void MessengerThread::event_dataArrived() {
CHECK(crcIsValid(submessage, crc));
/// we now got a proper frame, starting to decode a frame
stream = pb::istream_from_span(submessage);
stream = pb::istream_from_span(submessage);
auto cb = TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }};
switch (id.receiver) { // check which endpoint is the receiver
case temperature_receiver_tag: {
CHECK(handle_temperatureIngressMsg(id, stream, TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }}));
CHECK(handle_temperatureIngressMsg(id, stream, std::move(cb)));
break;
}
case ctrl_receiver_tag: {
CHECK(handle_ctrlIngressMsg(id, stream, TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }}));
CHECK(handle_ctrlIngressMsg(id, stream, std::move(cb)));
break;
}
case config_receiver_tag: {
CHECK(handle_configIngressMsg(id, stream, TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }}));
CHECK(handle_configIngressMsg(id, stream, std::move(cb)));
break;
}
case logging_receiver_tag: {
// logIngressFifoQueueBuffer.try_produce()
break;
}
case gpio_receiver_tag: {
CHECK(handle_gpioIngressMsg(id, stream, TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }}));
CHECK(handle_gpioIngressMsg(id, stream, std::move(cb)));
break;
}
case operation_receiver_tag: {
CHECK(handle_opIngressMsg(id, stream, TransmitCB{[dev = buf.device](std::span<std::byte> bytes) { dev->transmit(dev, bytes); }}));
CHECK(handle_opIngressMsg(id, stream, std::move(cb)));
break;
}
default: {
@ -426,18 +426,16 @@ void MessengerThread::egressPush(messenger_Message &message, int wireId_receiver
void MessengerThread::egressPush(void *submessage, const pb_msgdesc_t &fields, int wireId_receiver, std::optional<uint32_t> requestId) {
// encode embedded message directly to the buffer of output message to save stack
/// TODO the retransmissing type should be declared when callback is create and not here, this works but is stupid ;(
// ULOG_DEBUG("egressPush");
auto wireId = WireFormatID{}.setReceiver(wireId_receiver);
if (MessengerThread::activeRequestIsIPC(wireId, requestId.value_or(0))) {
auto requestData = takeActiveRequest(wireId, requestId.value_or(0));
// send egress message directly through callback stream
requestData->transmit({(std::byte *)submessage, sizeof(void *)});
} else {
messenger_Message message = messenger_Message_init_zero;
auto ostream = pb::ostream_from_span(std::span{message.data.bytes}); // TODO max data size
pb::encode(ostream, fields, submessage);
auto ostream = pb::ostream_from_span(std::span{message.data.bytes}); // TODO max data size
pb::encode(ostream, fields, submessage); // this can fail
message.data.size = ostream.bytes_written;
egressPush(message, wireId_receiver, requestId);

View File

@ -4,7 +4,6 @@
#include "function.hpp"
#include "id.hpp"
#include "message_type_id.hpp"
#include "messenger_ipc.hpp"
#include "zephyr.hpp"
@ -12,6 +11,7 @@
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cassert>
#include <optional>
#include <span>
#include <type_traits>
@ -41,7 +41,7 @@ inline auto next_sequence_value() {
} // namespace details
template <typename IngressT, typename RequestT> //
void copyToIngress(IngressT &ingress, const RequestT &request) {
constexpr void copyToIngress(IngressT &ingress, const RequestT &request) {
ingress = std::decay_t<decltype(ingress)>{};
ingress.request_id = details::next_sequence_value();
ingress.which_data = tag<RequestT>();
@ -52,18 +52,17 @@ constexpr WireFormatID ipcID(int receiver_group) {
return WireFormatID{}.setType(Type::Request).setSender(0xdead).setReceiver(receiver_group).makeIPC();
}
using TransmitCB = rims::function<void(std::span<std::byte> data), 16>;
using TransmitCB = rims::function<void(std::span<std::byte> data), 8>;
bool createRequest(WireFormatID wireId, uint32_t requestId, TransmitCB &&cb);
template <typename EgressT, typename ResponseT> static auto makeIpcCallback(zephyr::semaphore::sem &sem, ResponseT &response) {
// response -> e.g
// response -> e.g
return TransmitCB{[&](std::span<std::byte> res) {
// res is the egress message from subsystem that contains my response e.g. ctrl_EgressMessage
// ctrl_PowerControlAlgorithmResponse
static_assert(std::is_trivial_v<ResponseT>);
auto *egress = reinterpret_cast<EgressT *>(res.data());
__ASSERT_NO_MSG(egress->which_data == tag<ResponseT>());
assert(egress->which_data == tag<ResponseT>());
memcpy(&response, &egress->data, sizeof(response));
k_sem_give(&sem);
}};
@ -73,7 +72,7 @@ template <typename QueueT, typename RequestT, typename ResponseT = typename Resp
auto defaultIpcHandler(QueueT &queue, int tag, zephyr::semaphore::sem &sem, const RequestT &request) -> std::optional<ResponseT> {
// queue -> IngressQueue e.g. fifo_queue<ctrl_IngressMessage, 2>
// RequestT -> for example ctrl_PowerControlAlgorithmRequest, one of ingressQueue type submessage
typename ResponseSelector<RequestT>::response_t response = {};
if (queue.try_produce([&](auto &ingress) {
// type of IngressQueue element e.g. ctrl_IngressMessage
@ -87,7 +86,6 @@ auto defaultIpcHandler(QueueT &queue, int tag, zephyr::semaphore::sem &sem, cons
return std::nullopt;
}
class MessengerThread : public ZephyrThread {
public:
MessengerThread(TStackBase &stack);
@ -122,12 +120,13 @@ class MessengerThread : public ZephyrThread {
void event_logEgress();
void event_gpioEgress();
void event_operation();
NDIS std::expected<void, Error> handle_temperatureIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS std::expected<void, Error> handle_ctrlIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS std::expected<void, Error> handle_configIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS std::expected<void, Error> handle_gpioIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS std::expected<void, Error> handle_opIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
using handler_ret_t = std::expected<void, Error>;
NDIS handler_ret_t handle_temperatureIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS handler_ret_t handle_ctrlIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS handler_ret_t handle_configIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS handler_ret_t handle_gpioIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS handler_ret_t handle_opIngressMsg(WireFormatID id, pb_istream_t &stream, TransmitCB &&cb);
NDIS std::expected<void, Error> decode(pb_istream_t &stream, const pb_msgdesc_t &fields, void *dest) const;
NDIS std::expected<void, Error> transmit(messenger_Message &msg, const TransmitCB &cb) const;

View File

@ -178,9 +178,9 @@ class PhaseModulationOrchestrator {
using handler_ret_t = std::expected<void, ctrl::error>;
[[nodiscard]] handler_ret_t handler_powerControlAlgorithmRequest(const PowerControlAlgorithmRequest &request, PowerControlAlgorithmResponse &resp);
[[nodiscard]] handler_ret_t handler_powerLevelRequest(const PowerLevelRequest &request, PowerLevelResponse &response);
[[nodiscard]] handler_ret_t handler_watchdogRequest(const WatchdogRequest &request, WatchdogResponse &response);
NDIS handler_ret_t handler_powerControlAlgorithmRequest(const PowerControlAlgorithmRequest &request, PowerControlAlgorithmResponse &resp);
NDIS handler_ret_t handler_powerLevelRequest(const PowerLevelRequest &request, PowerLevelResponse &response);
NDIS handler_ret_t handler_watchdogRequest(const WatchdogRequest &request, WatchdogResponse &response);
private:
void event_zeroCrossDetection();
@ -188,7 +188,7 @@ class PhaseModulationOrchestrator {
void event_ctrlWatchdog(valid_channel ch);
/// Helpers
[[nodiscard]] handler_ret_t setPowerControlAlgorithm(valid_channel ch, const ctrl_PowerControlAlgorithmData &alg);
NDIS handler_ret_t setPowerControlAlgorithm(valid_channel ch, const ctrl_PowerControlAlgorithmData &alg);
PowerControlAlgorithm powerControlAlgorithm(valid_channel ch);
bool setup();