cpld: basic switching capability
This commit is contained in:
parent
393138dc9a
commit
58e77ae671
|
@ -1,5 +1,5 @@
|
||||||
[target.thumbv7em-none-eabihf]
|
[target.thumbv7em-none-eabihf]
|
||||||
runner = "gdb -q -x gdb_config/debug.gdb"
|
runner = "gdb -q -x gdb_config/fpga_config.gdb"
|
||||||
rustflags = [
|
rustflags = [
|
||||||
"-C", "link-arg=-Tlink.x",
|
"-C", "link-arg=-Tlink.x",
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,14 +22,14 @@ class UrukulConnector(Module):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
eem.p[0].eq(spi.sclk),
|
eem.p[0].eq(spi.sclk),
|
||||||
eem.p[1].eq(spi.mosi),
|
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[3].eq(spi.cs[0]),
|
||||||
eem.p[4].eq(spi.cs[1]),
|
eem.p[4].eq(spi.cs[1]),
|
||||||
eem.p[5].eq(spi.cs[2]),
|
eem.p[5].eq(spi.cs[2]),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Debug purposes: Tie MISO to MOSI
|
# Debug purposes: Tie EEM MISO to EEM MOSI
|
||||||
self.comb += spi.miso.eq(spi.mosi)
|
# self.comb += eem.p[2].eq(eem.n[1])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main.rs
26
src/main.rs
|
@ -17,6 +17,7 @@ use cortex_m_semihosting::hprintln;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use nb::block;
|
use nb::block;
|
||||||
|
|
||||||
|
mod cpld;
|
||||||
|
|
||||||
#[entry]
|
#[entry]
|
||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
|
@ -37,6 +38,7 @@ fn main() -> ! {
|
||||||
|
|
||||||
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
|
let gpioa = dp.GPIOA.split(ccdr.peripheral.GPIOA);
|
||||||
let gpiob = dp.GPIOB.split(ccdr.peripheral.GPIOB);
|
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 gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD);
|
||||||
let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF);
|
let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF);
|
||||||
|
|
||||||
|
@ -71,20 +73,18 @@ fn main() -> ! {
|
||||||
|
|
||||||
let mut data :u8 = 0xAD;
|
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 {
|
loop {
|
||||||
hprintln!("Sent {}", data).unwrap();
|
// hprintln!("Sent {}", data).unwrap();
|
||||||
block!(spi.send(data)).unwrap();
|
// block!(spi.send(data)).unwrap();
|
||||||
data = block!(spi.read()).unwrap();
|
// data = block!(spi.read()).unwrap();
|
||||||
hprintln!("Read {}", data).unwrap();
|
// hprintln!("Read {}", data).unwrap();
|
||||||
|
nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue