SPI stm32 f3discovery communication

I have been trying for the past few days to try and get the SPI working on the stm32f3discovery in order to talk to the l3gd20 gyroscope. I started off with getting nothing back from it but am now at a stage where I am getting data back from the gyro but it all seems to be garbage, I am pretty sure it is to do with the FIFO system inside the stm32f303 processor but can't work out what is going wrong. When i run the who_am_i function it works well and returns 212 as it should, its just the other results that are results struggling.

Any help at all will be much appreciated.

Something weird to note as well, if i change the reg_address and the data variables around in my_api::spi_mod::spi_func::write_data() I still get the same weird results.



// pick a panicking behavior
extern crate panic_halt; // you can put a breakpoint on `rust_begin_unwind` to catch panics

use cortex_m::{asm, iprintln, Peripherals as core_peripherals};
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use stm32f3::stm32f303;

mod my_api;
mod sensor;

fn main() -> ! {

    let periph = stm32f303::Peripherals::take().unwrap();
    let mut core_p = core_peripherals::take().unwrap();

    let itm = &mut core_p.ITM.stim[0];

    let gpioa = periph.GPIOA;
    let gpiob = periph.GPIOB;
    let gpioe = periph.GPIOE;
    let rcc = periph.RCC;
    let tim6 = periph.TIM6;
    let i2c1 = periph.I2C1;
    let flash = periph.FLASH;
    let spi1 = periph.SPI1;

    set_to_72MHz(&rcc, &flash);

    let spi = my_api::spi_mod::spi_func::new(&rcc, &gpioa, &gpioe, &spi1);

    let mut gyro = sensor::Gyro::gyro::new(&spi, &spi1).init(&spi, &spi1, &gpioe);

    iprintln!(itm, "Finished Setup");
    loop {

            gyro.read_data(&spi, &spi1, &gpioe);
            iprintln!(itm, "{:?}", (gyro.x, gyro.y, gyro.z));


pub mod Gyro{
    pub use crate::my_api::spi_mod;
    const WHO_AM_I: u8 = 0b0000_1111;
    const CTRL_REG1: u8 = 0x20;
    const CTRL_REG4: u8 = 0x23;
    const OUT_X_L: u8 = 0x28;
    const OUT_X_H: u8 = 0x29;
    const OUT_Y_L: u8 = 0x2A;
    const OUT_Y_H: u8 = 0x2B;
    const OUT_Z_L: u8 = 0x2C;
    const OUT_Z_H: u8 = 0x2D;

    pub struct gyro{
        pub x: i32,
        pub y: i32,
        pub z: i32,
        offset_x: i32,
        offset_y: i32,
        offset_z: i32,

    impl gyro{
        pub fn new(my_spi_mod: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1) -> Self {
                x: 0,
                y: 0,
                z: 0,
                offset_x: 0,
                offset_y: 0,
                offset_z: 0,

        pub fn init(self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> Self{
            spi.write_data(&spi1, CTRL_REG1, 0x3F); //power on the gyro // 760Hz - 50 Cut off
            //spi.write_data(&spi1, CTRL_REG4, 0x00); //setup to continues update - 500dps


        pub fn who_am_i(&self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> u8 {
            let data = spi.read_register(&spi1, WHO_AM_I);

        pub fn read_data(&mut self, spi: &spi_mod::spi_func, spi1: &stm32f3::stm32f303::SPI1, gpioe: &stm32f3::stm32f303::GPIOE) -> (i32, i32, i32){
            let mut data: [u8;6] = [0,0,0,0,0,0];
            data[0] = spi.read_register(&spi1, OUT_X_L); for i in 0..200{} //the for loop sems to help 
            data[1] = spi.read_register(&spi1, OUT_X_H); for i in 0..200{} //otherwise all the 
            data[2] = spi.read_register(&spi1, OUT_Y_L); for i in 0..200{}
            data[3] = spi.read_register(&spi1, OUT_Y_H); for i in 0..200{}
            data[4] = spi.read_register(&spi1, OUT_Z_L); for i in 0..200{}
            data[5] = spi.read_register(&spi1, OUT_Z_H);

            // spi.read_multiple_register(&spi1, OUT_X_L, &mut data, 6);    
            let x_data: i32 = {let result = ((data[1] as i32) << 8) + (data[0] as i32); if result >= 32768 {-65536+result-self.offset_x as i32} else {result-self.offset_x as i32}};
            let y_data: i32 = {let result = ((data[3] as i32) << 8) + (data[2] as i32); if result >= 32768 {-65536+result-self.offset_y as i32} else {result-self.offset_y as i32}};
            let z_data: i32 = {let result = ((data[5] as i32) << 8) + (data[4] as i32); if result >= 32768 {-65536+result-self.offset_z as i32} else {result-self.offset_z as i32}};

            self.x = x_data;
            self.y = y_data;
            self.z = z_data;



        fn cs_low(&self, gpioe: &stm32f3::stm32f303::GPIOE){
            gpioe.odr.modify(|_,w| w.odr3().clear_bit());

        fn cs_high(&self, gpioe: &stm32f3::stm32f303::GPIOE){
            gpioe.odr.modify(|_,w| w.odr3().set_bit());



pub mod spi_mod{
    pub struct spi_func{}

    impl spi_func{
        pub fn new(rcc: &stm32f3::stm32f303::RCC, gpioa: &stm32f3::stm32f303::GPIOA, gpioe: &stm32f3::stm32f303::GPIOE, spi: &stm32f3::stm32f303::SPI1) -> Self {
            rcc.apb2enr.modify(|_,w| w.spi1en().set_bit()); //enable spi clock
            rcc.apb2rstr.modify(|_,w| w.spi1rst().set_bit()); //reset clock
            rcc.apb2rstr.modify(|_,w| w.spi1rst().clear_bit()); //reset clock

            rcc.ahbenr.modify(|_,w| w.iopaen().set_bit()); // enable gpio clocks
            rcc.ahbenr.modify(|_,w| w.iopeen().set_bit());

            gpioe.moder.modify(|_,w| w.moder3().bits(0b01)); //CS pin
            gpioe.otyper.modify(|_,w| w.ot3().clear_bit());
            gpioe.odr.modify(|_,w| w.odr3().set_bit()); //bring pe3 high to disable gyro com

            gpioa.moder.modify(|_,w| {
                w.moder5().bits(0b10); // output type

            gpioa.otyper.modify(|_,w| {
                w.ot5().clear_bit();// push pull type

            gpioa.ospeedr.modify(|_,w| {
                w.ospeedr5().bits(0b11);// fast mode

            gpioa.afrl.modify(|_,w| {
                w.afrl5().bits(0b0101);//Alternate function 5

            spi.cr1.modify(|_,w| {
                w.bidimode().clear_bit(); //bidirectional mode
                w.rxonly().clear_bit(); //full duplex
                w.ssm().set_bit(); // hardware slave management disabled
                w.br().bits(0b111); // bring rate from 72MHz to 72/16MHz as gyro cant go above 10MHz
                w.mstr().set_bit(); // set to master mode
                w.cpol().set_bit(); // set to mode 3 to work for the l3gd20

            spi.cr2.modify(|_,w| {
                w.txeie().set_bit(); //enable interupt flags   
                w.ssoe().set_bit() //set to single master mode

            spi.cr1.modify(|_,w| w.spe().set_bit());


        fn check_faults(&self, spi1: &stm32f3::stm32f303::SPI1) -> bool {
            if spi1.sr.read().ovr().bit_is_set(){ //checks through all the flags
            }else if spi1.sr.read().modf().bit_is_set(){
            }else if spi1.sr.read().crcerr().bit_is_set(){
            }else if spi1.sr.read().udr().bit_is_set(){
            } else {

        fn write(&self, spi1: &stm32f3::stm32f303::SPI1, data: u16) {
            if self.check_faults(&spi1){
                spi1.dr.modify(|_,w| w.dr().bits(data)); //write to the dr register
                while spi1.sr.read().bsy().bit_is_clear(){}

        fn read(&self, spi1: &stm32f3::stm32f303::SPI1) -> u8 {
            if self.check_faults(&spi1){
                while spi1.sr.read().bsy().bit_is_clear(){}
                return (spi1.dr.read().dr().bits() >> 8) as u8 //read from the dr register

        pub fn write_data(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8, data: u8) {
            let total_data: u16 = ((data as u16) << 8) + (reg_address as u16);
            self.write(&spi1, total_data);

        pub fn read_register(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8) -> u8{
            self.write(&spi1, (reg_address | 0x80) as u16); //set the bit to read mode and send
            self.read(&spi1) //read the result

        pub fn read_multiple_register(&self, spi1: &stm32f3::stm32f303::SPI1, reg_address: u8, rx_data: &mut [u8], request_length: u8){
            for count in 0..request_length{
                rx_data[count as usize] = self.read_register(&spi1, reg_address + count); //im not using this yet as i am just keeping it simple


These are what the result look like
Screenshot from 2020-05-27 18-57-51

When you set MS bit to 1, it automatically increments address in multiple reading. See page 31 of the datasheet.
I wonder if something like this would solve the issue.

let mut data: [u8; 6] = [0,0,0,0,0,0];
write(&spi1, (OUT_X_L | 0x80 | 0x40) as u16); // R/W = 1, MS = 1
for d in data.iter_mut() {
    spi.write(&spi1, 0x00);
    *d = spi.read(&spi1);

0x80 is R/W bit as you know. 0x40 sets MS bit.

I had that in the read_multiple_registers to begin with before I tried to simplify everything down.
I tried it with your code anyway and this is what came out

Screenshot from 2020-05-28 14-20-44

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.