forked from stm32-rs/stm32f1xx-hal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi-slave.rs
154 lines (125 loc) · 3.84 KB
/
spi-slave.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
//! SPI slave mode test
//!
//! spi1 master <-> spi2 slave
//! PA5 <-SCK-> PB13
//! PA6 <-MISO-> PB14
//! PA7 <-MOSI-> PB15
#![allow(clippy::empty_loop)]
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use panic_halt as _;
use cortex_m::{asm, singleton};
use embedded_hal::spi::{Mode, Phase, Polarity};
pub const MODE: Mode = Mode {
phase: Phase::CaptureOnSecondTransition,
polarity: Polarity::IdleHigh,
};
use stm32f1xx_hal::{
gpio::{
gpiob::{PB13, PB14, PB15},
Alternate, Floating, Input, PushPull,
},
pac::{self, interrupt, Peripherals, SPI2},
prelude::*,
spi::{Event, Slave, Spi, Spi2NoRemap},
};
type SlaveSpi = Spi<
SPI2,
Spi2NoRemap,
(
PB13<Input<Floating>>,
PB14<Alternate<PushPull>>,
PB15<Input<Floating>>,
),
u8,
Slave,
>;
static mut SPI2SLAVE: Option<SlaveSpi> = None;
#[entry]
fn main() -> ! {
let dp = Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut afio = dp.AFIO.constrain();
let mut gpioa = dp.GPIOA.split();
let mut gpiob = dp.GPIOB.split();
// SPI1
let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl);
let miso = gpioa.pa6;
let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl);
let spi1 = Spi::spi1(
dp.SPI1,
(sck, miso, mosi),
&mut afio.mapr,
MODE,
10.kHz(),
clocks,
);
// SPI2
let sck = gpiob.pb13;
let miso = gpiob.pb14.into_alternate_push_pull(&mut gpiob.crh);
let mosi = gpiob.pb15;
let spi2 = Spi::spi2_slave(dp.SPI2, (sck, miso, mosi), MODE);
// Set up the DMA device
let dma = dp.DMA1.split();
let master_spi_dma = spi1.with_rx_tx_dma(dma.2, dma.3);
let slave_spi_dma = spi2.with_rx_tx_dma(dma.4, dma.5);
let master_buf = singleton!(: [u8; 12] = [0; 12]).unwrap();
let slave_buf = singleton!(: [u8; 12] = [0; 12]).unwrap();
// Make sure the buffers are the same length
let slave_transfer = slave_spi_dma.read_write(slave_buf, b"hello,master");
let master_transfer = master_spi_dma.read_write(master_buf, b"hello, slave");
let (buffer, spi1_dma) = master_transfer.wait();
let (_buffer, spi2_dma) = slave_transfer.wait();
asm::bkpt();
// test SPI with interrupts
let (mut spi2, _, _) = spi2_dma.release();
spi2.listen(Event::Rxne);
spi2.listen(Event::Txe);
spi2.listen(Event::Error);
cortex_m::interrupt::free(|_| unsafe {
SPI2SLAVE.replace(spi2);
});
unsafe {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::SPI2);
}
let master_transfer = spi1_dma.read_write(buffer.0, buffer.1);
let (_buffer, _spi1_dma) = master_transfer.wait();
loop {}
}
const R_BUFFER_LEN: usize = 16;
static mut R_BUFFER: &mut [u8; R_BUFFER_LEN] = &mut [0; R_BUFFER_LEN];
static mut RIDX: usize = 0;
const W_BUFFER_LEN: usize = 3;
static W_BUFFER: &[u8; W_BUFFER_LEN] = &[1, 2, 3];
static mut WIDX: usize = 0;
#[interrupt]
unsafe fn SPI2() {
cortex_m::interrupt::free(|_| {
if let Some(spi2) = SPI2SLAVE.as_mut() {
if spi2.is_overrun() {
// mcu processing speed is not enough
asm::bkpt();
}
if spi2.is_rx_not_empty() {
if let Ok(w) = nb::block!(spi2.read()) {
R_BUFFER[RIDX] = w;
RIDX += 1;
if RIDX >= R_BUFFER_LEN - 1 {
RIDX = 0;
}
}
}
if spi2.is_tx_empty() {
if let Ok(()) = nb::block!(spi2.send(W_BUFFER[WIDX])) {
WIDX += 1;
if WIDX >= W_BUFFER_LEN {
WIDX = 0;
}
}
}
}
})
}