TI 提供的F2837xD的SysCtrl函数,该芯片是双核拥有两个CPU,具体的以后会阐述。
//###########################################################################
//
// FILE: F2837xD_SysCtrl.c
//
// TITLE: F2837xD Device System Control Initialization & Support Functions.
//
// DESCRIPTION:
//
// Example initialization of system resources.
//
//###########################################################################
// $TI Release: F2837xD Support Library v100 $
// $Release Date: Mon Dec 9 12:58:09 CST 2013 $
//###########################################################################
#include "F2837xD_Device.h" // Headerfile Include File
#include "F2837xD_Examples.h"
// Examples Include File
// Functions that will be run from RAM need to be assigned to
// a different section. This section will then be mapped to a load and
// run address using the linker cmd file.
//
// *IMPORTANT*
// IF RUNNING FROM FLASH, PLEASE COPY OVER THE SECTION "ramfuncs" FROM FLASH
// TO RAM PRIOR TO CALLING InitSysCtrl(). THIS PREVENTS THE MCU FROM THROWING
// AN EXCEPTION WHEN A CALL TO DELAY_US() IS MADE.
//
#pragma CODE_SECTION(InitFlash, "ramfuncs");//将InitFlash函数存在ramfuncs中。
void InitSysCtrl(void)
{
// Disable the watchdog
DisableDog();
#ifdef _FLASH
// flash中将程序复制到RAM中,注意RamfuncsRunStart, RamfuncsLoadStart, RamfuncsLoadSize三个变量要与RAM.cmd文件中ramfuncs处的三个变量完全一致,并且这三个变量要进行全局变量申明
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM在RAM中初始化
InitFlash();
#endif
//复制ADC&晶振的标称值从TI的保留OTP到寄存器中。先使能时钟再调用函数#define Device_cal (void (*)(void))0x000000
#ifdef CPU1
EALLOW;
CpuSysRegs.PCLKCR13.bit.ADC_A = 1;
CpuSysRegs.PCLKCR13.bit.ADC_B = 1;
CpuSysRegs.PCLKCR13.bit.ADC_C = 1;
CpuSysRegs.PCLKCR13.bit.ADC_D = 1;
// (*Device_cal)();
CpuSysRegs.PCLKCR13.bit.ADC_A = 0;
CpuSysRegs.PCLKCR13.bit.ADC_B = 0;
CpuSysRegs.PCLKCR13.bit.ADC_C = 0;
CpuSysRegs.PCLKCR13.bit.ADC_D = 0;
EDIS;
// Initialize the PLL control: PLLCR and CLKINDIV
// F28_PLLCR and F28_CLKINDIV are defined in F2837xD_Examples.h
InitSysPll(XTAL_OSC,IMULT_20,FMULT_1,PLLCLK_BY_2);
//PLLSYSCLK = 10Mhz(OSCCLK) * 40 (IMULT) * 1 (FMULT) / 2 (PLLCLK_BY_2)
//Turn on all peripherals
InitPeripheralClocks();
#endif
}
看门狗定时器是一个独立于CPU的计数单元,如果不采用特定的指令周期地使看门狗定时器复位,看门狗定时器将会使系统复位。为了避免不必要的复位,要求用户软件周期的对看门狗定时器进行复位操作。如果不明原因使CPU中断程序,比如系统软件进入死循环或者CPU的程序运行到了不确定的程序空间,从而使系统不能正常的工作,则看门狗电路可产生一个复位信号使CPU复位,程序从系统软件的开始执行。看门狗可以监测软件和硬件的运行状态,提高系统的可靠性。
只有先写0x55再写0xAA才会使WECNTR(看门狗计数器)复位
void ServiceDog(void)
{
EALLOW;
WdRegs.WDKEY.bit.WDKEY = 0x0055;
WdRegs.WDKEY.bit.WDKEY = 0x00AA;
EDIS;
}//复位看门狗计数器
//---------------------------------------------------------------------------
// Example: InitFlash:
//---------------------------------------------------------------------------
// 初始化 Flash Control registers
注意:该函数必须在RAM中执行,如果在OTP/Flash中执行将有不可预知的结果
//InitSysPLL设置了PLLSYSCLK=OSCCLK x (SYSPLLMULT.IMULT + SYSPLLMULT.FMULT)/SYSCLKDIVSEL
//InitPheralClocks()使能了所有的外设
1.#pragma CODE_SECTION(InitFlash, "ramfuncs")
解释:将InitFlash函数存在ramfuncs中。该语句功能是将InitFlash函数写入RAM中,因为InitFlash经常被调用,这样省得每次都从flash中写入RAM。如果还有经常反复调用的函数,也可自行添加类似语句,需注意#pragma
CODE_SECTION (InitFlash, "ramfuncs") 应该写在函数Initflash()所在的C文件中,并且在函数之前声明;在CCS中,如果我们不指定变量的存放位置,编译器会自动给变量分配一个位置,但有的时候我们想要把变量放在一个特定的空间里,那应该怎么办呢?
CCS提供了以下两个指令:#pragma CODE_SECTION和#pragma DATA_SECTION,其中data_section是针对数据空间的,code_section是针对程序空间的。CODE_SECTION
Pragma命令格式:#pragma CODE_SECTION (func, "section name")
为函数func分配一个段空间,且该空间不在.text段(一般程序),段名为"section name。DATA_SECTION pragma命令格式:#pragma DATA_SECTION (symbol, "section name")。将数据对象symbol分配在不同于.bss(一般数据)的空间内,生成一个数据段,段名为"section
name“.
例如:#pragma DATA_SECTION (AdcRegs,"AdcRegsFile");
volatile struct ADC_REGS AdcRegs;
将一个结构体AdcRegs与F2812的外设AD转换寄存器相对应。使得对结构体的操作作用于寄存器。
没有调用InitFlash这个函数就不需要这个#pragma CODE_SECTION(InitFlash, "ramfuncs");
一般说来,初始化时,是需要初始化Flash的,所以是需要的。很多例程不过是没有调用的。flash的初始化是需要在ram中运行,不能放在flash中运行。
由于在基于DSP的嵌入式系统开发中,存储资源特别是片内高速存储资源有限,在算法系统集成时Memory的管理对于提高整个系统的优化是非常重要的,这一方面影响数据的读取、搬移速度;另一方面还影响Cache(缓存)的命中率,下面分程序和数据两方面分析。
程序区:最大原则是将经常调度使用的算法模块放片内。为做到这点,TI的CCS中提供了#pragma CODE_SECTION,可以把需要单独控制存放的函数段从.text段中独立出来,从而在.cmd文件中对这些函数段进行单独物理地址映射。还可以使用程序动态的方式,将需要运行的代码段先调度进片内memory,如H.264/AVC中CAVLC和CABAC两个算法模块具有互斥性,因此可以将这两个算法模块放在片外而且对应于片内同一块运行区,在运行其中某一个算法模块之前,先将其调入片内,从而充分利用片内有限的高速存储区。程序区的管理考虑到一级程序Cache(L1
P)的命中率,最好将具有先后执行顺序的函数按地址先后顺序配置在程序空间中,同时对代码比较大的处理函数将其拆分成小函数。