📄 bsp.c
字号:
/*
*********************************************************************************************************
* Atmel AT91SAM9261
* Board Support Package
*
* (c) Copyright 2004, Micrium, Inc., Weston, FL
* All Rights Reserved
*
*
* File : BSP.C
* By : Eric Shufro
*********************************************************************************************************
*/
#include <includes.h>
/*
*********************************************************************************************************
* CONSTANTS
*********************************************************************************************************
*/
#define SLOW_CLK_FRQ 32768UL /* Slow oscillator clock frequency in Hz */
#define MAIN_CLK_FRQ 18432000UL /* Main oscillator clock frequency (crystal frequency) Hz */
#define BSP_RAM_REMAP_TEST_BYTE (*(CPU_INT08U *)0x00000030UL)
/*
*********************************************************************************************************
* DATA TYPES
*********************************************************************************************************
*/
typedef void (*BSP_FNCT_PTR)(void);
/*
*********************************************************************************************************
* PROTOTYPES
*********************************************************************************************************
*/
static void BSP_DummyISR_Handler(void);
static void BSP_IntCtrlInit(void);
static void PLL_Init(void);
#if BSP_EXT_MEM_INIT
static void ExtMemory_Init(void);
#endif
static void Tmr_TickInit(void);
static void Tmr_TickISR_Handler(void);
void Sys_Int_Handler(void);
/*
*********************************************************************************************************
* DUMMY IRQ HANDLER
*
* Description : This function is called to handle invalid IRQs
*
* Arguments : none
*********************************************************************************************************
*/
static void BSP_DummyISR_Handler (void)
{
CPU_INT32U irq_id;
irq_id = AT91C_BASE_AIC->AIC_ISR & 0x1F; /* Retrieve the ID of the interrupting source */
AT91C_BASE_AIC->AIC_ICCR = (1 << irq_id); /* Clear the current interrupt */
}
/*
*********************************************************************************************************
* BSP INITIALIZATION
*
* Description : This function should be called by your application code before you make use of any of the
* functions found in this module.
*
* Arguments : none
*********************************************************************************************************
*/
void BSP_Init (void)
{
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; /* Disable the Watchdog Timer */
AT91C_BASE_RSTC->RSTC_RMR = ((0x01 << 8) & AT91C_RSTC_ERSTL)
| AT91C_RSTC_KEY;
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_EXTRST /* Assert the NRST pin to reset the peripherals */
| AT91C_RSTC_KEY; /* Provide the correct KEY */
while ((AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL) == 0) { /* Wait for reset to complete */
;
}
LED_Init(); /* Initialize the I/Os for the LEDs */
PLL_Init(); /* Initialize PLLA and select it for MCLK */
BSP_IntCtrlInit(); /* Initialize the Interrupt Controller */
Tmr_TickInit(); /* Initialize uC/OS-II's Tick Rate */
#if BSP_EXT_MEM_INIT /* ExtMemoryInit is not necessary when using a boot loader */
ExtMemory_Init(); /* Initialize External Memories */
#endif
}
/*
*********************************************************************************************************
* PLL INITIALIZATION
*
* Description : This function initializes the AT91SAM9261 PLLB which controlls the main processor
* and USB clock.
*
* Arguments : none
*
* Notes : 1) PLLB was chosen over PLLA since it also controls the USB clock, as opposed to having
* to initialize both PLLA for the MCLK and PLLB for the USB clock.
*
* 2) The PLL input reference clock is #defined above as MAIN_CLK_FRQ = 18.432MHz. To
* generate the PLL output frequency, the equation is:
*
* (MAIN_CLK_FRQ / DIV) * MULT + 1, where (MAIN_CLK_FRQ / DIV) > 1MHz
*********************************************************************************************************
*/
static void PLL_Init (void)
{
CPU_INT32U reg_val;
/* Enable the Main Oscillator */
AT91C_BASE_CKGR->CKGR_MOR = AT91C_CKGR_OSCOUNT | AT91C_CKGR_MOSCEN;
/* Wait for the Main Oscillator to start up */
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS) == 0) {
;
}
AT91C_BASE_PMC->PMC_PLLBR = 0x20913F0E; /* Conf PLLB assuming input frq BSP_XTAL_FREQ */
/* Summary: PLLB CLK: 192MHZ, USB CLKS: 48MHZ */
/* [07:00] Divider = 14 */
/* [13:08] PLLBCount startup dly: 63 SCLKs */
/* [26:16] Multiplier = (145 + 1) = 146 */
/* [29:28] USB Divider = 4 */
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKB) == 0) { /* Wait for the PLL to start up */
;
}
reg_val = AT91C_BASE_PMC->PMC_MCKR; /* Read the current Master Clock configuration */
reg_val &= ~AT91C_PMC_MDIV; /* Clear the Master Divider bits */
reg_val &= ~AT91C_PMC_PRES; /* Clear the prescaler bits */
reg_val |= AT91C_PMC_MDIV_2; /* Configure a Master clock divider of 2 */
reg_val |= AT91C_PMC_PRES_CLK; /* Set a processor clock (PCK) divider of 1 */
AT91C_BASE_PMC->PMC_MCKR = reg_val; /* Write new prescaler of 2, do not change CSS field. */
/* MCK must be less than 119MHz, therefore (PLLB / 2) is ok */
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0) { /* Wait ready bit to become set before switching to PLLB */
;
}
reg_val &= ~AT91C_PMC_CSS; /* Clear the CSS field bits */
reg_val |= AT91C_PMC_CSS_PLLB_CLK; /* Configure CSS field, do not modify the PRES field */
AT91C_BASE_PMC->PMC_MCKR |= reg_val; /* Switch to the PLLB */
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0) { /* Wait for the Master Clock (MCK) to start up */
;
}
}
/*
*********************************************************************************************************
* DETERMINE AND RETURN CPU OPERATING FREQUENCY
*
* Description : This function is called by OSView_c.c : OSView_GetCPUName().
* and will return the processor clock frequency (PCK) in Hz
*
* Arguments : none
*
* Returns : The CPU frequency (PCK)in Hz, 0 on error
*********************************************************************************************************
*/
CPU_INT32U BSP_PCK_Frq (void)
{
CPU_INT08U pres;
CPU_INT08U css;
CPU_INT32U pll_mult;
CPU_INT32U pll_div;
CPU_INT32U sel_clk_frq;
CPU_INT32U pck_frq;
css = (AT91C_BASE_PMC->PMC_MCKR & 0x03); /* Get the Clock Selection Source field */
pres = (AT91C_BASE_PMC->PMC_MCKR >> 2) & 0x07; /* Get the selected clock prescaler setting */
pres = (1 << pres); /* Convert 0-7 into 1, 2, 4, 8, 16, 32, or 64 */
switch (css) {
case 0x00: /* Slow clock currently selected */
sel_clk_frq = SLOW_CLK_FRQ; /* Get the Slow Clock frequency in Hz */
break;
case 0x01: /* Main Clock currently selected */
sel_clk_frq = MAIN_CLK_FRQ; /* Get the Main Clock frequency in Hz */
break;
case 0x02: /* PLLA currently selected */
pll_mult = (AT91C_BASE_CKGR->CKGR_PLLAR & 0x07FF0000) >> 16;
pll_div = (AT91C_BASE_CKGR->CKGR_PLLAR & 0x000000FF) >> 0;
sel_clk_frq = (MAIN_CLK_FRQ / pll_div) * (pll_mult + 1);
break;
case 0x03: /* PLLB currently selected */
pll_mult = (AT91C_BASE_CKGR->CKGR_PLLBR & 0x07FF0000) >> 16;
pll_div = (AT91C_BASE_CKGR->CKGR_PLLBR & 0x000000FF) >> 0;
sel_clk_frq = (MAIN_CLK_FRQ / pll_div) * (pll_mult + 1);
break;
}
pck_frq = sel_clk_frq / pres; /* Determine the peripheral clock frequency which feeds MCK */
return (pck_frq);
}
/*
*********************************************************************************************************
* DETERMINE AND RETURN CPU OPERATING FREQUENCY
*
* Description : This function is called by varous modules for determine the peripheral clock
* frequency (MCK, Master Clock).
* Arguments : none
*
* Returns : The CPU frequency (MCK)in Hz, 0 on error
*********************************************************************************************************
*/
CPU_INT32U BSP_MCK_Frq (void)
{
CPU_INT08U mdiv;
CPU_INT32U mck_frq;
CPU_INT32U pck_frq;
pck_frq = BSP_PCK_Frq(); /* Get the processor clock frequency */
mdiv = (AT91C_BASE_PMC->PMC_MCKR >> 8) & 0x03; /* Get the Master Clock (MCK) Divider field */
if (mdiv != 3) { /* Ensure that the MCLK divider is not the reserved value */
mdiv = (1 << mdiv); /* If not reserved, convert 0-3 into 1, 2, 4 */
} else {
return (0); /* Return 0 if MDIV is set to the reserved value */
}
mck_frq = pck_frq / mdiv; /* Determine the Master Clock (MCK) frequency in Hz */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -