a653rs/apex/
error.rs

1/// bindings for ARINC653P1-5 3.8 health monitoring
2pub mod basic {
3    use crate::apex::process::basic::*;
4    use crate::apex::types::basic::*;
5
6    /// ARINC653P1-5 3.8.1 Maximum message size in bytes
7    pub const MAX_ERROR_MESSAGE_SIZE: usize = 128;
8
9    /// ARINC653P1-5 3.8.1
10    pub type ErrorMessageSize = ApexInteger;
11    /// ARINC653P1-5 3.8.1
12    pub type ErrorMessage = [ApexByte; MAX_ERROR_MESSAGE_SIZE];
13
14    /// ARINC653P1-5 3.8.1 Process level error
15    #[repr(u32)]
16    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
17    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18    #[cfg_attr(feature = "strum", derive(strum::FromRepr))]
19    pub enum ErrorCode {
20        DeadlineMissed = 0,
21        /// error raised by [raise_application_error](crate::prelude::ApexErrorP4Ext::raise_application_error)
22        ApplicationError = 1,
23        NumericError = 2,
24        /// unallowed syscall / OS request
25        IllegalRequest = 3,
26        StackOverflow = 4,
27        MemoryViolation = 5,
28        /// I/O error
29        HardwareFault = 6,
30        /// info for saving data before power off
31        PowerFail = 7,
32    }
33
34    /// ARINC653P1-5 3.8.1
35    #[derive(Debug, Clone, PartialEq, Eq)]
36    pub struct ErrorStatus {
37        /// related implementation dependent address
38        pub failed_address: SystemAddress,
39        pub failed_process_id: ProcessId,
40        pub error_code: ErrorCode,
41        /// error message length
42        pub length: ErrorMessageSize,
43        pub message: ErrorMessage,
44    }
45
46    /// ARINC653P1-5 3.8.1
47    #[repr(u32)]
48    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
49    #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50    #[cfg_attr(feature = "strum", derive(strum::FromRepr))]
51    pub enum ErrorHandlerConcurrencyControl {
52        /// processes are paused when error handler is active
53        ProcessesPause = 0,
54        /// processes run parallel to error handler
55        ProcessesScheduled = 1,
56    }
57
58    /// ARINC653P4 3.8.2 required functions for health monitoring functionality
59    pub trait ApexErrorP4 {
60        /// APEX653P4 3.8.2.1 report message to health monitor
61        ///
62        /// # Errors
63        /// - [ErrorReturnCode::InvalidParam]: `message` is too large
64        fn report_application_message(message: &[ApexByte]) -> Result<(), ErrorReturnCode>;
65
66        /// APEX653P4 3.8.2.4 trigger error handler process
67        ///
68        /// # Errors
69        /// - [ErrorReturnCode::InvalidParam]: `message` is larger than [MAX_ERROR_MESSAGE_SIZE]
70        /// - [ErrorReturnCode::InvalidParam]: `error_code` is not [ErrorCode::ApplicationError]
71        fn raise_application_error(
72            error_code: ErrorCode,
73            message: &[ApexByte],
74        ) -> Result<(), ErrorReturnCode>;
75    }
76
77    /// ARINC653P1-5 3.8.2 required functions for health monitoring functionality
78    pub trait ApexErrorP1 {
79        /// APEX653P1-5 3.8.2.2
80        ///
81        /// # Errors
82        /// - [ErrorReturnCode::NoAction]: error handler exists already
83        /// - [ErrorReturnCode::InvalidConfig]: not enough memory is available
84        /// - [ErrorReturnCode::InvalidConfig]: `stack_size` is too large
85        /// - [ErrorReturnCode::InvalidMode]: our current operating mode is [OperatingMode::Normal](crate::prelude::OperatingMode::Normal)
86        fn create_error_handler(
87            entry_point: SystemAddress,
88            stack_size: StackSize,
89        ) -> Result<(), ErrorReturnCode>;
90
91        /// APEX653P1-5 3.8.2.3 get current error status
92        ///
93        /// # Errors
94        /// - [ErrorReturnCode::InvalidConfig]: the calling process is not an error handler
95        /// - [ErrorReturnCode::NoAction]: no error exists right now
96        fn get_error_status() -> Result<ErrorStatus, ErrorReturnCode>;
97
98        /// APEX653P1-5 3.8.2.5
99        ///
100        /// # Errors
101        /// - [ErrorReturnCode::InvalidConfig]: no error handler exists
102        /// - [ErrorReturnCode::InvalidMode]: our current operating mode is [OperatingMode::Normal](crate::prelude::OperatingMode::Normal)
103        fn configure_error_handler(
104            concurrency_control: ErrorHandlerConcurrencyControl,
105            processor_core_id: ProcessorCoreId,
106        ) -> Result<(), ErrorReturnCode>;
107    }
108}
109
110/// abstraction for ARINC653P1-5 3.8 health monitoring
111pub mod abstraction {
112    use super::basic::{ApexErrorP1, ApexErrorP4};
113    // Reexport important basic-types for downstream-user
114    pub use super::basic::{
115        ErrorCode, ErrorHandlerConcurrencyControl, ErrorStatus, MAX_ERROR_MESSAGE_SIZE,
116    };
117    use crate::prelude::*;
118
119    /// Free extra functions for implementer of [ApexErrorP4]
120    pub trait ApexErrorP4Ext: ApexErrorP4 {
121        /// report message to health monitor
122        ///
123        /// # Errors
124        /// - [Error::InvalidParam]: `message` is too large
125        fn report_application_message(message: &[ApexByte]) -> Result<(), Error>;
126
127        /// trigger error handler process
128        ///
129        /// # Errors
130        /// - [Error::InvalidParam]: `message` is larger than [MAX_ERROR_MESSAGE_SIZE]
131        fn raise_application_error(message: &[ApexByte]) -> Result<(), Error>;
132    }
133
134    /// Free extra functions for implementer of [ApexErrorP1]
135    pub trait ApexErrorP1Ext: ApexErrorP1 {
136        /// get current error status
137        ///
138        /// # Errors
139        /// - [Error::InvalidConfig]: the calling process is not an error handler
140        /// - [Error::NoAction]: no error exists right now
141        fn error_status() -> Result<ErrorStatus, Error>;
142    }
143
144    impl<E: ApexErrorP4> ApexErrorP4Ext for E {
145        fn report_application_message(message: &[ApexByte]) -> Result<(), Error> {
146            E::report_application_message(message.validate_write(MAX_ERROR_MESSAGE_SIZE as u32)?)?;
147            Ok(())
148        }
149
150        fn raise_application_error(message: &[ApexByte]) -> Result<(), Error> {
151            E::raise_application_error(
152                ErrorCode::ApplicationError,
153                message.validate_write(MAX_ERROR_MESSAGE_SIZE as u32)?,
154            )?;
155            Ok(())
156        }
157    }
158
159    impl<E: ApexErrorP1> ApexErrorP1Ext for E {
160        fn error_status() -> Result<ErrorStatus, Error> {
161            Ok(E::get_error_status()?)
162        }
163    }
164
165    impl<E: ApexErrorP1> StartContext<E> {
166        /// # Errors
167        /// - [Error::NoAction]: error handler exists already
168        /// - [Error::InvalidConfig]: not enough memory is available
169        /// - [Error::InvalidConfig]: `stack_size` is too large
170        pub fn set_error_handler(
171            &self,
172            entry_point: SystemAddress,
173            stack_size: StackSize,
174        ) -> Result<(), Error> {
175            E::create_error_handler(entry_point, stack_size)?;
176            Ok(())
177        }
178
179        /// # Errors
180        /// - [Error::InvalidConfig]: no error handler exists
181        pub fn configure_error_handler(
182            &self,
183            concurrency_control: ErrorHandlerConcurrencyControl,
184            processor_core_id: ProcessorCoreId,
185        ) -> Result<(), Error> {
186            E::configure_error_handler(concurrency_control, processor_core_id)?;
187            Ok(())
188        }
189    }
190}