没有标题的

目录

系统时钟

顺便一提Device_Cal:

 

void InitGpio(void)

void InitPieCtrl(void)


系统时钟

 

C28x Core是CPU,CLKIN信号送入CPU后,经过CPU的分发,作为SYSCLKOUT信号送往各个外设,因此:S Y S C L K O U T = C L K I N ,但是部分低速外设还需要经过LOSPCP寄存器变成LSPCLK后提供给相关外设。进行ADC,SCI等相关外设的设置时需要知道这个具体的频率数值来进行计算。

从上图可以看出SPI-A,SPI-B,SCI-A的时钟来自低速外设时钟LSPCLK; eCAN-A,LIN-A的时钟由SYSCLKOUT的二分频获得; 其它外设的时钟都是SYSCLKOUT。其中LSPCLK的大小由LOSPCP寄存器所设置,如下图:

这里写图片描述

 TMS320x2803x系列(28035为例)的时钟源选择,如下图:

 时钟源选择
2803x系列DSP有两个内部时钟源INTOSC1INTOSC2),可以不需要外部时钟。同时,也具有PLL时钟模块。一共有4种时钟源可供选择
1) INTOSC1(10MHz)
内部时钟源1(INTOSC1),此时钟提供给看门狗块模块,内核和CPU定时器2 。
时钟频率默认为10MHz,可以通过INTOSCnTRIM寄存器修改频率。
2) INTOSC2(10MHz)
功能与INTOSC1是一样的。
3) 外部晶体振荡器XTAL(10MHZ)
使用外部晶体振荡器给芯片提供时钟,晶振连接于X1/X2 脚。

10M晶振代表一个晶振的振荡周期是100ns,晶振的一头对地是100ns周期的正弦波,另一头是差不多1V的高电平
4) 外部时钟源XCLKIN(我的板子上没有这个外部时钟源)
如果不使用外部晶振作为时钟源,可以选择这种模式。时钟从外部时钟源的XCLKIN引脚输入生成。
注意:XCLKIN复用于GPIO19或GPIO38脚。可以通过XCLK寄存器的XCLKINSEL位选择是GPIO19还是GPIO38作为XCLKIN输入。
CLKCTL(XCLKINOFF)为1时,不使能此时钟。如果时钟源不使用或作为GPIO引脚时,用户应该在启动引导时禁用。
上面时钟图粗看起来很复杂,如果仔细分析,其实也很简单。从图的中间画一条分隔线,左边部分为4个输入时钟源,其中INTOSC1和INTOSC2是一模一样的,XTAL和XCLKIN是另外的两个时钟源; 右边部分三个时钟模块,从上到下分别是看门狗时钟WDCLK,系统时钟OSCCLK(此时钟到PLL),以及CPU定时器2时钟CPUTMR2CLK。
看完时钟框图后,下面是软件系统时钟的设置
在main函数的最初位置初始化DSP,即调用void InitialDSP(void)函数。

