ARM

作者:linuxer

来源:蜗窝科技

一、前言

本文主要分析linux-4.4.6/arch/arm64/include/asm目录下的若干和地址翻译相关的头文件(例如page.h、pgtable.h、pgtable-hwdef.h、pgtable-prot.h等文件)中的各种宏定义以及相关的ARM64硬件知识。硬肯ARM ARM文档有时候太费劲,结合linux源代码会让学习变得简单一些。

二、ARM64地址翻译概述

ARM64定义了若干个translation regimes,下面的每一行地址翻译过程都是一个translation regimes:

Secure EL3 VA ----------- Secure EL3 stage 1 -----------> PA, Secure or Non-secure

Secure EL1&EL0 VA ----------- Secure EL1&EL0 stage 1 -----------> PA, Secure or Non-secure

Non-Secure EL2 VA ----------- Non-Secure EL2 stage 1 -----------> PA, Non-secure only

Non-Secure EL1&0 VA ------ stage 1 -----> IPA ------ stage 2 -----> PA, Non-secure only

translation regime可能包括一个stage,也可能包括两个stage。每个exception level都有自己的独立一套的地址翻译的机制,使用不同的页表基地址寄存器和控制寄存器。地址翻译可以细分到stage,大部分的EL包括一个stage的地址翻译过程, Non-Secure EL1&0包括了2个stage的地址翻译过程。每个stage都有自己独立的一系列Translation tables,每个stage都能独立的enable或者disable。每个stage都是将输入地址(可能是虚拟地址或者IPA)翻译成输出地址(可能是物理地址或者IPA)。

对于一个stage的地址翻译而言,也不是一蹴而就的,而是分成若干个level,每个level都是根据内存中的Translation table(我们将PGD,PUD,PMD和Page table统称Translation table)将整个VA中的部分地址翻译出来,一个简单的示意图如下(来自ULK3):

当然,上图是基于x86,对于ARM64,cr3寄存器应该是TTBRx寄存器,PGD也就是Level 0 translation table、PUD相当于Level 1 translation table、PMD对应Level 2 translation table、Page Table对应Level 3 translation table。

Linear Address是X86特有的地址类型,对于ARM64,Linear Address应该被修改为VA或者IPA,具体ARM64地址翻译单元要处理的地址类型如下:

(1)虚拟地址(Virtual Address,简称VA)。MMU的存在可以让各个进程生活在自己的虚拟地址空间中,因此,在进程在进行数据操作的时候(内存操作指令),在进程逻辑跳转的时候(指令地址)都是使用的虚拟地址。更具体的说,进程正文段程序位于虚拟地址之上,进程的数据段、stack和heap都是位于虚拟地址之上,因此CPU的PC、LR、SP、ELR等都是指向了虚拟地址。

(2)Intermediate Physical Address,简称IPA。IPA是计算机虚拟化之后引入的一个概念,传统的计算机系统都是虚拟地址直接映射到物理地址,但是,对于支持虚拟化的计算机系统,每一个guest OS不能直接将虚拟地址映射到整个系统的物理地址,而是映射到一个受限的物理地址空间上,而且映射是随着VM的创建而创建,一旦VM销毁,这些物理内存还需要返回给Hypervisor。因此在支持虚拟化的计算机系统中,guest OS负责将VA映射到IPA,而Hypervisor负责将IPA映射到具体的物理地址上去。

(3)物理地址(Physical Address,简称PA)。物理地址是实实在在的地址,体现在实际的电路中。如果CPU和memory chip是通过bus连接,那么物理地址就是bus上的地址信号线。实际的物理地址空间被分成了两个世界,一个是Normal world,另外一个是Secure world,虽然物理地址一样,但是却通往不同的memory cell。

三、如何确定page table level?

定义如下:

#define ARM64_HW_PGTABLE_LEVELS(va_bits) (((va_bits) - 4) / (PAGE_SHIFT - 3))

从这个宏定义可以看出,两个输入参数就可以确定page table level。其中一个参数就是PAGE_SHIFT(也就是page size了),另外一个va_bits,也就是虚拟地址的bit数目。为何公式这么怪异呢?3和4又是什么鬼?为了回答这个问题,我们先看看一些具体的例子好了。我们还是先用最经典的4K page为例来描述。一旦确定了4K的page size,那么页偏移所占用的bit数就确定了,即[11:0]这12个地位bit用来确定页内偏移。此外,一个Translation table往往占用一个page的size,由于ARM64中,一个page table中的描述符是8个字节,因此4K中有512个描述符,因此各级index(指向PGD/PUD/PMD/PT)占用的bit数都是9个,综上所述,48bit的虚拟地址在4K page的情况下,4级映射的地址分配如下:

高16bit用来确定选用TTBR0或者TTBR1的Translation tables。中间的bit被平均分成4个9-bit的段,分别用来索引到PGD/PUD/PMD/PT中的具体的描述符。

如果page size是64K的话,那么offset需要16个bit,一个Translation table占有64K,每个描述符8B,总共有8K个entry,需要13个bit做为index,这时候使用3级映射,地址分配如下:

这时候,由于是3级映射,PGD和PUD是重合的。此外需要说明的是PGD(或者PUD)中只有64个entry,其他的都是无效的。

OK,搞定了4K和64K page size之后,我们来看看16K size的情况。16K的页对应的offset的bit数目是14个bit,而index需要的bit是11个bit(即每个16K的Translation table中有2K个entry)。这时候使用4级映射,地址分配如下:

因此,经过上面的三个例子之后,我们可以回头看看ARM64_HW_PGTABLE_LEVELS这个宏定义了,该宏定义中的3其实是和描述符的size相关的,对于ARM64,描述符的size是8个字节,因此PAGE_SHIFT - 3实际上描述了中间level的translation table所占据的虚拟地址的bit数目。也就是说,从虚拟地址的LSB开始,先切掉 PAGE_SHIFT 个bit做为页内偏移,然后按照PAGE_SHIFT - 3来切其他的中间的各个中间level的translation table所占据的虚拟地址的bit数目。因此,page table levels 应该等于 DIV_ROUND_UP((va_bits - PAGE_SHIFT), (PAGE_SHIFT - 3)),也就是((((va_bits) - PAGE_SHIFT) + (PAGE_SHIFT - 3) - 1) / (PAGE_SHIFT - 3)),简单的数学运算之后就得到了(((va_bits) - 4) / (PAGE_SHIFT - 3))。

在linux kernel中,具体支持的配置请参考下面的表格:

四、如何定义各个level的地址bit偏移

在linux paging model中,PGD_SHIFT、PUD_SHIFT和PMD_SHIFT用来定义定义各个Translation table在虚拟地址上的偏移量,这些定义都借用了一个ARM64_HW_PGTABLE_LEVEL_SHIFT的宏定义,如下:

#define ARM64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3)

我们用下面的表格来表述虚拟地址偏移的定义(4 level page table):

从上面的表格可以看出,如果是4级映射都在,对于L0而言,该level的SHIFT值应该是3 x (PAGE_SHIFT - 3) + PAGE_SHIFT。对于L1而言,该level的SHIFT值应该是2 x (PAGE_SHIFT - 3) + PAGE_SHIFT。以此类推L2和L3的。假设用n来表示level,那么Ln的SHIFT值应该是((4 - n) - 1) * (PAGE_SHIFT - 3) + PAGE_SHIFT,经过简单的数学运算之后可以得到(4 - n) * (PAGE_SHIFT - 3) + 3。当然,如果page table的level没有那么多,那么情况也类似,只不过少了PUD和PMD而已。我们用下面的表格来表述3 level page table中虚拟地址偏移的定义:

2 level page table的情况请自行补脑。

五、Translation table中的一个描述符对应多大的地址空间呢?

对于Level 3 translation table而言(也就是linux paging model中的page table),一个描述符就指向一个page,因此相关定义如下:

#ifdef CONFIG_ARM64_64K_PAGES
#define PAGE_SHIFT 16
#elif defined(CONFIG_ARM64_16K_PAGES)
#define PAGE_SHIFT 14
#else
#define PAGE_SHIFT 12
#endif
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))

PAGE_SIZE定义了一个page的大小,可能是4K,16K或者64K。PAGE_MASK是地址掩码,可以屏蔽掉虚拟地址offset域的那些地址bits。

对于Level 2 translation table而言(也就是PMD),当page level大于2的时候(也就是说page level是3或者4的时候),定义如下:

#if CONFIG_PGTABLE_LEVELS > 2
#define PMD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(2)
#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))
#define PTRS_PER_PMD PTRS_PER_PTE
#endif

