周立功NXP LPC21xx22xx 系列ARM启动代码和分散加载程序分解
- 格式:docx
- 大小:67.84 KB
- 文档页数:33
周立功NXP LPC21xx/22xx系列ARM芯片的启动程序分解 2008.11.25 zhongcw1002@ 作者:钟常慰关于LPC2200启动程序分散加载描述文件的叙述在ADS LPC2200的启动模板中有一个scf文件夹,其中有mem_a.scf、mem_b.scf、mem_c.scf这3个文件,这3个文件是ADS的分散加载机制,其目的是将代码段和数据段分别定位到指定地址上。
可以在Arm Linker中选择加载路径。
分散装载技术概述:分散装载技术可以把用户的应用程序分割成多个RO(只读)运行域和RW(可读写)运行域(一个存储区域块),并且给它们制定不同的地址。
一个嵌入式系统中,Flash、16位RAM、32位RAM都可以存在于系统中,所以,将不同功能的代码定位在特定的位置会大大地提高系统的运行效率。
下面是最为常用的2种情况:1、32位的RAM运行速度很快,因此就把中断服务程序作为一个单独的运行域,放在32位的RAM,使它的响应时间达到最快。
2、程序在RAM中运行,其效率要远远高于在ROM中运行,所以将启动代码(Boot loader)以外的所有代码都复制在RAM中运行,可以提高运行效率。
分散装载技术主要完成了2个基本的功能:如何分散。
就是如何将输入段组成输出段和域。
如何装载。
就是确定装载域和运行域在存储空间里的地址是多少。
域可以分为装载域和运行域装载域描述运行前输出段和域在ROM/RAM里的分布状态,运行域描述了运行时输出段和域在ROM/RAM里的分布状态。
大多数情况下,映像文件在执行前把它装载到ROM里,而当运行时,RWRAM里,程序才能正常运行,所以,在装载和运行时,RW类的输出段处在不同的位置(地址空间)。
Scatterfile分散加载文件:RO:只读的代码段和常量RW:可以读写的全局变量和静态变量ZI:RW段中要被初始化为零的变量。
Scatterfile中的定义要按照系统冲定向后的存储器分布情况进行,在引导程序完成初始化任务后,应该把主程序转移到RAM中运行以加快系统的运行速度。
LPC2114/2124/2212/2214使用指南1.介绍 (10)1.1 概述 (10)1.2 特性 (10)1.3 应用 (11)1.4 器件信息 (11)1.5 结构概述 (11)1.6 ARM7TDMI-S处理器 (12)1.7 片内FLASH程序存储器 (12)1.8 片内静态RAM (12)1.9 LPC2114/2124/2212/2214寄存器 (13)2. LPC2114/2124/2212/2214存储器寻址 (22)2.1 存储器映射 (22)2.2 LPC2114/2124/2212/2214存储器重新映射和BOOT BLOCK (26)2.2.1 存储器映射概念和操作模式 (26)2.2.2 存储器的重新映射 (26)2.3 预取指中止和数据中止异常 (28)3. 外部存储器控制器(EMC) (28)3.1 特性 (28)3.2 概述 (29)3.3 管脚描述 (29)3.4 寄存器描述 (29)3.4.1 存储器组配置寄存器0-3(BCFG0-3 - 0xFFE00000-0C) (30)3.5 外部存储器接口 (31)3.6 典型总线时序 (33)3.7 外部存储器选择 (33)4. 系统控制模块 (34)4.1 系统控制模块功能汇总 (34)4.2 管脚描述 (34)4.3 寄存器描述 (35)4.4 晶体振荡器 (35)4.5 外部中断输入 (38)4.5.1 寄存器描述 (38)4.5.2 外部中断标志寄存器(EXTINT - 0xE01FC140) (38)4.5.3 外部中断唤醒寄存器(EXTWAKE - 0xE01FC144) (39)4.5.4 外部中断方式寄存器(EXTMODE – 0xE01FC148) (40)4.5.5 外部中断极性寄存器(EXTPOLAR – 0xE01FC14C) (40)4.5.6 多个外部中断管脚 (41)4.6 存储器映射控制 (41)4.6.1 存储器映射控制寄存器(MEMMAP – 0xE01FC040) (41)4.6.2 存储器映射控制的使用注意事项 (42)4.7 PLL(锁相环) (42)4.7.1 寄存器描述 (43)4.7.2 PLL控制寄存器(PLLCON – 0xE01FC080) (44)4.7.3 PLL配置寄存器(PLLCFG – 0xE01FC084) (44)4.7.4 PLL状态寄存器(PLLSTAT - 0xE01FC088) (44)4.7.5 PLL中断 (45)4.7.6 PLL模式 (45)4.7.7 PLL馈送寄存器(PLLFEED – 0xE01FC08C) (45)4.7.8 PLL和掉电模式 (46)4.7.9 PLL频率计算 (46)4.7.10 确定PLL设定的过程 (46)4.7.11 PLL举例 (47)4.8 功率控制 (47)4.8.1 寄存器描述 (48)4.8.2 功率控制寄存器(PCON – 0xE01FC0C0) (48)4.8.3 外设功率控制寄存器(PCONP – 0xE01FC0C4) (48)4.9 功率控制注意事项 (49)4.10 复位 (49)4.11 VPB分频器 (51)4.11.1 VPBDIV寄存器(VPBDIV - 0xE01FC100) (51)4.12 唤醒定时器 (52)5. 存储器加速模块(MAM) (53)5.1 介绍 (53)5.1.1 存储器加速器模块 (53)5.1.2 Flash存储器组 (54)5.1.3 指令锁存和数据锁存 (54)5.1.4 Flash编程问题 (54)5.2 存储器加速器模块的操作模式 (55)5.3 MAM配置 (55)5.4 寄存器描述 (55)5.4.1 MAM控制寄存器(MAMCR - 0xE01FC000) (56)5.4.2 MAM定时寄存器(MAMTIM - 0xE01FC004) (56)5.5 MAM使用注意事项 (57)6. 向量中断控制器(VIC) (57)6.1 特性 (57)6.2 描述 (57)6.3 寄存器描述 (59)6.4 VIC寄存器 (60)6.4.1 软件中断寄存器(VICSoftInt - 0xFFFFF018,读/写) (60)6.4.2 软件中断清零寄存器(VICSoftIntClear - 0xFFFFF01C,只写) (60)6.4.3 所有中断状态寄存器(VICRawIntr - 0xFFFFF008,只读) (61)6.4.4 中断使能寄存器(VICIntEnable - 0xFFFFF010,读/写) (61)6.4.5 中断使能清零寄存器(VICIntEnClear - 0xFFFFF014,只写) (61)6.4.6 中断选择寄存器(VICIntSelect - 0xFFFFF00C,读/写) (61)6.4.7 IRQ状态寄存器(VICIRQStatus - 0xFFFFF000,只读) (61)6.4.8 FIQ状态寄存器(VICFIQStatus - 0xFFFFF004,只读) (62)6.4.9 向量控制寄存器0-15(VICVectCnt l0-15 - 0xFFFFF200-23C,读/写) (62)6.4.10 向量地址寄存器0-15(VICVectAddr0-15 - 0xFFFFF100-13C,读/写) (62)6.4.11 默认向量地址寄存器(VICDefVectAddr - 0xFFFFF034,读/写) (62)6.4.12 向量地址寄存器(VICVectAddr - 0xFFFFF030,读/写) (63)6.4.13 保护使能寄存器(VICProtection - 0xFFFFF020,读/写) (63)6.5 中断源 (63)6.6 伪中断 (65)6.6.1 伪中断的详述和个案 (66)6.7 VIC使用事项 (67)7. 管脚配置 (69)7.1 LPC2114/2124的管脚分布 (69)7.2 LPC2114/2124的管脚描述 (69)7.3 LPC2212/2214的管脚分布 (74)7.4 LPC2212/2214的管脚描述 (74)8. 管脚连接模块 (80)8.1 应用 (80)8.2 描述 (81)8.3 寄存器描述 (81)8.3.1 管脚功能选择寄存器0(PINSEL0 - 0xE002C000) (81)8.3.2 管脚功能选择寄存器1(PINSEL1 - 0xE002C004) (82)8.3.3 管脚功能选择寄存器2(PINSEL2 - 0xE002C014) (83)8.3.4 管脚功能选择寄存器值 (84)8.4 144脚封装的引导控制 (85)9. GPIO (85)9.1 特性 (85)9.2 应用 (85)9.3 管脚描述 (85)9.4 寄存器描述 (86)9.4.1 GPIO管脚值寄存器(IO0PIN - 0xE0028000,IO1PIN – 0xE0028010,IO2PIN –0xE0028020,IO3PIN – 0xE0028030) (86)9.4.2 GPIO输出置位寄存器(IO0SET - 0xE0028004,IO1SET – 0xE0028014,IO2SET – 0xE0028024,IO3SET – 0xE0028034) (88)9.4.3 GPIO输出清零寄存器(IO0CLR - 0xE002800C,IO1CLR – 0xE002801C,IO2CLR – 0xE002802C,IO3CLR – 0xE002803C) (88)9.4.4 GPIO方向寄存器(IO0DIR - 0xE0028008,IO1DIR – 0xE0028018,IO2DIR –0xE0028028,IO3DIR – 0xE0028038) (88)9.5 GPIO使用注意事项 (89)10. UART 0 (89)10.1 特性 (89)10.2 管脚描述 (89)10.3 寄存器描述 (90)10.3.1 UART0接收器缓存寄存器(U0RBR - 0xE000C000,DLAB=0,只读) (90)10.3.2 UART0发送器保持寄存器(U0THR - 0xE000C000,DLAB=0,只写) (91)10.3.3 UART0除数锁存LSB寄存器(U0DLL - 0xE000C000,DLAB=1) (91)10.3.4 UART0除数锁存MSB寄存器(U0DLM - 0xE000C004,DLAB=1) (91)10.3.5 UART0中断使能寄存器(U0IER - 0xE000C004,DLAB=0) (91)10.3.6 UART0中断标识寄存器(U0IIR - 0xE000C008,只读) (92)10.3.7 UART0 FIFO控制寄存器(U0FCR - 0xE000C008) (93)10.3.8 UART0线控制寄存器(U0LCR - 0xE000C00C) (94)10.3.9 UART0线状态寄存器(U0LSR - 0xE000C014,只读) (94)10.3.10 UART0高速缓存寄存器(U0SCR – 0Xe000C01C) (95)10.4 结构 (95)11. UART1 (97)11.1 特性 (97)11.2 管脚描述 (97)11.3 寄存器描述 (98)11.3.1 UART1接收器缓存寄存器(U1RBR - 0xE0010000,DLAB=0,只读) (98)11.3.2 UART1发送器保持寄存器(U1THR - 0xE0010000,DLAB=0,只写) (99)11.3.3 UART1除数锁存LSB寄存器(U1DLL - 0xE0010000,DLAB=1) (99)11.3.4 UART1除数锁存MSB寄存器(U1DLM - 0xE0010004,DLAB=1) (99)11.3.5 UART1中断使能寄存器(U1IER - 0xE0010004,DLAB=0) (99)11.3.6 UART1中断标识寄存器(U1IIR - 0xE0010008,只读) (100)11.3.7 UART1 FIFO控制寄存器(U1FCR - 0xE0010008) (101)11.3.8 UART1线控制寄存器(U1LCR - 0xE001000C) (102)11.3.9 UART1 Modem控制寄存器(U1MCR - 0xE0010010) (102)11.3.10 UART1线状态寄存器(U1LSR – 0Xe0010014,只读) (103)11.3.11 UART1 Modem状态寄存器(U1MSR - 0x0E0010018) (104)11.3.12 UART1高速缓存寄存器(U1SCR - 0xE001001C) (105)11.4 结构 (105)12. I2C接口 (106)12.1 特性 (106)12.2 应用 (107)12.3 描述 (107)12.3.1 I2C操作模式 (107)12.3.1.1 主发送器模式: (107)12.3.1.2 主接收器模式 (108)12.3.1.3 从接收器模式 (109)12.3.1.4 从发送器模式 (110)12.4 管脚描述 (110)12.5 寄存器描述 (111)12.5.1 I2C控制置位寄存器(I2CONSET - 0xE001C000) (111)12.5.2 I2C控制清零寄存器(I2CONCLR – 0xE001C018) (112)12.5.3 I2C状态寄存器(I2STAT - 0xE001C004) (113)12.5.4 I2C数据寄存器(I2DAT - 0xE001C008) (113)12.5.5 I2C从地址寄存器(I2ADR - 0xE001C00C) (113)12.5.6 I2C SCL占空比寄存器(I2SCLH - 0xE001C010和I2SCLL - 0xE001C014)11313. SPI接口 (116)13.1 特性 (116)13.2 描述 (116)13.2.1 SPI概述 (116)13.2.2 SPI数据传输 (116)13.2.3 SPI外设描述 (117)13.2.3.1 概述 (117)13.2.3.2 主机操作 (118)13.2.3.3 从机操作 (118)13.2.3.4 异常状况 (119)13.3 管脚描述 (120)13.4 寄存器描述 (120)13.4.1 SPI控制寄存器(S0SPCR - 0xE0020000, S1SPCR - 0xE0030000) (121)13.4.2 SPI状态寄存器(S0SPSR - 0xE0020004, S1SPSR - 0xE0030004) (121)13.4.3 SPI数据寄存器(S0SPDR - 0xE0020008,S1SPDR – 0xE0030008) (121)13.4.4 SPI时钟计数寄存器(S0SPCCR - 0xE002000C,S1SPCCR – 0xE003000C) (122)13.4.5 SPI中断寄存器(S0SPINT - 0xE002001C,S1SPINT – 0xE003001C) (122)13.5 结构 (122)14. 定时器0和定时器1 (123)14.1 特性 (123)14.2 应用 (123)14.3 描述 (124)14.4 管脚描述 (124)14.5 寄存器描述 (124)14.5.1 中断寄存器(IR: 定时器0 - T0IR:0xE00040000;定时器1 - T1IR:0xE0008000) (125)14.5.2 定时器控制寄存器(TCR: 定时器0 – T0TCR:0xE0004004;定时器1 –T1TCR:0xE0008004) (126)14.5.3 定时器计数器(TC: 定时器0 – T0TC:0xE0004008;定时器1 – T1TC:0xE0008008) (126)14.5.4 预分频寄存器(PR: 定时器0 – T0PR:0xE000400C;定时器1 – T1PR:0xE000800C) (126)14.5.5 预分频计数器寄存器(PC: 定时器0 – T0PC:0xE0004010;定时器1 –T1PC:0xE0008010) (126)14.5.6 匹配寄存器(MR0 - MR3) (127)14.5.7 匹配控制寄存器(MCR: 定时器0 – T0MCR:0xE0004014;定时器1 –T1MCR:0xE00080014) (127)14.5.8 捕获寄存器(CR0 - CR3) (127)14.5.9 捕获控制寄存器(CCR: 定时器0 – T0CCR:0xE0004028;定时器1 –T1CCR:0xE0008028) (127)14.5.10 外部匹配寄存器(EMR: 定时器0 – T0EMR:0xE000403C;定时器1 –T1EMR:0xE0008003C) (128)14.5.11 定时器举例操作 (129)14.6 结构 (130)15. 脉宽调制器(PWM) (130)15.1 特性 (131)15.2 描述 (131)15.2.1 单边沿控制的PWM输出规则 (135)15.2.2 双边沿控制的PWM输出规则 (135)15.3 管脚描述 (135)15.4 寄存器描述 (135)15.4.1 PWM中断寄存器(PWMIR - 0xE0014000) (137)15.4.2 PWM定时器控制寄存器(PWMTCR - 0xE0014004) (137)15.4.3 PWM定时器计数器(PWMTC - 0xE0014008) (137)15.4.4 PWM预分频寄存器(PWMPR - 0xE001400C) (137)15.4.5 PWM预分频计数器寄存器(PWMPC - 0xE0014010) (138)15.4.6 PWM匹配寄存器(PWMMR0 –PWMMR6) (138)15.4.7 PWM匹配控制寄存器(PWMMCR - 0xE0014014) (138)15.4.8 PWM控制寄存器(PWMPCR - 0xE001404C) (139)15.4.9 PWM锁存使能寄存器(PWMLER - 0xE0014050) (140)16. A/D转换器 (141)16.1 特性 (141)16.2 描述 (141)16.3 管脚描述 (141)16.4 寄存器描述 (141)16.4.1 A/D控制寄存器(ADCR – 0xE0034000) (143)16.4.2 A/D数据寄存器(ADDR – 0xE0034004) (144)16.5 操作 (144)16.5.1 硬件触发转换 (144)16.5.2 时钟产生 (144)16.5.3 中断 (144)16.5.4 精度和数字接收器 (144)17. 实时时钟 (145)17.1 特性 (145)17.2 描述 (145)17.3 结构 (145)17.4 寄存器描述 (146)17.5 RTC中断 (147)17.6 混合寄存器组 (147)17.6.1 中断位置(ILR - 0xE0024000) (147)17.6.2 时钟节拍计数器(CTC - 0xE0024004) (147)17.6.3 时钟控制寄存器(CCR - 0xE0024008) (148)17.6.4 计数器增量中断 (148)17.6.5 报警屏蔽 (148)17.7 完整时间寄存器 (149)17.7.1 完整时间寄存器0(CTIME0 - 0xE0024014) (149)17.7.2 完整时间寄存器1(CTIME1 - 0xE0024018) (149)17.7.3 完整时间寄存器2(CTIME2 - 0xE002401C) (150)17.8 时间计数器组 (150)17.8.1 闰年计算 (150)17.9 报警寄存器组 (151)17.10 RTC使用注意事项 (151)17.11 基准时钟分频器(预分频器) (151)17.11.1 预分频整数寄存器(PREINT - 0xE0024080) (152)17.11.2 预分频小数寄存器(PREFRAC - 0xE0024084) (152)17.11.3 预分频器的使用举例 (152)17.11.4 预分频器操作 (153)18. 看门狗 (154)18.1 特性 (154)18.2 应用 (154)18.3 描述 (154)18.4 寄存器描述 (154)18.4.1 看门狗模式寄存器(WDMOD - 0xE0000000) (155)18.4.2 看门狗定时器常数寄存器(WDTC - 0xE0000004) (155)18.4.3 看门狗喂狗寄存器(WDFEED - 0xE0000008) (156)18.4.4 看门狗定时器值寄存器(WDTV - 0xE000000C) (156)18.5 方框图 (156)19. FLASH存储器系统和编程 (157)19.1 FLASH存储器系统 (157)19.2 FLASH BOOT装载程序 (157)19.3 特性 (157)19.4 应用 (157)19.5 描述 (157)19.5.1 通信协议 (159)19.5.1.1 ISP命令格式 (159)19.5.1.2 ISP响应格式 (159)19.5.1.3 ISP数据格式 (159)19.5.1.4 ISP流程控制 (159)19.5.1.5 ISP命令中止 (159)19.5.1.6 ISP过程中的中断 (159)19.5.1.7 IAP过程中的中断 (159)19.5.1.8 ISP命令处理器使用的RAM (159)19.5.1.9 IAP命令处理器使用的RAM (160)19.5.1.10 RealMonitor使用的RAM (160)19.6 BOOT处理流程图 (160)19.7 扇区数 (161)19.8 代码读保护 (162)19.8.1 ISP命令 (163)19.8.1.1 解锁<解锁代码> (163)19.8.1.2 设置波特率<波特率> <停止位> (164)19.8.1.3 回声<设定> (164)19.8.1.4 写RAM<起始地址> <字节数> (164)19.8.1.5 读存储器<地址> <字节数> (165)19.8.1.6 准备写操作的扇区<起始扇区号> <结束扇区号> (165)19.8.1.7 将RAM内容复制到Flash <Flash地址> <RAM地址> <字节数>..16619.8.1.8 运行<地址><模式> (166)19.8.1.9 擦除扇区<起始扇区号><结束扇区号> (167)19.8.1.10 扇区查空<起始扇区号><结束扇区号> (167)19.8.1.11 读器件ID (167)19.8.1.12 读Boot代码版本 (168)19.8.1.13 比较<地址1><地址2><字节数> (168)19.8.2 IAP命令 (169)19.8.2.1 准备编程扇区 (171)19.8.2.2 将RAM内容复制到Flash (171)19.8.3 擦除扇区 (172)19.8.3.1 扇区查空 (172)19.8.3.2 读器件ID (172)19.8.3.3 读Boot代码版本 (173)19.8.3.4 比较 (173)19.9 JTAG Flash编程接口 (174)20. EmbeddedICE逻辑 (174)20.1 特性 (174)20.2 应用 (174)20.3 描述 (174)20.4 管脚描述 (176)20.5 复用管脚的复位状态 (176)20.6 寄存器描述 (176)20.7 方框图 (177)21. 嵌入式跟踪宏单元 (177)21.1 特性 (177)21.2 应用 (177)21.3 描述 (178)21.3.1 ETM配置 (178)21.4 管脚描述 (178)21.5 复用管脚的复位状态 (179)21.6 寄存器描述 (179)21.7 方框图 (181)22. REALMONITOR (181)22.1 特性 (181)22.2 应用 (181)22.3 描述 (182)22.3.1 RealMonitor部件 (182)22.3.1.1 RMHost (182)22.3.1.2 RMTarget (182)22.3.2 RealMonitor是如何工作的 (183)22.4 如何使能RealMonitor (184)22.4.1 增加堆栈 (184)22.4.1.1 IRQ模式 (185)22.4.1.2 未定义模式 (185)22.4.1.3 SVC模式 (185)22.4.1.4 预取指中止模式 (185)22.4.1.5 数据中止模式 (185)22.4.1.6 用户/系统模式 (185)22.4.1.7 FIQ模式 (185)22.4.2 处理异常 (185)22.4.2.1 RealMonitor异常处理 (185)22.4.3 RMTarget初始化 (186)22.4.4 例程 (186)22.5 RealMonitor建立选项 (189)修订记录 (191)1.介绍1.1 概述LPC2114/2124/2212/2214是基于一个支持实时仿真和跟踪的16/32位ARM7TDMI-S TM CPU的微控制器,并带有128/256 k字节(kB)嵌入的高速Flash存储器。
个人电脑已经是64位了,您还在使用8位微控制器吗?尽管一般情况下嵌入式系统对CPU处理能力的要求比个人电脑(对CPU处理能力的要求)低,但随着人们生活的提高和技术的进步,嵌入式系统对CPU处理能力的要求也稳步的提高,大量高速的与MCS51体系结构兼容的微控制器的出现就证明了这一点。
但8位微控制器受限于体系结构,处理能力的提高始终有限。
而16位系统在性能上与8位机相比始终没有太大优势,成本上与32位系统相比也没有什么优势,未来一段时间嵌入式微控制器的发展方向必然是32位系统。
基于ARM体系结构的32位系统占领了32位嵌入式系统的大部分分额,但长期以来,基于ARM体系结构的32位系统仅在嵌入式式系统的高端(通讯领域、PDA)等场合使用,要么以专用芯片的面貌出现,要么以位处理器的庙貌出现,并没有出现性价比高的通用的微控制器。
PHILIPS发现了这个空当,推出了性价比很高LPC2000系列微控制器,让更多的嵌入式系统具有32位的处理能力。
这也预示着32位系统即将成为嵌入式系统的主流。
基于ARM体系结构的芯片在中国推广已经有好几年了,关于ARM的图书也出了不少。
关于ARM的图书主要有以下几类:1.关于ARM内核的图书,主要读者是芯片设计者,内容主要是介绍芯片设计的。
2.芯片应用类图书,主要是芯片的生产商或代理商编写,主要读者为应用工程师。
3.开发板类图书,主要介绍相应的ARM开发板,给应用者一些参考。
以上3类图书的侧重点都不是ARM应用开发教学,用于大学本科教学不太适合。
为了方便高等院校教学方便,笔者编写了这本教材。
不过,因为嵌入式系统牵涉的知识太广,一本教材无法深入论述。
为此,笔者还会推出多本被套图书以便学生知识扩展。
第1章嵌入式系统概述 (1)1.1嵌入式系统 (1)1.1.1 现实中的嵌入式系统 (1)1.1.2 嵌入式系统的概念 (2)1.1.3 嵌入式系统的未来 (2)1.2嵌入式处理器 (2)1.2.1 简介 (2)1.2.2 分类 (3)1.3嵌入式操作系统 (4)1.3.1 简介 (4)1.3.2 基本概念 (5)1.3.3 使用实时操作系统的必要性 (8)1.3.4 实时操作系统的优缺点 (8)1.3.5 常见的嵌入式操作系统 (8)第2章嵌入式系统工程设计 (14)2.1嵌入式系统项目开发生命周期 (14)2.1.1 概述 (14)2.1.2 识别需求 (15)2.1.3 提出方案 (17)2.1.4 执行项目 (19)2.1.5 结束项目 (21)2.2嵌入式系统工程设计方法简介 (22)2.2.1 由上而下与由下而上 (22)2.2.2 UML系统建模 (22)2.2.3 面向对象OO的思想 (23)第3章ARM7体系结构 (25)3.1简介 (25)3.1.1 ARM (25)3.1.2 ARM的体系结构 (25)3.1.3 ARM处理器核简介 (26)3.2ARM7TDMI (27)3.2.1 简介 (27)3.2.2 三级流水线 (28)3.2.4 存储器接口 (28)3.3ARM7TDMI的模块和内核框图 (29)3.4体系结构直接支持的数据类型 (31)3.5处理器状态 (32)3.6处理器模式 (32)3.7内部寄存器 (33)3.7.1 简介 (33)3.7.2 ARM状态寄存器集 (33)3.7.3 Thumb状态寄存器集 (35)3.8程序状态寄存器 (37)3.8.1 简介 (37)3.8.2 条件代码标志 (38)3.8.3 控制位 (38)3.8.4 保留位 (39)3.9异常 (39)3.9.1 简介 (39)3.9.2 异常入口/出口汇总 (39)3.9.3 进入异常 (40)3.9.4 退出异常 (41)3.9.5 快速中断请求 (41)3.9.6 中断请求 (41)3.9.7 中止 (41)3.9.8 软件中断指令 (42)3.9.9 未定义的指令 (42)3.9.10 异常向量 (42)3.9.11 异常优先级 (43)3.10中断延迟 (43)3.10.1 最大中断延迟 (43)3.10.2 最小中断延迟 (44)3.11复位 (44)3.12存储器及存储器映射I/O (44)3.12.1 简介 (44)3.12.2 地址空间 (44)3.12.3 存储器格式 (45)3.12.4 未对齐的存储器访问 (46)3.12.5 指令的预取和自修改代码 (47)3.13寻址方式简介 (51)3.14ARM7指令集简介 (52)3.14.1 简介 (52)3.14.2 ARM指令集 (52)3.14.3 Thumb指令集 (54)3.15协处理器接口 (56)3.15.1 简介 (56)3.15.2 可用的协处理器 (56)3.15.3 关于未定义的指令 (57)3.16调试接口简介 (57)3.16.1 典型调试系统 (57)3.16.2 调试接口 (58)3.16.3 EmbeddedICE-RT (58)3.16.4 扫描链和JTAG接口 (59)3.17ETM接口简介 (59)第4章ARM7TDMI(-S)指令系统 (61)4.1ARM处理器寻址方式 (61)4.2指令集介绍 (64)4.2.1 ARM指令集 (64)4.2.2 Thumb指令集 (90)第5章LPC2000系列ARM硬件结构 (112)5.1简介 (112)5.1.1 描述 (112)5.1.2 特性 (112)5.1.3 器件信息 (113)5.1.4 结构概述 (113)5.2引脚配置 (114)5.2.1 引脚排列及封装信息 (114)5.2.2 LPC2114/2124的引脚描述 (116)5.2.3 LPC2210/2212/2214的引脚描述 (120)5.2.4 引脚功能选择使用示例 (126)5.3存储器寻址 (126)5.3.1 片内存储器 (126)5.3.3 存储器映射 (127)5.3.4 预取指中止和数据中止异常 (131)5.3.5 存储器重映射及引导块 (132)5.3.6 启动代码相关部分 (134)5.4系统控制模块 (136)5.4.1 系统控制模块功能汇总 (136)5.4.2 引脚描述 (137)5.4.3 寄存器描述 (137)5.4.4 晶体振荡器 (138)5.4.5 复位 (139)5.4.6 外部中断输入 (142)5.4.7 外部中断应用示例 (145)5.4.8 存储器映射控制 (146)5.4.9 PLL(锁相环) (148)5.4.10 VPB分频器 (153)5.4.11 功率控制 (154)5.4.12 唤醒定时器 (156)5.4.13 启动代码相关部分 (156)5.5存储器加速模块(MAM) (158)5.5.1 描述 (158)5.5.2 MAM结构 (159)5.5.3 MAM的操作模式 (160)5.5.4 MAM配置 (161)5.5.5 寄存器描述 (161)5.5.6 MAM使用注意事项 (162)5.5.7 启动代码相关部分 (162)5.6外部存储器控制器(EMC) (163)5.6.1 特性 (163)5.6.2 概述 (163)5.6.3 引脚描述 (164)5.6.4 寄存器描述 (164)5.6.5 外部存储器接口 (166)5.6.6 典型总线时序 (168)5.6.7 外部存储器选择 (168)5.6.8 启动代码相关部分 (169)5.7引脚连接模块 (170)5.7.1 介绍 (170)5.7.2 寄存器描述 (170)5.7.3 引脚功能控制 (173)5.7.4 启动代码相关部分 (173)5.8.1 特性 (175)5.8.2 描述 (175)5.8.3 结构 (176)5.8.4 寄存器描述 (177)5.8.5 中断源 (181)5.8.6 VIC使用事项 (183)5.8.7 VIC应用示例 (184)5.8.8 启动代码相关部分 (185)5.9GPIO (186)5.9.1 特性 (186)5.9.2 应用 (186)5.9.3 引脚描述 (187)5.9.4 寄存器描述 (187)5.9.5 GPIO使用注意事项 (189)5.9.6 GPIO应用示例 (189)5.10UART 0 (189)5.10.1 特性 (189)5.10.2 引脚描述 (190)5.10.3 应用 (190)5.10.4 结构 (190)5.10.5 寄存器描述 (191)5.10.6 使用示例 (198)5.11UART1 (200)5.11.1 特性 (200)5.11.2 引脚描述 (200)5.11.3 应用 (201)5.11.4 结构 (202)5.11.5 寄存器描述 (203)5.12I2C接口 (211)5.12.1 特性 (211)5.12.2 应用 (211)5.12.3 引脚描述 (211)5.12.4 I2C接口描述 (211)5.12.5 I2C操作模式 (214)5.12.6 寄存器描述 (225)5.13SPI接口 (228)5.13.1 特性 (228)5.13.2 引脚描述 (228)5.13.3 描述 (229)5.13.5 寄存器描述 (235)5.14定时器0和定时器1 (237)5.14.1 描述 (237)5.14.2 特性 (237)5.14.3 应用 (238)5.14.4 管脚描述 (238)5.14.5 结构 (239)5.14.6 寄存器描述 (239)5.14.7 定时器举例操作 (244)5.14.8 使用示例 (245)5.15脉宽调制器(PWM) (247)5.15.1 特性 (247)5.15.2 引脚描述 (248)5.15.3 描述 (248)5.15.4 结构 (249)5.15.5 寄存器描述 (251)5.15.6 使用示例 (256)5.16A/D转换器 (258)5.16.1 特性 (258)5.16.2 描述 (258)5.16.3 引脚描述 (258)5.16.4 寄存器描述 (259)5.16.5 操作 (261)5.16.6 使用示例 (261)5.17实时时钟 (262)5.17.1 特性 (262)5.17.2 描述 (262)5.17.3 结构 (262)5.17.4 RTC中断 (263)5.17.5 闰年计算 (264)5.17.6 寄存器描述 (264)5.17.7 混合寄存器组 (265)5.17.8 完整时间寄存器 (267)5.17.9 时间计数器组 (268)5.17.10 报警寄存器组 (269)5.17.11 基准时钟分频器(预分频器) (269)5.17.12 RTC使用注意事项 (271)5.17.13 使用示例 (271)5.18看门狗 (274)5.18.2 应用 (274)5.18.3 描述 (274)5.18.4 结构 (275)5.18.5 寄存器描述 (275)5.18.6 使用示例 (277)5.19本章小结 (278)第6章接口技术与硬件设计 (280)6.1最小系统 (280)6.1.1 框图 (280)6.1.2 电源 (280)6.1.3 时钟 (284)6.1.4 复位及复位芯片配置 (284)6.1.5 存储器系统 (287)6.1.6 调试与测试接口 (288)6.1.7 完整的最小系统 (289)6.2片内外设 (291)6.2.1 GPIO(通用I/O) (291)6.2.2 UART、MODEM (295)6.2.3 I2C (298)6.2.4 SPI (304)6.3总线接口 (308)6.3.1 并行SRAM (308)6.3.2 并行FALSH (314)6.3.3 USB(D12)接口 (328)6.3.4 液晶接口 (332)6.3.5 网络接口 (341)6.4其它外设 (350)6.4.1 并行打印机接口 (350)6.4.2 CF卡及IDE硬盘接口 (356)第7章移植µC/OS-II到ARM7 (362)7.1µC/OS-II简介 (362)7.1.1 概述 (362)7.1.2 µC/OS-II的特点 (362)7.2移植规划 (363)7.2.1 编译器的选择 (363)7.2.2 任务模式的取舍 (363)7.3移植µC/OS-II (363)7.3.1 概述 (363)7.3.2 关于头文件includes.h和config.h (364)7.3.3 编写OS_CPU.H (365)7.3.4 编写Os_cpu_c.c文件 (366)7.3.5 编写Os_cpu_a.s (371)7.3.6 关于中断及时钟节拍 (374)7.4移植代码应用到LPC2000 (376)7.4.1 编写或获取启动代码 (376)7.4.2 挂接SWI软件中断 (376)7.4.3 中断及时钟节拍中断 (377)7.4.4 编写应用程序 (377)7.5本章小结 (379)第8章嵌入式系统开发平台 (380)8.1如何建立嵌入式系统开发平台 (380)8.1.1 使用平台开发是大势所趋 (380)8.1.2 建立开发平台的方法 (383)8.1.3 编写自己的软件模块 (384)8.2数据队列 (384)8.2.1 简介 (384)8.2.2 API函数集 (384)8.3串口驱动 (387)8.3.1 简介 (387)8.3.2 API函数集 (387)8.4MODEM接口模块 (389)8.4.1 简介 (389)8.4.2 MODEM的状态 (389)8.4.3 API函数集 (389)8.5I2C总线模块 (390)8.5.1 简介 (390)8.5.2 API函数集 (391)8.6SPI总线模块 (392)8.6.1 简介 (392)8.6.2 API函数集 (392)第1章嵌入式系统概述1.1 嵌入式系统经过几十年的发展,嵌入式系统已经在很大程度改变了人们的生活、工作和娱乐方式,而且这些改变还在加速。
ARM芯片的启动程序的分析和总结(2009-02-04 14:35:26)转载分类:ARM标签:杂谈1、综述:目前大多基于ARM芯片的系统都是一个比较复杂的片上系统,多数硬件模块都是可配置的,可以通过软件来设置其需要的工作状态。
因此在运行用户的应用程序之前,需要由专门的一段代码来完成对系统的初始化。
这一段代码就称为启动程序。
由于这类代码直接面对处理器内核和硬件控制器进行编程,一般都是用汇编语言。
在ARM系统上电复位后,需要设置中断向量表、初始化各模式堆栈、设置系统时钟频率等,需要用ARM的汇编语言编写启动代码,由启动代码完成系统初始化以及跳转到用户C程序。
在ARM设计开发中,启动代码的编写是一个极重要的过程。
然而启动代码随具体的目标系统和开发系统有所区别,但通常包含以下部分:·向量表定义·地址重映射及中断向量表的转移·堆栈初始化·设置系统时钟频率·中断寄存器的初始化·进入C应用程序下面就结合PHILIPS的LPC2119的启动代码来分析与说明ARM7处理器的启动代码的编写。
1.1向量表定义ARM芯片上电或复位后,系统进入管理模式、ARM状态、PC(R15寄存器)指向0x00000000地址处。
中断向量表为每一个中断设置1个字的存储空间,存放一条跳转指令,通过这条指令使PC指针指向相应的中断服务程序入口,继而执行相应的中断处理程序。
LPC2119的中断向量表和其它基于ARM核的芯片中断向量表较类似,只要注意LPC2119要使向量表所有数据32位累加和为零(0x00000000-0x0000001C的8个字的机器码累加), 才能使用户的程序脱机运行。
LPC2119的中断向量表如图1所示。
1.2 地址重映射及中断向量表的转移ARM7处理器在复位后从地址0读取第一条指令并执行,因此系统上电后地址0必须是非易失的ROM/FLASH,这样才能保证处理器有正确可用的指令。
Verilog®黄金参考指南V1.0 1996年8月©版权1996Doulos保留所有权力本刊物的任何部分在得到DOULOS的书面许可前都不能通过包括电子机械影印录像或其他任何形式或任何方式复制保存在搜索系统或发布在英国和北爱尔兰印刷Verilog-XL TM是商标Verilog®是Cadence Design System Inc的注册商标DOULOSChurch Hatch,22 Market Place,Ringwood.Hampshire.BH24 1AWEngland.Tel (+44) (0)1425 471223Fax (+44) (0)1425 471573Email**************.ukURL 序言 (4)指南的使用 (4)索引 (4)用于定义Verilog语法的记号说明 (4)Verilog的简单介绍 (5)背景 (5)语言 (5)编译 (6)模块结构 (6)语句 (7)按字母顺序参考的部分 (9)Always (9)Begin (10)Case (12)编码标准 (13)注释 (14)连续赋值 (15)Defparam (16)Delay (17)设计流程 (18)Disable (18)错误 (19)事件 (20)表达式 (21)For (22)Force (23)Forever (24)Fork (25)函数 (26)函数调用 (27)门 (27)IEEE1364 (30)If (31)Initial (32)实例化 (33)模块 (35)名字 (37)线网 (38)数字 (41)运算符 (43)参数 (44)PATHPULSE$ (46)端口 (47)过程赋值 (48)过程连续赋值 (50)编程语言接口 (51)寄存器 (51)Repeat (53)保留字 (53)Specify (54)Specparam (57)语句 (57)强度 (58)字符串 (60)任务 (61)任务使能 (64)定时控制 (65)用户定义的原语 (67)While (70)编译器伪指令 (71)编译器伪指令 (71)`define (72)`ifdef (74)`timescale (74)系统任务和函数 (76)系统任务和函数 (76)$display和$write (81)$fopen和$fclose (82)$monitor等 (83)$readmemb和$readmemh (84)$strobe (85)$timeformat (86)随机建模 (86)定时检查 (89)值改变转储 (91)命令行选项 (93)命令行选项 (93)序言Verilog黄金参考指南是Verilog硬件描述语言及其语法语义合并以及将它应用到硬件设计的一个简明的快速参考指南Verilog黄金参考指南并不是要代替IEEE的标准Verilog语言参考手册它不像IEEE的标准手册提供了Verilog完整正式的描述相反黄金参考指南以一种方便的参考格式解答了在Verilog的实践应用过程中经常遇到的问题Verilog黄金参考指南也不想成为介绍性的指南这里所提出的信息是一种扼要的参考格式而不是学习像Verilog这种复杂的主题所必要的渐进和共鸣方式但必须承认的是已经熟悉计算机语言的人希望将这个参考指南作为Verilog的课本因此在开始本指南就会对这个主题进行一个简单的非正式介绍Verilog黄金参考指南的主要特征是它包含了从许多Verilog项目中积聚起来的大量实践知识指南不仅提供方便的语法参考很多类似的书也有还对最常见的语言错误提出警告在代码不能编译的时候给出线索指出要看什么地方警告你注意合并问题并对改善你的编码形式提出建议Verilog黄金参考指南是为了给Doulos的系列Verilog训练课程增值也是HDL PaceMaker Doulos Verilog计算机基础训练包的补充指南的使用本指南的主体被分成3个主要部分每个部分都按字母顺序组织每一部分都以每页顶部的关键字词条作为索引通常你只要快速翻阅指南查找相应的关键字词条的就可以找到想要的信息如果找不到也可以用最后的完整索引查找本指南的很多信息都围绕Verilog的句法组织但也有另外一些有关编码标准设计流程错误保留字以及在正文按字母顺序参考部分后面的编译器伪指令系统任务和函数以及命令行选项等特殊的部分如果你是Verilog的新手请先阅读次页的Verilog简单介绍索引粗体的索引条目在指南的主体有对应的页剩下的索引条目按重要性的顺序在字符参考部分的页参考后面用于定义Verilog语法的记号说明在任何可能的时候语法定义要写得和例子相似但有需要引入一些额外的记号简单地来说方括号[ ]包含可选的项目三个点号…表示重复花括号{ }包含的是注释斜体表示语法该部分在别处定义记号的完整描述如下包含注释的花括号{ }所不是被定义的Verilog语法的一部分但它向你提供了有关语法定义的补充信息粗体的花括号{ }是Verilog句法的一部分连接运算符包含在方括号[ ]中的语法是可选的粗体的方括号是[ ]Verilog语法的一部分矢量范围位和部分选择存储器元素…表示前面的项目或行的重复0次或者多次或者表示一个列表例如Item…表示Item重复0次或多次,…表示在用逗号分隔的列表重复例如A,B,C列表中至少有一个项目列表的结尾没有,号小写的字是保留字是Verilog语言的组成部分例如module以大写字母开头的字不是斜体是Verilog的标识符即用户定义的名字它们都不是保留的标识符例如InstanceName斜体的字是句法范畴即在别处完整给出句法名字的定义句法范畴可以在相同的页里定义也可以在独立的页定义还可以在下面定义的其中一个特殊范畴中定义斜体=表示在同一页定义和使用的句法范畴特殊的语法范畴MinTypMaxExpression以Expression定义UnsignedNumber以Number定义SomethingExpression=Expression其中Something给出有关表达式的含意信息例如ConstantExpression ConstantMinTypMaxExpressionVerilog的简单介绍下面向不懂Verilog语言的读者在技术上简要介绍一下Verilog背景Verilog硬件描述语言HDL是描述电子电路行为和结构的一种语言是一种IEEE标准IEEEStd.1364-1995Verilog用于模拟从随机和纯行为到门级和开关级的抽象范围等层次的数字电子电路功能也用于从许多抽象寄存器传输级描述合并即自动产生门级描述Verilog一般用于支持高层次的设计或基于语言的设计其中电子设计在用自动合并工具进行详细设计前要通过高层次的完全抽象仿真来检验Verilog也广泛应用于IC的门级检验包括仿真故障仿真和定时检验Verilog最初是在1984年由Gateway Design Automation公司开发Verilog-XL仿真器的时候一起开发出来1989年Cadence Design Systems公司并购Gateway公司同时拥有对Verilog语言和Verilog-XL 仿真器的权力1990年Cadence将Verilog语言不是Verilog-XL放到公共领域为了使Verilog语言通过IEEE标准化过程一个非赢利性组织Open Verilog International OVI将它不断推进结果在1995年Verilog成为一个IEEE标准此后OVI仍继续不断维护和开发这种语言语言在本部分和指南剩下的部分以大写字母开头的斜体字都是技术术语都可以在本指南的主体中找到硬件设计的层次部分在Verilog中用模块Module描述模块定义了硬件单元的接口即输入和输出及其内部结构或行为大量的原语或者门Gates都内置在Verilog语言内它们表示基本的逻辑门例如and or另外还可以定义用户定义的原语User Defined Primitives UDPs电子电路的结构通过在高层模块内对模块和原语UDPs和门举实例Instances来描述而且实例之间通过线网Nets连接线网表示一个电气连接一条线路或总线端口Port连接列表用于将线网连接到模块的端口或者连接到原语的实例其中一个端口表示一个管脚寄存器Registers见下面也可以连接到实例的输入端口只能连接到输入端口线网和寄存器的值由逻辑值01X未知或未初始化的和Z高阻或悬空组成除了逻辑值外线网还有强度Strength值强度广泛地用于开关级模型以及解释网络有超过一个驱动器的情况电子电路的行为是用Initial和Aways结构以及连续赋值Continuous Assignments描述这些结构以及UDPs和门表示设计的层次树的叶子每个Initial Always连续赋值UDP和门实例相对于所有其他结构是同时执行的Initial或Always内的语句Statements在很多方面上都和软件编程语言的语句相似它们在用定时控制Timing Controls规定的时间例如延迟以及用仿真事件控制触发执行语句在Begin-End块顺序地执行在Fork-Join块并行地执行连续赋值语句修改线网的值Initial和Aways修改寄存器的值Initial或Always可以分解成有给定变量的指定的任务Tasks和函数FunctionsVerilog语言还有大量内置的系统任务System Tasks和函数Functions编程语言接口ProgrammingLanguage Interface PLI是Verilog语言的一个组成部分它提供了一种和调用系统任务和函数相同的方法调用以C写的函数编译Verilog源代码通常输入到计算机的一个或多个文本文件中然后这些文本文件被提交到Verilog编译器或解释器编译用于仿真或合并的数据文件有时候仿真在编译后立即进行不创建中间的数据文件模块结构module M (P1, P2, P3, P4);input P1, P2;output [7:0] P3;inout P4;reg [7:0] R1, M1[1:1024];wire W1, W2, W3, W4;parameter C1 = "This is a string";initialbegin : BlockName// 语句endalwaysbegin// 语句end// 连续赋值...assign W1 = Expression;wire (Strong1, Weak0) [3:0] #(2,3) W2 = Expression;// 模块实例...COMP U1 (W3, W4);COMP U2 (.P1(W3), .P2(W4));task T1;input A1;inout A2;output A3;begin// 语句endendtaskfunction [7:0] F1;input A1;begin// 语句F1 = Expression;endendfunctionendmodule语句#delaywait (Expression)@(A or B or C)@(posedge Clk)Reg = Expression;Reg <= Expression;VectorReg[Bit] = Expression; VectorReg[MSB:LSB] = Expression; Memory[Address] = Expression; assign Reg = Expression deassign Reg;TaskEnable(...);disable TaskOrBlock;-> EventName;if (Condition)...else if (Condition)...else...case (Selection)Choice1 :...Choice2, Choice3 :...default :...endcasefor (I=0; I<MAX; I=I+1)...repeat (8)...while (Condition)...forever...这个快速参考语法摘要不遵从本指南剩余部分所使用的符号惯例Verilog黄金参考指南按字母顺序参考的部分Always包含一条或多条语句过程赋值任务使能if case和循环语句这些语句在仿真运行中重复执行由定时控制管理语法alwaysStatement在何处使用module-<HERE>-endmodule规则• always只能赋值寄存器reg integer real time realtime类型• 启动仿真时所有always都开始执行而且在仿真过程中持续执行当到达always的最后一条语句时程序返回到always的第一条语句继续执行注意• 如果Always包含超过一条语句语句要包含在begin-end或fork-join块中• 没有定时控制的always将永远循环合并always是其中一条很有用的Verilog合并语句但always通常是不合并的为了使结果最好代码应受到下面其中一种模板的限制always @(Inputs) // 所有输入begin... // 组合逻辑endalways @(Inputs) // 所有输入if (Enable)begin... // 锁存器的动作endalways @(posedge Clock) // 只是时钟begin... // 同步的动作endalways @(posedge Clock or negedge Reset)// 只是时钟和复位beginif (!Reset) // 测试异步复位的有效激活电平... // 异步行动else... // 同步行动end // 给出触发器+逻辑举例下面的例子是一个寄存器传送级alwaysalways @(posedge Clock or negedge Reset)beginif (!Reset) // 异步复位Count <= 0;elseif (!Load) // 同步载入Count <= Data;elseCount <= Count + 1;end接下来的例子是描述组合逻辑的alwaysalways @(A or B or C or D)beginR = {A, B, C, D}F = 0;begin : Loopinteger I;for (I = 0; I < 4; I = I + 1)if (R[I])beginF = I;disable Loop;endend // 循环endBegin用于组合语句使它们按顺序执行Verilog的语法通常要求例如在always中只有一条语句如果需要超过一条语句语句就要被包含在一个begin-end块内语法begin [: Label[ Declarations...]]Statements...endDeclaration = {either} Register Parameter Event在何处使用见语句规则• begin-end块必须包含至少一条语句• Begin-end块内的语句按顺序执行定时控制与前一语句有关执行完begin-end块的最后一条语句后整个begin-end块的执行也完成• Begin-end和fork-join块可在自己内部或相互之间嵌套• 如果begin-end块要包含局部声明必须先命名这个begin-end块即必须有标记• 如果要禁能一个begin-end块必须先命名这个块注意仿真中Verilog LRM允许begin-end块被交叉执行这就是说即使begin-end块包含的两个相邻语句之间没有定时控制仿真器也可以选择执行另一个过程的部分例如另一个always的语句这就是Verilog语言有不确定性的原因提示• 在没有局部声明和块不会被禁能的情况下也可以给begin-end块加上标记增加其可读性• 不会在别处使用的寄存器可以用局部声明来声明这使声明更明确举例initialbegin : GenerateInputsinteger I;for (I = 0; I < 8; I = I + 1)#Period {A, B, C} = I;endinitialbeginLoad = 0; // 时刻0Enable = 0;Reset = 0;#10 Reset =1; // 时刻10#25 Enable =1; // 时刻35#100 Load = 1; // 时刻135endCase一个语句基于case表达式的值条件地执行最多一个分支语法CaseKeyword ( Expression)Expression,... : Statement {表达式可以是变量}Expression,... : Statement... {任意数量的情况}[default [:] Statement] {不一定在结尾}endcaseCaseKeyword = {either} case casex casez在何处使用见语句规则• casex语句的X和Z以及casez语句的Z表示无关• 最多可以有一条default语句当没有标记表达式符合case表达式时执行default语句标记是在冒号左面的一个表达式或是用逗号分隔的表达式列表也可以是保留字default default后面可以有或者没有冒号• 如果标记是用逗号分隔的两个或多个表达式列表只要case表达式符合其中一个标记表达式就认为标记就符合case表达式• 如果没有标记表达式符合case表达式而且没有default语句case语句不起作用注意• 如果特殊的标记要执行超过一条语句语句必须包含在begin-end或fork-join块内• 如果相应的标记是第一个符合case表达式的标记case只会执行这个分支Case的标记不需要互斥因此当相同的标记被错误地重复使用时Verilog编译器不会报告出错• Casex和casez语句的要用保留字endcase而不是endcasex或endcasez结束• Casex表达式中的X或Z或者casez表达式的Z符合所有case的标记这会使仿真结果混淆合并• case语句内的赋值一般合并到多路复用器如果case标记使用变量例如寄存器或线网那么可以合成优先权译码器• 无时钟的always中的不完全赋值即没有指定某些输入条件的输出被合并到透明锁存器有时钟always中的不完全赋值合并到循环寄存器提示• 仿真时通常用default作为最后一条case语句以捕捉非法的情况• casez通常比casex好因为在仿真中出现X会导致产生误导或混乱的结果• casex和casez标记的Z可用字符?代替这可以清楚地表示值无关而不是高阻举例case (Address)0 : A <= 1; // 选择一个单独的地址值1 : begin // 执行超过一条语句A <= 1;B <= 1;end2, 3, 4 : C <= 1; // 选出几个地址值default : // 其他剩余的地址$display("Illegal Address value %h in %m at %t",Address, $realtime);endcasecasex (Instruction)8'b000xxxxx : Valid <= 1;8'b1xxxxxxx : Neg <= 1;defaultbeginValid <= 0;Neg <= 0;endendcasecasez ({A, B, C, D, E[3:0]})8'b1 : Op <= 2'b00;8'b010 : Op <= 2'b01;8'b00100 : Op <= 2'b10;default : Op <= 2'bxx;endcase编码标准编码标准共有两类词汇编码标准负责控制文本格式命名惯例和注释这种标准增加程序的可读性并简化维护合并编码标准控制Verilog的结构样式避免普通的合并缺陷并在设计流程的早期发现合并错误下面列出的编码标准需要根据所选的工具和个人喜好修改词汇编码标准• 将每个Verilog源文件的内容限制到一个模块不从文件分割模块• 源文件的名字应与文件内容有关例如ModuleName.v• 每行只写一条声明或语句• 使用和例子一样的缩进• 用户定义的名字要注意大小写一致例如第一个字符是大写• 尽管局部名字例如循环变量可能很简洁但用户定义的名字应当是有意义并包含信息的• 写注释来解释不是复制Verilog代码其中注释接口特别重要例如模块参数端口任务和函数变量• 在任何可能的时候用参数或`定义宏避免在声明和语句中直接嵌入文本数字和字符串合并编码标准• 将设计分割成小的功能块并为每个块使用一个行为样式除了设计的主要部分外其他部分要避免门级描述• 有定义好的时钟策略而且在Verilog明确执行该策略例如单时钟多相时钟门时钟多时钟域确保Verilog的时钟和复位信号是清楚的即不从组合逻辑或无意识的门产生• 有定义好制造好的测试策略并适当地编码Verilog例如所有触发器可复位从外部管脚进行测试无功能冗余• 所有Verilog的always应遵守标准合并处理模板的其中一个见Always• 描述组合和锁存逻辑的always必须在always顶部的事件控制列表列出所有输入• 组合的always必须不能包含不完全赋值即所有输入值的组合必须赋值给所有输出• 描述组合和锁存逻辑的always必须不能包含反馈即always中被赋值为输出的寄存器不能作为always的输入• 带时钟的always在事件控制列表中只能有时钟和异步控制输入一般是复位或置位• 避免不必要的锁存器这些多余的锁存器是由于无时钟always的不完全赋值产生• 避免不必要的触发器当用非阻塞赋值在带时钟的always内给寄存器赋值或者当寄存器在连续重复的带时钟always之间和时钟周期之间保持值不变时触发器被合并• 所有内部状态寄存器必须可复位这样寄存器传输极和门级描述在检验的时候可以复位到相同的已知状态这不能应用到流水线寄存器或同步寄存器• 对于有不能到达的状态的有限状态机器和其他时序电路例如一个4位的十进制计数器有6个不可到达的状态如果硬件在这些状态下可以被控制那么所有2N个可能的状态的行为必须在Verilog中明确描述包括不能到达的状态的行为这就允许保留状态机器进行合并• 避免在赋值中使用延时除非要求在寄存器传输级解决0延时时钟的时滞问题• 不要使用integer或time类型的寄存器否则它们会分别合并到32位总线和64位总线• 请仔细检查使用动态索引的Verilog代码即用可变的索引或地址作为位选择或存储器元素循环语句或算术运算符因为这些代码要被合并成大量难以优化的门注释可以应当在Verilog源代码中包含说明性的注释语法{单行注释}//{多行注释}/* ... */在何处使用几乎可以在任何地方使用但不能分割运算符数字字符串名字和关键字规则• 单行注释用两个斜杠字符开始在行的末端结束• 多行注释用/*开始注释可能跨过多行直到*/处结束• 多行注释不能嵌套但多行注释中可以有单行注释它们没有特别的含意注意/* ... /* ... */ ... */注释在第一个*/处结束第二个*/将被忽略这个例子无疑会出现句法错误提示全部使用单行注释只在例如在开发和调试代码的过程中需要注释大段代码时使用多行注释举例// 这是一个注释/*共有三行的多行注释*/module ALU /* 8位ALU */ (A, B, Opcode, F);连续赋值当表达式中的线网或寄存器的值改变时连续赋值在一个或多个线网创建事件语法{either}{见线网}NetLValue = {either}NetNameNetName[ConstantExpression ]NetName[ConstantExpression: ConstantExpression ]{NetLValue,...}在何处使用module-<HERE>-endmodule规则两种形式的连续赋值效果相同Assign左边的线网必须在连续赋值语句的前面的源代码中明确声明注意尽管连续赋值和过程连续赋值很相似但它们是不一样的请确保将assign放在正确的地方连续赋值在initial或always外过程连续赋值在允许使用语句的地方都可以使用initial always任务函数等的内部合并• 合并工具忽略延时和强度使用指定定时限制的工具代替• 连续赋值作为组合逻辑合并提示• 用连续赋值描述组合逻辑可以容易地用一个简单表达式描述函数可以用于组成表达式always 一般能较好地描述许多复杂的组合逻辑而且其仿真速度比用大量独立的连续赋值语句快得多• 当Verilog要求使用线网时连续赋值对传输寄存器的值到线网非常有用例如将在initial中描述的测试激励应用到模块实例的输入输出口举例wire cout, cin;wire [31:0] sum, a, b;assign {cout, sum} = a + b + cin;wire enable;reg [7:0] data;wire [7:0] #(3,4) f = enable ? data : 8'bz;Defparam编译时覆盖参数值通过使用层次名字参数值可以在设计层次内部或外部的任何地方被覆盖语法defparam ParameterName =ConstantExpression,ParameterName = ConstantExpression,... ;在何处使用module-<HERE>-endmodule合并一般不合并提示不要使用defparam它提供了一种有用的方法逆向注释布局延时但现在通常通过使用特殊的程序块和编程语言接口实现对要覆盖的参数请在模块实例化时使用#语法举例`timescale 1ns / 1psmodule LayoutDelays;defparam Design.U1.T_f = 2.7;defparam Design.U2.T_f = 3.1;...endmodulemodule Design (...);...and_gate U1 (f, a, b);and_gate U2 (f, a, b);...endmodulemodule and_gate (f, a, b);output f;input a, b;parameter T_f = 2;and #(T_f) (f,a,b);endmoduleDelay延时可以在UDP和门的实例连续赋值和线网中使用这些延时能为线网元件和连接的传播延时建模语法{either}# DelayValue#( DelayValue[, DelayValue[, DelayValue]]) {上升下降关断}DelayValue = {either}UnsignedNumberParameterNameConstantMinTypMaxExpression在何处使用见连续赋值实例化线网规则• 如果只给出一个延时的值这个值既表示上升和下降传播延时即分别从0或1跳变又表示关断延时如果可用• 如果给出两个延时的值第一个值是上升延时第二个值是下降延时但tranif0tranif1rtranif0和rtranif1除外它们的第一个值表示开启延时第二个值是关断延时• 如果给出三个延时的值第三个延时是关断延时转换到Z但trireg线网除外它的第三个延时是电荷衰减时间• X的延时是最小的指定延时• 对于矢量来说从非0到0的转换被认为是下降转换到Z是关断所有其他转换都被认为是上升注意很多工具强调延时的MintypMax表达式必须包含在括号中例如#(1:2:3)是允许的但#1:2:3是不允许的合并合并工具忽略延时合并线网列表的延时受到合并工具命令例如设置最大的时钟周期约束提示指定的块延时路径延时通常是建模延时的一种很精确的方式而且它还提供了计算延时的机制以及逆向注释布局信息设计流程使用Verilog和合并设计ASIC或复杂FPGA的基本流程如下设计流程需要进行迭代但这里不作介对于每个块写寄存器传输级Verilog边界条件分析门计数和定时对于完整的芯片Verilog或装配接线柱布局仿真故障仿真和定时分析Disable使激活的任务或有名字的块在执行完所有语句前终止其执行语法disable BlockOrTaskName;在何处使用见语句规则• 禁能一个有名字的模块begin-end或fork-join或者一个任务就禁能从该模块或任务使能的所有任务而且向下禁能到使能的任务层次然后继续执行被禁能的任务后面使能的语句或有名字的块• 有名字的模块或任务可以在自己内部用disable语句自我禁能• 当任务被禁能时下面的事件不能确定任何输出或输入输出的值仍未生效的非阻塞赋值预定的事件assign和force语句• 函数不能被禁能注意任务自我禁能与任务返回不一样因为任务自我禁能的输出没有定义合并disable只在有名字的模块或任务自我禁能时合并提示用disable可以从任务早期退出退出循环或继续下一个迭代的循环举例begin : Breakforeverbegin : Continue...disable Continue; // 继续下一个迭代...disable Break; // 退出forever循环...end // 继续end // 终止错误下面列出的是最常见的Verilog错误前五位占了所有错误的50%前5位Verilog错误• 过程赋值的左边不声明为寄存器类型• 缺少begin-end语句或begin-end语句不匹配• 二进制数缺少基’b也就是说编译器将它们看作是十进制数• 在编译器伪指令中错误使用撇号应当是后撇号或重音符号`和数字基应当是一般的单引号或倒转的逗号’• 语句的结尾缺少分号其他常见错误• 尝试在任务或函数名字后面的方括号中定义任务和函数参数• 在测试程序中测试时忘了要将模块实例化• 用过程连续赋值代替连续赋值即assign在错误的地方使用• 尝试用保留字作为标识符例如xor• Always内没有定时控制导致无限循环• 在事件控制例如@(a or b)中用逻辑或运算符||代替保留字or• 用隐式线网连接矢量端口• 模块实例中端口连接的顺序错误• 嵌套的if-else语句中有包含错误begin-end的位置不正确• 等号的形式错误=用于赋值==用于比较数字值===用于匹配01X和Z的精确序列事件事件用于在行为模型中描述通讯和同步语法event Name ,...; {声明事件}-> EventName; {触发事件}在何处使用见->的语句在以下的地方允许有事件声明module-<HERE>-endmodulebegin : Label-<HERE>-endfork : Label-<HERE>-jointask-<HERE>-endtaskfunction-<HERE>-endfunction规则事件没有值或延时它们被事件触发语句触发在跳变沿敏感的定时控制中测试合并一般不合并提示有名字的事件通常用于在测试程序和系统级模型中与相同模块或不同模块使用层次名字的always 之间通讯举例event StartClock, StopClock;alwaysforkbegin : ClockGeneratorClock = 0;@StartClockforever#HalfPeriod Clock = !Clock;end@StopClock disable ClockGenerator;joininitialbegin : stimulus...-> StartClock;...-> StopClock;...-> StartClock;...-> StopClock;end表达式表达式从一组运算符名字文本值和子表达式计算值常数表达式是在编译时可以计算值的表达式标量表达式只计算1位的值延时可以用MinTypMax表达式表示语法Expression = {either}PrimaryOperator Primary{一元运算符}Expression Operator Expression{二元运算符}Expression ? Expression : ExpressionStringPrimary = {either}NumberName {参数线网或寄存器的名字}Name[ Expression]{位选择}Name[Expression: Expression]{部分选择}MemoryName[Expression]{Expression,...}{串联}{Expression{ Expression,...}}{复制}FunctionCall( MinTypMaxExpression){延时使用MinTypMax表达式}MinTypMaxExpression = {either}ExpressionExpression: Expression: Expression规则• 只有矢量的线网和reg以及integer和time允许位和部分选择• 部分选择必须在分号的左边寻址一个比分号右边更高的位最高位是线网或寄存器声明中左边的范围表达式的值• 有X或Z或超出范围的位和部分选择可能会也可能不会被捕捉为编译器错误它们给出的表达式结果是X• 存储器没有位或部分选择机制• 当表达式用整数常数作为操作数无基但带符号的整数例如-5的处理和有基且带符号的整数例如-‘d5不一样前者作为带符号数处理后者作为无符号数处理注意很多工具要求常数MinTypMax表达式的最小典型和最大延时值有序例如min<=typ<=max举例A + B!A(A && B) || CA[7:0]B[1]-4'd12/3 // 一个很大的正数"Hello" != "Goodbye" // 表达式为真1$realtobits(r); // 系统函数调用{A, B, C[1:6]} // 并置8位1:2:3 // MinTypMaxFor通用循环语句允许一条或多条语句重复执行语法for ( RegAssignment; {初始值}Expression; {循环条件}RegAssignment) {循环值}Statement。
周立功ARM调试心得2008-9-11调试"SmartARM2200 V2.02实验箱"心得:1、在调试"E:\htwang\smart2200v201\ARM嵌入式系统实验教程(二)\开发板出厂编程程序\液晶显示程序\LCM_Disp"的程序时,想使用外部RAM进行仿真调试,在将ADS1.2中的"DebugInExram Settings->Arm Linker -> Output -> Equivalent Command Line"的"-info totals -entry 0x8100000 -scatter .\src\mem_b.scf"改为"-info totals -entry 0x80000000 -scatter .\src\mem_b.scf"时,编译时总是出现错误信息"Error: L6206E: Entry point(0x80000000) lies outside the images",经梁工(宝琼)提示:"这是由于程序空间超出范围,需要改一个参数。
"打开关于外部RAM调试的分散加载文件"mem_b.scf"发现所有的程序调试地址都是指向0x81000000的Flash地址空间,而不是0x80000000的RAM地址空间(此时硬件电路板上的短路片RAM接CS0、Flash接CS1),后把0x81******全部改为0x80******,编译调试都正常。
2、不正常现象:在调试"SmartARM2200 V2.02"实验箱时,每次实验箱断电或实验箱上复位按键后,H-Flash的Load操作都要重新执行一遍(或者简单一点:只要在H-Flash -> Programming -> Check 按钮上点击一下也可以),否则下载程序后实验箱运行不了。
from:/116243391.html网上已经有人做了一个周立功lpc2000(ARM7TDMI)启动代码分析的文章,我本来想做一个s3c2410(ARM920T)的启动代码分析的, 但是看来了一下2410的启动代码,发现有些东西还不是理解的很清楚, 我ARM9的经验比较少.ARM7的启动代码分析网上那一份相比,我这个主要关注startup.s文件.网上那个startup.s几乎是一笔带过的.红色标记的是源码.SVC_STACK_LEGTH EQU 0FIQ_STACK_LEGTH EQU 0IRQ_STACK_LEGTH EQU 256ABT_STACK_LEGTH EQU 0UND_STACK_LEGTH EQU 0NoInt EQU 0x80USR32Mode EQU 0x10SVC32Mode EQU 0x13SYS32Mode EQU 0x1fIRQ32Mode EQU 0x12FIQ32Mode EQU 0x11上面几行代码,不用过多分析, 定义几个符号而已, 把EQU想像成C中的#define就可以了. 具体定义的数值,下面的代码用到我再解释.IMPORT __use_no_semihosting_swi上面这一句的作用是在代码中禁用 semihosting 机制. 到底什么是semihostiong这里不多说, 网上有很多. 这里只说明Semihosting主要用来调试, 在release版本的代码中一般是要禁用的.IMPORT FIQ_ExceptionIMPORT __mainIMPORT TargetResetInit上面三行是把要引入的外部标号声明一下,以便下面使用.EXPORT bottom_of_heapEXPORT StackUsrEXPORT ResetEXPORT __user_initial_stackheap上面四行是把要给其它文件使用的标号声明AREA vectors,CODE,READONLYENTRY上面这一行声明汇编文件的入口, 整个文件是从这里开始执行的.ResetLDR PC, ResetAddrLDR PC, UndefinedAddrLDR PC, SWI_AddrLDR PC, PrefetchAddrLDR PC, DataAbortAddrDCD 0xb9205f80LDR PC, [PC, #-0xff0]LDR PC, FIQ_Addr上面几行是配置中断向量表. 中断向量表的顺序是不能变的,因为这是ARM7规定的,可以参考相关书籍. 这里有几个问题要说明一下.第一, 关于DCD 0xb9205f80, 按照ARM7的中断向量表分布图, 这个位置是个保留位. 但是究竟为什么要用0xb9205f80这个数值呢.根据周立功的说法, nxp系列的lpc21xx,lpc22xx片子要求"中断向量表中所有数据32位累加和为0,否则程序不能脱机运行", 我在AXD反汇编了一下(如下图),把中断向量表中的8个机器码累加了一下:0xe59ff018*6+0xe51ffff0+0xb9205f80,没错, 结果是零. 但是我遇到一个问题, 就是我在实验中,把0xb9205f80这个数值改成任何值,程序运行都没问题. 头大了, 这个问题待解决中……(希望高手看到了可以指点一二).第二, 关于LDR PC, [PC, #-0xff0]. 这里本应该放IRQ中断的, 为什么是这么一句话. 其实在我blog的其中一篇文章里有提到过这一点.ARM7的三级流水线结构导致了PC指向的是当前指令的后8个字节. 本来IRQ是应该放在0x00000018处的. LDR PC, [PC, #-0xff0]这条语句执行后, PC的当前值就是0x00000018+8-0xff0. 很容易计算出它的结果是0xfffff030. 看一下lpc22xx的手册就知道. 这个地址就是VICVectAddr. 也就是说本来这个地址是应该放IRQ服务程序的入口地址的,但是这个地址被放在了VICVectAddr 这个寄存器里. 英文手册里有一段对VICVectAddr 描述. 看了之后就容易明白是怎么回事了: Vector Address Register. When an IRQ interrupt occurs, the IRQ service routine can read this register and jump to the value readResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortNouse DCD 0IRQ_Addr DCD 0FIQ_Addr DCD FIQ_Handler这几行是为上面中断向量表中的中断标号分配内存空间, 也就是它们的执行地址. 一开始我有个疑问, 为什么不直接用LDR PC, ResetInit,还要用DCD中转一下, 后来上网查了一下,才恍然大悟, ldr指令中的地址必须为当前指令地址是4KB范围内, 用DCD中转一下就可以在整个程序空间寻址.UndefinedB UndefinedSoftwareInterruptB SoftwareInterruptPrefetchAbortB PrefetchAbortDataAbortB DataAbortFIQ_HandlerSTMFD SP!, {R0-R3, LR}BL FIQ_ExceptionLDMFD SP!, {R0-R3, LR}SUBS PC, LR, #4这几行不用过多解释, 只是说明上面几个异常如何执行.InitStackMOV R0, LR;设置管理模式堆栈MSR CPSR_c, #0xd3LDR SP, StackSvc;设置中断模式堆栈MSR CPSR_c, #0xd2LDR SP, StackIrq;设置快速中断模式堆栈MSR CPSR_c, #0xd1LDR SP, StackFiq;设置中止模式堆栈MSR CPSR_c, #0xd7LDR SP, StackAbt;设置未定义模式堆栈MSR CPSR_c, #0xdbLDR SP, StackUnd;设置系统模式堆栈MSR CPSR_c, #0xdfLDR SP, =StackUsrMOV PC, R0上面是一个子函数, 函数名为InitStack. 顾名思意, 这个函数设置ARM七种工作模式下的堆栈. 关于这一段代码有三点要说.第一, MSR CPSR_c, #0xdf, 这一句把ARM的工作模式设置为系统模式,或者也可以说是用户模式, 因为系统模式与用户模式是共享相同的寄存器组. 用0xdf对CPSR寄存器赋值,就把IRQ中断关闭了(可以查一下CRSR的详细说明), 代码正常执行时处理器是处在用户模式的,所以IRQ中断是不会执行的. 所以,如果用周立功的这个启动代码,当你的程序中需要中断时,要把0xdf改成0x5f. 之前看到很多人在网上说用周立功的ADS工程模板,进不了中断,很多情况下是这个原因.第二, 并不是每一种模式下的堆栈都用设置的, 比如说如果你的程序中不会用到FIQ,就可以不用设置快速中断下的堆栈.第三, 注意LDR SP, =StackUsr这个语句, 其它都是没有=号的, 为什么这个要用等号呢? 这就是LDR伪指令与LDR指令的区别了, LDR SP, =StackUsr是把StackUsr表示的地址装载到sp, LDR SP, StackUnd是把StackUnd表示地址的内容装载到sp,注意下面几句StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4可以看到,没有”=”的标号都已经用DCD初始化了, 而StackUsr到底是什么呢, 它是由下面的语句决定的(startup.s文件)AREA Stacks, DATA, NOINITStackUsr(分散加载文件)STACKS 0x40002000 UNINIT{Startup.o (Stacks)}这样就明白了, StackUsr肯定是0x40000000~0x400020000之间的某个数. 用户模式下的堆栈空间就是它了.ResetInitBL InitStackBL TargetResetInitB __main处理器上电复位后通过中断向量表进入该函数,__main函数主要工作是初始化C的库函数, 并由它进入C的main函数.__user_initial_stackheapLDR r0,=bottom_of_heap; LDR r1,=StackUsrMOV pc,lr__user_initial_stackheap函数是ADS的一个库函数, 如果程序中用到的分散加载文件, 这个函数必须要被实现. 应用程序的栈和heap是在C库函数初始化过程中建立起来的。
LPC2000系列32位ARM微控制器的CAN接收过滤设置控制器局域网(CAN)是一种串行通讯协议,它能有效支持高安全等级的分布实时控制。
CAN的应用范围很广,从高速的网络到低价位的多路接线都可以使用CAN。
LPC2119/2129/2290/2194/2292/2294 系列ARM芯片可同时支持对多个CAN总线的操作,使器件可用作网关、开关或工业或汽车应用中多个CAN总线的路由器。
LPC2000系列32位ARM微控制器集成有2个(LPC2119/2129/2290/2292)或4个(LPC2194/2294)CAN 控制器,每一个CAN控制器都与独立CAN控制器SJA1000有着相似的寄存器结构,只是器件的寄存器访问由原来的8bit字节访问转变为了32bit的双字访问,其主要的区别在于标识符接收过滤的编程操作上。
在传统的SJA1000中,接收过滤只能满足一些规律性较高的ID筛选过滤,或个数较少的ID(一般小于10~15个)进行任意筛选过滤,难以实现更复杂的任意ID进行筛选过滤,这无疑增加了系统软件设计及运行时负担。
LPC2000系列32位ARM微控制器中为所有CAN控制器提供了全局的接收标识符查询功能。
它包含一个512×32(2k字节)的RAM,通过软件处理,可在RAM中存放1~5个标识符表格。
整个AF RAM可容纳1024个标准标识符或512个扩展标识符,或两种类型混合的标识符。
由于允许的表格范围有2k字节,所以能容易地满足设计复杂的ID接收过滤要求。
首先概括性描述全局接收过滤的工作流程:当CAN控制器的接收端已接收到一个完整的标识符,它将通知接收过滤器。
接收过滤器响应这个信号,并读出控制器编号、标识符尺寸(11bit或29bit),然后,接收过滤器搜索AF RAM中的表格进行匹配,以决定接收或放弃这一帧信息。
如果FullCAN模式使能,且CAN控制器告知当前信息包含一个标准标识符,则接收过滤器(AF)首先查询FullCAN标准标识符表格,以便接收可在FullCAN模式下处理。
ARM嵌入式系统基础教程习题答案周立功arm嵌入式系统基础教程习题答案--周立功第一章思考与练习1、列举3个书本中未提到的嵌入式系统的例子。
请问:红绿灯掌控,数字空调,机顶盒2、什么叫做嵌入式系统嵌入式系统:以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。
3、什么叫嵌入式处理器?嵌入式处理器分为哪几类?嵌入式处理器就是为顺利完成特定的应用领域而设计的特定目的的处理器。
嵌入式微处理器(embeddedmicroprocessorunit,empu)嵌入式微控制器(microcontrollerunit,mcu)嵌入式dsp处理器(embeddeddigitalsignalprocessor,edsp)嵌入式片上系统(systemonchip)4、什么就是嵌入式操作系统?为何必须采用嵌入式操作系统?是一段在嵌入式系统启动后首先执行的背景程序,首先,嵌入式实时操作系统提高了系统的可靠性。
其次,提高了开发效率,缩短了开发周期。
再次,嵌入式实时操作系统充分发挥了32位cpu的多任务潜力。
第二章1、嵌入式系统项目研发的生命周期分后哪几个阶段?各自的具体任务就是什么?项目的生命周期一般分为识别需求、提出解决方案、执行项目和结束项目4个阶段。
识别需求阶段的主要任务是确认需求,分析投资收益比,研究项目的可行性,分析厂商所应具备的条件。
明确提出解决方案阶段由各厂商向客户递交标书、了解解决方案。
执行项目阶段细化目标,制定工作计划,协调人力和其他资源;定期监控进展,分析项目偏差,采取必要措施以实现目标。
完结项目阶段主要包含转交工作成果,协助客户同时实现商务目标;系统更替给保护人员;还清各种款项。
2、为何要进行风险分析?嵌入式项目主要有哪些方面的风险?在一个项目中,存有许多的因素可以影响至项目展开,因此在项目展开的初期,在客户和研发团队都还未资金投入大量资源之前,风险的评估可以用以预估项目展开可能会遭遇的难题。
/****************************************************************************** *********** 文件名:LCDDRIVE.C* 功能:通过操作S1D13503,控制256色RGB伪彩液晶显示屏。
* 说明:使用LPC2200芯片控制,8位总线接口。
* S1D13503的寄存器地址为0x83A000xx,显示存储器的地址为0x839xxxxx。
* 作者:黄绍斌* 日期:2005.05.26******************************************************************************* *********/#include "config.h"/* 定义显示缓冲区(可根据情况定义或直接使用LCM显示存储空间) */TCOLOR gui_disp_buf[GUI_LCM_YMAX][GUI_LCM_XMAX];uint8 const INIT_TAB[14] = { 0x00, // 寄存器0 -- 00000000B (正常工作模式,即非测试模式)0xBD, // 寄存器1 -- 10111101B (模式控制:打开显示,单屏,屏蔽XSCL水平非显示周期输出,使能LCDENB,彩色8位LCD数据--无XCSL2,16位显示存储数据总线方式)159, // 寄存器2 -- 159 (行字节控制)(每行显示占用的存储器字节数,即列参数)0x0E, // 寄存器3 -- 00001110B (非节功模式,256彩色方式)239, // 寄存器4 -- 239 (总行数)0, // 寄存器5 -- 0 (WF翻转周期,为0时表示每一帧WF输出翻转一次)0x00, // 寄存器6 -- 00H (第一屏显示RAM地址低8位)0x00, // 寄存器7 -- 00H (第一屏显示RAM地址高8位)0x00, // 寄存器8 -- 00H (第二屏显示RAM地址低8位)0x00, // 寄存器9 -- 00H (第二屏显示RAM地址高8位)239, // 寄存器A -- 239 (显示一区占用行数)0, // 寄存器B -- 0 (显示一区占用行数,高2位)10, // 寄存器C -- 10 (水平默认不显示周期)0 // 寄存器D -- 0 (显示域冗余宽度,正常操作模式)};/**************************************************************************** * 名称:S1D13503_Init()* 功能:初始化S1D13503。
周立功LPC2200开发板引导代码分析---by 铁匠,2005.07.181.周立功公司的LPC系列开发板,开发环境:编译软件:ADS 1.2 ,调试仿真:AXD+EASY JTAG。
2.周立功公司为了方便ADS的使用,建立了工程模板:ARM Executable Image for lpc2200//ARM指令模板Thumb Executable Image for lpc2200//Thumb指令模板ARM Executable Image for UCOSII(for lpc2200)//ARM指令模板(UCOSII用) Thumb Executable Image for UCOSII(for lpc2200)// Thumb指令模板(UCOSII用) ASM for lpc2200//汇编模板Thumb ARM Interworking Image for lpc2200// ARM和Thumb交叉工作模板6种模式,工作方式大同小异。
差别在于用到UCOSII的进行了系统移植。
而指令集不同,模板也略有不同。
本文只分析ARM指令模板。
3.文件功能模块划分(以老版本模板进行分析):Config.h 定义了数据基本类型、系统时钟设置。
Target.h 定义了软复位函数和目标板初始化函数。
Lpc2294.h 定义了芯片的内部寄存器地址映射、固件函数。
Target.c 目标板代码,包括异常处理程序和目标板初始化程序,用户根据程序的需要修改本文件。
Heap.s 堆空间初始化。
IRQ.s 中断处理。
Stack.s 栈空间初始化。
//最新模板中没有Startup.s 启动引导代码。
//最新模板中没有Mem_a.scfMem_b.scfMem_c.scfMain.c4.Lpc2294.h说明:主要定义了寄存器的地址映射和固件函数。
(固件函数含义不知)估计是出厂时,这些地址写入了固化函数,在这里声明。
/* Define firmware Functions *//* 定义固件函数 */#define rm_init_entry() ((void (*)())(0x7fffff91))()#define rm_undef_handler() ((void (*)())(0x7fffffa0))()#define rm_prefetchabort_handler() ((void (*)())(0x7fffffb0))()#define rm_dataabort_handler() ((void (*)())(0x7fffffc0))()#define rm_irqhandler() ((void (*)())(0x7fffffd0))()#define rm_irqhandler2() ((void (*)())(0x7fffffe0))()#define iap_entry(a, b) ((void (*)())(0x7ffffff1))(a, b)5.Config.h说明:只有下面4个选项需要设置:/* 系统设置, Fosc、Fcclk、Fcco、Fpclk必须定义*/#define Fosc 11059200 //晶振频率,10MHz~25MHz,应当与实际一至#define Fcclk (Fosc * 4) //系统频率,必须为Fosc的整数倍(1~32),且<=60MHZ#define Fcco (Fcclk * 4) //CCO频率,必须为Fcclk的2、4、8、16倍,范围156MHz~320MHz #define Fpclk (Fcclk / 4) * 1 //VPB时钟频率,只能为(Fcclk / 4)的1 ~ 4倍通常只需要设置Fosc即可。
分散加载文件浅释ARM嵌入式开发广州周立功单片机科技有限公司目录1. 适用范围 (1)2. 基础知识 (2)2.1 基本概念 (2)3. 分散加载文件概述 (3)4. 分散加载文件语法 (4)4.14.24.35.15.25.35.45.55.6 加载时域的描述 (4)运行时域的描述 ....................................................................................................... 5 输入段描述 ............................................................................................................... 6 一个普通的分散加载配置 ....................................................................................... 8 多块RAM的分散加载文件配置 ............................................................................ 8 多块Flash的分散加载文件配置 .......................................................................... 10 Flash特殊要求应用 ............................................................................................... 13 段在分散加载文件中的应用 ................................................................................. 13 程序拷贝到RAM中执行应用 .............................................................................. 14 5. 分散加载应用实例 ................................................................................................... 8 工程技术笔记©2008 Guangzhou ZHIYUAN Electronics CO., LTD.11. 适用范围有时候用户希望将不同代码放在不同存储空间,也就是通过编译器生成的映像文件需要包含多个域,每个域在加载和运行时可以有不同的地址。
第1章 MagicARM2200-S教学实验开发平台1.1总体特性MagicARM2200-S是专为高校嵌入式系统教学精心打造的ARM嵌入式教学实验开发平台,支持多种嵌入式操作系统,提供丰富的配套教材和众多的实验例程,提供多种的商业化软件包,并配备精心设计的多媒体教学课件,是高校嵌入式系统创新实验室首选平台。
z多种可选嵌入式硬件开发平台¾ARM7微处理器(LPC2210/2212/2214/2220/2290/2292/2294)¾ARM9微处理器(LPC3000系列ARM微处理器)z支持多种可选嵌入式操作系统¾μC/OS-II嵌入式实时操作系统(ARM7/ARM9)¾μCLinux操作系统(ARM7)¾Linux/操作系统(ARM9)z配套丰富的教材《ARM嵌入式系统基础教程》(标配)《MagicARM2200-S教学实验开发平台实验指导(上册)》(标配)《MagicARM2200-S教学实验开发平台实验指导(下册)》(标配)《ARM嵌入式软件开发实例(一)》(选配)《ARM嵌入式软件开发实例(二)》(选配)《ARM嵌入式µCLinux系统构建与驱动开发范例》(选配)《ARM嵌入式MiniGUI初步与应用开发范例》(选配)z多媒体教学课件¾耗时半年之久,倾力制作¾大量动画突出重点和难点,层层剥笋由浅入深¾紧扣教材主线,任君裁剪z丰富翔实的联机实验指导¾在本机上运行,无需电脑。
¾可以从多种介质中启动程序,方便扩充。
¾支持从内部FALSH、CF卡/硬盘。
¾内容丰富,可部分替代实验教材。
¾可直接运行实验程序,察看运行效果。
z附带众多源码和软件包¾众多实验例程和源代码¾众多商业化软件包z免费捆绑MiniGUI学习版软件(单独销价129元)¾北京飞漫出品,周立功公司独家代理¾提供MiniGUI for µCLinux移植实验,MiniGUI应用实例¾免费提供MiniGUI-STR软件包z可进实现近众多项实验课题¾基础实验¾扩展实验¾基于μC/OS-II的基础实验¾基于μCLinux基础实验¾MiniGUI图形界面实验¾课程设计¾毕业设计1.2产品外观实验箱和配套资料1.3主板介绍MagicARM2200-S主板图片见附录部分。
周立功NXP LPC21xx/22xx 系列ARM 芯片的启动程序分解关于LPC2200 启动程序分散加载描述文件的叙述在ADS LPC2200 的启动模板中有一个scf 文件夹,其中有mem_a.scf、mem_b.scf、mem_c.scf 这3 个文件,这3 个文件是ADS 的分散加载机制,其目的是将代码段和数据段分别定位到指定地址上。
可以在Arm Linker 中选择加载路径。
分散装载技术概述:分散装载技术可以把用户的应用程序分割成多个RO(只读)运行域和RW(可读写)运行域(一个存储区域块),并且给它们制定不同的地址。
一个嵌入式系统中,Flash、16 位RAM、32 位RAM 都可以存在于系统中,所以,将不同功能的代码定位在特定的位置会大大地提高系统的运行效率。
下面是最为常用的2 种情况:1、32 位的RAM 运行速度很快,因此就把中断服务程序作为一个单独的运行域,放在32 位的RAM,使它的响应时间达到最快。
2、程序在RAM 中运行,其效率要远远高于在ROM 中运行,所以将启动代码(Boot loader)以外的所有代码都复制在RAM 中运行,可以提高运行效率。
分散装载技术主要完成了2 个基本的功能:如何分散。
就是如何将输入段组成输出段和域。
如何装载。
就是确定装载域和运行域在存储空间里的地址是多少。
域可以分为装载域和运行域装载域描述运行前输出段和域在ROM/RAM 里的分布状态,运行域描述了运行时输出段和域在ROM/RAM 里的分布状态。
大多数情况下,映像文件在执行前把它装载到ROM 里,而当运行时,域里的有些输出段(比如RW 类型的输出段)必须复制到RAM 里,程序才能正常运行,所以,在装载和运行时,RW 类的输出段处在不同的位置(地址空间)。
Scatterfile 分散加载文件:在scatterfile 中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading 的存储区块可以分成二种类型:装载区:当系统启动或加载时应用程序的存放区。
执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。
映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。
scatter 文件语法scatter 文件是一个简单的文本文件,包含一些简单的语法。
My Region 0x0000 0x1000 ;我的名字My Region 起始地址0x0000 属性0x1000{;the context of region 这个域的范围}标题每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,如(0x0000),另外还有最大长度等其他一些属性选项(注:这些属性是可选的,如0x1000)。
内容块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。
1、一个加载块必须至少含有一个执行块;实践中通常有多个执行块。
2、一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。
有以下几种属性:RO:只读的代码段和常量RW:可以读写的全局变量和静态变量ZI:RW 段中要被初始化为零的变量。
Scatterfile 中的定义要按照系统冲定向后的存储器分布情况进行,在引导程序完成初始化任务后,应该把主程序转移到RAM 中运行以加快系统的运行速度。
LPC2200 的分散加载文件分析:ROM_LOAD 0x80000000 (1){ROM_EXEC 0x80000000 (2){ Startup.o (vectors, +First) (3)* (+RO) } (4)IRAM 0x40000000 (5){ Startup.o (MyStacks) } (6)STACKS_BOTTOM +0 UNINIT (7){ Startup.o (StackBottom) } (8)STACKS 0x40004000 UNINIT (9){ Startup.o (Stacks) } (10)ERAM 0x80040000 (11){ * (+RW,+ZI) } (12)HEAP +0 UNINIT (13){ Startup.o (Heap) } (14)HEAP_BOTTOM 0x80080000 UNINIT (15){ Startup.o (HeapTop) } (16)}FLASH_LOAD 0x81000000 0x1000 (17){ FLASH_EXEC 0x81000000 (18){ main.o (+RO) } (19)}(1) 加载时域描述,名称位ROM_LODA 它的地址为0x80000000;0x80000000 为LPC 片外RAM 地址,即将以下的加载的段和域都在RAM 中。
(2) 第一个运行时域描述。
ROM_EXEC 描述了执行区的地址,放在第一块定义,其起始地址、空间大小域加载区起始地址、空间大小要一样。
(2)-(4)从起始地址开始放置向量表。
Startup.o 是Startup.s 的目标文件。
Vectors 为中断向量表。
模块Startup 位于该加载域的开头(+First),vectors 作为入口点,包含全部的RO 代码。
ARM 在芯片复位之后,系统进入管理模式、ARM 状态,PC(R15)寄存器的值为0x00000000,所以必须保证用户的向量表代码定位在0x00000000 处,或者映射到0x00000000 处(例如向量表代码在0x80000000处,通过存储器映射,访问0x0000000 就是访问(0x80000000)。
(5)-(6)第二运行时域描述。
将MyStacks 堆栈段装载到片内静态RAM 中。
(7)-(8)将栈底放入堆栈的后面(+0)不进行初始化(UNINIT), 栈底为Startup 中的StackBottom。
(9)-(10) 将栈放入地址为0x40004000 并且不进行初始化(UNINIT)。
(11)-(12 将所有的RW 和ZI 段放入外部存储器中以0x80040000 为开头的地址中。
并且全部清零(+ZI)外部RAM 中指定的区域。
(13)-(14)在RW ZI 段后放入堆底(Startup.o(Heap))并且不进行初始化。
(15)-(16)将堆定放入外部RAM 中(0x80080000)。
(17)-(19)自己添加的加载代码,把main.c 的目标文件加载到片外Flash 中并且占用了0x1000 的大小。
;******************************************************************************************* *************/;** File Name: men_a.scfROM_LOAD 0x80000000 // ROM加载{ROM_EXEC 0x80000000 // ROM执行(起始地址)程序0x80000000 外部存储区{ Startup.o (vectors, +First) // Startup.o文件(向量,程序入口)* (+RO)} // 只读IRAM 0x40000000 // Indexed Random Access Method,索引随机存取方法0x40000000{ Startup.o (MyStacks)} // Startup(堆栈)装载到片内SRAM中STACKS_BOTTOM +0 UNINIT // 堆栈栈底,将栈底放入堆栈的后面(+0),不初始化{ Startup.o (StackBottom)} // 将栈放入地址为0x40004000 并且不进行初始化(UNINIT)STACKS 0x40004000 UNINIT // 堆栈0x40004000 16kb的SRAM片内存储区{ Startup.o (Stacks)} // Startup.o文件(堆栈)ERAM 0x81000000 // 将所有的RW和ZI段放入外部存储器中0x81000000为开头的地址中{ * (+RW,+ZI)} // 并且全部清零(+ZI)外部RAM中指定的区域读写(无输入ZI)HEAP +0 UNINIT // 在RW ZI段后放入堆底(Startup.o(Heap))并且不进行初始化{ Startup.o (Heap)} // Startup.o文件(堆栈)HEAP_BOTTOM 0x81080000 UNINIT // 将堆定放入外部RAM中0x81080000{ Startup.o (HeapTop)} // Startup.o文件(堆栈栈顶)};******************************************************************************************* *************/;** File Name: men_b.scfROM_LOAD 0x80000000{ROM_EXEC 0x80000000{ Startup.o (vectors, +First)* (+RO)}IRAM 0x40000000{ Startup.o (MyStacks)}STACKS_BOTTOM +0 UNINIT{ Startup.o (StackBottom)}STACKS 0x40004000 UNINIT{ Startup.o (Stacks)}ERAM 0x80040000{ * (+RW,+ZI)}HEAP +0 UNINIT{ Startup.o (Heap)}HEAP_BOTTOM 0x80080000 UNINIT{ Startup.o (HeapTop)}};******************************************************************************************* *************/;** File Name: men_c.scfROM_LOAD 0x0{ROM_EXEC 0x00000000{ Startup.o (vectors, +First)* (+RO)}IRAM 0x40000000{ Startup.o (MyStacks)}STACKS_BOTTOM +0 UNINIT{ Startup.o (StackBottom)}STACKS 0x40004000 UNINIT{ Startup.o (Stacks)}ERAM 0x80000000{ * (+RW,+ZI)}HEAP +0 UNINIT{ Startup.o (Heap)}HEAP_BOTTOM 0x80080000 UNINIT{ Startup.o (HeapTop)}};/****************************************************************************************** **************加载文件的更多分解说明,网上了解资料。