<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Zephyr设备初始化机制交互式解析</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <!-- Chosen Palette: Soft Tech -->
    <!-- Application Structure Plan: The application is designed around a central, interactive, vertical flowchart representing the Zephyr boot sequence. This visual anchor (hub) allows users to immediately form a mental model of the process. Instead of a linear report, content is organized into thematic sections (spokes) that are revealed dynamically when a user clicks on a corresponding stage in the flowchart. This hub-and-spoke model promotes non-linear exploration, which is ideal for a technical audience that may want to quickly jump to specific topics like initialization priorities or dependency issues. Key data points, such as initialization priorities, are visualized using a bar chart to make abstract numbers tangible. This structure was chosen to transform a dense, text-based report into an engaging and intuitive learning tool, prioritizing user understanding and exploration over simply reproducing the source document's layout. -->
    <!-- Visualization & Content Choices: 
        - Report Info: Zephyr Boot Sequence -> Goal: Organize/Change -> Viz: Vertical HTML/CSS flowchart -> Interaction: Click to navigate to content sections -> Justification: Provides a high-level map and acts as the main navigation, guiding the user's journey.
        - Report Info: DEVICE_DEFINE macro -> Goal: Inform/Organize -> Viz: Code block + HTML table -> Interaction: Click button to toggle table visibility -> Justification: Clearly separates code from its explanation, reducing initial clutter.
        - Report Info: Initialization Levels -> Goal: Compare/Inform -> Viz: HTML table -> Interaction: Highlight active level based on flowchart selection -> Justification: Table is ideal for comparison; highlighting adds context.
        - Report Info: Initialization Priorities -> Goal: Compare/Relationships -> Viz: Chart.js Bar Chart -> Interaction: Highlight specific driver priority -> Justification: A chart visualizes relative numerical order far more effectively than text, making priority conflicts easier to understand.
        - Report Info: Dependency/Future Issues -> Goal: Organize/Inform -> Viz: Interactive accordion cards -> Interaction: Click to expand/collapse -> Justification: Breaks down complex problems into digestible chunks, encouraging engagement without overwhelming the user.
        - Library/Method: Chart.js for canvas-based charts, Vanilla JS for all interactions (toggles, navigation), Tailwind CSS for layout and styling. -->
    <!-- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
    <style>
        body {
            font-family: 'Inter', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif';
        }
        .nav-link.active {
            background-color: #e0f2fe; /* sky-100 */
            color: #0c4a6e; /* sky-900 */
            font-weight: 600;
            border-left-color: #0ea5e9; /* sky-500 */
        }
        .content-section {
            display: none;
        }
        .content-section.active {
            display: block;
        }
        .flow-line {
            width: 2px;
            background-color: #cbd5e1; /* slate-300 */
            height: 1.5rem;
            margin-left: calc(0.75rem - 1px);
        }
        .flow-dot {
            width: 0.75rem;
            height: 0.75rem;
            background-color: #94a3b8; /* slate-400 */
            border-radius: 9999px;
        }
        .nav-link.active .flow-dot {
            background-color: #0ea5e9; /* sky-500 */
        }
        .accordion-content {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.3s ease-out;
        }
    </style>
