PER Firmware
Loading...
Searching...
No Matches
spmc.h
Go to the documentation of this file.
1#ifndef SPMC_H
2#define SPMC_H
3
11#include <stddef.h>
12#include <stdint.h>
13
14#include "timestamped_frame.h"
15
16// todo tune values based on testing
17static constexpr size_t SPMC_CHUNK_NUM_FRAMES = 512;
18static constexpr size_t SPMC_CHUNK_CAPACITY = 12;
19static constexpr size_t SPMC_FRAME_CAPACITY = SPMC_CHUNK_NUM_FRAMES * SPMC_CHUNK_CAPACITY;
20static_assert(
21 SPMC_FRAME_CAPACITY % SPMC_CHUNK_NUM_FRAMES == 0,
22 "the SPMC capacity must be a multiple of SPMC_CHUNK_NUM_FRAMES "
23 "to prevent DMA wraparound issues and fragmentation"
24);
25static constexpr size_t SPMC_BYTES_PER_CHUNK = SPMC_CHUNK_NUM_FRAMES * sizeof(timestamped_frame_t);
26
27static constexpr size_t SPMC_MINI_NUM_FRAMES = 16;
28static_assert(
29 SPMC_CHUNK_NUM_FRAMES % SPMC_MINI_NUM_FRAMES == 0,
30 "SPMC_CHUNK_NUM_FRAMES must be divisible by SPMC_MINI_NUM_FRAMES "
31 "to allow mini chunk peeks for the ETH follower"
32);
33
34typedef struct {
35 timestamped_frame_t data[SPMC_FRAME_CAPACITY];
36 volatile size_t head; // shared head
37 volatile size_t master_tail; // SD tail
38 volatile size_t follower_tail; // best-effort ETH tail
39
40 // stats
41 volatile uint32_t overflows; // items dropped due to full buffer
42 volatile uint32_t follower_drops; // follower items lost due to lagging too far behind
43 volatile bool is_full;
44} SPMC_t;
45
46extern SPMC_t g_spmc;
47
48static_assert(
49 sizeof(size_t) == 4,
50 "32-bit loads and stores are atomic, this is required for the lock-free design to work"
51);
52
53void SPMC_init(SPMC_t *spmc);
54bool SPMC_enqueue_from_ISR(SPMC_t *spmc, timestamped_frame_t *incoming_frame);
55
56bool SPMC_master_peek_chunk(SPMC_t *spmc, timestamped_frame_t **first_item);
58
59size_t SPMC_follower_peek_minis(SPMC_t *spmc, timestamped_frame_t **first_item);
60void SPMC_follower_advance_tail(SPMC_t *spmc, size_t minis_consumed);
61
62#endif // SPMC_H
bool SPMC_enqueue_from_ISR(SPMC_t *spmc, timestamped_frame_t *incoming_frame)
Enqueues a received CAN message into the SPMC buffer from an ISR context. ! the two producer ISRs mus...
Definition spmc.c:65
bool SPMC_master_peek_chunk(SPMC_t *spmc, timestamped_frame_t **first_item)
Peeks at the next chunk for the master (SD logging) without committing the tail.
Definition spmc.c:100
void SPMC_master_advance_tail(SPMC_t *spmc)
Advances the master tail pointer by one chunk.
Definition spmc.c:131
void SPMC_init(SPMC_t *spmc)
Initializes the SPMC instance and configures CAN RX interrupts.
Definition spmc.c:41
size_t SPMC_follower_peek_minis(SPMC_t *spmc, timestamped_frame_t **first_item)
Peeks at the number of contiguous mini chunks available for the follower without lapping the master's...
Definition spmc.c:155
void SPMC_follower_advance_tail(SPMC_t *spmc, size_t minis_consumed)
Advances the follower tail pointer by a given number of mini chunks.
Definition spmc.c:202
Definition spmc.h:34
Definition timestamped_frame.h:13
Definition for timestamped CAN frames.