void InitPeripherals(void)
{
	// Step 1. Initialize System Control:
	// PLL, WatchDog, enable Peripheral Clocks
	// This example function is found in the DSP2803x_SysCtrl.c file.
	InitSysCtrl();
	// Step 2. Init GPIO:
	// This example function is found in the DSP2803x_Gpio.c file and
	// illustrates how to set the GPIO to it's default state.
	InitGpio();
	
	// Step 3. Clear all interrupts and initialize PIE vector table:
	// Disable CPU interrupts
	DINT;
	// Initialize the PIE control registers to their default state.
	// The default state is all PIE interrupts disabled and flags
	// are cleared.
	// This function is found in the DSP2803x_PieCtrl.c file.
	InitPieCtrl();
	// Disable CPU interrupts and clear all CPU interrupt flags:
	IER = 0x0000;
	IFR = 0x0000;
	// Initialize the PIE vector table with pointers to the shell Interrupt
	// Service Routines (ISR).
	// This will populate the entire table, even if the interrupt
	// is not used in this example.  This is useful for debug purposes.
	// The shell ISR routines are found in DSP2803x_DefaultIsr.c.
	// This function is found in DSP2803x_PieVect.c.
	InitPieVectTable();
	vCsmUnlock();
	// Step 4. Initialize all the Device Peripherals:
	memcpy((unsigned int *)&RamfuncsRunStart,(unsigned int *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize);
	InitFlash();
	vClearRam();
	InitCla();
	InitAdc();
	//InitComp();
	InitCpuTimers();
	ConfigCpuTimer(&CpuTimer0, 60, 1000,0);
    InitEPwm();
	InitSci();
	InitI2C();
	InitECan();
	//InitECap();
			
	// Step 5. User specific code, enable interrupts
	EALLOW;
	Flash_CPUScaleFactor = SCALE_FACTOR;
	Flash_CallbackPtr = (void*)0;
    EDIS;
	// Interrupts that are used in this example are re-mapped to
	// ISR functions found within this file.
    //EALLOW;  // This is needed to write to EALLOW protected registers
	//PieVectTable.XINT1 = &vSinSyncIn_isr;
    //PieVectTable.EPWM3_INT = &vPwm3Int_isr;
	//EDIS;   // This is needed to disable write to EALLOW protected registers

	//PieCtrlRegs.PIEIER1.bit.INTx4 = 1;          // Enable PIE Group 1 INT4
	//PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
	//PieCtrlRegs.PIEACK.all = PIEACK_GROUP1|PIEACK_GROUP3;
	//IER |= M_INT1|M_INT3;                              // Enable CPU INT1
	DINT;                                       // Enable Global Interrupts
    DRTM;
}

void InitPeripherals(void)
{
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2803x_SysCtrl.c file.
    InitSysCtrl();
    // Step 2. Init GPIO:
    // This example function is found in the DSP2803x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    InitGpio();
    
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    DINT;
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the DSP2803x_PieCtrl.c file.
    InitPieCtrl();
    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

Interrupt 1标志。INT1是连接到CPU中断级别INT1的中断标志。
0没有INT1中断挂起
1至少有一个INT1中断挂起。给这个位写一个0,将它清除为0,并清除中断请求
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in DSP2803x_DefaultIsr.c.
    // This function is found in DSP2803x_PieVect.c.
    InitPieVectTable();
    vCsmUnlock();
    // Step 4. Initialize all the Device Peripherals:
    memcpy((unsigned int *)&RamfuncsRunStart,(unsigned int *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize);
    InitFlash();
    vClearRam();
    InitCla();
    InitAdc();
    //InitComp();
    InitCpuTimers();
    ConfigCpuTimer(&CpuTimer0, 60, 1000,0);
    InitEPwm();
    InitSci();
    InitI2C();
    InitECan();
    //InitECap();
            
    // Step 5. User specific code, enable interrupts
    EALLOW;
    Flash_CPUScaleFactor = SCALE_FACTOR;
    Flash_CallbackPtr = (void*)0;
    EDIS;
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //EALLOW;  // This is needed to write to EALLOW protected registers
    //PieVectTable.XINT1 = &vSinSyncIn_isr;
    //PieVectTable.EPWM3_INT = &vPwm3Int_isr;
    //EDIS;   // This is needed to disable write to EALLOW protected registers

 

 

 

 

    //PieCtrlRegs.PIEIER1.bit.INTx4 = 1;          // Enable PIE Group 1 INT4
    //PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
    //PieCtrlRegs.PIEACK.all = PIEACK_GROUP1|PIEACK_GROUP3;
    //IER |= M_INT1|M_INT3;                              // Enable CPU INT1
    DINT;                                       // Enable Global Interrupts
    DRTM;
}

 

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();
	XtalOscSel();						    //
    // Initialize the PLL control: PLLCR and CLKINDIV
    // DSP28_PLLCR and DSP28_CLKINDIV are defined in DSP2803x_Examples.h
    InitPll(DSP28_PLLCR,DSP28_DIVSEL);     //External clock 20MHz, Fosc=60MHz
    // Initialize the peripheral clocks
    InitPeripheralClocks();
}
void XtalOscSel (void)  {
	EALLOW;
     SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 0;     // Turn on XTALOSC
     SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1;      // Turn off XCLKIN
     SysCtrlRegs.CLKCTL.bit.OSCCLKSRC2SEL = 0;  // Switch to external clock
     SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 1;   // Switch from INTOSC1 to INTOSC2/ext clk
     SysCtrlRegs.CLKCTL.bit.WDCLKSRCSEL = 1;    // Switch Watchdog Clk Src to external clock
     SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1;		// Turn off INTOSC2
     SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 1;		// Turn off INTOSC1
    EDIS;
}

void XtalOscSel (void)  {
    EALLOW;
     SysCtrlRegs.CLKCTL.bit.XTALOSCOFF = 0;     // Turn on XTALOSC
     SysCtrlRegs.CLKCTL.bit.XCLKINOFF = 1;      // Turn off XCLKIN
     SysCtrlRegs.CLKCTL.bit.OSCCLKSRC2SEL = 0;  // Switch to external clock
     SysCtrlRegs.CLKCTL.bit.OSCCLKSRCSEL = 1;   // Switch from INTOSC1 to INTOSC2/ext clk
     SysCtrlRegs.CLKCTL.bit.WDCLKSRCSEL = 1;    // Switch Watchdog Clk Src to external clock
     SysCtrlRegs.CLKCTL.bit.INTOSC2OFF = 1;        // Turn off INTOSC2
     SysCtrlRegs.CLKCTL.bit.INTOSC1OFF = 1;        // Turn off INTOSC1
    EDIS;
}

void InitPll(Uint16 val, Uint16 divsel)
{
   volatile Uint16 iVol;

   // Make sure the PLL is not running in limp mode
   if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
   {
	  EALLOW;
      // OSCCLKSRC1 failure detected. PLL running in limp mode.
      // Re-enable missing clock logic.
      SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;
      EDIS;
      // Replace this line with a call to an appropriate
      // SystemShutdown(); function.
      asm("        ESTOP0");     // Uncomment for debugging purposes
   }

   // DIVSEL MUST be 0 before PLLCR can be changed from
   // 0x0000. It is set to 0 by an external reset XRSn
   // This puts us in 1/4
   if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
   {
       EALLOW;
       SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
       EDIS;
   }

   // Change the PLLCR
   if (SysCtrlRegs.PLLCR.bit.DIV != val)
   {

      EALLOW;
      // Before setting PLLCR turn off missing clock detect logic
      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
      SysCtrlRegs.PLLCR.bit.DIV = val;
      EDIS;

      // Optional: Wait for PLL to lock.
      // During this time the CPU will switch to OSCCLK/2 until
      // the PLL is stable.  Once the PLL is stable the CPU will
      // switch to the new PLL value.
      //
      // This time-to-lock is monitored by a PLL lock counter.
      //
      // Code is not required to sit and wait for the PLL to lock.
      // However, if the code does anything that is timing critical,
      // and requires the correct clock be locked, then it is best to
      // wait until this switching has completed.

      // Wait for the PLL lock bit to be set.

      // The watchdog should be disabled before this loop, or fed within
      // the loop via ServiceDog().

	  // Uncomment to disable the watchdog
      DisableDog();

      while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
      {
	      // Uncomment to service the watchdog
          // ServiceDog();
      }

      EALLOW;
      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
      EDIS;
    }

    // If switching to 1/2
	if((divsel == 1)||(divsel == 2))
	{
		EALLOW;
	    SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
	    EDIS;
	}

	// If switching to 1/1
	// * First go to 1/2 and let the power settle
	//   The time required will depend on the system, this is only an example
	// * Then switch to 1/1
	if(divsel == 3)
	{
		EALLOW;
	    SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
	    DELAY_US(50L);
	    SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
	    EDIS;
    }
}

 注意:当我用delay_ms()函数来延时灯的亮灭时,改变分频和倍频可以改变灯的亮灭速度。

但是调用了官方的延时函数,即便改变了倍频和分频因子,改变函数的延时时间并没有改变,比如延时1s,就真的是延时1s。

 

void InitPll(Uint16 val, Uint16 divsel)
{
   volatile Uint16 iVol;

   // Make sure the PLL is not running in limp mode
   if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
   {

缺少时钟状态位。在复位后检查此位的状态,以确定是否检测到缺失的振荡器条件。
在正常情况下,该位应为0。对该位的写入将被忽略。该位将通过写入MCLKCLR位或强制外部重置来清除。
0表示正常操作。未检测到丢失的时钟条件。
1检测到OSCCLK缺失。主振荡器故障检测逻辑已重置设备和CPU现在被锁相环工作在软模频率上计时。当缺失的时钟检测电路自动在OSCCLKSRC2和OSCCLKSRC1之间切换时(在检测到OSCCLKSRC2故障后),该位将自动清除,缺失的时钟检测电路将重新启用。对于所有其他情况,用户需要通过向MCLKCLR位写入1来重新启用此模式。


      EALLOW;
      // OSCCLKSRC1 failure detected. PLL running in limp mode.
      // Re-enable missing clock logic.
      SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;

缺失时钟清除位。
0 写一个0没有效果。这个位总是读为0。
1强制清除缺失的时钟检测电路并复位。
如果OSCCLK仍然缺失,检测电路将再次对系统产生复位,设置缺失的时钟状态位(MCLKSTS), CPU将由软模频率下运行的锁相环供电。
      EDIS;
      // Replace this line with a call to an appropriate
      // SystemShutdown(); function.
      asm("        ESTOP0");     // Uncomment for debugging purposes
   }

   // DIVSEL MUST be 0 before PLLCR can be changed from
   // 0x0000. It is set to 0 by an external reset XRSn
   // This puts us in 1/4
   if (SysCtrlRegs.PLLSTS.bit.DIVSEL != 0)
   {
       EALLOW;
       SysCtrlRegs.PLLSTS.bit.DIVSEL = 0;
       EDIS;

Divide Select:当CLKIN到CPU时,在/4、/2和/1之间进行选择。
DIVSEL位的配置如下:
00, 01“CLKIN”选择“除以4”
10在“CLKIN”中选择“除以2”
11选择“CLKIN”的“除1”。(该模式只能在关闭或绕过锁相环时使用。)
   }

   // Change the PLLCR
   if (SysCtrlRegs.PLLCR.bit.DIV != val)


 

 {

      EALLOW;
      // Before setting PLLCR turn off missing clock detect logic
      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;

缺失时钟检测关闭位
0启用主振荡器故障检测逻辑。(默认)
1主振荡器故障检测逻辑被禁用,锁相环将不会发出跛行模式时钟。
当代码不能受到检测电路的影响时,使用此模式。
例如,如果外部时钟被关闭。


      SysCtrlRegs.PLLCR.bit.DIV = val;
      EDIS;

      // Optional: Wait for PLL to lock.
      // During this time the CPU will switch to OSCCLK/2 until
      // the PLL is stable.  Once the PLL is stable the CPU will
      // switch to the new PLL value.
      //
      // This time-to-lock is monitored by a PLL lock counter.
      //
      // Code is not required to sit and wait for the PLL to lock.
      // However, if the code does anything that is timing critical,
      // and requires the correct clock be locked, then it is best to
      // wait until this switching has completed.

      // Wait for the PLL lock bit to be set.

      // The watchdog should be disabled before this loop, or fed within
      // the loop via ServiceDog().

      // Uncomment to disable the watchdog
      DisableDog();

      while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
      {
          // Uncomment to service the watchdog
          // ServiceDog();锁相锁状态位。
0表示PLLCR寄存器已被写入,PLL当前处于锁定状态。CPU被OSCCLK/2时钟控制,直到锁相锁锁。
1锁相环锁定完成,处于稳定状态。
      }

      EALLOW;
      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;

缺少时钟检测关闭位
0启用主振荡器故障检测逻辑。(默认)
1主振荡器故障检测逻辑被禁用,锁相环将不会发出跛行模式时钟。当代码不能受到检测电路的影响时,使用此模式。例如,如果外部时钟被关闭。


      EDIS;
    }

    // If switching to 1/2
    if((divsel == 1)||(divsel == 2))
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = divsel;
        EDIS;
    }

    // If switching to 1/1
    // * First go to 1/2 and let the power settle
    //   The time required will depend on the system, this is only an example
    // * Then switch to 1/1
    if(divsel == 3)
    {
        EALLOW;
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 2;
        DELAY_US(50L);
        SysCtrlRegs.PLLSTS.bit.DIVSEL = 3;
        EDIS;
    }
}

 8-7:

