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#include "timestamped_frame.h"
14
15// todo tune values based on testing
16static constexpr size_t SPMC_CHUNK_NUM_FRAMES = 512;
17static constexpr size_t SPMC_CHUNK_CAPACITY = 12;
18static constexpr size_t SPMC_FRAME_CAPACITY = SPMC_CHUNK_NUM_FRAMES * SPMC_CHUNK_CAPACITY;
19static_assert(
20 SPMC_FRAME_CAPACITY % SPMC_CHUNK_NUM_FRAMES == 0,
21 "the SPMC capacity must be a multiple of SPMC_CHUNK_NUM_FRAMES "
22 "to prevent DMA wraparound issues and fragmentation"
23);
24
25static constexpr size_t SPMC_MINI_NUM_FRAMES = 16;
26static_assert(
27 SPMC_CHUNK_NUM_FRAMES % SPMC_MINI_NUM_FRAMES == 0,
28 "SPMC_CHUNK_NUM_FRAMES must be divisible by SPMC_MINI_NUM_FRAMES "
29 "to allow mini chunk peeks for the ETH follower"
30);
31
32typedef struct {
33 timestamped_frame_t data[SPMC_FRAME_CAPACITY];
34 volatile size_t head; // shared head
35 volatile size_t master_tail; // SD tail
36 volatile size_t follower_tail; // best-effort ETH tail
37
38 // stats
39 volatile uint32_t overflows; // items dropped due to full buffer
40 volatile uint32_t follower_drops; // follower items lost due to lagging too far behind
41 volatile bool is_full;
42} SPMC_t;
43
44extern SPMC_t g_spmc;
45
46static_assert(
47 sizeof(size_t) == 4,
48 "32-bit loads and stores are atomic, this is required for the lock-free design to work"
49);
50
51void SPMC_init(SPMC_t *spmc);
52bool SPMC_enqueue_from_ISR(SPMC_t *spmc, timestamped_frame_t *incoming_frame);
53
54bool SPMC_master_peek_chunk(SPMC_t *spmc, timestamped_frame_t **first_item);
56
57size_t SPMC_follower_peek_minis(SPMC_t *spmc, timestamped_frame_t **first_item);
58void SPMC_follower_advance_tail(SPMC_t *spmc, size_t minis_consumed);
59
60#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:64
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:99
void SPMC_master_advance_tail(SPMC_t *spmc)
Advances the master tail pointer by one chunk.
Definition spmc.c:130
void SPMC_init(SPMC_t *spmc)
Initializes the SPMC instance and configures CAN RX interrupts.
Definition spmc.c:40
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:154
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:201
Definition spmc.h:32
Definition timestamped_frame.h:13
Definition for timestamped CAN frames.