</head>
<body class="bg-slate-50 text-slate-700">

    <main class="container mx-auto p-4 md:p-8">
        <header class="text-center mb-10">
            <h1 class="text-3xl md:text-4xl font-bold text-slate-900 mb-2">Zephyr设备初始化机制交互式解析</h1>
            <p class="text-lg text-slate-600">一份将复杂的技术报告转化为可探索体验的交互式应用</p>
        </header>

        <div class="flex flex-col md:flex-row gap-8">
            <!-- Sticky Navigation -->
            <aside class="md:w-1/4 lg:w-1/5 md:sticky top-8 self-start">
                <h2 class="text-lg font-semibold text-slate-800 mb-4">系统启动流程</h2>
                <nav id="boot-sequence-nav" class="flex flex-col items-start">
                    <!-- Nav items will be dynamically generated here -->
                </nav>
            </aside>

            <!-- Content Panel -->
            <div id="content-panel" class="md:w-3/4 lg:w-4/5 min-h-screen">
                <!-- Content sections will be dynamically generated here -->
            </div>
        </div>
    </main>

    <footer class="text-center p-6 mt-12 border-t border-slate-200">
        <p class="text-sm text-slate-500">基于 Zephyr RTOS 设备模型报告构建 | 旨在促进理解与探索</p>
    </footer>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const navContainer = document.getElementById('boot-sequence-nav');
            const contentContainer = document.getElementById('content-panel');

            const contentData = [
                {
                    id: 'intro',
                    title: '报告引言',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">深入理解Zephyr的自动化设备初始化</h3>
                        <p class="mb-4 text-slate-600 leading-relaxed">在像Zephyr这样的实时操作系统中,确保所有硬件设备在主应用程序开始前都已正确初始化是至关重要的。本应用的源报告深入探讨了Zephyr的设备模型,特别是<code>DEVICE_DEFINE</code>宏如何将一个设备(如DSP)的初始化函数(例如<code>dsp_acts_init</code>)无缝集成到系统启动流程中。这个过程是高度自动化的,旨在简化开发,但其背后依赖于一个由初始化级别、优先级和“链接器魔法”构成的复杂系统。</p>
                        <p class="mb-6 text-slate-600 leading-relaxed">本交互式应用旨在揭开这一过程的神秘面纱。您可以通过左侧的启动流程图进行导航,逐步探索从设备定义到内核调用其初始化函数的完整路径。我们将通过可视化的方式,帮助您理解其中的关键概念、潜在的依赖问题以及Zephyr社区为应对这些挑战而提出的未来演进方向。</p>
                        <div class="bg-sky-50 border-l-4 border-sky-400 p-4 rounded-r-lg">
                            <p class="text-sky-800"><strong>如何使用:</strong> 点击左侧“系统启动流程”中的任意阶段,右侧将显示对应的详细解析。请从“设备定义”开始您的探索之旅!</p>
                        </div>
                    `
                },
                {
                    id: 'device-define',
                    title: '1. 设备定义: DEVICE_DEFINE',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">一切的起点:<code>DEVICE_DEFINE</code> 宏</h3>
                        <p class="mb-4 text-slate-600 leading-relaxed">在Zephyr中,一个设备驱动程序的生命周期始于<code>DEVICE_DEFINE</code>宏。这个宏是Zephyr设备模型的核心,它在编译时静态地创建一个设备实例,并将其初始化函数注册到系统的启动序列中。这使得内核能够在启动时自动发现并初始化所有已定义的设备,而无需开发者手动调用任何初始化代码。</p>
                        <p class="mb-6 text-slate-600 leading-relaxed">下面是源报告中分析的<code>dsp_acts</code>设备的定义示例。这个宏的每个参数都扮演着至关重要的角色,共同构成了设备在系统中的完整画像。</p>
                        <div class="bg-gray-900 rounded-lg p-4 my-6 text-white text-sm font-mono overflow-x-auto">
                            <pre><code>DEVICE_DEFINE(dsp_acts, CONFIG_DSP_NAME,
              dsp_acts_init, NULL, &dsp_data, &dsp_acts_config,
              POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &dsp_drv_api);</code></pre>
                        </div>
                        <div id="param-table-container" class="border border-slate-200 rounded-lg p-6">
                            <h4 class="text-xl font-semibold text-slate-800 mb-4">参数详解</h4>
                            <p class="mb-4 text-slate-600">下表详细解释了<code>DEVICE_DEFINE</code>宏的每个参数及其在<code>dsp_acts</code>示例中的具体值,这些参数共同决定了设备的身份、行为和初始化时机。</p>
                            <div class="overflow-x-auto">
                                <table class="w-full text-left border-collapse">
                                    <thead class="bg-slate-100">
                                        <tr>
                                            <th class="p-3 font-semibold text-slate-700 border-b border-slate-200">参数</th>
                                            <th class="p-3 font-semibold text-slate-700 border-b border-slate-200">描述</th>
                                            <th class="p-3 font-semibold text-slate-700 border-b border-slate-200"><code>dsp_acts</code> 示例值</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">init_fn</td>
                                            <td class="p-3 border-b border-slate-200">设备初始化函数指针,由内核在启动时调用。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">dsp_acts_init</td>
                                        </tr>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">data</td>
                                            <td class="p-3 border-b border-slate-200">指向设备运行时可变数据结构体的指针(存-在RAM中)。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">&amp;dsp_data</td>
                                        </tr>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">config</td>
                                            <td class="p-3 border-b border-slate-200">指向设备只读配置数据结构体的指针(存在ROM中)。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">&amp;dsp_acts_config</td>
                                        </tr>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">level</td>
                                            <td class="p-3 border-b border-slate-200">初始化发生的系统级别。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">POST_KERNEL</td>
                                        </tr>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">prio</td>
                                            <td class="p-3 border-b border-slate-200">在指定级别内的初始化优先级 (0-99)。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">CONFIG_KERNEL_INIT_PRIORITY_DEVICE</td>
                                        </tr>
                                        <tr class="hover:bg-slate-50">
                                            <td class="p-3 border-b border-slate-200 font-mono text-sky-700">api</td>
                                            <td class="p-3 border-b border-slate-200">指向设备API函数指针集合的指针,提供抽象接口。</td>
                                            <td class="p-3 border-b border-slate-200 font-mono">&amp;dsp_drv_api</td>
                                        </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    `
                },
                {
                    id: 'init-levels',
                    title: '2. 初始化级别 (Level)',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">时机至关重要:初始化级别</h3>
                        <p class="mb-4 text-slate-600 leading-relaxed">Zephyr的启动过程被划分为几个明确的阶段或“级别”。<code>DEVICE_DEFINE</code>宏中的<code>level</code>参数决定了设备的初始化函数将在哪个阶段被执行。这是一个粗粒度的排序机制,确保了系统资源按逻辑顺序准备就绪。</p>
                        <p class="mb-6 text-slate-600 leading-relaxed"><code>dsp_acts</code>设备被配置在<code>POST_KERNEL</code>级别进行初始化。这是一个非常关键的选择,因为它意味着初始化将在Zephyr内核完全启动、所有内核服务(如线程、信号量、内存管理)都可用之后进行。这为驱动程序提供了安全使用内核功能的保障。</p>
                        <div class="overflow-x-auto border border-slate-200 rounded-lg p-6">
                            <h4 class="text-xl font-semibold text-slate-800 mb-4">Zephyr 系统初始化级别详解</h4>
                             <table class="w-full text-left border-collapse">
                                <thead class="bg-slate-100">
                                    <tr>
                                        <th class="p-3 font-semibold text-slate-700 border-b border-slate-200">级别</th>
                                        <th class="p-3 font-semibold text-slate-700 border-b border-slate-200">描述</th>
                                        <th class="p-3 font-semibold text-slate-700 border-b border-slate-200">典型用途</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr class="hover:bg-slate-50">
                                        <td class="p-3 border-b border-slate-200 font-mono">EARLY</td>
                                        <td class="p-3 border-b border-slate-200">极早期,在C代码环境准备好后立即执行。</td>
                                        <td class="p-3 border-b border-slate-200">SoC或架构特定的底层初始化。</td>
                                    </tr>
                                    <tr class="hover:bg-slate-50">
                                        <td class="p-3 border-b border-slate-200 font-mono">PRE_KERNEL_1 / 2</td>
                                        <td class="p-3 border-b border-slate-200">内核服务可用之前。</td>
                                        <td class="p-3 border-b border-slate-200">不依赖内核服务的早期驱动初始化。</td>
                                    </tr>
                                    <tr class="bg-sky-100 font-semibold text-sky-900">
                                        <td class="p-3 border-b border-slate-200 font-mono">POST_KERNEL</td>
                                        <td class="p-3 border-b border-slate-200">内核已启动并活跃,所有内核原语可用。</td>
                                        <td class="p-3 border-b border-slate-200">大部分设备驱动和系统服务(如本例的DSP、蓝牙栈)。</td>
                                    </tr>
                                    <tr class="hover:bg-slate-50">
                                        <td class="p-3 border-b border-slate-200 font-mono">APPLICATION</td>
                                        <td class="p-3 border-b border-slate-200">在<code>main()</code>函数执行之前。</td>
                                        <td class="p-3 border-b border-slate-200">应用程序特定的初始化。</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    `
                },
                {
                    id: 'priority',
                    title: '3. 初始化优先级 (Priority)',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">精细控制:初始化优先级</h3>
                        <p class="mb-4 text-slate-600 leading-relaxed">在同一个初始化级别内,可能存在数十个设备和系统服务需要初始化。为了管理它们之间的顺序,特别是处理依赖关系,Zephyr引入了优先级(priority)机制。这是一个从0到99的数字,数字越小,优先级越高,越早被执行。</p>
                        <p class="mb-6 text-slate-600 leading-relaxed"><code>dsp_acts</code>设备的优先级被设置为<code>CONFIG_KERNEL_INIT_PRIORITY_DEVICE</code>,这是一个Kconfig选项,默认值通常为50。这个选择决定了它在<code>POST_KERNEL</code>级别中与其他设备(如PINMUX、I2C控制器等)的相对初始化顺序。正确的优先级设置对于避免“鸡生蛋,蛋生鸡”式的依赖问题至关重要。</p>
                        <div class="border border-slate-200 rounded-lg p-6">
                            <h4 class="text-xl font-semibold text-slate-800 mb-4">POST_KERNEL 级别内常见优先级对比</h4>
                            <p class="mb-4 text-slate-600">下图通过一个条形图直观地展示了<code>POST_KERNEL</code>级别中一些常见驱动的初始化优先级。您可以看到,像PINMUX(引脚复用)这样的基础服务通常具有更高的优先级(数值更小),以确保它们在依赖它们的设备(如我们的DSP)之前准备就M就绪。</p>
                            <div class="chart-container relative h-96 max-h-[400px] w-full max-w-3xl mx-auto">
                                <canvas id="priorityChart"></canvas>
                            </div>
                        </div>
                    `
                },
                {
                    id: 'linker-magic',
                    title: '4. 链接器魔法与调用',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">幕后英雄:链接器</h3>
                        <p class="mb-4 text-slate-600 leading-relaxed">我们已经定义了设备、级别和优先级,但系统究竟是如何找到并按正确顺序调用<code>dsp_acts_init</code>函数的呢?答案在于“链接器魔法”。当编译器处理<code>DEVICE_DEFINE</code>宏时,它会生成一个包含初始化函数指针和设备信息的小结构体(<code>init_entry</code>)。</p>
                        <p class="mb-6 text-slate-600 leading-relaxed">然后,链接器脚本会将所有这些<code>init_entry</code>结构体收集起来,并将它们放入一个特殊的内存区域(链接器章节)。最关键的是,链接器会根据每个入口的初始化级别和优先级对它们进行排序。这样,在最终的固件镜像中,就形成了一个预先排好序的初始化函数指针数组。</p>
                        <div class="bg-slate-100 rounded-lg p-6">
                            <h4 class="text-xl font-semibold text-slate-800 mb-4">最终调用路径</h4>
                            <ol class="list-decimal list-inside space-y-3 text-slate-700">
                                <li><strong>定义与注册:</strong> <code>DEVICE_DEFINE</code> 创建一个包含 <code>dsp_acts_init</code> 函数指针的 <code>init_entry</code>。</li>
                                <li><strong>收集与排序:</strong> 链接器将这个 <code>init_entry</code> 和其他所有入口放入一个特定内存段,并根据级别和优先级排序。</li>
                                <li><strong>内核遍历:</strong> 系统启动时,内核中的一个函数(如 <code>z_sys_init_runlevel</code>)会遍历这个排好序的数组。</li>
                                <li><strong>执行调用:</strong> 当遍历到 <code>dsp_acts</code> 对应的入口时,内核会调用 <code>dsp_acts_init</code> 函数,并将指向 <code>dsp_acts</code> 设备实例的指针作为参数传入。</li>
                            </ol>
                        </div>
                    `
                },
                {
                    id: 'dependencies',
                    title: '5. 依赖问题与演进',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">挑战与未来:依赖管理</h3>
                        <p class="mb-6 text-slate-600 leading-relaxed">尽管Zephyr的初始化系统很强大,但它并非完美无缺。当前基于优先级的依赖管理机制将保证正确顺序的责任完全交给了开发者。如果依赖关系复杂或未被完全理解,就很容易导致难以调试的运行时错误。源报告中强调了几个关键挑战以及社区正在探索的解决方案。</p>
                        
                        <div class="space-y-4 accordion-container">
                            <div class="accordion-item border border-slate-200 rounded-lg">
                                <button class="accordion-header w-full flex justify-between items-center p-4 text-left font-semibold text-slate-800 bg-slate-100 hover:bg-slate-200 transition-colors">
                                    <span>挑战:隐式依赖与优先级冲突</span>
                                    <svg class="w-5 h-5 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
                                </button>
                                <div class="accordion-content">
                                    <div class="p-4 border-t border-slate-200 text-slate-600">
                                        <p><strong>问题:</strong> 系统本身不追踪设备间的依赖关系。例如,一个EEPROM驱动可能依赖I2C总线,但如果I2C驱动的初始化优先级(数字更大)低于EEPROM驱动,EEPROM在尝试获取I2C总线句柄时将失败,导致系统故障。</p>
                                        <p class="mt-2"><strong>影响:</strong> 这种手动管理方式是脆弱的,特别是在大型、复杂的项目中,依赖关系可能跨越多个子系统,使得正确的优先级设置变得异常困难。</p>
                                    </div>
                                </div>
                            </div>

                            <div class="accordion-item border border-slate-200 rounded-lg">
                                <button class="accordion-header w-full flex justify-between items-center p-4 text-left font-semibold text-slate-800 bg-slate-100 hover:bg-slate-200 transition-colors">
                                    <span>演进方向一:延迟初始化 (Deferred Init)</span>
                                    <svg class="w-5 h-5 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
                                </button>
                                <div class="accordion-content">
                                    <div class="p-4 border-t border-slate-200 text-slate-600">
                                       <p><strong>方案:</strong> 允许某些设备在启动时不自动初始化。应用程序可以在运行时,当条件成熟时(例如,电源已稳定、所需资源已可用),手动调用其初始化函数。</p>
                                       <p class="mt-2"><strong>优势:</strong> 这对于需要动态电源管理的设备或共享资源的场景非常有用,提供了更大的灵活性,避免了在不适宜的时候强制初始化。</p>
                                    </div>
                                </div>
                            </div>

                            <div class="accordion-item border border-slate-200 rounded-lg">
                                <button class="accordion-header w-full flex justify-between items-center p-4 text-left font-semibold text-slate-800 bg-slate-100 hover:bg-slate-200 transition-colors">
                                    <span>演进方向二:利用Devicetree序数</span>
                                    <svg class="w-5 h-5 transform transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path></svg>
                                </button>
                                <div class="accordion-content">
                                    <div class="p-4 border-t border-slate-200 text-slate-600">
                                        <p><strong>方案:</strong> 探索使用设备树(Devicetree)来更明确地声明设备间的依赖关系。构建系统可以解析这些依赖,并自动生成正确的初始化顺序,而不是依赖开发者手动设置的数字优先级。</p>
                                        <p class="mt-2"><strong>优势:</strong> 将依赖管理从命令式(手动设置优先级)转变为声明式(声明依赖关系),这是一种更健壮、更不易出错的方法,可以大大提高系统的可靠性和可维护性。</p>
                                    </div>
                                </div>
                            </div>
                        </div>
                    `
                },
                {
                    id: 'summary',
                    title: '6. 总结与最佳实践',
                    content: `
                        <h3 class="text-2xl font-bold text-slate-800 mb-4">总结与关键启示</h3>
                        <p class="mb-6 text-slate-600 leading-relaxed">通过本次交互式探索,我们揭示了Zephyr RTOS中<code>dsp_acts_init</code>函数的完整调用路径:它始于<code>DEVICE_DEFINE</code>的静态注册,经过初始化级别和优先级的分类,由链接器进行编译时排序,最终在系统启动过程中被内核按预定顺序精确调用。这个自动化机制是Zephyr高效和可预测性的关键。</p>
                        
                        <div class="bg-sky-50 border-l-4 border-sky-400 p-6 rounded-r-lg">
                            <h4 class="text-xl font-semibold text-sky-900 mb-3">开发者最佳实践</h4>
                            <ul class="list-disc list-inside space-y-2 text-sky-800">
                                <li><strong>深入理解级别与优先级:</strong> 仔细选择初始化级别和优先级,确保所有依赖项(如时钟、PINMUX、总线控制器)都已就绪。</li>
                                <li><strong>显式管理依赖:</strong> 在文档或代码注释中明确记录驱动的依赖关系。在复杂的系统中,优先考虑使用设备树来声明依赖,而不是仅仅依赖优先级数字。</li>
                                <li><strong>拥抱未来机制:</strong> 关注Zephyr社区关于延迟初始化和设备树序数等新机制的进展,并适时采用它们来构建更健壮、更灵活的系统。</li>
                                <li><strong>利用日志与调试:</strong> 当遇到初始化问题时,善用日志系统在初始化函数中打印关键信息,这是定位优先级冲突或资源未就绪问题的最有效方法。</li>
                            </ul>
                        </div>
                    `
                },
            ];

            let activeLink = null;
            let priorityChartInstance = null;
            
            // Generate Nav and Content
            contentData.forEach((item, index) => {
                // Create Nav Link
                const navItemContainer = document.createElement('div');
                navItemContainer.className = 'flex items-center w-full';

                const navLink = document.createElement('a');
                navLink.href = `#${item.id}`;
                navLink.id = `nav-${item.id}`;
                navLink.className = 'nav-link flex-grow pl-4 pr-2 py-2 border-l-4 border-transparent hover:bg-slate-100 transition-colors rounded-r-md';
                navLink.innerHTML = `<span class="text-slate-700">${item.title}</span>`;
                navLink.addEventListener('click', (e) => {
                    e.preventDefault();
                    setActiveSection(item.id);
                    // Smooth scroll for better UX on mobile where content is below
                    document.getElementById(item.id).scrollIntoView({ behavior: 'smooth', block: 'start' });
                });

                const dot = document.createElement('div');
                dot.className = 'flow-dot -ml-1.5 z-10';
                
                navItemContainer.appendChild(dot);
                navItemContainer.appendChild(navLink);

                navContainer.appendChild(navItemContainer);
                
                if (index < contentData.length - 1) {
                    const line = document.createElement('div');
                    line.className = 'flow-line';
                    navContainer.appendChild(line);
                }

                // Create Content Section
                const section = document.createElement('section');
                section.id = item.id;
                section.className = 'content-section';
                section.innerHTML = item.content;
                contentContainer.appendChild(section);
            });

            // Accordion Logic
            document.querySelectorAll('.accordion-header').forEach(button => {
                button.addEventListener('click', () => {
                    const content = button.nextElementSibling;
                    const icon = button.querySelector('svg');
                    button.parentElement.classList.toggle('open');
                    icon.classList.toggle('rotate-180');

                    if (content.style.maxHeight) {
                        content.style.maxHeight = null;
                    } else {
                        content.style.maxHeight = content.scrollHeight + "px";
                    }
                });
            });

            function setActiveSection(id) {
                if (activeLink) {
                    activeLink.classList.remove('active');
                }

                document.querySelectorAll('.content-section').forEach(section => {
                    section.classList.remove('active');
                });
                document.querySelectorAll('.nav-link').forEach(link => {
                    link.classList.remove('active');
                });

                const newActiveSection = document.getElementById(id);
                const newActiveLink = document.getElementById(`nav-${id}`);

                if (newActiveSection && newActiveLink) {
                    newActiveSection.classList.add('active');
                    newActiveLink.classList.add('active');
                    activeLink = newActiveLink;

                    if (id === 'priority') {
                        renderPriorityChart();
                    }
                }
            }
            
            function renderPriorityChart() {
                const ctx = document.getElementById('priorityChart');
                if (!ctx) return;
                
                if (priorityChartInstance) {
                    priorityChartInstance.destroy();
                }

                const data = {
                    labels: ['PINMUX', 'CLOCK_CONTROL', 'DSP (本例)', 'I2C Controller', 'Sensor Driver'],
                    datasets: [{
                        label: 'POST_KERNEL 初始化优先级 (值越小越高)',
                        data: [45, 48, 50, 60, 80],
                        backgroundColor: [
                            'rgba(56, 189, 248, 0.6)', // sky-400
                            'rgba(56, 189, 248, 0.6)',
                            'rgba(251, 146, 60, 0.7)', // orange-400
                            'rgba(165, 180, 252, 0.6)', // indigo-300
                            'rgba(165, 180, 252, 0.6)',
                        ],
                        borderColor: [
                            'rgba(14, 165, 233, 1)',
                            'rgba(14, 165, 233, 1)',
                            'rgba(249, 115, 22, 1)',
                            'rgba(99, 102, 241, 1)',
                            'rgba(99, 102, 241, 1)',
                        ],
                        borderWidth: 1
                    }]
                };

                priorityChartInstance = new Chart(ctx, {
                    type: 'bar',
                    data: data,
                    options: {
                        indexAxis: 'y',
                        maintainAspectRatio: false,
                        responsive: true,
                        plugins: {
                            legend: {
                                display: false
                            },
                            title: {
                                display: true,
                                text: '常见驱动的初始化优先级对比',
                                font: {
                                    size: 16
                                },
                                color: '#334155'
                            },
                            tooltip: {
                                callbacks: {
                                    label: function(context) {
                                        return ` 优先级: ${context.raw} (数值越小, 越早执行)`;
                                    }
                                }
                            }
                        },
                        scales: {
                            x: {
                                beginAtZero: true,
                                title: {
                                    display: true,
                                    text: '优先级数值'
                                }
                            }
                        }
                    }
                });
            }

            // Set initial state
            setActiveSection('intro');
        });
    </script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84174.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84174.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84174.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