分割选择:CLKIN到CPU的位在/4,/2和/1之间选择。

DIVSEL位的配置如下:

00,01 对于CLKIN选择“除4”

10 在“CLKIN”选项中选择“除2”

11 选择“CLKIN”对应的“除1”。(此模式只能在锁相环关闭或旁路时使用。)

  • 6位:MCLKOFF,丢失时钟检测关闭位;
    • 0——默认设置,主振荡器时钟丢失检测使能
    • 1——主振荡器时钟丢失检测禁止
  • 5位:OSCOFF,控制振荡器时钟信号,该位为1,振荡器信号允许通过,兵分两路,一路直接过去,一路进入锁相环模块;
  • 4位:MCLKCLR,丢失时钟清除位,若该位写0,无效,写1强制丢失时钟信号检测电路清除和复位;
  • 3位:MCLKSTS, 丢失时钟信号状态位,0为正常模式,表示时钟信号没有丢失,1表示时钟信号丢失,CPU工作在无序频率模式;
  • 2位:PLLOFF,锁相器关闭位;
  • 1位:保留;
  • 0位:PLLOCKS:锁相器锁状态位。

 上面的代码都是按照手册里提供的程序流程图来写的,下面把PLLCR更改的程序流程图贴出来。

void InitPeripheralClocks(void)
{
   EALLOW;

// LOSPCP prescale register settings, normally it will be set to default values

   GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0;  // GPIO18 = XCLKOUT
   SysCtrlRegs.LOSPCP.all = 0x0002;

// XCLKOUT to SYSCLKOUT ratio.  By default XCLKOUT = 1/4 SYSCLKOUT
   SysCtrlRegs.XCLK.bit.XCLKOUTDIV=3;   //turn off

// Peripheral clock enables set for the selected peripherals.
// If you are not using a peripheral leave the clock off
// to save on power.
//
// Note: not all peripherals are available on all 2803x derivates.
// Refer to the datasheet for your particular device.
//
// This function is not written to be an example of efficient code.

//We will turn on the Peripheral clock later
   SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;      // ADC
   SysCtrlRegs.PCLKCR3.bit.COMP1ENCLK = 0;    // COMP1
   SysCtrlRegs.PCLKCR3.bit.COMP2ENCLK = 0;    // COMP2
   SysCtrlRegs.PCLKCR3.bit.COMP3ENCLK = 0;    // COMP3
   SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 0;    // eCAP1
   SysCtrlRegs.PCLKCR0.bit.ECANAENCLK=	0;      // eCAN-A
   SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK = 0;    // eQEP1
   SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 0;    // ePWM1
   SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 0;    // ePWM2
   SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK = 0;    // ePWM3
   SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK = 0;    // ePWM4
   SysCtrlRegs.PCLKCR1.bit.EPWM5ENCLK = 0;	  // ePWM5
   SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 0;	  // ePWM6
   SysCtrlRegs.PCLKCR0.bit.HRPWMENCLK = 0;    // HRPWM
   SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 0;     // I2C
   SysCtrlRegs.PCLKCR0.bit.LINAENCLK = 0;     // LIN-A
   SysCtrlRegs.PCLKCR3.bit.CLA1ENCLK = 0;     // CLA1
   SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 0;     // SCI-A
   SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 0;     // SPI-A
   SysCtrlRegs.PCLKCR0.bit.SPIBENCLK = 0;     // SPI-B

   SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;     // Disable TBCLK within the ePWM

   EDIS;
}

