• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cbruiz / printhor / 13753907916

10 Mar 2025 12:08AM UTC coverage: 90.771% (+0.2%) from 90.599%
13753907916

Pull #35

github

web-flow
Merge 76633dfa7 into cc61929b1
Pull Request #35: Features/s_plot recovery

442 of 472 new or added lines in 7 files covered. (93.64%)

4 existing lines in 3 files now uncovered.

14832 of 16340 relevant lines covered (90.77%)

734462.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.39
/printhor/src/bin/printhor.rs
1
//! Main program (entry point)
2
#![allow(stable_features)]
3
#![cfg_attr(not(feature = "native"), no_std)]
4
#![cfg_attr(not(feature = "native"), no_main)]
5
#![doc = include_str!("../../design/architecture.md")]
6

7
extern crate alloc;
8
extern crate core;
9
pub mod control;
10
pub mod helpers;
11
pub mod hwa;
12

13
#[allow(unused)]
14
use hwa::{Contract, HwiContract, RawHwiResource};
15

16
use hwa::math;
17
#[allow(unused)]
18
use math::{Real, TVector};
19

20
//noinspection RsUnresolvedReference
21
///! Program entry point
UNCOV
22
#[embassy_executor::main]
×
23
async fn main(spawner: embassy_executor::Spawner) {
24
    printhor_main(spawner, true).await;
25
}
26

27
pub async fn printhor_main(spawner: embassy_executor::Spawner, keep_feeding: bool) {
4✔
28
    hwa::Contract::init_logger();
4✔
29
    hwa::info!("Log ready. Starting...");
4✔
30

31
    hwa::Contract::init_heap();
4✔
32
    hwa::info!(
4✔
33
        "Initializing {} {}",
4✔
34
        hwa::Contract::FIRMWARE_NAME,
35
        hwa::Contract::FIRMWARE_VERSION
36
    );
37

38
    let wdt = match sys_start(spawner).await {
4✔
39
        Ok(wdt) => wdt,
4✔
40
        Err(_) => {
41
            hwa::error!("Error starting system");
×
42
            panic!("Unable to start");
×
43
        }
44
    };
45

46
    // The core of the main function is just to periodically feed watchdog
47
    if keep_feeding {
4✔
48
        let mut ticker = embassy_time::Ticker::every(embassy_time::Duration::from_secs(2));
×
49
        loop {
50
            {
51
                wdt.lock().await.pet();
×
52
            }
×
53
            ticker.next().await;
×
54
        }
55
    }
4✔
56
}
4✔
57

58
async fn sys_start(
4✔
59
    spawner: embassy_executor::Spawner,
4✔
60
) -> Result<hwa::types::WatchDogController, ()> {
4✔
61
    //#region "Init contract"
62

63
    let context = hwa::Contract::init(spawner).await;
4✔
64

65
    hwa::info!(
4✔
66
        "HWI setup completed. Allocated {} bytes for context.",
4✔
67
        core::mem::size_of_val(&context)
4✔
68
    );
69
    hwa::info!(
4✔
70
        "Vector<Real> size: {} bytes",
4✔
71
        core::mem::size_of::<TVector<Real>>()
72
    );
73

74
    //#endregion
75

76
    //#region "Setup event bus"
77

78
    type EventBusMutexStrategyType = <hwa::Contract as HwiContract>::EventBusMutexStrategy;
79
    type EventBusPubSubMutexType = <hwa::Contract as HwiContract>::EventBusPubSubMutexType;
80

81
    let event_bus: hwa::GenericEventBus<EventBusMutexStrategyType, EventBusPubSubMutexType> =
4✔
82
        hwa::GenericEventBus::new(hwa::make_static_async_controller!(
4✔
83
            "EventBus",
84
            EventBusMutexStrategyType,
85
            hwa::EventBusChannelController::new(hwa::make_static_ref!(
4✔
86
                "EventBusChannel",
87
                hwa::EventBusPubSubType<EventBusPubSubMutexType>,
88
                hwa::EventBusPubSubType::new(),
4✔
89
            )),
4✔
90
        ));
4✔
91

4✔
92
    event_bus
4✔
93
        .publish_event(hwa::EventStatus::containing(hwa::EventFlags::SYS_BOOTING))
4✔
94
        .await;
4✔
95

96
    //#endregion
97

98
    //#region "Setup defer channel (if hotends or motion are enabled)"
99

100
    cfg_if::cfg_if! {
101
        if #[cfg(any(feature = "with-motion", feature = "with-hot-end", feature = "with-hot-bed"))] {
102
            type DeferChannelMutexType = <hwa::Contract as HwiContract>::DeferChannelMutexType;
103
            let _defer_channel: hwa::GenericDeferChannel<DeferChannelMutexType> = {
4✔
104
                hwa::GenericDeferChannel::new(hwa::make_static_ref!(
4✔
105
                    "DeferChannel",
106
                    hwa::DeferChannelChannelType<DeferChannelMutexType>,
107
                    hwa::DeferChannelChannelType::new()
4✔
108
                ))
3✔
109
            };
3✔
110
        }
3✔
111
    }
