单片机
返回首页

LPC2000系列学习笔记10--Bootloader

2021-08-31 来源:eefocus

1.1 变(常)量声明

首先声明堆栈大小


SVC_STACK_LEGTH         EQU         0

    FIQ_STACK_LEGTH         EQU         0

    IRQ_STACK_LEGTH         EQU         256    ;IRQ中断堆栈

    ABT_STACK_LEGTH         EQU         0

    UND_STACK_LEGTH         EQU         0

  处理器模式声明

    NoInt       EQU 0x80


    USR32Mode   EQU 0x10

    SVC32Mode   EQU 0x13

    SYS32Mode   EQU 0x1f

    IRQ32Mode   EQU 0x12

    FIQ32Mode   EQU 0x11

  外部存储器配置声明

    PINSEL2     EQU 0xE002C014


    BCFG0       EQU 0xFFE00000

    BCFG1       EQU 0xFFE00004 

    BCFG2       EQU 0xFFE00008

    BCFG3       EQU 0xFFE0000C


    IMPORT __use_no_semihosting_swi

    IMPORT __use_two_region_memory


  ;引入的外部标号在这声明

    IMPORT  FIQ_Exception                   ;快速中断异常处理程序

    IMPORT  __main                          ; C语言主程序入口 

    IMPORT  TargetResetInit                 ;目标板基本初始化


;给外部使用的标号在这声明

    EXPORT  bottom_of_heap                  ;heap的底部

    EXPORT  bottom_of_Stacks                ;stack的底部

    EXPORT  top_of_heap                     ;heap的顶部

    EXPORT  StackUsr                        

    

    EXPORT  Reset                           ;复位

    EXPORT __user_initial_stackheap         ;用户初始化堆栈和堆


1.2 建立中断向量表(向量表所有数据32位累加和为0)

 Reset

        LDR     PC, ResetAddr               ;复位后开始的执行地址

        LDR     PC, UndefinedAddr           ;未定义指令异常           

        LDR     PC, SWI_Addr                ;软件中断

        LDR     PC, PrefetchAddr            ;预取中止

        LDR     PC, DataAbortAddr           ;预取数据中止

        DCD     0xb9205f80                  ;保留的异常

        LDR     PC, [PC, #-0xff0]           ;IRQ ( 该指令会读取VICVectAddr寄存器的值,然后放入PC指针 )

        LDR     PC, FIQ_Addr                ;FIQ


    ;给每一个向量分配连续的字存储单元

    ResetAddr           DCD     ResetInit

    UndefinedAddr       DCD     Undefined

    SWI_Addr            DCD     SoftwareInterrupt

    PrefetchAddr        DCD     PrefetchAbort

    DataAbortAddr       DCD     DataAbort

    Nouse               DCD     0

    IRQ_Addr            DCD     0

    FIQ_Addr            DCD     FIQ_Handler


    ;发生以下异常时程序暂停( 除了FIQ )

    ;未定义指令

    Undefined

            B       Undefined


    ;软中断

    SoftwareInterrupt   

            B       SoftwareInterrupt 


    ;取指令中止

    PrefetchAbort

            B       PrefetchAbort


    ;取数据中止

    DataAbort

            B       DataAbort


    ;快速中断

    FIQ_Handler

            STMFD   SP!, {R0-R3, LR}            ;把R0-R3,LR的值存入堆栈

            BL      FIQ_Exception               ;跳转到FIQ中断程序

            LDMFD   SP!, {R0-R3, LR}            ;恢复R0-R3,LR的值

            SUBS    PC,  LR,  #4                ;PC指针跳转到LR-4


1.3 复位程序

    根据外部存储器控制器的引脚接法,对GPIO进行设置(外部存储器所接引脚与P1,P2,P3口的GPIO功能复用),之后对用到的四组存储器组进行设置.

    ResetInit

    ;Initial extenal bus controller.

    ;初始化外部总线控制器,根据目标板决定配置


            LDR     R0, =PINSEL2

        IF :DEF: EN_CRP

            LDR     R1, =0x0f814910   ;芯片加密,禁止JTAG调试

        ELSE

            LDR     R1, =0x0f814914   ;设置总线的I/O引脚

        ENDIF

            STR     R1, [R0]

    ;设置四组存储器配置

            LDR     R0, =BCFG0

            LDR     R1, =0x1000ffef

            STR     R1, [R0]                 ;设置外部第0个存储区


            LDR     R0, =BCFG1

            LDR     R1, =0x1000ffef

            STR     R1, [R0]                 ;设置外部第1个存储区


    ;        LDR     R0, =BCFG2              ;该开发板没有用到后面两组存储器接口  

    ;        LDR     R1, =0x2000ffef

    ;        STR     R1, [R0]                ;设置外部第2个存储区


    ;        LDR     R0, =BCFG3

    ;        LDR     R1, =0x2000ffef

    ;        STR     R1, [R0]                ;设置外部第3个存储区


            BL      InitStack               ;初始化堆栈 Initialize the stack

            BL      TargetResetInit         ;目标板基本初始化 Initialize the target board

                                            ;跳转到c语言入口 Jump to the entry point of C program

        B       __main


1.4 堆栈初始化

    初始化各模式堆栈

InitStack    

        MOV     R0, LR;因芯片模式切换,故将程序返回地址保存到R0,同时在初始化堆栈完成后使用R0返回

;Build the SVC stack

;设置管理模式堆栈

        MSR     CPSR_c, #0xd3  

        LDR     SP, StackSvc

;Build the IRQ stack   

;设置中断模式堆栈

        MSR     CPSR_c, #0xd2

        LDR     SP, StackIrq

;Build the FIQ stack

;设置快速中断模式堆栈

        MSR     CPSR_c, #0xd1

        LDR     SP, StackFiq

;Build the DATAABORT stack

;设置中止模式堆栈

        MSR     CPSR_c, #0xd7

        LDR     SP, StackAbt

;Build the UDF stack

;设置未定义模式堆栈

        MSR     CPSR_c, #0xdb

        LDR     SP, StackUnd

;Build the SYS stack

;设置系统模式堆栈

        MSR     CPSR_c, #0xdf             ;修改为0x5d将打开IRQ中断

        LDR     SP, =StackUsr


        MOV     PC, R0                    ;子程序返回


1.5 目标板初始化

        void TargetResetInit(void)

{

// 设置存储器映射方式,这必须根据硬件来设置. 这里是ADS1.2中的设置.

#ifdef __DEBUG    

    MEMMAP = 0x3;                   //remap

#endif


#ifdef __OUT_CHIP    

    MEMMAP = 0x3;                   //remap

#endif


#ifdef __IN_CHIP    

    MEMMAP = 0x1;                   //remap,根据预定义的宏,设置存储器映射方式

#endif


/* 设置系统各部分时钟 */

    PLLCON = 1;                    ;使能PLL(锁相环),但不连接PLL

#if (Fpclk / (Fcclk / 4)) == 1

    VPBDIV = 0;

#endif

#if (Fpclk / (Fcclk / 4)) == 2

    VPBDIV = 2;

#endif

#if (Fpclk / (Fcclk / 4)) == 4

    VPBDIV = 1;

#endif                          /*设置外设时钟(VPB时钟pclk)与系统时钟(cclk)的分频比*/


#if (Fcco / Fcclk) == 2

    PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5);

#endif

#if (Fcco / Fcclk) == 4

    PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5);

#endif

#if (Fcco / Fcclk) == 8

    PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5);

#endif

#if (Fcco / Fcclk) == 16

    PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5);

#endif              /*根据PLL的电流控制振荡器和系统时钟的频率比,设置PLL的乘因子和除因子*/

    PLLFEED = 0xaa;

    PLLFEED = 0x55;     /*使用芯片要求的访问序列把数据写入PLL相关寄存器*/

    while((PLLSTAT & (1 << 10)) == 0);    /*等待PLL跟踪完成*/

    PLLCON = 3;                                // 按照特定的设置方式对PLL控制寄存器进行设置

    PLLFEED = 0xaa;

    PLLFEED = 0x55;                    /*使PLL连上系统*/

    

    /* 设置存储器加速模块 */

    MAMCR = 0;                         /*关闭MAM*/

