mini2440之Main分析 2012-03-17 20:51:29

分类: 嵌入式

/****************************************************************
 NAME: u2440mon.c
 DESC: u2440mon entry point,menu,download
 HISTORY:
 Mar.25.2002:purnnamu: S3C2400X profile.c is ported for S3C2410X.
 Mar.27.2002:purnnamu: DMA is enabled.
 Apr.01.2002:purnnamu: isDownloadReady flag is added.
 Apr.10.2002:purnnamu: - Selecting menu is available in the waiting loop. 
                         So, isDownloadReady flag gets not needed
                       - UART ch.1 can be selected for the console.
 Aug.20.2002:purnnamu: revision number change 0.2 -> R1.1       
 Sep.03.2002:purnnamu: To remove the power noise in the USB signal, the unused CLKOUT0,1 is disabled.
 ****************************************************************/
#define GLOBAL_CLK  1
#include <stdlib.h>  //声明一些执行数值转换,内存分配以及其他类似工作的函数
#include <string.h>  //字符串函数
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"
extern char Image$$RO$$Limit[];
extern char Image$$RO$$Base[];
extern char Image$$RW$$Limit[];
extern char Image$$RW$$Base[];
extern char Image$$ZI$$Limit[];
extern char Image$$ZI$$Base[];
void Isr_Init(void);
void HaltUndef(void);
void HaltSwi(void);
void HaltPabort(void);
void HaltDabort(void);
void ClearMemory(void);
void Clk0_Enable(int clock_sel); 
void Clk1_Enable(int clock_sel);
void Clk0_Disable(void);
void Clk1_Disable(void);
//extern void TFT_LCD_Init(void);
//extern void TFT_LCD_Test(void);
extern void TFT_LCD_Init(void);
extern void TFT_LCD_Test(void);
extern void Test_Touchpanel(void) ;
extern void Test_Adc(void) ;  //adc test
extern void KeyScan_Test(void) ;
extern void RTC_Display(void) ;
extern void Test_IrDA_Tx(void) ;
extern void PlayMusicTest(void) ;
extern void RecordTest( void ) ;
extern void Test_Iic(void) ;
extern void Test_SDI(void) ;
extern void Camera_Test( void ) ;
//volatile影响编译器编译的结果,指出volatile变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化。
volatile U32 downloadAddress;
// void (*restart)(void),定义一个指针,指针名为restart,指针指向函数,函数的返回类型为void
//(void (*)(void))0x0,将0x0强制转换,使其符合等号左边的类型。
void (*restart)(void)=(void (*)(void))0x0;
volatile U8  *downPt;
volatile U32 downloadFileSize;
volatile U16 checkSum;
volatile U32 err=0;
volatile U32 totalDmaCount;
volatile S32 isUsbdSetConfiguration;
int download_run=0;
U32 tempDownloadAddress;
int menuUsed=0;
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
int consoleNum;
/*   在全局变量之前,加上关键字static,全局变量就被定义成为一个全局静态变量。
1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)
2)初始化:未经初始化的全局静态变量会被程序自动初始化为0
3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地将从定义之处开始到文件结尾
*/
static U32 cpu_freq;
static U32 UPLL;
/*在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
  函数的定义和声明默认情况下是extern的,但静态函数只是在声明它的文件当中可见,不能被其他文件使用。
*/
static void cal_cpu_bus_clk(void)
{
 U32 val;
 U8 m, p, s;
 
 val = rMPLLCON;
 m = (val>>12)&0xff;//m=92=MDIV
 p = (val>>4)&0x3f; //p=1=PDIV
 s = val&3;         //s=1=SDIV
/*按照手册上面的计算,Fout=2*m*Fin/(p*2s),其中Fin=12MHz。但m、p、s与上面的不一样。公式中m=MDIV+8,p=PDIV+2,s=SDIV
    (1<<s),将1左移S位。逻辑左移相当于乘以2的N次方。而逻辑右移,相当于除以2的N次方
     FIN、FCLK在option.h中定义,FIN=12000000,经计算FCLK=400MHz
 */
 //(m+8)*FIN*2 不要超出32位数!
 FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;
 
 val = rCLKDIVN;
 m = (val>>1)&3; // m=2=HDIVN,HCLK=FCLK/4
 p = val&1;     //p=1=PDIVN
 val = rCAMDIVN; //由于之前没有设置过CAMDIVN寄存器,所以是默认值s=0x0,其最后两位00,代表没移位之前的CAMDIVN[9:8]
 s = val>>8;
 
 switch (m) {
 case 0:
  HCLK = FCLK;   //当HDIV[2:1]=00,HCLK=FCLK/1
  break;
 case 1:
  HCLK = FCLK>>1; //当HDIV[2:1]=01,HCLK=FCLK/2
  break;
 case 2:
  if(s&2)
   HCLK = FCLK>>3; //当HDIV[2:1]=10,CAMDIVN[9]=1,则表示HCLK=FCLK/8
  else
   HCLK = FCLK>>2; //当HDIV[2:1]=10,CAMDIVN[9]=0,则表示HCLK=FCLK/4
  break;
 case 3:
  if(s&1)
   HCLK = FCLK/6; //当HDIV[2:1]=11,CAMDIVN[8]=1,则表示HCLK=FCLK/6
  else
   HCLK = FCLK/3; //当HDIV[2:1]=11,CAMDIVN[8]=0,则表示HCLK=FCLK/3
  break;
 }
 
 if(p)
  PCLK = HCLK>>1; //当PDIVN=1,PCLK=HCLK/2
 else
  PCLK = HCLK;  //当PDIVN=0,PCLK=HCLK/1
 
 if(s&0x10)     //CAMDIVN[12]=0,CPU频率等于HCLK频率
  cpu_freq = HCLK;
 else
  cpu_freq = FCLK; //CAMDIVN[12]=1,表示CPU频率等于FCLK频率
  
 val = rUPLLCON;  //UPLLCON在Main函数里没有设置,但在2440init里有设置
 m = (val>>12)&0xff; //m=56=MDIV
 p = (val>>4)&0x3f;  //p=2=PDIV
 s = val&3;//s=2=SDIV
 UPLL = ((m+8)*FIN)/((p+2)*(1<<s)); //UPLL的计算方法,同MPLL一样,经计算知,UPLL=48MHz
 UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL; //根据2440init里CLKVAL的值,CLKDIVN[3]=DIVN_UPLL=0,rCLKDIVN&8=0,所以UCLK=UPLL=48MHz
}
void Temp_function() { Uart_Printf("\nPlease input 1-16 to select test!!!\n"); }
struct {
 void (*fun)(void);   //声明一个结构体
 char  *tip;         //声明一个函数指针
}CmdTip[] = {           //结构体初始化
    { Temp_function, "Please input 1-16 to select test" } ,
    { BUZZER_PWM_Test, "Test PWM" } ,
    { RTC_Display, "RTC time display" } ,
    { Test_Adc, "Test ADC" } ,
    { KeyScan_Test, "Test interrupt and key scan" } ,
    { Test_Touchpanel, "Test Touchpanel" } ,
    { TFT_LCD_Test, "Test TFT-LCD or VGA1024x768 module" } ,
    { Test_Iic, "Test IIC EEPROM, if use QQ2440, please remove the LCD" } ,
    { PlayMusicTest, "UDA1341 play music" } ,
    { Test_SDI, "Test SD Card" } ,
    { Camera_Test, "Test CMOS Camera"},
    { 0, 0}      
   };