腾讯地图Web版解决热力图被轮廓覆盖的问题

前言 你好&#xff0c;我是喵喵侠。 还记得那天傍晚&#xff0c;我正对着电脑调试一个腾讯地图的热力图页面。项目是一个区域人流密度可视化模块&#xff0c;我加了一个淡蓝色的轮廓图层用于表示区域范围&#xff0c;热力图放在下面用于展示人流热度。效果一预览&#xff0c;…

【JVMGC垃圾回收场景总结】

文章目录 CMS在并发标记阶段&#xff0c;已经被标记的对象&#xff0c;又被新生代跨带引用&#xff0c;这时JVM会怎么处理?为什么 Minor GC 会发生 STW&#xff1f;有哪些对象是在栈上分配的&#xff1f;对象在 JVM 中的内存结构为什么需要对齐填充&#xff1f;JVM 对象分配空…

3_STM32开发板使用(STM32F103ZET6)

STM32开发板使用(STM32F103ZET6) 一、概述 当前所用开发板为正点原子精英板,MCU: STM32F103ZET6。一般而言,拿到板子之后先要对板子有基础的认识,包括对开发板上电开机、固件下载、调试方法这三个部分有基本的掌握。 二、系统开机 2.1 硬件连接 直接接电源线或Type-c线…

