我最近需要在AT32UC3L0256的 build NVRAM/EEPROM 中使用来存储一些配置数据。我终于设法使用 MCU 的用户页面 NVRAM(经过几天的反复试验和诅咒 GCC 忽略noinit
指令以及像往常一样修复和解决 ASF 中的错误)到这样的东西:
typedef struct
{
int writes; // write cycles counter
int irc_pot; // IRC_POT_IN position state
} _cfg;
volatile static int *nvram_adr=(int*)(void*)0x80800000; // user page NVRAM
volatile static _cfg ram_cfg; // RAM copy of cfg
void cfg_load() // nvram_cfg -> ram_cfg
{
ram_cfg.writes =nvram_adr[8];
ram_cfg.irc_pot=nvram_adr[9];
}
void cfg_save() // nvram_cfg <- ram_cfg
{
int i;
U32 buf[128];
// blank
for (i=0;i<128;i++) buf[i]=0xFFFFFFFF;
// cfg
buf[8]=ram_cfg.writes;
buf[9]=ram_cfg.irc_pot;
// Bootloader default cfg
buf[126]=0x929E0B79;
buf[127]=0xE11EFFD7;
flashcdw_memcpy(nvram_adr ,buf ,256,true); // write data -> nvram_cfg with erase
flashcdw_memcpy(nvram_adr+64,buf+64,256,false); // write data -> nvram_cfg without erase (fucking ASF cant write more than 256Bytes at once but erases whole page !!!)
}
为了能够写入完整的 512 字节,我必须进行更新flashcdw.c,flashcdw.h
,因为旧 ASF 确实编程了最多 256 字节,但擦除了整个页面,弄得一团糟。ASF 3.48.0.98
我还必须存储整个页面(而不是因为擦除而只存储 8 个字节),并且像往常一样由于 ASF 错误,我需要按原样进行操作,而不是只调用flashcdw_memcpy
一次...
它现在可以工作,但我发现某些地址会导致奇怪的行为。当0xFF
不在某个地址上时,设备将不再正常复位(但在复位运行正常之前仍然如此)。在非引导加载程序重置时,它会启动固件代码,但在几次之后[ms]
它会再次重置,这会永远持续下去。要清楚 RESET 发生在这部分代码中(在我的情况下):
for (U8 i=0;i<4;i++)
{
gpio_tgl_gpio_pin(_LED);
wait_ms(200);
}
配置系统后 LED 会简单闪烁(PLL CPU 时钟、配置的定时器和 ISR,但仍禁用中断)。LED 应闪烁几次(PLL 以正确的速度工作)但在循环完成之前发生复位。等待很简单:
//------------------------------------------------------------------------------------------------
#define clk_cpu 50000000
#define RDTSC_mask 0x0FFFFFFF
void wait_ms(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
static const U32 ms=(clk_cpu+999)/1000;
t0&=RDTSC_mask;
for (;dt>0;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=ms)
{
dt--;
t0+=ms;
t0&=RDTSC_mask;
continue;
}
}
}
//------------------------------------------------------------------------------------------------
更奇怪的是,如果我启动引导加载程序然后再次正常重置,设备正在正确重置并且固件再次工作(没有任何擦除/编程)但是如果我再次正常重置,重置循环再次发生......
如果我.userpage
使用 BatchISP(翻转)将 NVRAM 重新编程回原始状态,则芯片会再次正常工作。
所以最后的问题:
NVRAM 的用户页中的哪些地址会导致此问题或应保留/避免更改?
我知道最后 8 个字节是引导加载程序配置。我怀疑有问题的地址是前 16 个字节。应该用于用户数据并且
.userpage
不包含保险丝。怎么了?
它是某种看门狗还是什么?我以为那些是存放在其他地方的保险丝。我在数据表中看不到任何内容。
这里是原始的十六进制.userpage
:
:020000048080FA
:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
:1001F000FFFFFFFFFFFFFFFF929E0B79E11EFFD77E
:00000001FF
我使用这些(翻转命令)来获取和恢复它:
Batchisp -device AT32UC3L0256 -hardware RS232 -port COM1 -baudrate 115200 -operation memory user read savebuffer cfg_userpage.hex hex386 start reset 0
Batchisp -device AT32UC3L0256 -hardware RS232 -port COM1 -baudrate 115200 -operation onfail abort memory user loadbuffer cfg_userpage.hex program start reset 0
有问题的引导加载程序是 USART 版本:1.0.2 并且具有此行为的固件使用PLL、TC、GPIO、PWMA、ADC模块,但是在任何 ISR 和/或 ADC、PWMA、TC 使用之前发生复位。
[Edit1] 看门狗
据此,NVRAM 中的第一个字.userpage
是看门狗的保险丝,它解释了在ms
将数据修复为原始值并禁用 复位WDT
停止后几次复位。然而,现在不是启动程序而是启动了引导加载程序,所以仍然有一些可疑的东西。Bootloader 管脚选择在最后 8 字节
我还查看了 USART Bootloader ver: 1.0.2 源代码,发现它们正在使用FLASHC
而不是FLASHCDW
强制启动看门狗(这可能会重置其状态并使我的程序以某种方式再次运行)。
[Edit2] 错误隔离
我终于发现问题是由写入 512 字节的最后一个 32 位字引起的.userpage
:
U32 btldr[2]={0x929E0B79,0xE11EFFD7};
flashcdw_memcpy(&nvram_adr[127],(U32*)&btldr[1] ,4,false);
这是一个巨大的问题,因为为了正确存储数据,我必须使用擦除来擦除整个页面,无论如何,为了仍然能够正确引导到引导加载程序或我的固件,我必须恢复引导加载程序配置数据:
U32 btldr[2]={0x929E0B79,0xE11EFFD7};
flashcdw_memcpy(&nvram_adr[126],(U32*)&btldr[0] ,4,false);
flashcdw_memcpy(&nvram_adr[127],(U32*)&btldr[1] ,4,false);
我需要找到一种解决方法,如何将芯片恢复到功能状态。也许从引导加载程序复制看门狗重置(但这在我的应用程序中会非常有问题,甚至有风险),因为即使没有任何闪烁,它也会恢复芯片......
所以现在映射:
:020000048080FA
:10000000---WDT--FFFFFFFFFFFFFFFFFFFFFFFF00
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:10008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
:10009000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
:1000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
:1000B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
:1000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
:1000D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
:1000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:1000F000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:10010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
:10011000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
:10012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
:10013000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
:10014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
:10015000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
:10016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
:10017000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
:10018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
:10019000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
:1001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
:1001B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
:1001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
:1001D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
:1001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
:1001F000FFFFFFFFFFFFFFFF------BTLDR-----7E
:00000001FF
[Edit3] 解决方法
我设法成功地写入/读取程序存储器闪存(用 BatchISP 和 MCU 本身检查)它也可以正常启动。
这里的代码我用以下代码进行测试:
// **** test ****
volatile static U32 *flash_adr=(U32*)(void*)0x00000000;
const U32 buf[4]=
{
0xDEADBEEF,0x00112233,
0xDEADBEEF,0x44556677,
};
volatile static U32 *adr=(U32*)(void*)0x80030000;
flashcdw_memcpy(&adr[0],(U32*)buf,4*4,true ); // erase
flash_adr=(U32*)(void*)0x80000000;
for (U32 i=0;i<0x08000000;i++,flash_adr++)
{
if (flash_adr!=buf)
if (flash_adr[0]==buf[0])
if (flash_adr[1]==buf[1])
if (flash_adr[2]==buf[2])
if (flash_adr[3]==buf[3])
{ break; }
if ((i&0xFFF)==0) gpio_tgl_gpio_pin(_LED);
}
flash_adr
找到的地址与签名匹配的地址在哪里buf[]
......(我在 LCD 上打印它,所以我看看它是否符合我的预期),它终于做到了:)。所以我将使用它而不是.userpage
.
然而,.userpage
引导问题修复仍然是悬而未决的问题