You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Microchip Studio的Attiny1616:NVMCTRL写入Flash方法咨询

ATtiny1616 Flash 写入指南(基于NVMCTRL)

核心概念:页缓冲区与Flash写入逻辑

  • 页缓冲区:ATtiny1616的Flash以64字节为一页划分,页缓冲区是NVM控制器内部的临时存储区,大小与Flash页一致。写入Flash前,必须将整页的完整数据(包括新计算结果和需要保留的旧数据)加载到该缓冲区,再一次性写入对应Flash页。
  • Flash物理限制:Flash只能将位从1改写为0,要修改已写入的内容必须先擦除整个页(擦除后页内所有位变为1)。

完整Flash写入流程

  1. 等待NVM控制器空闲(检查NVMCTRL.STATUS的BUSY位)
  2. 擦除目标Flash页
  3. 将整页数据(新计算结果+需保留的旧数据)逐字加载到页缓冲区
  4. 执行页编程操作,将缓冲区内容写入Flash
  5. 等待编程完成

修正后的示例代码

以下代码实现了将计算得到的批量数据写入指定Flash页的功能:

#include <avr/io.h>

// 目标Flash页起始地址(必须对齐64字节页边界,0x8E00符合要求)
#define FLASH_TARGET_PAGE 0x8E00

/**
 * 擦除指定Flash页
 * @param page_addr 页起始地址(必须对齐页边界)
 */
void flash_erase_page(uint16_t page_addr) {
    // 等待NVM控制器空闲
    while(NVMCTRL.STATUS & NVMCTRL_BUSY_bm);
    
    // 设置要擦除的页地址
    NVMCTRL_ADDR = page_addr;
    
    // 解锁CCP寄存器,执行页擦除命令
    CCP = CCP_IOREG_gc; // 0x9D,对应IO寄存器解锁密钥
    NVMCTRL.CTRLA = NVMCTRL_CMD_PAGEERASE_gc; // 页擦除命令(0x03)
}

/**
 * 将16位数据加载到页缓冲区的指定地址
 * @param addr Flash中的目标地址(需在目标页范围内)
 * @param data 要写入的16位数据
 */
void flash_load_word(uint16_t addr, uint16_t data) {
    while(NVMCTRL.STATUS & NVMCTRL_BUSY_bm);
    
    NVMCTRL_ADDR = addr;
    NVMCTRL_DATA = data;
    
    CCP = CCP_IOREG_gc;
    NVMCTRL.CTRLA = NVMCTRL_CMD_WORDWRITE_gc; // 页缓冲区加载命令(0x06)
}

/**
 * 将页缓冲区内容编程到Flash页
 * @param page_addr 页起始地址
 */
void flash_program_page(uint16_t page_addr) {
    while(NVMCTRL.STATUS & NVMCTRL_BUSY_bm);
    
    NVMCTRL_ADDR = page_addr;
    
    CCP = CCP_IOREG_gc;
    NVMCTRL.CTRLA = NVMCTRL_CMD_PAGEWRITE_gc; // 页编程命令(0x04)
}

int main(void) {
    // 示例:生成32个16位计算结果(正好填满一页64字节)
    uint16_t results[32];
    for(int i = 0; i < 32; i++) {
        results[i] = i * 0x101; // 替换为你的实际计算逻辑
    }
    
    // 步骤1:擦除目标页
    flash_erase_page(FLASH_TARGET_PAGE);
    
    // 步骤2:将所有计算结果加载到页缓冲区
    for(int i = 0; i < 32; i++) {
        uint16_t target_addr = FLASH_TARGET_PAGE + (i * 2); // 每个16位字占2字节
        flash_load_word(target_addr, results[i]);
    }
    
    // 步骤3:将缓冲区内容写入Flash
    flash_program_page(FLASH_TARGET_PAGE);
    
    // 写入完成,进入 idle 状态
    while(1) {
        // 可添加其他任务逻辑,或保持休眠
    }
}

原代码的问题分析

  1. 缺少页擦除步骤:未擦除的Flash页无法被改写,直接编程会导致数据写入失败或错乱。
  2. 仅加载单个字到缓冲区:编程后整个页除了该字外,其他位置会被设为0xFF,原有数据完全丢失。
  3. 循环重复写入:Flash有擦写寿命限制(约10000次),无意义的重复擦写会加速芯片老化。

内容的提问来源于stack exchange,提问作者Takeru Tsuji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 10:57:20