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
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 Interface (IPC with other processes)
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; /* Written by Process A */
42 train_command_t cmd_b; /* Written by Process B */
43 uint32_t process_a_seq; /* Sequence number from A */
44 uint32_t process_b_seq; /* Sequence number from B */
45 volatile uint8_t ready_a; /* 1 when cmd_a is valid */
46 volatile uint8_t ready_b; /* 1 when cmd_b is valid */
47 volatile uint8_t process_a_healthy; /* Health status */
48 volatile uint8_t process_b_healthy; /* Health status */
49 uint32_t timestamp_ms;
51
52/* Global shared memory (in production: mapped file or IPC) */
53__attribute__((aligned(64)))
54static shared_state_t shared_mem = {0};
55
56/* ============================================================================
57 * Simulated Train Database
58 * ========================================================================== */
59
60typedef struct {
61 uint32_t train_id;
62 uint32_t position;
64
65static train_db_entry_t trains[] = {
66 { .train_id = 101, .position = 500 },
67 { .train_id = 102, .position = 2500 },
68 { .train_id = 103, .position = 7500 },
69};
70
71#define TRAIN_COUNT (sizeof(trains) / sizeof(trains[0]))
72
73/* ============================================================================
74 * CRC32 Checksum
75 * ========================================================================== */
76
77static uint32_t crc32_checksum(const uint8_t *data, uint32_t len)
78{
79 uint32_t crc = 0xffffffff;
80 for (uint32_t i = 0; i < len; i++) {
81 uint8_t byte = data[i];
82 crc = (crc >> 8) ^ (uint32_t)(crc ^ byte);
83 }
84 return crc ^ 0xffffffff;
85}
86
87/* ============================================================================
88 * Process A: Compute Train Commands (Vital Channel)
89 * ========================================================================== */
90
91static train_command_t compute_train_command(uint32_t train_id, uint32_t position)
92{
93 train_command_t cmd = {
94 .train_id = train_id,
95 .position = position,
96 .emergency_stop = 0,
97 .timestamp_ms = (uint32_t)(time(NULL) * 1000) & 0xffffffff,
98 .sequence_number = 0,
99 };
100
101 /* Safety-critical signal logic */
102 if (position < 1000) {
103 cmd.signal_state = 2; /* Green */
104 cmd.speed_limit = 80;
105 } else if (position < 5000) {
106 cmd.signal_state = 1; /* Yellow */
107 cmd.speed_limit = 40;
108 } else if (position < 9000) {
109 cmd.signal_state = 0; /* Red */
110 cmd.speed_limit = 0;
111 } else {
112 cmd.emergency_stop = 1; /* Beyond end of track */
113 cmd.signal_state = 0;
114 cmd.speed_limit = 0;
115 }
116
117 /* Compute integrity checksum (SIL 4 requirement) */
118 uint8_t *cmd_bytes = (uint8_t *)&cmd;
119 cmd.checksum = crc32_checksum(cmd_bytes,
120 sizeof(cmd) - sizeof(cmd.checksum));
121
122 return cmd;
123}
124
125/* ============================================================================
126 * Main Loop
127 * ========================================================================== */
128
129int main(int argc, char *argv[])
130{
131 (void)argc;
132 (void)argv;
133
134 uint32_t cycle_count = 0;
135 uint32_t process_a_seq = 0;
136
137 fprintf(stderr, "[WEST:A] Process A (Vital Channel A) starting\n");
138 fprintf(stderr, "[WEST:A] Computing train commands every 25ms\n");
139
140 while (1) {
141 cycle_count++;
142 process_a_seq++;
143
144 /* Simulate train movement */
145 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
146 trains[i].position += (i + 1) * 3; /* Different speeds */
147 if (trains[i].position > 10000) {
148 trains[i].position = 10000;
149 }
150 }
151
152 /* Compute commands for all trains */
153 for (uint32_t i = 0; i < TRAIN_COUNT; i++) {
154 train_command_t cmd = compute_train_command(
155 trains[i].train_id,
156 trains[i].position
157 );
158 cmd.sequence_number = process_a_seq;
159
160 /* Write to shared memory */
161 shared_mem.cmd_a = cmd;
162 shared_mem.process_a_seq = process_a_seq;
163 __sync_synchronize(); /* Memory fence */
164 shared_mem.ready_a = 1;
165
166 if (cycle_count % 10 == 0) {
167 fprintf(stderr,
168 "[WEST:A] Cycle %u: train=%u, pos=%u, sig=%u, speed=%u\n",
169 cycle_count, cmd.train_id, cmd.position,
170 cmd.signal_state, cmd.speed_limit);
171 }
172 }
173
174 /* Mark as healthy */
175 shared_mem.process_a_healthy = 1;
176
177 /* Sleep 25ms (deterministic cycle) */
178 usleep(25000);
179 }
180
181 return EXIT_SUCCESS;
182}
Definition process_a.c:64