osal_rs/freertos/
system.rs1use core::fmt::Debug;
21use core::ops::Deref;
22use core::time::Duration;
23
24use alloc::vec::Vec;
25
26use super::ffi::{
27 BLOCKED, DELETED, READY, RUNNING, SUSPENDED, TaskStatus, eTaskGetState, osal_rs_critical_section_enter, osal_rs_critical_section_exit, osal_rs_port_end_switching_isr, osal_rs_port_yield_from_isr, uxTaskGetNumberOfTasks, uxTaskGetSystemState, vTaskDelay, vTaskEndScheduler, vTaskStartScheduler, vTaskSuspendAll, xPortGetFreeHeapSize, xTaskDelayUntil, xTaskGetCurrentTaskHandle, xTaskGetTickCount, xTaskResumeAll
28};
29use super::thread::{ThreadState, ThreadMetadata};
30use super::types::{BaseType, TickType, UBaseType};
31use crate::tick_period_ms;
32use crate::traits::{SystemFn, ToTick};
33use crate::utils::{CpuRegisterSize::*, register_bit_size, OsalRsBool};
34
35#[derive(Debug, Clone)]
36pub struct SystemState {
37 pub tasks: Vec<ThreadMetadata>,
38 pub total_run_time: u32
39}
40
41impl Deref for SystemState {
42 type Target = [ThreadMetadata];
43
44 fn deref(&self) -> &Self::Target {
45 &self.tasks
46 }
47}
48
49pub struct System;
50
51impl System {
52 #[inline]
53 pub fn delay_with_to_tick(ticks: impl ToTick){
54 Self::delay(ticks.to_ticks());
55 }
56
57 #[inline]
58 pub fn delay_until_with_to_tick(previous_wake_time: &mut TickType, time_increment: impl ToTick) {
59 Self::delay_until(previous_wake_time, time_increment.to_ticks());
60 }
61}
62
63impl SystemFn for System {
64 fn start() {
65 unsafe {
66 vTaskStartScheduler();
67 }
68 }
69
70 fn get_state() -> ThreadState {
71 use super::thread::ThreadState::*;
72 let state = unsafe { eTaskGetState(xTaskGetCurrentTaskHandle()) };
73 match state {
74 RUNNING => Running,
75 READY => Ready,
76 BLOCKED => Blocked,
77 SUSPENDED => Suspended,
78 DELETED => Deleted,
79 _ => Invalid, }
81 }
82
83 fn suspend_all() {
84 unsafe {
85 vTaskSuspendAll();
86 }
87 }
88 fn resume_all() -> BaseType {
89 unsafe { xTaskResumeAll() }
90 }
91
92 fn stop() {
93 unsafe {
94 vTaskEndScheduler();
95 }
96 }
97
98 fn get_tick_count() -> TickType {
99 unsafe { xTaskGetTickCount() }
100 }
101
102 fn get_current_time_us () -> Duration {
103 let ticks = Self::get_tick_count();
104 Duration::from_millis( 1_000 * ticks as u64 / tick_period_ms!() as u64 )
105 }
106
107 fn get_us_from_tick(duration: &Duration) -> TickType {
108 let millis = duration.as_millis() as TickType;
109 millis / (1_000 * tick_period_ms!() as TickType)
110 }
111
112 fn count_threads() -> usize {
113 unsafe { uxTaskGetNumberOfTasks() as usize }
114 }
115
116 fn get_all_thread() -> SystemState {
117 let threads_count = Self::count_threads();
118 let mut threads: Vec<TaskStatus> = Vec::with_capacity(threads_count);
119 let mut total_run_time: u32 = 0;
120
121 unsafe {
122 let count = uxTaskGetSystemState(
123 threads.as_mut_ptr(),
124 threads_count as UBaseType,
125 &raw mut total_run_time,
126 ) as usize;
127
128 threads.set_len(count);
130 }
131
132 let tasks = threads.into_iter()
133 .map(|task_status| {
134 ThreadMetadata::from((
135 task_status.xHandle,
136 task_status
137 ))
138 }).collect();
139
140 SystemState {
141 tasks,
142 total_run_time
143 }
144 }
145
146
147 fn delay(ticks: TickType){
148 unsafe {
149 vTaskDelay(ticks);
150 }
151 }
152
153 fn delay_until(previous_wake_time: &mut TickType, time_increment: TickType) {
154 unsafe {
155 xTaskDelayUntil(
156 previous_wake_time,
157 time_increment,
158 );
159 }
160 }
161
162 fn critical_section_enter() {
163 unsafe {
164 osal_rs_critical_section_enter();
165 }
166 }
167
168 fn critical_section_exit() {
169 unsafe {
170 osal_rs_critical_section_exit();
171 }
172 }
173
174 fn check_timer(timestamp: &Duration, time: &Duration) -> OsalRsBool {
175 let temp_tick_time = Self::get_current_time_us();
176
177 let time_passing = if temp_tick_time >= *timestamp {
178 temp_tick_time - *timestamp
179 } else {
180 if register_bit_size() == Bit32 {
181 let overflow_correction = Duration::from_micros(0xff_ff_ff_ff_u64);
183 overflow_correction - *timestamp + temp_tick_time
184 } else {
185 let overflow_correction = Duration::from_micros(0xff_ff_ff_ff_ff_ff_ff_ff_u64);
187 overflow_correction - *timestamp + temp_tick_time
188 }
189 };
190
191 if time_passing >= *time {
192 OsalRsBool::True
193 } else {
194 OsalRsBool::False
195 }
196 }
197
198 fn yield_from_isr(higher_priority_task_woken: BaseType) {
199 unsafe {
200 osal_rs_port_yield_from_isr(higher_priority_task_woken);
201 }
202 }
203
204 fn end_switching_isr( switch_required: BaseType ) {
205 unsafe {
206 osal_rs_port_end_switching_isr( switch_required );
207 }
208 }
209
210 fn get_free_heap_size() -> usize {
211 unsafe {
212 xPortGetFreeHeapSize()
213 }
214 }
215
216}
217