ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

S3C44B0X开发板实战:ARM7存储器映射、中断定时与JTAG调试

S3C44B0X开发板实战:ARM7存储器映射、中断定时与JTAG调试 简介这份PPT面向嵌入式开发初学者与硬件工程师系统梳理ARM芯片与开发板的对应关系重点剖析三星S3C44B0XARM7TDMI内核的内部结构与工程应用。内容从16/32位RISC指令集、Thumb协处理器、片上ICE调试与32×8硬件乘法器讲起逐层展开8KB Cache、外部存储器控制器、LCD控制器、DMA通道、UART、I2C与IIS总线、PWM定时器、71个通用I/O口及8通道10位ADC等集成模块并延伸至系统板组成包括LCD与触摸屏接口、USB HOST、JTAG调试、IIC接口EEPROM、矩阵键盘、LED指示灯与数码管电路这些模块可按项目需要灵活裁剪。资源以1个pptx文件交付压缩包约1.33MB页面结构清晰便于课堂讲授与自学翻阅。已有75人学习关注适合需要理解ARM7体系结构、内存Bank管理、BOOTLOADER流程、时钟与低功耗模式、30个中断源与矢量IRQ/FIQ机制以及硬件断点与软件断点调试差异的读者作为入门与查阅参考。1. 从一块 66MHz 的 ARM7 开发板说起手里拿到一块 S3C44B0X 系统板第一反应往往是它“太老了”66MHz 主频、8KB Cache、2 路 UART连 SD 卡控制器都要外挂。但恰恰是这种“什么都要自己配”的板子把 ARM 体系里的存储器映射、中断向量、PLL 倍频、Bootloader 搬运这几件事完整地摊在工程师面前。S3C44B0X 用的是 ARM7TDMI 核16/32 位 RISC 结构带 Thumb 指令集压缩代码密度片上还有 32×8 位硬件乘法器和 ICE 中断调试通道。三星把 LCD 控制器、4 路 DMA、IIC/IIS 总线控制器、5 通道 PWM 定时器、8 通道 10 位 ADC、71 个通用 I/O 全都塞进了一颗芯片对当年手持设备和工控板来说这是一份相当完整的低成本解决方案。开发板的类型五花八门但核心板加底板的组合逻辑大同小异核心板管 CPU、Flash、SDRAM底板管 LCD、USB HOST、4×4 矩阵键盘这些外围。后面几章按存储映射、功耗中断、定时器与 RTC、调试四个方向从寄存器配置一路走到可下载运行的代码。2. S3C44B0X 存储器映射与 Bank 时序配置实战2.1 256MB 地址空间凭什么切成 8 个 BankARM7TDMI 的地址总线是 32 位但 S3C44B0X 只对外引出 256MB 的物理寻址空间原因是它把地址空间平均切成 8 个 32MB 的 Bank。Bank0 到 Bank5 只用于 ROM 和 SRAMBank6、Bank7 才有 DRAM/SDRAM 控制器支持自动刷新和对称/非对称寻址。这个划分方式决定了板上器件怎么摆Boot Flash 必须挂在 Bank0因为复位后 ARM7TDMI 从 0x00000000 取第一条指令SDRAM 一般放 Bank6起始地址由 BANKSIZE 寄存器配置。Bank0 的起始地址固定其余 7 个 Bank 可以编程其中 1 个 Bank 支持起始地址和尺寸同时可编程。每个 Bank 的数据总线宽度单独可编程支持 8/16/32 位三种。一块板子上 Flash 是 16 位、SDRAM 是 32 位这种混搭很常见所以 BWSCON 里每个 Bank 占 2 个位来控制 DW。Bank起始地址可挂器件典型用途Bank00x00000000 固定ROM/SRAMBoot FlashBank1–5可编程ROM/SRAM网卡、NOR FlashBank6可编程尺寸可调ROM/SRAM/DRAM主 SDRAMBank7可编程尺寸可调ROM/SRAM/DRAM扩展 SDRAM提示Bank6、Bank7 的尺寸设置必须一致或成对出现SDRAM 单条时通常只配 Bank6Bank7 留空。2.2 BWSCON 与 BANKCON 的寄存器写法存储器控制器寄存器组从 0x01C80000 开始。BWSCON 管总线宽度和等待状态BANKCON0–5 管 ROM/SRAM 的时序BANKCON6/7 管 DRAM 的 RAS/CAS 时序REFRESH 管自刷新周期。工程里习惯用volatile指针直接映射避免编译器优化掉寄存器写操作。#define BWSCON (*(volatile unsigned long *)0x01C80000) #define BANKCON0 (*(volatile unsigned long *)0x01C80004) #define BANKCON6 (*(volatile unsigned long *)0x01C8001C) #define REFRESH (*(volatile unsigned long *)0x01C80024) #define BANKSIZE (*(volatile unsigned long *)0x01C80028) void mem_ctrl_init(void) { /* Bank0: 16 位 Flash无等待状态Bank6: 32 位 SDRAM */ BWSCON (0x0 0) /* DW0 16 位 */ | (0x2 4) /* Bank6 DW 32 位 */ | (0x1 27); /* Bank6 使能等待状态 */ BANKCON0 (0x7 8) /* Tacc: 访问周期 */ | (0x1 6); /* Tacs: 片选建立时间 */ BANKCON6 (0x3 0) /* MT: SDRAM */ | (0x1 2) /* Trcd */ | (0x0 4); /* SCAN: 列地址位数 */ /* 64MB SDRAM刷新计数按 64ms/8192 行 与 HCLK 换算 */ REFRESH (0x1 23) /* REFEN: 刷新使能 */ | (0x0 22) /* TREFMD: CBR 刷新 */ | (0x3 20) /* Trp */ | (0x3 18) /* Trc */ | (0x547); /* 刷新计数值需按 HCLK 重算 */ BANKSIZE (0x2 0); /* Bank6/7 尺寸 64MB */ }逻辑上先配总线宽度和等待状态再细化时序最后打开刷新。参数说明Tacc决定读周期长度Flash 越慢这个值越大Trp、Trc是 SDRAM 预充电和行周期时间必须满足颗粒手册的最小值REFRESH低 11 位的刷新计数按公式2^11 1 - HCLK × Tras计算HCLK 变了就要重算否则数据会静默出错而不是立即跑飞这是最常见的坑。2.3 Bootloader 的位置选择与串口下载链路Bootloader 烧在 Flash 里复位后先跑它。它的职责不只是“启动内核”而是一整套引导工具通过串口与 PC 终端建立连接、配置板级参数、打印帮助菜单、把应用镜像下载到 SDRAM 直接运行、确认无误后再写入 Flash、最后跑一段自检。SDRAM 下载和 Flash 运行需要两份不同的链接地址这是新手最容易踩的地方。下载调试时链接到 SDRAM如 0x0C000000烧写运行时链接到 Bank0 的 0x00000000。用 GNU 工具链时靠链接脚本和-Ttext切换# 生成下载到 SDRAM 调试的可执行文件 arm-elf-gcc -mcpuarm7tdmi -mthumb-interwork -O2 \ -Ttext0x0C000000 -o app.elf start.S main.c # 转成裸二进制供 Bootloader 串口接收 arm-elf-objcopy -O binary app.elf app.bin # 转成反汇编核对入口地址是否落在预期位置 arm-elf-objdump -d app.elf | head -40-mcpuarm7tdmi指定内核-mthumb-interwork允许 ARM 和 Thumb 指令集互相调用-Ttext决定代码段的运行地址。下载到 SDRAM 调试时用 0x0C000000烧 Flash 前改成 0x00000000 重新链接。串口传输前记得把 SDRAM 控制器初始化好否则 Bootloader 收完数据往 SDRAM 写会直接丢失——现象是“传输进度条走完但一执行就重启”。3. PLL 倍频、四种功耗模式与 30 个中断源调度3.1 时钟树与功耗模式的进入退出条件S3C44B0X 的时钟电源管理寄存器从 0x01D80000 起核心包括 LOCKTIME、MPLLCON、CLKCON、CLKSLOW、CLKDIVN。晶振一般是 10MHz 或 12MHz通过 MPLL 倍频到 66MHz 主频再经 CLKDIVN 分频出 FCLK、HCLK、PCLK 三路。低功耗是这颗芯片的设计重点它把功耗分成四档每档能关掉的时钟范围不同模式CPU 时钟外设时钟唤醒源典型场景正常运行全开—正常工作低能低频无 PLL部分关—待机降频休眠停止保留EINT、RTC短时挂起停止停止全部停止EINT、RTC 报警深度省电进入停止模式前要先把外设状态保存好用CLKCON逐位关闭功能块时钟再写CLKSLOW停 PLL。唤醒靠外部中断或 RTC 报警中断唤醒后 PLL 需要重新锁定LOCKTIME里的锁定计数值不够会导致第一次跳转直接跑飞。#define LOCKTIME (*(volatile unsigned long *)0x01D80000) #define MPLLCON (*(volatile unsigned long *)0x01D80008) #define CLKCON (*(volatile unsigned long *)0x01D8000C) #define CLKSLOW (*(volatile unsigned long *)0x01D80010) #define CLKDIVN (*(volatile unsigned long *)0x01D80014) void clk_init(void) { LOCKTIME 0x0FFF; /* PLL 锁定等待时间值越大越稳 */ MPLLCON (0x2A 12) /* MDIV */ | (0x3 4) /* PDIV */ | (0x1); /* SDIV按 10MHz 输入算 66MHz 输出 */ CLKDIVN (0x1 1); /* HCLK FCLKPCLK 分频 */ CLKCON 0x7FF8; /* 关闭未用外设时钟保留必要模块 */ } void enter_stop_mode(void) { CLKCON | (0x1 1); /* 停止 CPU 时钟 */ CLKSLOW | (0x1 4); /* 停 PLL */ __asm volatile (nop); /* 等待时钟真正停摆指令流水清空 */ }参数说明MPLLCON的 MDIV/PDIV/SDIV 由目标频率反推公式在数据手册里有LOCKTIME不是越大越好太大会拖慢唤醒响应CLKCON里被关掉时钟的外设再次使用前必须重新使能否则读寄存器读回全 0。3.2 30 个中断源如何分给 IRQ 和 FIQS3C44B0X 共 30 个中断源看门狗 1 个、定时器 6 个、UART 6 个、外部中断 8 个、DMA 4 个、RTC 2 个、ADC 1 个、IIC 1 个、SIO 1 个。控制器把中断分成两类普通 IRQ 走矢量模式每个源有独立向量响应周期被压缩紧急中断走 FIQ只有一路用于实时性最高的场合。中断控制器寄存器INTCON0x01E40000管模式和极性INTPND0x01E40004记录当前挂起的中断INTMOD0x01E40008决定某源走 IRQ 还是 FIQINTMSK0x01E4000C负责屏蔽。外部中断还支持水平/边缘触发极性可编程。配置顺序有个固定套路先清INTPND再设INTMOD和触发方式最后解INTMSK。顺序搞反会在解屏蔽的瞬间触发一次假中断。3.3 中断服务程序注册与 INTPND 清除顺序矢量 IRQ 模式下可以在 C 里用函数属性直接写 ISR但更多老工程用汇编跳转表。无论哪种处理完必须按“先清源中断标志、再清 INTPND 对应位”的顺序来。__attribute__((interrupt(IRQ))) void timer0_isr(void) { /* 1. 先清定时器自身的中断挂起位 */ TCON ~(0x1 6); /* 2. 再清中断控制器的挂起位写 1 清除 */ INTPND (0x1 10); /* 3. 业务逻辑放在最后 */ tick_counter; }逻辑说明TCON的位 6 是定时器 0 的清除位不清它中断会反复触发INTPND是写 1 清除与很多平台的写 0 清除相反写错会导致中断永久挂起。参数上如果两个源同时挂起只清一个就返回剩下那个要等下次进入所以 ISR 里通常循环检查INTPND直到全部清干净。4. PWM 定时器、RTC 与 8 通道 ADC 的驱动写法4.1 16 位 PWM 定时器的频率与占空比计算S3C44B0X 有 5 个 16 位带 PWM 的定时器加 1 个内部定时器PWM 输出靠 TCNTB计数初值和 TCMPB比较值两个寄存器配合。工作流程是TCNTB 递减计数计到和 TCMPB 相等时翻转输出电平计到 0 时重载并产生中断。频率由预分频TCFG0和分频器TCFG1两级决定输出频率公式是f_out f_pclk / (prescaler 1) / divider / TCNTB占空比则是TCMPB / TCNTB。因为 TCNTB 是 16 位最大 65535所以在给定 PCLK 下频率和分辨率是一对矛盾频率越高占空比可调的台阶越少。预分频分频器TCNTB输出频率PCLK66MHz占空比精度65/25001kHz1/50065/4500500Hz1/500255/161000约16Hz1/10009/16553约1kHz1/6553#define TCFG0 (*(volatile unsigned long *)0x01D50000) #define TCFG1 (*(volatile unsigned long *)0x01D50004) #define TCON (*(volatile unsigned long *)0x01D50008) void pwm0_init(unsigned int period, unsigned int duty) { TCFG0 65; /* 预分频 65两级分频 */ TCFG1 0x0; /* 定时器0 分频 1/2 */ TCNTB0 period; /* 计数初值决定频率 */ TCMPB0 duty; /* 比较值决定占空比 */ TCON | (0x1 1); /* 手动更新 TCNTB/TCMPB */ TCON ~(0x1 1); /* 清手动更新位 */ TCON | (0x1 3) | (0x1 0); /* 自动重载 启动定时器0 */ }参数说明先写 TCNTB/TCMPB再置手动更新位让值生效最后才启动否则初值可能没加载。TCFG1低位选分频0 是 1/2、1 是 1/4依次翻倍。调 LED 亮度时改TCMPB0改频率时动TCNTB0两者都受 16 位上限约束做低频大范围调光时优先加大预分频把 TCNTB 留足空间。4.2 RTC 的 BCD 读写与报警唤醒RTC 在 32.768kHz 石英晶体下运行能提供毫秒、秒、分、时、天、星期、月、年带 CPU 唤醒的报警中断。读时间前必须先使能RTCCON的控制位写完再关掉否则时钟数据在读写过程中会跳变。#define RTCCON (*(volatile unsigned char *)0x01D70040) #define BCDSEC (*(volatile unsigned char *)0x01D70070) #define BCDMIN (*(volatile unsigned char *)0x01D70074) #define RTCALM (*(volatile unsigned char *)0x01D70050) #define ALMMIN (*(volatile unsigned char *)0x01D70054) void rtc_read(unsigned char *h, unsigned char *m, unsigned char *s) { RTCCON | 0x1; /* 使能 RTC 读写 */ *s BCDSEC 0x7F; /* 屏蔽最高位 */ *m BCDMIN 0x7F; *h *(volatile unsigned char *)0x01D70078 0x3F; RTCCON ~0x1; /* 关闭读写窗口 */ }RTC 寄存器是 BCD 码不是二进制显示前要转码。报警功能靠RTCALM逐位使能年/月/日/时/分/秒再往对应的ALMxxx寄存器写目标值最后在中断控制器里解开 RTC 报警中断。从停止模式唤醒时这条路径是少数几个还能工作的唤醒源之一。4.3 8 通道 10 位 ADC 的采集流程ADC 是 8 通道、10 位逐次逼近型寄存器三个ADCCON控制启动和通道选择ADCPSR设预分频ADCDAT存结果。转换需要时间启动后要等状态位不能直接读。寄存器作用关键位ADCCON通道选择、启动bit0 启动bit5:3 通道号ADCPSR预分频低 8 位决定转换时钟ADCDAT转换结果低 10 位有效#define ADCCON (*(volatile unsigned long *)0x01D40000) #define ADCPSR (*(volatile unsigned long *)0x01D40004) #define ADCDAT (*(volatile unsigned long *)0x01D40008) unsigned int adc_read(unsigned char ch) { ADCPSR 19; /* 转换时钟 PCLK/(191) */ ADCCON (0x1 2) | (ch 3); /* 使能、选通道 */ while (ADCCON 0x1); /* 等待启动位自动清零 */ ADCCON ~(0x1 2); /* 关闭使能降低功耗 */ return ADCDAT 0x3FF; /* 只取低 10 位 */ }逻辑说明启动位写 1 后硬件会自动清零轮询它比固定延时可靠。参数上ADCPSR太小会让采样保持时间不足读回值抖动大通道号 0–7 对应外部引脚换成触摸屏时改用其他通道组合。读回值要换算成电压V ADCDAT / 1023 * VREF。5. JTAG 断点与 watchpoint 定位跑飞现场5.1 硬件断点和软件断点的适用边界ARM7TDMI 通过 EmbeddedICE 提供两个 watchpoint 单元每个 watchpoint 可以设置地址、数据和相关控制信号。当 CPU 执行的指令地址有时还有数据命中 watchpoint 时内核从运行态切到 Debug 态这就是断点的底层机制。断点分两类边界很清楚类型实现方式数量限制可设位置硬件断点直接写 watchpoint 地址受 watchpoint 数目限制2 个任意地址包括 ROM/Flash软件断点把指令替换成未定义指令 X不受限只能在可写存储器RAM软件断点靠改存储器内容实现Flash 里改不动所以调试烧在 Flash 里的代码只能靠硬件断点。两个硬件 watchpoint 要省着用一个盯入口一个盯变量地址是最常见的组合。5.2 用 watchpoint 抓变量被踩的现场程序跑飞但不知道谁改坏了某个全局变量时硬件 watchpoint 比单步高效得多。做法是把这个变量的地址写进 watchpoint设成“写命中”一旦有人改它立刻停机。在 GDB 里连接好调试器后# 连接到 JTAG 调试器 target remote :3333 # 复位并停在入口 monitor reset halt # 监视全局变量的写操作硬件写断点 watch sensor_state # 继续运行命中后打印调用栈 continue backtrace info registerswatch设的是写断点rwatch是读断点awatch读写都停。命中后backtrace能看到调用链info registers核对 pc、sp 是否落在合理区间。如果两个 watchpoint 都被占用说明该优化代码结构而不是继续加断点。一个容易被忽略的点watchpoint 匹配的是物理地址开了 Cache 之后 CPU 访问的是缓存写回内存的时机和指令执行不同步所以调试数据一致性问题时先关 Cache或者用非缓存的 SRAM 区域做变量否则断点命中位置会和预期错位误判成“硬件坏了”。另外Bootloader 阶段的调试建议全程开着 JTAG让下载、写 Flash、自检这些动作都处于可断点状态一旦写 Flash 失败或 SDRAM 校验出错能立刻停下来看寄存器快照比串口打印日志快得多。本文还有配套的精品资源点击获取
返回列表