crackme012

crackme012 名称值软件名称attackiko.exe加壳方式无保护方式serial编译语言Delphi v1.0调试环境win10 64位使用工具x32dbg,PEid破解日期2025-06-18 -发现是 16位windows 程序环境还没搭好先留坑

CppCon 2016 学习:I Just Wanted a Random Integer

你想要一个随机整数&#xff0c;用于模拟随机大小的DNA读取片段&#xff08;reads&#xff09;&#xff0c;希望覆盖不同长度范围&#xff0c;也能测试边界情况。 代码部分是&#xff1a; #include <cstdlib> auto r std::rand() % 100;它生成一个0到99之间的随机整数&…

MySQL层级查询实战:无函数实现部门父路径

本次需要击毙的MySQL函数 函数主要用于获取部门的完整层级路径&#xff0c;方便在应用程序或SQL查询中直接调用&#xff0c;快速获得部门的上下级关系信息。执行该函数之后简单使用SQL可以实现数据库中部门名称查询。例如下面sql select name,GetDepartmentParentNames(du.de…

Python初学者教程:如何从文本中提取IP地址

Python初学者教程:如何从文本中提取IP地址 在网络安全和数据分析领域,经常需要从文本文件中提取IP地址。本文将引导您使用Python创建一个简单但实用的工具,用于从文本文件提取所有IP地址并将其保存到新文件中。即使您是编程新手,也可以跟随本教程学习Python的基础知识! …