PMD_SHIFT包括了虚拟地址中的offset域和table域,PMD_SIZE定义了PMD中的一个描述能mapping的地址空间的size。PMD_MASK是地址掩码,可以mask掉虚拟地址level 3 以及offset域的那些地址bits。

page level小于等于2的时候(也就是说page level是1或者2的时候,当然,目前ARM64中不支持page level等于1的情况),相关定义如下:

#define PMD_SHIFT PUD_SHIFT
#define PTRS_PER_PMD 1
#define PMD_SIZE (1UL << PMD_SHIFT)
#define PMD_MASK (~(PMD_SIZE-1))

也就是说,PMD_SHIFT跟随PUD_SHIFT(当然,这时候其实PUD也不存在,是说L2变成了PGD)。对于Level 1 translation table而言(也就是PUD),当page level大于3的时候(也就是说page level是4的时候),定义如下:

#if CONFIG_PGTABLE_LEVELS > 3
#define PUD_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(1)
#define PUD_SIZE (_AC(1, UL) << PUD_SHIFT)
#define PUD_MASK (~(PUD_SIZE-1))
#define PTRS_PER_PUD PTRS_PER_PTE
#endif

当page level小于等于3的时候(也就是说page level是3或者2的时候),相关定义如下:

#define PUD_SHIFT PGDIR_SHIFT
#define PTRS_PER_PUD 1
#define PUD_SIZE (1UL << PUD_SHIFT)
#define PUD_MASK (~(PUD_SIZE-1))

也就是说,PUD_SHIFT跟随PGDIR_SHIFT。而PGD相关的定义如下:

#define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - CONFIG_PGTABLE_LEVELS)
#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
#define PTRS_PER_PGD (1 << (VA_BITS - PGDIR_SHIFT))

PGDIR_SHIFT其实可以确定最高层那个level的Translation table(TTBR指向的那个Translation table)中的一个描述符能够mapping多大size的地址空间(参考PGDIR_SIZE的定义)。具体这个top level的Translation table是那个呢?根据硬件手册的描述,可能是L0,可能是L1,也可能是L2,和page level的配置有关。具体的关系是4 - CONFIG_PGTABLE_LEVELS,也就是说,如果CONFIG_PGTABLE_LEVELS等于4,那么top level的Translation table就是L0,如果CONFIG_PGTABLE_LEVELS等于3,那么top level的Translation table就是L1。

OK,我们一起来整理一下ARM64上的具体映射关系,如下图所示:

当page level等于4的时候,映射关系是PGD(L0)--->PUD(L1)--->PMD(L2)--->Page table(L3)--->page。当page level等于3的时候,没有PUD,这时候映射关系是PGD(L1)--->PMD(L2)--->Page table(L3)--->page。当page level等于2的时候,没有PUD和PMD,映射关系是PGD(L2)--->Page table(L3)--->page。

最后,闲聊一下PTRS_PER_PTE、PTRS_PER_PMD、PTRS_PER_PUD和PTRS_PER_PGD。PTRS_PER_PGD定义了PGD中有多少个描述符,当然,有多少个描述符是和Global Dir bits的长度相关,也就是VA_BITS - PGDIR_SHIFT。而其他的PTRS_PER_XXX都是描述相应translation table中描述符的个数,对于ARM64,PTRS_PER_PMD和PTRS_PER_PUD(如果存在的话)中的描述符个数基本是是固定的,和PTRS_PER_PTE保持一致,定义如下:
#define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3))

六、Translation table相关的宏定义

在内核中,pte_t,pmd_t,pud_t和pgd_t分别描述了page table(L3),PMD(L2),PUD(L1)和PGD(L0)中一个描述符的数据结构,对于ARM64而言其类型就是U64。pgprot_t也是U64,描述了各个Translation table中一个描述符中的flag域。根据ARM硬件手册,Translation table中的描述符可能有四种情况:

(1)是table descriptor,指向下一级的Translation table

(2)是page descriptor,指向一个PAGE size的地址区域

(3)是block descriptor,指向一个Block size的地址区域

(4)无效描述符

对于L0,L1和L2级别的tranlation table而言,其描述符的定义如下:

我们选择L1为例子来看看内核代码(其他的定义大家自己看source code吧,灰常类似):

#define PUD_TYPE_TABLE (_AT(pudval_t, 3) << 0)
#define PUD_TABLE_BIT (_AT(pgdval_t, 1) << 1)
#define PUD_TYPE_MASK (_AT(pgdval_t, 3) << 0)
#define PUD_TYPE_SECT (_AT(pgdval_t, 1) << 0)

描述符中,bit 0是表示该描述符是否是一个有效描述符,bit 1表示该描述符的类型。0b01是block descriptor,0b11是table描述符。L0,L1和L2的描述符不可能指向page descripotr。

这里我们还要具体讲讲什么是block。根据上文的描述,VA到PA的映射的最小力度就是page size(4K,16K或者64K),不过在有些情况下,例如kernel image对应地址空间的翻译,即便64K的page size也显得比较小(更大的mapping粒度意味着更高的TLB hit,从而提高性能),这时候,有一个叫做section的概念被提出了(ARM手册的术语是block),具体定义如下:

#define SECTION_SHIFT PMD_SHIFT
#define SECTION_SIZE (_AC(1, UL) << SECTION_SHIFT)
#define SECTION_MASK (~(SECTION_SIZE-1))

什么是section呢?我用一个实际的例子来描述好了。假设VA是48 bit,page size是4K,那么,在地址映射过程中,地址被分成9(level 0) + 9(level 1) + 9(level 2) + 9(level 3) + 12(page offset),对于kernel image这样的big block memory region,使用4K的page来mapping有点得不偿失,在这种情况下,可以考虑让level 2的Translation table entry指向一个2M 的memory region,而不是下一级的Translation table。所谓的section map就是指使用2M的为单位进行映射。对于其他的VA配置和page size的情况请大家自行理解吧,都是类似的。

对于L3级别的tranlation table而言,其描述符的定义和上图非常类似,只不过0b01是reserved,0b11是page描述符。L3的描述符不可能指向block descripotr或者table descriptor。具体定义如下:

#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
#define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0)
#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
#define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1)

参考文献:

1、ULK3 第二章

2、ARM Architecture Reference Manual(ARMv8, for ARMv8-A architecture profile)

围观 681

一、ARM中异常中断的类型:

异常中断名称 含义 复位(Reset)

当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行。复位异常中断通常用在下面几种情况:

1、系统加电时

2、系统复位时

3、跳转到复位中断向量处执行,称为软复位

未定义的指令 当ARM处理器或者是系统中协处理器认为当前指令未定义时,产生未定义指令异常中断。可以通过该异常中断机制仿真浮点向量运算。

软件中断

(software interrupt SWI)

这是一个由用户定义的中断指令。可以用于用户模式下程序调用特权操作指令。在实时操作系统(RTOS)中可以通过该机制实现系统功能调用

指令预取中止

(Prefech Abort)

如果处理器预取指令的地址不存在,或者该地址不允许当前指令访问,当该被预取的指令执行时,处理器产生指令预取中止异常中断

数据访问中止

(Data Abort)

如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断 外部中断请求(IRQ) 当处理器的外部中断请求引脚有效,而且CPSR寄存器的I控制位被清除时,处理器产生外部中断请求(IRQ)异常中断。系统中各外设通常通过该异常中断请求处理器服务 快速中断请求(FIQ) 当处理器的外部快速中断请求引脚有效,而且CPSR寄存器的F控制位被清除时,处理器产生外部中断请求(FIQ)异常中断

注:不要把异常中断类型和处理器的工作模式搞混。

复位异常发生后,进入到管理模式(svc)下。 软中断发生后,进入到管理模式(svc)下。 未定义指令异常发生后,进入到未定义指令中止模式(und)下。 指令预取中止异常发生后,进入到数据访问中止模式(abt)下; 数据访问中止异常发生后,进入到数据访问中止模式(abt)下: 外部中断发生后,进入到外部中断模式(irq)下; 快速中断发生后,进入到快速中断模式(fiq)下; 二、ARM对异常中断的响应过程

(1)ARM处理器对异常中断的响应过程:

保存处理器当前状态、中断屏蔽位以及各条件标志位。这是通过将当前程序状态寄存器CPSR的内容保存到将要执行的异常中断对应的SPSR寄存器中实现的。各异常中断有自己的物理SPSR寄存器。 设置当前程序状态寄存器CPSR中相应的位。包括:进入ARM状态;设置CPSR中的位,使处理器进入相应的执行模式;设置CPSR中的位,禁IRQ中断,当进入FIQ模式时,禁止FIQ中断。 将寄存器Ir_mode(R14)设置成返回地址。 将程序计数器值(PC),设置成该异常中断的中断向量地址,从而跳转到相应异常中断处理程序处执行。

