Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
process_a.c
Go to the documentation of this file.
1
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <stdint.h>
22#include <unistd.h>
23#include <time.h>
24
25/* ============================================================================
26 * Shared Memory
27 * ========================================================================== */
28
29typedef struct {
30 uint32_t train_id;
31 uint32_t position;
32 uint8_t signal_state;
33 uint8_t emergency_stop;
34 uint16_t speed_limit;
35 uint32_t timestamp_ms;
36 uint32_t checksum;
37 uint32_t sequence_number;
39
40typedef struct {
41 train_command_t cmd_a;
42 train_command_t cmd_b;
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;
51
52__attribute__((aligned(64)))
53static shared_state_t shared_mem = {0};
54
55/* ============================================================================
56 * Train Database (Synchronized with WEST)
57 * ========================================================================== */
58
59typedef struct {
60 uint32_t train_id;
61 uint32_t position;
63
64static train_db_entry_t trains[] = {
65 { .train_id = 101, .position = 500 },
66 { .train_id = 102, .position = 2500 },
67 { .train_id = 103, .position = 7500 },
68};
69
70#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
71
72/* ============================================================================
73 * CRC32
74 * ========================================================================== */
75
76static uint32_t crc32_checksum(const uint8_t *data, uint32_t len)
77{
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);
82 }
83 return crc ^ 0xffffffff;
84}
85
86/* ============================================================================
87 * Process A (Standby - mirrors WEST)
88 * ========================================================================== */
89
90static train_command_t compute_train_command(uint32_t train_id, uint32_t position)
91{
92 train_command_t cmd = {
93 .train_id = train_id,
94 .position = position,
95 .emergency_stop = 0,
96 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
97 .sequence_number = 0,
98 };
99
100 if (position < 1000) {
101 cmd.signal_state = 2;
102 cmd.speed_limit = 80;
103 } else if (position < 5000) {
104 cmd.signal_state = 1;
105 cmd.speed_limit = 40;
106 } else if (position < 9000) {
107 cmd.signal_state = 0;
108 cmd.speed_limit = 0;
109 } else {
110 cmd.emergency_stop = 1;
111 cmd.signal_state = 0;
112 cmd.speed_limit = 0;
113 }
114
115 uint8_t *cmd_bytes = (uint8_t *)&cmd;
116 cmd.checksum = crc32_checksum(cmd_bytes,
117 sizeof(cmd) - sizeof(cmd.checksum));
118
119 return cmd;
120}
121
122/* ============================================================================
123 * Main Loop
124 * ========================================================================== */
125
126int main(int argc, char *argv[])
127{
128 (void)argc;
129 (void)argv;
130
131 uint32_t cycle_count = 0;
132 uint32_t process_a_seq = 0;
133
134 fprintf(stderr, "[EAST:A] Process A (Standby Channel A) starting\n");
135 fprintf(stderr, "[EAST:A] Synchronizing with WEST (role: STANDBY)\n");
136
137 while (1) {
138 cycle_count++;
139 process_a_seq++;
140
141 /* Synchronize train positions with WEST */
142 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
143 trains[i].position += (i + 1) * 3;
144 if (trains[i].position > 10000) {
145 trains[i].position = 10000;
146 }
147 }
148
149 /* Compute commands (keeping in sync for failover) */
150 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
151 train_command_t cmd = compute_train_command(
152 trains[i].train_id,
153 trains[i].position
154 );
155 cmd.sequence_number = process_a_seq;
156
157 shared_mem.cmd_a = cmd;
158 shared_mem.process_a_seq = process_a_seq;
159 __sync_synchronize();
160 shared_mem.ready_a = 1;
161
162 if (cycle_count % 10 == 0) {
163 fprintf(stderr,
164 "[EAST:A] Cycle %u (STANDBY): train=%u, pos=%u, sig=%u, speed=%u\n",
165 cycle_count, cmd.train_id, cmd.position,
166 cmd.signal_state, cmd.speed_limit);
167 }
168 }
169
170 shared_mem.process_a_healthy = 1;
171 usleep(25000);
172 }
173
174 return EXIT_SUCCESS;
175}
Definition process_a.c:64