i2c check 1
diff --git a/apps/i2c-slave-echo/src/main.rs b/apps/i2c-slave-echo/src/main.rs index ef2d6b9..7fdc094 100644 --- a/apps/i2c-slave-echo/src/main.rs +++ b/apps/i2c-slave-echo/src/main.rs
@@ -67,7 +67,9 @@ let mut reg_ptr: u8 = 0; // Pre-load the initial read response. - let _ = client.slave_set_response(SLAVE_BUS, &[reg_map[reg_ptr as usize]]); + if let Err(_) = client.slave_set_response(SLAVE_BUS, &[reg_map[reg_ptr as usize]]) { + pw_log::error!("Initial slave_set_response failed"); + } let mut rx_buf = [0u8; 32]; @@ -87,7 +89,9 @@ reg_ptr as u32, val as u32, ); - let _ = client.slave_set_response(SLAVE_BUS, &[val]); + if let Err(_) = client.slave_set_response(SLAVE_BUS, &[val]) { + pw_log::error!("slave_set_response failed"); + } } _ => { // Write: byte 0 = register address, byte 1 = value. @@ -100,7 +104,9 @@ val as u32, ); //Update read response in case master reads back immediately. - let _ = client.slave_set_response(SLAVE_BUS, &[val]); + if let Err(_) = client.slave_set_response(SLAVE_BUS, &[val]) { + pw_log::error!("slave_set_response failed"); + } } } }
diff --git a/services/i2c/backend-aspeed/src/lib.rs b/services/i2c/backend-aspeed/src/lib.rs index 86a4343..46885f6 100644 --- a/services/i2c/backend-aspeed/src/lib.rs +++ b/services/i2c/backend-aspeed/src/lib.rs
@@ -342,9 +342,37 @@ if !self.is_bus_initialized(bus) { return Err(ResponseCode::ServerError); } + if (self.slave_configured & (1 << bus)) == 0 { + return Err(ResponseCode::NotInitialized); + } + let len = data.len().min(SLAVE_TX_BUF_SIZE); self.slave_tx_bufs[bus as usize][..len].copy_from_slice(&data[..len]); self.slave_tx_lens[bus as usize] = len; + + // Pre-load the hardware TX buffer and length register so it's ready for the next + // master read. We do NOT set AST_I2CS_TX_BUFF_EN here because that would put the + // slave into TX mode and prevent it from receiving writes. The TX_BUFF_EN flag + // will be set later when we detect a ReadRequest event. + let (regs, buffs) = self.controller_regs(bus)?; + + // Manually pre-load TX buffer without triggering transmission. + // Only copy 1 byte to match the DDK's current limitation. + let to_write = 1.min(len); + if to_write > 0 { + // Write directly to hardware buffer register (first DWORD) + // The buffer is organized as 8 DWORDs, each holding up to 4 bytes + unsafe { + buffs.buff(0).write(|w| w.bits(data[0] as u32)); + + // Set transfer length register (tx_data_byte_count = len - 1) + regs.i2cc0c() + .modify(|_, w| w.tx_data_byte_count().bits((to_write - 1) as u8)); + } + // Note: We do NOT set AST_I2CS_TX_BUFF_EN here - that happens in slave_wait_event + // when ReadRequest is detected, to avoid blocking RX operations. + } + Ok(()) } @@ -390,6 +418,8 @@ return Ok((SlaveEventKind::DataReceived, n)); } Some(SlaveEvent::ReadRequest) => { + // Hardware should already have the TX buffer armed from slave_set_response(), + // but call slave_write() as a fallback in case the timing worked out. let _ = i2c.slave_write(&tx_local[..tx_len]); return Ok((SlaveEventKind::ReadRequest, 0)); }
diff --git a/target/ast1060-evb/harness/uart_test_exec.py b/target/ast1060-evb/harness/uart_test_exec.py index 10bab93..e7ada83 100644 --- a/target/ast1060-evb/harness/uart_test_exec.py +++ b/target/ast1060-evb/harness/uart_test_exec.py
@@ -13,6 +13,7 @@ import base64 import binascii import os +import signal import subprocess import sys import time @@ -302,17 +303,21 @@ start_time = time.time() buffer = b"" - while time.time() - start_time < timeout: - data = self.read_serial_data(0.1) - if data: - buffer += data - if not self.args.quiet: - self.print_uart_data(data) + try: + while time.time() - start_time < timeout: + data = self.read_serial_data(0.1) + if data: + buffer += data + if not self.args.quiet: + self.print_uart_data(data) - # Look for 'U' character - if b"U" in buffer: - self.log("\nUART bootloader ready detected!") - return True + # Look for 'U' character + if b"U" in buffer: + self.log("\nUART bootloader ready detected!") + return True + except KeyboardInterrupt: + self.log("\nInterrupted while waiting for UART ready") + raise self.log("\nTimeout waiting for UART ready signal") return False @@ -343,20 +348,26 @@ chunk_size = 1024 bytes_sent = 0 - for i in range(0, len(firmware_data), chunk_size): - chunk = firmware_data[i : i + chunk_size] + try: + for i in range(0, len(firmware_data), chunk_size): + chunk = firmware_data[i : i + chunk_size] - if not self.write_serial_data(chunk): - self.log("Failed to write firmware chunk") - return False + if not self.write_serial_data(chunk): + self.log("Failed to write firmware chunk") + return False - bytes_sent += len(chunk) - time.sleep(0.01) + bytes_sent += len(chunk) + time.sleep(0.01) - # Progress indicator - if not self.args.quiet and bytes_sent % (chunk_size * 10) == 0: - progress = (bytes_sent * 100) // len(firmware_data) - print(f"\rProgress: {progress}%", end="", flush=True) + # Progress indicator + if not self.args.quiet and bytes_sent % (chunk_size * 10) == 0: + progress = (bytes_sent * 100) // len(firmware_data) + print(f"\rProgress: {progress}%", end="", flush=True) + except KeyboardInterrupt: + if not self.args.quiet: + print() + self.log("Firmware upload interrupted") + raise if not self.args.quiet: print() @@ -364,6 +375,8 @@ self.log("Firmware upload completed") return True + except KeyboardInterrupt: + raise except Exception as e: self.log(f"Failed to upload firmware: {e}") return False @@ -385,37 +398,41 @@ line_buffer = "" test_results = {"passed": 0, "failed": 0, "skipped": 0} - while time.time() - start_time < actual_timeout: - data = self.read_serial_data(0.5) - if data: - if not self.args.quiet: - self.print_uart_data(data) + try: + while time.time() - start_time < actual_timeout: + data = self.read_serial_data(0.5) + if data: + if not self.args.quiet: + self.print_uart_data(data) - line_buffer += data.decode("utf-8", errors="replace") - lines = line_buffer.split("\n") - # Keep the last (possibly incomplete) line in the buffer - line_buffer = lines[-1] + line_buffer += data.decode("utf-8", errors="replace") + lines = line_buffer.split("\n") + # Keep the last (possibly incomplete) line in the buffer + line_buffer = lines[-1] - for line in lines[:-1]: - if "PASS" in line: - test_results["passed"] += 1 - elif "FAIL" in line: - test_results["failed"] += 1 - elif "SKIP" in line: - test_results["skipped"] += 1 + for line in lines[:-1]: + if "PASS" in line: + test_results["passed"] += 1 + elif "FAIL" in line: + test_results["failed"] += 1 + elif "SKIP" in line: + test_results["skipped"] += 1 - # Check for completion - for pattern in self.SUCCESS_PATTERNS: - if pattern in line: - self.log(f"\nTest execution completed!") - self.log(f"Results: {test_results}") - return test_results["failed"] == 0 + # Check for completion + for pattern in self.SUCCESS_PATTERNS: + if pattern in line: + self.log(f"\nTest execution completed!") + self.log(f"Results: {test_results}") + return test_results["failed"] == 0 - # Check for failure - for pattern in self.FAILURE_PATTERNS: - if pattern.lower() in line.lower(): - self.log(f"\nFailure detected: {pattern}") - return False + # Check for failure + for pattern in self.FAILURE_PATTERNS: + if pattern.lower() in line.lower(): + self.log(f"\nFailure detected: {pattern}") + return False + except KeyboardInterrupt: + self.log(f"\nMonitoring interrupted. Results so far: {test_results}") + raise self.log(f"\nTest monitoring timeout. Results so far: {test_results}") return test_results["failed"] == 0 @@ -424,6 +441,12 @@ """Clean up resources.""" self.close_serial() + def _install_signal_handler(self): + """Install SIGINT handler so Ctrl+C always triggers clean shutdown.""" + def _handler(signum, frame): + raise KeyboardInterrupt + signal.signal(signal.SIGINT, _handler) + def run_parse_only(self) -> int: """Read and print UART output indefinitely. Returns 0 on KeyboardInterrupt.""" try: @@ -640,6 +663,7 @@ parser.error(f"UART device not found: {args.uart_device}") executor = UartTestExecutor(args) + executor._install_signal_handler() try: # Parse-only mode: read UART indefinitely @@ -698,7 +722,8 @@ return 1 except KeyboardInterrupt: - executor.log("\nInterrupted by user") + executor.log("\nInterrupted.") + executor.cleanup() return 130 except Exception as e: executor.log(f"Error: {e}")