注:以上过程全部是由硬件自动完成的。不管是在ARM状态下还是在THUMB状态下发生异常,都会自动切换到ARM状态下进行异常的处理

(2)从异常中断处理程序中返回:

恢复被中断程序的处理器状态,即将SPSR_mode寄存器内容复制到CPSR中。 返回到发生异常中断的指令下一条指令处执行,即将Ir_mode寄存器的内容复制到程序计数器PC中。

注:实际上,当异常中断发生时,程序计数器PC所指的位置对于不同的异常中断是不同的。同样,返回地址对于各种不同的异常中断也是不同的。详细见(3)

复位异常中断处理程序不需要返回。在复位异常中断处理程序开始整个用户程序的执行,因而它不需要返回。 由于异常模式不同以及ARM内核采用流水线技术,异常处理程序里要根据异常模式计算返回地址。 一条指令的执行分为:取指,译码,执行三个主要阶段,CPU由于使用流水线技术,造成当前执行指令的地址应该是PC – 8(32位机一条指令四个字节),那么执行指令的下条指令应该是PC – 4。在异常发生时,CPU自动会将将PC – 4的值保存到LR里,但是该值是否正确还要看异常类型才能决定

(3)详细:各个异常状态发生后,ARM处理器硬件响应过程

1、响应复位异常中断

上电复位:在上电后,复位使内部达到预定的状态,特别是程序跳到初始入口; 复位引脚上的复位脉冲:这是由外部其他控制信号引起的; 对系统电源检测发现过压或欠压; 时钟异常复位。

当发生复位时,处理器硬件响应中断,自动执行如下操作:

强制进入管理模式; 强制进入ARM状态; 禁止IRQ中断和FIQ中断; 跳转到绝对地址PC=0x00000000处执行

2、未定义指令异常

遇到一条无法执行的指令,此指令没有定义; 执行一条对协处理器的操作指令,在正常情况下,协处理器应该应答,但协处理器没有应答。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_und; 强制进入未定义模式; 强制进入到ARM模式; 禁止IRQ中断 把下一条指令的地址拷贝给LR; 跳转到绝对地址PC=0x00000004处执行

关于从异常中断处理程序的返回:

未定义指令异常中断是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当未定义指令异常中断发生时,处理器自动将值(pc-4)保存到lr_und中,此时(pc-4)指向当前指令的下一条指令,所以从未定义指令异常中断返回可以通过如下指令来实现:

MOV PC,LR

当异常中断处理程序中使用了数据栈时,可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用。

3、软件中断异常

是由指令SWI引起的,程序在执行这一指令后,进入异常中断。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_svc; 强制进入管理模式; 强制进入到ARM状态; 禁止IRQ中断。 把下一条指令的地址拷贝给LR; 跳转到绝对地址PC=0x00000008处执行;

关于从异常中断处理程序的返回:

软件中断异常是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当软件中断发生时,处理器自动将值(pc-4)保存到lr_siw中,此时(pc-4)指向当前指令的下一条指令,所以从软件中断返回可以通过如下指令来实现:

MOV PC,LR

当异常中断处理程序中使用了数据栈时,可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用。

4、预取指中止异常

由程序存储器引起的中止异常叫做预取指中止异常; 由数据存储器引起的中止异常叫做数据中止异常。 由于ARM的指令是3级流水线结构,读取指令周期是提前进行的,因此把读取指令的过程一般称预取指。在指令预取时,如果目标地址是非法的,该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行。有两种可能如下:

1.当执行这条指令前程序发生跳转,则这条无效指令不引起异常中断; 2.当执行到这条指令时,处理器会发生预取指中止异常,引起中断。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_abt; 强制进入中止异常模式; 强制进入到ARM状态; 禁止IRQ中断。 把中断时PC的地址拷贝给LR; 跳转到绝对地址PC=0x0000000C处执行;

关于从异常中断处理程序的返回:

在指令预取时,如果目标地址是非法的,该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行,当执行到该被标记成有问题的指令时,处理器产生指令预取中止异常中断。发生指令预取异常中断时,程序要返回到该有问题的指令处,重新读取并执行该指令,因此指令预取中止异常中断应该返回到产生该指令预取中止异常中断的指令处,而不是当前指令的下一条指令。

指令预取异常是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当指令预取中止异常中断发生时,处理器自动将值(pc-4)保存到lr_abt中,此时(pc-4)指向当前指令的下一条指令,所以从软件中断返回可以通过如下指令来实现:

SUBS PC,LR,#4

当异常中断处理程序中使用了数据栈时,可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

SUBS LR,LR,#4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用

5、数据中止异常

ARM处理器访问数据存储器时,在读取数据的同时数据存储器发出了中止信号,引起数据中止异常。 如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_abt; 强制进入中止异常模式; 强制进入到ARM状态; 禁止IRQ中断; 把中断时的PC的地址拷贝给LR; 跳转到绝对地址PC=0x00000010处执行

关于从异常中断处理程序的返回:

发生数据访问异常中断时,程序要返回到该有问题的指令处,重新访问该数据,因此数据访问异常中断应该返回到产生该数据访问中止异常中断的指令处,而不是当前指令的下一条指令。 数据访问异常中断由当前执行的指令在ALU里执行时产生,当数据访问异常中断发生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置)。此时处理器将值(pc-4)保存到lr_abt中,它指向当前指令后面第2条指令,所以返回操作可以通过下面指令实现:

SUBS PC, LR, #8

当异常中断处理程序中使用了数据栈时,可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

SUBS LR,LR,#8

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用。

6、中断请求(IRQ)异常

例如:定时器中断、串行口通讯中断、外部信号中断和A/D处理中断等。IRQ中断是可屏蔽的。在状态寄存器中的I位就是IRQ的屏蔽位。当I=1时。则屏蔽IRQ中断,当I=0时,则允许中断。处理器复位后置I为1,关闭中断。 处理器响应中断后,硬件自动执行下列操作: 把程序状态寄存器CPSR拷贝给SPSR_irq; 强制进入IRQ异常模式; 强制进入到ARM状态; 禁止IRQ中断; 把中断时的PC的地址值拷贝给LR; 跳转到绝对地址PC=0x00000018处执行;

关于从异常中断处理程序的返回:

通常处理器执行完当前指令后,查询IRQ中断引脚,并查看系统是否允许IRQ中断,如果某个中断引脚有效,并且系统允许该中断产生,处理器将产生IRQ异常中断,当IRQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置),当IRQ异常中断产生时,处理器将值(pc-4)保存到IRQ异常模式下的寄存器lr_irq中,它指向当前指令之后的第2条指令,因此正确返回地址可以通过下面指令算出:

SUBS PC,LR,#4

当异常中断处理程序中使用了数据栈时,可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

SUBS LR, LR, #4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用

注:为什么PC会指向当前执行指令的后12个字节?

当前指令执行时(此时PC指向当前指令后面的第2条指令),如果发生IRQ中断,ARM检测到IRQ中断后,取指和执行单元都不会改变,只有译码单元会改变,译码单元改为开始译码中断指令。执行完当前指令后,PC值加4个字节(此时PC指向刚刚那条指令后面的第3条指令),译码单元将译完的中断指令送到执行单元,执行单元执行中断指令,保存PC-4(此时PC指向当前指令后面的第2条指令)的值到LR_irq,同时跳转到IRQ中断向量处。(详细可看ARM流水线机制

7、快速中断(FIQ)请求异常。

FIQ快速中断是可屏蔽的。在状态寄存器中的F位就是FIQ的屏蔽位。当F=1时。则屏蔽FIQ中断,当F=0时,则允许中断。处理器复位后置F为1,关闭中断。 处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_fiq; 强制进入FIQ异常模式; 强制进入到ARM状态; 禁止FIQ中断; 把中断时的PC的地址值拷贝给LR; 跳转到绝对地址PC=0x0000001C处执行;

关于从异常中断处理程序的返回:

通常处理器执行完当前指令后,查询FIQ中断引脚,并查看系统是否允许FIQ中断,如果某个中断引脚有效,并且系统允许该中断产生,处理器将产生FIQ异常中断,当FIQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置),当FIQ异常中断产生时,处理器将值(pc-4)保存到IRQ异常模式下的寄存器lr_fiq中,它指向当前指令之后的第2条指令,因此正确返回地址可以通过下面指令算出:

SUBS PC,LR,#4

当异常中断处理程序中使用了数据栈时,成都设计公司建议可以使用下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断程序中使用的数据栈由用户提供。

SUBS LR, LR, #4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

reglist时异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器的内容复制到CPSR中,该指令只能在特权模式下使用。

