Files
gameboy_rs/src/main.rs

112 lines
3.4 KiB
Rust

#![no_std]
#![no_main]
use core::cell::RefCell;
use core::ptr::read_volatile;
use cortex_m::interrupt::Mutex;
use panic_halt as _;
use cortex_m_rt::{entry, exception};
use cortex_m_semihosting::hprintln;
use stm32f1::stm32f103;
use stm32f1::stm32f103::interrupt;
static mut SYS_TICK: u32 = 0;
static I2C1: Mutex<RefCell<Option<stm32f103::I2C1>>> = Mutex::new(RefCell::new(None));
fn get_sys_tick() -> u32 {
unsafe { read_volatile(&raw const SYS_TICK) }
}
#[exception]
fn SysTick() {
unsafe { SYS_TICK += 1; }
}
fn toggle_mcu_led(gpioa: &mut stm32f103::GPIOA) {
gpioa.odr.modify(|r, w| {
match r.odr3().bit() {
true => w.odr3().clear_bit(),
false => w.odr3().set_bit(),
}
});
}
#[interrupt]
fn I2C1_EV() {
cortex_m::interrupt::free(|cs| {
if let Some(ref mut i2c1) = *I2C1.borrow(cs).borrow_mut() {
if i2c1.sr1.read().addr().bit_is_set() {
let _ = i2c1.sr2.read();
i2c1.dr.write(|w| w.dr().bits(0xAA));
}
}
});
}
#[entry]
fn main() -> ! {
let peripherals = stm32f103::Peripherals::take().unwrap();
let core_peripherals = cortex_m::Peripherals::take().unwrap();
let mut syst = core_peripherals.SYST;
let i2c1 = peripherals.I2C1;
let mut gpioa = peripherals.GPIOA;
// Enable Cortex-M SysTick
peripherals.STK.ctrl.modify(|_,w| w.tickint().set_bit()); // Enable Systick Interrupt
syst.set_reload(1_000 - 1); // Set period to 1ms
syst.clear_current(); // Clear the current value register
syst.enable_counter(); // Enable SysTick
// Enable clock for GPIOA by setting IOPAEN in RCC APB2ENR
peripherals.RCC.apb2enr.modify(|_, w| w.iopaen().set_bit());
gpioa.crl.modify(|_, w| w.mode3().output());
gpioa.crl.modify(|_, w| w.cnf3().push_pull());
gpioa.odr.modify(|_, w| w.odr3().high());
// Init i2c
// Configure i2c clock
peripherals.RCC.cfgr.modify(|_, w| w.ppre1().div2());
peripherals.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled());
// Enable i2c clock
peripherals.RCC.apb2enr.modify(|_,w| w.iopben().enabled());
// Set GPIO pin configurations
peripherals.GPIOB.crl.modify(|_,w| w.mode6().output50());
peripherals.GPIOB.crl.modify(|_,w| w.mode7().output50());
peripherals.GPIOB.crl.modify(|_,w| w.cnf6().alt_open_drain());
peripherals.GPIOB.crl.modify(|_,w| w.cnf7().alt_open_drain());
// Configure peripheral
i2c1.cr1.modify(|_,w| w.pe().enabled());
i2c1.cr1.modify(|_,w| w.smbus().i2c());
i2c1.cr1.modify(|_, w| w.ack().set_bit());
i2c1.oar1.modify(|_,w| w.add().bits(0x32 << 1));
i2c1.oar1.modify(|_,w| w.addmode().add7());
// Pass peripheral reference to global static
cortex_m::interrupt::free(|cs| {
i2c1.cr2.modify(|_,w| w.itevten().enabled());
i2c1.cr2.modify(|_,w| w.itbufen().enabled());
*I2C1.borrow(cs).borrow_mut() = Some(i2c1);
// I don't understand why this is unsafe or how I could make it safe.
unsafe { cortex_m::peripheral::NVIC::unmask(stm32f1::stm32f103::interrupt::I2C1_EV); }
});
let mut timer_ms = 500;
loop {
let current_value = get_sys_tick();
if current_value >= timer_ms
{
toggle_mcu_led(&mut gpioa);
timer_ms = current_value + 500;
}
}
}