33#include <osdlp/uslp.hpp>
34#include <psa/crypto.h>
35#include <satnogs-comms-lib/version.hpp>
37#include <zephyr/task_wdt/task_wdt.h>
42static constexpr std::array<uint8_t, 32>
45 std::array<uint8_t, 32> key = {0};
46 static_assert(std::char_traits<char>::length(CONFIG_TLC_SHA256_KEY) == 64,
47 "Hash should be exactly 64 hex annotated chars");
48 for (
unsigned int i = 0; i < 64; i += 2) {
49 char s[2] = {CONFIG_TLC_SHA256_KEY[i], CONFIG_TLC_SHA256_KEY[i + 1]};
50 char byte = (char)strtol(s, NULL, 16);
56static struct k_thread msg_arbiter_thread_data;
60static struct k_msgq rx_msgq;
64static struct k_msgq can1_tx_msgq;
68static struct k_msgq can2_tx_msgq;
72static struct k_msgq uhf_tx_msgq;
76static struct k_msgq sband_tx_msgq;
80static const auto &tlc_key = sha256_key_hex2bytes();
100 return k_msgq_put(&rx_msgq, &m, wait);
119 return k_msgq_get(&can1_tx_msgq, &m, wait);
121 return k_msgq_get(&can2_tx_msgq, &m, wait);
123 return k_msgq_get(&uhf_tx_msgq, &m, wait);
125 return k_msgq_get(&sband_tx_msgq, &m, wait);
149#if CONFIG_IO_CAN1_ENABLE
150 return k_msgq_put(&can1_tx_msgq, &m, wait);
156#if CONFIG_IO_CAN2_ENABLE
157 return k_msgq_put(&can2_tx_msgq, &m, wait);
163 return k_msgq_put(&uhf_tx_msgq, &m, wait);
165 return k_msgq_put(&sband_tx_msgq, &m, wait);
173 subsys s, k_timeout_t wait)
175 osdlp::tf_primary_header uslp_tf_hdr(
176 CONFIG_CCSDS_SPACECRAFT_ID,
177 osdlp::tf_source_destination_id::SOURCE_TRANSFER_FRAME, vcid, mapid,
178 osdlp::tf_bypass_sequence_control_flag::SEQUENCE_CONTROLLED_QOS, 0,
179 osdlp::tf_operational_control_field_flag::OCF_NOT_PRESENT, 0);
181 osdlp::tf_data_field_header uslp_tfdf_hdr;
182 osdlp::uslp uslp_resp(uslp_tf_hdr, uslp_tfdf_hdr);
185 uslp_resp.serialize(fw_response.data, CONFIG_MAX_MTU, m.
data, m.
len);
187 fw_response.iface = m.
iface;
188 fw_response.len = uslp_len;
189 return fwd(fw_response, s, wait);
204 return k_msgq_num_used_get(&can1_tx_msgq);
206 return k_msgq_num_used_get(&can2_tx_msgq);
208 return k_msgq_num_used_get(&uhf_tx_msgq);
210 return k_msgq_num_used_get(&sband_tx_msgq);
224 m_tid = k_thread_create(&msg_arbiter_thread_data, msg_arbiter_thread_stack,
225 K_THREAD_STACK_SIZEOF(msg_arbiter_thread_stack),
226 parse_thread, NULL, NULL, NULL,
227 CONFIG_MSG_ARBITER_PRIO, 0, K_NO_WAIT);
231 k_thread_name_set(m_tid,
"msg_arbiter");
235msg_arbiter::parse_thread(
void *arg1,
void *arg2,
void *arg3)
237 int task_wdt_id = task_wdt_add(CONFIG_WATCHDOG_PERIOD_MSG_ARBITER,
244 task_wdt_feed(task_wdt_id);
245 if (k_msgq_get(&rx_msgq, &arb.m_msg, K_MSEC(1000)) == 0) {
252 osdlp::tf_primary_header uslp_tf_hdr;
253 osdlp::tf_data_field_header uslp_tfdf_hdr;
255 osdlp::uslp<> uslp(uslp_tf_hdr, uslp_tfdf_hdr);
256 uslp.deserialize(arb.m_msg.
data, arb.m_msg.
len);
257 if (uslp.get_is_valid_packet()) {
259 if (uslp_tf_hdr.get_spacecraft_id() != CONFIG_CCSDS_SPACECRAFT_ID) {
264 if (uslp_tf_hdr.get_source_destination_id() !=
265 osdlp::tf_source_destination_id::DESTINATION_TRANSFER_FRAME) {
273 const uint8_t *sp = uslp.get_payload();
274 size_t sp_len = uslp.get_payload_length();
281 space_packet.
len = std::min<size_t>(sp_len, CONFIG_MAX_MTU);
283 std::copy_n(sp, space_packet.
len, space_packet.
data);
296 osdlp::tf_primary_header uslp_resp_tf_hdr(
297 CONFIG_CCSDS_SPACECRAFT_ID,
298 osdlp::tf_source_destination_id::SOURCE_TRANSFER_FRAME, 0, 0,
299 osdlp::tf_bypass_sequence_control_flag::SEQUENCE_CONTROLLED_QOS,
300 0, osdlp::tf_operational_control_field_flag::OCF_NOT_PRESENT,
303 osdlp::tf_data_field_header uslp_resp_tfdf_hdr;
304 osdlp::uslp uslp_resp(uslp_resp_tf_hdr, uslp_resp_tfdf_hdr);
307 auto uslp_len = uslp_resp.serialize(arb.m_msg.
data, CONFIG_MAX_MTU,
309 arb.m_msg.
len = uslp_len;
311 arb.
fwd(arb.m_msg, arb.m_msg.
iface);
321 }
catch (
const scl::exception &e) {
324 }
catch (
const std::exception &e) {
333 k_msgq_init(&rx_msgq, rx_msgq_buffer,
sizeof(msg_arbiter::msg),
rx_msgq_size);
334 k_msgq_init(&can1_tx_msgq, can1_tx_msgq_buffer,
sizeof(msg_arbiter::msg),
336 k_msgq_init(&can2_tx_msgq, can2_tx_msgq_buffer,
sizeof(msg_arbiter::msg),
338 k_msgq_init(&uhf_tx_msgq, uhf_tx_msgq_buffer,
sizeof(msg_arbiter::msg),
340 k_msgq_init(&sband_tx_msgq, sband_tx_msgq_buffer,
sizeof(msg_arbiter::msg),
342 k_mutex_init(&m_mtx);
static error_handler & get_instance()
Singleton access to the error_handler subsystem.
Generic exception indicating an invalid argument.
bool msg_parser(msg_arbiter::msg &msg, bool is_sp)
This method is called inside the msg_arbiter, in case an incoming message was not parsed by the defau...
static mission & get_instance()
Get a singleton access to the mission subsystem.
uint8_t data[mtu]
Buffer to hold the data.
size_t len
Data size in bytes.
subsys iface
The interface from which the msg was received.
Incoming/Outgoing Message Arbiter.
static constexpr size_t rx_msgq_size
uint32_t backpressure(subsys s)
Returns the number of messages that are waiting in the message queue of a specific subsystem.
int pull(msg_arbiter::msg &m, subsys s, k_timeout_t wait=K_MSEC(CONFIG_MSG_ARBITER_TIMEOUT_MS))
Pulls a message for a specific IO interface.
static constexpr size_t uhf_tx_msgq_size
int fwd(const msg_arbiter::msg &m, subsys s, k_timeout_t wait=K_MSEC(CONFIG_MSG_ARBITER_TIMEOUT_MS))
Forward a received message for processing.
static msg_arbiter & get_instance()
Singleton access to a unique and global msg_arbiter instance.
subsys
Peripheral identifier.
static constexpr size_t sband_tx_msgq_size
void start()
Starts the processing task for incoming messages handling.
msg_arbiter(msg_arbiter const &)=delete
static constexpr size_t can2_tx_msgq_size
int push(const msg_arbiter::msg &m, k_timeout_t wait=K_MSEC(CONFIG_MSG_ARBITER_TIMEOUT_MS))
Push a received message for processing.
static constexpr size_t can1_tx_msgq_size
bool decode_ccsds_xtce(msg_arbiter::msg &m, int wdgid)
static telecommand & get_instance()
bool ccsds_frame_valid(const uint8_t *b, size_t len)
void task_wdt_callback(int channel_id, void *user_data)
K_THREAD_STACK_DEFINE(radio_rx_thread_stack, CONFIG_RADIO_RX_THREAD_STACK_SIZE)