注:为什么PC会指向当前执行指令的后12个字节?

当前指令执行时(此时PC指向当前指令后面的第2条指令),如果发生FIQ中断,ARM检测到FIQ中断后,取指和执行单元都不会改变,只有译码单元会改变,译码单元改为开始译码中断指令。执行完当前指令后,PC值加4个字节(此时PC指向刚刚那条指令后面的第3条指令),译码单元将译完的中断指令送到执行单元,执行单元执行中断指令,保存PC-4(此时PC指向当前指令后面的第2条指令)的值到LR_fiq,同时跳转到FIQ中断向量处。(详细可看ARM流水线机制)

围观 493

ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。

LDR伪指令的形式是“LDR Rn,=expr”。下面举一个例子来说明它的用法。

COUNT EQU 0x40003100

……

LDR R1,=COUNT

MOV R0,#0

STR R0,[R1]

COUNT是我们定义的一个变量,地址为0x40003100。这中定义方法在汇编语言中是很常见的,如果使用过单片机的话,应该都熟悉这种用法。

LDR R1,=COUNT是将COUNT这个变量的地址,也就是0x40003100放到R1中。

MOV R0,#0是将立即数0放到R0中。最后一句STR R0,[R1]是一个典型的存储指令,将R0中的值放到以R1中的值为地址的存储单元去。实际就是将0放到地址为0x40003100的存储单元中去。可 见这三条指令是为了完成对变量COUNT赋值。用三条指令来完成对一个变量的赋值,看起来有点不太舒服。这可能跟ARM的采用RISC有关。

下面还有一个例子

;将COUNT的值赋给R0

LDR R1,=COUNT

LDR R0,[R1]

LDR R1,=COUNT这条伪指令,是怎样完成将COUNT的地址赋给R1,有兴趣的可以看它编译后的结果。这条指令实际上会编译成一条LDR指令和一条DCD伪指令。

LDR 的两种用法

1)LDR pc, =MyHandleIRQ 表示将MyHandleIRQ符号放入pc寄存器中

2)LDR PC,MyHandleIRQ 表示将读取存储器中MyHandleIRQ符号所表示的地址中的值,及需要多读一次存储器。

在代码中:

start:
ldr pc,=MyHandleReset @jump to HandleReset
ldr pc,=MyHandleUndef @jump to HandleUndef
ldr pc,=MyHandleSWI @jump to HandleSWI
ldr pc,=MyHandleIabort @jump to HandleIabort
ldr pc,=MyHandleDabort @jump to HandleDabort
nop
ldr pc,=MyHandleIRQ @jump to HandleIRQ <=之前出错的一行
ldr pc,=MyHandleFIQ @jump to HandleFIQ

@MyHandleIRQ: .word OS_CPU_IRQ_ISR
MyHandleIRQ:
sub lr, lr, #4 @ to calculate the return address
stmdb sp!, {r0-r12,lr}
ldr lr, =int_return @ restore the return address
ldr pc, =int_handle @ call for the interrupt handler

在“之前出错的一行”处,如果改成“ldr pc,MyHandleIRQ”当中断来临时,无法进行中断处理。

另一种情况是正确的,注意体会:

start:
ldr pc,=MyHandleReset @jump to HandleReset
ldr pc,=MyHandleUndef @jump to HandleUndef
ldr pc,=MyHandleSWI @jump to HandleSWI
ldr pc,=MyHandleIabort @jump to HandleIabort
ldr pc,=MyHandleDabort @jump to HandleDabort
nop
ldr pc,MyHandleIRQ @jump to HandleIRQ <=之前出错的一行
ldr pc,=MyHandleFIQ @jump to HandleFIQ

MyHandleIRQ: .word OS_CPU_IRQ_ISR
@MyHandleIRQ:
@ sub lr, lr, #4 @ to calculate the return address
@ stmdb sp!, {r0-r12,lr}
@ ldr lr, =int_return @ restore the return address
@ ldr pc, =int_handle @ call for the interrupt handler

因为当中断来临时,还需要去MyHandleIRQ处把OS_CPU_IRQ_ISR取出,即多取一次存储器。

围观 454

正如汽车代替了马车,电子邮件代替了普通邮件一样,32位微控制器(MCU)让8位MCU变得黯然失色。尽管未来8位MCU朝向32位MCU发展将会成为现实,但目前还没那么容易实现。事实证明8位MCU和32位MCU仍是互补的技术,在一些方面各有千秋,而在其它方面的表现却同样出色。这其中的窍门在于厘清何种应用适合哪种MCU架构。

本文比较了8位MCU和32位MCU的使用案例,可作为如何选择这两种MCU架构的指南使用。

本文大部分32位范例将关注于ARM Cortex-M装置,Cortex-M在不同MCU供货商产品组合中表现非常相似。由于8位MCU有很多种架构,所以很难对8位供货商之间进行类似的产品比较。为了进行比较,本文将使用广泛应用、易于理解的8051 8位架构。

事实上,“ARM Cortex和8051哪个比较好”不是个逻辑问题,反而像是在问“吉他和钢琴哪个好”?真正要解决的问题是“哪种MCU最能帮助解决目前面临的问题?”。

不同的任务须使用不同的工具,使用者目的是要了解“如何才能善用所拥有的工具”,包括8位和32位装置。

对不同的装置进行比较,须要对其进行测量。有很多建构工具可供选择,本文尽量选择一些认为能够进行最公平的比较,且最能代表开发人员真实体验的情境。

以下ARM数据是透过GCC+ nanoCLibrary和-03优化选项所生成。

此一比较试验并不为任何一种装置的代码优化,只是简单实现90%开发人员都会使用的常见代码,并呈现普通开发人员所见到的结果,而不是理想状态下的结果。当然,花费诸多时间、精力和财力去调整8051代码使其表现胜过ARM是可能的,反之亦然,但一开始就选择适合该项工作的最佳工具比费尽心力做优化简单多了。

8位MCU功效持续精进

在开始对架构进行比较前,要注意到并非所有的MCU都是一样,这一点非常重要。

如果将基于ARM Cortex-M0+处理器的现代MCU与30年前的8051 MCU做对比,8051 MCU在性能上当然不会胜出。幸运的是,许多供货商一直对8位处理器持续投资。

例如芯科实验室(Silicon Labs)正持续更新基于8051核心的EFM8 MCU产品线,其效能比原始的8051架构更高,而且开发过程也已实现现代化。所以在许多应用中,8位核心能够容易弥补比M0+或M3核心不利的地方,甚至在一些方面性能更佳。

开发工具也很重要。现代嵌入式韧体开发需要全功能IDE、现成的韧体库、丰富的范例、完整的评估和入门套件,以及助手应用,以简化硬件配置、数据库管理和量产编程之类的工作。当MCU有了现代化的8位核心和开发环境时,在很多情况下,这样的MCU将超越基于ARM-Cortex的类似MCU。

以系统规模选择MCU

第一个一般性原则是:ARM Cortex-M核心更适用于较大的系统规模(>64KB代码),而8051装置适用于较小的系统规模(<8KB代码)。中等规模的系统可以选择两种方式,这取决于系统要执行的任务。须要注意的是,在大多数情况下,周边组合将会发挥重要作用。如果需要三个UART、一个LCD控制器、四个频率和两个ADC,用户可能不会在8位MCU上找到所有的周边。

易用性与成本/尺寸之比较

对于中等规模的系统来说,使用任何一种架构都可以完成工作。但主要须考虑是选择ARM核心带来的易用性,还是8051装置带来的成本和物理尺寸优势。

ARM Cortex-M架构具备统一的储存模式,并在所有常见编译程序中支持完整的C99,这使得该架构非常易于写韧体。此外,还可得到一系列数据库和第三方代码。

当然,这种易用性的代价就是成本。对于高复杂性、上市时间较短的应用或缺乏经验的韧体开发人员来说,易用性是个重要因素。

比起32位MCU,8位MCU的成本颇具优势。使用者经常会发现内建2KB/512B(Flash/RAM)的小容量8位MCU,而却很难找到低于8KB/2KB的32位MCU。在不需要很多资源的系统中,储存容量小的MCU能够让系统开发人员获得显著的成本降低。因此,对成本极为敏感或仅需较小储存容量的应用,会更倾向于选择8051解决方案。

8位芯片通常也具备物理尺寸上的优势。例如Silicon Labs提供的最小32位QFN封装为4mm×4mm,而基于8051的8位芯片的QFN封装可小至2mm×2mm。

芯片级封装(CSP)的8位和32位架构之间的差异较小,但却使成本增加,且组装较难。对于空间严格受限的应用来说,通常须要选择8051装置来满足限制要求。

通用代码/RAM效率易影响MCU成本

