Skip to content

Commit e9d9eb5

Browse files
committed
Add read and write impl for Serial, Irq flags functions and RTIC example
1 parent d8f0b07 commit e9d9eb5

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ panic-probe = "0.2.0"
5151
panic-semihosting = "0.5.6"
5252
usbd-serial = "0.1.1"
5353
usb-device = "0.2.8"
54+
cortex-m-rtic = "0.6.0-alpha.4"
55+
dwt-systick-monotonic = "0.1.0-alpha.2"
56+
panic-rtt-target = { version = "0.1", features = ["cortex-m"] }
57+
rtt-target = { version = "0.3.0", features = ["cortex-m"] }
5458

5559
[build-dependencies]
5660
cargo_metadata = "0.13.1"
@@ -163,6 +167,10 @@ required-features = ["ld", "can", "stm32f303"]
163167
name = "serial_dma"
164168
required-features = ["ld", "stm32f303"]
165169

170+
[[example]]
171+
name = "serial_echo_rtic"
172+
required-features = ["ld", "rt", "stm32f303xc"]
173+
166174
[[example]]
167175
name = "adc"
168176
required-features = ["ld", "stm32f303"]

examples/serial_echo_rtic.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
use panic_rtt_target as _;
5+
6+
#[rtic::app(device = stm32f3xx_hal::pac, dispatchers = [TIM20_BRK, TIM20_UP, TIM20_TRG_COM])]
7+
mod app {
8+
use dwt_systick_monotonic::DwtSystick;
9+
use rtt_target::{rprintln, rtt_init_print};
10+
use stm32f3xx_hal::{prelude::*, serial::{Event, Serial}};
11+
use stm32f3xx_hal::gpio::{self, Output, PushPull, Alternate, U};
12+
13+
#[monotonic(binds = SysTick, default = true)]
14+
type DwtMono = DwtSystick<48_000_000>;
15+
16+
type SerialType = Serial<stm32f3xx_hal::pac::USART1, (gpio::Pin<gpio::Gpioa, U<9_u8>, Alternate<PushPull, 7_u8>>, gpio::Pin<gpio::Gpioa, U<10_u8>, Alternate<PushPull, 7_u8>>)>;
17+
type DirType = stm32f3xx_hal::gpio::Pin<gpio::Gpioe, U<13_u8>, Output<PushPull>>;
18+
#[resources]
19+
struct Resources {
20+
serial: SerialType,
21+
dir: DirType,
22+
}
23+
24+
#[init]
25+
fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) {
26+
let mut flash = cx.device.FLASH.constrain();
27+
let mut rcc = cx.device.RCC.constrain();
28+
let mut dcb = cx.core.DCB;
29+
let dwt = cx.core.DWT;
30+
let systick = cx.core.SYST;
31+
32+
rtt_init_print!(NoBlockSkip, 4096);
33+
rprintln!("pre init");
34+
35+
// Initialize the clocks
36+
let clocks = rcc.cfgr.sysclk(48.MHz()).freeze(&mut flash.acr);
37+
let mono = DwtSystick::new(&mut dcb, dwt, systick, clocks.sysclk().0);
38+
39+
// Initialize the peripherals
40+
// DIR
41+
let mut gpioe = cx.device.GPIOE.split(&mut rcc.ahb);
42+
let mut dir : DirType = gpioe.pe13.into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
43+
dir.set_low().unwrap();
44+
45+
// SERIAL
46+
let mut gpioa = cx.device.GPIOA.split(&mut rcc.ahb);
47+
let mut pins = (
48+
gpioa
49+
.pa9
50+
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
51+
gpioa
52+
.pa10
53+
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
54+
);
55+
pins.1.internal_pull_up(&mut gpioa.pupdr, true);
56+
let mut serial: SerialType = Serial::usart1(cx.device.USART1, pins, 19200_u32.Bd(), clocks, &mut rcc.apb2);
57+
serial.listen(Event::Rxne);
58+
59+
rprintln!("post init");
60+
61+
task1::spawn().unwrap();
62+
63+
(init::LateResources {serial, dir}, init::Monotonics(mono))
64+
}
65+
66+
#[task(binds = USART1_EXTI25, resources = [serial, dir])]
67+
fn protocol_serial_task(cx: protocol_serial_task::Context) {
68+
let mut serial = cx.resources.serial;
69+
let mut dir = cx.resources.dir;
70+
71+
serial.lock(|serial| {
72+
dir.lock(|dir| {
73+
if serial.is_rxne() {
74+
dir.set_high().unwrap();
75+
serial.unlisten(Event::Rxne);
76+
match serial.read() {
77+
Ok(byte) => {
78+
serial.write(byte).unwrap();
79+
serial.listen(Event::Tc);
80+
},
81+
Err(_error) => rprintln!("irq error"),
82+
};
83+
}
84+
85+
if serial.is_tc() {
86+
dir.set_low().unwrap();
87+
serial.unlisten(Event::Tc);
88+
serial.listen(Event::Rxne);
89+
}
90+
})
91+
});
92+
}
93+
94+
#[task]
95+
fn task1(_cx: task1::Context) {
96+
rprintln!("task1");
97+
}
98+
99+
#[idle]
100+
fn idle(_: idle::Context) -> ! {
101+
rprintln!("idle");
102+
loop {
103+
cortex_m::asm::nop();
104+
}
105+
}
106+
}

