1. DSP基础与硬件架构:DSP芯片概述、TMS320C6000系列架构、CPU与外设总线、存储器映射
各位同学,咱们今天聊聊DSP的根——硬件架构。说实话,我入行那会儿,第一次拿到TMS320C6000的datasheet,看着那密密麻麻的框图,头都大了。但后来我发现,搞懂硬件架构,就像拿到了一张地图,后面写Bootloader、调外设,心里才有底。
1.1 DSP芯片概述:它到底特别在哪?
DSP,全称数字信号处理器。你可能会问,它跟普通单片机有啥区别?说白了,DSP是个偏科生。普通MCU擅长控制逻辑,比如点个灯、读个按键。但DSP的强项是——算得快。
我举个例子。你在做音频处理,要对一段声音做FFT(快速傅里叶变换)。普通MCU算半天,DSP可能几个时钟周期就搞定了。为什么?因为它的硬件架构就是为乘加运算(MAC)量身定做的。
核心特点:
- 哈佛架构:程序总线和数据总线分开,取指令和读写数据可以同时进行。不像冯·诺依曼架构,取指令和读写数据要排队。
- 硬件乘法器:一个时钟周期就能完成一次乘加运算。普通MCU要用软件模拟,慢得多。
- 流水线技术:指令执行像工厂流水线,取指、译码、执行、写回,每个阶段并行处理。
嗯,这里要注意。DSP虽然算得快,但控制能力相对弱。所以很多系统里,DSP负责算,MCU负责管。我在项目中就遇到过,用DSP做电机控制算法,但逻辑判断和通信协议还是交给旁边的ARM处理。
1.2 TMS320C6000系列架构:C64x+核心
咱们课程主要围绕TMS320C6000系列,特别是C64x+核心。这个系列是TI的明星产品,广泛应用于通信基站、医疗影像、工业控制等领域。
我个人习惯,看芯片先看它的核心架构。C64x+有以下几个关键点:
1.2.1 VLIW架构
VLIW,超长指令字。什么意思?普通CPU一次只能发一条指令,但C64x+一次能发8条指令!这8条指令打包成一个256位的指令包,同时分发给8个功能单元去执行。
你想想看,这相当于一个工厂里,8个工人同时干活。但前提是,这8条指令之间不能有数据依赖。编译器在编译时就要安排好,哪些指令可以并行。所以,C64x+对编译器的依赖非常大。
我的经验:写C6000的代码,尽量用TI的编译器优化选项。我曾经手写汇编优化了一段FFT代码,折腾了两周,结果编译器自动优化后的性能只差5%。从那以后,我学会了信任编译器。
1.2.2 功能单元与寄存器
C64x+核心有8个功能单元,分成两组:
- .L1, .L2:逻辑/算术单元,做加减、逻辑运算
- .S1, .S2:移位/比较单元,做移位、比较、位操作
- .M1, .M2:乘法单元,做16位或32位乘法
- .D1, .D2:数据存取单元,负责从内存读写数据
每个功能单元都有自己的寄存器组。A组(A0-A15)和B组(B0-B15),共32个32位通用寄存器。为什么分两组?因为两组可以并行工作,提高数据吞吐量。
我记得刚学的时候,总搞不清哪个指令用哪个单元。后来我画了个表贴在工位上:
| 指令类型 | 可用功能单元 | 示例 |
|---|---|---|
| 加法/减法 | .L1, .L2, .S1, .S2 | ADD .L1 A0, A1, A2 |
| 乘法 | .M1, .M2 | MPY .M1 A0, A1, A2 |
| 加载/存储 | .D1, .D2 | LDW .D1 *A0, A2 |
| 移位 | .S1, .S2 | SHR .S1 A0, 4, A1 |
1.3 CPU与外设总线:数据怎么跑起来?
CPU再强,也得跟外设打交道。C6000系列的总线架构,我总结为「三层网络」:
- CPU内部总线:连接核心、L1缓存、寄存器组。速度最快,一个时钟周期搞定。
- 外设总线(Peripheral Bus):连接各种外设,比如GPIO、UART、I2C、SPI。速度中等,通常跑在CPU频率的一半或更低。
- EMIF(外部存储器接口):连接外部SDRAM、Flash、SRAM。速度取决于外部器件,但带宽很大。
这里有个坑,我踩过。有一次调试UART,发现数据总是丢包。查了半天,原来是外设总线时钟配置错了。UART模块的时钟源来自外设总线,如果总线频率不对,波特率就偏了。
避坑指南:配置外设时钟时,一定要确认外设模块的时钟源和分频系数。我曾经因为没仔细看datasheet,把SPI时钟配成了CPU频率的1/2,结果SPI通信死活不稳定。后来改成1/4,问题解决。
1.4 存储器映射:你的代码住哪?
存储器映射,说白了就是给芯片里的每个存储单元分配一个地址。C6000系列的地址空间是32位的,最大寻址4GB。
典型的存储器映射如下:
| 地址范围 | 用途 | 说明 |
|---|---|---|
| 0x00000000 - 0x000FFFFF | 内部RAM(L2 SRAM) | 1MB,速度最快,放关键代码和数据 |
| 0x00100000 - 0x01FFFFFF | 外部存储器(EMIF) | 可接SDRAM、Flash、SRAM |
| 0x01800000 - 0x01FFFFFF | 外设寄存器 | 配置GPIO、UART、定时器等 |
| 0x80000000 - 0xFFFFFFFF | 保留/扩展 | 留给未来或特殊用途 |
你可能会问,为什么内部RAM只有1MB?因为DSP的核心理念是「快」,内部RAM用SRAM实现,速度快但成本高。所以,我们通常把最关键的代码(比如中断服务函数、实时性要求高的算法)放在内部RAM,其他代码和数据放在外部存储器。
我个人习惯,在写Bootloader时,会把启动代码放在内部RAM的起始地址(0x00000000)。因为上电后,CPU默认从0x00000000取第一条指令。这个地址必须放有效的代码,否则芯片就「死」了。
关键点:上电复位后,CPU从地址0x00000000开始执行。这个地址通常映射到内部ROM或Flash。如果内部ROM是空的,CPU就会跑飞。所以,Bootloader的第一件事,就是把外部Flash里的代码搬进内部RAM,然后跳转执行。
1.5 知识体系总览
为了让你更直观地理解本章的知识结构,我画了一张图:
这张图把本章的核心知识点串起来了。从DSP芯片概述出发,到具体的C6000架构,再到总线与存储器映射。你学完这一章,应该能回答三个问题:DSP是什么?C6000怎么工作的?代码和数据存在哪?
学习建议:别急着背寄存器地址。先理解架构的「为什么」——为什么用哈佛架构?为什么分功能单元?为什么存储器要分层?想通了这些,后面写代码自然水到渠成。
好了,这一章就到这里。下一章咱们开始动手,看看Bootloader到底是怎么把代码从Flash搬到RAM的。到时候我会拿一个实际项目中的例子,一步步带你走通启动流程。
公众号:蓝海资料掘金营,微信deep3321