8051 MCU成本较低的主要原因之一是其使用Flash和RAM的效率通常比ARM Cortex-M核心更高,这允许系统采用更少资源实现。系统越大,这种影响就越小。

然而,这种8位储存资源的优势并不总是如此,这一点很重要。在某些情况下,ARM核心会像8051核心一样高效或比其更高效。例如32位运算在ARM MCU上仅需要一条指令,而在8051 MCU上则需要多条8位指令。显然,这种代码在ARM架构上有更高的执行效率。

ARM架构在Flash/RAM尺寸较小时的两个主要缺点是代码空间效率和RAM使用的可预测性。首要也是最明显的问题是通用代码空间效率。8051核心使用1字节、2字节或3字节指令,而ARM核心使用2字节或4字节指令。

通常情况下,8051指令更小,但这一优势因实际上花费许多时间而受到削弱,ARM核心比8051在一条指令下能做更多工作。32位运算就是这样一个范例。以实践来说,指令宽度是能在8051上产生适度的更密集代码。

代码空间效率

在含有分布式存取变量的系统中,ARM架构的加载/储存架构通常比指令宽度更为重要。试想讯号量的实现,一个变量需要在代码周围的多个不同位置进行减量(分配)或者增量(释放)。ARM核心必须将变量加载到缓存器,对其进行操作并重新储存,这需要三条指令。另一方面,8051核心可以直接在内存位置上进行操作,且仅需一条指令。随着每次对变量完成工作量的增大,由加载/储存而产生的消耗就变得微不足道。但对于每次仅完成一点工作的情况来说,加载/储存能产生重要影响,让8051获得明显的效率优势。

尽管讯号量在嵌入式软件中并非常见结构,但简单的计数器和标志却广泛应用于控制导向的应用中并发挥相同的作用。许多常见的MCU代码都属于这一类型。

另一个原因是ARM处理器比8051核心具有更多的自由使用堆栈。通常情况下,8051装置针对每次函数调用仅在堆栈上储存返回地址(2字节),透过通常分配给堆栈的静态变量处理大量的任务。在某些情况下,这会产生问题,因为这会造成函数默认不可重入。然而,这也意味着必须保留的堆栈空间很小,且完全可预测,这在RAM容量有限的MCU中至关重要。

举个简单的例子,试验者设计了以下程序,然后测量funcB内部的堆栈深度(图1),发现M0+核心的堆栈用了四十八个字节,而8051核心的堆栈仅用了十六个字节。当然,8051核心还静态分配了八个字节的RAM,总共用了二十四个字节。在较大的系统中,这个差异显得微不足道,但是在仅有256字节的ARM的系统中,这就变得很重要。

图1 测量funcB内部堆栈程序示意图。

架构细节之考虑

假设有基于ARM和基于8051的MCU各一个,配有所需的周边,那么对于较大的系统或需要重点考虑易用性的应用来说,ARM装置是更好的选择。如果首要考虑的是低成本/小尺寸,那么8051装置将是更好的选择。本文以下对于每种架构更擅长的应用进行更详细的分析,同时也划分出一般原则。

影响延时因素

两种架构的中断和函数调用延时存在很大差异,8051比ARM Cortex-M核心更快。

此外,高阶周边总线(APB)配备的周边也会影响延时,这是因为数据必须透过APB和AMBA高性能总线(AHB)传输。最后,当使用高频核心频率时,许多基于Cortex-M的MCU需要分配APB频率,这也增加了周边延时。

试验者做了个简单的实验,实验中的中断是透过I/O引脚触发的。该中断对引脚发出一些讯号,并根据引发中断的引脚更新标志,之后再量测其部分参数的变化。图2为此次32位Cortex-M与8051对照实验的程序代码与参数比较。

图2 测试程序代码与所得结果参数

8051核心在中断服务程序(ISR)进入和退出时显示出优势。但是,随着中断服务程序(ISR)越来越大和运行时间的增加,这些延迟将变得微不足道。和既有原则一致,系统越大,8051的优势越小。此外,如果中断服务程序(ISR)涉及到大量数据迁移或大于8位的整数数据运算,中断服务程序(ISR)运行时间的优势将转向ARM核心。例如,一个采用新样本更新16位或32位转动平均(Rolling Average)的ADC ISR可能在ARM装置上执行的更快。

文章来源 : 新电子

围观 502

一、存储器格式(字对齐):

Arm体系结构将存储器看做是从零地址开始的字节的线性组合。从零字节到三字节放置第一个存储的字(32位)数据,从第四个字节到第七个字节放置第二个存储的字数据,一次排列。作为32位的微处理器,arm体系结构所支持的最大寻址空间为4GB。

存储器格式

1、大端格式:高字节在低地址,低字节在高地址;

2、小端格式:高字节在高地址,低字节在低地址;

指令长度:

Arm微处理器的指令长度是32位的,也可以为16位(thumb状态下)。Arm微处理器中支持字节(8位),半字(16位),字(32位)三种数据类型,其中,字需要4字节对齐,半字需要2字节对齐。
注:所谓的指令长度是一条完整的指令的长度,而不是单纯的mov这3个字母长度

二、ARM体系的CPU有两种工作状态

1、ARM状态:处理器执行32位的字对齐的ARM指令;

2、Thumb状态:处理器执行16位的、半字对齐的Thumb指令;

在程序运行的过程中,可以在两种状态之间进行相应的转换。处理器工作状态的转变并不影响处理器的工作模式和相应寄存器中的内容。
CPU上电处于ARM状态

三、ARM体系的CPU有以下7种工作模式:

1、用户模式(Usr):用于正常执行程序;

2、快速中断模式(FIQ):用于高速数据传输;

3、外部中断模式(IRQ):用于通常的中断处理;

4、管理模式(svc):操作系统使用的保护模式;

5、数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储以及存储保护;

6、系统模式(sys):运行具有特权的操作系统任务;

7、未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件;

Arm的工作模式切换有两种方法:

被动切换:在arm运行的时候产生一些异常或者中断来自动进行模式切换

主动切换:通过软件改变,即软件设置寄存器来经行arm的模式切换,应为arm的工作模式都是可以通过相应寄存器的赋值来切换的。

Tips:当处理器运行在用户模式下,某些被保护的系统资源是不能被访问的。

除用户模式外,其余6种工作模式都属于特权模式;

特权模式中除了系统模式以外的其余5种模式称为异常模式;

大多数程序运行于用户模式;

进入特权模式是为了处理中断、异常、或者访问被保护的系统资源;

四、寄存器

ARM有31个通用的32位寄存器,6个程序状态寄存器,共分为7组,有些寄存器是所有工作模式共用的,还有一些寄存器专属于每一种工作模式;

R13——栈指针寄存器,用于保存堆栈指针;

R14——程序连接寄存器,当执行BL子程序调用指令时,R14中得到R15的备份,而当发生中断或异常时,R14保存R15的返回值;

R15——程序计数器;

快速中断模式有7个备份寄存器R8—R14,这使得进入快速中断模式执行很大部分程序时,甚至不需要保存任何寄存器;

其它特权模式都含有两个独立的寄存器副本R13、R14,这样可以令每个模式都拥有自己的堆栈指针和连接寄存器;

五、当前程序状态寄存器(CPSR)

CPSR中各位意义如下:

T位:1——CPU处于Thumb状态, 0——CPU处于ARM状态;

I、F(中断禁止位): 1——禁止中断, 0——中断使能;

工作模式位:可以改变这些位,进行模式切换;

六、程序状态保存寄存器(SPSR)

当切换进入某一个特权模式时,SPSR保存前一个工作模式的CPSR值,这样,当返回前一个工作模式时,可以将SPSR的值恢复到CPSR中;

七、模式切换

当异常发生,CPU进入相应的异常模式时,以下工作是由CPU自动完成的:

1、在异常模式的R14中保存前一工作模式的下一条即将执行的指令地址;

2、将CPSR的值复制到异常模式的SPSR中;

3、将CPSR的工作模式设为该异常模式对应的工作模式;

4、令PC值等于这个异常模式在异常向量表中的地址,即跳转去执行异常向量表中的相应指令;

从异常工作模式退回到之前的工作模式时,需要由软件来完成以下工作:

1、将异常模式的R14减去一个适当的值(4或8)后赋给PC寄存器;

2、将异常模式SPSR的值赋给CPSR;

文章来源:博客园

围观 201

1 – 总览

对于一个 ARM 微控制器的初学者来说,有时候要找到一些有用的设计参考信息是非常困难的一件事。因为在网上实在有太多资源了,最先遇到的困难可能就是能不能找到一个地方帮助你正确选择一款 ARM 的处理器 ,目前,主要有两种 ARM 处理器:

应用处理器 Application processors – 这些都是能跑操作系统的,比如 Linux 呀, Windows RT 啥的。典型应用就是智能手机,移动计算设备甚至服务器。 推荐用 ARM Cortex-A 系列处理器

嵌入式处理器 Embedded processors – 比较典型的包括微控制器产品,以及其他广泛的嵌入式系统。目前在微控制器市场最流行的是 ARM Cortex-M 处理器系列 ,而 Cortex-R 处理器系列常用于专用控制器,比如硬盘驱动,汽车应用以及 基带控制等。

当然最近几年来,基于 Cortex-A 的微控制器也逐渐多起来了。这些微控制器可以跑 Linux 或者 Android 。和传统的模块化电脑 COM ( computer-on-module )相比, 成本降低了很多 。

2- ARM 网站文档

在 ARM 的信息中心 ( http://infocenter.arm.com ) 可以找到大量的 ARM 技术文档。

2.1 – 应用处理器资源

如果你是一个应用处理器的开发人员,或者你想使用一个基于 ARM Cortex-A 处理器的微控制器,那么下面的文档可以帮到你:

参考 文档
1 Cortex-A Series Programmer’s Guide
2 Neon Programmer’s Guide

这些文档深入介绍了 Cortex-A 处理器的架构。如果需要了解处理器产品的概述和相关信息,也可以访问产品网页 ( http://www.arm.com/products/processors/cortex-a/index.php )

如果你需要为智能手机开发基于 Android , Linux 或者 WindowsRT 的应用软件,那么最好从相应的 SDK 文档开始( Software Development Kit 软件开发套件)。 因为经常在编程环境中,应用代码只需要利用设备驱动或者 操作系统的应用程序编程接口,而不需要直接关联底层硬件 。

2.2 – 嵌入式处理器资源

如果你对低成本和低功耗微控制器感兴趣,那么 Cortex-M 系列将是你的不二之选。

您如果访问 http://www.keil.com/learn 网页 ,就会发现ARM提供了教程,应用笔记,视频等有用的资源给Cortex-M微控制器的用户。

同时在信息中心你能找到很多嵌入式处理器的文档。比如有一系列的 Cortex-M 处理器的入门手册:

处理器 入门手册
Cortex-M7 Cortex-M7 Devices Generic User Guide
Cortex-M4 Cortex-M4 Devices Generic User Guide
Cortex-M3 Cortex-M3 Devices Generic User Guide
Cortex-M0+ Cortex-M0+ Devices Generic User Guide
Cortex-M0 Cortex-M0 Devices Generic User Guide

这些文档涵盖了编程模型,处理器内嵌外设(比如中断控制器)以及指令设置等信息。 不过,如果你需要了解其他外设,内存映射以及微控制器(系列)其他特点,还是需要阅读微控制器制造商的用户手册

此外你还可以在 ARM 网站上找到更多的相关信息。从2015年第一季度开始,Cortex-M7的相关文档也能查找了。

如果您是从ARM7切换到Cortex-M的用户,这篇文档(稍微有点老)可能对您有一些帮助: http://www.arm.com/zh/files/pdf/Cortex-M3_programming_for_ARM7_developer...

如果您是从Cortex-M4 切换到Cortex-M7 的用户, 这篇 应用笔记 可以帮到你: NEW App Note: Migrating Application Code from ARM Cortex-M4 to Cortex-M7 Processors

而如果您需要Cortex-R的编程手册,可以点击Cortex-R编程手册

要找其他的Cortex-M产品信息,请访问这个网址

Cortex-R产品的信息,则请访问这个网址

2.3 – ARM 经典处理器资源

如果您选用的是 ARM 经典处理器例如 ARM7TDMI 或者 ARM926EJ-S 同样也可以在 ARM 网站或者信息中心找到相应文档资源 ( http://www.arm.com/products/processors/classic/index.php ). 此外需要强调的是其实有很多微控制器是基于 ARM7TDMI 或者 ARM9 处理器的 . 在 ARM 网站上,您同样可以找到相应的大量技术参考手册 Technical Reference Manuals (TRM) 。

同时,还有不少第三方也提供 ARM7 微控制器的学习指导文档。比如 Hitex 免费电子内部指导手册就涵盖了一些 ARM7 的微控制器产品 ( http://www.hitex.com/index.php?id=download-insiders-guides ).

2.4 – 教育 / 教学用资源

ARM 提供非常多的免费资料用于教学,中国大学的朋友们可 以点击这个链接: ARM 大学计划

2.5 – ARM 网站上的其他资源

在 ARM 信息中心,除了产品信息和用户手册以外,您还可以找到很多:

同时,在 Keil 的网站上 ( http://www.keil.com/ ),我们为初学者提供教程和应用笔记( http://www.keil.com/learn ) 还有许多应用笔记和教程告诉您如何为一些流行的微控制器开发代码 ( 例如 http://www.keil.com/appnotes/list/arm.htm ).

3 – 其他信息和资料

3.1 – 书籍

这里可以找到 ARM 相关书籍 : http://www.arm.com/support/resources/arm-books/index.php

3.2 – 在线资源

除了 ARM 的官网,还有很多地方有不少好的资料

在 ARM 在线社区 , Alban Rampon 建立了一个 MCU resources . 的网页

Stephan Cadene 也在 LinkedIn 上建立一个有用文档的列表 :

Some links and books to begin in ARM Architectures

微控制器厂商也有很多文档,教程,应用笔记等资源。有些厂商还有自己的论坛 。

3.3 – 视频

在 Youtube 上可以找到很多 ARM 的相关视频比如 ARMflix 频道 http://www.youtube.com/user/ARMflix . ARMflix 包含很多有用的教程帮助你学习 ARM 架构和开发工具,其中也包含 介绍 ARM 架构基本原理的内容 ARM Architecture Fundamentals 由 Chris Shore 发布 ( http://www.youtube.com/watch?v=7LqPJGnBPMM ). 中国用户可以去ARM的优酷网站观看其中一部分视频,请点击:ARM视界

3.4 – 开发工具

通常当你安装一个开发套件的时候,里面就已经包含有文档了(有一些甚至还有快速学习指导文档)以及样例项目。这些可以帮助你尽快理解软件开发流程和开展项目

当然也请不要忘记到工具厂商的网站去检查一下有没有其他的应用笔记。

3.5 - mbed 开发平台

mbed 是一个易于使用并且低成本的微控制器软件开发平台帮助你开发 ARM 微控制器。 m bed 板子设计就是用来轻松上手的,并且这个开发环境提供大量的外设和中间件的 API ,你可以为你的系统找到合适的范例。建议从第二版 mbed SDK 上手, SDK 是开源的 ( mbed )

4 – 学习 AAE 和 AAME ( ARM Accredited Engineer / ARM Accredited Microcontroller Engineer )

如果你在学习 AAE or AAME ( http://www.arm.com/support/arm-accredited-engineer-program/index.php ), 你可以在 ARM 网站上找到教学大纲:

不要忘记下载学习指导 ( 注 : AAME) 这些指导会帮助你更详细地了解如何找到相应的信息

同时在 AAE 和 AAME 网页 , 你可以找到其他的参考文档列表。

5 – 总结

其实有很多资源可以帮助大家上手 ARM 的微控制器。希望这篇文章能给你一个好的启示。如果你发现了什么有用的资源,请告知我们让我们做出更新。

原文地址: Getting started with ARM Microcontroller Resources

转自:极客头条

围观 540

科技的发展,身边的智能产品越来丰富,扫地机器人、手机、VR、穿戴设备及车载仪表、导航仪等,这些产品都具备个智能的“芯”,今天,主要介绍这些“芯”的特点与联系。

ARM

ARM处理器是Acorn计算机有限公司面向低预算市场设计的第一款RISC微处理器。更早称作Acorn RISC Machine。ARM处理器本身是32位设计,但也配备16位指令集,一般来讲比等价32位代码节省达35%,却能保留32位系统的所有优势。20世纪90年代,ARM 32位嵌入式RISC(Reduced lnstruction Set Computer)处理器扩展到世界范围,占据了低功耗、低成本和高性能的嵌入式系统应用领域的领先地位。ARM公司既不生产芯片也不销售芯片,它只出售芯片技术授权。

1

MCU

MCU本质为一片单片机,指将计算机的CPU、RAM、ROM、定时计数器和多种I/O接口集成在一片芯片上,形成的芯片级的计算机。

DSP

DSP(DigitalSignalProcessing),数字信号处理,简称DSP。DSP是用数值计算的方式对信号进行加工的理论和技术。另外DSP也是Digital Signal Processor的简称,即数字信号处理器,它是集成专用计算机的一种芯片,只有一枚硬币那么大。

FPGA

FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。

SOC

SoC的定义多种多样,由于其内涵丰富、应用范围广,很难给出准确定义。一般说来, SoC称为系统级芯片,也有称片上系统,意指它是一个产品,是一个有专用目标的集成电路,其中包含完整系统并有嵌入软件的全部内容。同时它又是一种技术,用以实现从确定系统功能开始,到软/硬件划分,并完成设计的整个过程。

ARM、MCU、DSP、FPGA、SOC的比较

采用架构

● ARM:架构采用32位精简指令集(RISC)处理器架构,从ARM9开始ARM都采用了哈佛体系结构,这是一种将指令与数据分开存放在各自独立的存储器结构,独立的程序存储器与数据存储器使处理器的处理能力得到较大的提高。ARM多采用流水线技术,此技术通过多个功率部件并行工作来缩短程序执行时间,使指令能在多条流水线上流动,从而提高处理器的效率和吞吐率。现今ARM7采用了典型的三级流水线,ARM9采用五级流水线技术,而ARM11使用了7级流水线,ARM Cortex-A9更是使用了可变流水线结构(支持8-11级流水线)。在多核心的支持上ARM Cortex-A9最多可支持4个核心,这是ARM系列处理器中首次支持多核心技术。下图表示了NXP ARM体每当处理器。   

2

● MCU:大都在结构上是基于冯·诺伊曼结构的,这种结构清楚地定义了嵌入式系统所必需的四个基本部分:一个中央处理器核心,程序存储器(只读存储器或者闪存)、数据存储器(随机存储器)、一个或者更多的定时/计数器,还有用来与外围设备以及扩展资源进行通信的输入/输出端口——所有这些都被集成在单个集成电路芯片上。指令集上早期的MCU是采用CISC的,后面被RISC取代。在总线位数上,MCU覆盖了4位、8位、16位、32位,应用十分广泛。

● DSP:又名数字信号处理器,它是一种专用于实时的数字信号处理的微处理器。结构上它采用哈佛结构,同样采用流水线技术。此外,DSP被用于宿主环境时可作为直接内存存取设备运作,还支持从模拟数字转换器(ADC)获得数据,最终输出的是由数字模拟转换器(DAC)转换为模拟信号的数据,支持一定的并行处理。

● FPGA:FPGA是英文FieldProgrammable Gate Array(现场可编程门阵列)的缩写,它是在PAL、GAL、PLD等可编程器件的基础上进一步发展的产物,是专用集成电路(ASIC)中集成度最高的一种。FPGA采用了逻辑单元阵列LCA(Logic Cell Array)这样一个新概念,内部包括可配置逻辑模块CLB(Configurable Logic Block)、输出输入模块IOB(Input Output Block)和内部连线(Interconnect)三个部分。用户可对FPGA内部的逻辑模块和I/O模块重新配置,以实现用户的逻辑。它还具有静态可重复编程和动态在系统重构的特性,使得硬件的功能可以像软件一样通过编程来修改。FPGA有别于DSP、ARM、MCU的地方主要在于它的并行处理能力,它的强大并行性使复杂的运算得到极大的速度比提升。

● SOC::系统芯片是一个将计算机或其他电子系统集成单一芯片的集成电路。系统芯片可以处理数字信号、模拟信号、混合信号甚至更高频率的信号。系统芯片常常应用在嵌入式系统中。系统芯片的集成规模很大,一般达到几百万门到几千万门。SOC相对比较灵活,它可以将ARM架构的处理器与一些专用的外围芯片集成到一起,组成一个系统。其实现有的ARM处理器如Hisi-3507、hisi3516等处理器都是一个SOC系统,尤其是应用处理器它集成了许多外围的器件,为执行更复杂的任务、更复杂的应用提供了强大的支持。

功耗

● ARM:可以说ARM之所以在移动市场上得到极大的成功,其中最主要的原因便是它的低功耗。众所周知的是在移动市场上的电子产品对处理器的功耗是十分敏感的,在过去PC平台上处理器的功耗在几十W到上百W不等,这样的功耗放在移动平台上是不可想像的,ARM在主频1G的情况下功耗才几百mW,强劲的低功耗使它能适应移动电子产品。

● DSP:在与非网的一组数据上显示,在数字信号处理方面的市场占有率DSP与FPGA各得半壁江山。DSP相对于FPGA的一个优势是它的功耗相对较低,DSP生产厂商通过提高处理器的主频、努力降低功耗来保证它的市场占有率,因为在高性能的数字处理市场上FPGA似乎更占有优势。如果单纯从DSP领域上来看,DSP在功耗上、性能上做得最好的要数TI公司,TI公司的DSP处理器相对其它的DSP厂商生产的处理器成本更低、功耗更低,所以TI的DSP芯片更在竞争力。

● MCU:MCU面世时间最长,各种厂商都有它们自己的架构与指令集,如果从低功耗方面来看,TI的MSP430型MCU做得相对较好。

● FPGA:FPGA由于它的内部结构原因造成它的功耗相对较高、芯片发热量大,这也是它的一个缺点。但这也是不可避免的,在支持高性能的并发计算数字电路,且内部的逻辑门大都采用标准的宽长比,最终生成的数字电路必然会在功耗上无法与ASIC等专用处理器比较。

● SOC:由于SOC自身的灵活性,它将多个器件集成到一个极小的芯片上从而组成一个系统,SOC系统相对于MCU等处理器组成的系统来说,它在功耗上具有优势。并且,SOC芯片可在版图层面上结合工艺、电路设计等因素对系统的功耗进行系统的优化,这样比由现今外围的PCB版搭建出来的系统功耗更低,占用面积更小。

速度

● ARM:随着市场应用的需求提高,ARM厂商纷纷通过优化来提高它的主频,提升它的性能。从开始的100Mhz到惊人的2.3Ghz,ARM主频以惊人的速度向前发展。

● DSP:现今最快的主频能达到1.2Ghz。当然不能单纯从主频判断它的性能会比ARM差,DSP具有单时钟周期内完成一次乘法和一次加法的能力,一般的ARM不具备这样的能力,DSP在计算领域优势尤其明显,所以TI结合了ARM和DSP两者的优势,生产出达芬奇异构芯片,当然这是属于SOC的范畴了。

● MCU:作为低端的应用处理器,它的主频从数M到几十Mhz不等。

FPGA主频时钟最高可达几Ghz甚至上10Ghz,当然它的成本也不菲。如果将FPGA与ARM、DSP等作为比较,从主频上进行比较是没有多大意义的,毕竟并行计算的能力要远远超出一般通用的处理器采用的串行计算几十倍。如同样的一个滤波算法在主频为100Mhz的FPGA上实现要比在主频为1Ghz的ARM上实现仍要快。

应用与市场

● ARM处理器现在主要是三个系列分别为A系列、R系列、M系列,其中A系列主攻消费电子应用,应用十分广泛。

计算:上网本、智能本、输入板、电子书阅读器、瘦客户端
手机:智能手机、特色手机
数字家电:机顶盒、数字电视、蓝光播放器、游戏控制台
汽车:信息娱乐、导航
企业:激光打印机、路由器、无线基站、VOIP 电话和设备
无线基础结构:Web 2.0、无线基站、交换机、服务器

3

R系列处理器主要针对一些对实时性要求较高的应用,如航空航天、汽车电子等场合,它具备高可靠性、高可用性、高容错能力、实时响应等优点。

M系列处理器主要针对较低端的应用,它的最初目标是替换现有的市面上的MCU。

● DSP主要针对一些计算能力要求较高的应用,如视频图像处理、智能机器人、数字无线、宽带访问、数字音频、高分辨率成像和数字电机控制等。

● MCU应用最为广泛,主要利益于它的成本控制上,使它能在许多对计算能力要求不那么高的应用立足。相信在未来几年里,MCU市场关键增长驱动力将来自于绿色能源,智能电子设备,智能电网以及电子产品的升级换代比如汽车电子。

● SOC应用也十分广泛,主要是因为现有主流ARM芯片采用的架构便是SOC架构的一种,SOC是一个比较广泛的概念,现阶段许多ARM、DSP都开始采用SOC的方式来将多个器件加到处理器上组成复杂的系统。

开发成本

● ARM主要是搭载LINUX、ANDROID、WINCE等操作系统,在开发难度上看,相对MCU、DSP较难入门,它需要开发人员对操作系统有较深的了解;从成本来看,ARM的单芯片成本较MCU要高,主要还是应用于一些较为复杂的系统上。加速产品上市,降低硬件设计门槛,像周立功公司推出了一系列的核心板产品(WWW.ZLG.CN)。

4

● MCU入门最容易,上手也快,开发难度较小,并且它的成本低,在低端市场应用最为广泛。

● DSP入门较容易,但单芯片成本较高,主要还是应用于对计算能力要求高的应用。当然DSP也可以搭载操作系统,搭载操作系统后可适用于多任务的应用上。

● FPGA的开发难度较大并且开发周期也相对较长,此外它的单芯片成本很高。

来源:周立功单片机公众号

围观 392

本文介绍ARM的9种寻址方式,基础知识,需要牢固掌握,快来看一下吧。

ARM的9种寻址方式

1)立即寻址

操作数是立即数,以“#”为前缀,表示 16 进制数值时以“0x”表示。

例:

MOV R0,#0xFF00 ;0xFF00 -> R0

SUBS R0,R0,#1 ;R0 – 1 -> R0

2)寄存器寻址

操作数的值在寄存器中,指令执行时直接取出寄存器值操作。

例:

MOV R1,R2 ;R2 -> R1

SUB R0,R1,R2 ;R1 - R2 -> R0

3)寄存器偏移寻址

当第二操作数是寄存器偏移方式时,第二个寄存器操作数在与第一个操作数结合之前,选择进行移位操作。

例:

MOV R0,R2,LSL #3 ;R2 的值左移 3 位,结果放入 R0,即 R0 = R2 * 8

ANDS R1,R1,R2,LSL #3 ;R2 的值左移 3 位,然后和 R1 相与操作,结果放入 R1

可采用的移位操作:

LSL:逻辑左移(Logical Shift Left),低端空出位补 0

LSR:逻辑右移(Logical Shift Right),高端空出位补 0

ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即源操作数为正数,则高端空出位补 0,否则补 1

ROR:循环右移(Rotate Right),由低端移出位填入高端空出位

RRX:带扩展的循环右移(Rotate Right eXtended by 1 place),操作数右移一位,高端空出位用原 C 标志值填充。

各移位操作过程如图所示。

4)寄存器间接寻址

操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。

例:

LDR R1,[R2] ;将 R2 中的数值作为地址,取出此地址中的数据保存在 R1 中

SWP R1,R1,[R2] ;将R2中的数值作为地址,取出此地址中的数值与 R1 中的值**

5)基址寻址

将基址寄存器的值与偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能寄存器访问等。

例:

LDR R2,[R3,#0x0F] ;将R3中的数值加 0x0F 作为地址,取此地址的值保存在 R2 中

STR R1,[R0,#-2] ;将R0中的数值减 2 作为地址,把 R1的值保存到此地址中

6)多寄存器寻址

一次传送多个寄存器值,允许一条指令传送 16 个寄存器的任何子集或所有寄存器。多寄存器寻址时,寄存器子集按由小到大的顺序排列,连续的寄存器可用“-”连接,否则,用“,”分隔书写。

例:

LDMIA R1!,{R2-R7,R12} ;将 R1的值读出到 R2-R7,R12,过程中R1 自动加 1

STMIA R0!,{R3-R6,R10};将 R3-R6,R10的值保存到 R0 指向的地址,过程中R0 自动加 1

7)堆栈寻址

堆栈寻址使用堆栈指针SP,即R13,指向堆栈的栈顶。堆栈可分为两种:

向上生长:向高地址方向生长,称为递增堆栈,

向下生长:向低地址方向生长,称为递减堆栈,

堆栈指针指向最后压入的有效数据项,称为满堆栈,

堆栈指针指向下一个要放入的空位置,称为空堆栈,这样就有 4 种类型的堆栈。

A)满递增:堆栈地址向上增长,堆栈指针指向有效数据的最高地址。如 LDMFA,STMFA。

