- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Atmel samd21 microcontroller它有一个皮质 m0+ 核心。要引导加载新程序,我想删除位于地址 0x0000 0000
的向量表并在其中写入新数据。我遇到了两个问题:
0
上进行删除似乎并没有真正删除任何内容0
时遇到硬错误我将尝试更改 VTOR
的地址看看这是否能帮到我(编辑: 它没有帮助)。除此之外,有人知道是否:
0
时的硬故障是 Cortex m0+ 规范中定义的内容(我找不到任何东西),还是实现定义的行为?编辑
我的引导加载程序位于 max_flash - 0x1000
。我意识到这可能不是最好的事情,所以我可能会改变一些东西,使引导加载程序(有自己的向量表)位于 0x0000
。不过,我仍然想知道为什么我不能写入地址 0x0000
。 cortex m0+ 文档中没有任何内容表明我不应该这样做。
我检查了以下内容:
__asm__ volatile("cpsid if");
就在我开始戳内存之前)VTOR
的值会有什么不同吗? (它没有)BOOTPROT
“锁定”了? ? (不是,BOOTPROT
= 7。)LOCK
中被列为锁定区域?登记? (它们不是,LOCK
= 0xffff
)pc
= 0xf1dc
。还有什么要检查的吗?
最佳答案
可悲的是,Atmel(不能将此归咎于微芯片,这是在他们被同化之前发生的)放弃了他们内置的 SAM-BA 引导加载程序。相反,他们提供了一个软件/源版本,您可以自己放置它和一些额外的控件来在某种程度上保护该空间,但没有对保护的保护,因此程序解锁和删除或造成损坏是微不足道的。因此,最好要么只制作自己的引导加载程序,一个更简单、更易于维护的程序(并且尽量不要删除它),要么使用 SWD 接口(interface),如果不是替代方案,它是竞争产品的唯一解决方案。我最终选择了后者。
我发现,在该空间上删除和写入不仅容易,而且容易得可怕,一旦解锁了一些魔法,您就可以有意或无意地对该空间进行简单的存储以进行垃圾处理/覆盖。
我会发布我的代码接受或保留它,自从我阅读数据表以来已经有一段时间了,除了今天,我发现您应该搜索 BOOTPROT 以了解这些保护位以及要更改哪些寄存器以禁用该保护(如果它甚至打开)。
put 和 get 只是存储和加载指令的抽象。
//------------------------------------------------------------------------
//------------------------------------------------------------------------
#include "flash-bin.h"
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void PUT16 ( unsigned int, unsigned int );
unsigned int GET16 ( unsigned int );
void PUT8 ( unsigned int, unsigned int );
unsigned int GET8 ( unsigned int );
void dummy ( unsigned int );
#define PORT_BASE 0x41004400
#define PORTA_DIRSET (PORT_BASE+0x00+0x08)
#define PORTA_OUTCLR (PORT_BASE+0x00+0x14)
#define PORTA_OUTSET (PORT_BASE+0x00+0x18)
#define PORTA_OUTTGL (PORT_BASE+0x00+0x1C)
#define PORTB_DIRSET (PORT_BASE+0x80+0x08)
#define PORTB_OUTCLR (PORT_BASE+0x80+0x14)
#define PORTB_OUTSET (PORT_BASE+0x80+0x18)
#define PORTB_OUTTGL (PORT_BASE+0x80+0x1C)
#define PORTA_PMUX05 (PORT_BASE+0x00+0x30+5)
#define PORTA_PINCFG10 (PORT_BASE+0x00+0x40+10)
#define PORTA_PINCFG11 (PORT_BASE+0x00+0x40+11)
#define PORTB_PMUX01 (PORT_BASE+0x80+0x30+1)
#define PORTB_PMUX11 (PORT_BASE+0x80+0x30+11)
#define PORTB_PINCFG03 (PORT_BASE+0x80+0x40+3)
#define PORTB_PINCFG22 (PORT_BASE+0x80+0x40+22)
#define PORTB_PINCFG23 (PORT_BASE+0x80+0x40+23)
#define GCLK_BASE 0x40000C00
#define GCLK_CTRL (GCLK_BASE+0x00)
#define GCLK_STATUS (GCLK_BASE+0x01)
#define GCLK_CLKCTRL (GCLK_BASE+0x02)
#define GCLK_GENCTRL (GCLK_BASE+0x04)
#define GCLK_GENDIV (GCLK_BASE+0x08)
#define PM_BASE 0x40000400
#define APBCMASK (PM_BASE+0x20)
#define SYSCTRL_BASE 0x40000800
#define OSC8M (SYSCTRL_BASE+0x20)
#define SERCOM5_BASE 0x42001C00
#define SERCOM5_CTRLA (SERCOM5_BASE+0x00)
#define SERCOM5_CTRLB (SERCOM5_BASE+0x04)
#define SERCOM5_BAUD (SERCOM5_BASE+0x0C)
#define SERCOM5_INTFLAG (SERCOM5_BASE+0x18)
#define SERCOM5_SYNCBUSY (SERCOM5_BASE+0x1C)
#define SERCOM5_DATA (SERCOM5_BASE+0x28)
#define SERCOM0_BASE 0x42000800
#define SERCOM0_CTRLA (SERCOM0_BASE+0x00)
#define SERCOM0_CTRLB (SERCOM0_BASE+0x04)
#define SERCOM0_BAUD (SERCOM0_BASE+0x0C)
#define SERCOM0_INTFLAG (SERCOM0_BASE+0x18)
#define SERCOM0_SYNCBUSY (SERCOM0_BASE+0x1C)
#define SERCOM0_DATA (SERCOM0_BASE+0x28)
#define STK_CSR 0xE000E010
#define STK_RVR 0xE000E014
#define STK_CVR 0xE000E018
#define STK_MASK 0x00FFFFFF
#define ACTLR 0xE000E008
#define CPUID 0xE000ED00
#define NVMCTRL_BASE 0x41004000
#define NVM_CTRLA (NVMCTRL_BASE+0x00)
#define NVM_CTRLB (NVMCTRL_BASE+0x04)
#define NVM_PARAM (NVMCTRL_BASE+0x08)
#define NVM_INTFLAG (NVMCTRL_BASE+0x14)
#define NVM_STATUS (NVMCTRL_BASE+0x18)
#define NVM_ADDR (NVMCTRL_BASE+0x1C)
#define NVM_LOCK (NVMCTRL_BASE+0x20)
//------------------------------------------------------------------------
static void clock_init ( void )
{
unsigned int ra;
ra=GET32(OSC8M);
ra&=~(3<<8);
PUT32(OSC8M,ra);
}
//------------------------------------------------------------------------
#ifdef USE_SERCOM0
//TX PA10 SERCOM0 PAD[2] FUNCTION C SERCOM2 PAD[2] FUNCTION D
//RX PA11 SERCOM0 PAD[3] FUNCTION C SERCOM2 PAD[3] FUNCTION D
//------------------------------------------------------------------------
static void uart_init ( void )
{
unsigned int ra;
ra=GET32(APBCMASK);
ra|=1<<2; //enable SERCOM0
PUT32(APBCMASK,ra);
PUT32(GCLK_GENCTRL,0x00010605);
PUT16(GCLK_CLKCTRL,0x4514);
PUT8(PORTA_PINCFG10,0x01);
PUT8(PORTA_PINCFG11,0x01);
PUT8(PORTA_PMUX05,0x22);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT32(SERCOM0_CTRLA,0x00000000);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT32(SERCOM0_CTRLA,0x00000001);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT32(SERCOM0_CTRLA,0x40310004);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT32(SERCOM0_CTRLB,0x00030000);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT16(SERCOM0_BAUD,50436);
while(GET32(SERCOM0_SYNCBUSY)) continue;
PUT32(SERCOM0_CTRLA,0x40310006);
while(GET32(SERCOM0_SYNCBUSY)) continue;
}
//------------------------------------------------------------------------
//static void uart_flush ( void )
//{
//while(1)
//{
//if(GET8(SERCOM0_INTFLAG)&2) break;
//}
//}
//------------------------------------------------------------------------
static void uart_send ( unsigned int d )
{
while(1)
{
if(GET8(SERCOM0_INTFLAG)&1) break;
}
PUT8(SERCOM0_DATA,d&0xFF);
}
//------------------------------------------------------------------------
//static unsigned int uart_recv ( void )
//{
//while(1)
//{
//if(GET8(SERCOM0_INTFLAG)&4) break;
//}
//return(GET8(SERCOM0_DATA)&0xFF);
//}
//------------------------------------------------------------------------
#else
//TX PB22 SERCOM5 PAD[2] PORT FUNCTION D
//RX PB23 SERCOM5 PAD[3] PORT FUNCTION D
//------------------------------------------------------------------------
static void uart_init ( void )
{
unsigned int ra;
ra=GET32(APBCMASK);
ra|=1<<7; //enable SERCOM5
ra|=1<<2; //enable SERCOM0
PUT32(APBCMASK,ra);
PUT32(GCLK_GENCTRL,0x00010605);
PUT16(GCLK_CLKCTRL,0x4519);
PUT8(PORTB_PINCFG22,0x01);
PUT8(PORTB_PINCFG23,0x01);
PUT8(PORTB_PMUX11,0x33);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT32(SERCOM5_CTRLA,0x00000000);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT32(SERCOM5_CTRLA,0x00000001);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT32(SERCOM5_CTRLA,0x40310004);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT32(SERCOM5_CTRLB,0x00030000);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT16(SERCOM5_BAUD,50436);
while(GET32(SERCOM5_SYNCBUSY)) continue;
PUT32(SERCOM5_CTRLA,0x40310006);
while(GET32(SERCOM5_SYNCBUSY)) continue;
}
//------------------------------------------------------------------------
//static void uart_flush ( void )
//{
//while(1)
//{
//if(GET8(SERCOM5_INTFLAG)&2) break;
//}
//}
//------------------------------------------------------------------------
static void uart_send ( unsigned int d )
{
while(1)
{
if(GET8(SERCOM5_INTFLAG)&1) break;
}
PUT8(SERCOM5_DATA,d&0xFF);
}
//------------------------------------------------------------------------
//static unsigned int uart_recv ( void )
//{
//while(1)
//{
//if(GET8(SERCOM5_INTFLAG)&4) break;
//}
//return(GET8(SERCOM5_DATA)&0xFF);
//}
//------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------
static void hexstrings ( unsigned int d )
{
//unsigned int ra;
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x20);
}
//------------------------------------------------------------------------
static void hexstring ( unsigned int d )
{
hexstrings(d);
uart_send(0x0D);
uart_send(0x0A);
}
//------------------------------------------------------------------------
static void flash_busy ( void )
{
while(1)
{
if(GET8(NVM_INTFLAG)&(1<<0)) break;
}
}
//------------------------------------------------------------------------
static void flash_command ( unsigned int cmd )
{
PUT16(NVM_CTRLA,0xA500+cmd);
flash_busy();
}
//------------------------------------------------------------------------
#define FLASH_ER 0x02
#define FLASH_WP 0x04
#define FLASH_UR 0x41
#define FLASH_PBC 0x44
#define FLASH_INVALL 0x46
//------------------------------------------------------------------------
int notmain ( void )
{
unsigned int ra;
unsigned int addr;
unsigned int page_size;
unsigned int row_size;
unsigned int pages;
unsigned int rows;
clock_init();
uart_init();
hexstring(0x12345678);
hexstring(GET32(ACTLR));
hexstring(GET32(CPUID));
hexstring(GET32(NVM_PARAM));
ra=GET32(NVM_PARAM);
pages=ra&0xFFFF;
page_size=(ra>>16)&7;
page_size=8<<page_size;
row_size=page_size<<2;
rows=pages>>2;
hexstring(pages);
hexstring(page_size);
hexstring(rows);
hexstring(row_size);
flash_busy();
flash_command(FLASH_INVALL); //where do you use this if at all?
for(addr=0x0000;addr<0x8000;addr+=0x100)
{
hexstrings(addr); hexstring(GET8(NVM_INTFLAG));
PUT32(NVM_ADDR,addr);
flash_command(FLASH_UR); //unlock
flash_command(FLASH_ER); //erase row
}
for(ra=0x0000;ra<0x0040;ra+=4)
{
hexstrings(ra); hexstring(GET32(ra));
}
if(1)
{
flash_command(FLASH_INVALL); //where do you use this if at all?
flash_command(FLASH_PBC); //page buffer clear
for(addr=0x0000,ra=0;ra<(0x800>>2);ra++,addr+=4)
{
if((addr&0x3F)==0) hexstring(addr);
PUT32(addr,rom[ra]);
if((addr&0x3F)==0x3C) flash_busy();
}
for(ra=0x0000;ra<0x0040;ra+=4)
{
hexstrings(ra); hexstring(GET32(ra));
}
}
return(0);
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
因为几乎所有有用的 SWD/JTAG 调试器都允许您在 ram 中下载和运行程序,但并不是所有的调试器都内置了对闪存所有编程细微差别的支持,我个人的偏好是在ram 携带一个有效载荷,它是 flash 程序,它在应用程序中对其进行编程,这样任何调试器都可以使用。如果两者都没有足够的 ram,或者使用 ram 程序来刻录引导加载程序,然后使用引导加载程序来刻录更大的应用程序,那么我会编写一个引导加载程序。
sram.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
ldr r0,stacktop
mov sp,r0
bl notmain
b hang
.thumb_func
hang: b .
.align
stacktop: .word 0x20001000
.thumb_func
.globl PUT8
PUT8:
strb r1,[r0]
bx lr
.thumb_func
.globl PUT16
PUT16:
strh r1,[r0]
bx lr
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET8
GET8:
ldrb r0,[r0]
bx lr
.thumb_func
.globl GET16
GET16:
ldrh r0,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.thumb_func
.globl dummy
dummy:
bx lr
.end
sram.ld
MEMORY
{
ram : ORIGIN = 0x20000000, LENGTH = 0xD00
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
关于arm - 无法删除 samd21 微 Controller 闪存的第一页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44500021/
我是一名优秀的程序员,十分优秀!