Skip to content
Snippets Groups Projects
Select Git revision
  • c3ecee05e7a0050a42ffc684402dad788f52c96f
  • master default protected
2 results

.vimrc

Blame
  • usart_clk.rs 5.89 KiB
    //! Test the USART1 instance
    //!
    //! Connect the TX and RX pins to run this test
    //!
    //! PA2 (TX), PA3(RX) on the MCU is connected to the pin header CN3
    //#![deny(unsafe_code)]
    #![deny(warnings)]
    #![allow(warnings)]
    #![feature(proc_macro)]
    #![no_std]
    
    extern crate cortex_m_rtfm as rtfm;
    extern crate cortex_m_semihosting as semihosting;
    extern crate hal;
    #[macro_use]
    extern crate nb;
    #[macro_use]
    extern crate nucleo_64;
    extern crate stm32f40x;
    use hal::usart::USART;
    
    use nucleo_64::time::Hertz;
    
    use rtfm::app;
    use core::ptr;
    use nucleo_64::apb1;
    
    const BAUD_RATE: Hertz = Hertz(115_200);
    
    app! {
        device: nucleo_64::stm32f40x,
    }
    
    use stm32f40x::USART2;
    
    fn serial_init(p: &init::Peripherals) {
        // RM0368 6.3.9
        // enable clock to GPIOA, USART2
        p.RCC.ahb1enr.modify(|_, w| w.gpioaen().enable());
    
        // enable clock to
        p.RCC.apb1enr.modify(|_, w| w.usart2en().bit(true));
    
        // RM0368 8.4.1
        // set output mode for GPIOA
        // PA2 = TX (output mode), PA3 = RX (input mode)
        p.GPIOA.moder.modify(|_, w| {
            w.moder2()
                .variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
                .moder3()
                .variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
        });
    
        // we don't care about the speed register atm
        // DM00102166
        // AF7, Table 9
        // PA2 and PA3 is connected to USART2 TX and RX respectively
        p.GPIOA.afrl.modify(|_, w| w.afrl2().af7().afrl3().af7());
    
        // 8N1, stop bit
        p.USART2.cr2.write(|w| unsafe { w.stop().bits(0b00) });
    
        // baud rate
        //    let brr :<U::Ticks>= BAUD_RATE.into();
        let brr: apb1::Ticks = BAUD_RATE.invert().into();
        let brr = brr.0;
        assert!(brr >= 16, "impossible baud rate");
    
        p.USART2.brr.write(|w| unsafe { w.bits(brr) });
    
        // disable hardware flow control
        // enable DMA TX and RX transfers
        p.USART2.cr3.write(|w| {
            w.rtse() /* Ready To Send disable */
                .clear_bit()
                .ctse() /* Clear To Send disable */
                .clear_bit()
                .dmat() /* Enable DMA Transmit */
                .set_bit()
                .dmar()  /* Enable DMA Receive */
                .set_bit()
        });
    
        // enable TX, RX; disable parity checking
        p.USART2.cr1.write(|w| {
            w.ue() /* Usart Enable */
                .set_bit()
                .re() /* Receiver Enable */
                .set_bit()
                .te() /* Transmitter Enable */
                .set_bit()
                .m() /* Word Length, 8 */
                .clear_bit()
                .pce() /* Parity Control Enable */
                .clear_bit()
                .rxneie() /* Reception Interrupt Enable */
                .clear_bit()
        });
    }
    
    fn clk_init(p: &init::Peripherals) {
        // setting up the flash memory latency
        // RM0368 8.4.1 (register), 3.4 Table 6
        // we assume 3.3 volt operation, thus 2 cycles for 84mHz
        // apb1 will be at 42 MHz
        p.FLASH.acr.modify(|_, w| unsafe { w.latency().bits(2) });
        println!("Flash latency! {:x}", p.FLASH.acr.read().latency().bits());
    
        p.RCC
            .cfgr
            .modify(|_, w| w.sw0().clear_bit().sw1().clear_bit()); //Switch to HSI
        p.RCC.cfgr.modify(|_, w| unsafe { w.ppre1().bits(4) }); //Configure apb1 prescaler = 2,
        p.RCC.apb1enr.modify(|_, w| w.pwren().set_bit());
        p.RCC.cr.write(|w| w.pllon().clear_bit());
    
        //Enable PLL
        //					   PP	  PLLN	    PLLM
        // 0b0000 0000 0000 00 01 0 101010000 010000
        // RM0368 6.3.2
        // PP 01
        p.RCC
            .pllcfgr
            .write(|w| unsafe { w.bits(0b00000000000000010101010000010000) }); //Configure PLL
    
        p.RCC.cr.modify(|_, w| w.pllon().set_bit()); //Enable PLL
    
        while p.RCC.cr.read().pllrdy().bit_is_clear() {}
    
        p.RCC
            .cfgr
            .modify(|_, w| w.sw0().clear_bit().sw1().set_bit()); //Switch to PLL
    
        // System configuration controller clock enable
        p.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit());
    
        p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); //Enable GPIOA clock
        p.RCC.ahb1enr.modify(|_, w| w.gpioben().set_bit()); //Enable GPIOB clock
    }
    
    #[inline(never)]
    fn init(p: init::Peripherals) {
        println!("Init!");
        // clk_init(&p);
        serial_init(&p);
        //USART::initialize(p.GPIOA, p.RCC, p.USART2);
    
        USART::send(p.USART2, "\n\n\nUSART \n\r");
    
        loop {
            let b = block!(read(p.USART2)).unwrap();
            write(p.USART2, b).unwrap();
        }
    }
    
    // Specialized `Result` type
    pub type Result<T> = ::core::result::Result<T, nb::Error<Error>>;
    
    /// An error
    #[derive(Debug)]
    pub enum Error {
        /// De-synchronization, excessive noise or a break character detected
        Framing,
        /// Noise detected in the received frame
        Noise,
        /// RX buffer overrun
        Overrun,
        #[doc(hidden)] _Extensible,
    }
    
    fn write(usart2: &USART2, byte: u8) -> Result<()> {
        let sr = usart2.sr.read();
    
        if sr.ore().bit_is_set() {
            Err(nb::Error::Other(Error::Overrun))
        } else if sr.nf().bit_is_set() {
            Err(nb::Error::Other(Error::Noise))
        } else if sr.fe().bit_is_set() {
            Err(nb::Error::Other(Error::Framing))
        } else if sr.txe().bit_is_set() {
            // NOTE(write_volatile) see NOTE in the `read` method
            unsafe { ptr::write_volatile(&usart2.dr as *const _ as *mut u8, byte) }
            Ok(())
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
    
    fn read(usart2: &USART2) -> Result<u8> {
        let sr = usart2.sr.read();
    
        if sr.ore().bit_is_set() {
            Err(nb::Error::Other(Error::Overrun))
        } else if sr.nf().bit_is_set() {
            Err(nb::Error::Other(Error::Noise))
        } else if sr.fe().bit_is_set() {
            Err(nb::Error::Other(Error::Framing))
        } else if sr.rxne().bit_is_set() {
            // NOTE(read_volatile) the register is 9 bits big but we'll only
            // work with the first 8 bits
            Ok(unsafe {
                ptr::read_volatile(&usart2.dr as *const _ as *const u8)
            })
        } else {
            Err(nb::Error::WouldBlock)
        }
    }
    
    fn idle() -> ! {
        // Will never be hit, as
        rtfm::bkpt();
    
        // Sleep
        loop {
            rtfm::wfi();
        }
    }