当前位置: 首页 > news >正文

ADI的BF609双核DSP怎么做开发,我来说一说(二)DDR驱动测试

作者的话

ADI的双核DSP,第二颗是Blackfin系列的BF609,这颗DSP我用了很久,比较熟悉,且写过一些给新手的教程。

硬件准备

ADSP-BF609-CORE:ADI BF609开发板

产品链接:https://item.taobao.com/item.htm?id=39901289258

AD-HP530ICE仿真器:ADI DSP通用仿真器

产品链接:https://item.taobao.com/item.htm?id=753233120844

软件准备

CCES2.2.0

硬件环境的搭建

在这里插入图片描述

  1. 选中DDR程序,鼠标右键:

在这里插入图片描述

在这里插入图片描述

  1. 选择芯片型号为BF609,然后下一步:

在这里插入图片描述

  1. 选择emulator,下一步

在这里插入图片描述

  1. 选择ICE-1000(AD-HP530ICE仿真器采用的是ICE-1000的固件),完成

在这里插入图片描述

  1. 回到原界面,选择debug

在这里插入图片描述

  1. 跳出来一个对话框,选择yes

在这里插入图片描述

  1. 软件进行debug编译,这个时候会跳出这个对话框,选择YES。

在这里插入图片描述

  1. 完成编译

在这里插入图片描述

  1. 点击运行,开始跑DDR测试程序,console界面会陆续打印测试结果,说明DDR运行正常,完成程序测试,再中止程序(测试的主频+时钟组合很多,测完一个即可点中止)。

在这里插入图片描述

在这里插入图片描述

  1. 回到工程界面

在这里插入图片描述

核心代码分析

/********************************************************
*

  • OpenADSP开源社区
  • http://www.openadsp.com
  • 【OpenADSP开源社区】
  • http://www.openadsp.cn

********************************************************/
#include <cdefBF609.h>
#include <defBF609.h>
#include <ccblkfn.h>
#include “post_debug.h”
#include “cgu_init.h”
#include “ddr_init.h”
#include <math.h>

#define DLL_LOCK_PERIOD 4500
#define NUM_FREQS 7

/* DDR2 range */
#define DDR2_START_ADDRESS 0x0
#define DDR2_END_ADDRESS 0x8000000
#define BUFFER_SIZE 0x400

#define N BUFFER_SIZE
#define MEM_SIZE_32 0x200 /* 4 byte xfer /
#define INT_XCNT_0 0x100000 /
interrupt on x count going to 0 */

int freq[NUM_FREQS] = { 250, 225, 200, 166, 150, 133, 125 };
int nFailureCnt = 0;

int DDR2_Src_Buffer[N];
int DDR2_Dest_Buffer[N];
int nCurrent_DDR_Addr = DDR2_START_ADDRESS;

char * pattern_comments[] =
{
"DDR pattern random ",
"DDR pattern incrementing ",
"DDR pattern all 0’s ",
"DDR pattern all 5’s ",
"DDR pattern all A’s ",
"DDR pattern all F’s ",
};

enum /* data pattern */
{
RANDOM,
INCREMENTING,
ALL_0S,
ALL_5S,
ALL_AS,
ALL_FS,
};

static int nTest = RANDOM;

/* DDR2 timing parameters after calculation */
unsigned int uiCL=0, uiRCD=0, uiRP=0,uiRC=0, uiRRD=0, uiRAS=0, uiRFC=0, uiFAW=0, uiRTP=0, uiWR=0, uiWTR=0, uiREFVAL =0;

/* Local Function Declarations */
void DDR2_Config(unsigned int uiDDRCfg, unsigned int uiDDRTr0, unsigned int uiDDRTr1, unsigned int uiDDRTr2, unsigned int uiDDRMr, unsigned int uiDDREmr1, unsigned int uiDDRCtl);
void Change_CGU(void);

/* Calculate DDR2 timing parameters based on DCLK */
int Calc_Params( float uiDDR2Val, float fDCLKns);

