cpld: basic switching capability

This commit is contained in:
occheung 2020-08-09 18:46:06 +08:00
parent 393138dc9a
commit 58e77ae671
6 changed files with 79 additions and 205 deletions

View File

@ -1,5 +1,5 @@
[target.thumbv7em-none-eabihf]
runner = "gdb -q -x gdb_config/debug.gdb"
runner = "gdb -q -x gdb_config/fpga_config.gdb"
rustflags = [
"-C", "link-arg=-Tlink.x",
]

View File

@ -22,14 +22,14 @@ class UrukulConnector(Module):
self.comb += [
eem.p[0].eq(spi.sclk),
eem.p[1].eq(spi.mosi),
eem.p[2].eq(spi.miso),
spi.miso.eq(eem.p[2]),
eem.p[3].eq(spi.cs[0]),
eem.p[4].eq(spi.cs[1]),
eem.p[5].eq(spi.cs[2]),
]
# Debug purposes: Tie MISO to MOSI
self.comb += spi.miso.eq(spi.mosi)
# Debug purposes: Tie EEM MISO to EEM MOSI
# self.comb += eem.p[2].eq(eem.n[1])
if __name__ == "__main__":

View File

@ -1,112 +0,0 @@
#![no_main]
#![no_std]
extern crate panic_itm;
use stm32h7xx_hal::hal::digital::v2::OutputPin;
use stm32h7xx_hal::{pac, prelude::*};
use cortex_m_rt::entry;
use cortex_m_log::println;
use cortex_m_log::{
destination::Itm, printer::itm::InterruptSync as InterruptSyncItm,
};
/*
* I2C Address of the I2C switch (TCA9548ARGER)
*/
const TCA9548ARGER_ADDR :u8 = 0x72;
/*
* Control register bit masks
*/
const CHANNEL_0 :u8 = 0x01;
const CHANNEL_1 :u8 = 0x02;
const CHANNEL_2 :u8 = 0x04;
const CHANNEL_3 :u8 = 0x08;
const CHANNEL_4 :u8 = 0x10;
const CHANNEL_5 :u8 = 0x20;
const CHANNEL_6 :u8 = 0x40;
const CHANNEL_7 :u8 = 0x80;
/*
* I2C Address of slaves at different channels
*/
const TEMP_1_ADDR :u8 = 0x48;
const TEMP_PRODUCT_ID_REG :u8 = 0x07;
#[entry]
fn main() -> ! {
let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut log = InterruptSyncItm::new(Itm::new(cp.ITM));
// Constrain and Freeze power
// println!(log, "Setup PWR... ");
let pwr = dp.PWR.constrain();
let vos = pwr.freeze();
// Constrain and Freeze clock
// println!(log, "Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc.sys_ck(100.mhz()).freeze(vos, &dp.SYSCFG);
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE);
// Configure the SCL and the SDA pin for our I2C bus
let scl = gpiob.pb8.into_alternate_af4().set_open_drain();
let sda = gpiob.pb9.into_alternate_af4().set_open_drain();
let mut i2c =
dp.I2C1
.i2c((scl, sda), 100.khz(), ccdr.peripheral.I2C1, &ccdr.clocks);
// Setup delay
let mut delay = cp.SYST.delay(ccdr.clocks);
// Configure led
let mut green = gpiob.pb0.into_push_pull_output();
let mut yellow = gpioe.pe1.into_push_pull_output();
let mut red = gpiob.pb14.into_push_pull_output();
// I2C switch (TCA9548ARGER_ADDR): Only enable channel 5
let mut tx1 :[u8, 1] = [CHANNEL_5];
let mut rx1 :[u8; 1] = [0];
loop {
i2c.write(TCA9548ARGER_ADDR, &tx1);
delay.delay_ms(10_u16);
}
// Read back the control value
i2c.read(TCA9548ARGER_ADDR, &mut rx1).unwrap();
// Match the control register content with the CHANNEL_5 mask
match rx1[0] {
CHANNEL_5 => yellow.set_high(),
_ => yellow.set_low(),
}.unwrap();
loop {
red.set_high().unwrap();
}
// delay.delay_ms(100_u16);
// Temperature sensor (TEMP_1_ADDR): write TEMP_PRODUCT_ID_REG, and read its content (1 byte)
let mut tx2 :[u8, 1] = TEMP_PRODUCT_ID_REG;
let mut rx2 :[u8; 1] = [0];
// i2c.write_read(TEMP_1_ADDR, &tx1.clone(), &mut rx).unwrap();
i2c.write_read(TCA9548ARGER_ADDR, &tx2.clone(), &mut rx2).unwrap();
// The ID should be 0xA1.
match rx2[0] {
0xA1 => green.set_high(),
_ => green.set_low(),
}.unwrap();
loop {
red.set_high().unwrap();
}
}

