LPC3250的時鐘介紹

2021-06-16 08:17:39 字數 4980 閱讀 8941

arm_clk:在sysclk後有乙個hclkpll用於將sysclk轉換成arm_clk。arm_clk用於armcpu,mssdclk。在暫存器hclk_ctrl中,arm_clk將會被分頻成hclk,pclk和ddram_clk。

hclk:ahb匯流排時鐘。用於ahb矩陣和usbahb、ahb從機、fab從機和apb從機

p_clk:外設時鐘。

clk48mhz:usb48mhz時鐘——基於osc_clk。

ddram_clk:ddr sdram時鐘

mssdclk:sd卡時鐘。

二、clock.c中有關函式介紹

clk結構體定義

struct clk {

structlist_head node;

struct module*owner;

const char*name;           /* clock name */

struct clk*parent;           /* parent clock */

u32 rate;                 /* rate in hz for the clock (0= disabled) */

u32 flags;                /* setup flags */

s8 usecount;                   /* number of users of thisclock */

/* requiredfunctions per clock */

int(*set_rate) (struct clk *, u32);

u32(*round_rate) (struct clk *, u32);

int (*enable)(struct clk *clk, int);

/* optionalfunctions per clock */

int(*set_parent) (struct clk * clk, struct clk * parent);

u32(*get_rate) (struct clk *clk);

/* registerand mask for enablings/disabling the clock, only

used when the clk_flag_st_enab flag is set*/

u32enable_reg;               /* register toenable and disable associated clock */

u32enable_mask;            /* or mask forenable, and ~mask for disable */

static void clk_upate_children(struct clk *clk)

local_update_armpll_rate();

local_update_usbpll_rate();

這個函式作用就是根據輸入的系統時鐘sysclk和相關暫存器的設定來獲得clk_armpll.rate和clk_usbpll.rate 的成員值。當然後面還有函式會根據這個值去設定相關暫存器。

local_update_armpll_rate()和local_update_usbpll_rate()實現過程相仿。只追蹤第乙個函式的實現過程。

static void local_update_armpll_rate(void)

u32 clkin,pllreg;

/* get pllinput clock rate */

獲得系統時鐘速率

clkin =clk_armpll.parent->rate;

/* get armhclkpll register */

pllreg =__raw_readl(clkpwr_hclkpll_ctrl(clkpwr_iobase)) & 0x1ffff;

根據系統時鐘速度,和乙個配置項獲得arm_clk的速率。

clk_armpll.rate= local_clk_get_pllrate_from_reg(clkin, pllreg);

static u32 local_clk_find_pll_cfg(u32 pllin_freq,

u32 target_freq,

clkpwr_hclk_pll_setup_t *pllsetup)

這個函式作用是根據目前的pllin_freq和target_freq為設定pllsetup 。即如果按照pllsetup的項去配置相關暫存器,即可實現由pllin_freq 到target_freq的目標。而函式

static u32local_clk_hclkpll_setup(clkpwr_hclk_pll_setup_t *phclkpllsetup)就是做這個事情的。

static int local_armpll_set_rate(struct clk *clk, u32rate)封裝上面介紹的兩個函式。這函式很簡單,給定乙個時鐘,然後再給定乙個要設定的速率。就能實現目標。不看其具體的實現就知道,它先要根據rate和clk->parent.rate為自己找到乙個合適的pllsetup,然後再將任務傳給local_clk_hclkpll_setup()去實現。

static struct clk *chip_clks = {

&osc_32khz,

&osc_pll397,

&osc_main,

&clk_sys,

&clk_armpll,

&clk_hclk,

&clk_pclk,

&clk_usbpll,

&clk_timer0,

&clk_timer1,

&clk_timer2,

&clk_timer3,

&clk_vfp9,

&clk_dma,

#if defined (config_lpc32xx_watchdog)

&clk_wdt,

#endif

#if defined (config_mach_lpc32xx_uart3_enable)

&clk_uart3,

#endif

#if defined (config_mach_lpc32xx_uart4_enable)

&clk_uart4,

#endif

#if defined (config_mach_lpc32xx_uart5_enable)

&clk_uart5,

#endif

#if defined (config_mach_lpc32xx_uart6_enable)

&clk_uart6,

#endif

#if defined (config_mach_lpc32xx_i2c0_enable)

&clk_i2c0,

#endif

#if defined (config_mach_lpc32xx_i2c1_enable)

&clk_i2c1,

#endif

#if defined (config_mach_lpc32xx_usbotg_i2c_enable)

&clk_i2c2,

#endif

#if defined(config_spi_lpc32xx)

#if defined(config_mach_lpc32xx_ssp0_enable)

&clk_ssp0,

#endif

#if defined(config_mach_lpc32xx_ssp1_enable)

&clk_ssp1,

#endif

#endif

#if defined(config_keyboard_lpc32xx)

&clk_kscan,

#endif

#if defined(config_mtd_nand_slc_lpc32xx)

&clk_nand,

#endif

#if defined(config_snd_lpc3***_soc_i2s)

&clk_i2s0,

&clk_i2s1,

#endif

#if defined (config_touchscreen_lpc32xx)

&clk_tsc,

#endif

#if defined (config_mmc_armmmci)

&clk_mmc,

#endif

#if defined (config_lpc32xx_mii)

&clk_net,

#endif

#if defined (config_fb_armclcd)

&clk_lcd,

#endif

#if defined (config_usb_gadget_lpc32xx)

&clk_usbd,

#endif

這個結構體列出了lpc3250可能用到的所有時鐘,而時鐘的具體實現就是利用前面介紹的函式。

struct clk *local_clk_get(struct device *dev, const char*id)這個函式一般是會在id的位置傳入乙個時鐘名稱。然後該函式返回這個時鐘的結構體。第乙個引數沒什麼用處。

static int local_clk_enable(struct clk *clk)這個函式只是根據具體的時鐘,來呼叫clk->enable成員方法。

struct clk *clk_get(struct device *dev, const char *id)是對struct clk *local_clk_get()函式的封裝。只是中間新增了這麼一項:在獲取時鐘結構體期間禁能了中斷

int clk_is_sysclk_mainosc(void)判斷系統時鐘是否是從osc_clk(主振盪器時鐘)獲取。

最後的int __initclk_init(void)函式,分別註冊了lpc3250的時鐘,確定了系統時鐘源。增加引用計數。雖然這個函式將時鐘註冊進了linux系統,但是這配置都還是預設的配置。arm_clk和osc_clk還是一樣的。所以時鐘在具體使用的時候,還要再具體配置。

lpc1768的時鐘樹梳理和小結

可以看到,外部晶振我使用的是8mhz,這個在配置檔案的時候需要設定。不然keil計算就會出現錯誤。看到cclk是100mhz,因為這個晶元最快是100mhz的主頻,usb不能超過48,一般設定為48,可以低於48,但是也有限制,幾個pll都是有最大最小值的限制的,這個在參考手冊中有說明的,因此放大縮...

STM32的時鐘系統介紹

stm32 有5個時鐘源 hsi hse lsi lse pll hsi是高速內部時鐘,rc振盪器,頻率約為8mhz,精度不高。hse是高速外部時鐘,接外部時鐘源,頻率範圍為4mhz 16mhz。lsi是低速內部時鐘,rc振盪器,頻率約為40khz,提供低功耗時鐘。lse是低速外部時鐘,接頻率為32...

TMS320F28335的時鐘介紹

tms320f28335的時鐘介紹 tms320f28335上有乙個基於pll電路的片上時鐘模組,為cpu及外設提供時鐘有兩種方式 一種是用外部的時鐘源,將其連線到x1引腳上或者xclkin引腳上,x2接地 另一種是使用振盪器產生時鐘,用30mhz的晶體和兩個20pf的電容組成的電路分別連線到x1和...