33 uint8_t emergency_stop;
35 uint32_t timestamp_ms;
37 uint32_t sequence_number;
43 uint32_t process_a_seq;
44 uint32_t process_b_seq;
45 volatile uint8_t ready_a;
46 volatile uint8_t ready_b;
47 volatile uint8_t process_a_healthy;
48 volatile uint8_t process_b_healthy;
49 uint32_t timestamp_ms;
52__attribute__((aligned(64)))
65 { .train_id = 101, .position = 500 },
66 { .train_id = 102, .position = 2500 },
67 { .train_id = 103, .position = 7500 },
70#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
76static uint32_t crc32_checksum(
const uint8_t *data, uint32_t len)
78 uint32_t crc = 0xffffffff;
79 for (uint32_t i = 0; i < len; i++) {
80 uint8_t
byte = data[i];
81 crc = (crc >> 8) ^ (uint32_t)(crc ^ byte);
83 return crc ^ 0xffffffff;
90static train_command_t compute_train_command(uint32_t train_id, uint32_t position)
96 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
101 if (position < 1000) {
102 cmd.signal_state = 2;
103 cmd.speed_limit = 80;
104 }
else if (position < 5000) {
105 cmd.signal_state = 1;
106 cmd.speed_limit = 40;
107 }
else if (position < 9000) {
108 cmd.signal_state = 0;
111 cmd.emergency_stop = 1;
112 cmd.signal_state = 0;
116 uint8_t *cmd_bytes = (uint8_t *)&cmd;
117 cmd.checksum = crc32_checksum(cmd_bytes,
118 sizeof(cmd) -
sizeof(cmd.checksum));
127int main(
int argc,
char *argv[])
132 uint32_t cycle_count = 0;
133 uint32_t process_b_seq = 0;
134 uint32_t mismatch_count = 0;
136 fprintf(stderr,
"[WEST:B] Process B (Vital Channel B) starting\n");
137 fprintf(stderr,
"[WEST:B] Verifying commands every 25ms\n");
144 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
145 trains[i].position += (i + 1) * 3;
146 if (trains[i].position > 10000) {
147 trains[i].position = 10000;
152 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
157 cmd.sequence_number = process_b_seq;
160 shared_mem.cmd_b = cmd;
161 shared_mem.process_b_seq = process_b_seq;
162 __sync_synchronize();
163 shared_mem.ready_b = 1;
166 if (shared_mem.ready_a &&
167 shared_mem.process_a_seq == process_b_seq) {
169 if (shared_mem.cmd_a.signal_state != cmd.signal_state ||
170 shared_mem.cmd_a.speed_limit != cmd.speed_limit) {
174 "[WEST:B] MISMATCH detected cycle %u: "
175 "A(sig=%u,spd=%u) vs B(sig=%u,spd=%u)\n",
177 shared_mem.cmd_a.signal_state,
178 shared_mem.cmd_a.speed_limit,
179 cmd.signal_state, cmd.speed_limit);
183 if (cycle_count % 10 == 0) {
185 "[WEST:B] Cycle %u: train=%u, pos=%u, sig=%u, speed=%u "
187 cycle_count, cmd.train_id, cmd.position,
188 cmd.signal_state, cmd.speed_limit, mismatch_count);
193 shared_mem.process_b_healthy = 1;