Skip to content

Commit e225883

Browse files
committed
Add separate async-await and polling binaries
1 parent d4d70ac commit e225883

File tree

3 files changed

+340
-26
lines changed

3 files changed

+340
-26
lines changed

src/main.rs renamed to src/bin/async-await.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -423,20 +423,22 @@ impl<S, F> TouchTask<S, F> where S: Stream<Item=()>, F: Framebuffer, {
423423
struct AudioTask<F, S> where F: Framebuffer, S: Stream<Item=()> {
424424
sai_2: SAI2,
425425
idle_stream: S,
426-
audio_writer: AudioWriter<F>,
426+
layer_mutex: Arc<FutureMutex<Layer<F>>>,
427+
audio_writer: AudioWriter,
427428
}
428429

429430
impl<F, S> AudioTask<F, S> where F: Framebuffer, S: Stream<Item=()> {
430431
fn new(layer_mutex: Arc<FutureMutex<Layer<F>>>, sai_2: SAI2, idle_stream: S) -> Self {
431432
Self {
432433
sai_2,
433434
idle_stream,
434-
audio_writer: AudioWriter::new(layer_mutex),
435+
layer_mutex,
436+
audio_writer: AudioWriter::new(),
435437
}
436438
}
437439

438-
async fn run(mut self) {
439-
let idle_stream = self.idle_stream;
440+
async fn run(self) {
441+
let Self {idle_stream, layer_mutex, mut audio_writer, sai_2} = self;
440442
pin_mut!(idle_stream);
441443

442444
let mut data0_buffer = None;
@@ -445,16 +447,18 @@ impl<F, S> AudioTask<F, S> where F: Framebuffer, S: Stream<Item=()> {
445447
await!(idle_stream.next());
446448

447449
// poll for new audio data
448-
if self.sai_2.bsr.read().freq().bit_is_set() {
450+
if sai_2.bsr.read().freq().bit_is_set() {
449451
// fifo_request_flag is set -> new data available
450-
let data = self.sai_2.bdr.read().data().bits();
452+
let data = sai_2.bdr.read().data().bits();
451453
match data0_buffer {
452454
None => {
453455
data0_buffer = Some(data);
454456
},
455457
Some(data0) => {
456458
let data1 = data;
457-
await!(self.audio_writer.set_next_col(data0, data1));
459+
await!(layer_mutex.with(|l| {
460+
audio_writer.set_next_col(l,data0, data1)
461+
}));
458462
data0_buffer = None;
459463
}
460464
}

src/bin/polling.rs

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
#![feature(alloc)]
2+
#![feature(alloc_error_handler)]
3+
#![no_main]
4+
#![no_std]
5+
6+
#[macro_use]
7+
extern crate alloc;
8+
extern crate alloc_cortex_m;
9+
extern crate cortex_m;
10+
extern crate cortex_m_rt as rt;
11+
extern crate cortex_m_semihosting as sh;
12+
#[macro_use]
13+
extern crate stm32f7;
14+
#[macro_use]
15+
extern crate stm32f7_discovery;
16+
extern crate smoltcp;
17+
18+
use alloc::vec::Vec;
19+
use alloc_cortex_m::CortexMHeap;
20+
use core::alloc::Layout as AllocLayout;
21+
use core::fmt::Write;
22+
use core::panic::PanicInfo;
23+
use cortex_m::{asm, interrupt};
24+
use rt::{entry, exception, ExceptionFrame};
25+
use sh::hio::{self, HStdout};
26+
use smoltcp::{
27+
socket::{
28+
Socket, SocketSet, TcpSocket, TcpSocketBuffer, UdpPacketMetadata, UdpSocket,
29+
UdpSocketBuffer,
30+
},
31+
time::Instant,
32+
wire::{EthernetAddress, IpAddress, IpEndpoint, Ipv4Address},
33+
};
34+
use stm32f7::stm32f7x6::{CorePeripherals, Interrupt, Peripherals};
35+
use stm32f7_discovery::{
36+
ethernet,
37+
gpio::{GpioPort, InputPin, OutputPin},
38+
init,
39+
lcd::{self, Color},
40+
random::Rng,
41+
sd,
42+
system_clock::{self, Hz},
43+
touch,
44+
lcd::AudioWriter,
45+
};
46+
47+
#[global_allocator]
48+
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
49+
50+
const HEAP_SIZE: usize = 50 * 1024; // in bytes
51+
const ETH_ADDR: EthernetAddress = EthernetAddress([0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef]);
52+
const IP_ADDR: Ipv4Address = Ipv4Address([141, 52, 46, 198]);
53+
54+
#[entry]
55+
fn main() -> ! {
56+
let core_peripherals = CorePeripherals::take().unwrap();
57+
let mut systick = core_peripherals.SYST;
58+
let mut nvic = core_peripherals.NVIC;
59+
60+
let peripherals = Peripherals::take().unwrap();
61+
let mut rcc = peripherals.RCC;
62+
let mut pwr = peripherals.PWR;
63+
let mut flash = peripherals.FLASH;
64+
let mut fmc = peripherals.FMC;
65+
let mut ltdc = peripherals.LTDC;
66+
let mut sai_2 = peripherals.SAI2;
67+
let mut rng = peripherals.RNG;
68+
let mut sdmmc = peripherals.SDMMC1;
69+
let mut syscfg = peripherals.SYSCFG;
70+
let mut ethernet_mac = peripherals.ETHERNET_MAC;
71+
let mut ethernet_dma = peripherals.ETHERNET_DMA;
72+
73+
init::init_system_clock_216mhz(&mut rcc, &mut pwr, &mut flash);
74+
init::enable_gpio_ports(&mut rcc);
75+
76+
let gpio_a = GpioPort::new_a(&peripherals.GPIOA);
77+
let gpio_b = GpioPort::new_b(&peripherals.GPIOB);
78+
let gpio_c = GpioPort::new(&peripherals.GPIOC);
79+
let gpio_d = GpioPort::new(&peripherals.GPIOD);
80+
let gpio_e = GpioPort::new(&peripherals.GPIOE);
81+
let gpio_f = GpioPort::new(&peripherals.GPIOF);
82+
let gpio_g = GpioPort::new(&peripherals.GPIOG);
83+
let gpio_h = GpioPort::new(&peripherals.GPIOH);
84+
let gpio_i = GpioPort::new(&peripherals.GPIOI);
85+
let gpio_j = GpioPort::new(&peripherals.GPIOJ);
86+
let gpio_k = GpioPort::new(&peripherals.GPIOK);
87+
let mut pins = init::pins(
88+
gpio_a, gpio_b, gpio_c, gpio_d, gpio_e, gpio_f, gpio_g, gpio_h, gpio_i, gpio_j, gpio_k,
89+
);
90+
91+
// configures the system timer to trigger a SysTick exception every second
92+
init::init_systick(Hz(100), &mut systick, &rcc);
93+
systick.enable_interrupt();
94+
95+
init::init_sdram(&mut rcc, &mut fmc);
96+
let mut lcd = init::init_lcd(&mut ltdc, &mut rcc);
97+
pins.display_enable.set(true);
98+
pins.backlight.set(true);
99+
100+
let mut layer_1 = lcd.layer_1().unwrap();
101+
let mut layer_2 = lcd.layer_2().unwrap();
102+
103+
layer_1.clear();
104+
layer_2.clear();
105+
lcd::init_stdout(layer_2);
106+
107+
println!("Hello World");
108+
109+
// Initialize the allocator BEFORE you use it
110+
unsafe { ALLOCATOR.init(rt::heap_start() as usize, HEAP_SIZE) }
111+
112+
let _xs = vec![1, 2, 3];
113+
114+
let mut i2c_3 = init::init_i2c_3(&peripherals.I2C3, &mut rcc);
115+
i2c_3.test_1();
116+
i2c_3.test_2();
117+
118+
nvic.enable(Interrupt::EXTI0);
119+
120+
let mut sd = sd::Sd::new(&mut sdmmc, &mut rcc, &pins.sdcard_present);
121+
122+
init::init_sai_2(&mut sai_2, &mut rcc);
123+
init::init_wm8994(&mut i2c_3).expect("WM8994 init failed");
124+
// touch initialization should be done after audio initialization, because the touch
125+
// controller might not be ready yet
126+
touch::check_family_id(&mut i2c_3).unwrap();
127+
128+
let mut rng = Rng::init(&mut rng, &mut rcc).expect("RNG init failed");
129+
print!("Random numbers: ");
130+
for _ in 0..4 {
131+
print!(
132+
"{} ",
133+
rng.poll_and_get()
134+
.expect("Failed to generate random number")
135+
);
136+
}
137+
println!("");
138+
139+
// ethernet
140+
let mut ethernet_interface = ethernet::EthernetDevice::new(
141+
Default::default(),
142+
Default::default(),
143+
&mut rcc,
144+
&mut syscfg,
145+
&mut ethernet_mac,
146+
&mut ethernet_dma,
147+
ETH_ADDR,
148+
)
149+
.map(|device| device.into_interface(IP_ADDR));
150+
if let Err(e) = ethernet_interface {
151+
println!("ethernet init failed: {:?}", e);
152+
};
153+
154+
let mut sockets = SocketSet::new(Vec::new());
155+
156+
if ethernet_interface.is_ok() {
157+
let endpoint = IpEndpoint::new(IpAddress::Ipv4(IP_ADDR), 15);
158+
let udp_rx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; 3], vec![0u8; 256]);
159+
let udp_tx_buffer = UdpSocketBuffer::new(vec![UdpPacketMetadata::EMPTY; 1], vec![0u8; 128]);
160+
let mut example_udp_socket = UdpSocket::new(udp_rx_buffer, udp_tx_buffer);
161+
example_udp_socket.bind(endpoint).unwrap();
162+
sockets.add(example_udp_socket);
163+
164+
let tcp_rx_buffer = TcpSocketBuffer::new(vec![0; ethernet::MTU]);
165+
let tcp_tx_buffer = TcpSocketBuffer::new(vec![0; ethernet::MTU]);
166+
let mut example_tcp_socket = TcpSocket::new(tcp_rx_buffer, tcp_tx_buffer);
167+
example_tcp_socket.listen(endpoint).unwrap();
168+
sockets.add(example_tcp_socket);
169+
}
170+
171+
let mut previous_button_state = pins.button.get();
172+
let mut audio_writer = AudioWriter::new();
173+
loop {
174+
// poll button state
175+
let current_button_state = pins.button.get();
176+
if current_button_state != previous_button_state {
177+
if current_button_state {
178+
pins.led.toggle();
179+
180+
// trigger the `EXTI0` interrupt
181+
nvic.set_pending(Interrupt::EXTI0);
182+
}
183+
184+
previous_button_state = current_button_state;
185+
}
186+
187+
// poll for new touch data
188+
for touch in &touch::touches(&mut i2c_3).unwrap() {
189+
layer_1.print_point_color_at(
190+
touch.x as usize,
191+
touch.y as usize,
192+
Color::from_hex(0xffff00),
193+
);
194+
}
195+
196+
// poll for new audio data
197+
while sai_2.bsr.read().freq().bit_is_clear() {} // fifo_request_flag
198+
let data0 = sai_2.bdr.read().data().bits();
199+
while sai_2.bsr.read().freq().bit_is_clear() {} // fifo_request_flag
200+
let data1 = sai_2.bdr.read().data().bits();
201+
202+
audio_writer.set_next_col(&mut layer_1, data0, data1);
203+
204+
// handle new ethernet packets
205+
if let Ok(ref mut eth) = ethernet_interface {
206+
match eth.poll(
207+
&mut sockets,
208+
Instant::from_millis(system_clock::ms() as i64),
209+
) {
210+
Err(::smoltcp::Error::Exhausted) => continue,
211+
Err(::smoltcp::Error::Unrecognized) => {}
212+
Err(e) => println!("Network error: {:?}", e),
213+
Ok(socket_changed) => {
214+
if socket_changed {
215+
for mut socket in sockets.iter_mut() {
216+
poll_socket(&mut socket).expect("socket poll failed");
217+
}
218+
}
219+
}
220+
}
221+
}
222+
223+
// Initialize the SD Card on insert and deinitialize on extract.
224+
if sd.card_present() && !sd.card_initialized() {
225+
if let Some(i_err) = sd::init(&mut sd).err() {
226+
println!("{:?}", i_err);
227+
}
228+
} else if !sd.card_present() && sd.card_initialized() {
229+
sd::de_init(&mut sd);
230+
}
231+
}
232+
}
233+
234+
fn poll_socket(socket: &mut Socket) -> Result<(), smoltcp::Error> {
235+
match socket {
236+
&mut Socket::Udp(ref mut socket) => match socket.endpoint().port {
237+
15 => loop {
238+
let reply;
239+
match socket.recv() {
240+
Ok((data, remote_endpoint)) => {
241+
let mut data = Vec::from(data);
242+
let len = data.len() - 1;
243+
data[..len].reverse();
244+
reply = (data, remote_endpoint);
245+
}
246+
Err(smoltcp::Error::Exhausted) => break,
247+
Err(err) => return Err(err),
248+
}
249+
socket.send_slice(&reply.0, reply.1)?;
250+
},
251+
_ => {}
252+
},
253+
&mut Socket::Tcp(ref mut socket) => match socket.local_endpoint().port {
254+
15 => {
255+
if !socket.may_recv() {
256+
return Ok(());
257+
}
258+
let reply = socket.recv(|data| {
259+
if data.len() > 0 {
260+
let mut reply = Vec::from("tcp: ");
261+
let start_index = reply.len();
262+
reply.extend_from_slice(data);
263+
reply[start_index..(start_index + data.len() - 1)].reverse();
264+
(data.len(), Some(reply))
265+
} else {
266+
(data.len(), None)
267+
}
268+
})?;
269+
if let Some(reply) = reply {
270+
assert_eq!(socket.send_slice(&reply)?, reply.len());
271+
}
272+
}
273+
_ => {}
274+
},
275+
_ => {}
276+
}
277+
Ok(())
278+
}
279+
280+
interrupt!(EXTI0, exti0, state: Option<HStdout> = None);
281+
282+
fn exti0(_state: &mut Option<HStdout>) {
283+
println!("Interrupt fired! This means that the button was pressed.");
284+
}
285+
286+
#[exception]
287+
fn SysTick() {
288+
system_clock::tick();
289+
// print a `.` every 500ms
290+
if system_clock::ticks() % 50 == 0 && lcd::stdout::is_initialized() {
291+
print!(".");
292+
}
293+
}
294+
295+
#[exception]
296+
fn HardFault(ef: &ExceptionFrame) -> ! {
297+
panic!("HardFault at {:#?}", ef);
298+
}
299+
300+
// define what happens in an Out Of Memory (OOM) condition
301+
#[alloc_error_handler]
302+
fn rust_oom(_: AllocLayout) -> ! {
303+
panic!("out of memory");
304+
}
305+
306+
#[panic_handler]
307+
fn panic(info: &PanicInfo) -> ! {
308+
interrupt::disable();
309+
310+
if lcd::stdout::is_initialized() {
311+
println!("{}", info);
312+
}
313+
314+
if let Ok(mut hstdout) = hio::hstdout() {
315+
let _ = writeln!(hstdout, "{}", info);
316+
}
317+
318+
// OK to fire a breakpoint here because we know the microcontroller is connected to a debugger
319+
asm::bkpt();
320+
321+
loop {}
322+
}

0 commit comments

Comments
 (0)