// TI File $Revision: /main/3 $
// Checkin $Date: April 4, 2007   13:20:29 $
//###########################################################################
//
// FILE:   DSP281x_SysCtrl.c
//
// TITLE:  DSP281x Device System Control Initialization & Support Functions.
//
// DESCRIPTION:
//
//         Example initialization of system resources.
//
//###########################################################################
// $TI Release:$
// $Release Date:$
//###########################################################################

#include "DSP281x_Device.h"     // DSP281x Headerfile Include File
#include "DSP281x_Examples.h"   // DSP281x 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.

//---------------------------------------------------------------------------
// InitSysCtrl:
//---------------------------------------------------------------------------
// This function initializes the System Control registers to a known state.
// - Disables the watchdog
// - Set the PLLCR for proper SYSCLKOUT frequency
// - Set the pre-scaler for the high and low frequency peripheral clocks
// - Enable the clocks to the peripherals

void InitSysCtrl(void)
{

// On F2812/F2810 TMX samples prior to rev C this initialization was
// required.  For Rev C and after this is no longer required
/*   EALLOW;
   DevEmuRegs.M0RAMDFT = 0x0300;
   DevEmuRegs.M1RAMDFT = 0x0300;
   DevEmuRegs.L0RAMDFT = 0x0300;
   DevEmuRegs.L1RAMDFT = 0x0300;
   DevEmuRegs.H0RAMDFT = 0x0300;
   EDIS;
*/
   // Disable the watchdog
   DisableDog();

   // Initialize the PLLCR to 0xA
   InitPll(0xA);

   // Initialize the peripheral clocks
   InitPeripheralClocks();
}


//---------------------------------------------------------------------------
// Example: InitFlash:
//---------------------------------------------------------------------------
// This function initializes the Flash Control registers

//                   CAUTION
// This function MUST be executed out of RAM. Executing it
// out of OTP/Flash will yield unpredictable results
#ifdef __cplusplus
#pragma CODE_SECTION("ramfuncs");
#else
#pragma CODE_SECTION(InitFlash, "ramfuncs");
#endif
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 Random Waitstate for the Flash
   FlashRegs.FBANKWAIT.bit.RANDWAIT = 5;

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

   //                CAUTION
   //Minimum cycles required to move between power states
   //at a given CPU rate must be characterized by TI.
   //Refer to the datasheet for the latest information.

   //For now use the default count
   //Set number of cycles to transition from sleep to standby
   FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF;

   //Set number of cycles to transition from standby to active
   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");
}


//---------------------------------------------------------------------------
// Example: KickDog:
//---------------------------------------------------------------------------
// This function resets the watchdog timer.
// Enable this function for using KickDog in the application

void KickDog(void)
{
    EALLOW;
    SysCtrlRegs.WDKEY = 0x0055;
    SysCtrlRegs.WDKEY = 0x00AA;
    EDIS;
}

//---------------------------------------------------------------------------
// Example: DisableDog:
//---------------------------------------------------------------------------
// This function disables the watchdog timer.

void DisableDog(void)
{
    EALLOW;
    SysCtrlRegs.WDCR= 0x0068;
    EDIS;
}

//---------------------------------------------------------------------------

void RunDog(Uint16 WDPS)
{
    WDPS |= 0x0028u;

    EALLOW;
    SysCtrlRegs.WDCR  = WDPS;
    SysCtrlRegs.WDKEY = 0x0055u;
    SysCtrlRegs.WDKEY = 0x00AAu;
    EDIS;
}

//---------------------------------------------------------------------------
// Example: InitPll:
//---------------------------------------------------------------------------
// This function initializes the PLLCR register.

void InitPll(Uint16 PLL_val)
{
   volatile Uint16 iVol;

   if (SysCtrlRegs.PLLCR.bit.DIV != PLL_val)
   {
      EALLOW;
      SysCtrlRegs.PLLCR.bit.DIV = PLL_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 switch time is 131072 CLKIN cycles as of Rev C silicon.
   //
   // 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.

   // If this function is run from waitstated memory, then the loop count can
   // be reduced as long as the minimum switch time is still met.

   // iVol is volatile so the compiler will not optimize this loop out
   //
   // The watchdog should be disabled before this loop, or fed within
   // the loop.

      DisableDog();

   // Wait lock cycles.
   // Note,  This loop is tuned to 0-waitstate RAM memory.  If this
   // function is run from wait-stated memory such as Flash or XINTF,
   // then the number of times through the loop can be reduced
   // accordingly.
      for(iVol = 0; iVol < ( (131072/2)/12 ); iVol++)
      {

      }
   }
}

//--------------------------------------------------------------------------
// Example: InitPeripheralClocks:
//---------------------------------------------------------------------------
// This function initializes the clocks to the peripheral modules.
// First the high and low clock prescalers are set
// Second the clocks are enabled to each peripheral.
// To reduce power, leave clocks to unused peripherals disabled
// Note: If a peripherals clock is not enabled then you cannot
// read or write to the registers for that peripheral

void InitPeripheralClocks(void)
{
   EALLOW;
// HISPCP/LOSPCP prescale register settings, normally it will be set to default values
   SysCtrlRegs.HISPCP.all = 0x0000; //  HSPCLK=SYSCLKOUT/2
   SysCtrlRegs.LOSPCP.all = 0x0002; //  LSPCLK=SYSCLKOUT/4

// Peripheral clock enables set for the selected peripherals.
   SysCtrlRegs.PCLKCR.bit.EVAENCLK 		= 0;
   SysCtrlRegs.PCLKCR.bit.EVBENCLK 		= 1;
   SysCtrlRegs.PCLKCR.bit.SCIAENCLK 	= 1;
   SysCtrlRegs.PCLKCR.bit.SCIBENCLK 	= 1;
   SysCtrlRegs.PCLKCR.bit.MCBSPENCLK 	= 1;
   SysCtrlRegs.PCLKCR.bit.SPIENCLK 		= 1;
   SysCtrlRegs.PCLKCR.bit.ECANENCLK 	= 1;
   SysCtrlRegs.PCLKCR.bit.ADCENCLK 		= 1;
   EDIS;
}

//---------------------------------------------------------------------------
// Example: CsmUnlock:
//---------------------------------------------------------------------------
// This function unlocks the CSM. User must replace 0xFFFF's with current
// password for the DSP. Returns 1 if unlock is successful.

#define STATUS_FAIL          0
#define STATUS_SUCCESS       1

Uint16 CsmUnlock(void)
{
    volatile Uint16 temp;
    unsigned short UnlockState = STATUS_FAIL;

    // Load the key registers with the current password. The 0xFFFF's are dummy
	// passwords.  User should replace them with the correct password for the DSP.

    EALLOW;
    CsmRegs.KEY0 = 0xF803;
    CsmRegs.KEY1 = 0x72E6;
    CsmRegs.KEY2 = 0x9B74;
    CsmRegs.KEY3 = 0xD0FB;
    CsmRegs.KEY4 = 0xAFE8;
    CsmRegs.KEY5 = 0x048C;
    CsmRegs.KEY6 = 0xB42B;
    CsmRegs.KEY7 = 0x2976;
    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.bit.SECURE == 0)
    {
    	UnlockState = STATUS_SUCCESS;
    }

    return UnlockState;
}

//===========================================================================
// No more.
//===========================================================================