3✔
112

3✔
113
    //#endregion
3✔
114

3✔
115
    //#region "Setup motion broadcast channel (if with-motion-broadcast is enabled)"
3✔
116

3✔
117
    cfg_if::cfg_if! {
3✔
118
        if #[cfg(all(feature = "with-motion", feature = "with-motion-broadcast"))] {
3✔
119
            type MotionBroadcastChannelMutexType = <hwa::Contract as HwiContract>::MotionBroadcastChannelMutexType;
3✔
120
            let _motion_broadcast_channel: hwa::GenericMotionBroadcastChannel<MotionBroadcastChannelMutexType> = {
4✔
121
                hwa::GenericMotionBroadcastChannel::new(hwa::make_static_ref!(
4✔
122
                    "MotionBroadcastChannel",
3✔
123
                    hwa::MotionBroadcastChannelType<MotionBroadcastChannelMutexType>,
3✔
124
                    hwa::MotionBroadcastChannelType::new()
4✔
125
                ))
4✔
126
            };
4✔
127
        }
4✔
128
    }
4✔
129

4✔
130
    //#endregion
4✔
131

4✔
132
    //#region "Setup System WatchDog"
4✔
133

4✔
134
    let sys_watch_dog = context.sys_watch_dog.clone();
4✔
135
    sys_watch_dog.lock().await.unleash();
4✔
136

4✔
137
    //#endregion
4✔
138

4✔
139
    //#region "Init controllers and spawn Tasks"
4✔
140
    cfg_if::cfg_if! {
4✔
141
        if #[cfg(any(feature="with-motion-stepper", feature="with-motion-broadcast"))] {
4✔
142
            Contract::setup_ticker()
4✔
143
        }
4✔
144
    }
4✔
145
    //#endregion
4✔
146

4✔
147
    //#region "Init controllers and spawn Tasks"
4✔
148

4✔
149
    if init_controllers_and_spawn_tasks(
4✔
150
        spawner,
4✔
151
        event_bus.clone(),
4✔
152
        #[cfg(any(
4✔
153
            feature = "with-motion",
4✔
154
            feature = "with-hot-end",
4✔
155
            feature = "with-hot-bed"
4✔
156
        ))]
4✔
157
        _defer_channel,
4✔
158
        #[cfg(all(feature = "with-motion", feature = "with-motion-broadcast"))]
4✔
159
        _motion_broadcast_channel,
4✔
160
        context,
4✔
161
        sys_watch_dog.clone(),
4✔
162
    )
4✔
163
    .await
4✔
164
    .is_ok()
