This is the mail archive of the
ecos-discuss@sourceware.org
mailing list for the eCos project.
Re: Redboot for FSL TWRK70F120M with Linux kernel booting
On Wed, Mar 14, 2012 at 2:44 PM, Ilija Kocho <ilijak@siva.com.mk> wrote:
> Hi Linh
>
>
>
> On 14.03.2012 05:39, Linh Nguyán wrote:
>> Hi all,
>>
>> Does anyone successful porting Redboot for TWRK70F120M hardware board?
>> I have edited HAL of TWRK60N512 to use as TWRK70F120M. It can run but
>> I don't now how to add SDRAM of K70 into linker file and use it.
>> Attached files are linker file that I edited to use SDRAM, I have
>> initialized PLL0 and PLL1 then DDR registers. I can access SDRAM by
>> hard address (like 0x70001000). But when I load a binary file into
>> SDRAM, it shown the warrning as bellow:
>> <code>
>> RedBoot> load -r -v -h 10.207.215.87 -m tftp -b 0x70008000 Image
>> Specified address (0x70008000) is not believed to be in RAM - continue (y/n)? y
>> </code>
>>
>> If you have any ideas about the problems, please let me know :).
>
> You need to report this memory to RedBoot. Look for
> cyg_plf_memory_segment() in twr_k60n512_misc.c (or whatever name you
> have given to this file).
I have done this before. (twr_k70f120m_misc.c attached.)
Can you take a look at the file and show me my mistake :). Or please
share me your linker config & memory segment () that you configure for
DRAM.
>
>> If anyone have ported Redboot to K70 or successful in using SDRAM
>> please share me :).
> Thank you for your offer.
> I am working on K70 port, everything essential seem to work (including
> FPU) but I have problem initializing PLL1. I have read the errata but it
> still doesn't work for me. Is there any trick?
>
> Also when trying to initialize DDR registers the chip freezes, I guess
> that it is because PLL1 is not working but maybe I need to enable
> something else than DDRAM clock.
> Can you send me the clock and DDR initialization sequence you are using?
About clock and DDRAM initialization I follow Kinetis 120MHz bare
metal sample code from Freescale site
(https://www.freescale.com/webapp/Download?colCode=KINETIS_120MHZ_SC&prodCode=K70_120&appType=license&location=null&fpsp=1&Parent_nodeId=1326817898002720905982&Parent_pageType=product&Parent_nodeId=1326817898002720905982&Parent_pageType=product).
kinetis_clocking.c attached contains my PLL0 & PLL1 initialization
sequences. My source code is hard-code for K70 only, so it can't build
for another board. You can find MK70F12.h in the package with link
above.
>
> Regards
>
> Ilija
>
Thanks & Regards,
Linh Nguyen.
//==========================================================================
//
// twr_k70f120m_misc.c
//
// Cortex-M4 TWR-K70F120M EVAL HAL functions
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2011 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): ilijak
// Contributor(s):
// Date: 2011-02-05
// Description:
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/hal.h>
#include <pkgconf/hal_cortexm.h>
#include <pkgconf/hal_cortexm_kinetis.h>
#include <pkgconf/hal_cortexm_kinetis_twr_k70f120m.h>
#ifdef CYGPKG_KERNEL
#include <pkgconf/kernel.h>
#endif
#include <cyg/infra/diag.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/hal/hal_arch.h> // HAL header
#include <cyg/hal/hal_intr.h> // HAL header
#include <cyg/hal/MK70F12.h> // BOARD header
static inline void hal_gpio_init(void);
// DATA and BSS locations
__externC cyg_uint32 __ram_data_start;
__externC cyg_uint32 __ram_data_end;
__externC cyg_uint32 __rom_data_start;
__externC cyg_uint32 __sram_data_start;
__externC cyg_uint32 __sram_data_end;
__externC cyg_uint32 __srom_data_start;
__externC cyg_uint32 __bss_start;
__externC cyg_uint32 __bss_end;
//==========================================================================
// System init
//
// This is run to set up the basic system, including GPIO setting,
// clock feeds, power supply, and memory initialization. This code
// runs before the DATA is copied from ROM and the BSS cleared, hence
// it cannot make use of static variables or data tables.
__externC void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_system_init( void )
{
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_SRAM)
hal_wdog_disable();
hal_gpio_init();
#endif
#if defined(CYG_HAL_STARTUP_SRAM) && !defined(CYGHWR_HAL_CORTEXM_KINETIS_SRAM_UNIFIED)
// Note: For CYG_HAL_STARTUP_SRAM, the SRAM_L bank simulates ROM
// Relocate data from ROM to RAM
{
register cyg_uint32 *ram_p, *rom_p;
for( ram_p = &__ram_data_start, rom_p = &__rom_data_start;
ram_p < &__ram_data_end;
ram_p++, rom_p++ )
*ram_p = *rom_p;
}
// Relocate data from ROM to SRAM
{
register cyg_uint32 *ram_p, *sram_p;
for( ram_p = &__sram_data_start, sram_p = &__srom_data_start;
ram_p < &__sram_data_end;
ram_p++, sram_p++ )
*ram_p = *sram_p;
}
#endif
}
//===========================================================================
// hal_gpio_init
//===========================================================================
static inline void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_gpio_init(void)
{
cyghwr_hal_kinetis_sim_t *sim_p = CYGHWR_HAL_KINETIS_SIM_P;
cyghwr_hal_kinetis_mpu_t *mpu_p = CYGHWR_HAL_KINETIS_MPU_P;
// Enable clocks on all ports.
sim_p->scgc1 = CYGHWR_HAL_KINETIS_SIM_SCGC1_ALL_M;
sim_p->scgc2 = CYGHWR_HAL_KINETIS_SIM_SCGC2_ALL_M;
sim_p->scgc3 = CYGHWR_HAL_KINETIS_SIM_SCGC3_ALL_M;
sim_p->scgc4 = CYGHWR_HAL_KINETIS_SIM_SCGC4_ALL_M;
sim_p->scgc5 = CYGHWR_HAL_KINETIS_SIM_SCGC5_ALL_M;
sim_p->scgc6 = CYGHWR_HAL_KINETIS_SIM_SCGC6_ALL_M;
sim_p->scgc7 = CYGHWR_HAL_KINETIS_SIM_SCGC7_ALL_M;
// Disable MPU
MPU_CESR = 0;
// Set MUX for LEDs
PORTA_PCR10 |= PORT_PCR_MUX(MUX_ALT1);
PORTA_PCR11 |= PORT_PCR_MUX(MUX_ALT1);
PORTA_PCR28 |= PORT_PCR_MUX(MUX_ALT1);
PORTA_PCR29 |= PORT_PCR_MUX(MUX_ALT1);
// Set output direction for LEDs
PTA_BASE_PTR->PDDR |= (1 << 10) | (1 << 11) | (1 << 28) | (1 << 29);
// Set initial value for LEDs
PTA_BASE_PTR->PCOR |= (1 << 10) | (1 << 11) | (1 << 28) | (1 << 29);
}
//==========================================================================
__externC void hal_platform_init( void )
{
}
//==========================================================================
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
#include CYGHWR_MEMORY_LAYOUT_H
//--------------------------------------------------------------------------
// Accesses to areas not backed by real devices or memory can cause
// the CPU to hang.
//
// The following table defines the memory areas that GDB is allowed to
// touch. All others are disallowed.
// This table needs to be kept up to date with the set of memory areas
// that are available on the board.
static struct {
CYG_ADDRESS start; // Region start address
CYG_ADDRESS end; // End address (last byte)
} hal_data_access[] =
{
{ CYGMEM_REGION_ram, CYGMEM_REGION_ram+CYGMEM_REGION_ram_SIZE-1 }, // Main RAM
#ifdef CYGMEM_REGION_sram
{ CYGMEM_REGION_sram, CYGMEM_REGION_sram+CYGMEM_REGION_sram_SIZE-1 }, // On-chip SRAM
#endif
#ifdef CYGMEM_REGION_dram
{ CYGMEM_REGION_dram, CYGMEM_REGION_dram+CYGMEM_REGION_dram_SIZE-1 }, // External SDRAM
#endif
#ifdef CYGMEM_REGION_flash
{ CYGMEM_REGION_flash, CYGMEM_REGION_flash+CYGMEM_REGION_flash_SIZE-1 }, // On-chip flash
#endif
#ifdef CYGMEM_REGION_rom
{ CYGMEM_REGION_rom, CYGMEM_REGION_rom+CYGMEM_REGION_rom_SIZE-1 }, // External flash
#endif
{ 0xE0000000, 0x00000000-1 }, // Cortex-M peripherals
{ 0x40000000, 0x60000000-1 }, // Chip specific peripherals
};
__externC int cyg_hal_stub_permit_data_access( CYG_ADDRESS addr, cyg_uint32 count )
{
int i;
for( i = 0; i < sizeof(hal_data_access)/sizeof(hal_data_access[0]); i++ ) {
if( (addr >= hal_data_access[i].start) &&
(addr+count) <= hal_data_access[i].end)
return true;
}
return false;
}
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
//==========================================================================
#ifdef CYGPKG_REDBOOT
#include <redboot.h>
#include CYGHWR_MEMORY_LAYOUT_H
//--------------------------------------------------------------------------
// Memory layout
//
// We report the on-chip SRAM and external SRAM.
void
cyg_plf_memory_segment(int seg, unsigned char **start, unsigned char **end)
{
switch (seg) {
case 0:
*start = (unsigned char *)CYGMEM_REGION_ram;
*end = (unsigned char *)(CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE);
break;
#ifdef CYGMEM_REGION_sram
case 1:
*start = (unsigned char *)CYGMEM_REGION_sram;
*end = (unsigned char *)(CYGMEM_REGION_sram + CYGMEM_REGION_sram_SIZE);
break;
#endif
#ifdef CYGMEM_REGION_dram
#ifndef CYGMEM_REGION_sram
case 1:
#else
case 2:
#endif
*start = (unsigned char *)CYGMEM_REGION_dram;
*end = (unsigned char *)(CYGMEM_REGION_dram + CYGMEM_REGION_dram_SIZE);
break;
#endif
default:
*start = *end = NO_MEMORY;
break;
}
} // cyg_plf_memory_segment()
#endif // CYGPKG_REDBOOT
//==========================================================================
// EOF twr_k70f120m_misc.c
//==========================================================================
//
// kinetis_clocking.c
//
// Cortex-M Kinetis HAL functions
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2010 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Ilija kocho <ilijak@siva.com.mk>
// Date: 2011-10-19
// Description:
//
//####DESCRIPTIONEND####
//
//========================================================================
#include <pkgconf/hal.h>
#include <pkgconf/hal_cortexm.h>
#include <pkgconf/hal_cortexm_kinetis.h>
#ifdef CYGPKG_KERNEL
#include <pkgconf/kernel.h>
#endif
#include <cyg/infra/diag.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <cyg/hal/cortexm_endian.h>
#include <cyg/hal/hal_arch.h> // HAL header
#include <cyg/hal/hal_intr.h> // HAL header
#include <cyg/hal/hal_if.h> // HAL header
#include <cyg/io/ser_freescale_uart.h>
#include <cyg/hal/MK70F12.h>
// Constants for use in pll_init
#define NO_OSCINIT 0
#define OSCINIT 1
#define OSC_0 0
#define OSC_1 1
#define LOW_POWER 0
#define HIGH_GAIN 1
#define CANNED_OSC 0
#define CRYSTAL 1
#define PLL_0 0
#define PLL_1 1
#define PLL_ONLY 0
#define MCGOUT 1
/*
* Input Clock Info
*/
#define CLK0_FREQ_HZ 50000000
#define CLK0_TYPE CANNED_OSC
#define CLK1_FREQ_HZ 12000000
#define CLK1_TYPE CRYSTAL
#define ASYNCH_MODE /* PLL1 is source for MCGCLKOUT and DDR controller */
#define PLL0_PRDIV 5
#define PLL0_VDIV 24
#define PLL1_PRDIV 5
#define PLL1_VDIV 30
//===========================================================================
// Forward declarations
//===========================================================================
cyg_uint32 hal_cortexm_systick_clock;
cyg_uint32 hal_kinetis_sysclk;
cyg_uint32 hal_kinetis_busclk;
cyg_uint32 hal_get_cpu_clock(void);
//void hal_start_main_clock(void);
void hal_set_clock_dividers(void);
#ifdef CYGHWR_HAL_CORTEXM_KINETIS_RTC
void hal_start_rtc_clock(void);
#endif
void fb_clk_init(void);
void twr_ddr2_script_init(void);
int pll_init(unsigned char init_osc, unsigned char osc_select, int crystal_val, unsigned char hgo_val, unsigned char erefs_val, unsigned char pll_select, signed char prdiv_val, signed char vdiv_val, unsigned char mcgout_select);
//==========================================================================
// Setup up system clocks
//
// Set up clocks from configuration. In the future this should be extended so
// that clock rates can be changed at runtime.
void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_start_clocks( void )
{
int mcg_clk_hz, pll_1_clk_khz;
SIM_MemMapPtr sim_p = SIM_BASE_PTR;
#ifdef CYGHWR_HAL_CORTEXM_KINETIS_TRACE_CLKOUT
PORT_MemMapPtr port_p = PORTA_BASE_PTR;
#endif
#if !defined(CYG_HAL_STARTUP_RAM)
# ifdef CYGHWR_HAL_CORTEXM_KINETIS_RTC
// Real Time Clock
hal_start_rtc_clock();
# endif
// Main clock - MCG
// hal_start_main_clock();
hal_set_clock_dividers();
/* Initialize PLL0 */
/* PLL0 will be the source for MCG CLKOUT so the core, system, FlexBus, and flash clocks are derived from it */
mcg_clk_hz = pll_init(OSCINIT, /* Initialize the oscillator circuit */
OSC_0, /* Use CLKIN0 as the input clock */
CLK0_FREQ_HZ, /* CLKIN0 frequency */
LOW_POWER, /* Set the oscillator for low power mode */
CLK0_TYPE, /* Crystal or canned oscillator clock input */
PLL_0, /* PLL to initialize, in this case PLL0 */
PLL0_PRDIV, /* PLL predivider value */
PLL0_VDIV, /* PLL multiplier */
MCGOUT); /* Use the output from this PLL as the MCGOUT */
/* Check the value returned from pll_init() to make sure there wasn't an error */
if (mcg_clk_hz < 0x100)
while (1)
;
/* Initialize PLL1 */
/* PLL1 will be the source for the DDR controller, but NOT the MCGOUT */
pll_1_clk_khz = (pll_init(NO_OSCINIT, /* Don't init the osc circuit, already done */
OSC_0, /* Use CLKIN0 as the input clock */
CLK0_FREQ_HZ, /* CLKIN0 frequency */
LOW_POWER, /* Set the oscillator for low power mode */
CLK0_TYPE, /* Crystal or canned oscillator clock input */
PLL_1, /* PLL to initialize, in this case PLL1 */
PLL1_PRDIV, /* PLL predivider value */
PLL1_VDIV, /* PLL multiplier */
PLL_ONLY) / 1000); /* Don't use the output from this PLL as the MCGOUT */
/* Check the value returned from pll_init() to make sure there wasn't an error */
if ((pll_1_clk_khz * 1000) < 0x100)
while (1)
;
fb_clk_init();
/* Initialize the DDR if the project option if defined */
twr_ddr2_script_init();
#endif
hal_kinetis_sysclk=hal_get_cpu_clock();
// Write sysclk into DRAM memory
* (cyg_uint32 *)(0x08001234) = hal_kinetis_sysclk;
hal_kinetis_busclk=hal_kinetis_sysclk /
CYGHWR_HAL_CORTEXM_KINETIS_CLKDIV_PER_BUS;
//Write busclk into DRAM memory
* (cyg_uint32 *)(0x08001238) = hal_kinetis_busclk;
hal_cortexm_systick_clock=hal_kinetis_sysclk;
// Trace clock
#ifdef CYGHWR_HAL_CORTEXM_KINETIS_TRACECLK_CORE
sim_p->SOPT2 |= SIM_SOPT2_TRACECLKSEL_MASK;
#else
sim_p->SOPT2 &= ~SIM_SOPT2_TRACECLKSEL_MASK;
#endif
#ifdef CYGHWR_HAL_CORTEXM_KINETIS_TRACE_CLKOUT
port_p->PCR[6] = PORT_PCR_MUX(0x7);
#endif
}
#define MCG_WAIT_WHILE(_condition_) do{}while(_condition_)
// Setup MCG
// Note: Currently only PBE mode is supported and tested.
//void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
//hal_start_main_clock(void)
//{
// MCG_MemMapPtr mcg_p = MCG_BASE_PTR;
//#if defined CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL ||\
// defined CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_RTC
// SIM_MemMapPtr sim_p = SIM_BASE_PTR;
//#endif
//#ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT
//# if defined CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL || \
// defined CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_OSC
// volatile cyg_uint8 *osc_cr_p = CYGHWR_HAL_KINETIS_OSC_CR_P;
//# endif
//
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL
// // Set the main oscillator
// *osc_cr_p = CYGHWR_HAL_CORTEXM_KINETIS_OSC_CAP / 2;
//# elif defined CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_OSC
// // Select exteranal oscillator
// *osc_cr_p = CYGHWR_HAL_KINETIS_OSC_CR_ERCLKEN_M |
// CYGHWR_HAL_KINETIS_OSC_CR_EREFSTEN_M;
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL
//
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_RTC
// // Select RTC clock source for MCG reference
// sim_p->sopt2 |= CYGHWR_HAL_KINETIS_SIM_SOPT2_MCGCLKSEL_M;
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_RTC
//#endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT
//
//#if defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL) || \
// defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_FLL) || \
// defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
// // Enter FBE mode
// mcg_p->C2 = MCG_C2_RANGE(
// CYGNUM_HAL_CORTEXM_KINETIS_MCG_REF_FREQ_RANGE)
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL
// | CYGHWR_HAL_KINETIS_MCG_C2_EREFS_M | CYGHWR_HAL_KINETIS_MCG_C2_HGO_M
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL
// ;
// mcg_p->C1 = MCG_C1_FRDIV(
// CYGNUM_HAL_CORTEXM_KINETIS_MCG_REF_FRDIV_REG)
//# if defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL) || \
// defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
// |MCG_C1_CLKS(CYGHWR_HAL_KINETIS_MCG_C1_CLKS_EXT_REF)
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL
// ;
//
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_XTAL
// // Wait for oscillator start up
// MCG_WAIT_WHILE(!(mcg_p->status & CYGHWR_HAL_KINETIS_MCG_S_OSCINIT_M));
//# endif
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT
// // Wait for reference clock to switch to external reference
// MCG_WAIT_WHILE(mcg_p->status & CYGHWR_HAL_KINETIS_MCG_S_IREFST_M);
// // Wait for status flags update
// MCG_WAIT_WHILE((mcg_p->status & CYGHWR_HAL_KINETIS_MCG_S_CLKST_M) !=
//# if defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL) || \
//defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
// CYGHWR_HAL_KINETIS_MCG_S_CLKST_EXT
//# else
// CYGHWR_HAL_KINETIS_MCG_S_CLKST_FLL
//# endif
// );
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT
// // Set peripheral dividers before switching to high frequency.
// hal_set_clock_dividers();
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_FLL
// // Configure FLL
// mcg_p->c4 = (mcg_p->c4 & 0x1f) |
// (CYGNUM_HAL_CORTEXM_MCG_DCO_DMX32 |
// CYGHWR_HAL_KINETIS_MCG_C4_DRST_DRS(
// CYGNUM_HAL_CORTEXM_MCG_DCO_DRST_DRS));
//
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_FLL
//# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL
// // Configure PLL and enter PBE mode
// mcg_p->C5 = MCG_C5_PRDIV(
// CYGOPT_HAL_CORTEXM_KINETIS_MCGOUT_PLL_PRDIV-1) |
// CYGHWR_HAL_KINETIS_MCG_C5_PLLSTEN_M;
// mcg_p->C6 = MCG_C6_VDIV(
// CYGOPT_HAL_CORTEXM_KINETIS_MCGOUT_PLL_VDIV-16);
//
// // Switch to PBE mode
// mcg_p->C6 |= MCG_C6_PLLS_MASK;
//
// MCG_WAIT_WHILE((mcg_p->S & MCG_S_CLKST_MASK) !=
// MCG_S_CLKST(2));
// MCG_WAIT_WHILE(!(mcg_p->S & MCG_S_PLLST_MASK));
// MCG_WAIT_WHILE(!(mcg_p->S & MCG_S_LOCK_MASK));
//
// // Enter PEE mode
// mcg_p->C1 &= ~MCG_C1_CLKS_MASK;
// MCG_WAIT_WHILE((mcg_p->S & MCG_S_CLKST_MASK) !=
// MCG_S_CLKST(3));
//# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL
//# if defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL) || \
// defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
// sim_p->SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;
//# endif
//
//#endif // defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL) ||
// // defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_FLL) ||
// // defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
//}
cyg_uint32 CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_get_cpu_clock(void)
{
cyg_uint32 freq;
#ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_PLL
MCG_MemMapPtr mcg_p = MCG_BASE_PTR;
freq = CYGNUM_HAL_CORTEXM_KINETIS_MCG_FLL_PLL_REF_FREQ /
((mcg_p->C5 & MCG_C5_PRDIV_MASK)+1) *
((mcg_p->C6 & MCG_C6_VDIV_MASK)+16) / 2;
#elif defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_FLL)
freq = CYGNUM_HAL_CORTEXM_KINETIS_MCG_FLL_FREQ_AV;
#elif defined(CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_EXT_REFCLK)
freq = CYGOPT_HAL_CORTEXM_KINETIS_MCGOUT_EXT_RC;
#else // ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_none
#endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_MCGOUTCLK_end
return freq;
}
void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_set_clock_dividers(void)
{
SIM_MemMapPtr sim_p = SIM_BASE_PTR;
sim_p->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) |
SIM_CLKDIV1_OUTDIV2(
CYGHWR_HAL_CORTEXM_KINETIS_CLKDIV_PER_BUS-1) |
SIM_CLKDIV1_OUTDIV3(
CYGHWR_HAL_CORTEXM_KINETIS_CLKDIV_FLEX_BUS-1) |
SIM_CLKDIV1_OUTDIV4(
CYGHWR_HAL_CORTEXM_KINETIS_CLKDIV_FLASH-1);
sim_p->CLKDIV2 = SIM_CLKDIV2_USBFSDIV(
CYGHWR_HAL_CORTEXM_KINETIS_USBCLK_DIV-1) |
(CYGHWR_HAL_CORTEXM_KINETIS_USBCLK_FRAC==2 ?
SIM_CLKDIV2_USBHSFRAC_MASK : 0);
}
#ifdef CYGHWR_HAL_CORTEXM_KINETIS_RTC
void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_start_rtc_clock(void)
{
RTC_MemMapPtr rtc_p = RTC_BASE_PTR;
rtc_p->IER=0; // Disable RTC interrupts
//Start RTC clock if not already started
if(!(rtc_p->CR & 1 << RTC_CR_OSCE_SHIFT)){
rtc_p->CR = 1 << RTC_CR_OSCE_SHIFT |
CYGHWR_HAL_CORTEXM_KINETIS_RTC_OSC_CAP;
# ifdef CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_RTC
{
volatile cyg_uint32 busycnt;
for(busycnt=1000000; busycnt; busycnt--)
__asm__ volatile ("nop\n");
}
# endif // CYGOPT_HAL_CORTEXM_KINETIS_MCG_REF_EXT_IS_RTC
}
}
#endif
//==========================================================================
// UART baud rate
//
// Set the baud rate divider of a UART based on the requested rate and
// the current clock settings.
void CYGOPT_HAL_KINETIS_MISC_FLASH_SECTION_ATTR
hal_freescale_uart_setbaud(cyg_uint32 uart_p, cyg_uint32 baud)
{
cyg_uint32 sbr, brfa;
cyg_uint32 regval;
switch(uart_p) {
case CYGADDR_IO_SERIAL_FREESCALE_UART0_BASE:
case CYGADDR_IO_SERIAL_FREESCALE_UART1_BASE:
sbr = hal_kinetis_sysclk/(16*baud);
break;
case CYGADDR_IO_SERIAL_FREESCALE_UART2_BASE:
case CYGADDR_IO_SERIAL_FREESCALE_UART3_BASE:
case CYGADDR_IO_SERIAL_FREESCALE_UART4_BASE:
case CYGADDR_IO_SERIAL_FREESCALE_UART5_BASE:
sbr = hal_kinetis_busclk/(16*baud);
break;
default:
sbr=0;
break;
}
if(sbr) {
HAL_READ_UINT8(uart_p + CYGHWR_DEV_FREESCALE_UART_BDH, regval);
regval &= 0xE0;
regval |= sbr >> 8;
HAL_WRITE_UINT8(uart_p + CYGHWR_DEV_FREESCALE_UART_BDH, regval);
HAL_WRITE_UINT8(uart_p + CYGHWR_DEV_FREESCALE_UART_BDL, (sbr & 0xFF));
brfa = (((32*hal_kinetis_busclk)/(16*baud))-(32*sbr));
HAL_READ_UINT8(uart_p + CYGHWR_DEV_FREESCALE_UART_C4, regval);
regval &= 0xE0;
regval |= brfa & 0x1f;
HAL_WRITE_UINT8(uart_p + CYGHWR_DEV_FREESCALE_UART_C4, regval);
}
}
/*********************************************************************************************/
/* Functon name : pll_init
*
* Mode transition: Option to move from FEI to PEE mode or to just initialize the PLL
*
* This function initializess either PLL0 or PLL1. Either OSC0 or OSC1 can be selected for the
* reference clock source. The oscillators can be configured to use a crystal or take in an
* external square wave clock.
* NOTE : This driver does not presently (as of Sept 9 2011) support the use of OSC1 as the
* reference clock for the MCGOUT clock used for the system clocks.
* The PLL outputs a PLLCLK and PLLCLK2X. PLLCLK2X is the actual PLL frequency and PLLCLK is
* half this frequency. PLLCLK is used for MCGOUT and is also typically used by the
* peripherals that can select the PLL as a clock source. So the PLL frequency generated will
* be twice the desired frequency.
* Using the function parameter names the PLL frequency is calculated as follows:
* PLL freq = ((crystal_val / prdiv_val) * vdiv_val)
* Refer to the readme file in the mcg driver directory for examples of pll_init configurations.
* All parameters must be provided, for example crystal_val must be provided even if the
* oscillator associated with that parameter is already initialized.
* The various passed parameters are checked to ensure they are within the allowed range. If any
* of these checks fail the driver will exit and return a fail/error code. An error code will
* also be returned if any error occurs during the PLL initialization sequence. Refer to the
* readme file in the mcg driver directory for a list of all these codes.
*
* Parameters: init_osc - 0 if oscillator does not need to be initialized, non-zero if the
* oscillator needs to be configured.
* osc_select - 0 to select OSC0, non-zero to select OSC1.
* crystal_val - external clock frequency in Hz either from a crystal or square
* wave clock source
* hgo_val - selects whether low power or high gain mode is selected
* for the crystal oscillator. This has no meaning if an
* external clock is used.
* erefs_val - selects external clock (=0) or crystal osc (=1)
* pll_select - 0 to select PLL0, non-zero to select PLL1.
* prdiv_val - value to divide the external clock source by to create the desired
* PLL reference clock frequency
* vdiv_val - value to multiply the PLL reference clock frequency by
* mcgout_select - 0 if the PLL is just to be enabled, non-zero if the PLL is used
* to provide the MCGOUT clock for the system.
*
* Return value : PLL frequency (Hz) divided by 2 or error code
*/
int pll_init(unsigned char init_osc, unsigned char osc_select, int crystal_val, unsigned char hgo_val, unsigned char erefs_val, unsigned char pll_select, signed char prdiv_val, signed char vdiv_val, unsigned char mcgout_select)
{
unsigned char frdiv_val;
unsigned char temp_reg;
unsigned char prdiv, vdiv;
short i;
int ref_freq;
int pll_freq;
// If using the PLL as MCG_OUT must check if the MCG is in FEI mode first
if (mcgout_select)
{
// check if in FEI mode
if (!((((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) == 0x0) && // check CLKS mux has selcted FLL output
(MCG_S & MCG_S_IREFST_MASK) && // check FLL ref is internal ref clk
(!(MCG_S & MCG_S_PLLST_MASK)))) // check PLLS mux has selected FLL
{
return 0x1; // return error code
}
} // if (mcgout_select)
// Check if OSC1 is being used as a reference for the MCGOUT PLL
// This requires a more complicated MCG configuration.
// At this time (Sept 8th 2011) this driver does not support this option
if (osc_select && mcgout_select)
{
return 0x80; // Driver does not support using OSC1 as the PLL reference for the system clock on MCGOUT
}
// check external frequency is less than the maximum frequency
if (crystal_val > 60000000) {return 0x21;}
// check crystal frequency is within spec. if crystal osc is being used as PLL ref
if (erefs_val)
{
if ((crystal_val < 8000000) || (crystal_val > 32000000)) {return 0x22;} // return 1 if one of the available crystal options is not available
}
// make sure HGO will never be greater than 1. Could return an error instead if desired.
if (hgo_val > 0)
{
hgo_val = 1; // force hgo_val to 1 if > 0
}
// Check PLL divider settings are within spec.
if ((prdiv_val < 1) || (prdiv_val > 8)) {return 0x41;}
if ((vdiv_val < 16) || (vdiv_val > 47)) {return 0x42;}
// Check PLL reference clock frequency is within spec.
ref_freq = crystal_val / prdiv_val;
if ((ref_freq < 8000000) || (ref_freq > 32000000)) {return 0x43;}
// Check PLL output frequency is within spec.
pll_freq = (crystal_val / prdiv_val) * vdiv_val;
if ((pll_freq < 180000000) || (pll_freq > 360000000)) {return 0x45;}
// Determine if oscillator needs to be set up
if (init_osc)
{
// Check if the oscillator needs to be configured
if (!osc_select)
{
// configure the MCG_C2 register
// the RANGE value is determined by the external frequency. Since the RANGE parameter affects the FRDIV divide value
// it still needs to be set correctly even if the oscillator is not being used
temp_reg = MCG_C2;
temp_reg &= ~(MCG_C2_RANGE_MASK | MCG_C2_HGO_MASK | MCG_C2_EREFS_MASK); // clear fields before writing new values
if (crystal_val <= 8000000)
{
temp_reg |= (MCG_C2_RANGE(1) | (hgo_val << MCG_C2_HGO_SHIFT) | (erefs_val << MCG_C2_EREFS_SHIFT));
}
else
{
// On rev. 1.0 of silicon there is an issue where the the input bufferd are enabled when JTAG is connected.
// This has the affect of sometimes preventing the oscillator from running. To keep the oscillator amplitude
// low, RANGE = 2 should not be used. This should be removed when fixed silicon is available.
//temp_reg |= (MCG_C2_RANGE(2) | (hgo_val << MCG_C2_HGO_SHIFT) | (erefs_val << MCG_C2_EREFS_SHIFT));
temp_reg |= (MCG_C2_RANGE(1) | (hgo_val << MCG_C2_HGO_SHIFT) | (erefs_val << MCG_C2_EREFS_SHIFT));
}
MCG_C2 = temp_reg;
}
else
{
// configure the MCG_C10 register
// the RANGE value is determined by the external frequency. Since the RANGE parameter affects the FRDIV divide value
// it still needs to be set correctly even if the oscillator is not being used
temp_reg = MCG_C10;
temp_reg &= ~(MCG_C10_RANGE2_MASK | MCG_C10_HGO2_MASK | MCG_C10_EREFS2_MASK); // clear fields before writing new values
if (crystal_val <= 8000000)
{
temp_reg |= MCG_C10_RANGE2(1) | (hgo_val << MCG_C10_HGO2_SHIFT) | (erefs_val << MCG_C10_EREFS2_SHIFT);
}
else
{
// On rev. 1.0 of silicon there is an issue where the the input bufferd are enabled when JTAG is connected.
// This has the affect of sometimes preventing the oscillator from running. To keep the oscillator amplitude
// low, RANGE = 2 should not be used. This should be removed when fixed silicon is available.
//temp_reg |= MCG_C10_RANGE2(2) | (hgo_val << MCG_C10_HGO2_SHIFT) | (erefs_val << MCG_C10_EREFS2_SHIFT);
temp_reg |= MCG_C10_RANGE2(1) | (hgo_val << MCG_C10_HGO2_SHIFT) | (erefs_val << MCG_C10_EREFS2_SHIFT);
}
MCG_C10 = temp_reg;
} // if (!osc_select)
} // if (init_osc)
if (mcgout_select)
{
// determine FRDIV based on reference clock frequency
// since the external frequency has already been checked only the maximum frequency for each FRDIV value needs to be compared here.
if (crystal_val <= 1250000) {frdiv_val = 0;}
else if (crystal_val <= 2500000) {frdiv_val = 1;}
else if (crystal_val <= 5000000) {frdiv_val = 2;}
else if (crystal_val <= 10000000) {frdiv_val = 3;}
else if (crystal_val <= 20000000) {frdiv_val = 4;}
else {frdiv_val = 5;}
// Select external oscillator and Reference Divider and clear IREFS to start ext osc
// If IRCLK is required it must be enabled outside of this driver, existing state will be maintained
// CLKS=2, FRDIV=frdiv_val, IREFS=0, IRCLKEN=0, IREFSTEN=0
temp_reg = MCG_C1;
temp_reg &= ~(MCG_C1_CLKS_MASK | MCG_C1_FRDIV_MASK | MCG_C1_IREFS_MASK); // Clear values in these fields
temp_reg = MCG_C1_CLKS(2) | MCG_C1_FRDIV(frdiv_val); // Set the required CLKS and FRDIV values
MCG_C1 = temp_reg;
// if the external oscillator is used need to wait for OSCINIT to set
if (erefs_val)
{
for (i = 0 ; i < 10000 ; i++)
{
if (MCG_S & MCG_S_OSCINIT_MASK) break; // jump out early if OSCINIT sets before loop finishes
}
if (!(MCG_S & MCG_S_OSCINIT_MASK)) return 0x23; // check bit is really set and return with error if not set
}
// wait for Reference clock Status bit to clear
for (i = 0 ; i < 2000 ; i++)
{
if (!(MCG_S & MCG_S_IREFST_MASK)) break; // jump out early if IREFST clears before loop finishes
}
if (MCG_S & MCG_S_IREFST_MASK) return 0x11; // check bit is really clear and return with error if not set
// Wait for clock status bits to show clock source is ext ref clk
for (i = 0 ; i < 2000 ; i++)
{
if (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) == 0x2) break; // jump out early if CLKST shows EXT CLK slected before loop finishes
}
if (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2) return 0x1A; // check EXT CLK is really selected and return with error if not
// Now in FBE
// It is recommended that the clock monitor is enabled when using an external clock as the clock source/reference.
// It is enabled here but can be removed if this is not required.
MCG_C6 |= MCG_C6_CME_MASK;
// Select which PLL to enable
if (!pll_select)
{
// Configure PLL0
// Ensure OSC0 is selected as the reference clock
MCG_C5 &= ~MCG_C5_PLLREFSEL_MASK;
//Select PLL0 as the source of the PLLS mux
MCG_C11 &= ~MCG_C11_PLLCS_MASK;
// Configure MCG_C5
// If the PLL is to run in STOP mode then the PLLSTEN bit needs to be OR'ed in here or in user code.
temp_reg = MCG_C5;
temp_reg &= ~MCG_C5_PRDIV_MASK;
temp_reg |= MCG_C5_PRDIV(prdiv_val - 1); //set PLL ref divider
MCG_C5 = temp_reg;
// Configure MCG_C6
// The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
// The loss of lock interrupt can be enabled by seperately OR'ing in the LOLIE bit in MCG_C6
temp_reg = MCG_C6; // store present C6 value
temp_reg &= ~MCG_C6_VDIV_MASK; // clear VDIV settings
temp_reg |= MCG_C6_PLLS_MASK | MCG_C6_VDIV(vdiv_val - 16); // write new VDIV and enable PLL
MCG_C6 = temp_reg; // update MCG_C6
// wait for PLLST status bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S & MCG_S_PLLST_MASK) break; // jump out early if PLLST sets before loop finishes
}
if (!(MCG_S & MCG_S_PLLST_MASK)) return 0x16; // check bit is really set and return with error if not set
// Wait for LOCK bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S & MCG_S_LOCK_MASK) break; // jump out early if LOCK sets before loop finishes
}
if (!(MCG_S & MCG_S_LOCK_MASK)) return 0x44; // check bit is really set and return with error if not set
// Use actual PLL settings to calculate PLL frequency
prdiv = ((MCG_C5 & MCG_C5_PRDIV_MASK) + 1);
vdiv = ((MCG_C6 & MCG_C6_VDIV_MASK) + 16);
}
else
{
// Configure PLL1
// Ensure OSC0 is selected as the reference clock
MCG_C11 &= ~MCG_C11_PLLREFSEL2_MASK;
//Select PLL1 as the source of the PLLS mux
MCG_C11 |= MCG_C11_PLLCS_MASK;
// Configure MCG_C11
// If the PLL is to run in STOP mode then the PLLSTEN2 bit needs to be OR'ed in here or in user code.
temp_reg = MCG_C11;
temp_reg &= ~MCG_C11_PRDIV2_MASK;
temp_reg |= MCG_C11_PRDIV2(prdiv_val - 1); //set PLL ref divider
MCG_C11 = temp_reg;
// Configure MCG_C12
// The PLLS bit is set to enable the PLL, MCGOUT still sourced from ext ref clk
// The loss of lock interrupt can be enabled by seperately OR'ing in the LOLIE2 bit in MCG_C12
temp_reg = MCG_C12; // store present C12 value
temp_reg &= ~MCG_C12_VDIV2_MASK; // clear VDIV settings
temp_reg |= MCG_C12_VDIV2(vdiv_val - 16); // write new VDIV and enable PLL
MCG_C12 = temp_reg; // update MCG_C12
// Enable PLL by setting PLLS bit
MCG_C6 |= MCG_C6_PLLS_MASK;
// wait for PLLCST status bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S2 & MCG_S2_PLLCST_MASK) break; // jump out early if PLLST sets before loop finishes
}
if (!(MCG_S2 & MCG_S2_PLLCST_MASK)) return 0x17; // check bit is really set and return with error if not set
// wait for PLLST status bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S & MCG_S_PLLST_MASK) break; // jump out early if PLLST sets before loop finishes
}
if (!(MCG_S & MCG_S_PLLST_MASK)) return 0x16; // check bit is really set and return with error if not set
// Wait for LOCK bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S2 & MCG_S2_LOCK2_MASK) break; // jump out early if LOCK sets before loop finishes
}
if (!(MCG_S2 & MCG_S2_LOCK2_MASK)) return 0x44; // check bit is really set and return with error if not set
// Use actual PLL settings to calculate PLL frequency
prdiv = ((MCG_C11 & MCG_C11_PRDIV2_MASK) + 1);
vdiv = ((MCG_C12 & MCG_C12_VDIV2_MASK) + 16);
} // if (!pll_select)
// now in PBE
MCG_C1 &= ~MCG_C1_CLKS_MASK; // clear CLKS to switch CLKS mux to select PLL as MCG_OUT
// Wait for clock status bits to update
for (i = 0 ; i < 2000 ; i++)
{
if (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) == 0x3) break; // jump out early if CLKST = 3 before loop finishes
}
if (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3) return 0x1B; // check CLKST is set correctly and return with error if not
// Now in PEE
}
else
{
// Setup PLL for peripheral only use
if (pll_select)
{
// Setup and enable PLL1
// Select ref source
if (osc_select)
{
MCG_C11 |= MCG_C11_PLLREFSEL2_MASK; // Set select bit to choose OSC1
}
else
{
MCG_C11 &= ~MCG_C11_PLLREFSEL2_MASK; // Clear select bit to choose OSC0
}
// Configure MCG_C11
// If the PLL is to run in STOP mode then the PLLSTEN2 bit needs to be OR'ed in here or in user code.
temp_reg = MCG_C11;
temp_reg &= ~MCG_C11_PRDIV2_MASK;
temp_reg |= MCG_C11_PRDIV2(prdiv_val - 1); //set PLL ref divider
MCG_C11 = temp_reg;
// Configure MCG_C12
// The loss of lock interrupt can be enabled by seperately OR'ing in the LOLIE2 bit in MCG_C12
temp_reg = MCG_C12; // store present C12 value
temp_reg &= ~MCG_C12_VDIV2_MASK; // clear VDIV settings
temp_reg |= MCG_C12_VDIV2(vdiv_val - 16); // write new VDIV and enable PLL
MCG_C12 = temp_reg; // update MCG_C12
// Now enable the PLL
MCG_C11 |= MCG_C11_PLLCLKEN2_MASK; // Set PLLCLKEN2 to enable PLL1
// Wait for LOCK bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S2 & MCG_S2_LOCK2_MASK) break; // jump out early if LOCK sets before loop finishes
}
if (!(MCG_S2 & MCG_S2_LOCK2_MASK)) return 0x44; // check bit is really set and return with error if not set
// Use actual PLL settings to calculate PLL frequency
prdiv = ((MCG_C11 & MCG_C11_PRDIV2_MASK) + 1);
vdiv = ((MCG_C12 & MCG_C12_VDIV2_MASK) + 16);
}
else
{
// Setup and enable PLL0
// Select ref source
if (osc_select)
{
MCG_C5 |= MCG_C5_PLLREFSEL_MASK; // Set select bit to choose OSC1
}
else
{
MCG_C5 &= ~MCG_C5_PLLREFSEL_MASK; // Clear select bit to choose OSC0
}
// Configure MCG_C5
// If the PLL is to run in STOP mode then the PLLSTEN bit needs to be OR'ed in here or in user code.
temp_reg = MCG_C5;
temp_reg &= ~MCG_C5_PRDIV_MASK;
temp_reg |= MCG_C5_PRDIV(prdiv_val - 1); //set PLL ref divider
MCG_C5 = temp_reg;
// Configure MCG_C6
// The loss of lock interrupt can be enabled by seperately OR'ing in the LOLIE bit in MCG_C6
temp_reg = MCG_C6; // store present C6 value
temp_reg &= ~MCG_C6_VDIV_MASK; // clear VDIV settings
temp_reg |= MCG_C6_VDIV(vdiv_val - 16); // write new VDIV and enable PLL
MCG_C6 = temp_reg; // update MCG_C6
// Now enable the PLL
MCG_C5 |= MCG_C5_PLLCLKEN_MASK; // Set PLLCLKEN to enable PLL0
// Wait for LOCK bit to set
for (i = 0 ; i < 2000 ; i++)
{
if (MCG_S & MCG_S_LOCK_MASK) break; // jump out early if LOCK sets before loop finishes
}
if (!(MCG_S & MCG_S_LOCK_MASK)) return 0x44; // check bit is really set and return with error if not set
// Use actual PLL settings to calculate PLL frequency
prdiv = ((MCG_C5 & MCG_C5_PRDIV_MASK) + 1);
vdiv = ((MCG_C6 & MCG_C6_VDIV_MASK) + 16);
} // if (pll_select)
} // if (mcgout_select)
return (((crystal_val / prdiv) * vdiv) / 2); //MCGOUT equals PLL output frequency/2
} // pll_init
/********************************************************************/
void fb_clk_init(void)
{
/* Enable the clock to the FlexBus module */
SIM_SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
/* Enable the FB_CLKOUT function on PTC3 (alt5 function) */
PORTC_PCR3 = ( PORT_PCR_MUX(0x5));
}
void twr_ddr2_script_init(void)
{
/* Enable DDR controller clock */
SIM_SCGC3 |= SIM_SCGC3_DDR_MASK;
/* Enable DDR pads and set slew rate */
SIM_MCR |= 0xC4; // bits were left out of the manual so there isn't a macro right now
DDR_RCR |= DDR_RCR_RST_MASK;
* (cyg_uint32 *)(0x400Ae1ac) = 0x01030203;
DDR_CR00 = 0x00000400;
DDR_CR02 = 0x02000031;
DDR_CR03 = 0x02020506;
DDR_CR04 = 0x06090202;
DDR_CR05 = 0x02020302;
DDR_CR06 = 0x02904002;
DDR_CR07 = 0x01000303;
DDR_CR08 = 0x05030201;
DDR_CR09 = 0x020000c8;
DDR_CR10 = 0x03003207;
DDR_CR11 = 0x01000000;
DDR_CR12 = 0x04920031;
DDR_CR13 = 0x00000005;
DDR_CR14 = 0x00C80002;
DDR_CR15 = 0x00000032;
DDR_CR16 = 0x00000001;
DDR_CR20 = 0x00030300;
DDR_CR21 = 0x00040232;
DDR_CR22 = 0x00000000;
DDR_CR23 = 0x00040302;
DDR_CR25 = 0x0A010201;
DDR_CR26 = 0x0101FFFF;
DDR_CR27 = 0x01010101;
DDR_CR28 = 0x00000003;
DDR_CR29 = 0x00000000;
DDR_CR30 = 0x00000001;
DDR_CR34 = 0x02020101;
DDR_CR36 = 0x01010201;
DDR_CR37 = 0x00000200;
DDR_CR38 = 0x00200000;
DDR_CR39 = 0x01010020;
DDR_CR40 = 0x00002000;
DDR_CR41 = 0x01010020;
DDR_CR42 = 0x00002000;
DDR_CR43 = 0x01010020;
DDR_CR44 = 0x00000000;
DDR_CR45 = 0x03030303;
DDR_CR46 = 0x02006401;
DDR_CR47 = 0x01020202;
DDR_CR48 = 0x01010064;
DDR_CR49 = 0x00020101;
DDR_CR50 = 0x00000064;
DDR_CR52 = 0x02000602;
DDR_CR53 = 0x03c80000;
DDR_CR54 = 0x03c803c8;
DDR_CR55 = 0x03c803c8;
DDR_CR56 = 0x020303c8;
DDR_CR57 = 0x01010002;
__asm__ volatile ("nop\n");
DDR_CR00 |= 0x00000001;
while ((DDR_CR30 & 0x400) != 0x400);
MCM_CR |= MCM_CR_DDRSIZE(1);
}
//==========================================================================
// EOF kinetis_clocking.c
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss