概述
写作背景:我最近在写一个DSP的项目,由于上一次接触DSP处理器写代码是在一两年之前,再加上之前主要是学习了STM32,关于DSP的一些知识已经忘记得差不多了。现在重新捡起DSP来,又要花费大量得时间来重新找资料,读文档。所以产生了写点东西得想法,主要的目的是把DSP的硬件知识(主要是寄存器相关)和软件初始化的核心代码记录下来,使自己未来再一次使用DSP时能够快速熟悉必要知识开始项目,最后把基本的代码打包,以达到快速复盘的目的。
注:虽然本文基于TMS2802x,是由于常用的几种DSP型号结构是差不多的,也可以用作其他型号芯片的入门资料。
参考文档标注在图片地下和文章结尾处。
1. 时钟系统的主要结构
DSP时钟系统被称为其“心脏”,的主要结构包括振荡器(SOC),锁相环(PLL)和时钟机制。此外还包括看门狗,低功耗模式等内容,另外DSP处理器还带有3个CPU计时器(CPU Timer0/1/2)。这篇主要介绍前三项内容,对于掌握DSP运行的时钟走向和后续其他模块设置十分重要。
上面的图片可以清晰看到时钟信号的流向,从振荡时钟OSCCLK,经过中间的PLL和时钟机制,在这个过程中PLL有可能不使用(一般是使用的)。最后图上的输出信号CLKIN,从英文名称上称为时钟输入信号,实际上它是CPU的输入信号,因此也就是最终的CPU频率。需要指出的是图中OSCCLK并不是指某一个具体的信号,这是因为在2802x中这个信号可以有多个来源,需要根据具体的寄存器设置才能决定,因此首先说一下OSCCLK信号。
1.1振荡时钟的输入源选择
可以OSCCLK的来源主要有四个,两个内部振荡器,一个外部引脚输入和一个外部晶振。从上到下分别是internal OSC1,internal OSC2,XCLKIN以及外部晶振XTAL提供时基的(Crystal)OSC信号。需要注意的是XCLKIN和上一节提到的CLKIN的不同。四个信号经过层层“关卡”,最后只有某一个才能够成为OSCCLK,进而输入到PLL进行后面的“转换”。
常用的输入源是内部振荡OSC1和XTAL外部晶振信号。TI(德州仪器)官方给出的库文件初始化代码(后面会讲解),最终将输入源默认设置为10MHz,这已经完全够用。在平时项目中一般还会使用XTAL,也就是外部晶振作为时钟源。
1.2 锁相环PLL及时钟机制
这里再贴一次第一张图
OSCCLK信号需要经过两层“关卡”才能到达CLKIN送入CPU。第一层是锁存器PLL,锁存器的作用是对OSCCLK信号进行n倍频,也就是把其信号频率提升n倍,同时也可以不使用PLL,直接把信号送到下一层“关卡”,通过PLLSTS[PLLOFF],即PLL状态寄存器的第二位可以控制是否使用PLL。DSP在复位时该位为0,默认打开PLL。使用PLL可以倍频提高CPU的运算速度。n的大小取决于PLLCR[DIV](PLL控制寄存器)的值进行设定。
PLL对OSCCLK进行倍频的同时,下一层“关卡”会对信号进行分频,因此CLKIN的频率最终由PLLCR[DIV]和PLLSTS[DIVSEL]这两个位决定,对频率进行先乘后除后送入CPU。
1.3 CPU时钟CLKIN与外设时钟的关系
C28x Core是CPU,CLKIN信号送入CPU后,经过CPU的分发,作为SYSCLKOUT信号送往各个外设,因此:
S
Y
S
C
L
K
O
U
T
=
C
L
K
I
N
SYSCLKOUT=CLKIN
SYSCLKOUT=CLKIN,但是部分低速外设还需要经过LOSPCP寄存器变成LSPCLK后提供给相关外设。进行ADC,SCI等相关外设的设置时需要知道这个具体的频率数值来进行计算。
2. 主要需要关注的寄存器和寄存器位。
上图是DSP的系统控制寄存器(System Control Register File),包括了系统时钟相关的一系列寄存器,下面就重点提一下从时钟输入到CLKIN一路过来的主要寄存器和寄存器位。
主要是CLKCTL,这三个寄存器,复位后DSP内部的振荡器都处于开启状态,但是选择哪一个作为OSCCLK取决于CLKCTL的[OSCCLKSRCSEL]位,这一位复位默认为0,因此选择internal OSC1作为时钟源。之后便是PLLCR[DIV]和PLLSTS[DIVSEL]这两个寄存器共同决定CLKIN的频率。如下图所示:
需要指出的是PLLCR[DIV]在上电时为0,处于被旁路状态(旁路但是PLL处于运行状态),OSCCLK被四分频(OSCCLK/4)送入后面的信号,这是为了防止DSP超频导致系统启动时出问题。在官方的库代码中,上电后会对这两个位进行设置,比如将PLLCR[DIV]设置为12,PLLSTS[DIVSEL]设置为2,因此最终CPU运行频率为:(OSCCLK=10MHz * 12) / 2 = 60MHz,这也是数据手册给出的最大运行频率。
3. 库文件的初始化代码
在官方给出的库文件DSP2802x_SysCtrl.c中,主函数main进入后的第一个函数InitSysCtrl()
就是系统的初始话函数,包括的系统的时钟设置。
void InitSysCtrl(void)
{
// Disable the watchdog
DisableDog();
// *IMPORTANT*
// The Device_cal function, which copies the ADC & oscillator calibration values
// from TI reserved OTP into the appropriate trim registers, occurs automatically
// in the Boot ROM. If the boot ROM code is bypassed during the debug process, the
// following function MUST be called for the ADC and oscillators to function according
// to specification. The clocks to the ADC MUST be enabled before calling this
// function.
// See the device data manual and/or the ADC Reference
// Manual for more information.
EALLOW;
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // Enable ADC peripheral clock
(*Device_cal)();
SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0; // Return ADC clock to original state
EDIS;
// Select Internal Oscillator 1 as Clock Source (default), and turn off all unused clocks to
// conserve power.
IntOsc1Sel();
// Initialize the PLL control: PLLCR and DIVSEL
// DSP28_PLLCR and DSP28_DIVSEL are defined in DSP2802x_Examples.h
InitPll(DSP28_PLLCR,DSP28_DIVSEL);
// Initialize the peripheral clocks
InitPeripheralClocks();
}
首先的ADC的校准代码,这个放着先不管,之后是IntOscSel()
,该函数选择内部振荡器OSC1作为时钟源,并关闭其他未使用的时钟来降低功耗。
然后是InitPLL()
,用于设置PLLCR[DIV]和PLLSTS[DIVSEL]这两个位,具体实现方式不做描述。该函数具有两个参数,DSP28_PLLCR
和DSP28_DIVSEL
,通过宏定义的方式来确定具体的数值。修改宏定义便能确定CLKIN的最终频率。
宏定义位于DSP2802x_Example.h中。
/*-----------------------------------------------------------------------------
Specify the PLL control register (PLLCR) and divide select (DIVSEL) value.
-----------------------------------------------------------------------------*/
//#define DSP28_DIVSEL 0 // Enable /4 for SYSCLKOUT
//#define DSP28_DIVSEL 1 // Disable /4 for SYSCKOUT
#define DSP28_DIVSEL 2 // Enable /2 for SYSCLKOUT
//#define DSP28_DIVSEL 3 // Enable /1 for SYSCLKOUT
#define DSP28_PLLCR 12 // Uncomment for 60 MHz devices [60 MHz = (10MHz * 12)/2]
//#define DSP28_PLLCR 11
//#define DSP28_PLLCR 10 // Uncomment for 50 Mhz devices [50 Mhz = (10MHz * 10)/2]
//#define DSP28_PLLCR 9
//#define DSP28_PLLCR 8 // Uncomment for 40 MHz devices [40 MHz = (10MHz * 8)/2]
//#define DSP28_PLLCR 7
...
...
4.总结
总体来说,DSP的时钟系统虽然看起来比较复杂,但是对于初级的程序涉及到的寄存器和代码并不多,比较简单。
ps:还有一些图片和表述我觉得不够完善,后面再进行修改吧。
最后
以上就是可耐老虎为你收集整理的DSP快速复盘——时钟系统总结(基本知识+核心代码)基于TMS2802x处理器1. 时钟系统的主要结构2. 主要需要关注的寄存器和寄存器位。3. 库文件的初始化代码4.总结的全部内容,希望文章能够帮你解决DSP快速复盘——时钟系统总结(基本知识+核心代码)基于TMS2802x处理器1. 时钟系统的主要结构2. 主要需要关注的寄存器和寄存器位。3. 库文件的初始化代码4.总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复