4✔
165
    {
166
        event_bus
4✔
167
            .publish_event(hwa::EventStatus::not_containing(
4✔
168
                hwa::EventFlags::SYS_BOOTING,
4✔
169
            ))
4✔
170
            .await;
4✔
171

172
        cfg_if::cfg_if! {
173
            if #[cfg(feature = "with-motion")] {
174
                let mut event_suscriber = event_bus.subscriber().await;
4✔
175
                if event_suscriber.ft_wait_until(hwa::EventFlags::MOV_QUEUE_EMPTY).await.is_err() {
4✔
176
                    initialization_error()
×
177
                }
4✔
178
            }
179
        }
180

181
        hwa::info!(
4✔
182
            "Tasks spawned. Allocated {} bytes for shared state. Firing SYS_READY.",
4✔
183
            hwa::Contract::stack_reservation_current_size(),
4✔
184
        );
185
        event_bus
4✔
186
            .publish_event(hwa::EventStatus::containing(hwa::EventFlags::SYS_READY))
4✔
187
            .await;
4✔
188
        Ok(sys_watch_dog)
4✔
189
    } else {
190
        event_bus
×
191
            .publish_event(hwa::EventStatus::containing(
×
192
                hwa::EventFlags::SYS_BOOT_FAILURE,
×
193
            ))
×
194
            .await;
×
195
        hwa::error!("Unable start. Any task launch failed");
×
196
        Err(())
×
197
    }
198

199
    //#endregion
200
}
4✔
201

202
async fn init_controllers_and_spawn_tasks(
4✔
203
    spawner: embassy_executor::Spawner,
4✔
204
    event_bus: hwa::types::EventBus,
4✔
205
    #[cfg(any(
4✔
206
        feature = "with-motion",
4✔
207
        feature = "with-hot-end",
4✔
208
        feature = "with-hot-bed"
4✔
209
    ))]
4✔
210
    _defer_channel: hwa::types::DeferChannel,
4✔
211
    #[cfg(all(feature = "with-motion", feature = "with-motion-broadcast"))]
4✔
212
    _motion_broadcast_channel: hwa::types::MotionBroadcastChannel,
4✔
213
    _context: hwa::HwiContext<hwa::Contract>,
4✔
214
    _wd: hwa::types::WatchDogController,
4✔
215
) -> Result<(), ()> {
4✔
216
    //#region "Init printer controller (if with-print-job is set)"
4✔
217

4✔
218
    cfg_if::cfg_if! {
4✔
219
        if #[cfg(feature = "with-print-job")] {
4✔
220
            let printer_controller = hwa::controllers::PrinterController::new(event_bus.clone());
4✔
221
        }
222
    }
223

224
    //#endregion
225

226
    //#region "Init Probe controller (if with-probe is set)"
227

228
    cfg_if::cfg_if! {
229
        if #[cfg(feature = "with-probe")] {
230

231
            let probe_controller = hwa::make_static_async_controller!(
4✔
232
                "ProbeController",
233
                hwa::types::ProbeControllerMutexStrategy,
234
                hwa::types::InnerProbeController::new(
4✔
235
                    _context.probe_pwm,
4✔
236
                    _context.probe_pwm_channel.take(),
4✔
237
                )
4✔
238
            );
239
        }
240
    }
241

242
    //#endregion
243

244
    //#region "Init HotEnd controller (if with-hot-end is set)"
245

