您好,欢迎来到61ic! | [登录] [注册] 忘记密码 | 设为首页 帮助
 . 网站首页 . 业界新闻 . 设计中心 . 移动技术 . TI专栏 . ADI专栏 . FPGA专栏 . 代码工厂 . 官方商城 . 
 . 活动专区 . 新品快递 . 解决方案 . 前沿科技 . TI资源 . ADI资源 . FPGA资源 . 下载中心 . 产品展示 . 
加入收藏
付款方式
联系我们
您现在的位置: 61IC电子在线 >> TI专栏 >> TI DaVinci >> TMS320DM81x SOC >> 正文
  DM8168裸机调试-GPMC+FPGA           ★★★ 【字体:
DM8168裸机调试-GPMC+FPGA
作者:swat    文章来源:swat    点击数:    更新时间:2014-9-25    

前言
GPMC产生背景(个人理解):当调试nor flash、nand flash、FPGA、网卡等外部扩展设备时,需要CPU给这些设备 分配地址空间、提供访问时序、访问接口等控制。Cotex-A8将这些外扩设备的控制集成在GPMC模块内。对于用户只需要配置GPMC模块,既可以访问该设备。

GPMC工作机制:若访问物理地址落在GPMC的0x00 - 0x1FFF FFFF的512MB地址范围内,则将物理地址信息Address 进行解码。
  这里的解码主要是对物理地址Address  同掩码地址做逻辑与&操作,若运算结果,同基地址一致,则使能cs片选信号,同时可以访问该区间;反之无CS片选且无法访问该区间。

                                

配置GPMC模块核心(以FPGA为例说明):

                          1、配置设备类型                           GPMC_CONFIG1

                          2、配置访问时序,主要读写时序  GPMC_CONFIG2-6

                          3、配置基地址、容量(即掩码地址)、使能CS信号 GPMC_CONFIG7

注:FPGA属于nor flash类型,对于nand flash配置稍微复杂些(目前未调试,后期会调试,进一步完善)。

一、硬件原理图
DM8168同FPGA(X3SC250)硬件连接图:

                                

                                                                                          总框图

FPGA实现功能:扩展6路串口。

接线定义:

                                FPGA                                     Cortex-A8

             时钟信号:由24M晶振提供

             数据总线:A[0-7]、A[8]                            GPMC_A[0-7]、GPMC_A[27]

             地址总线:D[0-8]                                     GPMC_D[0-8]

             控制信号:WRn                                       GPMC_WEn

                               RDn                                        GPMC_OE_REn

                               CSn                                        GPMC_CS[ 3 ]n

                               ALE                                        GPMC_ADV_ALE                    FPGA的该引脚保留  未使用

                               IRQ0                                       GP1[9]                                     中断引脚(有中断触发,该引脚置高)

                               IRQ1                                       GP113]                                    FPGA的该引脚保留  未使用             

                               IRQ2                                       GP1[25]                                   FPGA的该引脚保留  未使用

           UART输出:EUART0 - 5

            电源:3.3V  2.5V  1.2V

注:

1、时钟源:GPMC模块使用MainPLL_CLOCK4产生500MHz经过4分频后SYSCLK6,即125MHz 输出 .所以GPMC_FCLK=125 MHz(T=8 ns)

2、电源域:由PRCM模块ALWAY_ON域供电,始终接通供电。

二、程序
第一是GPMC的片选寻址机制,第二是GPMC的访问外扩设备。