void Main(void)
{
 char *mode;
 int i;
 U8 key;
 U32 mpll_val = 0 ;
 //U32 divn_upll = 0 ;
//#if如果给定条件为真,则编译下面代码,直到出现#else、#elif或#endif为止;否则就不编译。ADS10在option.h定义,ADS10=1,这段没有任何作用    
 #if ADS10   
// __rt_lib_init(); //for ADS 1.0
 #endif
//端口初始化,设置GPA/B/C/D/E/F/G/H/J相应的管脚,EXTINT0/1/2/3  
 Port_Init();
//设置中断服务程序,初始化。把所有中断设置为IRQ模式,屏蔽所有中断请求 
 Isr_Init();
 
 i = 2 ; //don't use 100M!
  //boot_params.cpu_clk.val = 3;
 switch ( i ) {
 case 0: //200
  key = 12;
  mpll_val = (92<<12)|(4<<4)|(1);
  break;
 case 1: //300
  key = 13;
  mpll_val = (67<<12)|(1<<4)|(1);
  break;
 case 2: //400
 //设置时钟分频比的值,FCLK:HCLK:PCLK
  key = 14;
 //设置FCLK的值,MDIV=92,PDIV=1,SDIV=1
  mpll_val = (92<<12)|(1<<4)|(1);
  break;
 case 3: //440!!!
  key = 14;
  mpll_val = (102<<12)|(1<<4)|(1);
  break;
 default:
  key = 14;
  mpll_val = (92<<12)|(1<<4)|(1);
  break;
 }
 
 //init FCLK=400M, so change MPLL first
 ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
 ChangeClockDivider(key, 12);
 cal_cpu_bus_clk();
//串口设置:串口选择,串口波特率设置; 
 consoleNum = 0; // Uart 1 select for debug.
 Uart_Init( 0,115200 );
 Uart_Select( consoleNum );
 
 Beep(2000, 100);
 
 Uart_SendByte('\n');
 Uart_Printf("<***********************************************>\n");
 Uart_Printf("           SBC2440 Test Program VER1.0\n");
 Uart_Printf("                www.arm9.net\n");
 Uart_Printf("      Build time is: %s  %s\n", __DATE__ , __TIME__  );
    Uart_Printf( "          Image$$RO$$Base  = 0x%x\n", Image$$RO$$Base );
 Uart_Printf( "          Image$$RO$$Limit = 0x%x\n", Image$$RO$$Limit );
 Uart_Printf( "          Image$$RW$$Base  = 0x%x\n", Image$$RW$$Base );
 Uart_Printf( "          Image$$RW$$Limit = 0x%x\n", Image$$RW$$Limit );
    Uart_Printf( "          Image$$ZI$$Base  = 0x%x\n", Image$$ZI$$Base );
    Uart_Printf( "          Image$$ZI$$Limit = 0x%x\n", Image$$ZI$$Limit );
 Uart_Printf("<***********************************************>\n");
//不同种类的控制寄存器设置,这里主要是选择USB端口
 rMISCCR=rMISCCR&~(1<<3);  // 选择USB device,而不是USB host
 rMISCCR=rMISCCR&~(1<<13); // 设置Port1有效
//
//  USBD should be initialized first of all.
//
// isUsbdSetConfiguration=0;
 
// rd_dm9000_id();   //
// rGPBCON &= ~(3<<20); //CF_CARD Power
// rGPBCON |= 1<<20;
// rGPBDAT |= 1<<10;
// rDSC0 = 0x155;
// rDSC1 = 0x15555555;
//设置输出管脚驱动电流
 rDSC0 = 0x2aa;
 rDSC1 = 0x2aaaaaaa;
 //Enable NAND, USBD, PWM TImer, UART0,1 and GPIO clock,
 //the others must be enabled in OS!!!
//设置时钟控制寄存器,选择各个外部接口的时钟源
 rCLKCON = 0xfffff0;
 
 //MMU_EnableICache();
  MMU_Init(); //内存存储管理。裸奔暂时用不上
  //Uart_Printf("NOR Flash ID is 0x%08x\n", GetFlashID());
 pISR_SWI=(_ISR_STARTADDRESS+0xf0); //for pSOS
 // GPB5=nLED1,GPB6=nLED2,GPB7=nLED3,GPB8=nLED4
    //LED2、3亮
 Led_Display(0x66);
#if USBDMA
 mode="DMA";
#else
 mode="Int";
#endif
 // CLKOUT0/1 select.
 //Uart_Printf("CLKOUT0:MPLL in, CLKOUT1:RTC clock.\n");
 //Clk0_Enable(0); // 0:MPLLin,  1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
 //Clk1_Enable(2); // 0:MPLLout, 1:UPLL, 2:RTC,  3:HCLK, 4:PCLK, 5:DCLK1 
 Clk0_Disable();
 Clk1_Disable();
//回读PLL控制寄存器的值到变量中;
 mpll_val = rMPLLCON;
 
 TFT_LCD_Init();
// TFT_LCD_Init();
  
 download_run=1; //The default menu is the Download & Run mode.
 while(1)
 {
  U8 idx;
  
  Uart_Printf("\nPlease select function : \n"); 
  for(i=0; CmdTip[i].fun!=0; i++)
   Uart_Printf("%d : %s\n", i, CmdTip[i].tip);
  idx = Uart_GetIntNum_GJ() ; //函数功能将串口接收到的字符串根据形式(进制)转换为int数据返回
  if(idx<i)
  {
   (*CmdTip[idx].fun)();  //调用相应的功能函数
   Delay(20);
   Uart_Init( 0,115200 );
  } 
 
 }    
}
void Isr_Init(void)
{
 pISR_UNDEF=(unsigned)HaltUndef; 
 pISR_SWI  =(unsigned)HaltSwi;
 pISR_PABORT=(unsigned)HaltPabort;
 pISR_DABORT=(unsigned)HaltDabort;
 rINTMOD=0x0;       // All=IRQ mode
 rINTMSK=BIT_ALLMSK;   // All interrupt is masked.
 //pISR_URXD0=(unsigned)Uart0_RxInt; 
 //rINTMSK=~(BIT_URXD0);   //enable UART0 RX Default value=0xffffffff
//#if 1
// pISR_USBD =(unsigned)IsrUsbd;
// pISR_DMA2 =(unsigned)IsrDma2;
//#else
// pISR_IRQ =(unsigned)IsrUsbd; 
  //Why doesn't it receive the big file if use this. (???)
  //It always stops when 327680 bytes are received.
//#endif 
// ClearPending(BIT_DMA2);
// ClearPending(BIT_USBD);
 //rINTMSK&=~(BIT_USBD);  
   
 //pISR_FIQ,pISR_IRQ must be initialized
}
void HaltUndef(void)
{
 Uart_Printf("Undefined instruction exception!!!\n");
 while(1);
}
void HaltSwi(void)
{
 Uart_Printf("SWI exception!!!\n");
 while(1);
}
void HaltPabort(void)
{
 Uart_Printf("Pabort exception!!!\n");
 while(1);
}
void HaltDabort(void)
{
 Uart_Printf("Dabort exception!!!\n");
 while(1);
}
void ClearMemory(void)
{
 //int i;
 //U32 data;
 int memError=0;
 U32 *pt; //设定一个指针变量pt,用来存储内存的每一个存储单元的地址,因为本系统构建了32位的数据总线,因此pt的类型为无符号整形unsigned int。
 
 Uart_Printf("Clear Memory (%xh-%xh):WR",_RAM_STARTADDRESS,HEAPEND); //输出log,信息为存储测试开始,首先进行men写操作,输出操作范围为地址0x30000000h到0x33ff0000h
 pt=(U32 *)_RAM_STARTADDRESS; //开始,首先将起始地址赋给指针变量pt,指针指向测试的起始地址0x30000000
 while((U32)pt < HEAPEND)     //定义一个循环语句,循环结束的条件是pt>0x33ff0000
 {
  *pt=(U32)0x0; //清除内存开始
  pt++;         //pt指向下一个存储单元格
 }
 
 if(memError==0)Uart_Printf("\b\bO.K.\n"); //条件比较中看标志变量memError是否为假,如果为假即无错误发生,检测结束,输出"O.K.",程序结束。
}
void Clk0_Enable(int clock_sel) 
{ // 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
 rMISCCR = rMISCCR&~(7<<4) | (clock_sel<<4);
 rGPHCON = rGPHCON&~(3<<18) | (2<<18);
}
void Clk1_Enable(int clock_sel)
{ // 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1 
 rMISCCR = rMISCCR&~(7<<8) | (clock_sel<<8);
 rGPHCON = rGPHCON&~(3<<20) | (2<<20);
}
void Clk0_Disable(void)
{
 rGPHCON = rGPHCON&~(3<<18); // GPH9 Input
}
void Clk1_Disable(void)
{
 rGPHCON = rGPHCON&~(3<<20); // GPH10 Input
}