246
    cfg_if::cfg_if! {
247
        if #[cfg(feature = "with-hot-end")] {
248
            let hot_end_controller: hwa::types::HotEndController = hwa::make_static_async_controller!(
2✔
249
                "HotEndController",
250
                hwa::types::HotEndControllerMutexStrategy,
251
                hwa::controllers::HeaterController::new(
2✔
252
                    hwa::types::HotEndAdcController::new(
2✔
253
                        _context.hot_end_adc,
2✔
254
                        _context.hot_end_adc_pin.take(),
2✔
255
                        <hwa::Contract as HwiContract>::HOT_END_ADC_V_REF_DEFAULT_SAMPLE,
2✔
256
                    ),
2✔
257
                    hwa::types::HotEndPwmController::new(
2✔
258
                        _context.hot_end_pwm,
2✔
259
                        _context.hot_end_pwm_channel.take(),
2✔
260
                    ),
2✔
261
                    <hwa::Contract as HwiContract>::HOT_END_THERM_BETA,
2✔
262
                    <hwa::Contract as HwiContract>::HOT_END_THERM_NOMINAL_RESISTANCE,
2✔
263
                    <hwa::Contract as HwiContract>::HOT_END_THERM_PULL_UP_RESISTANCE,
2✔
264
                    _defer_channel.clone(),
2✔
265
                    hwa::DeferAction::HotEndTemperature,
2✔
266
                    hwa::EventFlags::HOT_END_TEMP_OK,
2✔
267
                )
2✔
268
            );
2✔
269
            hot_end_controller.lock().await
2✔
270
                .init(<hwa::Contract as HwiContract>::HOT_END_ADC_V_REF_DEFAULT_MV).await;
2✔
271
        }
272
    }
273

274
    //#endregion
275

276
    //#region "Init HotBed controller (if with-hot-bed is set)"
277

278
    cfg_if::cfg_if! {
279
        if #[cfg(feature = "with-hot-bed")] {
280
            let hot_bed_controller: hwa::types::HotBedController = hwa::make_static_async_controller!(
2✔
281
                "HotBedController",
282
                hwa::types::HotBedControllerMutexStrategy,
283
                hwa::controllers::HeaterController::new(
2✔
284
                    hwa::types::HotBedAdcController::new(
2✔
285
                        _context.hot_bed_adc,
2✔
286
                        _context.hot_bed_adc_pin.take(),
2✔
287
                        <hwa::Contract as HwiContract>::HOT_BED_ADC_V_REF_DEFAULT_SAMPLE,
2✔
288
                    ),
2✔
289
                    hwa::types::HotBedPwmController::new(
2✔
290
                        _context.hot_bed_pwm,
2✔
291
                        _context.hot_bed_pwm_channel.take(),
2✔
292
                    ),
2✔
293
                    <hwa::Contract as HwiContract>::HOT_BED_THERM_BETA,
2✔
294
                    <hwa::Contract as HwiContract>::HOT_BED_THERM_NOMINAL_RESISTANCE,
2✔
295
                    <hwa::Contract as HwiContract>::HOT_BED_THERM_PULL_UP_RESISTANCE,
2✔
296
                    _defer_channel.clone(),
2✔
297
                    hwa::DeferAction::HotBedTemperature,
2✔
298
                    hwa::EventFlags::HOT_BED_TEMP_OK,
2✔
299
                )
2✔
300
            );
2✔
301
            hot_bed_controller.lock().await
2✔
302
                .init(<hwa::Contract as HwiContract>::HOT_BED_ADC_V_REF_DEFAULT_MV).await;
2✔
303
        }
304
    }
305

306
    //#endregion
307

308
    //#region "Init Laser controller (if with-laser is set)"
309

310
    cfg_if::cfg_if! {
311
        if #[cfg(feature = "with-laser")] {
312

313
            let laser_controller = hwa::make_static_async_controller!(
4✔
314
                "LaserController",
315
                hwa::types::LaserControllerMutexStrategy,
316
                hwa::types::InnerLaserController::new(
4✔
317
                    _context.laser_pwm,
4✔
318
                    _context.laser_pwm_channel.take(),
4✔
319
                )
4✔
320
            );
321
        }
322
    }
323

324
    //#endregion
325

326
    //#region "Init FanLayer controller (if with-fan-layer is set)"
327