B)空递增:堆栈地址向上增长,堆栈指针指向堆栈上的第一个空位置。如 LDMEA,STMEA 。

C)满递减:堆栈地址向下增长,堆栈指针指向有效数据项的最低地址。如 LDMFD,STMFD。

D)空递减:堆栈地址向下增长,堆栈指针指向堆栈下的第一个空位置。如 LDMED,STMED 。

例:

STMFD SP!,{R1-R7,LR} ; 将 R1~R7,LR 入栈。满递减堆栈。

LDMFD SP!,{R1-R7,LR} ;数据出栈,放入 R1~R7,LR 寄存器。满递减堆栈。

8)块拷贝寻址

用于将一块数据从存储器的某一位置拷贝到另一位置。

例:

STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向上增长。

STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向上增长。

STMDA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向下增长。

STMDB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向下增长。

9)相对寻址

相对寻址是基址寻址的一种变通,由程序计数器 PC 提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到有效地址。

例:

BL ROUTE1 ;调用ROUTE1 子程序

BEQ LOOP ;条件跳转到 LOOP 标号处

LOOP MOV R2,#2

ROUTE1

围观 287

由于嵌入式开发环境的特殊性(交叉编译),我们会用到一些其他的外围工具,这里做简要的说明。并重新介绍一下整个开发环境中,各个工具的使用,及一个简单应用的开发流程。

SecureCRT : 串口输出显示工具、SSHclient 。

SecureCRT 是一款支持SSH(SSH1和SSH2)的终端仿真程序,同时支持Telnet和rlogin协议。

这个是最有用的吧,你看到她就会爱上她。并且是可以窗口内多标签,界面和蔼可亲的。

DNW : USB下载工具。(配合u-boot使用)

DNW 是一款USB下载传输工具,把编号的目标板的.bin二进制文件通过开发板的USB线,下载传输到板子上,通常用来传输的是编译好的Linux目标板镜像或者板子上无OS裸奔的程序,这里主要是配合bootloader使用的。需要进行传输时,在串口工具的u-boot输出菜单中选择对应的选项(比如:download Linux kernel to Nandflash),bootloader就会在目标机端(开发板端)准备好USB端口,等待在USB中数据的写入,然后,在PC端打开DNW选择要传输的文件,传输就好。传输过程中以及传输完成后,都会在串口工具窗口(也就是SecureCRT )看到串口输出的信息反馈。DNW有windows版也有Linux版,Linux下的需要自己编译并安装附带的USB驱动模块,而windows下的只用一个DNW.exe就ok了,不需要安装包安装(如果你真的想那么做的话。。。。。ps:应用USB下载即DNW下载时,需要安装USB下载驱动,开发板的光盘中都会有所附带)

DNW 在引起windows蓝屏后无法运行的问题解决如何解决?

另外需要注意:比如TQ2440出厂的U-boot,通过DNW传输时,会出现传输后没反应,然后再次选择传输文件,电脑就蓝屏了(如你所知,这肯定是在windows环境下),这样,确实很悲剧,并且你会不只一次碰到,如果你的PC足够顽强,应该不会有什么事儿的,也有可能是windows 7的兼容问题吧,上次发生是不是在XP下,我也忘了。言归正传,蓝屏后,重启系统,会出现DNW 无法运行的情况,即使你再找个dnw.exe,它还是不甩你。怎么办呢?它肯定是知道了在上次运行时你虐待它了,这是在记仇啊,记仇?它怎么记?软件么,很定时在配置文件中记的,打开C盘,在根目录下有一个dnw.ini ,这个就是它的配置文件,直接把它删了,它就会忘记你曾经对她犯下的错,又是这么小气又是这么的通情达理。。。。OK,可以正常运行了。

U-boot:强大的bootloader。

为什么把它也作为开发工具来说呢?因为学习刚开始,我们暂且还不去涉及bootloader的移植问题,而它的存在,会方便我们往开发板上烧写程序。有了它,我们可以用NFS下载镜像(程序),我们可以用USB下载镜像(程序),我们还可以用ftp下载……一劳永逸啊。为了方便开发,我们就直接把它作为我们目标板端的常用工具,暂且屏蔽到它的内部细节,这不影响我们做裸奔的接口实验,和Linux内核移植及驱动开发,过早的接触并试着去了解太多名词,会领我们有恐惧感的,是时候了解它的内部逻辑时,我们自然会接触到,万法自然,随他去吧……

Jlink :仿真器。

还要涉及一个名词是j-tag,jlink是一个外部仿真器,jtag是个内部开发调试接口。Jlink是通过jtag接口实现的一个仿真器,可以跟踪调试。目前我们用到它的可能就是来烧写u-boot了。如果用于调试的话,可以配合ADS使用,来编写裸奔程序。至于如何在空板子上烧写u-boot,各个开发板都会有详细说明,我也不费这口舌了,他们写的要比我专业的多。。。。。

好的,下边用一张图片来描述一下工具之间的配合使用。

图片只是简述了各个工具在开发过程中扮演的角色。希望画的还能让您明白。。。。

文章来源:玩转单片机

围观 469

页面

订阅 RSS - ARM