void InitPeripheralClocks(void)
{
   EALLOW;

// LOSPCP prescale register settings, normally it will be set to default values

   GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 0;  // GPIO18 = XCLKOUT
   SysCtrlRegs.LOSPCP.all = 0x0002;

 

// XCLKOUT to SYSCLKOUT ratio.  By default XCLKOUT = 1/4 SYSCLKOUT
   SysCtrlRegs.XCLK.bit.XCLKOUTDIV=3;   //turn off

// Peripheral clock enables set for the selected peripherals.
// If you are not using a peripheral leave the clock off
// to save on power.
//
// Note: not all peripherals are available on all 2803x derivates.
// Refer to the datasheet for your particular device.
//
// This function is not written to be an example of efficient code.

//We will turn on the Peripheral clock later
   SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;      // 关ADC
   SysCtrlRegs.PCLKCR3.bit.COMP1ENCLK = 0;    // COMP1
   SysCtrlRegs.PCLKCR3.bit.COMP2ENCLK = 0;    // COMP2
   SysCtrlRegs.PCLKCR3.bit.COMP3ENCLK = 0;    // COMP3
   SysCtrlRegs.PCLKCR1.bit.ECAP1ENCLK = 0;    // eCAP1
   SysCtrlRegs.PCLKCR0.bit.ECANAENCLK=    0;      // eCAN-A
   SysCtrlRegs.PCLKCR1.bit.EQEP1ENCLK = 0;    // eQEP1
   SysCtrlRegs.PCLKCR1.bit.EPWM1ENCLK = 0;    // ePWM1
   SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK = 0;    // ePWM2
   SysCtrlRegs.PCLKCR1.bit.EPWM3ENCLK = 0;    // ePWM3
   SysCtrlRegs.PCLKCR1.bit.EPWM4ENCLK = 0;    // ePWM4
   SysCtrlRegs.PCLKCR1.bit.EPWM5ENCLK = 0;      // ePWM5
   SysCtrlRegs.PCLKCR1.bit.EPWM6ENCLK = 0;      // ePWM6
   SysCtrlRegs.PCLKCR0.bit.HRPWMENCLK = 0;    // HRPWM
   SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 0;     // I2C
   SysCtrlRegs.PCLKCR0.bit.LINAENCLK = 0;     // LIN-A
   SysCtrlRegs.PCLKCR3.bit.CLA1ENCLK = 0;     // CLA1
   SysCtrlRegs.PCLKCR0.bit.SCIAENCLK = 0;     // SCI-A
   SysCtrlRegs.PCLKCR0.bit.SPIAENCLK = 0;     // SPI-A
   SysCtrlRegs.PCLKCR0.bit.SPIBENCLK = 0;     // SPI-B

   SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;     // Disable TBCLK within the ePWM

   EDIS;
}

锁相环PLL及时钟机制 

 时钟输入源选择Page=53

XCLKOUT信号直接来自于系统时钟SYSCLKOUT,如图25所示。

XCLKOUT可以等于SYSCLKOUT的1 或1/2或1 / 4。默认情况下,上电时,XCLKOUT = syclkout /4或XCLKOUT = OSCCLK/16。

注意:要想使用XCLKOUT这个引脚输出时钟信号的话,在XCLKOUTDIV[1:0]不能选择11,而且得复用引脚改为XLCKOUT。

GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3; 

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。
 

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,这也是数据手册给出的最大运行频率。

顺便一提Device_Cal:

 

Device_cal()例程被工厂编程到TI预留内存中。引导ROM自动调用Device_cal()例程,用设备特定的校准数据校准内部振荡器和ADC。在正常操作中,这个过程会自动发生,用户不需要做任何操作。