328
    cfg_if::cfg_if! {
329
        if #[cfg(feature = "with-fan-layer")] {
330

331
            let fan_layer_controller = hwa::make_static_async_controller!(
2✔
332
                "FanLayerController",
333
                hwa::types::FanLayerControllerMutexStrategy,
334
                hwa::types::InnerFanLayerController::new(
2✔
335
                    _context.fan_layer_pwm,
2✔
336
                    _context.fan_layer_pwm_channel.take(),
2✔
337
                )
2✔
338
            );
339
        }
340
    }
341

342
    //#endregion
343

344
    //#region "Init FanExtra controller (if with-fan-extra-1 is set)"
345

346
    cfg_if::cfg_if! {
347
        if #[cfg(feature = "with-fan-extra-1")] {
348

349
            let fan_extra1_controller = hwa::make_static_async_controller!(
4✔
350
                "FanExtra1Controller",
351
                hwa::types::FanExtra1ControllerMutexStrategy,
352
                hwa::types::InnerFanExtra1Controller::new(
4✔
353
                    _context.fan_extra1_pwm,
4✔
354
                    _context.fan_extra1_pwm_channel.take(),
4✔
355
                )
4✔
356
            );
357
        }
358
    }
359

360
    //#endregion
361

362
    //#region "Init SD-Card controller (if with-sd-card is set)"
363

364
    cfg_if::cfg_if! {
365
        if #[cfg(feature = "with-sd-card")] {
366

367
            type SDManager = hwa::AsyncStandardStrategy<
368
                    hwa::AsyncNoopMutexType,
369
                    hwa::sd_card::SDStateManager<
370
                        <hwa::Contract as HwiContract>::SDCardBlockDevice,
371
                        {<hwa::Contract as HwiContract>::SD_CARD_MAX_DIRS},
372
                        {<hwa::Contract as HwiContract>::SD_CARD_MAX_FILES},
373
                        {<hwa::Contract as HwiContract>::SD_CARD_MAX_DIRS + <hwa::Contract as HwiContract>::SD_CARD_MAX_FILES},
374
                    >
375
                >;
376

377
            let card = hwa::sd_card::SDStateManager::new(
4✔
378
                _context.sd_card_block_device, 0
4✔
379
            ).await;
4✔
380

381
            let sd_card_controller = hwa::controllers::GenericSDCardController::new(
4✔
382
                hwa::make_static_async_controller!(
4✔
383
                    "SDCardManager",
384
                    SDManager,
385
                    card
4✔
386
                )
4✔
387
            ).await;
4✔
388
        }
389
    }
390

391
    //#endregion
392

393
    //#region "Init motion Controllers (if with-motion is set)"
394

