//============================================================================ // 作者: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); } 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.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)) { this.Log(LogLevel.Info, "===> 转发中断 {0} 到MIC@{0} (CPU中断线{0})", i); gpio.Set(true); var localI = i; machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ => { if (Connections.TryGetValue(localI, out var g)) { g.Set(false); } }); } else { this.Log(LogLevel.Warning, "中断 {0} 无法转发: 连接未找到!", i); } } } } public override void Reset() { base.Reset(); intMaskPriority = 0; intFTP = 0; } public long Size => 0x10; public IReadOnlyDictionary Connections { get; } private readonly IMachine machine; private readonly Dictionary connections; private readonly bool forceEnableIRQ4 = true; private uint intMaskPriority; private uint intFTP; // 寄存器定义 private enum Registers { IntMaskPriority = 0x00, IntFTP = 0x04, IntForce = 0x08, IntClr = 0x0C, } } }