如果在开发过程中Code Composer Studio绕过了引导ROM,那么必须由应用程序初始化校准。工作示例请参见《C280 3x C/ c++头文件和外设示例》中的系统初始化。

注意:初始化这些寄存器失败将导致振荡器和ADC功能不符合规格。以下三个步骤描述了如何从应用程序调用Device_cal例程。

步骤1:创建一个指向Device_cal函数的指针,如例2-5所示。这个#定义包含在头文件和外设示例中。

步骤2:调用Device_cal()所指向的函数,如例2-5所示。在进行此调用之前,必须启用ADC时钟。

 

void InitGpio(void)

void InitGpio(void)
{
	EALLOW;
  
	//Input IO

	//Test Mode Pin: Enable Pull Up, Qualification using 3 samples, Input GPIO
    //GpioCtrlRegs.GPAPUD.bit.GPIO9 = 0;
	//GpioCtrlRegs.GPAQSEL1.bit.GPIO9 = 1;
	//GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 0;
	//GpioCtrlRegs.GPADIR.bit.GPIO9 = 0;
	
    //Output IO
    
	//SHCP : Disable Pull Up, Set Low
	GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;
	GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;
	GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;

    //RLY_DRV : Disable Pull Up, Set Low
	GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;
	GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;
	GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
    
    //DE : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO20 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO20 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO20 = 1;

    //STCP : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO21 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO21 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO21 = 1;

    //WP : Disable Pull Up, Set High
    GpioCtrlRegs.GPAPUD.bit.GPIO24 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 0;
    GpioDataRegs.GPASET.bit.GPIO24 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO24 = 1;
    
    //DS : Disable Pull Up, Set High
    GpioCtrlRegs.GPBPUD.bit.GPIO35 = 1;
    GpioCtrlRegs.GPBMUX1.bit.GPIO35 = 0;
    GpioDataRegs.GPBCLEAR.bit.GPIO35 = 1;
    GpioCtrlRegs.GPBDIR.bit.GPIO35 = 1;

	EDIS;	


}

void InitGpio(void)
{
    EALLOW;
  
    //Input IO

    //Test Mode Pin: Enable Pull Up, Qualification using 3 samples, Input GPIO
    //GpioCtrlRegs.GPAPUD.bit.GPIO9 = 0;
    //GpioCtrlRegs.GPAQSEL1.bit.GPIO9 = 1;为GPIO0到GPIO15选择输入限定类型。每个GPIO输入的输入限定由两个位控制,如图57所示。
00只同步到SYSCLKOUT。适用于外设和GPIO引脚。
01使用3个样品进行鉴定。对配置为GPIO或外设功能的引脚有效。
样本之间的时间间隔在GPACTRL寄存器中指定。
10使用6个样品进行鉴定。对配置为GPIO或外设功能的引脚有效。
样本之间的时间间隔在GPACTRL寄存器中指定。
11异步。(没有同步或限定)。此选项仅适用于配置为外设的引脚。如果将引脚配置为GPIO输入,则该选项与0,0相同,或者同步到SYSCLKOUT。
    //GpioCtrlRegs.GPAMUX1.bit.GPIO9 = 0;
    //GpioCtrlRegs.GPADIR.bit.GPIO9 = 0;
    
    //Output IO
    
    //SHCP : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;每个GPIO端口A引脚(GPIO0-GPIO31)对应于这个寄存器中的一个位,如图68所示。
0的写操作被忽略。
这个寄存器总是读回一个0。
1写一个1迫使各自的输出数据锁存到低。
如果引脚被配置为GPIO输出,那么它将被驱动到低电平。
如果引脚没有被配置为GPIO输出,那么锁存被清除,但是引脚没有被驱动。
    GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;

 

 

 

    //RLY_DRV : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO4 = 1;
    GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;
    
    //DE : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO20 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO20 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO20 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO20 = 1;

    //STCP : Disable Pull Up, Set Low
    GpioCtrlRegs.GPAPUD.bit.GPIO21 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO21 = 0;
    GpioDataRegs.GPACLEAR.bit.GPIO21 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO21 = 1;

    //WP : Disable Pull Up, Set High
    GpioCtrlRegs.GPAPUD.bit.GPIO24 = 1;
    GpioCtrlRegs.GPAMUX2.bit.GPIO24 = 0;
    GpioDataRegs.GPASET.bit.GPIO24 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO24 = 1;
    
    //DS : Disable Pull Up, Set High
    GpioCtrlRegs.GPBPUD.bit.GPIO35 = 1;
    GpioCtrlRegs.GPBMUX1.bit.GPIO35 = 0;
    GpioDataRegs.GPBCLEAR.bit.GPIO35 = 1;
    GpioCtrlRegs.GPBDIR.bit.GPIO35 = 1;

    EDIS;    
}

void InitPieCtrl(void)
{
    // Disable Interrupts at the CPU level:
    DINT;

    // Disable the PIE
    PieCtrlRegs.PIECTRL.bit.ENPIE = 0;

	// Clear all PIEIER registers:
	PieCtrlRegs.PIEIER1.all = 0;
	PieCtrlRegs.PIEIER2.all = 0;
	PieCtrlRegs.PIEIER3.all = 0;	
	PieCtrlRegs.PIEIER4.all = 0;
	PieCtrlRegs.PIEIER5.all = 0;
	PieCtrlRegs.PIEIER6.all = 0;
	PieCtrlRegs.PIEIER7.all = 0;
	PieCtrlRegs.PIEIER8.all = 0;
	PieCtrlRegs.PIEIER9.all = 0;
	PieCtrlRegs.PIEIER10.all = 0;
	PieCtrlRegs.PIEIER11.all = 0;
	PieCtrlRegs.PIEIER12.all = 0;

	// Clear all PIEIFR registers:
	PieCtrlRegs.PIEIFR1.all = 0;
	PieCtrlRegs.PIEIFR2.all = 0;
	PieCtrlRegs.PIEIFR3.all = 0;	
	PieCtrlRegs.PIEIFR4.all = 0;
	PieCtrlRegs.PIEIFR5.all = 0;
	PieCtrlRegs.PIEIFR6.all = 0;
	PieCtrlRegs.PIEIFR7.all = 0;
	PieCtrlRegs.PIEIFR8.all = 0;
	PieCtrlRegs.PIEIFR9.all = 0;
	PieCtrlRegs.PIEIFR10.all = 0;
	PieCtrlRegs.PIEIFR11.all = 0;
	PieCtrlRegs.PIEIFR12.all = 0;

}	

 