2.1、GPMC初始化
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
void GPMC_Init( void ) 

 
    /*第一步: enable gpmc  CLOCK*/ 
    WR_MEM_32(CM_ALWON_L3_SLOW_CLKSTCTRL, 0x2); // Enable the Power Domain Transition of L3 Slow Domain Peripheral 
    while((RD_MEM_32(CM_ALWON_L3_SLOW_CLKSTCTRL) & 0x2) !=0x2); 
 
    WR_MEM_32(CM_ALWON_GPMC_CLKCTRL , 0x2); // Enable GPMC CLOCK 
    while((RD_MEM_32(CM_ALWON_GPMC_CLKCTRL ) & 0x3) !=0x2); 
 
    /*第二步:enable PAD_ConfigMux */ 
    PAD_ConfigMux(PAD_FPGA_lineOffsets,PAD_FPGA_linedata); 
 
    /*第三步:Reset GPMC*/ 
    GPMC_Write(GPMC_SYSCONFIG,0x0a); 
    while(GPMC_Read(GPMC_SYSSTATUS) != 0x01);//等待复位完成 
 
    /*第四步:set GPMC_CONFIG */ 
    GPMC_SYSCONFIG      =   0x00; 
    GPMC_IRQENABLE      =   0x00; 
    GPMC_TIMEOUTCTRL    =   0x00; 
    GPMC_CONFIG         =   0x00; 
 
    GPMC_CONFIG1_3      =   0x00000010;//1、8位宽 类似nor flash器件 2、单次异步访问 3、地址/数据总线不复用 
    GPMC_CONFIG2_3      =   0x00070900;//1、CSWROFFtime =7*GPMC_FCLK  2、CSRDOFFtime =9*GPMC_FCLK 3、CSONtime =0 
    GPMC_CONFIG3_3      =   0x00000000;//该寄存器配置地址/数据总线时的参数,所有不需要配置  
    GPMC_CONFIG4_3      =   0x06010701;//1、WEOFFtime =6*GPMC_FCLK 2、WEONtime =1*GPMC_FCLK  
                                       //3、OEOFFtime =7*GPMC_FCLK 4、OEONtime =1*GPMC_FCLK 
     
    GPMC_CONFIG5_3      =   0x0009070C;//1、RDACCESStime =9*GPMC_FCLK 2、WRCYCLEtime =7*GPMC_FCLK  
                                       //3、RDCYCLEtime =11*GPMC_FCLK 
    GPMC_CONFIG6_3      =   0x08000000;//1、WRACCESStime =8*GPMC_FCLK 
    GPMC_CONFIG7_3      =   0x00000F42;//基地址=0x200 0000 ,容量=16 MB 
 
    printf("GPMC_SYSCONFIG = %02x   [%08X]\n",&GPMC_SYSCONFIG,GPMC_SYSCONFIG); 
    printf("GPMC_IRQENABLE = %02x   [%08X]\n",&GPMC_IRQENABLE,GPMC_IRQENABLE); 
    printf("GPMC_TIMEOUTCTRL = %02x [%08X]\n",&GPMC_TIMEOUTCTRL,GPMC_TIMEOUTCTRL); 
    printf("GPMC_CONFIG = %02x      [%08X]\n",&GPMC_CONFIG,GPMC_CONFIG); 
 
    printf("GPMC_CONFIG1_3 = %02x   [%08X]\n",&GPMC_CONFIG1_3,GPMC_CONFIG1_3); 
    printf("GPMC_CONFIG2_3 = %02x   [%08X]\n",&GPMC_CONFIG2_3,GPMC_CONFIG2_3); 
    printf("GPMC_CONFIG3_3 = %02x   [%08X]\n",&GPMC_CONFIG3_3,GPMC_CONFIG3_3); 
    printf("GPMC_CONFIG4_3 = %02x   [%08X]\n",&GPMC_CONFIG4_3,GPMC_CONFIG4_3); 
    printf("GPMC_CONFIG5_3 = %02x   [%08X]\n",&GPMC_CONFIG5_3,GPMC_CONFIG5_3); 
    printf("GPMC_CONFIG6_3 = %02x   [%08X]\n",&GPMC_CONFIG6_3,GPMC_CONFIG6_3); 
    printf("GPMC_CONFIG7_3 = %02x   [%08X]\n",&GPMC_CONFIG7_3,GPMC_CONFIG7_3); 
    EVM816X_waitmsec(2); 