src/serial.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ pub enum Event {
2525
Rxne,
2626
/// New data can be sent
2727
Txe,
28+
/// Transmission complete
29+
Tc,
2830
}
2931

3032
/// Serial error
@@ -151,6 +153,9 @@ macro_rules! hal {
151153
Event::Txe => {
152154
self.usart.cr1.modify(|_, w| w.txeie().set_bit())
153155
},
156+
Event::Tc => {
157+
self.usart.cr1.modify(|_, w| w.tcie().set_bit())
158+
},
154159
}
155160
}
156161

@@ -163,9 +168,31 @@ macro_rules! hal {
163168
Event::Txe => {
164169
self.usart.cr1.modify(|_, w| w.txeie().clear_bit())
165170
},
171+
Event::Tc => {
172+
self.usart.cr1.modify(|_, w| w.tcie().clear_bit())
173+
},
166174
}
167175
}
168176

177+
/// Return true if the line idle status is set
178+
pub fn is_tc(&self) -> bool {
179+
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
180+
isr.tc().bit_is_set()
181+
}
182+
183+
/// Return true if the tx register is empty (and can accept data)
184+
pub fn is_txe(&self) -> bool {
185+
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
186+
isr.txe().bit_is_set()
187+
}
188+
189+
/// Return true if the rx register is not empty (and can be read)
190+
pub fn is_rxne(&self) -> bool {
191+
let isr = unsafe { (*$USARTX::ptr()).isr.read() };
192+
isr.rxne().bit_is_set()
193+
}
194+
195+
169196
/// Splits the `Serial` abstraction into a transmitter and a receiver half
170197
pub fn split(self) -> (Tx<$USARTX>, Rx<$USARTX>) {
171198
(
@@ -183,6 +210,35 @@ macro_rules! hal {
183210
(self.usart, self.pins)
184211
}
185212
}
213+
214+
impl<TX, RX> serial::Read<u8> for Serial<$USARTX, (TX, RX)> {
215+
type Error = Error;
216+
217+
fn read(&mut self) -> nb::Result<u8, Error> {
218+
let mut rx: Rx<$USARTX> = Rx {
219+
_usart: PhantomData,
220+
};
221+
rx.read()
222+
}
223+
}
224+
225+
impl<TX, RX> serial::Write<u8> for Serial<$USARTX, (TX, RX)> {
226+
type Error = Infallible;
227+
228+
fn flush(&mut self) -> nb::Result<(), Infallible> {
229+
let mut tx: Tx<$USARTX> = Tx {
230+
_usart: PhantomData,
231+
};
232+
tx.flush()
233+
}
234+
235+
fn write(&mut self, byte: u8) -> nb::Result<(), Infallible> {
236+
let mut tx: Tx<$USARTX> = Tx {
237+
_usart: PhantomData,
238+
};
239+
tx.write(byte)
240+
}
241+
}
186242

187243
impl serial::Read<u8> for Rx<$USARTX> {
188244
type Error = Error;

0 commit comments

Comments
 (0)