PIE

 

 

 

 

 

 PIE向量表(见表1-119)由256 × 16的SARAM块组成,如果PIE块没有被使用,它也可以用作RAM(仅在数据空间中)。
PIE向量表内容在重置时未定义。
CPU处理INT1到INT12的中断优先级。
PIE控制每组8个中断的优先级。
例如,如果INT1.1应该与INT8.1同时发生,这两个中断将由PIE块同时提交给CPU,并且CPU服务INT1.1优先。
如果INT1.1和INT1.8同时发生,则首先将INT1.1发送给CPU,然后再将INT1.8发送给CPU。



在表1-118中96个可能的MUXed中断中,目前使用了43个中断。
其余的中断为将来的设备保留。

 

 

 

void InitPieCtrl(void)


{
    // Disable Interrupts at the CPU level:
    DINT;

    // Disable the PIE
    PieCtrlRegs.PIECTRL.bit.ENPIE = 0;

 启用从PIE向量表中获取向量。
注意:重置向量永远不会从PIE中获取,即使它是启用的。
这个向量总是从引导ROM中获取。
0如果该位设置为0,则禁用PIE块,并从引导ROM中的CPU向量表中获取向量。即使禁用了PIE块,也可以访问所有的PIE块寄存器(PIEACK, PIEIFR, PIEIER)。
1当ENPIE设置为1时,除reset外的所有向量都从PIE向量表中获取。
重置向量总是从引导ROM中获取。

    // Clear all PIEIER registers:
    PieCtrlRegs.PIEIER1.all = 0;这些寄存器位单独启用一个组中的中断,行为非常类似于核心中断启用寄存器。
将位设置为1将启用对相应中断的服务。
将位设置为0将禁用中断服务。X = 1到12。INTx表示CPU INT1 ~ INT12
    PieCtrlRegs.PIEIER2.all = 0;
    PieCtrlRegs.PIEIER3.all = 0;    
    PieCtrlRegs.PIEIER4.all = 0;
    PieCtrlRegs.PIEIER5.all = 0;
    PieCtrlRegs.PIEIER6.all = 0;
    PieCtrlRegs.PIEIER7.all = 0;
    PieCtrlRegs.PIEIER8.all = 0;
    PieCtrlRegs.PIEIER9.all = 0;
    PieCtrlRegs.PIEIER10.all = 0;
    PieCtrlRegs.PIEIER11.all = 0;
    PieCtrlRegs.PIEIER12.all = 0;

 

 

    // Clear all PIEIFR registers:
    PieCtrlRegs.PIEIFR1.all = 0;这些寄存器位指示中断当前是否处于活动状态。
它们的行为非常像CPU中断标志寄存器。
当一个中断是活动的,相应的寄存器位被设置。
当中断被服务时,或者通过向寄存器位写入0来清除该位。
还可以读取该寄存器以确定哪些中断是活动的或挂起的。
X = 1到12。
INTx表示CPU INT1 ~ INT12。
在中断处理的中断向量提取部分,piifr寄存器位被清除。
硬件优先于CPU访问PIEIFR寄存器。
    PieCtrlRegs.PIEIFR2.all = 0;
    PieCtrlRegs.PIEIFR3.all = 0;    
    PieCtrlRegs.PIEIFR4.all = 0;
    PieCtrlRegs.PIEIFR5.all = 0;
    PieCtrlRegs.PIEIFR6.all = 0;
    PieCtrlRegs.PIEIFR7.all = 0;
    PieCtrlRegs.PIEIFR8.all = 0;
    PieCtrlRegs.PIEIFR9.all = 0;
    PieCtrlRegs.PIEIFR10.all = 0;
    PieCtrlRegs.PIEIFR11.all = 0;
    PieCtrlRegs.PIEIFR12.all = 0;

}    

 

void InitPieVectTable(void)
{
	int16	i;
	Uint32 *Source = (void *) &PieVectTableInit;
	Uint32 *Dest = (void *) &PieVectTable;

	// Do not write over first 3 32-bit locations (these locations are
	// initialized by Boot ROM with boot variables)

	Source = Source + 3;
	Dest = Dest + 3;

	EALLOW;
	for(i=0; i < 125; i++)
		*Dest++ = *Source++;
	EDIS;

	// Enable the PIE Vector Table
	PieCtrlRegs.PIECTRL.bit.ENPIE = 1;

}

在任何复位之后,CPU从地址0x3FFFC0(重置向量)开始执行,它在引导ROM中。
在运行引导ROM代码之后,CPU通常会分支到地址0x80000的闪存开始。
有关控制引导过程的更多信息,请参阅ROM代码和外围设备引导章节。

 

 

uint16 vCsmUnlock()

Uint16 vCsmUnlock()
{
    volatile Uint16 temp;
    
    // Load the key registers with the current password
    // These are defined in Example_Flash2803x_CsmKeys.asm
    
    EALLOW;
    CsmRegs.KEY0 = PRG_key0;
    CsmRegs.KEY1 = PRG_key1;
    CsmRegs.KEY2 = PRG_key2;
    CsmRegs.KEY3 = PRG_key3;
    CsmRegs.KEY4 = PRG_key4;
    CsmRegs.KEY5 = PRG_key5;
    CsmRegs.KEY6 = PRG_key6;
    CsmRegs.KEY7 = PRG_key7;   
    EDIS;

    // Perform a dummy read of the password locations
    // if they match the key values, the CSM will unlock 
        
    temp = CsmPwl.PSWD0;
    temp = CsmPwl.PSWD1;
    temp = CsmPwl.PSWD2;
    temp = CsmPwl.PSWD3;
    temp = CsmPwl.PSWD4;
    temp = CsmPwl.PSWD5;
    temp = CsmPwl.PSWD6;
    temp = CsmPwl.PSWD7;

    // If the CSM unlocked, return succes, otherwise return
    // failure.
    if ( (CsmRegs.CSMSCR.all & 0x0001) == 0) return 1;
    else return STATUS_FAIL_CSM_LOCKED;    
}

 

 

