原创 复位不稳定 LPC ARM 从用户代码进入ISP模式

2011-4-18 10:00 6521 9 9 分类: MCU/ 嵌入式

内容取自NXP AN10356: Entering ISP mode from user code

文档信息


  关键词:ARM ISP, bootloader
  摘要:进入ISP模式通常是在复位过程中采样某个引脚完成的。这篇应用笔记叙述了一个从正在运行的用户代码中进入ISP模式的方法。

1、简介


  在系统编程[In-System programming (ISP)]是一种利用bootloader软件和串行端口来编程与擦除片上Flash或RAM存储器的方法。ISP部分可以存在于最终用户系统中。Flash bootloader提供了编程片上Flash或RAM存储器的在系统编程接口。这个bootloader在Flash存储器的高8kB地址空间,用户可以读出这些ISP代码但是无法写入或者擦除它们。在很多情况下,用户也许想在运行过程中不复位芯片就能够进入ISP模式。这篇应用笔记叙述了利用少量代码便可实现这个目的的一个方法。

2、LPC2000 ISP综述


  Flash bootloader代码在芯片每次上电或复位都执行。该loader可以执行ISP命令处理程序或者执行用户应用程序代码。复位后,P0.14引脚上的<COLOR="RED">低电平被认为是由外部硬件请求启动ISP命令处理程序。bootloader在复位过程中采样该引脚电平。
  假设在Reset引脚的复位电平上升沿产生时X1引脚出现合适的信号,在P0.14引脚被采样并作出继续执行用户代码或ISP处理程序决定之前,有长达3毫秒的时间。如果P0.14采样为<COLOR="RED">低电平且看门狗溢出标志被置位,那么外部硬件的启动ISP命令处理程序请求将被忽略。如果没有执行ISP命令处理程序的外部请求(复位后P0.14采样为高电平),bootloader会进行有效用户代码的搜索。当搜索到有效的用户程序时,bootloader将执行控制权将转交给它。若未找到有效的用户程序,则执行自动波特率例程。由于P0.14被用作ISP的硬件请求,因此需要特别注意。在复位后P0.14为高阻态,重要的一点是用户必须提供外部硬件(一个上拉电阻或者其它设备)令该引脚处于一个确定状态。否则可能导致芯片意外进入ISP模式。

3、从用户代码进入ISP模式


  从用户代码进入ISP模式的具体步骤如下:

  • 将RXD0(UART 0的接收脚)配置为输入引脚。这可以通过往PINSEL0和IODIR0寄存器填入合适的值来实现。
  • 将P0.14配置为输出引脚。
  • 清零P0.14(置为低电平)
  • 通过设置VIC中断使能清除寄存器(0xFFFF F014地址处的VICIntEnClear)中相应位来禁能之前使能的中断。
  • 若已连接PLL,断开它(强烈建议)。
  • 如果需要,将外设总线分频器设置为1/4。
  • 若UART使用了分数波特率发生器则应将分数分频寄存器(FDR)设置为它的复位值(这在下面的代码中没有体现)。
  • 恢复定时器1为它的复位状态。定时器1被用来实现ISP自动波特率。
  • 将中断向量重映射到引导块。
  • 通过调用位于bootloader入口处的函数,即0x00处的复位向量来执行bootloader。

  完成上术操作的代码如下:

#define MEMMAP (*((volatile unsigned int *) 0xE01FC040))
#define IODIR0 (*((volatile unsigned int *) 0xE0028008))
#define IOCLR0 (*((volatile unsigned int *) 0xE002800C))
#define PINSEL0 (*((volatile unsigned int *) 0xE002C000))
#define VPBDIV (*((volatile unsigned int *) 0xE01FC100))
#define PLLCON (*((volatile unsigned int *) 0xE01FC080))
#define PLLFEED (*((volatile unsigned int *) 0xE01FC08C))
#define VICINTENCLR (*((volatile unsigned int *) 0Xfffff014))
#define TIMER1_PR (*((volatile unsigned int *) 0xE000800C))
#define TIMER1_MCR (*((volatile unsigned int *) 0xE0008014))
#define TIMER1_CCR (*((volatile unsigned int *) 0xE0008028))

void (*bootloader_entry)(void);
unsigned long temp;

void init(void)
{
temp = PINSEL0;
/* Connect RXD0 & TXD0 pins to GPIO */
PINSEL0 = temp & 0xFFFFFFF3;

/* Select P0.14 as an output and P0.1 as an input */
temp = IODIR0;
temp = temp | 0x4000;
temp = temp & 0xFFFFFFFD;
IODIR0 = temp;

/* Clear P0.14 */
IOCLR0 = 0x4000;

/* Disable Interrupts in the VIC*/
VICINTENCLR=0X…;

/*
Disconnect PLL if you want to do ISP at crystal frequency.
Otherwise you need to pass the PLL freq when bootloader goes in
ISP mode.
cclk = crystal when PLL is disconnected
cclk = PLL freq when PLL is connected.
Disconnecting the PLL is recommended. */
PLLCON = 0x0;
PLLFEED = 0xAA;
PLLFEED= 0x55;

/*
Set the VPB divider to 1/4 if your application changes the VPBDIV value.
The bootloader is hard-coded to use the reset value of VPBDIV register
VPBDIV = 0x0;
*/
/* Restore reset state of Timer1 */
TIMER1_PR=0x0;
TIMER1_MCR=0x0;
TIMER1_CCR=0x0;

/* Map bootloader vectors */
MEMMAP = 0x0;
/* Point to bootloader entry point i.e. reset vector 0x0 */
bootloader_entry = (void (*)(void))(0x0);
}

/*
Invoke the bootloader
The bootloader will read pin P0.14 to detect if ISP is forced
Since P0.14 is configured as an output and set to 0, the bootloader
will go in ISP mode.
*/
int main(void)
{
init();
while(1)
bootloader_entry();
}

LPC系列ARM如何确定用户代码是有效的

  LPC系列ARM的BootLoader确定芯片已写入有效用户代码的判据:ARM中断向量表中的保留位置(0x0000 0014)处应该为其余中断向量校验和的2的补码。这样一来,所有中断向量的校验和才为零。在上电启动后,LPC系列芯片内置的Boot Locader在这个条件满足时向程序计数器PC填入0x0000 0000将控制权移交给用户代码。

  我们如何实现这个校验和?难道每编译一次程序都要手工计算并填入吗?不必担心,目前流行的支持LPC系列ARM芯片的Flash编程工具(包括调试器和ISP程序)都内建了上述校验特性。也就是说,当编程软件导入用户目标代码之后,它会对中断向量表进行计算并将合适的值填充到保留位置(0x0000 0014),之后才编程芯片。

  常见的LPC系列芯片ISP工具如:Flash Magiclpc21isp

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条