Реализация I2C на Rust stm32f3discovery

Итак, я пытаюсь создать несколько функций, которые помогают взаимодействовать с интерфейсом i2c на stm32f3discovery. У меня проблемы со следующим кодом. Все это компилируется и запускается, но когда я запускаю цикл while, проверяющий, установлен ли регистр txis (проверяет, пуст ли txdr), он просто зависает в этой строке, и регистр, по-видимому, никогда не устанавливается. Если я возьму эту строку, она зависнет в цикле while, проверяя, очищен ли регистр tc (передача завершена).

my_api.rs

pub fn new(rcc: &stm32f3::stm32f303::RCC, gpiob: &stm32f3::stm32f303::GPIOB, i2c: &stm32f3::stm32f303::I2C1) -> Self {
        rcc.apb1enr.write(|w| w.i2c1en().set_bit()); //enable i2c1 clock
        rcc.ahbenr.write(|w| w.iopaen().set_bit()); //enable gpioa clock

        gpiob.moder.write(|w| w.moder8().bits(0b10).moder9().bits(0b10)); //alternate function mode
        gpiob.pupdr.write(|w| unsafe{w.pupdr8().bits(0b01).pupdr9().bits(0b01)}); //pull up resister
        gpiob.otyper.write(|w| w.ot8().set_bit().ot9().set_bit()); //open drain output
        gpiob.ospeedr.write(|w| w.ospeedr8().bits(0b11).ospeedr9().bits(0b11)); //high speed
        gpiob.afrh.write(|w| w.afrh8().bits(0b0100).afrh9().bits(0b0100)); //alternate function 4

        i2c.cr1.write(|w| w.pe().clear_bit());

        i2c.timingr.write(|w| {
            w.presc().bits(1); // all settings from page 849 on port mapping
            w.scll().bits(0x13); // standard mode at 8MHz cpu and 100kHz i2c
            w.sclh().bits(0xF);
            w.sdadel().bits(0x2);
            w.scldel().bits(0x4)
        });

        i2c.cr1.write(|w| {
            w.nostretch().clear_bit();
            w.txie().set_bit(); //enable interrupt registers
            w.rxie().set_bit()
        });
        i2c.cr1.write(|w| w.pe().set_bit()); //enable preipheral


        i2c_func{}
    }

    pub fn read(&self, i2c: &stm32f3::stm32f303::I2C1, device_address: u16, register_address: u8, request_length: u8, rx_data: &mut [u8]) {

        i2c.cr2.write(|w| {
            w.sadd().bits(device_address); //set device address
            w.nbytes().bits(1); //amount of bytes to send
            w.rd_wrn().clear_bit(); //set as a write operation
            w.autoend().clear_bit()
        });

        i2c.cr2.write(|w| w.start().set_bit()); //send start signal
        //hangs on this line
        while i2c.isr.read().txis().bit_is_clear() {} //wait for txis to register to be set

        i2c.txdr.write(|w| w.txdata().bits(register_address)); // Send the address of the register that we want to read: IRA_REG_M


        while i2c.isr.read().tc().bit_is_clear() {} // Wait until transfer complete


        i2c.cr2.modify(|_, w| {
            w.nbytes().bits(request_length); //set 
            w.rd_wrn().set_bit();
            w.autoend().set_bit()
        });

        i2c.cr2.write(|w| w.start().set_bit());

        for count in 0..request_length{
            // Wait until we have received the contents of the register
            while i2c.isr.read().rxne().bit_is_clear() {}

            // Broadcast STOP (automatic because of `AUTOEND = 1`)
            rx_data[count as usize] = i2c.rxdr.read().rxdata().bits()
        }
    }

main.rs

#![no_std]
#![no_main]

// pick a panicking behavior
extern crate panic_halt; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// extern crate panic_abort; // requires nightly
// extern crate panic_itm; // logs messages over ITM; requires ITM support
// extern crate panic_semihosting; // logs messages to the host stderr; requires a debugger

use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};
use stm32f3::stm32f303;


mod my_api;

#[entry]
fn main() -> ! {
    //hprintln!("Starting Setup").unwrap();

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

    let gpioe = periph.GPIOE;
    let rcc = periph.RCC;
    let tim6 = periph.TIM6;
    let gpiob = periph.GPIOB;
    let i2c1 = periph.I2C1;


    let i2c = my_api::i2c_mod::i2c_func::new(&rcc, &gpiob, &i2c1);

    let mut rx_data: [u8; 10] = [0,0,0,0,0,0,0,0,0,0];
    i2c.read(&i2c1, 0b001_1110, 0x0A, 1, &mut rx_data);

    hprintln!("{}", rx_data[0]).unwrap();

    loop {}
}

0 ответов

Другие вопросы по тегам