From d276237532bd62039f73015e6be7b6f443551526 Mon Sep 17 00:00:00 2001 From: dengxingting Date: Tue, 31 Mar 2026 17:52:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=E3=80=8C/=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LC3233_Timer_InterruptController_NO3.cs | 441 ++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 LC3233_Timer_InterruptController_NO3.cs diff --git a/LC3233_Timer_InterruptController_NO3.cs b/LC3233_Timer_InterruptController_NO3.cs new file mode 100644 index 0000000..18b22ee --- /dev/null +++ b/LC3233_Timer_InterruptController_NO3.cs @@ -0,0 +1,441 @@ +//============================================================================ +// 作者: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, + } + } +}