Skip to content

Commit

Permalink
Merge pull request #66 from hnez/gen3-explicit
Browse files Browse the repository at this point in the history
 Add LXA TAC hardware generation 3 support (explicit generation detection)
  • Loading branch information
hnez authored Apr 9, 2024
2 parents 002ba08 + 382ce79 commit e1e6ef5
Show file tree
Hide file tree
Showing 14 changed files with 364 additions and 163 deletions.
15 changes: 15 additions & 0 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,21 @@ paths:
schema:
type: string

/v1/tac/info/hardware_generation:
get:
summary: Get the LXA TAC hardware generation
tags: [System]
responses:
'200':
content:
application/json:
schema:
type: string
enum:
- Gen1
- Gen2
- Gen3

/v1/tac/setup_mode:
get:
summary: Check if the TAC has completed the set up or is still in setup mode
Expand Down
11 changes: 8 additions & 3 deletions src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use async_std::task::sleep;

use crate::broker::{BrokerBuilder, Topic};
use crate::measurement::{Measurement, Timestamp};
use crate::system::HardwareGeneration;
use crate::watched_tasks::WatchedTasksBuilder;

const HISTORY_LENGTH: usize = 200;
Expand Down Expand Up @@ -78,9 +79,13 @@ pub struct Adc {
}