/*

  • Function name: DDR2_Init

  • Description: This function initializes the DDR2 based on CGU initialization.

  • Obtains the MSEL/CLKIN/DF values and calculates DCLK. Based on DCLK calculates

  • timing parameters

  • Arguments: None

  • Return value: None.
    */
    void DDR2_Init(void)
    {
    int i=0,Dll_cycles;
    int DFval=0, DSELval = 0, MSELval=0, CSELval = 0;

    /* Check for DMA IDLE */
    while(!(*pREG_DMC0_STAT & BITM_DMC_STAT_IDLE))
    NOP;

    /* put the part into self refresh only if already initialized */
    if((*pREG_DMC0_STAT & BITM_DMC_STAT_MEMINITDONE)&&(pREG_DMC0_STAT & BITP_DMC_STAT_DLLCALDONE))
    {
    /
    Enable self Refresh */
    *pREG_DMC0_CTL |= BITM_DMC_CTL_SRREQ;

    /* wait for SRACK to get set */
    while(!(*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK))NOP;
    

    }
    /* CGU init */
    Change_CGU();

    /* calculate the DLL wait cycles */
    DSELval = (*pREG_CGU0_DIV & BITM_CGU_DIV_DSEL) >> BITP_CGU_DIV_DSEL;
    CSELval = (*pREG_CGU0_DIV & BITM_CGU_DIV_CSEL) >> BITP_CGU_DIV_CSEL;
    Dll_cycles =DLL_LOCK_PERIOD * DSELval/CSELval;

    /* DLL Lock */
    for (i=0; i<Dll_cycles; i++)
    NOP;

    /* Get the DDR2 out of self refresh only if already initialized */
    if((*pREG_DMC0_STAT & BITM_DMC_STAT_MEMINITDONE)&&(pREG_DMC0_STAT & BITP_DMC_STAT_DLLCALDONE))
    {
    /
    Disable self refresh */
    *pREG_DMC0_CTL ^=BITM_DMC_CTL_SRREQ;

    /* Wait for SRACK to clear */
    while((*pREG_DMC0_STAT & BITM_DMC_STAT_SRACK))NOP;
    

    }

    /* Get CGU information - needs CLKIN, DSEL, DF, MSEL */
    DFval = (*pREG_CGU0_CTL & BITM_CGU_CTL_DF) >> BITP_CGU_CTL_DF;
    MSELval = (*pREG_CGU0_CTL & BITM_CGU_CTL_MSEL) >> BITP_CGU_CTL_MSEL;

    /* Calculate DCLK */
    float fDCLKMHz = 0, fDCLKns =0;
    fDCLKMHz = ((CLKINMHz * MSELval)/(DFval+1))/(DSELval);
    fDCLKns = 1000/fDCLKMHz;

    /* Calculate parameters */
    if (fDCLKMHz >= 200 )
    uiCL = 4;
    else
    uiCL = 3;

    uiRCD = Calc_Params(DDR2_RCD,fDCLKns);
    uiRP = Calc_Params(DDR2_RP,fDCLKns);
    uiRC = Calc_Params(DDR2_RC,fDCLKns);
    uiRRD = Calc_Params(DDR2_RRD,fDCLKns);
    uiRAS = Calc_Params(DDR2_RAS,fDCLKns);
    uiRFC = Calc_Params(DDR2_RFC,fDCLKns);
    uiFAW = Calc_Params(DDR2_FAW,fDCLKns);
    uiWR = Calc_Params(DDR2_WR,fDCLKns);
    uiWTR = Calc_Params(DDR2_WTR,fDCLKns);
    uiREFVAL = fDCLKMHz *DDR2_TREFIus;

    DDR2_Config(DDR0_CFG, DDR0_TR0, DDR0_TR1,DDR0_TR2, DDR0_MR, DDR0_EMR1,DDR0_CTL);

}