【Redis】Redis核心探秘:数据类型的编码实现与高速访问之道

&#x1f4da;️前言 &#x1f31f;&#x1f31f;&#x1f31f;精彩导读 本次我们将全面剖析Redis的核心技术要点&#xff0c;包括其丰富的数据类型体系、高效的编码方式以及秒级响应的性能奥秘。对于渴望深入理解Redis底层机制的技术爱好者&#xff0c;这是一次难得的学习机会…

Halcon —— 多种二维码检测

工业视觉实战&#xff1a;Halcon多类型二维码识别技术详解 在工业自动化场景中&#xff0c;兼容多种二维码类型是提高生产线灵活性的关键。本文将深入解析Halcon实现Data Matrix、QR Code和PDF417三种主流二维码的兼容识别方案&#xff0c;并重点解释核心算子参数。 一、多类型…

安卓vscodeAI开发实例

前言 前些天发现了一个巨牛的人工智能免费学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 目录 一、安卓开发基础与工具链革新 1.1 Android Studio的局限性分析 1.2 VSCode在移动开发中的崛起 1.3 跨平台开发工具链对比…

③通用搜索---解析FastAdmin中的表格列表的功能

深度解析FastAdmin中的表格列表的功能-CSDN博客文章浏览阅读25次。本文将FastAdmin框架的CRUD功能配置要点进行了系统梳理。官方文档与开发经验相结合&#xff0c;详细介绍了菜单显示、TAB过滤、通用搜索、工具栏按钮、动态统计、快速搜索等17项功能的配置方法。包括字段渲染&a…

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_项目里程碑示例(CalendarView01_22)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