View File

@ -1,76 +0,0 @@
#![deny(warnings)]
#![deny(unsafe_code)]
#![no_main]
#![no_std]
extern crate panic_itm;
use cortex_m;
use cortex_m_rt::entry;
use stm32h7xx_hal::hal::digital::v2::OutputPin;
use stm32h7xx_hal::{pac, prelude::*};
use cortex_m_log::println;
use cortex_m_log::{
destination::Itm, printer::itm::InterruptSync as InterruptSyncItm,
};
#[entry]
fn main() -> ! {
let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut log = InterruptSyncItm::new(Itm::new(cp.ITM));
// Constrain and Freeze power
println!(log, "Setup PWR... ");
let pwr = dp.PWR.constrain();
let vos = pwr.freeze();
// Constrain and Freeze clock
println!(log, "Setup RCC... ");
let rcc = dp.RCC.constrain();
let ccdr = rcc.sys_ck(100.mhz()).freeze(vos, &dp.SYSCFG);
println!(log, "");
println!(log, "stm32h7xx-hal example - Blinky");
println!(log, "");
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE);
// Configure PE1 as output.
let mut green = gpiob.pb0.into_push_pull_output();
let mut yellow = gpioe.pe1.into_push_pull_output();
let mut red = gpiob.pb14.into_push_pull_output();
// Get the delay provider.
let mut delay = cp.SYST.delay(ccdr.clocks);
let mut num = 0;
loop {
delay.delay_ms(500_u16);
if num & 4 != 0 {
green.set_high().unwrap();
}
else {
green.set_low().unwrap();
}
if num & 2 != 0 {
yellow.set_high().unwrap();
}
else {
yellow.set_low().unwrap();
}
if num & 1 != 0 {
red.set_high().unwrap();
}
else {
red.set_low().unwrap();
}
num = (num + 1) % 8;
}
}

62
src/cpld.rs Normal file
View File

@ -0,0 +1,62 @@
#![no_std]
use stm32h7xx_hal::{
hal::{
digital::v2::{
InputPin,
OutputPin,
},
blocking::spi::Transfer,
},
pac,
prelude::*,
spi,
};
use cortex_m;
use cortex_m::asm::nop;
use cortex_m_semihosting::hprintln;
use nb::block;
/*
* Basic structure for CPLD signal multiplexing
*/
pub struct CPLD<SPI, CS0, CS1, CS2> {
spi: SPI,
chip_select: (CS0, CS1, CS2),
}
impl<SPI, CS0, CS1, CS2> CPLD<SPI, CS0, CS1, CS2> where
SPI: Transfer<u8>,
CS0: OutputPin,
CS1: OutputPin,
CS2: OutputPin,
{
// Constructor for CPLD
pub fn new(spi: SPI, chip_select: (CS0, CS1, CS2)) -> Self {
// Init CS to be 0
let mut obj = Self{spi, chip_select};
obj.select_chip(0);
return obj
}
// Select chip
pub fn select_chip(&mut self, channel: u8) {
match channel & (1 << 0) {
0 => self.chip_select.0.set_low(),
_ => self.chip_select.0.set_high(),
};
match channel & (1 << 1) {
0 => self.chip_select.1.set_low(),
_ => self.chip_select.1.set_high(),
};
match channel & (1 << 2) {
0 => self.chip_select.2.set_low(),
_ => self.chip_select.2.set_high(),
};
}
}

View File

@ -17,6 +17,7 @@ use cortex_m_semihosting::hprintln;
use core::ptr;
use nb::block;
mod cpld;
#[entry]
fn main() -> ! {
@ -37,6 +38,7 @@ fn main() -> ! {
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD);
let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF);
@ -71,20 +73,18 @@ fn main() -> ! {
let mut data :u8 = 0xAD;
let mut switch = cpld::CPLD::new(spi, (
gpiob.pb12.into_push_pull_output(),
gpioa.pa15.into_push_pull_output(),
gpioc.pc7.into_push_pull_output(),
));
loop {
hprintln!("Sent {}", data).unwrap();
block!(spi.send(data)).unwrap();
data = block!(spi.read()).unwrap();
hprintln!("Read {}", data).unwrap();
// hprintln!("Sent {}", data).unwrap();
// block!(spi.send(data)).unwrap();
// data = block!(spi.read()).unwrap();
// hprintln!("Read {}", data).unwrap();
nop();
}
}