void GPMC_Init( void )
{

 /*第一步: enable gpmc  CLOCK*/
 WR_MEM_32(CM_ALWON_L3_SLOW_CLKSTCTRL, 0x2); // Enable the Power Domain Transition of L3 Slow Domain Peripheral
 while((RD_MEM_32(CM_ALWON_L3_SLOW_CLKSTCTRL) & 0x2) !=0x2);

 WR_MEM_32(CM_ALWON_GPMC_CLKCTRL , 0x2); // Enable GPMC CLOCK
 while((RD_MEM_32(CM_ALWON_GPMC_CLKCTRL ) & 0x3) !=0x2);

 /*第二步:enable PAD_ConfigMux */
 PAD_ConfigMux(PAD_FPGA_lineOffsets,PAD_FPGA_linedata);

    /*第三步:Reset GPMC*/
 GPMC_Write(GPMC_SYSCONFIG,0x0a);
    while(GPMC_Read(GPMC_SYSSTATUS) != 0x01);//等待复位完成

    /*第四步:set GPMC_CONFIG */
    GPMC_SYSCONFIG  = 0x00;
    GPMC_IRQENABLE  = 0x00;
    GPMC_TIMEOUTCTRL  = 0x00;
    GPMC_CONFIG   = 0x00;

    GPMC_CONFIG1_3  = 0x00000010;//1、8位宽 类似nor flash器件 2、单次异步访问 3、地址/数据总线不复用
    GPMC_CONFIG2_3  = 0x00070900;//1、CSWROFFtime =7*GPMC_FCLK  2、CSRDOFFtime =9*GPMC_FCLK 3、CSONtime =0
    GPMC_CONFIG3_3  = 0x00000000;//该寄存器配置地址/数据总线时的参数,所有不需要配置
    GPMC_CONFIG4_3  = 0x06010701;//1、WEOFFtime =6*GPMC_FCLK 2、WEONtime =1*GPMC_FCLK
            //3、OEOFFtime =7*GPMC_FCLK 4、OEONtime =1*GPMC_FCLK
 
    GPMC_CONFIG5_3  = 0x0009070C;//1、RDACCESStime =9*GPMC_FCLK 2、WRCYCLEtime =7*GPMC_FCLK
            //3、RDCYCLEtime =11*GPMC_FCLK
    GPMC_CONFIG6_3  = 0x08000000;//1、WRACCESStime =8*GPMC_FCLK
    GPMC_CONFIG7_3  = 0x00000F42;//基地址=0x200 0000 ,容量=16 MB

    printf("GPMC_SYSCONFIG = %02x   [%08X]\n",&GPMC_SYSCONFIG,GPMC_SYSCONFIG);
    printf("GPMC_IRQENABLE = %02x   [%08X]\n",&GPMC_IRQENABLE,GPMC_IRQENABLE);
    printf("GPMC_TIMEOUTCTRL = %02x [%08X]\n",&GPMC_TIMEOUTCTRL,GPMC_TIMEOUTCTRL);
    printf("GPMC_CONFIG = %02x    [%08X]\n",&GPMC_CONFIG,GPMC_CONFIG);

    printf("GPMC_CONFIG1_3 = %02x   [%08X]\n",&GPMC_CONFIG1_3,GPMC_CONFIG1_3);
    printf("GPMC_CONFIG2_3 = %02x   [%08X]\n",&GPMC_CONFIG2_3,GPMC_CONFIG2_3);
    printf("GPMC_CONFIG3_3 = %02x   [%08X]\n",&GPMC_CONFIG3_3,GPMC_CONFIG3_3);
    printf("GPMC_CONFIG4_3 = %02x   [%08X]\n",&GPMC_CONFIG4_3,GPMC_CONFIG4_3);
    printf("GPMC_CONFIG5_3 = %02x   [%08X]\n",&GPMC_CONFIG5_3,GPMC_CONFIG5_3);
    printf("GPMC_CONFIG6_3 = %02x   [%08X]\n",&GPMC_CONFIG6_3,GPMC_CONFIG6_3);
    printf("GPMC_CONFIG7_3 = %02x   [%08X]\n",&GPMC_CONFIG7_3,GPMC_CONFIG7_3);
    EVM816X_waitmsec(2);
}


2.2、FPGA操作
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
#include "fpga.h" 
#include "evm816x.h" 
#define deubg                0 
#define UARTn               UART0 
#define Baud_9600           1 
#define Baud_115200         0 
#define Baud_250000         0 
#define INT_EN              0 
Uint8 Fpga_read( Uint32 adress) 

    Uint8 data; 
    data = *(volatile Uint8 *) adress; 
    return data; 

 
void Fpga_wrtie( Uint32 adress,Uint8 data) 

    *(volatile Uint8 *) adress = data; 

 
void Fpag_init(void) 

/*第一步:读版本号*/ 
    printf("\nRVR0 = %02x,          [%02x] \n",(RVE +RVR0),Fpga_read(RVE +RVR0)); 
    printf("\nRVR1 = %02x,          [%02x] \n",(RVE +RVR1),Fpga_read(RVE +RVR1)); 
    printf("\nPNR0 = %02x,          [%02x] \n",(RVE +PNR0),Fpga_read(RVE +PNR0)); 
    printf("\nPNR1 = %02x,          [%02x] \n",(RVE +PNR1),Fpga_read(RVE +PNR1)); 
 
/*第二步:配置波特率 及 帧数据格式*/ 
     Fpga_wrtie(UARTn+LCR,0x80);//配置波特率寄存器时,LCR.DLAB必须置1。 
 
#if Baud_9600 
     Fpga_wrtie(UARTn+DLL,0x39);//波特率=9600,配置值=0x139 
     Fpga_wrtie(UARTn+DLM,0x01); 
#endif 
 
#if Baud_115200 
     Fpga_wrtie(UARTn+DLL,0x1A);//波特率=9600,配置值=0x139 
     Fpga_wrtie(UARTn+DLM,0x00); 