Python爬虫实战:获取Diesel电商数据并分析

1. 引言 在当今数字化时代,电商平台积累了海量的产品和用户数据。通过对这些数据的挖掘和分析,企业可以深入了解市场动态、消费者需求和竞争态势,从而制定更有效的营销策略和产品规划。Diesel 作为知名的时尚品牌,其在电商平台上的表现备受关注。本研究旨在通过 Python 爬…

Spring RestTemplate + MultiValueMap vs OkHttp 多值参数的处理

&#x1f4cc; Spring RestTemplate vs OkHttp&#xff1a;多值参数处理 一、MultiValueMap 与 FormBody 的差异 特性RestTemplate MultiValueMapOkHttp FormBody多值参数支持✅ 原生支持&#xff08;add("key", "value") 自动追加&#xff09;❌ 需显…

GelSight视触觉3D轮廓仪赋能Beomni人形机器人触觉遥测,开启人形机器人触觉应用新场景

在智能制造、航空航天等领域&#xff0c;传统机器人常面临操作精度不足、环境适应力弱等问题。GelSight触觉传感技术与Beomni人形机器人的融合&#xff0c;为这些场景提供了新可能 —— 通过亚微米级触觉感知能力&#xff0c;操作员可远程感知物体表面细节&#xff0c;在复杂环…