#if Fcclk < 20000000

    MAMTIM = 1;

#else

#if Fcclk < 40000000

    MAMTIM = 2;

#else

    MAMTIM = 3;                      /*根据Fcclk的大小来设置MAM定时寄存器*/

#endif

#endif

    MAMCR = 2;                          /*使能MAM*/

    

    /* 初始化VIC */

    /* initialize VIC*/

    VICIntEnClr = 0xffffffff;           ;禁止所有中断

    VICVectAddr = 0;                    ;设置向量地址寄存器(VICVectAddr)的值为0

    VICIntSelect = 0;                   ;将所有中断设置为IRQ中断


}


1.6 其它

;/*********************************************************************************************************

;** unction name  函数名称:  __user_initial_stackheap

;** Descriptions  功能描述:  Initial the function library stacks and heaps, can not deleted!   

;**                                     库函数初始化堆和栈,不能删除

;** input parameters  输 入:    reference by function library 参考库函数手册

;** Returned value    输 出 :   reference by function library 参考库函数手册

;** Used global variables 全局变量:  None 无

;** Calling modules  调用模块:  None 无

;********************************************************************************************************/

__user_initial_stackheap    

    LDR   r0,=bottom_of_heap

;    LDR   r1,=StackUsr

    LDR   r2,=top_of_heap

    LDR   r3,=bottom_of_Stacks

    MOV   pc,lr


StackSvc           DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4

StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4

StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4

StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4

StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4


;/*********************************************************************************************************

;** unction name  函数名称:  CrpData

;** Descriptions  功能描述:  encrypt the chip

;** input parameters  输 入:    None 无

;** Returned value    输 出 :   None 无

;** Used global variables 全局变量:  None 无

;** Calling modules  调用模块:  None 无

;********************************************************************************************************/

    IF :DEF: EN_CRP

        IF  . >= 0x1fc

        INFO    1,'/nThe data at 0x000001fc must be 0x87654321./nPlease delete some source before this line.'

        ENDIF

CrpData

    WHILE . < 0x1fc

    NOP

    WEND

CrpData1

    DCD     0x87654321          ;/*When the Data is 为0x87654321,user code be protected. 当此数为0x87654321时,用户程序被保护 */

    ENDIF

    

;/* 分配堆栈空间 */

        AREA    MyStacks, DATA, NOINIT, ALIGN=2

SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  ;Stack spaces for Administration Mode 管理模式堆栈空间

IrqStackSpace      SPACE   IRQ_STACK_LEGTH * 4  ;Stack spaces for Interrupt ReQuest Mode 中断模式堆栈空间

FiqStackSpace      SPACE   FIQ_STACK_LEGTH * 4  ;Stack spaces for Fast Interrupt reQuest Mode 快速中断模式堆栈空间

AbtStackSpace      SPACE   ABT_STACK_LEGTH * 4  ;Stack spaces for Suspend Mode 中止义模式堆栈空间

UndtStackSpace     SPACE   UND_STACK_LEGTH * 4  ;Stack spaces for Undefined Mode 未定义模式堆栈



        AREA    Heap, DATA, NOINIT

bottom_of_heap      SPACE   1


        AREA    StackBottom, DATA, NOINIT

bottom_of_Stacks    SPACE   1


        AREA    HeapTop, DATA, NOINIT

top_of_heap


        AREA    Stacks, DATA, NOINIT

StackUsr

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 光控电路设计与分析

  • IGBT模块通过控制门极阻断过电流

  • CCFL的工作原理及电子驱动电路解析

  • 开关电源的基本组成及工作原理

  • 基于M66T旋律发​​生器的电路图解析

  • 基于CA3193的热电偶放大器电路

    相关电子头条文章