I'm trying to configure my stm32f446 nucleo board to transmit a simple message to the pc over usart2. I've read the manual and configured it to work with a single buffer. However, the rust code compiles but does not print anything to the putty console. The C version works fine. I was trying to step through the code while looking at the disassembly view, but code was behaving unpredictably.
This is the original C code written by controller's tech:
/**
******************************************************************************
CLOCK Setup For STM32F446RE
Author: ControllersTech
Updated: 2nd Aug 2020
******************************************************************************
Copyright (C) 2017 ControllersTech.com
This is a free software under the GNU license, you can redistribute it and/or modify it under the terms
of the GNU General Public License version 3 as published by the Free Software Foundation.
This software library is shared with public for educational purposes, without WARRANTY and Author is not liable for any damages caused directly
or indirectly by this software, read more about this on the GNU General Public License.
******************************************************************************
*/
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = PLL (HSE)
* SYSCLK(Hz) = 180000000
* HCLK(Hz) = 180000000
* AHB Prescaler = 1
* APB1 Prescaler = 4
* APB2 Prescaler = 2
* HSE Frequency(Hz) = 8000000
* PLL_M = 4
* PLL_N = 180
* PLL_P = 2
* VDD(V) = 3.3
* Main regulator output voltage = Scale1 mode
* Flash Latency(WS) = 5
* @param None
* @retval None
*/
#include "RccConfig.h"
void SysClockConfig (void)
{
/*************>>>>>>> STEPS FOLLOWED <<<<<<<<************
1. ENABLE HSE and wait for the HSE to become Ready
2. Set the POWER ENABLE CLOCK and VOLTAGE REGULATOR
3. Configure the FLASH PREFETCH and the LATENCY Related Settings
4. Configure the PRESCALARS HCLK, PCLK1, PCLK2
5. Configure the MAIN PLL
6. Enable the PLL and wait for it to become ready
7. Select the Clock Source and wait for it to be set
********************************************************/
#define PLL_M 4
#define PLL_N 180
#define PLL_P 0 // PLLP = 2
// 1. ENABLE HSE and wait for the HSE to become Ready
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
// 2. Set the POWER ENABLE CLOCK and VOLTAGE REGULATOR
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_VOS;
// 3. Configure the FLASH PREFETCH and the LATENCY Related Settings
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_5WS;
// 4. Configure the PRESCALARS HCLK, PCLK1, PCLK2
// AHB PR
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
// APB1 PR
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
// APB2 PR
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
// 5. Configure the MAIN PLL
RCC->PLLCFGR = (PLL_M <<0) | (PLL_N << 6) | (PLL_P <<16) | (RCC_PLLCFGR_PLLSRC_HSE);
// 6. Enable the PLL and wait for it to become ready
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
// 7. Select the Clock Source and wait for it to be set
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
}
this is the ported rust code that I wrote:
#![no_std]
#![no_main]
pub mod stm32_lib;
// pick a panicking behavior
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
// use panic_abort as _; // requires nightly
// use panic_itm as _; // logs messages over ITM; requires ITM support
// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger
use cortex_m_rt::entry;
use stm32_lib::rcc;
use stm32f4::stm32f446;
pub fn uart_send_data(data: &str, uart: &mut stm32f446::USART2) {
//Write the data to send in the USART DATA register
for &byte in data.as_bytes() {
uart.dr.write(|w| w.dr().bits(u16::from(byte)));
while !(uart.sr.read().tc().bit()) {}
}
}
#[entry]
fn main() -> ! {
let peripherals = stm32f446::Peripherals::take().unwrap();
let mut rcc = peripherals.RCC;
let mut timer = peripherals.TIM11; //used for the delay
let mut flash = peripherals.FLASH;
let mut gpio = peripherals.GPIOA; //general purpose pin normally used as output.
let mut pwr = peripherals.PWR;
let mut uart = peripherals.USART2;
rcc::initialize_clock(&mut rcc, &mut pwr, &mut flash);
rcc::config_timer(&mut rcc, &mut timer);
//Enable the UART CLOCK and GPIO CLOCK
rcc.apb1enr.modify(|_r, w| w.usart2en().set_bit());
rcc.ahb1enr.modify(|_r, w| w.gpioaen().set_bit());
//Configure the alternate mode register for the gpio
gpio.moder.write(|w| w.moder2().bits(0b10));
gpio.moder.modify(|_r, w| w.moder3().bits(0b10));
gpio.ospeedr.modify(|_r, w| w.ospeedr2().bits(3));
gpio.ospeedr.modify(|_r, w| w.ospeedr3().bits(0b11));
gpio.afrl.modify(|_r, w| w.afrl2().bits(0b0111));
gpio.afrl.modify(|_r, w| w.afrl3().bits(0b0111));
//Enable the UART by writing the UE bit in the USART_CR1 register
uart.cr1.write(|w| w.ue().enabled());
//Program the M bit to define the word length
uart.cr1.modify(|_r, w| w.m().clear_bit());
//Select the desired baud rate using USART BRR register
uart.brr.write(|w| w.div_fraction().bits(7));
uart.brr.modify(|_r, w| w.div_mantissa().bits(24));
//Enable the transmitter/Reciver by Setting the TE and RE bits in USART_CR1 Register
uart.cr1.modify(|_r, w| w.te().set_bit()); // TE = 1;
uart.cr1.modify(|_r, w| w.re().set_bit()); // RE = 1;
uart_send_data("ok", &mut uart);
loop {
//
}
}
Just need some direction I could take in debugging the issue. thanks for reading