python设置word的字体颜色

这个错误是由于python-docx的RGBColor对象没有.rgb属性导致的。正确的属性访问方式是分别获取红、绿(g)、蓝(b)三个分量。以下是修复方案&#xff1a; 错误原因分析 RGBColor对象的结构如下&#xff1a; from docx.shared import RGBColorcolor RGBColor(255, 204, 51) pri…

推荐模型之GBDT-LR

一、概念 GBDT-LR模型由FaceBook&#xff08;现在的Meta&#xff09;团队于2014年在论文《Practial Lessons from Predicting Clicks on Ads at Facebook》中提出&#xff0c;目标是用于预测FaceBook的广告点击量&#xff08;实际上广告和推荐领域很多算法模型都是共用的&#…

Java实现Excel图片URL筛选与大小检测

Java实现Excel图片URL筛选与大小检测 在数据处理场景中&#xff0c;我们常需筛选Excel中的图片URL。本文分享一个完整的Java方案&#xff0c;涵盖从读取图片URL到检测有效性、筛选大小&#xff0c;再到生成新Excel文件的全过程&#xff0c;同时讲解开发与优化过程&#xff0c;…

Java 实现后端调用 Chromium 浏览器无头模式截图的方案

Java 实现后端调用 Chromium 浏览器无头模式截图的方案 1. 使用 Playwright 优点&#xff1a;功能强大、支持多浏览器&#xff08;Chromium/Firefox/WebKit&#xff09;、支持异步操作。实现方式&#xff1a; 利用 Playwright 创建无头浏览器实例&#xff1b;使用 Java 的调度…

基于多模态文档解析与RAG的行业知识库构建技术指南

1. 技术背景 随着企业非结构化数据&#xff08;扫描件、PDF、图像等&#xff09;占比超过80%&#xff0c;传统关键词检索已无法满足精准问答需求。本文提出融合**计算机视觉&#xff08;CV&#xff09;与大语言模型&#xff08;LLM&#xff09;**的解决方案&#xff0c;关键技…