DSP快速复盘——时钟系统总结(基本知识+核心代码)基于TMS2802x处理器

写作背景:我最近在写一个DSP的项目,由于上一次接触DSP处理器写代码是在一两年之前,再加上之前主要是学习了STM32,关于DSP的一些知识已经忘记得差不多了。现在重新捡起DSP来,又要花费大量得时间来重新找资料,读文档。所以产生了写点东西得想法,主要的目的是把DSP的硬件知识(主要是寄存器相关)和软件初始化的核心代码记录下来,使自己未来再一次使用DSP时能够快速熟悉必要知识开始项目,最后把基本的代码打包,以达到快速复盘的目的。
注:虽然本文基于TMS2802x,是由于常用的几种DSP型号结构是差不多的,也可以用作其他型号芯片的入门资料。

参考文档标注在图片地下和文章结尾处。

1. 时钟系统的主要结构

DSP时钟系统被称为其“心脏”,的主要结构包括振荡器(SOC),锁相环(PLL)和时钟机制。此外还包括看门狗,低功耗模式等内容,另外DSP处理器还带有3个CPU计时器(CPU Timer0/1/2)。这篇主要介绍前三项内容,对于掌握DSP运行的时钟走向和后续其他模块设置十分重要。
OSC和PLL模块Page=58
上面的图片可以清晰看到时钟信号的流向,从振荡时钟OSCCLK,经过中间的PLL和时钟机制,在这个过程中PLL有可能不使用(一般是使用的)。最后图上的输出信号CLKIN,从英文名称上称为时钟输入信号,实际上它是CPU的输入信号,因此也就是最终的CPU频率。需要指出的是图中OSCCLK并不是指某一个具体的信号,这是因为在2802x中这个信号可以有多个来源,需要根据具体的寄存器设置才能决定,因此首先说一下OSCCLK信号。

1.1振荡时钟的输入源选择

时钟输入源选择Page=53
可以OSCCLK的来源主要有四个,两个内部振荡器,一个外部引脚输入和一个外部晶振。从上到下分别是internal OSC1,internal OSC2,XCLKIN以及外部晶振XTAL提供时基的(Crystal)OSC信号。需要注意的是XCLKIN和上一节提到的CLKIN的不同。四个信号经过层层“关卡”,最后只有某一个才能够成为OSCCLK,进而输入到PLL进行后面的“转换”。
常用的输入源是内部振荡OSC1和XTAL外部晶振信号。TI(德州仪器)官方给出的库文件初始化代码(后面会讲解),最终将输入源默认设置为10MHz,这已经完全够用。在平时项目中一般还会使用XTAL,也就是外部晶振作为时钟源。

1.2 锁相环PLL及时钟机制

这里再贴一次第一张图
时钟输入源选择Page=53
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. 主要需要关注的寄存器和寄存器位。

PLL_Clocking_Watchdog_and_LowPower_Mode_Registers_page48
上图是DSP的系统控制寄存器(System Control Register File),包括了系统时钟相关的一系列寄存器,下面就重点提一下从时钟输入到CLKIN一路过来的主要寄存器和寄存器位。
主要是CLKCTL,这三个寄存器,复位后DSP内部的振荡器都处于开启状态,但是选择哪一个作为OSCCLK取决于CLKCTL的[OSCCLKSRCSEL]位,这一位复位默认为0,因此选择internal OSC1作为时钟源。之后便是PLLCR[DIV]和PLLSTS[DIVSEL]这两个寄存器共同决定CLKIN的频率。如下图所示:
PLL_Settings_page61
需要指出的是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_PLLCRDSP28_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:还有一些图片和表述我觉得不够完善,后面再进行修改吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值