#endif 
 
#if Baud_250000 
     Fpga_wrtie(UARTn+DLL,0x0C);//波特率=250k,配置值=0xC 
     Fpga_wrtie(UARTn+DLM,0x00); 
#endif 
 
 
#if deubg 
     printf("\n UART0+IIR       = %02x, \n",Fpga_read(UARTn+DLL)); 
     printf("\n GOBAL_INT+IRR0  = %02x, \n",Fpga_read(UARTn+DLM)); 
#endif 
     Fpga_wrtie(UARTn+LCR,0x00);//无校验位     1位 停止位    8位数据长度 
 
#if INT_EN 
     /*第二步:使能相应中断*/ 
    Fpga_wrtie(GOBAL_INT+IMR0,0x01 ); 
    Fpga_wrtie(UARTn+IER,(IER_RBI | IER_THEI)); 
#endif 

/* Fpga_test() 功能:FPGA的uart模块的自发自收的程序*/ 
void Fpga_test(void) 

    Fpag_init(  ); 
    while(1) 
    { 
 
 
     Fpga_wrtie(UARTn+THR, 0xaa);//向发送缓冲区写入数据,开始发送 
     /* 判断是否1、发送器空    2、发送保持寄存器空  3、成功接收一个数据,如果同时满足,表示自发自收成功。*/ 
     while( (Fpga_read(UARTn+LSR) & (LSR_THRE | LSR_TEMT | LSR_DR)) != (LSR_THRE | LSR_TEMT | LSR_DR) ) // 
     { 
         Fpga_wrtie(UARTn+THR, 0xaa); 
         printf("\n UARTn+LSR       = %02x, \n",Fpga_read(UARTn+LSR ));//读取UART当前状态 
         EVM816X_waitmsec(1); 
     } 
     printf("\n UARTn+LSR       = %02x, \n",Fpga_read(UARTn+LSR ));//读取退出while时,UART当前状态 
     printf("\n UARTn+RBR       = %02x, \n",Fpga_read(UARTn+RBR));//读取接收缓冲区内容 
     EVM816X_waitmsec(5); 
 
  } 

#include "fpga.h"
#include "evm816x.h"
#define deubg                0
#define UARTn               UART0
#define Baud_9600   1
#define Baud_115200   0
#define Baud_250000   0
#define INT_EN    0
Uint8 Fpga_read( Uint32 adress)
{
 Uint8 data;
 data = *(volatile Uint8 *) adress;
 return data;
}

void Fpga_wrtie( Uint32 adress,Uint8 data)
{
 *(volatile Uint8 *) adress = data;
}

void Fpag_init(void)
{
/*第一步:读版本号*/
 printf("\nRVR0 = %02x,   [%02x] \n",(RVE +RVR0),Fpga_read(RVE +RVR0));
 printf("\nRVR1 = %02x,   [%02x] \n",(RVE +RVR1),Fpga_read(RVE +RVR1));
 printf("\nPNR0 = %02x,   [%02x] \n",(RVE +PNR0),Fpga_read(RVE +PNR0));
 printf("\nPNR1 = %02x,   [%02x] \n",(RVE +PNR1),Fpga_read(RVE +PNR1));

/*第二步:配置波特率 及 帧数据格式*/
  Fpga_wrtie(UARTn+LCR,0x80);//配置波特率寄存器时,LCR.DLAB必须置1。

#if Baud_9600
  Fpga_wrtie(UARTn+DLL,0x39);//波特率=9600,配置值=0x139
  Fpga_wrtie(UARTn+DLM,0x01);
#endif

#if Baud_115200
  Fpga_wrtie(UARTn+DLL,0x1A);//波特率=9600,配置值=0x139
  Fpga_wrtie(UARTn+DLM,0x00);
#endif

#if Baud_250000
  Fpga_wrtie(UARTn+DLL,0x0C);//波特率=250k,配置值=0xC
  Fpga_wrtie(UARTn+DLM,0x00);
#endif


#if deubg
  printf("\n UART0+IIR   = %02x, \n",Fpga_read(UARTn+DLL));
  printf("\n GOBAL_INT+IRR0  = %02x, \n",Fpga_read(UARTn+DLM));
#endif
  Fpga_wrtie(UARTn+LCR,0x00);//无校验位     1位 停止位    8位数据长度

#if INT_EN
  /*第二步:使能相应中断*/
  Fpga_wrtie(GOBAL_INT+IMR0,0x01 );
  Fpga_wrtie(UARTn+IER,(IER_RBI | IER_THEI));
#endif
}
/* Fpga_test() 功能:FPGA的uart模块的自发自收的程序*/
void Fpga_test(void)
{
 Fpag_init( );
 while(1)
 {


  Fpga_wrtie(UARTn+THR, 0xaa);//向发送缓冲区写入数据,开始发送
  /* 判断是否1、发送器空    2、发送保持寄存器空  3、成功接收一个数据,如果同时满足,表示自发自收成功。*/
  while( (Fpga_read(UARTn+LSR) & (LSR_THRE | LSR_TEMT | LSR_DR)) != (LSR_THRE | LSR_TEMT | LSR_DR) ) //
  {
   Fpga_wrtie(UARTn+THR, 0xaa);
   printf("\n UARTn+LSR   = %02x, \n",Fpga_read(UARTn+LSR ));//读取UART当前状态
   EVM816X_waitmsec(1);
  }
  printf("\n UARTn+LSR   = %02x, \n",Fpga_read(UARTn+LSR ));//读取退出while时,UART当前状态
  printf("\n UARTn+RBR   = %02x, \n",Fpga_read(UARTn+RBR));//读取接收缓冲区内容
  EVM816X_waitmsec(5);

  }
}
2.3 时序参数