impl Adc {
pub async fn new(bb: &mut BrokerBuilder, wtb: &mut WatchedTasksBuilder) -> Result<Self> {
let stm32_thread = IioThread::new_stm32(wtb).await?;
let powerboard_thread = IioThread::new_powerboard(wtb).await?;
pub async fn new(
bb: &mut BrokerBuilder,
wtb: &mut WatchedTasksBuilder,
hardware_generation: HardwareGeneration,
) -> Result<Self> {
let stm32_thread = IioThread::new_stm32(wtb, hardware_generation).await?;
let powerboard_thread = IioThread::new_powerboard(wtb, hardware_generation).await?;

let adc = Self {
usb_host_curr: AdcChannel {
Expand Down
4 changes: 2 additions & 2 deletions src/adc/iio/demo_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub struct IioThread {
}

impl IioThread {
pub async fn new_stm32<W>(_wtb: &W) -> Result<Arc<Self>> {
pub async fn new_stm32<W, G>(_wtb: &W, _hardware_generation: G) -> Result<Arc<Self>> {
let mut demo_magic = block_on(DEMO_MAGIC_STM32.lock());

// Only ever set up a single demo_mode "IioThread" per ADC
Expand Down Expand Up @@ -195,7 +195,7 @@ impl IioThread {
Ok(this)
}

pub async fn new_powerboard<W>(_wtb: &W) -> Result<Arc<Self>> {
pub async fn new_powerboard<W, G>(_wtb: &W, _hardware_generation: G) -> Result<Arc<Self>> {
let mut demo_magic = block_on(DEMO_MAGIC_POWERBOARD.lock());

// Only ever set up a single demo_mode "IioThread" per ADC
Expand Down
86 changes: 17 additions & 69 deletions src/adc/iio/hardware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,74 +32,12 @@ use log::{debug, error, warn};
use thread_priority::*;

use crate::measurement::{Measurement, Timestamp};
use crate::system::HardwareGeneration;
use crate::watched_tasks::WatchedTasksBuilder;

struct ChannelDesc {
kernel_name: &'static str,
calibration_path: &'static str,
name: &'static str,
}
mod channels;

// Hard coded list of channels using the internal STM32MP1 ADC.
// Consists of the IIO channel name, the location of the calibration data
// in the device tree and an internal name for the channel.
const CHANNELS_STM32: &[ChannelDesc] = &[
ChannelDesc {
kernel_name: "voltage13",
calibration_path: "baseboard-factory-data/usb-host-curr",
name: "usb-host-curr",
},
ChannelDesc {
kernel_name: "voltage15",
calibration_path: "baseboard-factory-data/usb-host1-curr",
name: "usb-host1-curr",
},
ChannelDesc {
kernel_name: "voltage0",
calibration_path: "baseboard-factory-data/usb-host2-curr",
name: "usb-host2-curr",
},
ChannelDesc {
kernel_name: "voltage1",
calibration_path: "baseboard-factory-data/usb-host3-curr",
name: "usb-host3-curr",
},
ChannelDesc {
kernel_name: "voltage2",
calibration_path: "baseboard-factory-data/out0-volt",
name: "out0-volt",
},
ChannelDesc {
kernel_name: "voltage10",
calibration_path: "baseboard-factory-data/out1-volt",
name: "out1-volt",
},
ChannelDesc {
kernel_name: "voltage5",
calibration_path: "baseboard-factory-data/iobus-curr",
name: "iobus-curr",
},
ChannelDesc {
kernel_name: "voltage9",
calibration_path: "baseboard-factory-data/iobus-volt",
name: "iobus-volt",
},
];

// The same as for the STM32MP1 channels but for the discrete ADC on the power
// board.
const CHANNELS_PWR: &[ChannelDesc] = &[
ChannelDesc {
kernel_name: "voltage",
calibration_path: "powerboard-factory-data/pwr-volt",
name: "pwr-volt",
},
ChannelDesc {
kernel_name: "current",
calibration_path: "powerboard-factory-data/pwr-curr",
name: "pwr-curr",
},
];
use channels::{ChannelDesc, Channels};

const TRIGGER_HR_PWR_DIR: &str = "/sys/kernel/config/iio/triggers/hrtimer/tacd-pwr";

Expand Down Expand Up @@ -431,33 +369,43 @@ impl IioThread {
Ok(thread)
}

pub async fn new_stm32(wtb: &mut WatchedTasksBuilder) -> Result<Arc<Self>> {
pub async fn new_stm32(
wtb: &mut WatchedTasksBuilder,
hardware_generation: HardwareGeneration,
) -> Result<Arc<Self>> {
let channels = hardware_generation.channels_stm32();

Self::new(
wtb,
"adc-stm32",
"48003000.adc:adc@0",
"tim4_trgo",
80,
CHANNELS_STM32,
channels,
4,
)
.await
}

pub async fn new_powerboard(wtb: &mut WatchedTasksBuilder) -> Result<Arc<Self>> {
pub async fn new_powerboard(
wtb: &mut WatchedTasksBuilder,
hardware_generation: HardwareGeneration,
) -> Result<Arc<Self>> {
let hr_trigger_path = Path::new(TRIGGER_HR_PWR_DIR);

if !hr_trigger_path.is_dir() {
create_dir(hr_trigger_path)?;
}

let channels = hardware_generation.channels_pwr();

Self::new(
wtb,
"adc-powerboard",
"lmp92064",
"tacd-pwr",
20,
CHANNELS_PWR,
channels,
1,
)
.await
Expand Down
139 changes: 139 additions & 0 deletions src/adc/iio/hardware/channels.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use crate::system::HardwareGeneration;

pub(super) struct ChannelDesc {
pub kernel_name: &'static str,
pub calibration_path: &'static str,
pub name: &'static str,
}

// Hard coded list of channels using the internal STM32MP1 ADC.
// Consists of the IIO channel name, the location of the calibration data
// in the device tree and an internal name for the channel.
const CHANNELS_STM32_GEN1_GEN2: &[ChannelDesc] = &[
ChannelDesc {
kernel_name: "voltage13",
calibration_path: "baseboard-factory-data/usb-host-curr",
name: "usb-host-curr",
},
ChannelDesc {
kernel_name: "voltage15",
calibration_path: "baseboard-factory-data/usb-host1-curr",
name: "usb-host1-curr",
},
ChannelDesc {
kernel_name: "voltage0",
calibration_path: "baseboard-factory-data/usb-host2-curr",
name: "usb-host2-curr",
},
ChannelDesc {
kernel_name: "voltage1",
calibration_path: "baseboard-factory-data/usb-host3-curr",
name: "usb-host3-curr",
},
ChannelDesc {
kernel_name: "voltage2",
calibration_path: "baseboard-factory-data/out0-volt",
name: "out0-volt",
},
ChannelDesc {
kernel_name: "voltage10",
calibration_path: "baseboard-factory-data/out1-volt",
name: "out1-volt",
},
ChannelDesc {
kernel_name: "voltage5",
calibration_path: "baseboard-factory-data/iobus-curr",
name: "iobus-curr",
},
ChannelDesc {
kernel_name: "voltage9",
calibration_path: "baseboard-factory-data/iobus-volt",
name: "iobus-volt",
},
];

const CHANNELS_STM32_GEN3: &[ChannelDesc] = &[
ChannelDesc {
kernel_name: "voltage13",
calibration_path: "baseboard-factory-data/usb-host-curr",
name: "usb-host-curr",
},
ChannelDesc {
kernel_name: "voltage15",
calibration_path: "baseboard-factory-data/usb-host1-curr",
name: "usb-host1-curr",
},
ChannelDesc {
kernel_name: "voltage18",
calibration_path: "baseboard-factory-data/usb-host2-curr",
name: "usb-host2-curr",
},
ChannelDesc {
kernel_name: "voltage14",
calibration_path: "baseboard-factory-data/usb-host3-curr",
name: "usb-host3-curr",
},
ChannelDesc {
kernel_name: "voltage2",
calibration_path: "baseboard-factory-data/out0-volt",
name: "out0-volt",
},
ChannelDesc {
kernel_name: "voltage10",
calibration_path: "baseboard-factory-data/out1-volt",
name: "out1-volt",
},
ChannelDesc {
kernel_name: "voltage5",
calibration_path: "baseboard-factory-data/iobus-curr",
name: "iobus-curr",
},
ChannelDesc {
kernel_name: "voltage9",
calibration_path: "baseboard-factory-data/iobus-volt",
name: "iobus-volt",
},
];

// The same as for the STM32MP1 channels but for the discrete ADC on the power
// board.
const CHANNELS_PWR: &[ChannelDesc] = &[
ChannelDesc {
kernel_name: "voltage",
calibration_path: "powerboard-factory-data/pwr-volt",
name: "pwr-volt",
},
ChannelDesc {
kernel_name: "current",
calibration_path: "powerboard-factory-data/pwr-curr",
name: "pwr-curr",
},
];

pub(super) trait Channels {
fn channels_stm32(&self) -> &'static [ChannelDesc];
fn channels_pwr(&self) -> &'static [ChannelDesc];
}

impl Channels for HardwareGeneration {
fn channels_stm32(&self) -> &'static [ChannelDesc] {
// LXA TAC hardware generation 3 has move some of the ADC channels around
// so that channel 0 and 1 are no longer used.
// Channel 0 and 1 are special in that they do not use the pinmuxing support
// of the STM32MP1 SoC.
// Instead they are always connected to the ADC.
// This causes issues when the ADC peripheral is put into stanby,
// because current will leak into these pins in that case.

match self {
HardwareGeneration::Gen1 | HardwareGeneration::Gen2 => CHANNELS_STM32_GEN1_GEN2,
HardwareGeneration::Gen3 => CHANNELS_STM32_GEN3,
}
}

fn channels_pwr(&self) -> &'static [ChannelDesc] {
// The pin assignment of the power board is currently independent from the
// hardware generation.
CHANNELS_PWR
}
}
4 changes: 2 additions & 2 deletions src/adc/iio/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub struct IioThread {
}

impl IioThread {
pub async fn new_stm32<W>(_wtb: &W) -> Result<Arc<Self>> {
pub async fn new_stm32<W, G>(_wtb: &W, _hardware_generation: G) -> Result<Arc<Self>> {
let mut channels = Vec::new();

for name in CHANNELS_STM32 {
Expand All @@ -117,7 +117,7 @@ impl IioThread {
Ok(Arc::new(Self { channels }))
}

pub async fn new_powerboard<W>(_wtb: &W) -> Result<Arc<Self>> {
pub async fn new_powerboard<W, G>(_wtb: &W, _hardware_generation: G) -> Result<Arc<Self>> {
let mut channels = Vec::new();

for name in CHANNELS_PWR {
Expand Down
16 changes: 2 additions & 14 deletions src/digital_io/gpio/demo_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ impl LineHandle {
// It is just a hack to let adc/iio/demo_mode.rs
// communicate with this function so that toggling an output
// has an effect on the measured values.
let iio_thread_stm32 = block_on(IioThread::new_stm32(&())).unwrap();
let iio_thread_pwr = block_on(IioThread::new_powerboard(&())).unwrap();
let iio_thread_stm32 = block_on(IioThread::new_stm32(&(), ())).unwrap();
let iio_thread_pwr = block_on(IioThread::new_powerboard(&(), ())).unwrap();

match self.name.as_str() {
"OUT_0" => iio_thread_stm32
Expand Down Expand Up @@ -80,14 +80,6 @@ impl BitOr for LineRequestFlags {
}
}

pub struct ChipDecoy;

impl ChipDecoy {
pub fn label(&self) -> &'static str {
"demo_mode"
}
}

pub struct FindDecoy {
name: String,
}
Expand All @@ -102,10 +94,6 @@ impl FindDecoy {

Ok(line_handle)
}

pub fn chip(&self) -> ChipDecoy {
ChipDecoy
}
}

pub fn find_line(name: &str) -> Option<FindDecoy> {
Expand Down
Loading

0 comments on commit e1e6ef5

Please sign in to comment.