spi-test/src/main.rs

128 lines
3.4 KiB
Rust

#![no_std]
#![feature(asm, used, const_fn, naked_functions, alloc, box_syntax)]
#![no_main]
#![feature(extern_prelude)]
#[macro_use]
extern crate hcl;
#[macro_use]
extern crate alloc;
use core::mem;
use hcl::platform::gpio;
use hcl::platform::rcc;
use hcl::platform::scs;
use hcl::platform::PeripheralRef;
use hcl::platform::Location;
use hcl::platform::spi;
fn configure_clocks(rcc: &mut rcc::RCC) {
rcc.clock_control.set_hse_on(true);
while !rcc.clock_control.hse_ready() {}
rcc.clock_config
.configure(|c| {
c.set_pll_multiplier(10)
.set_pll_source(rcc::PllSource::HsiDiv2)
});
rcc.clock_control.set_pll_on(true);
while !rcc.clock_control.pll_ready() {}
rcc.clock_config
.switch_clock_source(rcc::SystemClockSource::Pll);
}
fn configure_peripherals(rcc: &mut hcl::platform::rcc::RCC,
gpio_a: &mut gpio::GPIO,
gpio_c: &mut gpio::GPIO) {
rcc.apb2_enable
.configure(|a| a.set_gpio_a(true).set_gpio_c(true).set_spi1(true));
gpio_a.configure(|g| {
g.set_mode(2, gpio::PinMode::Output50MHz)
.set_output_config(2, gpio::OutputConfig::AfPushPull)
.set_mode(3, gpio::PinMode::Output50MHz)
.set_output_config(3, gpio::OutputConfig::AfPushPull)
// SCK1
.set_mode(5, gpio::PinMode::Output50MHz)
.set_output_config(5, gpio::OutputConfig::AfPushPull)
// MOSI1
.set_mode(7, gpio::PinMode::Output50MHz)
.set_output_config(7, gpio::OutputConfig::AfPushPull)
// MISO1
.set_mode(6, gpio::PinMode::Input)
.set_input_config(6, gpio::InputConfig::PullUpDown)
// ST7735 cs pin
.set_mode(0, gpio::PinMode::Output50MHz)
.set_output_config(0, gpio::OutputConfig::PushPull)
});
gpio_c.configure(|g| {
g.set_mode(13, gpio::PinMode::Output50MHz)
.set_output_config(13, gpio::OutputConfig::PushPull)
});
}
fn write_byte<SPIAddr>(spi : &mut PeripheralRef<spi::SPI, SPIAddr>, byte : u8)
where SPIAddr: Location {
spi.set_data(byte as u32);
while !spi.tx_buffer_empty() {};
while spi.busy() {};
}
const LOGO_PX: [u16; 11] =
[0x4081, 0x4880, 0x4880, 0x2861, 0x38c1, 0x38c1, 0x30a1, 0x3081, 0x2861, 0x1861, 0x1061];
// allowing inlining into main() breaks the stack, since main() must be naked to set up a process stack.
#[inline(never)]
fn run(mut scs: scs::Instance, mut p: hcl::platform::Instance) {
configure_clocks(&mut p.rcc);
configure_peripherals(&mut p.rcc, &mut p.gpio_a, &mut p.gpio_c);
let mut spi = p.spi1;
let mut gpio = p.gpio_a;
spi.configure(|s| {
s.set_master_mode(true)
.set_software_slave_select(true)
.set_clock_divider(8)
// required for master mode, even if ss is done manually
.set_slave_select_output_enabled(true)
.set_enabled(true)
});
gpio.set_bit(0);
loop {
for i in 0..11 {
let word = LOGO_PX[i];
let data0 = (word >> 8) as u8;
let data1 = (word & 0xFF) as u8;
gpio.reset_bit(0);
write_byte(&mut spi, data0);
write_byte(&mut spi, data1);
gpio.set_bit(0);
}
}
}
entry_point!(main);
fn main(scs: scs::Instance, p: hcl::platform::Instance) {
declare_thread_stack!(stack, 3072);
unsafe {
hcl::set_process_stack(&stack);
hcl::use_process_stack(true);
}
run(scs, p);
}