395
    cfg_if::cfg_if! {
396
        if #[cfg(feature = "with-motion")] {
397
            let step_actuator = hwa::controllers::StepActuatorController::new(
4✔
398
                hwa::make_static_sync_controller!(
4✔
399
                    "StepActuator",
400
                    hwa::types::StepActuatorMutexStrategy,
401
                    _context.motion_pins,
4✔
402
                ),
4✔
403
                #[cfg(feature = "with-motion-broadcast")]
4✔
404
                _motion_broadcast_channel.clone(),
4✔
405
            );
4✔
406

4✔
407
            step_actuator.disable_steppers(hwa::CoordSel::all_axis());
4✔
408
            step_actuator.set_forward_direction(hwa::CoordSel::all_axis(), hwa::CoordSel::all_axis());
4✔
409

410
            let motion_config = hwa::controllers::MotionConfig::new(hwa::make_static_sync_controller!(
4✔
411
                "MotionConfig",
412
                hwa::types::MotionConfigMutexStrategy,
413
                hwa::controllers::MotionConfigContent::new()
4✔
414
            ));
4✔
415
            #[cfg(feature = "with-trinamic")]
4✔
416
            let trinamic_controller = hwa::controllers::TrinamicController::new(
4✔
417
                _context.trinamic_uart, motion_config.clone()
4✔
418
            );
4✔
419
            let motion_status = hwa::controllers::MotionStatus::new(hwa::make_static_sync_controller!(
4✔
420
                "MotionStatus",
421
                hwa::types::MotionStatusMutexStrategy,
422
                hwa::controllers::MotionStatusContent::new()
4✔
423
            ));
424
            let motion_planner = {
4✔
425
                let motion_driver = hwa::make_static_async_controller!(
4✔
426
                    "MotionDriver",
427
                    hwa::types::MotionDriverMutexStrategy,
428
                    hwa::drivers::MotionDriver::new(
4✔
429
                        step_actuator,
4✔
430
                        #[cfg(feature = "with-trinamic")]
4✔
431
                        trinamic_controller,
4✔
432
                        #[cfg(feature = "with-probe")]
4✔
433
                        probe_controller.clone(),
4✔
434
                        #[cfg(feature = "with-fan-layer")]
4✔
435
                        fan_layer_controller.clone(),
4✔
436
                        #[cfg(feature = "with-fan-extra-1")]
4✔
437
                        fan_extra1_controller.clone(),
4✔
438
                        #[cfg(feature = "with-laser")]
4✔
439
                        laser_controller.clone(),
4✔
440
                    )
4✔
441
                );
4✔
442

4✔
443
                hwa::controllers::MotionPlanner::new(
4✔
444
                    _defer_channel.clone(),
4✔
445
                    motion_config.clone(),
4✔
446
                    motion_status.clone(),
4✔
447
                    motion_driver,
4✔
448
                )
4✔
449
            };
4✔
450

4✔
451
        }
4✔
452
    }
4✔
453

4✔
454
    //#endregion
4✔
455

4✔
456
    //#region "Init Gcode processor"
4✔
457

4✔
458
    let processor: hwa::GCodeProcessor = hwa::GCodeProcessor::new(
4✔
459
        event_bus.clone(),
4✔
460
        #[cfg(feature = "with-serial-usb")]
4✔
461
        _context.serial_usb_tx,
4✔
462
        #[cfg(feature = "with-serial-port-1")]
4✔
463
        _context.serial_port_1_tx,
4✔
464
        #[cfg(feature = "with-serial-port-2")]
4✔
465
        _context.serial_port_2_tx,
4✔
466
        #[cfg(feature = "with-motion")]
4✔
467
        motion_planner,
4✔
468
        #[cfg(feature = "with-ps-on")]
4✔
469
        _context.ps_on,
4✔
470
        #[cfg(feature = "with-probe")]
4✔
471
        probe_controller,
4✔
472
        #[cfg(feature = "with-hot-end")]
4✔
473
        hot_end_controller.clone(),
4✔
474
        #[cfg(feature = "with-hot-bed")]
4✔
475
        hot_bed_controller.clone(),
4✔
476
        #[cfg(feature = "with-fan-layer")]
4✔
477
        fan_layer_controller.clone(),
4✔
478
        #[cfg(feature = "with-fan-extra-1")]
4✔
479
        fan_extra1_controller.clone(),
4✔
480
        #[cfg(feature = "with-laser")]
4✔
481
        laser_controller,
4✔
482
    );
4✔
483

4✔
484
    //#endregion
4✔
485

4✔
486
    //#region "Configure Motion defaults (if with-motion is set)"
4✔
487

