⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tm_clk.c

📁 YL9200开发板的BIOSBOX源码
💻 C
字号:
#include "../inc/def.h"
#include "../inc/config.h"
#include "../inc/board.h"
#include "../inc/slib.h"
#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#include "../inc/utils.h"

#define	DELAY_PLL			1000
#define DELAY_MAIN_FREQ		1000

#define	EXT_OSC_CLK			18432000

#define AT91C_PLLA_VALUE	0x205FBE0A	//PLLA = 0x60*18.432M/0xa = 176.9472M
#define	MCKR_VAL	0x202				//1/3

static struct{
	U32 plla;
	U32 mckr;
	U32 n1;
	U32 n2;
} ClkPara;

#define	AT91C_PLLB_VALUE	0x10483E0E	//* 48,054857 MHz (divider by 2 for USB)

static void set_pll(void)
{
	volatile int tmp = 0;
	U32 freq;
	
	/* APMC Initialization for Crystal */
	AT91PS_PMC pApmc = (AT91PS_PMC)AT91C_BASE_PMC;
	AT91PS_CKGR pCkgr =  (AT91PS_CKGR)AT91C_BASE_CKGR;
	
//	if(((pCkgr->CKGR_PLLAR&0x7ff0000)==(ClkPara.plla&0x7ff0000)) &&
//		((pCkgr->CKGR_PLLAR&0xff)==(ClkPara.plla&0xff)) &&
//		(pApmc->PMC_MCKR==))
//		return
	
	ClkPara.plla &= 0x7ff00ff;
	ClkPara.plla |= (1<<29)|(0x3f<<8);
	freq = (((ClkPara.plla>>16)&0x7ff)+1)*EXT_OSC_CLK/(ClkPara.plla&0xff);
	if(freq>=150000000)
		ClkPara.plla |= 1<<15;
		
	ClkPara.mckr &= 0x300;
	ClkPara.mckr |= 2;

	//禁止PMC的所有中断源
	pApmc->PMC_IDR = 0xFFFFFFFF;
	
	// Setting PLLB and Divider B
	if((pCkgr->CKGR_PLLBR^AT91C_PLLB_VALUE)&0x07ff00ff) {
		pCkgr->CKGR_PLLBR = AT91C_PLLB_VALUE;
		//* Wait for PLLB stabilization LOCKB bit in PMC_SR
		tmp = 0;
		while(!(pApmc->PMC_SR & AT91C_PMC_LOCKB) && (tmp++ < DELAY_MAIN_FREQ));
	}
	
	//先选择PLLB做为主时钟
	/* Write in the MCKR dirty value concerning the clock selection CSS then overwrite it in a second sequence */
	pApmc->PMC_MCKR = 0x203;
	/* Wait until the master clock is established */
	tmp = 0;
	while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_PLL));

	//再设置PLLA,若原主时钟为PLLA而在未切换到其他时钟源时设置PLLA(值不变),启动会等很久,why?
	if((pCkgr->CKGR_PLLAR^ClkPara.plla)&0x07ff00ff) {
		pCkgr->CKGR_PLLAR = ClkPara.plla;
		//* Wait for PLLB stabilization LOCKB bit in PMC_SR
		tmp = 0;
		while(!(pApmc->PMC_SR & AT91C_PMC_LOCKA) && (tmp++ < DELAY_PLL));
	}
	
	//再把主时钟源换到PLLA,设置同步模式,等待时钟稳定
	/* - Commuting Master Clock from PLLB to PLLA/3 */
	pApmc->PMC_MCKR = ClkPara.mckr;	//master clock 为 PLLA,预分频为1,Processor clock为master clock的2/3倍
	/* Wait until the master clock is established */
	tmp = 0;
	while(!(pApmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
	MMU_SetAsyncBusMode();		//设置CPU总线同步模式	
	
	ClkPara.n1   = GetCpuClock();
	ClkPara.n2   = GetMasterClock();
}

void SystemClockInit(void)
{
	//ClkPara.plla = AT91C_PLLA_VALUE;
	//ClkPara.mckr = MCKR_VAL;
	ClkPara.plla = (97<<16)|10;
	ClkPara.mckr = 2<<8;
	set_pll();
}

U32 GetCpuClock(void)
{
	return AT91F_PMC_GetProcessorClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, 32768);
}

U32 GetMasterClock(void)
{
	return AT91F_PMC_GetMasterClock(AT91C_BASE_PMC, AT91C_BASE_CKGR, 32768);
}

int SetSysClock(void)
{
	int mul, div, mdiv;
	char tmp[8];
	
	printf("Please enter the PLL parameter to use, mul[0-2047], div[0-255], mdiv[0-3]\n");
	
	printf("mul: ");
	if((mul=strtodec(tmp, GetParameter(tmp, 4)))<0) {
		printf("\nget mull Error!\n");
		return -1;
	}					
	
	printf("\ndiv: ");
	if((div=strtodec(tmp, GetParameter(tmp, 3)))<0) {
		printf("\nget div Error!\n");
		return -1;
	}	
	
	printf("\nmdiv: ");
	if((mdiv=strtodec(tmp, GetParameter(tmp, 1)))<0) {
		printf("\nget mdiv Error!\n");
		return -1;
	}		
	
	if((mul>2047)||(div>255)||(mdiv>3)) {
		printf("Parameters error!\n");
		return -1;
	}	
	
	printf("\nYou set System clock mul = %d, div = %d, mdiv = %d\n", mul, div, mdiv);
	
	Delay(10);
		
	ClkPara.plla = (mul<<16)|div;
	ClkPara.mckr = mdiv<<8;
	
	set_pll();
	
	return 0;
}

