mctp refactor
diff --git a/services/mctp/server/src/main.rs b/services/mctp/server/src/main.rs index c3195d1..b431aac 100644 --- a/services/mctp/server/src/main.rs +++ b/services/mctp/server/src/main.rs
@@ -47,7 +47,7 @@ use openprot_mctp_api::ResponseCode; use openprot_mctp_server::dispatch; -use i2c_api::{BusIndex, I2cTargetClient, TargetMessage}; +use i2c_api::{BusIndex, I2cAddress, I2cTargetClient, TargetMessage}; use i2c_client::IpcI2cClient; use openprot_mctp_transport_i2c::{I2cSender, MctpI2cReceiver}; @@ -70,12 +70,25 @@ // I2C notification client: receives slave-mode interrupts via Signals::USER. let mut i2c_notify = IpcI2cClient::new(handle::I2C); + + // Configure I2C bus 2 as slave at our address + let addr = I2cAddress::new(OWN_I2C_ADDR).map_err(|_| pw_status::Error::InvalidArgument)?; i2c_notify - .register_notification(BusIndex::BUS_0, 0) + .configure_target_address(BusIndex::BUS_2, addr) + .map_err(|_| pw_status::Error::Internal)?; + + // Enable slave receive mode + i2c_notify + .enable_receive(BusIndex::BUS_2) + .map_err(|_| pw_status::Error::Internal)?; + + // Register for notifications + i2c_notify + .register_notification(BusIndex::BUS_2, 0) .map_err(|_| pw_status::Error::Internal)?; // Separate handle for the sender — I2cSender takes ownership. - let sender = I2cSender::new(IpcI2cClient::new(handle::I2C), BusIndex::BUS_0, OWN_I2C_ADDR); + let sender = I2cSender::new(IpcI2cClient::new(handle::I2C), BusIndex::BUS_2, OWN_I2C_ADDR); let receiver = MctpI2cReceiver::new(OWN_I2C_ADDR); let mut server = openprot_mctp_server::Server::<_, 16>::new( mctp::Eid(OWN_EID), @@ -93,6 +106,8 @@ syscall::wait_group_add(handle::WG, handle::MCTP, Signals::READABLE, 0usize)?; syscall::wait_group_add(handle::WG, handle::I2C, Signals::USER, 1usize)?; + pw_log::info!("MCTP server ready, entering event loop"); + loop { let ev = syscall::object_wait(handle::WG, Signals::READABLE, Instant::MAX)?; @@ -100,7 +115,7 @@ // Inbound I2C data: drain pending messages, decode I2C framing, // feed raw MCTP packets into the router. let mut msgs = [TargetMessage::default(); 1]; - if let Ok(n) = i2c_notify.get_pending_messages(BusIndex::BUS_0, &mut msgs) { + if let Ok(n) = i2c_notify.get_pending_messages(BusIndex::BUS_2, &mut msgs) { for msg in &msgs[..n] { if let Ok((pkt, _src_addr)) = receiver.decode(msg) { let _ = server.inbound(pkt);
diff --git a/target/ast1060-evb/BUILD.bazel b/target/ast1060-evb/BUILD.bazel index f26545a..1aa57d3 100644 --- a/target/ast1060-evb/BUILD.bazel +++ b/target/ast1060-evb/BUILD.bazel
@@ -21,8 +21,8 @@ flags = flags_from_dict( KERNEL_DEVICE_COMMON_FLAGS | { "@pigweed//pw_kernel/config:kernel_config": ":config", - # TODO: Switch to :console_backend_uart when aspeed-ddk uart driver is available - "@pigweed//pw_kernel/subsys/console:console_backend": "@pigweed//pw_kernel/subsys/console:console_backend_semihosting", + # Using UART console backend - output on UART at 115200 baud + "@pigweed//pw_kernel/subsys/console:console_backend": ":console_backend_uart", }, ), )
diff --git a/target/ast1060-evb/mctp/BUILD.bazel b/target/ast1060-evb/mctp/BUILD.bazel index f813178..14a53d8 100644 --- a/target/ast1060-evb/mctp/BUILD.bazel +++ b/target/ast1060-evb/mctp/BUILD.bazel
@@ -43,9 +43,9 @@ system_image( name = "mctp", apps = [ - ":mctp_echo", "//services/i2c/server:i2c_server", "//services/mctp/server:mctp_server", + ":mctp_echo", ], kernel = ":target", platform = "//target/ast1060-evb",
diff --git a/target/ast1060-evb/mctp/mctp_echo.rs b/target/ast1060-evb/mctp/mctp_echo.rs index ff08843..3f01a8c 100644 --- a/target/ast1060-evb/mctp/mctp_echo.rs +++ b/target/ast1060-evb/mctp/mctp_echo.rs
@@ -26,18 +26,29 @@ use app_mctp_echo::handle; -/// MCTP message type for echo (vendor-defined type 1). -const ECHO_MSG_TYPE: u8 = 1; +/// MCTP message type for echo (vendor-defined PCIe type). +/// 0x7e = MCTP_TYPE_VENDOR_PCIE +const ECHO_MSG_TYPE: u8 = 0x7e; + +/// AMD PCIe Vendor ID +const AMD_PCIE_VENDOR_ID: u16 = 0x1022; fn mctp_echo_loop() -> Result<()> { pw_log::info!("MCTP echo starting"); let client = IpcMctpClient::new(handle::MCTP); - // Register a listener for type-1 messages + // Register a listener for vendor-defined PCIe messages (0x7e) let listener = client .listener(ECHO_MSG_TYPE) - .map_err(|_| pw_status::Error::Internal)?; + .map_err(|e| { + pw_log::error!( + "Failed to register listener for msg_type 0x{:02x}: error code {}", + ECHO_MSG_TYPE as u32, + e.code as u32, + ); + pw_status::Error::Internal + })?; let mut buf = [0u8; 1024]; @@ -47,18 +58,33 @@ .recv(listener, 0, &mut buf) .map_err(|_| pw_status::Error::Internal)?; - pw_log::info!( - "Echo: received {} bytes from EID {}", - meta.payload_size as u32, - meta.remote_eid as u32, - ); + // Verify vendor ID (first 2 bytes should be AMD PCIe vendor ID in little-endian) + if meta.payload_size >= 2 { + let vendor_id = u16::from_le_bytes([buf[0], buf[1]]); + pw_log::info!( + "Echo: received {} bytes from EID {}, vendor ID: 0x{:04x}", + meta.payload_size as u32, + meta.remote_eid as u32, + vendor_id as u32, + ); - // Echo the payload back + if vendor_id != AMD_PCIE_VENDOR_ID { + pw_log::warn!( + "Unexpected vendor ID 0x{:04x}, expected AMD 0x{:04x}", + vendor_id as u32, + AMD_PCIE_VENDOR_ID as u32, + ); + } + } else { + pw_log::warn!("Payload too short: {} bytes", meta.payload_size as u32); + } + + // Echo the payload back (including vendor ID) let payload = &buf[..meta.payload_size]; client .send( None, // no request handle (this is a response) - meta.msg_type, // same message type + meta.msg_type, // same message type (0x7e) Some(meta.remote_eid), // back to sender Some(meta.msg_tag), // same tag meta.msg_ic, // preserve integrity check
diff --git a/target/ast1060-evb/mctp/system.json5 b/target/ast1060-evb/mctp/system.json5 index 86c2abd..4a2a74a 100644 --- a/target/ast1060-evb/mctp/system.json5 +++ b/target/ast1060-evb/mctp/system.json5
@@ -5,15 +5,16 @@ // 768KB SRAM (640KB usable), executes from RAM // // Memory Layout (PMSAv7-friendly, power-of-2 aligned regions): +// FIXED: Kernel RAM now comes BEFORE application RAM to avoid boot crashes // 0x00000000 - 0x00000500: Vector table + kernel annotations (1280 bytes) -// 0x00000500 - 0x00020000: Kernel flash (~127KB, ends at 128KB boundary) +// 0x00000500 - 0x00020000: Kernel flash (~127KB) // 0x00020000 - 0x00040000: i2c_server flash (128KB) -// 0x00040000 - 0x00060000: mctp_server flash (128KB) -// 0x00060000 - 0x00080000: mctp_echo flash (128KB) -// 0x00080000 - 0x00088000: i2c_server RAM (32KB) -// 0x00088000 - 0x00090000: mctp_server RAM (32KB) -// 0x00090000 - 0x00098000: mctp_echo RAM (32KB) -// 0x00098000 - 0x000A0000: Kernel RAM (32KB) +// 0x00040000 - 0x00050000: mctp_server flash (64KB) +// 0x00050000 - 0x00060000: mctp_echo flash (64KB) +// 0x00060000 - 0x00080000: Kernel RAM (128KB) <- MOVED HERE +// 0x00080000 - 0x00090000: i2c_server RAM (64KB) +// 0x00090000 - 0x00098000: mctp_server RAM (32KB) +// 0x00098000 - 0x000A0000: mctp_echo RAM (32KB) // // Total: 0xA0000 = 640KB (fits within the 640KB usable window of the AST1060's 768KB SRAM). { @@ -25,8 +26,8 @@ kernel: { flash_start_address: 0x00000500, // After vector table + annotations flash_size_bytes: 129792, // 0x1FB00: ends at exactly 0x20000 (128KB boundary) - ram_start_address: 0x00098000, // After all app RAM (3 × 32KB = 0x18000 past 0x80000) - ram_size_bytes: 32768, // 32KB + ram_start_address: 0x00060000, // Kernel RAM comes FIRST, before all app RAM + ram_size_bytes: 131072, // 128KB }, apps: [ // ──── I2C Server ──── @@ -35,7 +36,7 @@ { name: "i2c_server", flash_size_bytes: 131072, // 128KB for server code - ram_size_bytes: 32768, // 32KB RAM (register maps + buffers) + ram_size_bytes: 65536, // 64KB RAM (register maps + buffers) process: { name: "i2c server process", objects: [ @@ -75,7 +76,7 @@ // uses I2C transport for on-the-wire communication. { name: "mctp_server", - flash_size_bytes: 131072, // 128KB for MCTP server code + flash_size_bytes: 65536, // 64KB for MCTP server code ram_size_bytes: 32768, // 32KB RAM (Router state, buffers) process: { name: "mctp server process", @@ -109,7 +110,7 @@ // Listens for MCTP type-1 messages and echoes the payload back. { name: "mctp_echo", - flash_size_bytes: 131072, // 128KB for echo app + flash_size_bytes: 65536, // 64KB for echo app ram_size_bytes: 32768, // 32KB RAM process: { name: "mctp echo process",
diff --git a/target/ast1060-evb/mctp/target.rs b/target/ast1060-evb/mctp/target.rs index 3cb0a2e..931afa5 100644 --- a/target/ast1060-evb/mctp/target.rs +++ b/target/ast1060-evb/mctp/target.rs
@@ -8,7 +8,6 @@ #![no_std] #![no_main] -use cortex_m_semihosting::debug::{EXIT_FAILURE, EXIT_SUCCESS, exit}; use target_common::{TargetInterface, declare_target}; use {console_backend as _, entry as _}; @@ -25,11 +24,6 @@ fn shutdown(code: u32) -> ! { pw_log::info!("Shutting down with code {}", code as u32); - let status = match code { - 0 => EXIT_SUCCESS, - _ => EXIT_FAILURE, - }; - exit(status); #[expect(clippy::empty_loop)] loop {} }