Skip to content
Snippets Groups Projects
Commit d17eff19 authored by Johannes Sjölund's avatar Johannes Sjölund
Browse files

IMU LSM9DS1 lib and serial print example

parent 158bfaa0
No related branches found
No related tags found
No related merge requests found
//! Interfacing the LSM9DS1 3D accelerometer, gyroscope, and magnetometer
//! using SPI3.
//!
//! Using the SparkFun LSM9DS1 breakout board, connect:
//! PA_8 -> CS_AG (Chip Select for accelerometer/gyro)
//! PA_9 -> CS_M (Chip Select for magnetometer)
//! PB_3 -> SCL (SPI clock)
//! PB_4 -> SDO_M and SDO_AG (Combined SPI MISO)
//! PB_5 -> SDA (SPI MOSI)
#![deny(unsafe_code)]
#![deny(warnings)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![feature(lang_items)]
#![no_std]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
#[macro_use]
extern crate f4;
extern crate heapless;
extern crate stm32f40x;
use cortex_m::peripheral::SystClkSource;
use core::ops::Deref;
use f4::lsm9ds1::{ImuSettings, Lsm9ds1};
use f4::Serial;
use f4::Spi;
use f4::dma::{Buffer, Dma1Channel6};
use f4::time::Hertz;
use f4::clock;
use rtfm::{app, Threshold};
const BAUD_RATE: Hertz = Hertz(115_200);
const FREQUENCY: u32 = 10;
const MAX_TX_LEN: usize = 256;
app! {
device: f4::stm32f40x,
resources: {
static IMU_SETTINGS: ImuSettings = ImuSettings::new();
static TX_BUFFER: Buffer<[u8; MAX_TX_LEN], Dma1Channel6> = Buffer::new([0; MAX_TX_LEN]);
},
tasks: {
SYS_TICK: {
path: sys_tick,
priority: 1,
resources: [TX_BUFFER, IMU_SETTINGS, DMA1, USART2, SPI3, GPIOA],
},
DMA1_STREAM6: {
path: tx_done,
priority: 2,
resources: [TX_BUFFER, DMA1],
},
},
}
fn sys_tick(t: &mut Threshold, mut r: SYS_TICK::Resources) {
let spi = Spi(&**r.SPI3);
let imu = Lsm9ds1(&**r.SPI3);
let g = imu.read_gyro(&spi, r.GPIOA, &r.IMU_SETTINGS);
let a = imu.read_acc(&spi, r.GPIOA, &r.IMU_SETTINGS);
let m = imu.read_mag(&spi, r.GPIOA, &r.IMU_SETTINGS);
uprint!(
t,
r.USART2,
r.DMA1,
r.TX_BUFFER,
"a=({0: <11}, {1: <11}, {2: <11}), g=({3: <11}, {4: <11}, {5: <11}), m=({6: <11}, {7: <11}, {8: <11})\r\n",
a.x,a.y,a.z,g.x,g.y,g.z,m.x,m.y,m.z
);
}
fn init(p: init::Peripherals, r: init::Resources) {
let clk = clock::set_84_mhz(&p.RCC, &p.FLASH);
p.SYST.set_clock_source(SystClkSource::Core);
p.SYST.set_reload(clk / FREQUENCY);
p.SYST.enable_interrupt();
p.SYST.enable_counter();
// Start the serial port
let serial = Serial(p.USART2);
serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
// Setup CS pins
{
// Power on GPIOA
p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
// Set PA_8 and PA_9 as outputs
p.GPIOA
.moder
.modify(|_, w| w.moder8().bits(1).moder9().bits(1));
// Highest output speed
p.GPIOA
.ospeedr
.modify(|_, w| w.ospeedr8().bits(3).ospeedr9().bits(3));
// Default to high (CS disabled)
p.GPIOA
.odr
.modify(|_, w| w.odr8().bit(true).odr9().bit(true));
}
// Init the SPI peripheral
let spi = Spi(p.SPI3);
spi.init(p.GPIOA, p.GPIOB, p.RCC);
// For the LSM9DS1, the second clock transition is
// the first data capture edge
// RM0368 20.5.1
p.SPI3.cr1.modify(|_, w| w.cpha().set_bit());
spi.enable();
let imu = Lsm9ds1(p.SPI3);
imu.init_gyro(&spi, &p.GPIOA, &r.IMU_SETTINGS);
imu.init_acc(&spi, &p.GPIOA, &r.IMU_SETTINGS);
imu.init_mag(&spi, &p.GPIOA, &r.IMU_SETTINGS);
}
// Interrupt for serial transmit DMA
fn tx_done(t: &mut Threshold, r: DMA1_STREAM6::Resources) {
use rtfm::Resource;
// We need to unlock the DMA to use it again in the future
r.TX_BUFFER.claim(t, |tx, t| {
r.DMA1.claim(t, |dma, _| tx.release(dma).unwrap());
});
// Clear the transmit buffer so we do not retransmit old stuff
r.TX_BUFFER.claim_mut(t, |tx, _| {
let array = &**tx.deref();
array.borrow_mut()[..MAX_TX_LEN].clone_from_slice(&[0; MAX_TX_LEN]);
});
}
fn idle() -> ! {
loop {
rtfm::wfi();
}
}
......@@ -82,11 +82,7 @@ fn disable_ag(gpioa: &mut GPIOA) {
fn send_receive(spi: &f4::Spi<f4::stm32f40x::SPI3>, addr: u8) -> u8 {
// Send and receive using the hal crate
while spi.send(addr).is_err() {}
loop {
if let Ok(_) = spi.read() {
break;
}
}
while spi.read().is_err() {}
while spi.send(0).is_err() {}
loop {
if let Ok(byte) = spi.read() {
......
......@@ -31,4 +31,9 @@ impl PA5 {
(*GPIOA.get()).odr.modify(|_, w| w.odr5().bit(false));
}
}
/// True if LED is ON, false otherwise.
pub fn is_on(&self) -> bool {
unsafe { (*GPIOA.get()).odr.read().odr5().bit_is_set() }
}
}
......@@ -45,8 +45,9 @@ pub mod pwm;
pub mod capture;
pub mod clock;
pub mod spi;
pub mod lsm9ds1;
pub mod frequency;
use frequency::*;
pub use hal::prelude;
......@@ -56,6 +57,7 @@ pub use timer::{Channel, Timer};
pub use pwm::Pwm;
pub use capture::Capture;
pub use spi::Spi;
pub use lsm9ds1::{ImuSettings, Lsm9ds1, Vector3};
/// println over semihosting
#[macro_export]
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment