1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! Set of traits used to trace RTOS internals.
//! 
//! # Features
//! 
//! - `trace_impl`: Activates tracing function (on by default). Can be used by 
//!    the RTOS to deactivate tracing.
//! 
//! # Implementation
//! 
//! The backend is required implement [`RtosTrace`](crate::RtosTrace).
//! 
//! Existing implementation:
//! - [SEGGER SystemView](https://docs.rs/systemview-target/)
//! 
//! # Usage
//! 
//! ## RTOS
//! 
//! The RTOS can implement [`RtosTraceOSCallbacks`](crate::RtosTraceOSCallbacks) to provide additional 
//! information upon request from the tracing software. For example:
//! ```ignore
//! rtos_trace::global_os_callbacks!{Scheduler}
//! 
//! impl rtos_trace::RtosTraceOSCallbacks for Scheduler {
//!     fn task_list() {
//!         /*..*/
//!         for task in tasks.iter() {
//!             trace::task_send_info(task.id(), task.info());
//!         }
//!     }
//!     /*..*/
//! }
//! ```
//! 
//! Usage for the RTOS maintainer is simple:
//! ```ignore
//! use rtos_trace::{RtosTrace, trace}
//! 
//! pub fn spawn_task(/*..*/) {
//!     /*..*/
//!     trace::task_new(task_id);
//! }
//! ```
//! 
//! ## Application
//! 
//! Similar to a global logger the user must provide a tracing backend, i.e.:
//! ```ìgnore
//! use systemview_target::SystemView;
//! rtos_trace::global_trace!{SystemView}
//! ```
//! 
//! The user can implement [`RtosTraceApplicationCallbacks`] to provide 
//! additional information upon request from the tracing software. For example:
//! ```ignore
//! struct Application;
//! rtos_trace::global_application_callbacks!{Application}
//! 
//! impl rtos_trace::RtosTraceApplicationCallbacks for Application {
//!     fn system_description() {
//!         systemview_target::send_system_desc_app_name!("Espresso Machine");
//!         systemview_target::send_system_desc_device!("STM32F769NI");
//!         systemview_target::send_system_desc_core!("Cortex-M7");
//!         systemview_target::send_system_desc_os!("Bern RTOS");
//!         systemview_target::send_system_desc_interrupt!(15, "SysTick");
//!     }
//!     /*..*/
//! }
//! 
//! ```

#![no_std]

mod macros;
pub mod trace;

/// Task info block.
pub struct  TaskInfo {
    /// Names as static string.
    pub name: &'static str,
    /// Task priority number.
    pub priority: u32,
    /// Start address of the stack.
    pub stack_base: usize,
    /// Size of the stack in bytes.
    pub stack_size: usize,
}

/// Collection of tracing functions which are called by the RTOS.
pub trait RtosTrace {
    /// A new task with `id` was created.
    fn task_new(id: u32);
    /// The task with `id` has `info` attributes.
    fn task_send_info(id: u32, info: TaskInfo);
    /// The task with `id` has been terminated.
    fn task_terminate(id: u32);
    /// The task with `id` will start to run on the CPU now.
    fn task_exec_begin(id: u32);
    /// Execution of the current task has ended.
    fn task_exec_end();
    /// The task with `id` is ready to run.
    fn task_ready_begin(id: u32);
    /// The task with `id` is being blocked/suspended.
    fn task_ready_end(id: u32);

    /// The RTOS enters idle mode.
    fn system_idle();

    /// Enter an ISR.
    fn isr_enter();
    /// Exit an ISR.
    fn isr_exit();
    /// Exit an ISR to the scheduler.
    fn isr_exit_to_scheduler();

    /// Create a new marker with `id`.
    fn marker(id: u32);
    /// Begin event of marker with `id`.
    fn marker_begin(id: u32);
    /// End event of marker with `id`.
    fn marker_end(id: u32);
}

/// Callbacks to the OS invoked by the tracing system.
/// This trait can be implemented in the RTOS.
pub trait RtosTraceOSCallbacks {
    /// Send a list of all tasks to the tracing system.
    fn task_list();
    /// Get system time in microseconds.
    fn time() -> u64;
}

/// Callbacks to the application invoked by the tracing system.
/// This trait can be implemented by user.
pub trait RtosTraceApplicationCallbacks {
    /// Send a system and application description to the tracing system.
    fn system_description();
    /// Get system clock in Hertz.
    fn sysclock() -> u32;
}