//============================================================================ // 作者:liuwenbo // 日期:2026-03-24-2026-03-25 //============================================================================ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using Antmicro.Renode.Core; using Antmicro.Renode.Core.Structure.Registers; using Antmicro.Renode.Logging; using Antmicro.Renode.Peripherals.Bus; using Antmicro.Renode.Time; using Antmicro.Renode.Peripherals; using Antmicro.Renode.Peripherals.Timers; using Antmicro.Renode.Peripherals.IRQControllers; namespace Antmicro.Renode.Peripherals.Timers { public class LC3233_TaskTimer : BasicDoubleWordPeripheral, IKnownSize { public LC3233_TaskTimer(IMachine machine) : base(machine) { this.machine = machine; DefineRegisters(); Reset(); this.Log(LogLevel.Info, "LC3233 定时器已初始化 @ 0x80000000"); this.Log(LogLevel.Info, " 周期: 250ms (4Hz), 用于VxWorks任务调度"); } private void ScheduleNextTick() { if(timerScheduled || (timerCtrl & TIMER_CTRL_T0_EN) == 0) { return; } timerScheduled = true; var generation = timerGeneration; machine.ScheduleAction(TimeInterval.FromMilliseconds(250), _ => { timerScheduled = false; if(generation != timerGeneration || (timerCtrl & TIMER_CTRL_T0_EN) == 0) { return; } OnTimerExpired(); }); } private void OnTimerExpired() { timerExpiredCount++; //isPending = true; this.Log(LogLevel.Info, "========== 定时器溢出 #{0} ==========", timerExpiredCount); this.Log(LogLevel.Info, "准备触发中断线4..."); IRQ.Set(true); this.Log(LogLevel.Info, "已调用 IRQ.Set(true),信号应发送到 lc3233IntCtrl@4"); machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ => { IRQ.Set(false); this.Log(LogLevel.Debug, "中断脉冲结束"); }); if ((timerCtrl & TIMER_CTRL_T0_LOEN) != 0) { timer0Cntr = timer0Reld; ScheduleNextTick(); } } private void DefineRegisters() { Registers.TimerCtrl.Define(this) .WithValueField(0, 32, name: "timer_ctrl", writeCallback: (_, val) => { timerCtrl = (uint)val; // Bit 0: Timer0 Enable bool t0Enable = (val & TIMER_CTRL_T0_EN) != 0; if(!t0Enable) { timerGeneration++; timerScheduled = false; } else { timerGeneration++; timerScheduled = false; ScheduleNextTick(); } this.Log(LogLevel.Info, "TIMER_CTRL 写入: 0x{0:X8}", val); this.Log(LogLevel.Info, " Timer0 Enable: {0}", t0Enable); this.Log(LogLevel.Info, " Auto Reload: {0}", (val & TIMER_CTRL_T0_LOEN) != 0); }, valueProviderCallback: _ => timerCtrl); Registers.Timer0Cntr.Define(this) .WithValueField(0, 32, name: "timer0_cntr", writeCallback: (_, val) => { timer0Cntr = (uint)val; this.Log(LogLevel.Debug, "TIMER0_CNTR 写入: 0x{0:X8}", val); }, valueProviderCallback: _ => timer0Cntr); Registers.Timer0Reld.Define(this) .WithValueField(0, 32, name: "timer0_reld", writeCallback: (_, val) => { timer0Reld = (uint)val; this.Log(LogLevel.Debug, "TIMER0_RELD 写入: 0x{0:X8}", val); }, valueProviderCallback: _ => timer0Reld); Registers.Timer0DivFreq.Define(this) .WithValueField(0, 32, name: "timer0_divfreq", writeCallback: (_, val) => { timer0DivFreq = (uint)val; this.Log(LogLevel.Debug, "TIMER0_DIVFREQ 写入: 0x{0:X8}", val); }, valueProviderCallback: _ => timer0DivFreq); Registers.Timer0DfReld.Define(this) .WithValueField(0, 32, name: "timer0_df_reld", writeCallback: (_, val) => { timer0DfReld = (uint)val; this.Log(LogLevel.Debug, "TIMER0_DF_RELD 写入: 0x{0:X8}", val); }, valueProviderCallback: _ => timer0DfReld); } public override void Reset() { base.Reset(); timerCtrl = TIMER_CTRL_T0_EN | TIMER_CTRL_T0_LOEN; timer0Cntr = 0; timer0Reld = 0; timer0DivFreq = 0; timer0DfReld = 0; isPending = false; timerExpiredCount = 0; timerGeneration++; timerScheduled = false; ScheduleNextTick(); } public long Size => 0x100; public GPIO IRQ { get; } = new GPIO(); private enum Registers { TimerCtrl = 0x00, Timer0Cntr = 0x04, Timer0Reld = 0x08, WdgCntr = 0x0C, Timer1Cntr = 0x10, Timer1Reld = 0x14, Timer0DivFreq = 0x18, Timer0DfReld = 0x1C, } private const uint TIMER_CTRL_T0_EN = 0x00000001; private const uint TIMER_CTRL_T0_LOEN = 0x00000002; private const uint TIMER_CTRL_T0_RSTA = 0x00000004; private readonly IMachine machine; private uint timerCtrl; private uint timer0Cntr; private uint timer0Reld; private uint timer0DivFreq; private uint timer0DfReld; private bool isPending; private bool timerScheduled; private ulong timerGeneration; private ulong timerExpiredCount; } } namespace Antmicro.Renode.Peripherals.IRQControllers { public class LC3233_InterruptController : BasicDoubleWordPeripheral, IKnownSize, INumberedGPIOOutput, IGPIOReceiver { public LC3233_InterruptController(IMachine machine) : base(machine) { this.machine = machine; connections = new Dictionary(); for (int i = 0; i <= 15; i++) { connections[i] = new GPIO(); } Connections = new ReadOnlyDictionary(connections); DefineRegisters(); Reset(); this.Log(LogLevel.Info, "LC3233 中断控制器已初始化 @ 0x80020000"); this.Log(LogLevel.Info, " 管理15个中断源 (1-15)"); } /// /// 定义寄存器映射 /// private void DefineRegisters() { // Registers.IntMaskPriority.Define(this) // .WithValueField(0, 32, name: "int_mask_priority", // writeCallback: (_, val) => // { // intMaskPriority = (uint)val; // this.Log(LogLevel.Info, "INT_MASK_PRIORITY 写入: 0x{0:X8}", val); // this.Log(LogLevel.Info, " 临时兼容: IRQ4 强制视为使能"); // for (int i = 1; i <= 15; i++) // { // if ((val & (uint)(1 << i)) != 0) // { // this.Log(LogLevel.Debug, " 中断 {0} 已使能", i); // } // } // UpdateInterrupts(); // }, // valueProviderCallback: _ => intMaskPriority); // Registers.IntFTP.Define(this) // .WithValueField(0, 32, name: "int_f_t_p", // writeCallback: (_, val) => // { // intFTP |= (uint)val; // this.Log(LogLevel.Debug, "INT_F_T_P 写入: 0x{0:X8}, 当前值: 0x{1:X8}", val, intFTP); // UpdateInterrupts(); // }, // valueProviderCallback: _ => intFTP); // Registers.IntForce.Define(this) // .WithValueField(0, 32, FieldMode.Write, name: "int_force", // writeCallback: (_, val) => // { // this.Log(LogLevel.Info, "INT_FORCE 写入: 0x{0:X8}", val); // intFTP |= (uint)val; // UpdateInterrupts(); // }); // Registers.IntClr.Define(this) // .WithValueField(0, 32, FieldMode.Write, name: "int_clr", // writeCallback: (_, val) => // { // this.Log(LogLevel.Debug, "INT_CLR 写入: 0x{0:X8}", val); // intFTP &= ~(uint)val; // UpdateInterrupts(); // }); } public void OnGPIO(int irq, bool value) { if (irq < 0 || irq > 15) { this.Log(LogLevel.Error, "无效的中断号: {0}", irq); return; } if(value) { this.Log(LogLevel.Info, "*** 中断控制器接收到信号 IRQ{0}: {1} ***", irq, value ? "拉高" : "拉低"); // 自动使能中断 intMaskPriority |= (uint)(1 << irq); this.Log(LogLevel.Info, "自动使能中断 {0}: INT_MASK_PRIORITY = 0x{1:X8}", irq, intMaskPriority); //设置挂起寄存器 intFTP |= (uint)(1 << irq); this.Log(LogLevel.Info, "设置挂起位: INT_F_T_P = 0x{0:X8}", intFTP); UpdateInterrupts(); } else { } //this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU..."); //UpdateInterrupts(); // if (irq < 0 || irq > 15) // { // this.Log(LogLevel.Error, "无效的中断号: {0}", irq); // return; // } // this.Log(LogLevel.Info, "*** 中断控制器接收到信号 IRQ{0}: {1} ***", irq, value ? "拉高" : "拉低"); // if (value) // { // intFTP |= (uint)(1 << irq); // this.Log(LogLevel.Info, "设置挂起位: INT_F_T_P = 0x{0:X8}", intFTP); // } // else // { // } // this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU..."); // UpdateInterrupts(); } private void UpdateInterrupts() { this.Log(LogLevel.Info, "调用 UpdateInterrupts() 检查是否转发到CPU..."); this.Log(LogLevel.Debug, "UpdateInterrupts: MASK=0x{0:X8}, PENDING=0x{1:X8}", intMaskPriority, intFTP); for (int i = 15; i > 0; i--) { //bool masked = ((intMaskPriority & (uint)(1 << i)) != 0) || (forceEnableIRQ4 && i == 4); bool masked = ((intMaskPriority & (uint)(1 << i)) != 0); bool pending = (intFTP & (uint)(1 << i)) != 0; if (i == 5) { this.Log(LogLevel.Info, "IRQ{0} 状态检查: masked={1}, pending={2}", i, masked, pending); } if (i == 4) { this.Log(LogLevel.Info, "IRQ{0} 状态检查: masked={1}, pending={2}", i, masked, pending); } if (masked && pending) { if (Connections.TryGetValue(i, out var gpio)) { gpio.Set(true); this.Log(LogLevel.Info, "===> 转发中断 {0} 到MIC@{0} (CPU中断线{0})", i); var localI = i; machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ => { if (Connections.TryGetValue(localI, out var g)) { g.Set(false); machine.ScheduleAction(TimeInterval.FromMicroseconds(5000), _ => { intFTP &= ~(uint)(1 << localI); this.Log(LogLevel.Info, "*** 5ms 安全期已过,自动清除中断 {0} 的挂起位 ***", localI); UpdateInterrupts(); }); } }); } else { this.Log(LogLevel.Warning, "中断 {0} 无法转发: 连接未找到!", i); } } } } public override void Reset() { base.Reset(); intMaskPriority = 0; intFTP = 0; intClr = 0; } public long Size => 0x10; public IReadOnlyDictionary Connections { get; } private readonly IMachine machine; private readonly Dictionary connections; private readonly Dictionary gpioToIrqMap; // 字段声明 private readonly bool forceEnableIRQ4 = true; private uint intMaskPriority; private uint intFTP; private uint intClr; // 寄存器定义 private enum Registers { IntMaskPriority = 0x00, IntFTP = 0x04, IntForce = 0x08, IntClr = 0x0C, } } }