Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions crates/sbd-gen-schema/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,27 @@ impl Target {
false
}
}

/// Returns true if there are any UARTs listed for this board.
#[must_use]
pub fn has_uarts(&self) -> bool {
if let Some(uarts) = &self.uarts {
!uarts.is_empty()
} else {
false
}
}

/// Returns true if there are any UARTs listed for this board that have the
/// [`Uart::host_facing`] property.
#[must_use]
pub fn has_host_facing_uart(&self) -> bool {
Comment thread
kaspar030 marked this conversation as resolved.
if let Some(uarts) = &self.uarts {
uarts.iter().any(|u| u.host_facing)
} else {
false
}
}
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
Expand Down Expand Up @@ -164,6 +185,49 @@ pub struct Uart {
pub tx_pin: String,
pub cts_pin: Option<String>,
pub rts_pin: Option<String>,
/// Peripheral device names, any of which is fundamentally available to serve this connection
/// as the peripheral that takes control of the TX and RX pins.
///
/// # Usage
///
/// All items in the list are peripheral names of the MCU for which the UART interface is
/// implemented. For example, on EFM32, a pin combination might be configurable either using
/// `LEUART0` or `USART1`, in which case those are given as values.
///
/// On some OSes and platforms (e. g., at the time of writing, in Ariel OS on nRF devices),
/// using that device name might entail using companion peripherals that are statically
/// selected (e. g. `UARTE0` being bundled with `TIMER4`, `PPI_CH14`, `PPI_CH15` and
/// `PPI_GROUP5`). This is an implementation detail of the OS; the name in this list is still
/// only the name of the one peripheral that performs the UART functionality.
///
/// # Future development
///
/// When future versions of `sbd` or the OSes consuming this file learn to process per-MCU
/// information, this field might go away. Instead, the possible peripherals might be deduced
/// purely from the MCU's peripheral mapping and the `*_pin` values.
///
/// When multiple UARTs are in use in an application and their possible peripherals overlap,
/// deciding which of the choices to take is a [hard problem]. When none of the peripherals are
/// available, the OS's mechanism of choosing a peripheral may need enhancing: For example,
/// Ariel OS (at the time of writing) only selects the first peripheral. Future versions might
/// pick the first one that has not previously been taken, and ideally, a static choice would
/// be made at build time solving the satisfiability problem.
///
/// When no peripheral is given, or all are used for other purposes, the OS may fall back to
/// bit-banging operation; currently, they do not.
///
/// [hard problem]: https://en.wikipedia.org/wiki/Boolean_satisfiability_problem
#[serde(default)]
pub possible_peripherals: Vec<String>,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, so this is clearly chip specific meta info. We'll have to move this there (at some point). Let's go with it for now.


/// Set if the board supports using it with a host system (e.g. the build host), and this UART
/// would typically face that system.
///
/// For example, this is set on boards with built-in programmers on UARTs that are exposed by
/// the programmer as USB serial devices. Typical applications querying this are tools that
/// report debug or measurement data.
#[serde(default)]
pub host_facing: bool,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
Expand Down
81 changes: 79 additions & 2 deletions crates/sbd-gen/src/ariel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
};

use sbd_gen_schema::{
Button, Led, PinLevel, Quirk, SbdFile, SetPinOp, Target, common::StringOrVecString,
Button, Led, PinLevel, Quirk, SbdFile, SetPinOp, Target, Uart, common::StringOrVecString,
};

#[derive(argh::FromArgs, Debug)]
Expand Down Expand Up @@ -167,6 +167,9 @@ pub fn render_ariel_board_crate(sbd: &SbdFile) -> FileMap {
if target.has_buttons() {
target_builder.provides.insert("has_buttons".into());
}
if target.has_host_facing_uart() {
target_builder.provides.insert("has_host_facing_uart".into());
}

if let Some(swi) = target.ariel.swi {
target_builder.provides.insert("has_swi".into());
Expand Down Expand Up @@ -291,14 +294,17 @@ fn render_pins(target: &Target) -> String {

pins.push_str("pub mod pins {\n");

if target.has_leds() || target.has_buttons() {
if target.has_leds() || target.has_buttons() || target.has_uarts() {
pins.push_str("use ariel_os_hal::hal::peripherals;\n\n");
if let Some(leds) = target.leds.as_ref() {
pins.push_str(&render_led_pins(leds));
}
if let Some(buttons) = target.buttons.as_ref() {
pins.push_str(&render_button_pins(buttons));
}
if let Some(uarts) = target.uarts.as_ref() {
pins.push_str(&render_uarts(uarts));
}
}

pins.push_str("}\n");
Expand Down Expand Up @@ -333,3 +339,74 @@ fn render_button_pins(buttons: &[Button]) -> String {

buttons_rs
}

fn render_uarts(uarts: &[Uart]) -> String {
Comment thread
kaspar030 marked this conversation as resolved.
let mut code = String::new();

code.push_str("ariel_os_hal::define_uarts![\n");

for (uart_number, uart) in uarts.iter().enumerate() {
let name = uart.name.as_ref().map_or_else(
|| format!("_unnamed_uart_{uart_number}").into(),
std::borrow::Cow::from,
);
let Some(device) = uart.possible_peripherals.first() else {
eprintln!(
Comment thread
kaspar030 marked this conversation as resolved.
"warning: No peripheral defined for UART, making it unusable in Ariel output."
);
eprintln!("Affected UART: {uart:?}");
continue;
};
if uart.possible_peripherals.len() > 1
{
eprintln!(
"warning: Multiple hardware devices are available, but Ariel OS does not process any but the first."
);
eprintln!("Affected UART: {uart:?}");
}
// Deferring to a macro so that any actual logic in there is handled in the OS where it
// belongs; this merely processes the data into a format usable there.
writeln!(
code,
"{{ name: {}, device: {}, tx: {}, rx: {}, host_facing: {} }},",
name, device, uart.tx_pin, uart.rx_pin, uart.host_facing
)
.unwrap();
}

code.push_str("];\n");

code
}

#[test]
fn test_render_uarts() {
let rendered = render_uarts(&[
Uart {
name: Some("CON0".to_string()),
rx_pin: "PA08".to_owned(),
tx_pin: "PC99".to_owned(),
cts_pin: None,
rts_pin: None,
possible_peripherals: vec!["UART2".to_owned(), "LEUART0".to_owned()],
host_facing: false,
},
Uart {
name: Some("VCOM".to_string()),
rx_pin: "P0_04".to_owned(),
tx_pin: "P1_23".to_owned(),
cts_pin: Some("P7.89".to_owned()),
rts_pin: Some("D5".to_owned()),
possible_peripherals: vec!["UART1".to_owned(), "LEUART0".to_owned()],
host_facing: true,
},
]);
assert_eq!(
rendered,
"ariel_os_hal::define_uarts![
{ name: CON0, device: UART2, tx: PC99, rx: PA08, host_facing: false },
{ name: VCOM, device: UART1, tx: P1_23, rx: P0_04, host_facing: true },
];
"
);
}
2 changes: 1 addition & 1 deletion crates/sbd-gen/src/riot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ fn generate_riot_target(sbd: &SbdFile, target: &Target) -> Result<RiotTarget> {
println!(
"warning: {}: no peripheral found for UART {}",
target.name,
uart.name.as_ref().map_or_else(|| "unnamed", |s| s)
uart.name.as_deref().unwrap_or("unnamed")
);
}
}
Expand Down
Loading