Skip to content

Commit 44dfef3

Browse files
committed
Add SPI initialization process
1 parent 5471dbb commit 44dfef3

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ targets = ["riscv64gc-unknown-none-elf"]
1414

1515
[dependencies]
1616
embedded-hal = "1.0.0-alpha.1"
17-
nb = "1"
17+
nb = "0.1.1"
1818
k210-pac = "0.2.0"
1919
bitflags = "1.2.1"

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod gpio;
1919
pub mod gpiohs;
2020
pub mod plic;
2121
pub mod serial;
22+
pub mod spi;
2223
pub mod sha256;
2324
pub mod stdout;
2425
pub mod sysctl;

src/spi.rs

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
//! (TODO) Serial Peripheral Interface (SPI)
2+
3+
use crate::pac::SPI0;
4+
use crate::clock::Clocks;
5+
use crate::sysctl::{self, APB0};
6+
pub use embedded_hal::spi::{Mode, Polarity, Phase};
7+
use core::convert::Infallible;
8+
9+
///
10+
pub struct Spi<SPI> {
11+
spi: SPI
12+
}
13+
14+
impl Spi<SPI0> {
15+
pub fn spi0(
16+
spi: SPI0,
17+
mode: Mode,
18+
frame_format: FrameFormat,
19+
endian: Endian,
20+
clock: &Clocks,
21+
apb0: &mut APB0
22+
) -> Self {
23+
let work_mode = hal_mode_to_pac(mode);
24+
let frame_format = frame_format_to_pac(frame_format);
25+
let tmod = crate::pac::spi0::ctrlr0::TMOD_A::TRANS_RECV; // todo other modes
26+
let endian = endian as u32;
27+
let data_bit_length = 8; // todo more length
28+
let _ = clock; // todo
29+
unsafe {
30+
// no interrupts for now
31+
spi.imr.write(|w| w.bits(0x00));
32+
// no dma for now
33+
spi.dmacr.write(|w| w.bits(0x00));
34+
spi.dmatdlr.write(|w| w.bits(0x10));
35+
spi.dmardlr.write(|w| w.bits(0x00));
36+
// no slave access for now
37+
spi.ser.write(|w| w.bits(0x00));
38+
spi.ssienr.write(|w| w.bits(0x00));
39+
// set control registers
40+
spi.ctrlr0.write(|w| {
41+
w.work_mode()
42+
.variant(work_mode)
43+
.tmod()
44+
.variant(tmod)
45+
.frame_format()
46+
.variant(frame_format)
47+
.data_length()
48+
.bits(data_bit_length - 1)
49+
});
50+
spi.spi_ctrlr0.reset(); // standard
51+
spi.endian.write(|w| w.bits(endian));
52+
}
53+
// enable APB0 bus
54+
apb0.enable();
55+
// enable peripheral via sysctl
56+
sysctl::clk_en_peri().modify(|_r, w|
57+
w.spi0_clk_en().set_bit());
58+
Spi { spi }
59+
}
60+
61+
pub fn release(self) -> SPI0 {
62+
// power off
63+
sysctl::clk_en_peri().modify(|_r, w|
64+
w.spi0_clk_en().clear_bit());
65+
self.spi
66+
}
67+
}
68+
69+
impl embedded_hal::spi::FullDuplex<u8> for Spi<SPI0> {
70+
/// An enumeration of SPI errors
71+
type Error = Infallible;
72+
73+
/// Reads the word stored in the shift register
74+
///
75+
/// **NOTE** A word must be sent to the slave before attempting to call this
76+
/// method.
77+
fn try_read(&mut self) -> nb::Result<u8, Self::Error> {
78+
todo!()
79+
}
80+
81+
/// Sends a word to the slave
82+
fn try_send(&mut self, word: u8) -> nb::Result<(), Self::Error> {
83+
todo!("{}", word)
84+
}
85+
}
86+
87+
#[derive(Clone, Copy, PartialEq, Eq)]
88+
pub enum FrameFormat {
89+
Standard,
90+
Dual,
91+
Quad,
92+
Octal,
93+
}
94+
#[derive(Clone, Copy, PartialEq, Eq)]
95+
#[repr(u32)]
96+
pub enum Endian {
97+
Little = 0,
98+
Big = 1,
99+
}
100+
101+
#[inline]
102+
fn hal_mode_to_pac(mode: Mode) -> crate::pac::spi0::ctrlr0::WORK_MODE_A {
103+
use crate::pac::spi0::ctrlr0::WORK_MODE_A;
104+
use {Polarity::*, Phase::*};
105+
match (mode.polarity, mode.phase) {
106+
(IdleLow, CaptureOnFirstTransition) => WORK_MODE_A::MODE0,
107+
(IdleLow, CaptureOnSecondTransition) => WORK_MODE_A::MODE1,
108+
(IdleHigh, CaptureOnFirstTransition) => WORK_MODE_A::MODE2,
109+
(IdleHigh, CaptureOnSecondTransition) => WORK_MODE_A::MODE3,
110+
}
111+
}
112+
113+
#[inline]
114+
fn frame_format_to_pac(frame_format: FrameFormat) -> crate::pac::spi0::ctrlr0::FRAME_FORMAT_A {
115+
use crate::pac::spi0::ctrlr0::FRAME_FORMAT_A;
116+
match frame_format {
117+
FrameFormat::Standard => FRAME_FORMAT_A::STANDARD,
118+
FrameFormat::Dual => FRAME_FORMAT_A::DUAL,
119+
FrameFormat::Quad => FRAME_FORMAT_A::QUAD,
120+
FrameFormat::Octal => FRAME_FORMAT_A::OCTAL,
121+
}
122+
}

0 commit comments

Comments
 (0)