U32 GetSysClock(SysClock pSysClock[])
{
	pSysClock[0].name = "CPU";
	pSysClock[0].freq = GetCpuClock();
	pSysClock[1].name = "Master";
	pSysClock[1].freq = GetMasterClock();

	return 2;
}

void SetSysClockPara(void *addr)
{
	U32 *pData = addr;
	
	ClkPara.plla = pData[0];
	ClkPara.mckr = pData[1];	
	
	set_pll();
}

void GetSysClockPara(void *addr)
{
	U32 *pData = addr;
	
	pData[0] = ClkPara.plla;
	pData[1] = ClkPara.mckr;
	pData[2] = ClkPara.n1;
	pData[3] = ClkPara.n2;
}

void TimerInit(U32 HZ)
{
	AT91PS_TC pTC = AT91C_BASE_TC0;
	
	AT91F_TC0_CfgPMC();
	pTC->TC_IDR = 0xff;	//disable all interrupts
	//select TIMER_CLOCK2 = MCK/8, CPCTRG, up mode, Waveform mode
	pTC->TC_CMR = 1|(2<<13)|(1<<15);	//Capture模式下,RC COMPARE也可复位计数器
	pTC->TC_RC  = (GetMasterClock()>>3)/HZ;
	pTC->TC_CCR = 5;	//enable timer-counter and trig it
}

/*static __inline void ResetTimer(void)
{
	AT91C_BASE_TC0->TC_CCR = 4;
}*/

void Delay(U32 ms)
{
	U16 i;
	
	i = AT91C_BASE_TC0->TC_RC>>1;	//1000us/2
	
	AT91C_BASE_TC0->TC_CCR = 4;	//复位为0,加计数
	
	while(ms--) {
		while(AT91C_BASE_TC0->TC_CV<=i);
		while(AT91C_BASE_TC0->TC_CV>i);
	}
}

int WaitEventWithTimeout(int (*event)(void), int cond, U32 ms)
{
	int result;
	U16 half, ms_h;
	
	AT91C_BASE_TC0->TC_CCR = 4;
	half = AT91C_BASE_TC0->TC_RC>>1;
	ms_h = 0;
	
	while(ms) {
		result = (*event)();
		if(cond) {
			if(result)				
				return 0;
		} else {
			if(!result)
				return 0;
		}
	
		if(!ms_h) {
			if(AT91C_BASE_TC0->TC_CV>=half)
				ms_h = 1;
		} else {
			if(AT91C_BASE_TC0->TC_CV<half) {
				ms_h = 0;
				ms--;
			}
		}
	}
	
	return -1;
}

/*************************************************************/
void RtcSetDay(TIME_STRUC *time)
{
	AT91PS_RTC pRTC = AT91C_BASE_RTC;
	U32 tmp;
	
//	printf("RTC_VER=%x\n", pRTC->RTC_VER);
	//设置正确日期时间后可清除invalid位
	while(!(pRTC->RTC_SR&4));	
	
	tmp  = pRTC->RTC_CALR&(7<<21);
	tmp |= ((time->year&0x3f00)>>8) |
			((time->year&0xff)<<8) |
			((time->month&0x1f)<<16) |
			(time->day&0x3f)<<24;	
	
	pRTC->RTC_CR |= 3;
	while(!(pRTC->RTC_SR&1));
	
	pRTC->RTC_CALR = tmp;
					
	pRTC->RTC_CR &= ~3;
	
	pRTC->RTC_SCCR = 0x1f;
	
//	printf("RTC_VER=%x\n", pRTC->RTC_VER);
}

void RtcSetWeek(TIME_STRUC *time)
{
	AT91PS_RTC pRTC = AT91C_BASE_RTC;
	U32 tmp;	
	
	while(!(pRTC->RTC_SR&4));
	
	tmp = pRTC->RTC_CALR;
	tmp &= ~(7<<21);
	tmp |= (time->weekday&7)<<21;
	
	pRTC->RTC_CR |= 3;
	while(!(pRTC->RTC_SR&1));
	
	pRTC->RTC_CALR = tmp;	
	
	pRTC->RTC_CR &= ~3;
	
	pRTC->RTC_SCCR = 0x1f;
}

void RtcSetTime(TIME_STRUC *time)
{
	AT91PS_RTC pRTC = AT91C_BASE_RTC;
	
	while(!(pRTC->RTC_SR&4));
	
	pRTC->RTC_CR |= 1;
	while(!(pRTC->RTC_SR&1));
	
	pRTC->RTC_MR &= ~1;	//24 Hour mode	
	pRTC->RTC_TIMR = (time->hour<<16)|(time->min<<8)|time->sec;
	
	pRTC->RTC_CR &= ~1;
	
	pRTC->RTC_SCCR = 0x1f;
}

void RtcGetTime(TIME_STRUC *time)
{
	AT91PS_RTC pRTC = AT91C_BASE_RTC;
	U32 tmp, tmp1;
	
get_tm_agn:	
	tmp  = pRTC->RTC_TIMR;
	tmp1 = pRTC->RTC_CALR;

	time->year    = ((tmp1&0x3f)<<8)+((tmp1&0xff00)>>8);
	time->month   = (tmp1>>16)&0x1f;
	time->day     = (tmp1>>24)&0x3f;
	time->weekday = (tmp1>>21)&0x7;
	time->hour    = (tmp>>16)&0x3f;
	time->min     = (tmp>>8)&0x7f;
	time->sec     = tmp&0x7f;
	if(tmp!=pRTC->RTC_TIMR)
		goto get_tm_agn;
	
	if(pRTC->RTC_MR&1) {
		if(pRTC->RTC_TIMR&(1<<22))
			time->hour += 0x12;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -