Skip to content

Commit e9b49ac

Browse files
committed
Merge master
2 parents e32b3f3 + c2f67a2 commit e9b49ac

File tree

13 files changed

+189
-53
lines changed

13 files changed

+189
-53
lines changed

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,14 @@ jobs:
147147
with:
148148
files: .
149149
ignore_files: "target/"
150+
151+
link-checker:
152+
name: Link Checker
153+
runs-on: ubuntu-latest
154+
steps:
155+
- name: Checkout
156+
uses: actions/checkout@v2
157+
- name: Check URLs in documentation
158+
uses: lycheeverse/lychee-action@v1.0.4
159+
with:
160+
args: --verbose --no-progress "*.md" "**/*.md" "**/*.rs" "*.toml" "**/*.toml" -h accept=text/html

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ let clocks = rcc
3232
```
3333

3434
[embedded-time]: https://github.com/FluenTech/embedded-time/
35+
### Changed
36+
37+
- Added support for more CAN bit rates and modes. ([#186])
38+
39+
### Fixed
40+
41+
- Delay based on systick no longer panics ([#203]) for to high values
42+
and support longer delays ([#208])
3543

3644
## [v0.6.1] - 2020-12-10
3745

@@ -288,7 +296,10 @@ let clocks = rcc
288296

289297
- Support `stm32f303` device
290298

299+
[#208]: https://github.com/stm32-rs/stm32f3xx-hal/pull/208
300+
[#203]: https://github.com/stm32-rs/stm32f3xx-hal/issues/203
291301
[#192]: https://github.com/stm32-rs/stm32f3xx-hal/pull/192
302+
[#186]: https://github.com/stm32-rs/stm32f3xx-hal/pull/186
292303
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/184
293304
[#172]: https://github.com/stm32-rs/stm32f3xx-hal/pull/172
294305
[#170]: https://github.com/stm32-rs/stm32f3xx-hal/pull/170
@@ -354,7 +365,7 @@ let clocks = rcc
354365
[#2]: https://github.com/stm32-rs/stm32f3xx-hal/pull/2
355366

356367
[Unreleased]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.6.1...HEAD
357-
[v0.6.0]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.6.0...v0.6.1
368+
[v0.6.1]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.6.0...v0.6.1
358369
[v0.6.0]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.5.0...v0.6.0
359370
[v0.5.0]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.4.3...v0.5.0
360371
[v0.4.3]: https://github.com/stm32-rs/stm32f3xx-hal/compare/v0.4.2...v0.4.3

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,21 @@ expect it to do so.*
126126
## License
127127

128128
[0-clause BSD license](LICENSE-0BSD.txt).
129+
130+
## Contributing
131+
132+
### Running Tests
133+
134+
Tests are run via the integration test pattern and are executed on a target chip, rather than on a host system.
135+
First, install [probe-run](https://crates.io/crates/probe-run) via `cargo install probe-run`.
136+
Next, you'll need to modify `.cargo/config` to link defmt and use `probe-run` configured for your chip.
137+
See details within the comments in that file.
138+
139+
Now, you can execute a test by setting your device, defmt, and any test specific features:
140+
141+
```
142+
cargo test --test rcc --features=stm32f303xc,defmt,rt
143+
```
144+
145+
The result _always_ shows a backtrace, even in the case of success.
146+
Exit code of 0 means that the run was successful.

src/adc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! It can be built for the STM32F3Discovery running
88
//! `cargo build --example adc --features=stm32f303xc`
99
//!
10-
//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/adc.rs
10+
//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/adc.rs
1111
1212
use crate::{
1313
gpio::Analog,

src/can.rs

Lines changed: 98 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//!
1010
//! A usage example of the can peripheral can be found at [examples/can.rs]
1111
//!
12-
//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/can.rs
12+
//! [examples/can.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/can.rs
1313
1414
pub use embedded_hal_can::{self, Filter, Frame, Id, Receiver, Transmitter};
1515

@@ -20,10 +20,72 @@ use crate::stm32;
2020
use nb::{self, Error};
2121

2222
use core::sync::atomic::{AtomicU8, Ordering};
23+
pub use stm32::can::btr::LBKM_A;
2324

2425
const EXID_MASK: u32 = 0b1_1111_1111_1100_0000_0000_0000_0000;
2526
const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF;
2627

28+
/// Options the CAN bus. This is primarily used to set bus timings, but also controls options like enabling loopback or silent mode for debugging.
29+
/// See http://www.bittiming.can-wiki.info/#bxCAN for generating the timing parameters for different baud rates and clocks.
30+
///
31+
/// Use `CanOpts::default()` to get 250kbps at 32mhz system clock
32+
pub struct CanOpts {
33+
brp: u16,
34+
sjw: u8,
35+
ts1: u8,
36+
ts2: u8,
37+
lbkm: LBKM_A,
38+
}
39+
40+
impl CanOpts {
41+
/// Create new `CanOpts` using the default settings from `CanOpts::default()` to get 250kbps at 32mhz system clock.
42+
pub fn new() -> CanOpts {
43+
CanOpts::default()
44+
}
45+
46+
/// Set the Baud Rate Prescaler. See http://www.bittiming.can-wiki.info/#bxCAN for generating the timing parameters for different baud rates and clocks.
47+
pub fn brp(mut self, brp: u16) -> Self {
48+
self.brp = brp;
49+
self
50+
}
51+
52+
/// Set the Resynchronisation Jump Width. See http://www.bittiming.can-wiki.info/#bxCAN for generating the timing parameters for different baud rates and clocks.
53+
pub fn sjw(mut self, sjw: u8) -> Self {
54+
self.sjw = sjw;
55+
self
56+
}
57+
58+
/// Set Time Segment One. See http://www.bittiming.can-wiki.info/#bxCAN for generating the timing parameters for different baud rates and clocks.
59+
pub fn ts1(mut self, ts1: u8) -> Self {
60+
self.ts1 = ts1;
61+
self
62+
}
63+
64+
/// Set Time Segment Two. See http://www.bittiming.can-wiki.info/#bxCAN for generating the timing parameters for different baud rates and clocks.
65+
pub fn ts2(mut self, ts2: u8) -> Self {
66+
self.ts2 = ts2;
67+
self
68+
}
69+
70+
/// Enable or disable loopback mode on the CAN device. This is useful for debugging.
71+
pub fn lbkm(mut self, lbkm: LBKM_A) -> Self {
72+
self.lbkm = lbkm;
73+
self
74+
}
75+
}
76+
77+
impl Default for CanOpts {
78+
fn default() -> Self {
79+
CanOpts {
80+
brp: 4,
81+
sjw: 0,
82+
ts1: 10,
83+
ts2: 3,
84+
lbkm: LBKM_A::DISABLED,
85+
}
86+
}
87+
}
88+
2789
/// A CAN identifier, which can be either 11 or 27 (extended) bits.
2890
/// u16 and u32 respectively are used here despite the fact that the upper bits are unused.
2991
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
@@ -252,42 +314,28 @@ impl CanFilterData {
252314
}
253315

254316
impl Can {
255-
/// Initialize the CAN Peripheral
256-
pub fn new(
317+
/// Initialize the CAN peripheral using the options specified by `opts`.
318+
pub fn new_with_opts(
257319
can: stm32::CAN,
258320
rx: gpioa::PA11<AF9>,
259321
tx: gpioa::PA12<AF9>,
260322
apb1: &mut APB1,
261-
) -> Self {
323+
opts: CanOpts,
324+
) -> Can {
262325
apb1.enr().modify(|_, w| w.canen().enabled());
263326
can.mcr.modify(|_, w| w.sleep().clear_bit());
264327
can.mcr.modify(|_, w| w.inrq().set_bit());
265328

266329
// Wait for INAK to confirm we have entered initialization mode
267330
while !can.msr.read().inak().bit_is_set() {}
268331

269-
// TODO: actually calculate baud params
270-
271-
// Our baud rate calc here is aiming for roughly 4000uS total bit time or about 250kbps
272-
// Though we actually allow closer to 5500uS total given the sjw setting
273-
// Calculations for timing value from http://www.bittiming.can-wiki.info/#bxCAN
274-
275-
// Baud rate prescaler defines time quanta
276-
// tq = (BRP[9:0]+1) x tPCLK
277-
let brp: u16 = 4;
278-
279-
// Resynchronization jump width: number of quanta segments may be expanded to resync
280-
// tRJW = tq x (SJW[1:0] + 1)
281-
let sjw = 0;
282-
283-
// Time seg 2
284-
// tBS2 = tq x (TS2[2:0] + 1)
285-
let ts2 = 3;
286-
287-
// Time seg 1
288-
// tBS1 = tq x (TS1[3:0] + 1)
289-
let ts1 = 10;
290-
332+
let CanOpts {
333+
brp,
334+
sjw,
335+
ts1,
336+
ts2,
337+
lbkm,
338+
} = opts;
291339
can.btr.modify(|_, w| unsafe {
292340
w.brp()
293341
.bits(brp)
@@ -297,8 +345,8 @@ impl Can {
297345
.bits(ts1)
298346
.ts2()
299347
.bits(ts2)
300-
//.lbkm()
301-
//.set_bit()
348+
.lbkm()
349+
.variant(lbkm)
302350
});
303351

304352
// Leave initialization mode by clearing INRQ and switch to normal mode
@@ -312,6 +360,15 @@ impl Can {
312360
_tx: tx,
313361
}
314362
}
363+
/// Initialize the CAN Peripheral using default options from `CanOpts::default()`
364+
pub fn new(
365+
can: stm32::CAN,
366+
rx: gpioa::PA11<AF9>,
367+
tx: gpioa::PA12<AF9>,
368+
apb1: &mut APB1,
369+
) -> Self {
370+
Can::new_with_opts(can, rx, tx, apb1, CanOpts::default())
371+
}
315372

316373
/// Enable CAN event interrupts for `Event`
317374
pub fn listen(&mut self, event: Event) {
@@ -407,7 +464,7 @@ impl embedded_hal_can::Transmitter for CanTransmitter {
407464

408465
// NOTE(unsafe): full 8bit write is unsafe via the svd2rust api
409466
tx.tdtr
410-
.modify(|_, w| unsafe { w.dlc().bits(data.len() as u8) });
467+
.modify(|_, w| unsafe { w.dlc().bits(frame.dlc as u8) });
411468

412469
tx.tir.modify(|_, w| w.rtr().clear_bit());
413470
} else {
@@ -554,7 +611,7 @@ impl CanFrame {
554611
///
555612
/// This function will panic if length of `data` is greater than `8`
556613
pub fn new_data(id: CanId, data: &[u8]) -> CanFrame {
557-
crate::assert!((0..8).contains(&data.len()));
614+
crate::assert!((0..=8).contains(&data.len()));
558615

559616
let mut frame = Self {
560617
id,
@@ -569,7 +626,7 @@ impl CanFrame {
569626
///
570627
/// # Panics
571628
///
572-
/// This function will panic if `dlc` is not inside the vliad range `0..=8`.
629+
/// This function will panic if `dlc` is not inside the valid range `0..=8`.
573630
pub fn new_remote(id: CanId, dlc: usize) -> CanFrame {
574631
assert!((0..=8).contains(&dlc));
575632

@@ -579,4 +636,14 @@ impl CanFrame {
579636
data: [0; 8],
580637
}
581638
}
639+
640+
/// Length of the frame data
641+
pub fn len(&self) -> usize {
642+
self.dlc
643+
}
644+
645+
/// Is this frame empty. This usually indicates a remote frame.
646+
pub fn is_empty(&self) -> bool {
647+
self.dlc == 0
648+
}
582649
}

src/delay.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,19 @@ pub struct Delay {
1616

1717
impl Delay {
1818
/// Configures the system timer (SysTick) as a delay provider
19+
///
20+
/// # Limitations
21+
///
22+
/// Depending on the core clock, this delay provider
23+
/// can delay between 1 minute (for 72 Mhz) up to almost 9 minutes (for 8 Mhz).
24+
/// Higher input values will be capped to these limits.
25+
///
26+
/// For accuracy purposes and because this is a blocking, busy-waiting function,
27+
/// if delays in the second to minute range are needed, use timers instead.
1928
pub fn new(mut syst: SYST, clocks: Clocks) -> Self {
2029
syst.set_clock_source(SystClkSource::Core);
2130

22-
Delay { syst, clocks }
31+
Delay { clocks, syst }
2332
}
2433

2534
/// Releases the system timer (SysTick) resource
@@ -30,7 +39,7 @@ impl Delay {
3039

3140
impl DelayMs<u32> for Delay {
3241
fn delay_ms(&mut self, ms: u32) {
33-
self.delay_us(ms * 1_000);
42+
self.delay_us(ms.saturating_mul(1_000));
3443
}
3544
}
3645

@@ -48,17 +57,36 @@ impl DelayMs<u8> for Delay {
4857

4958
impl DelayUs<u32> for Delay {
5059
fn delay_us(&mut self, us: u32) {
51-
let rvr = us * (self.clocks.sysclk().0 / 1_000_000);
52-
53-
crate::assert!(rvr < (1 << 24));
54-
55-
self.syst.set_reload(rvr);
56-
self.syst.clear_current();
57-
self.syst.enable_counter();
58-
59-
while !self.syst.has_wrapped() {}
60-
61-
self.syst.disable_counter();
60+
// The RVR register is 24 bits wide, as SysTick is based on a 24 bit counter
61+
const MAX_RVR: u32 = 1 << 24;
62+
63+
// Depending on hclk (core clock), this 32 bit value allows
64+
// delays between 1 min to 9 min.
65+
//
66+
// (((32^2) - 1) / 72) µs ~ 59.6 seconds
67+
// (((32^2) - 1) / 8) µs ~ 536.8 seconds
68+
let mut total_rvr = us.saturating_mul(self.clocks.hclk().0 / 1_000_000);
69+
70+
// Use the full 32 bit range to allow longer delays
71+
//
72+
// Like dividing total_rvr / MAX_RVR
73+
// and delaying by MAX_RVR * (fraction).
74+
while total_rvr != 0 {
75+
let current_rvr = if total_rvr < MAX_RVR {
76+
total_rvr
77+
} else {
78+
MAX_RVR
79+
};
80+
total_rvr -= current_rvr;
81+
82+
self.syst.set_reload(current_rvr);
83+
self.syst.clear_current();
84+
self.syst.enable_counter();
85+
86+
while !self.syst.has_wrapped() {}
87+
88+
self.syst.disable_counter();
89+
}
6290
}
6391
}
6492

src/dma.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! An example how to use DMA for serial, can be found at [examples/serial_dma.rs]
66
//!
7-
//! [examples/serial_dma.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/serial_dma.rs
7+
//! [examples/serial_dma.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/serial_dma.rs
88
99
// To learn about most of the ideas implemented here, check out the DMA section
1010
// of the Embedonomicon: https://docs.rust-embedded.org/embedonomicon/dma.html

src/gpio.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
//!
2727
//! [InputPin]: embedded_hal::digital::v2::InputPin
2828
//! [OutputPin]: embedded_hal::digital::v2::OutputPin
29-
//! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/toggle.rs
29+
//! [examples/toggle.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/toggle.rs
3030
3131
use core::convert::Infallible;
3232
use core::marker::PhantomData;
@@ -163,7 +163,7 @@ macro_rules! gpio {
163163
///
164164
/// See [examples/gpio_erased.rs] as an example.
165165
///
166-
/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/gpio_erased.rs
166+
/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/gpio_erased.rs
167167
pub struct PXx<MODE> {
168168
i: u8,
169169
gpio: Gpio,

src/i2c.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! A usage example of the i2c peripheral can be found at [examples/i2c_scanner.rs]
44
//!
5-
//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/i2c_scanner.rs
5+
//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.1/examples/i2c_scanner.rs
66
77
use core::convert::TryFrom;
88
use core::ops::Deref;

0 commit comments

Comments
 (0)