1.2.3在用户应用程序中引入代码安全
在项目的开发阶段通常不需要代码安全性;
然而,一旦开发出健壮的代码,安全性是必需的。
在闪存中编写这样的代码之前,应该选择一个密码来保护设备。
一旦设置了密码,设备就得到了保护(也就是说,在适当的位置编程一个密码,执行设备重置或设置FORCESEC位(CSMSCR.15)是保护设备的操作)。
从那时起,通过任何方式(通过JTAG、外部/片上内存运行的代码等)访问调试安全内存的内容都需要提供有效的密码。
在安全内存中运行代码不需要密码(例如在典型的最终客户使用中);
但是,为了调试目的访问安全内存内容需要密码。

 

 

 memcpy函数

memcpy((unsigned int *)&RamfuncsRunStart,(unsigned int *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize);

LOAD_START(_RamfuncsLoadStart) 指ramfuncs这段代码的加载开始地址
  LOAD_END(_RamfuncsLoadEnd),指ramfuncs这段代码的加载结束地址
这里的RamfuncsLoad一般是FLASH

  RUN_START(_RamfuncsRunStart),指ramfuncs这段代码的运行开始地址
意思是把ramfuncs拷到RAM中执行

InitFlash函数

void InitFlash(void)
{
   EALLOW;
   //Enable Flash Pipeline mode to improve performance
   //of code executed from Flash.
   FlashRegs.FOPT.bit.ENPIPE = 1;

   //                CAUTION
   //Minimum waitstates required for the flash operating
   //at a given CPU rate must be characterized by TI.
   //Refer to the datasheet for the latest information.

   //Set the Paged Waitstate for the Flash
   FlashRegs.FBANKWAIT.bit.PAGEWAIT = 2;

   //Set the Random Waitstate for the Flash
   FlashRegs.FBANKWAIT.bit.RANDWAIT = 2;

   //Set the Waitstate for the OTP
   FlashRegs.FOTPWAIT.bit.OTPWAIT = 2;

   //                CAUTION
   //ONLY THE DEFAULT VALUE FOR THESE 2 REGISTERS SHOULD BE USED
   FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF;
   FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF;
   EDIS;

   //Force a pipeline flush to ensure that the write to
   //the last register configured occurs before returning.

   asm(" RPT #7 || NOP");
}

 

void InitFlash(void)
{
   EALLOW;
   //Enable Flash Pipeline mode to improve performance
   //of code executed from Flash.
   FlashRegs.FOPT.bit.ENPIPE = 1;

使能Flash Pipeline Mode Bit。设置此位时,Flash流水线模式激活。流水线模式通过预取指令来提高指令获取的性能。有关更多信息,请参见第1.3.2节。

当管道模式被启用时,flash等待状态(分页和随机)必须大于零。

在flash设备上,ENPIPE影响从flash和OTP的读取。

0 Flash流水线模式未激活。(默认)

1 Flash“Pipeline”模式激活。

打开Flash Pipeline模式,以提高Flash执行代码的性能。

   //                CAUTION
   //Minimum waitstates required for the flash operating
   //at a given CPU rate must be characterized by TI.
   //Refer to the datasheet for the latest information.

   //Set the Paged Waitstate for the Flash
   FlashRegs.FBANKWAIT.bit.PAGEWAIT = 2;

 

Flash page读等待状态。这些寄存器位指定了在CPU时钟周期(0..15SYSCLKOUT周期)到闪存银行。请参阅第1.3.1节了解更多信息。

关于page flash访问所需的最小时间,请参阅特定于设备的数据手册。

您必须将RANDWAIT设置为大于或等于PAGEWAIT设置的值。没有提供硬件来检测大于RANDWAIT的PAGEWAIT值。

0000  每次分页flash访问零等待状态或每次访问一个syclkout周期

0001 每次分页flash访问一个等待状态,或者每次访问总共有两个syclkout周期

0010每次分页flash访问有两个等待状态,或者每次访问总共有三个syclkout周期

0011每次分页flash访问有三个等待状态,或者每次访问总共有四个syclkout周期

. . . . . .

1111每次分页flash访问有15个等待状态,或者每次访问总共有16个SYSCLKOUT周期。(默认)

 

   //Set the Random Waitstate for the Flash
   FlashRegs.FBANKWAIT.bit.RANDWAIT = 2;

Flash随机读等待状态。这些寄存器位指定了CPU时钟周期(1..15)中随机读操作的等待状态的数量syclkout周期)到闪存银行。请参阅第1.3.1节了解更多信息。

关于随机闪存访问所需的最小时间,请参阅设备特定的数据手册。

RANDWAIT必须设置大于0。也就是说,必须使用至少一个随机等待状态。另外,必须将RANDWAIT设置为大于或等于PAGEWAIT设置的值。设备将不会检测并纠正大于RANDWAIT的PAGEWAIT值。

0000非法值。RANDWAIT必须设置大于0。

0001每次随机flash访问一个等待状态,或者每次访问总共有两个SYSCLKOUT周期。

0010每次随机flash访问有两个等待状态,或者每次访问总共有三个SYSCLKOUT周期。

0011每次随机flash访问有3个等待状态,或者每次访问总共有4个syclkout周期。

. . . . . .

1111每次随机flash访问有15个等待状态,或者每次访问总共有16个SYSCLKOUT周期。(默认)

 

   //Set the Waitstate for the OTP
   FlashRegs.FOTPWAIT.bit.OTPWAIT = 2;

 

OTP读等待状态。这些寄存器位指定了CPU时钟周期(1..31SYSCLKOUT循环)到OTP。详细信息请参见CPU Read Or Fetch Access From flash/OTP章节。OTP中没有PAGE模式。

OTPWAIT必须设置大于0。也就是说,必须使用至少1个等待状态。关于OTP访问所需的最短时间,请参阅设备专用数据手册。

00000非法值。OTPWAIT必须设置为1或更大。

00001每次OTP访问将使用一个等待状态,每次访问总共有两个syclkout周期。

00010每次OTP访问将使用两个等待状态,每次访问总共有三个syclkout周期。

00011每次OTP访问将使用三个等待状态,每次访问总共有四个syclkout周期。

. . . . . .

11111 31个等待状态将用于一次OTP访问,每次访问总共有32个syclkout周期。

   //                CAUTION
   //ONLY THE DEFAULT VALUE FOR THESE 2 REGISTERS SHOULD BE USED
   FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF;
   FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF;
   EDIS;

   //Force a pipeline flush to ensure that the write to
   //the last register configured occurs before returning.

   asm(" RPT #7 || NOP");
}