4✔
488
    cfg_if::cfg_if! {
4✔
489
        if #[cfg(feature = "with-motion")] {
4✔
490

4✔
491
            // Max speed
4✔
492
            motion_config.set_max_speed(hwa::Contract::DEFAULT_MAX_SPEED_PS);
4✔
493

4✔
494
            motion_config.set_max_accel(hwa::Contract::DEFAULT_MAX_ACCEL_PS);
4✔
495

4✔
496
            motion_config.set_max_jerk(hwa::Contract::DEFAULT_MAX_JERK_PS);
4✔
497

4✔
498
            motion_config.set_default_travel_speed(hwa::Contract::DEFAULT_TRAVEL_SPEED_PS);
4✔
499

4✔
500
            motion_config.set_space_units_per_world_unit(hwa::Contract::DEFAULT_UNITS_PER_WU);
4✔
501

4✔
502
            motion_config.set_micro_steps_per_axis(
4✔
503
                hwa::Contract::DEFAULT_MICRO_STEPS_PER_AXIS
4✔
504
            );
4✔
505

4✔
506
            motion_config.set_world_center(
4✔
507
                hwa::Contract::DEFAULT_WORLD_CENTER_WU
4✔
508
            );
4✔
509

4✔
510
            motion_config.set_world_size(
4✔
511
                hwa::Contract::DEFAULT_WORLD_SIZE_WU
4✔
512
            );
4✔
513

4✔
514
            motion_config.set_nozzle_offset(
4✔
515
                hwa::make_vector_real!(x=0.0, y=0.0,z=0.0)
4✔
516
            );
4✔
517

4✔
518
            motion_config.set_probe_offset(
4✔
519
                hwa::make_vector_real!(x=0.0, y=0.0,z=0.0)
4✔
520
            );
4✔
521

4✔
522
            motion_config.set_flow_rate(100);
4✔
523
            motion_config.set_speed_rate(100);
4✔
524

4✔
525
            // Compute min speed. Really useful because of discretion effects
4✔
526
            motion_config.compute_min_speed();
4✔
527

4✔
528

4✔
529
            // Make homing unneeded
4✔
530
            hwa::warn!("Virtually homing");
4✔
531
            {
4✔
532
                let pos = hwa::controllers::Position::new_with_world_projection(
4✔
533
                    &Contract::DEFAULT_WORLD_HOMING_POINT_WU
4✔
534
                );
4✔
535
                motion_status.update_last_planned_position(0, &pos);
4✔
536
                motion_status.update_current_position(0, &pos);
4✔
537
            }
4✔
538
            #[cfg(all(feature = "native", feature = "with-ps-on"))]
4✔
539
            {
4✔
540
                hwa::warn!("Virtually powering on");
4✔
541
                event_bus.publish_event(hwa::EventStatus::containing(hwa::EventFlags::ATX_ON)).await;
4✔
542
            }
543
        }
544
    }
545

546
    //#endregion
547

548
    hwa::info!("HWA setup completed. Spawning tasks...");
4✔
549

550
    //#region "Spawn print-job task (if with-print-job is set)"
551

552
    cfg_if::cfg_if! {
553
        if #[cfg(feature = "with-print-job")] {
554
            spawner.spawn(
4✔
555
                control::task_print_job::task_print_job(
4✔
556
                    processor.clone(),
4✔
557
                    printer_controller.clone(),
4✔
558
                    sd_card_controller.clone(),
4✔
559
                )
4✔
560
            ).map_err(|_| ())?;
4✔
561
        }
562
    }
563

564
    //#endregion
565

566
    //#region "Spawn motion tasks (if with-motion and with-motion-broadcast are set)"
567

568
    cfg_if::cfg_if! {
569
        if #[cfg(feature = "with-motion")] {
570
            spawner.spawn(
4✔
571
                control::task_stepper::task_stepper(
4✔
572
                    event_bus.clone(),
4✔
573
                    processor.motion_planner.clone(),
4✔
574
                    _wd,
4✔
575
                )
4✔
576
            ).map_err(|_| ())?;
4✔
577

578
            cfg_if::cfg_if! {
579
                if #[cfg(feature = "with-motion-broadcast")] {
580
                    hwa::Contract::launch_high_priotity(
1✔
581
                        _context.high_priority_core,
1✔
582
                        control::task_motion_broadcast::task_motion_broadcast(
1✔
583
                            _motion_broadcast_channel,
1✔
584
                            motion_config,
1✔
585
                            _context.motion_sender
1✔
586
                        )
1✔
587
                    ).map_err(|_| ())?;
1✔
588
                }
589
            }