void DDR2_Config(unsigned int uiDDRCfg, unsigned int uiDDRTr0, unsigned int uiDDRTr1, unsigned int uiDDRTr2, unsigned int uiDDRMr, unsigned int uiDDREmr1, unsigned int uiDDRCtl)
{
int i=0;
int dllDataCycle;

/* Configure DDR2 registers */
*pREG_DMC0_CFG = uiDDRCfg;
*pREG_DMC0_TR0 = uiDDRTr0;
*pREG_DMC0_TR1 = uiDDRTr1;
*pREG_DMC0_TR2=  uiDDRTr2;
*pREG_DMC0_MR=   uiDDRMr;
*pREG_DMC0_PHY_CTL3 = BITM_DMC_PHY_CTL3_ENODTDQ|BITM_DMC_PHY_CTL3_TMG0|BITM_DMC_PHY_CTL3_TMG1|BITM_DMC_PHY_CTL3_OFST0|BITM_DMC_PHY_CTL3_OFST1;
*pREG_DMC0_PHY_CTL1 =ENUM_DMC_PHY_CTL1_ODT_75;
*pREG_DMC0_CTL=  uiDDRCtl;/* Wait for initialization to complete */
while(!(*pREG_DMC0_STAT & BITM_DMC_STAT_MEMINITDONE))NOP;/* Wait for calibration to complete */
while(!(*pREG_DMC0_STAT & BITP_DMC_STAT_DLLCALDONE))NOP;/* keep the DLLCALRDCNT reset value and only modify DATACYC */
*pREG_DMC0_DLLCTL= 0x54B;

}

/*

  • Function name: CalcParams

  • Description: This function calculates DDR2 timing parameters based on DCLK

  • Arguments: None

  • Return value: Returns the calculated parameter value
    */
    int Calc_Params( float uiDDR2Val, float fDCLKns)
    {
    int uiParamVal=0;
    float fParamVal = 0.0;

    fParamVal =uiDDR2Val/fDCLKns;
    uiParamVal = ceil(fParamVal);

    return uiParamVal;
    }

void Change_CGU(void)
{
static int nFreqIndex = 0;

if( nFreqIndex > (NUM_FREQS - 1) )nFreqIndex = 0;switch(nFreqIndex)
{case 0:CGU_Init(20, 1, 2);				/* CCLK=500Mhz, 250Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 500, freq[nFreqIndex]);break;case 1:CGU_Init(18, 1, 2);				/* CCLK=450Mhz, 225Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 450, freq[nFreqIndex]);break;case 2:CGU_Init(16, 1, 2);				/* CCLK=400Mhz, 200Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 400, freq[nFreqIndex]);break;case 3:CGU_Init(20, 1, 3);				/* CCLK=500Mhz, 166Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 500, freq[nFreqIndex]);break;case 4:CGU_Init(18, 1, 3);				/* CCLK=450Mhz, 150Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 450, freq[nFreqIndex]);break;case 5:CGU_Init(16, 1, 3);				/* CCLK=400Mhz, 133Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 400, freq[nFreqIndex]);break;case 6:CGU_Init(20, 1, 4);				/* CCLK=500Mhz, 125Mhz DDR2 CLK */DEBUG_PRINT("Using %d MHz CCLK, %d DDR CLK...\n", 500, freq[nFreqIndex]);break;
}nFreqIndex++;

}

void FillSrcBuffer(int nDataPattern)
{
int nIndex = 0;

/* fill our out_buf with some data */
for(nIndex = 0; nIndex < N; nIndex++ )
{switch (nDataPattern){case ALL_0S:DDR2_Src_Buffer[nIndex] = 0x00000000;break;case ALL_5S:DDR2_Src_Buffer[nIndex] = 0x55555555;break;case ALL_AS:DDR2_Src_Buffer[nIndex] = 0xaaaaaaaa;break;case ALL_FS:DDR2_Src_Buffer[nIndex] = 0xffffffff;break;case INCREMENTING:DDR2_Src_Buffer[nIndex] = nIndex;break;case RANDOM:DDR2_Src_Buffer[nIndex] = rand();break;}
}

}

void WriteDDR(void)
{
int nIndex = 0;
unsigned int pDest = (unsigned int)nCurrent_DDR_Addr;

for(nIndex = 0; nIndex < N; nIndex++ )
{*pDest = DDR2_Src_Buffer[nIndex];pDest++;
}

}