vClearRam函数

void vClearRam(void)
{
	Uint16	*ram_ptr;
	for	(ram_ptr=(Uint16 *)0x8000; ram_ptr<(Uint16 *)0x8C00; ram_ptr++)		// if release
	{
		*ram_ptr = 0x0000;
	}

	for	(ram_ptr=(Uint16 *)0x0600; ram_ptr<(Uint16 *)0x0800; ram_ptr++)		// if release
	{
		*ram_ptr = 0x0000;
	}
}

 InitCla函数

void InitCla(void)
{
	EALLOW;
	SysCtrlRegs.PCLKCR3.bit.CLA1ENCLK = 1;     									         // CLA1 CLK Enable
    DSP28x_usDelay(1);                                                                   //Delay after CLK Enable    Not  necessary
    memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
    memcpy(&Cla1mathTablesRunStart, &Cla1mathTablesLoadStart, (Uint32)&Cla1mathTablesLoadSize);
    asm("   RPT #3 || NOP");

    Cla1Regs.MMEMCFG.bit.PROGE = 1;		// Configure the RAM as CLA program memory
    Cla1Regs.MMEMCFG.bit.RAM0E = 0;     // configure RAM L1, F28035 as Main Cpu Data memory 0
    Cla1Regs.MMEMCFG.bit.RAM1E = 1;		// Configure RAM L2, F28035 as CLA data memory 1

    // Symbols used in calculation are defined in CLA_Shared.h file
    Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT4 = (Uint16)((Uint32)&Cla1Task4 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT5 = (Uint16)((Uint32)&Cla1Task5 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT6 = (Uint16)((Uint32)&Cla1Task6 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT7 = (Uint16)((Uint32)&Cla1Task7 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT8 = (Uint16)((Uint32)&Cla1Task8 - (Uint32)&Cla1Prog_Start);

	// Map Peripheral interrupt to CLA Task
	// Below Task 1 is configured to be triggered by ADC INT1
	Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_ADCINT1;
	//Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_EPWM2INT;

	// Enable the IACK instruction to start a task
	// Enable the CLA interrupt 8 and software force it. For Initialize the variable used in cla
	asm(" RPT #3 || NOP");
	Cla1Regs.MCTL.bit.IACKE = 1;
	Cla1Regs.MIER.all = M_INT1|M_INT8;
	Cla1ForceTask8andWait();
	EDIS;
}

void InitCla(void)
{
    EALLOW;
    SysCtrlRegs.PCLKCR3.bit.CLA1ENCLK = 1;                                           // CLA1 CLK Enable
   

DSP28x_usDelay(1);                                        //Delay after CLK Enable    Not  necessary
    memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
    memcpy(&Cla1mathTablesRunStart, &Cla1mathTablesLoadStart, (Uint32)&Cla1mathTablesLoadSize);
    asm("   RPT #3 || NOP");

    Cla1Regs.MMEMCFG.bit.PROGE = 1;        // Configure the RAM as CLA program memory
   MMEMCFG寄存器用于将CLA程序和数据ram映射到CPU或CLA内存空间。通常,CLA程序和数据ram的映射只发生在初始化过程中。如果一段时间后,你想重新映射这些内存到CPU空间,那么禁用中断(MIER),并通过检查MIRUN寄存器来确保所有的任务已经完成。允许在更改这些内存的映射配置和访问它们之间有两个syclkout周期。

Cla1Regs.MMEMCFG.bit.RAM0E = 0;     // configure RAM L1, F28035 as Main Cpu Data memory 0
    Cla1Regs.MMEMCFG.bit.RAM1E = 1;        // Configure RAM L2, F28035 as CLA data memory 1

    // Symbols used in calculation are defined in CLA_Shared.h file
    Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT4 = (Uint16)((Uint32)&Cla1Task4 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT5 = (Uint16)((Uint32)&Cla1Task5 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT6 = (Uint16)((Uint32)&Cla1Task6 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT7 = (Uint16)((Uint32)&Cla1Task7 - (Uint32)&Cla1Prog_Start);
    Cla1Regs.MVECT8 = (Uint16)((Uint32)&Cla1Task8 - (Uint32)&Cla1Prog_Start);

    // Map Peripheral interrupt to CLA Task
    // Below Task 1 is configured to be triggered by ADC INT1
    Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_ADCINT1;
    //Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_EPWM2INT;

    // Enable the IACK instruction to start a task
    // Enable the CLA interrupt 8 and software force it. For Initialize the variable used in cla
    asm(" RPT #3 || NOP");
    Cla1Regs.MCTL.bit.IACKE = 1;
    Cla1Regs.MIER.all = M_INT1|M_INT8;
    Cla1ForceTask8andWait();
    EDIS;
}

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值