-
Notifications
You must be signed in to change notification settings - Fork 104
/
can-fd.rs
176 lines (148 loc) · 5.23 KB
/
can-fd.rs
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//! CAN-FD demo
//!
//! Demonstrates CAN-FD with Bit Rate Switching. The nominal bitrate is 500kHz,
//! but this increases to 1MHz for the data phase.
//!
//! Defaults to loopback mode. To test with other devices, enable normal mode by
//! uncommenting this line:
//!
//! ```
//! let mut can = can.into_normal();
//! ```
//!
//! Bit Rate Switching (BRS) can be disabled for all frames by changing
//! `FrameTransmissionConfig::AllowFdCanAndBRS` to
//! `FrameTransmissionConfig::AllowFdCan`.
//!
//! Tested on a MB1520-H735I-B02 development board.
//!
//! Logic Analyser trace:
//! https://github.com/stm32-rs/stm32h7xx-hal/blob/master/examples/support/pulseview-can-fd-with-brs.png
#![no_main]
#![no_std]
use crate::hal::{
gpio::{GpioExt as _, Speed},
nb::block,
pac,
prelude::*,
rcc,
rcc::rec,
};
use fdcan::{
config::{DataBitTiming, FrameTransmissionConfig, NominalBitTiming},
filter::{StandardFilter, StandardFilterSlot},
frame::{FrameFormat, TxFrameHeader},
id::StandardId,
};
use stm32h7xx_hal as hal;
use core::num::{NonZeroU16, NonZeroU8};
use cortex_m_rt::entry;
use log::info;
#[macro_use]
mod utilities;
#[entry]
fn main() -> ! {
utilities::logger::init();
// Kernel Clock 32MHz, Bit rate: 500kBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
// TODO: use the can_bit_timings crate
let nominal_bit_timing = NominalBitTiming {
prescaler: NonZeroU16::new(4).unwrap(),
seg1: NonZeroU8::new(13).unwrap(),
seg2: NonZeroU8::new(2).unwrap(),
sync_jump_width: NonZeroU8::new(1).unwrap(),
};
// Kernel Clock 32MHz, Bit rate: 1MBit/s, Sample Point 87.5%
// Value was calculated with http://www.bittiming.can-wiki.info/
// TODO: use the can_bit_timings crate
let data_bit_timing = DataBitTiming {
prescaler: NonZeroU8::new(2).unwrap(),
seg1: NonZeroU8::new(13).unwrap(),
seg2: NonZeroU8::new(2).unwrap(),
sync_jump_width: NonZeroU8::new(1).unwrap(),
transceiver_delay_compensation: true,
};
let dp = pac::Peripherals::take().unwrap();
let cp =
cortex_m::Peripherals::take().expect("cannot take core peripherals");
// Constrain and Freeze power
info!("Setup PWR... ");
let pwr = dp.PWR.constrain();
let pwrcfg = example_power!(pwr).freeze();
// Constrain and Freeze clock
info!("Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc
.sys_ck(192.MHz())
.pll1_strategy(rcc::PllConfigStrategy::Iterative)
.pll1_q_ck(32.MHz())
.freeze(pwrcfg, &dp.SYSCFG);
// Setup fdcan_tq_ck = 32MHz
assert_eq!(ccdr.clocks.pll1_q_ck().unwrap().raw(), 32_000_000);
let fdcan_prec = ccdr
.peripheral
.FDCAN
.kernel_clk_mux(rec::FdcanClkSel::Pll1Q);
let mut delay = cp.SYST.delay(ccdr.clocks);
let can1 = {
info!("Init CAN 1");
let gpioh = dp.GPIOH.split(ccdr.peripheral.GPIOH);
let rx = gpioh.ph14.into_alternate().speed(Speed::VeryHigh);
let tx = gpioh.ph13.into_alternate().speed(Speed::VeryHigh);
info!("-- Create CAN 1 instance");
dp.FDCAN1.fdcan(tx, rx, fdcan_prec)
};
// let can2 = {
// info!("Init CAN 2");
// let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
// let rx = gpiob.pb5.into_alternate().speed(Speed::VeryHigh);
// let tx = gpiob.pb6.into_alternate().speed(Speed::VeryHigh);
// info!("-- Create CAN 2 instance");
// dp.FDCAN2.fdcan(tx, rx, fdcan_prec)
// };
let mut can = can1;
can.set_protocol_exception_handling(false);
info!("-- Configure nominal timing");
can.set_nominal_bit_timing(nominal_bit_timing);
info!("-- Configure data phase timing");
can.set_data_bit_timing(data_bit_timing);
info!("-- Configure Filters");
can.set_standard_filter(
StandardFilterSlot::_0,
StandardFilter::accept_all_into_fifo0(),
);
info!("-- Apply CAN configuration");
let config = can
.get_config()
.set_frame_transmit(FrameTransmissionConfig::AllowFdCanAndBRS);
can.apply_config(config);
info!("-- Set CAN into loopback mode");
let mut can = can.into_external_loopback();
//let mut can = can.into_normal();
info!("Create Message Data");
let mut buffer = [
0xA1, 0xA2, 0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];
info!("Create Message Header");
let header = TxFrameHeader {
len: 8,
id: StandardId::new(0x1).unwrap().into(),
frame_format: FrameFormat::Fdcan,
bit_rate_switching: true,
marker: None,
};
info!("Initial Header: {:#X?}", &header);
info!("Transmit initial message");
block!(can.transmit(header, &buffer)).unwrap();
loop {
if let Ok(rxheader) = block!(can.receive0(&mut buffer)) {
info!("Received Header: {:#X?}", rxheader);
info!("received data: {:X?}", &buffer);
delay.delay_ms(1_u16);
block!(can.transmit(rxheader.unwrap().to_tx_header(None), &buffer))
.unwrap();
info!("Transmit: {:X?}", buffer);
}
}
}