590
        }
591
    }
592

593
    //#endregion
594

595
    //#region "Spawn temperature task (if with-hot-end or with-hot-bed are set)"
596

597
    cfg_if::cfg_if! {
598
        if #[cfg(any(feature = "with-hot-end", feature = "with-hot-bed"))] {
599
            spawner.spawn(
2✔
600
                control::task_temperature::task_temperature(
2✔
601
                    event_bus.clone(),
2✔
602
                    #[cfg(feature = "with-hot-end")]
2✔
603
                    hot_end_controller,
2✔
604
                    #[cfg(feature = "with-hot-bed")]
2✔
605
                    hot_bed_controller,
2✔
606
                )
2✔
607
            ).map_err(|_| ())?;
2✔
608
        }
609
    }
610

611
    //#endregion
612

613
    //#region "Spawn defer-event task (if motion or temperature features are set)"
614

615
    cfg_if::cfg_if! {
616
        if #[cfg(any(
617
            feature = "with-motion", feature = "with-hot-end", feature = "with-hot-bed"
618
        ))] {
619
            spawner.spawn(
4✔
620
                control::task_defer::task_defer(processor.clone(), _defer_channel)
4✔
621
            ).map_err(|_| ())?;
4✔
622
        }
623
    }
624

625
    //#endregion
626

627
    //#region "Spawn control task"
628

629
    spawner
4✔
630
        .spawn(control::task_control::task_control(
4✔
631
            processor.clone(),
4✔
632
            control::GCodeMultiplexedInputStream::new(
4✔
633
                #[cfg(feature = "with-serial-usb")]
4✔
634
                _context.serial_usb_rx_stream,
4✔
635
                #[cfg(feature = "with-serial-port-1")]
4✔
636
                _context.serial_port_1_rx_stream,
4✔
637
                #[cfg(feature = "with-serial-port-2")]
4✔
638
                _context.serial_port_2_rx_stream,
4✔
639
            ),
4✔
640
            #[cfg(feature = "with-print-job")]
4✔
641
            printer_controller.clone(),
4✔
642
            #[cfg(feature = "with-sd-card")]
4✔
643
            sd_card_controller.clone(),
4✔
644
        ))
4✔
645
        .map_err(|_| ())?;
4✔
646

647
    //#endregion
648

649
    //#region "Spawn integration task (if integration-test is set)"
650

651
    cfg_if::cfg_if! {
652
        if #[cfg(any(test, feature = "integration-test"))] {
653
            spawner.spawn(
4✔
654
                control::task_integration::task_integration(
4✔
655
                    processor.clone(),
4✔
656
                    #[cfg(feature = "with-sd-card")]
4✔
657
                    sd_card_controller.clone(),
4✔
658
                    #[cfg(feature = "with-print-job")]
4✔
659
                    printer_controller.clone()
4✔
660
                )
4✔
661
            ).map_err(|_| ())?;
4✔
662
        }
663
    }
664

665
    //#endregion
666

667
    Ok(())
4✔
668
}
4✔
669

670
pub fn initialization_error() {
×
671
    let msg = "Unable to start because SYS_ALARM raised at startup. Giving up...";
×
672
    hwa::error!("{}", msg);
×
673
    panic!("{}", msg);
×
674
}
675

676
//#region "Panic handling"
677

678
cfg_if::cfg_if! {
679
    if #[cfg(not(feature = "native"))] {
680
        cfg_if::cfg_if! {
681
            if #[cfg(feature = "with-defmt")] {
682
                #[allow(unused)]
683
                use defmt_rtt as _;
684
                #[allow(unused)]
685
                use panic_probe as _;
686
            }
687
            else {
688
                #[panic_handler]
689
                fn panic(_info: &core::panic::PanicInfo) -> ! {
690
                    loop {}
691
                }
692
            }
693
        }
694
    }
695
}
696

697
//#endregion
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc