<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[TXW81x_IOT-v2.5.3.6升级到TXW81x_FPV-v2.5.4.7 版本flash 加密写入异常]]></title><description><![CDATA[<h1>TXW81x：XIP 运行时 Flash 加密写（SET_ENCRYPT）不可用 / 极慢</h1>
<hr />
<h2>一、环境</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>值</th>
</tr>
</thead>
<tbody>
<tr>
<td>芯片</td>
<td>TXW817-824</td>
</tr>
<tr>
<td>SDK</td>
<td>hgSDK <strong>v2.5.4.3-41396</strong>（libflash / libcore 同版本）</td>
</tr>
<tr>
<td>运行方式</td>
<td>程序在 <strong>SPI Flash XIP</strong> 上执行（<code>SPI_NOR_XIP_MODE</code>，QSPI/<code>spi7</code>）</td>
</tr>
<tr>
<td>OS</td>
<td>RTOS（有任务 / mutex；<code>spi_nor_write</code> 内 <code>os_mutex_lock</code>）</td>
</tr>
<tr>
<td>镜像布局</td>
<td><code>ildr</code> @ <code>0x10000</code>，<code>iapp</code> @ <code>0x90000</code>，size <code>0x100000</code></td>
</tr>
<tr>
<td>makecode</td>
<td><code>CodeAddrOffset=0x1000</code>，<code>AesEnable=0</code></td>
</tr>
<tr>
<td>分区表</td>
<td><code>ildr</code> / <code>iapp</code> 等带 <strong>encrypted</strong> 标志</td>
</tr>
<tr>
<td>工厂烧录</td>
<td><code>AesEnable=0</code> + PT encrypted → 上电 txloader：<code>ENCRYPT</code>×N → <code>VERIFY</code> → <code>RUN</code> <strong>正常</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">加密 remap 约定（与官方注释一致）：</p>
<pre><code class="language-text">remap_base = partition_flash_addr + CodeAddrOffset
           = 0x90000 + 0x1000 = 0x91000   // iapp 为例
HDR [0, 0x1000) 明文；body [0x1000, ...) 需硬件加密写入
</code></pre>
<hr />
<h2>二、问题描述（摘要）</h2>
<p dir="auto"><strong>需求</strong>：Loader（XIP）做 OTA 时，按官方方式把 <strong>明文 body</strong> 写成与 txloader <code>ENCRYPT</code> 后相同的 <strong>片上 Flash 密文</strong>，以便复位后 VERIFY / 加密 XIP 启动。</p>
<p dir="auto"><strong>现象</strong>：</p>
<ol>
<li><strong>工厂 / txloader <code>ENCRYPT</code></strong>：正常（<code>encrypt bin done</code> → <code>verify bin done</code> → RUN）。</li>
<li><strong>应用内官方加密写</strong>（见下文伪代码）：
<ul>
<li>若按示例 <strong><code>__disable_irq()</code> 包住 <code>spi_nor_write</code></strong>：触发<br />
<code>** FATAL CALL , IRQ DISABLED **</code>（<code>pend_to_blk_obj</code>，mutex/信号量在关中断下阻塞）。</li>
<li>若 <strong>去掉关中断</strong>（仅保留 <code>SET_ENCRYPT</code> + <code>REMAP</code> + <code>spi_nor_write</code>）：能写完，但极慢，实测约 <strong><code>24000 ms / 1KB</code></strong>（约 24s/KB，整包 ~750KB body 不可接受）。</li>
</ul>
</li>
<li><strong>OTA 只写明文 body</strong>（不开 <code>SET_ENCRYPT</code>）：Loader 内 CRC 可对；复位后 txloader <strong>不再 ENCRYPT</strong>，直接 VERIFY → <code>boot_data_crc compare fail</code>（PT 仍 encrypted）。</li>
<li><strong>HDR <code>aes_en=0</code>（与 makecode AesEnable=0 一致）</strong>：不能让 VERIFY 按明文介质处理；加密策略以 <strong>PT encrypted</strong> 为准。</li>
<li>公开 SDK <strong>无</strong>「用 Flash 片内密钥在 RAM 加密 buffer，再明文 <code>spi_nor_write</code>」的 API（仅有通用 <code>sysaes</code>，需自备 key；<code>efuse</code> 只能取 key 的 CRC）。</li>
</ol>
<p dir="auto"><strong>诉求</strong>：请官方给出 <strong>XIP + RTOS 下</strong> 对 encrypted 分区做 OTA 加密写的推荐做法（或确认不支持），例如：</p>
<ul>
<li>是否必须把写路径放到 <strong>SRAM</strong> 再 <code>SET_ENCRYPT</code>？</li>
<li>是否有 <strong>host 预加密</strong> 工具/算法与片内一致？</li>
<li>是否有接口 <strong>强制再次 ENCRYPT</strong>（OTA 明文写后）？</li>
<li><code>SET_ENCRYPT</code> 期间与 XIP 取指的官方约束 / 时序（WIP、<code>wip.tms</code>）？</li>
</ul>
<hr />
<h2>三、官方路径伪代码（问题复现用）</h2>
<p dir="auto">与 SDK/<code>spi.h</code> 注释及官方 sample 中 <code>hal_partition_write_encrypt</code> 一致：</p>
<pre><code class="language-c">/* __CODE_OFFSET == makecode CodeAddrOffset == 0x1000 */

void official_flash_encrypt_program(uint32_t part_addr,
                                    uint32_t dst_offset, /* &gt;= 0x1000 for body */
                                    const uint8_t *plain, uint32_t len)
{
    struct spi_nor_flash *flash = (struct spi_nor_flash *)dev_get(HG_FLASH0_DEVID);
    uint32_t remap = part_addr + __CODE_OFFSET;  /* e.g. 0x91000 */
    uint32_t irq;

    spi_nor_open(flash);

    /* --- 官方示例常见写法：关中断 --- */
    irq = __disable_irq();

    spi_nor_ioctl(flash, SPI_XIP_CUSTOM_SET_ENCRYPT, 1, 0);
    spi_nor_ioctl(flash, SPI_XIP_CUSTOM_SET_REMAP, remap, 0);

    /* 写 Flash 绝对地址，不是 remap 后的 CPU 地址 */
    spi_nor_write(flash, part_addr + dst_offset, (uint8_t *)plain, len);

    spi_nor_ioctl(flash, SPI_XIP_CUSTOM_SET_ENCRYPT, 0, 0);
    spi_nor_ioctl(flash, SPI_XIP_CUSTOM_SET_REMAP, 0, 0);

    enable_irq(irq);
    spi_nor_close(flash);
}
</code></pre>
<p dir="auto">对应 SDK 枚举（<code>sdk/include/hal/spi.h</code>）：</p>
<pre><code class="language-c">SPI_XIP_CUSTOM_SET_REMAP,    // 配置 remap；需 SET_ENCRYPT=1 才生效
SPI_XIP_CUSTOM_SET_ENCRYPT,  // 是否强行加密
</code></pre>
<p dir="auto"><strong>变体 A（与示例一致，关中断）</strong> → 本板 RTOS：<code>FATAL CALL, IRQ DISABLED</code>。<br />
<strong>变体 B（去掉 disable_irq/enable_irq，其余相同）</strong> → 本板：功能上可写，<strong>~24s/KB</strong>。</p>
<p dir="auto">明文对照（同 XIP）：</p>
<pre><code class="language-c">/* HDR 或实验明文 body：不开 ENCRYPT */
spi_nor_open(flash);
spi_nor_write(flash, part_addr + dst_offset, plain, len);  /* 正常快 */
spi_nor_close(flash);
</code></pre>
<p dir="auto">擦除（64KB block）1MB 约百毫秒级，说明普通擦写正常。</p>
<hr />
<h2>四、复现步骤（简）</h2>
<ol>
<li>工厂烧录：PT <code>iapp</code> encrypted，<code>AesEnable=0</code>，确认上电有 <code>ENCRYPT</code>/<code>VERIFY</code>/<code>RUN</code>。</li>
<li>从 <strong>XIP Loader</strong> 擦除 <code>iapp</code>，写 HDR <code>[0,0x1000)</code> 明文（快）。</li>
<li>对 body <code>offset&gt;=0x1000</code> 调用上文 <code>official_flash_encrypt_program</code>：
<ul>
<li>带 <code>__disable_irq</code> → 观察 FATAL；</li>
<li>或不关中断 → 打点测量 <code>spi_nor_write</code> 耗时（本板 ~24000ms/1024B）。</li>
</ul>
</li>
<li>（可选）body 改明文写后 <code>mcu_reset</code>：观察多为 <code>INIT→INFO→VERIFY</code>（无 ENCRYPT），encrypted 槽 CRC fail。</li>
</ol>
<hr />
<h2>五、已排除 / 已观察</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>结论</th>
</tr>
</thead>
<tbody>
<tr>
<td>ioctl 顺序 / remap=<code>part+0x1000</code> / 绝对地址写</td>
<td>与官方一致</td>
</tr>
<tr>
<td>仅写 4KB HDR</td>
<td>不会进加密写（预期）</td>
</tr>
<tr>
<td>去 BLE、关 PSRAM_HEAP</td>
<td>未把 24s/KB 降到可用</td>
</tr>
<tr>
<td><code>spi7.wip.tms=60000</code>（无 erase-suspend 的 FAQ 配法）</td>
<td>erase 仍快；不解释为「每次等满 60s」，但是否加重 ENCRYPT+XIP 待官方确认</td>
</tr>
<tr>
<td>HDR <code>aes_en=0</code></td>
<td>不能改为明文 VERIFY</td>
</tr>
<tr>
<td>清 PT encrypted</td>
<td>双槽 VERIFY 失败 → <code>END</code>（已恢复）</td>
</tr>
</tbody>
</table>
<hr />
<h2>六、希望官方明确回答</h2>
<ol>
<li><strong>XIP 执行代码时</strong>，是否支持对同 Flash 做 <code>SET_ENCRYPT</code> + <code>spi_nor_write</code>？官方推荐流程是什么？</li>
<li>示例中的 **<code>__disable_irq</code> + spi_nor_write<code>** 在带 mutex 的 </code>libflash` 上如何避免 FATAL？是否必须 <strong>SRAM 重定位写函数</strong>？</li>
<li>有无 <strong>与片内 Flash 密钥一致</strong> 的预加密接口/工具（PC 或片上 buffer 加密）？</li>
<li>OTA 明文写入后，如何 <strong>触发与工厂相同的 ENCRYPT</strong>？</li>
<li><code>24000ms/1KB</code> 是否为已知限制？可接受优化手段？</li>
</ol>
<hr />
<h2>七、日志摘录</h2>
<p dir="auto"><strong>关中断 FATAL：</strong></p>
<pre><code class="language-text">enc-wr enter ...  (or WR into encrypt body @0x91000)
** FATAL CALL , IRQ DISABLED **
assertation ... pend_to_blk_obj ... Task:iplld_ws
</code></pre>
<p dir="auto"><strong>不关中断极慢：</strong></p>
<pre><code class="language-text">enc-wr off=0x1000 size=0x400 24000ms
</code></pre>
<p dir="auto"><strong>工厂路径正常：</strong></p>
<pre><code class="language-text">cur_st: ENCRYPT
working at 0, encrypt bin done
working at 1, encrypt bin done
cur_st: VERIFY
working at 0, verify bin done
cur_st: RUN
</code></pre>
<p dir="auto"><strong>明文 OTA 后复位（无再 ENCRYPT）：</strong></p>
<pre><code class="language-text">cur_st: INIT → INFO → VERIFY   // 无 ENCRYPT
... boot_data_crc compare fail ...
</code></pre>
]]></description><link>https://dev.taixin-semi.com/topic/53/txw81x_iot-v2.5.3.6升级到txw81x_fpv-v2.5.4.7-版本flash-加密写入异常</link><generator>RSS for Node</generator><lastBuildDate>Tue, 25 Aug 2026 13:42:50 GMT</lastBuildDate><atom:link href="https://dev.taixin-semi.com/topic/53.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 21 Aug 2026 07:26:37 GMT</pubDate><ttl>60</ttl></channel></rss>