mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-14 05:42:57 +08:00
286 lines
9.5 KiB
C
286 lines
9.5 KiB
C
/*****************************************************************************
|
|
* Modified by Quantum Leaps on 09-Mar-2010
|
|
* www.state-machine.com
|
|
*
|
|
* Rewrote SystemInit() to correctly handle various Stellaris device classes,
|
|
* such as: Sandstorm, Fury, DustDevil, and Tempest
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* system_lm3s.c - System initialization file for CMSIS application on a
|
|
* Luminary Micro Stellaris microcontroller.
|
|
*
|
|
* Copyright (c) 2009 Luminary Micro, Inc. All rights reserved.
|
|
* Software License Agreement
|
|
*
|
|
* Luminary Micro, Inc. (LMI) is supplying this software for use solely and
|
|
* exclusively on LMI's microcontroller products.
|
|
*
|
|
* The software is owned by LMI and/or its suppliers, and is protected under
|
|
* applicable copyright laws. All rights are reserved. You may not combine
|
|
* this software with "viral" open-source software in order to form a larger
|
|
* program. Any use in violation of the foregoing restrictions may subject
|
|
* the user to criminal sanctions under applicable laws, as well as to civil
|
|
* liability for the breach of the terms and conditions of this license.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
|
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS
|
|
* SOFTWARE. LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,
|
|
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
|
*
|
|
* This is part of revision 32 of the Stellaris CMSIS Package.
|
|
*****************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
#include "lm3s_cmsis.h"
|
|
#include "lm3s_config.h"
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Define clocks
|
|
*/
|
|
static const uint32_t l_pulXtals[] = {
|
|
1000000,
|
|
1843200,
|
|
2000000,
|
|
2457600,
|
|
3579545,
|
|
3686400,
|
|
4000000,
|
|
4096000,
|
|
4915200,
|
|
5000000,
|
|
5120000,
|
|
6000000,
|
|
6144000,
|
|
7372800,
|
|
8000000,
|
|
8192000,
|
|
10000000,
|
|
12000000,
|
|
12288000,
|
|
13560000,
|
|
14318180,
|
|
16000000,
|
|
16384000
|
|
};
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Clock Variable definitions
|
|
*/
|
|
uint32_t SystemFrequency = 0; /*!< System Clock Frequency (Core Clock) */
|
|
|
|
/**
|
|
* Initialize the system
|
|
*
|
|
* @param none
|
|
* @return none
|
|
*
|
|
* @brief Setup the microcontroller system.
|
|
* Initialize the System and update the SystemFrequency variable.
|
|
*/
|
|
void SystemInit (void) {
|
|
#ifdef CLOCK_SETUP
|
|
uint32_t volatile i;
|
|
uint32_t ulRCC, ulRCC2, ulPLL, ulClk;
|
|
|
|
SYSCTL->RCC2 = 0x07802810; /* set default value */
|
|
SYSCTL->RCC = 0x078E3AD1; /* set default value */
|
|
|
|
/* set value with BYPASS, PWRDN set, USESYSDIV reset */
|
|
SYSCTL->RCC = (RCC_Val | (1UL << 11) | (1UL << 13)) & ~(1UL << 22);
|
|
|
|
/* set value with BYPASS, PWRDN set */
|
|
SYSCTL->RCC2 = (RCC2_Val | (1UL << 11) | (1UL << 13));
|
|
for (i = 0; i < 1000; i++) { /* wait a while */
|
|
__NOP();
|
|
}
|
|
/* set value with BYPASS, USESYSDIV reset */
|
|
SYSCTL->RCC = (RCC_Val | (1UL << 11)) & ~(1UL << 22);
|
|
|
|
/* set value with BYPASS */
|
|
SYSCTL->RCC2 = (RCC2_Val | (1UL << 11));
|
|
for (i = 0; i < 1000; i++) { /* wait a while */
|
|
__NOP();
|
|
}
|
|
|
|
SYSCTL->RCC = (RCC_Val | (1UL << 11)); /* set value with BYPASS */
|
|
|
|
if ((((RCC_Val & (1UL << 13)) == 0) && ((RCC2_Val & (1UL << 31)) ==0)) ||
|
|
(((RCC2_Val & (1UL << 13)) == 0) && ((RCC2_Val & (1UL << 31)) !=0)))
|
|
{
|
|
/* wait until PLL is locked */
|
|
while ((SYSCTL->RIS & (1UL << 6)) != (1UL << 6)) {
|
|
__NOP();
|
|
}
|
|
}
|
|
|
|
SYSCTL->RCC = (RCC_Val); /* set value */
|
|
SYSCTL->RCC2 = (RCC2_Val); /* set value */
|
|
for (i = 0; i < 1000; i++) { /* wait a while */
|
|
__NOP();
|
|
}
|
|
|
|
#endif /* #ifdef CLOCK_SETUP */
|
|
|
|
/* Read RCC and RCC2. For Sandstorm-class devices (which do not have
|
|
* RCC2), the RCC2 read will return 0, which indicates that RCC2 is
|
|
* disabled (since the SYSCTL_RCC2_USERCC2 bit is clear).
|
|
*/
|
|
ulRCC = SYSCTL->RCC;
|
|
ulRCC2 = SYSCTL->RCC2;
|
|
|
|
/* Get the base clock rate */
|
|
switch((ulRCC2 & 0x80000000) ?
|
|
(ulRCC2 & 0x00000070) :
|
|
(ulRCC & 0x00000030))
|
|
{
|
|
/* The main oscillator is the clock source. Determine its rate from
|
|
* the crystal setting field.
|
|
*/
|
|
case 0x00: {
|
|
ulClk = l_pulXtals[(ulRCC & 0x000007C0) >> 6];
|
|
break;
|
|
}
|
|
|
|
/* The internal oscillator is the source clock */
|
|
case 0x10: {
|
|
/* See if this is a Sandstorm-class or Fury-class device. */
|
|
if (CLASS_IS_SANDSTORM) {
|
|
/* The internal oscillator on a Sandstorm-class device is
|
|
* 15 MHz +/- 50%.
|
|
*/
|
|
ulClk = 15000000;
|
|
}
|
|
else if((CLASS_IS_FURY && REVISION_IS_A2) ||
|
|
(CLASS_IS_DUSTDEVIL && REVISION_IS_A0))
|
|
{
|
|
/* The internal oscillator on a rev A2 Fury-class device and
|
|
* a rev A0 Dustdevil-class device is 12 MHz +/- 30%.
|
|
*/
|
|
ulClk = 12000000;
|
|
}
|
|
else {
|
|
/* The internal oscillator on all other devices is 16 MHz. */
|
|
ulClk = 16000000;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* The internal oscillator divided by four is the source clock. */
|
|
case 0x20: {
|
|
/* See if this is a Sandstorm-class or Fury-class device. */
|
|
if (CLASS_IS_SANDSTORM) {
|
|
/* The internal oscillator on a Sandstorm-class device is
|
|
* 15 MHz +/- 50%.
|
|
*/
|
|
ulClk = 15000000 / 4;
|
|
}
|
|
else if ((CLASS_IS_FURY && REVISION_IS_A2) ||
|
|
(CLASS_IS_DUSTDEVIL && REVISION_IS_A0))
|
|
{
|
|
/* The internal oscillator on a rev A2 Fury-class device and
|
|
* a rev A0 Dustdevil-class device is 12 MHz +/- 30%.
|
|
*/
|
|
ulClk = 12000000 / 4;
|
|
}
|
|
else {
|
|
/* The internal oscillator on a Tempest-class device is 16MHz
|
|
*/
|
|
ulClk = 16000000 / 4;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* The internal 30 KHz oscillator is the source clock. */
|
|
case 0x30: {
|
|
/* The internal 30 KHz oscillator has an accuracy of +/- 30%. */
|
|
ulClk = 30000;
|
|
break;
|
|
}
|
|
|
|
/* The 4.19 MHz clock from the hibernate module is the clock source */
|
|
case 0x60: {
|
|
ulClk = 4194304;
|
|
break;
|
|
}
|
|
|
|
/* The 32 KHz clock from the hibernate module is the source clock. */
|
|
case 0x70: {
|
|
ulClk = 32768;
|
|
break;
|
|
}
|
|
|
|
/* An unknown setting, so return a zero clock (that is, an unknown
|
|
* clock rate).
|
|
*/
|
|
default: {
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* See if the PLL is being used. */
|
|
if (((ulRCC2 & 0x80000000) && !(ulRCC2 & 0x00000800)) ||
|
|
(!(ulRCC2 & 0x80000000) && !(ulRCC & 0x00000800)))
|
|
{
|
|
/* Get the PLL configuration. */
|
|
ulPLL = SYSCTL->PLLCFG;
|
|
|
|
/* See if this is a Sandstorm-class or Fury-class device. */
|
|
if (CLASS_IS_SANDSTORM) {
|
|
/* Compute the PLL output frequency based on its input frequency.
|
|
* The formula for a Sandstorm-class devices is
|
|
* "(xtal * (f + 2)) / (r + 2)".
|
|
*/
|
|
ulClk = ((ulClk * (((ulPLL & 0x00003FE0) >> 5) + 2)) /
|
|
(((ulPLL & 0x000001F) >> 0) + 2));
|
|
}
|
|
else {
|
|
/* Compute the PLL output frequency based on its input frequency.
|
|
* The formula for a Fury-class device is
|
|
* "(xtal * f) / ((r + 1) * 2)".
|
|
*/
|
|
ulClk = ((ulClk * ((ulPLL & 0x00003FE0) >> 5)) /
|
|
((((ulPLL & 0x000001F) >> 0) + 1) * 2));
|
|
}
|
|
|
|
/* See if the optional output divide by 2 is being used. */
|
|
if (ulPLL & 0x00004000) {
|
|
ulClk /= 2;
|
|
}
|
|
|
|
/* See if the optional output divide by 4 is being used. */
|
|
if (ulPLL & 0x00008000) {
|
|
ulClk /= 4;
|
|
}
|
|
}
|
|
|
|
/* See if the system divider is being used. */
|
|
if (ulRCC & 0x00400000) {
|
|
/* Adjust the clock rate by the system clock divider. */
|
|
if (ulRCC2 & 0x80000000) {
|
|
if ((ulRCC2 & 0x40000000) &&
|
|
(((ulRCC2 & 0x80000000) &&
|
|
!(ulRCC2 & 0x00000800)) ||
|
|
(!(ulRCC2 & 0x80000000) &&
|
|
!(ulRCC & 0x00000800))))
|
|
|
|
{
|
|
ulClk = ((ulClk * 2) / (((ulRCC2 & (0x1F800000 | 0x00400000))
|
|
>> (23 - 1)) + 1));
|
|
}
|
|
else {
|
|
ulClk /= (((ulRCC2 & 0x1F800000) >> 23) + 1);
|
|
}
|
|
}
|
|
else {
|
|
ulClk /= (((ulRCC & 0x07800000) >> 23) + 1);
|
|
}
|
|
}
|
|
|
|
/* Set the computed clock rate */
|
|
SystemFrequency = ulClk;
|
|
}
|
|
|