void ReadDDR(void)
{
int nIndex = 0;
unsigned int pDest = (unsigned int)nCurrent_DDR_Addr;

for(nIndex = 0; nIndex < N; nIndex++ )
{DDR2_Dest_Buffer[nIndex] = *pDest;pDest++;
}

}

bool CompareDDR(void)
{
int nIndex = 0;
unsigned int pDest = (unsigned int)nCurrent_DDR_Addr;
bool bSuccess = true;

for(nIndex = 0; nIndex < N; nIndex++ )
{if( DDR2_Src_Buffer[nIndex] != DDR2_Dest_Buffer[nIndex] ){bSuccess = false;break;}pDest++;
}return bSuccess;

}

int main( void )
{
int i = 0;
bool bSuccess = true;
int nFreqIndex = 0;
DEBUG_HEADER( “DDR Memory Test” );

/* clear our buffer to start */
for(i=0; i < N; i++)
{DDR2_Src_Buffer[i]=0;
}srand(*(volatile int*)0xF0000000);	/* seed with a random value *//* loop through all frequencies */
while(nFreqIndex++ < NUM_FREQS)
{DDR2_Init();/* make sure we start with the first pattern */nTest = 0;/* loop through all patterns */while(nTest <= ALL_FS){DEBUG_PRINT("%susing core accesses.\n\n", pattern_comments[nTest]);nCurrent_DDR_Addr = DDR2_START_ADDRESS;FillSrcBuffer(nTest);/* do core access for he second half of memory */do{WriteDDR();ReadDDR();bSuccess = CompareDDR();if(!bSuccess){/* increment the failure count because we want to try *//* all frequencies no matter what */break;}nCurrent_DDR_Addr += (BUFFER_SIZE * sizeof(unsigned int));}while(nCurrent_DDR_Addr < DDR2_END_ADDRESS);if(!bSuccess){nFailureCnt++;}nTest++;}	/* while(nTest <= ALL_FS) */}	/* while(nFreqIndex++ < NUM_FREQS) */
/* now tell if there were any issues or not */
if(nFailureCnt)
{DEBUG_STATEMENT( "DDR Test Failed" );
}
else
{DEBUG_STATEMENT( "DDR Test OK" );
}

}

相关文章:

  • 记录一个坑关于STM32 ARM Compiler Version
  • HarmonyOS学习 实验九:@State和@Prop装饰器的使用方法
  • (三)谷歌Code as Policies复现(操作记录)
  • [学习] C语言数据结构深度解析:八种树结构与应用场景详解(代码示例)
  • 【MySQL学习】存储过程
  • 学习笔记十四——一文看懂 Rust 迭代器
  • SIMULIA-Abaqus有限元分析软件针对汽车行业的解决方案
  • 通信算法之266: 无人机信号带宽计算
  • 软件需求说明书模板
  • 遨游防爆手机:构筑煤矿安全通讯的数字护盾
  • 【Java学习笔记】运算符
  • 【星海随笔】Python-JSON数据的处理
  • C++中类拷贝、赋值与销毁详解
  • FairyGUI图标文字合批失败的原因
  • HarmonyOS 5.0应用开发——五子棋游戏(鸿蒙版)开发
  • 【双指针】专题:LeetCode 611题解——有效三角形的个数
  • OpenCV 图形API(39)图像滤波----同时计算图像在 X 和 Y 方向上的一阶导数函数SobelXY()
  • 企业采购平台搭建指南:从流程重构到生态协同的数字化转型路径
  • 【学习笔记】Taming 3DGS泛读
  • 【android bluetooth 协议分析 02】【bluetooth hal 层详解 1】【uart 介绍】
  • 深圳高端网站定制公/百度公司官网首页
  • 建筑工程网上保健网站/广告门
  • 天元建设集团有限公司联系电话/整站优化和单词
  • 做网站所具备的的条件/外贸建站教程
  • 阿里巴巴网站本土化建设/网站seo优化心得
  • 怎么做能上谷歌网站吗/网站设计与制作教程