@@ -95,11 +95,15 @@ use core::mem::MaybeUninit;
9595pub ( crate ) use esp_alloc:: InternalMemory ;
9696#[ cfg( any( multi_core, riscv) ) ]
9797use esp_hal:: interrupt:: software:: SoftwareInterrupt ;
98+ #[ cfg( systimer) ]
99+ use esp_hal:: timer:: systimer:: Alarm ;
100+ #[ cfg( timergroup) ]
101+ use esp_hal:: timer:: timg:: Timer ;
98102use esp_hal:: {
99103 Blocking ,
100104 system:: Cpu ,
101105 time:: { Duration , Instant } ,
102- timer:: { AnyTimer , OneShotTimer } ,
106+ timer:: { AnyTimer , OneShotTimer , any :: Degrade } ,
103107} ;
104108#[ cfg( multi_core) ]
105109use esp_hal:: {
@@ -205,9 +209,9 @@ mod esp_alloc {
205209 }
206210}
207211
208- /// A trait to allow better UX for initializing esp-rtos .
212+ /// Timers that can be used as time drivers .
209213 ///
210- /// This trait is meant to be used only for the `init` function.
214+ /// This trait is meant to be used only for the [`start`] function.
211215pub trait TimerSource : private:: Sealed + ' static {
212216 /// Returns the timer source.
213217 fn timer ( self ) -> TimeBase ;
@@ -220,28 +224,44 @@ mod private {
220224impl private:: Sealed for TimeBase { }
221225impl private:: Sealed for AnyTimer < ' static > { }
222226#[ cfg( timergroup) ]
223- impl private:: Sealed for esp_hal :: timer :: timg :: Timer < ' static > { }
227+ impl private:: Sealed for Timer < ' static > { }
224228#[ cfg( systimer) ]
225- impl private:: Sealed for esp_hal:: timer:: systimer:: Alarm < ' static > { }
229+ impl private:: Sealed for Alarm < ' static > { }
230+
231+ impl TimerSource for TimeBase {
232+ fn timer ( self ) -> TimeBase {
233+ self
234+ }
235+ }
226236
227- impl < T > TimerSource for T
228- where
229- T : esp_hal:: timer:: any:: Degrade + private:: Sealed + ' static ,
230- {
237+ impl TimerSource for AnyTimer < ' static > {
231238 fn timer ( self ) -> TimeBase {
232- let any_timer: AnyTimer < ' static > = self . degrade ( ) ;
233- TimeBase :: new ( any_timer)
239+ TimeBase :: new ( self )
240+ }
241+ }
242+
243+ #[ cfg( timergroup) ]
244+ impl TimerSource for Timer < ' static > {
245+ fn timer ( self ) -> TimeBase {
246+ TimeBase :: new ( self . degrade ( ) )
247+ }
248+ }
249+
250+ #[ cfg( systimer) ]
251+ impl TimerSource for Alarm < ' static > {
252+ fn timer ( self ) -> TimeBase {
253+ TimeBase :: new ( self . degrade ( ) )
234254 }
235255}
236256
237257/// Starts the scheduler.
238258///
239259/// The current context will be converted into the main task, and will be pinned to the first core.
240260///
241- /// This function is equivalent to [start_with_idle_hook], with the default idle hook. The default
261+ /// This function is equivalent to [` start_with_idle_hook` ], with the default idle hook. The default
242262/// idle hook will wait for an interrupt.
243263///
244- /// For information about the other arguments, see [start_with_idle_hook].
264+ /// For information about the arguments, see [` start_with_idle_hook` ].
245265pub fn start ( timer : impl TimerSource , #[ cfg( riscv) ] int0 : SoftwareInterrupt < ' static , 0 > ) {
246266 start_with_idle_hook (
247267 timer,
@@ -265,6 +285,7 @@ pub fn start(timer: impl TimerSource, #[cfg(riscv)] int0: SoftwareInterrupt<'sta
265285/// - A timg `Timer` instance
266286/// - A systimer `Alarm` instance
267287/// - An `AnyTimer` instance
288+ /// - A `OneShotTimer` instance
268289#[ doc = "" ]
269290#[ cfg_attr(
270291 riscv,
@@ -337,6 +358,10 @@ pub fn start_with_idle_hook(
337358///
338359/// The supplied stack and function will be used as the main thread of the second core. The thread
339360/// will be pinned to the second core.
361+ ///
362+ /// You can return from the second core's main thread function. This will cause the scheduler to
363+ /// enter the idle state, but the second core will continue to run interrupt handlers and other
364+ /// tasks.
340365#[ cfg( multi_core) ]
341366pub fn start_second_core < const STACK_SIZE : usize > (
342367 cpu_control : CPU_CTRL ,
@@ -351,10 +376,7 @@ pub fn start_second_core<const STACK_SIZE: usize>(
351376 int0,
352377 int1,
353378 stack,
354- Some ( esp_config:: esp_config_int!(
355- usize ,
356- "ESP_HAL_CONFIG_STACK_GUARD_OFFSET"
357- ) ) ,
379+ None ,
358380 func,
359381 ) ;
360382}
@@ -365,6 +387,14 @@ pub fn start_second_core<const STACK_SIZE: usize>(
365387///
366388/// The supplied stack and function will be used as the main thread of the second core. The thread
367389/// will be pinned to the second core.
390+ ///
391+ /// The stack guard offset is used to reserve a portion of the stack for the stack guard, for safety
392+ /// purposes. Passing `None` will result in the default value configured by the
393+ /// `ESP_HAL_CONFIG_STACK_GUARD_OFFSET` esp-hal configuration.
394+ ///
395+ /// You can return from the second core's main thread function. This will cause the scheduler to
396+ /// enter the idle state, but the second core will continue to run interrupt handlers and other
397+ /// tasks.
368398#[ cfg( multi_core) ]
369399pub fn start_second_core_with_stack_guard_offset < const STACK_SIZE : usize > (
370400 cpu_control : CPU_CTRL ,
@@ -390,9 +420,14 @@ pub fn start_second_core_with_stack_guard_offset<const STACK_SIZE: usize>(
390420 ) ,
391421 } ;
392422
423+ let stack_guard_offset = stack_guard_offset. unwrap_or ( esp_config:: esp_config_int!(
424+ usize ,
425+ "ESP_HAL_CONFIG_STACK_GUARD_OFFSET"
426+ ) ) ;
427+
393428 let mut cpu_control = CpuControl :: new ( cpu_control) ;
394429 let guard = cpu_control
395- . start_app_core_with_stack_guard_offset ( stack, stack_guard_offset, move || {
430+ . start_app_core_with_stack_guard_offset ( stack, Some ( stack_guard_offset) , move || {
396431 trace ! ( "Second core running" ) ;
397432 task:: setup_smp ( int1) ;
398433 SCHEDULER . with ( move |scheduler| {
@@ -405,12 +440,7 @@ pub fn start_second_core_with_stack_guard_offset<const STACK_SIZE: usize>(
405440
406441 // esp-hal may be configured to use a watchpoint. To work around that, we read the
407442 // memory at the stack guard, and we'll use whatever we find as the main task's
408- // stack guard value.
409- let stack_guard_offset = stack_guard_offset. unwrap_or ( esp_config:: esp_config_int!(
410- usize ,
411- "ESP_HAL_CONFIG_STACK_GUARD_OFFSET"
412- ) ) ;
413-
443+ // stack guard value, instead of writing our own stack guard value.
414444 let stack_bottom = ptrs. stack . cast :: < u32 > ( ) ;
415445 let stack_guard = unsafe { stack_bottom. byte_add ( stack_guard_offset) } ;
416446
@@ -429,6 +459,11 @@ pub fn start_second_core_with_stack_guard_offset<const STACK_SIZE: usize>(
429459 } )
430460 . unwrap ( ) ;
431461
462+ // Spin until the second core scheduler is initialized
463+ while SCHEDULER . with ( |s| !s. per_cpu [ 1 ] . initialized ) {
464+ esp_hal:: rom:: ets_delay_us ( 1 ) ;
465+ }
466+
432467 core:: mem:: forget ( guard) ;
433468}
434469
0 commit comments