在我们搭建好2440的硬件平台后,我们在调试硬件的时候,通常需要将系统的时钟测试引脚引出来测试,以确认系统是否达到设计的要求。2440提供了CLKOUT0和CLKOUT1这两个引脚用于测试时钟。可以通过设置MISCCR寄存器的CLKSEL0和CLKSEL1位来选择CLKOUT0和CLKOUT1的时钟源。其时钟源分别有000=MPLL输出,001为UPLL输出,010为RTC输出,011为HCLK,100为PCLK,101为DCLK1/0,11X为保留的。

S3C2440 裸机程序之音频的更多相关文章

  1. 基于KEIL4开发ARM9(S3C2440)的裸机程序

    本文主要介绍如何使用Keil4开发ARM9(S3C2440)裸机程序. 说明: 一.平台: 操作系统:Windows XP系统 KEIL版本:4.73 开发板:ARM9(S3C2440) 二.建立工程 ...

  2. s3c2440 lcd 显示图片裸机程序

    因为前面的裸机程序非常的简单,就不写博了. 程序的流程: 1,初始化C SP 2,关看门狗 3,初始化SDRAM 4,读出 NAND FLASH 中的 包含图片的程式放到SDRAM里面 5,跳转到SD ...

  3. 【转载】s3c2440裸机开发调试环境(MDK4.6,Jlink v8,mini2440)

    用于arm裸机程序开发的IDE基本有 以下3个:MDK,IAR,还有ADS.具体它们的具体情况在这里我就不多说了,百度一下就明白了.由于之前开发c51,stm32时候都使用了MDK开发环境,而且MDK ...

  4. JZ2440学习笔记之第一个裸机程序(Keil-MDK)

    CPU:S3C2440, ARM920T, Internal 4KB RAM, Support boot from NAND flash, 128MB for each bank. JZ2440:Me ...

  5. linux上使用J-Link调试S3C2440裸机代码

    linux上使用J-Link调试S3C2440裸机代码 工具: segger的jlink仿真器 segger的jlink for linux 交叉编译工具链里面的arm-xx-linux-xx-gdb ...

  6. JZ2440学习笔记之通过J-Link单步裸机程序(Keil+J-Link)

    我们还是使用JZ2440学习笔记之第一个裸机程序(Keil-MDK)里面的程序,但是把延时拿掉,要不然单步的时候一直在delay里面: int main(void) { // Set GPF4/5/6 ...

  7. ubuntu15.10跑裸机程序跑.bin文件

    1:安装tftp:#apt-get update#apt-get install tftp-hpa tftpd-hpa xinetd2:#cd /srv#mkdir tftp#chmod 777 tf ...

  8. EB-SAM9G45裸机程序下载方法

    开发板:EB-SAM9G45 这里提供一种裸程序下载的方法. 在官方提供的下载方法中有手动下载和自动下载,它们都离不开SAM-BA软件,而该软件使用比较麻烦,而且操作不当很容易导致电脑蓝屏,还有一个很 ...

  9. ARM入门实践(一)----Mini6410上最简单的LED点灯裸机程序

    Mini6410上最简单的LED点灯裸机程序 : 实验环境: 根据友善教程,要用ADS,据说现在都不用这个了,但是为了打开友善给的mcp工程,就下了一个,Win7下弄上兼容模式和管理员权限,再下一个S ...

随机推荐

  1. NOI模拟 热身赛T1

    设p(m)的值为m的正因数个数(包括1和m本身)给定n,求满足p(x)=n的最小x. 简直弱到不行了... VW做法: 其实蛮简单的,然而想的时候忽略了指数是不增的 然后你以为做完了吗? 愚蠢的贡献了 ...

  2. Invalid escape sequence(valid ones are \b \t \n \f \r \" \' \\)

    Invalid escape sequence(valid ones are \b \t \n \f \r \" \' \\) 在运行eclipse的相关程序代码时遇到了报错信息,查看控制台 ...

  3. GO语言练习:网络编程 ICMP 示例

    1.代码 2.编译及运行 1.Go语言网络编程:ICMP示例代码 icmptest.go package main import ( "fmt" "net" & ...

  4. 素数环 Primg Ring Problem

    素数环 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=84562#problem/C 题意: 输入正整数n,把整数1~n组成一个 ...

  5. [CareerCup] 15.7 Student Grade 学生成绩

    15.7 Imagine a simple database storing information for students' grades. Design what this database m ...

  6. 【hihoCoder】1041. 国庆出游

    问题:详见http://hihocoder.com/problemset/problem/1041 有n个城市,城市编号为1-n,城市间有n-1条路(所以,城市路网是一棵树).给定一个序列S,要求判断 ...

  7. [转] - MC、MC、MCMC简述

    贝叶斯集锦(3):从MC.MC到MCMC 2013-07-31 23:03:39 #####一份草稿 贝叶斯计算基础 一.从MC.MC到MCMC 斯坦福统计学教授Persi Diaconis是一位传奇 ...

  8. Git基本命令行操作

    A. 新建Git仓库,创建新文件夹git init  B. 添加文件到git索引git add <filename>  --- 单个文件添加git add * --- 全部文件添加 C. ...

  9. Quartz.net 的简单使用,创建定时任务

    ISchedulerFactory sf = new StdSchedulerFactory(); sched = sf.GetScheduler(); JobDetail job = new Job ...

  10. Another app is currently holding the yum lock; waiting for it to exit...

    刚安装完虚拟机,用xshell连接上linux后,安装程序时一直出现这个信息Another app is currently holding the yum lock; waiting for it ...