20 uint8_t emergency_stop;
22 uint32_t timestamp_ms;
24 uint32_t sequence_number;
30 uint32_t process_a_seq;
31 uint32_t process_b_seq;
32 volatile uint8_t ready_a;
33 volatile uint8_t ready_b;
34 volatile uint8_t process_a_healthy;
35 volatile uint8_t process_b_healthy;
36 uint32_t timestamp_ms;
39__attribute__((aligned(64)))
48 { .train_id = 101, .position = 500 },
49 { .train_id = 102, .position = 2500 },
50 { .train_id = 103, .position = 7500 },
53#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
55static uint32_t crc32_checksum(
const uint8_t *data, uint32_t len)
57 uint32_t crc = 0xffffffff;
58 for (uint32_t i = 0; i < len; i++) {
59 uint8_t
byte = data[i];
60 crc = (crc >> 8) ^ (uint32_t)(crc ^ byte);
62 return crc ^ 0xffffffff;
65static train_command_t compute_train_command(uint32_t train_id, uint32_t position)
71 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
75 if (position < 1000) {
78 }
else if (position < 5000) {
81 }
else if (position < 9000) {
85 cmd.emergency_stop = 1;
90 uint8_t *cmd_bytes = (uint8_t *)&cmd;
91 cmd.checksum = crc32_checksum(cmd_bytes,
sizeof(cmd) -
sizeof(cmd.checksum));
95int main(
int argc,
char *argv[])
100 uint32_t cycle_count = 0;
101 uint32_t process_b_seq = 0;
102 uint32_t mismatch_count = 0;
104 fprintf(stderr,
"[EAST:B] Process B (Standby Channel B) starting\n");
105 fprintf(stderr,
"[EAST:B] Verifying commands in STANDBY mode\n");
111 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
112 trains[i].position += (i + 1) * 3;
113 if (trains[i].position > 10000) {
114 trains[i].position = 10000;
118 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
123 cmd.sequence_number = process_b_seq;
125 shared_mem.cmd_b = cmd;
126 shared_mem.process_b_seq = process_b_seq;
127 __sync_synchronize();
128 shared_mem.ready_b = 1;
130 if (shared_mem.ready_a && shared_mem.process_a_seq == process_b_seq) {
131 if (shared_mem.cmd_a.signal_state != cmd.signal_state ||
132 shared_mem.cmd_a.speed_limit != cmd.speed_limit) {
134 fprintf(stderr,
"[EAST:B] MISMATCH: A(sig=%u,spd=%u) vs B(sig=%u,spd=%u)\n",
135 shared_mem.cmd_a.signal_state,
136 shared_mem.cmd_a.speed_limit,
137 cmd.signal_state, cmd.speed_limit);
141 if (cycle_count % 10 == 0) {
143 "[EAST:B] Cycle %u (STANDBY): train=%u, pos=%u, sig=%u, speed=%u\n",
144 cycle_count, cmd.train_id, cmd.position,
145 cmd.signal_state, cmd.speed_limit);
149 shared_mem.process_b_healthy = 1;