三、已解决疑问点
3.1、基地址和掩码地址设置原则
      基地址可以任意设置吗?同掩码地址关系
     1、将CS3基地址设置0x00,掩码容量16 MB。片选地址范围:0x00000000 -  0x00FF FFFF

     结果:无法访问该片选范围。why?? 因为GPMC中CS0-3基地址最小为16MB,即是16MB的倍数。
     验证:将CS3基地址设置0x0200 0000,掩码容量16 MB。可以访问0x0200 0000 -  0x02FF FFFF的16MB区间。
     所以基地址不是任意设置。

具体设置方法:

GPMC_CONFIG7 [5:0]对应A29-24,如果BASEADDRESS设置0x200 0000,则GPMC_CONFIG7 [5:0]= 000010。

              

疑问:0x00000000 -  0x00FF FFFF的16MB区间,如何访问??
    
      2、 访问的物理地址 & 掩码地址(即容量)  = 基地址 ,如何实现?

     通过GPMC访问机制:若物理地址落在GPMC的0x00 - 0x1FFF FFFF的512MB地址范围内,则将物理地址信息Address 进行解码。
这里的解码主要是对物理地址Address  同掩码地址做逻辑与&操作,若运算结果,同基地址一致,则使能cs片选信号,同时可以访问该区间; 反之无CS片选且无法访问该区间。

   下面以CS3基地址设置0x0200 0000,掩码容量16 MB实例说明一下:对应CONFIG7_i配置值 

     基地址 BASEADDRESS =0x02  MASKADDRESS = 0xFF,可以访问区间16MB的0x0200 0000 -  0x02FF FFFF


   若读取0x0200 007E地址中内容(即data = *(volatile Uint8 *) adress);首先0x0200 007E属于GPMC地址区间,然后将
  0x0200 007E &0x0F00 0000(掩码地址) =0x0200 00000,该结果同设置基地址相等,则使能CS片选信号且可以访问0x0200 007E地址。


3.2、片选容量验证

  以CS3基地址设置0x0200 0000,掩码容量16 MB实例说明
   第一步:输出片选区域的前10个和 后10个地址中数据(即0x0200 0000 -0x0200 0009 和 0x02FF FFF6 -0x0x02FF FFFF),
   第二步:输出片选区域 末地址+1(即0x0x02FF FFFF + 1 =0x0300 0000)
 

结果:可以读取0x0200 0000 -0x0200 0009 和 0x02FF FFF6 -0x0x02FF FFFF中数据,而读取0x0300 0000中数据,出现程序跑飞或地址指针指向无效内存区。由此可以验证片选容量。
 


3.3设置CS3片选区域,有必要设置CS0-2片选区域(CS0-2片选区域默认256MB)吗?
  结论:如果不是使用CS0-2区域,没有必要设置(虽然CS0-2片选区域默认256MB,但是GPMC_CONFIG_7[6]默认禁止CS片选使能。不使能CS信号,片选区域无法访问 )。

3.4时序配置问题

四、待解答

文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    DM8168 各个模块的时钟源
    bmp图片文件的操作 旋转、翻…
    RDK_OSD代码走读
    DM8168集成图像算法hellowor…
    DM8168的dsp怎么调用库和arm…
    DM8168 DVRRDK-link开发讲解
    DM8168 DVRRDK开发总结
    osd-link移植的代码流程
    scd-link移植的代码流程
    YUV422与RGB互相转
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61 湘ICP备13001086号-2