作者的话

BF533是ADI Blackfin系列DSP处理器里的最经典型号,这个DSP我用了20年,单就这一颗DSP来讲,我相信国内应该没有比我更资深的了,下面就来说一说这颗DSP。

这颗IC是Blackfin里的经典款,由于Blackfin系列DSP均是同一个内核,在我看来,会用BF533,就约等于会用ADI Blackfin全系列DSP。实际上也确实是这样,我本人是从2002年开始用BF533,后面继续做了BF527,BF524,BF537,BF547,BF548,BF561,BF518,BF512,BF504,BF506,BF592,BF706,BF707,BF609,BF608;几乎每一颗ADSP,我都有基于项目做过软硬件的开发,而这一切的基础就是BF533。

这个系列,我计划从内核架构开始,到外设、驱动、典型算法、软件应用、uclinux、ucos等方面,来说一说这颗DSP。

硬件准备

ADSP-EDU-BF533开发板:BF533全功能开发板

产品链接:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-5192690539.11.5c1d42b3yniNnQ&id=39598018589

在这里插入图片描述

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

产品链接:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-5192690539.11.52dfbfa3xB7JE7&id=38007242820

在这里插入图片描述

AD-CMOS:CMOS摄像头子卡
AD-MEMS:ADI MEMS三轴加速度传感器子卡
AD-ADC:ADC采集子卡
AD-LCD:2.4寸LCD子卡

硬件链接

在这里插入图片描述

接口功能介绍

MDMA 全称是 memoryDMA ,是内存到内存搬运数据的 DMA。在 DSP 做算法时,经常会遇到数据重组或者搬移,如果用 core 搬运这些数据,是对 DSP 资源的一种浪费,此时就可以用到 MDMA 进行数据搬移。

接口寄存器说明

在这里插入图片描述

核心代码分析

*pMDMA_S0_START_ADDR = pSrc; //设置源地址
*pMDMA_S0_X_COUNT = 8; //传输次数 8 次
*pMDMA_S0_X_MODIFY = 2; //地址修改增量 2,16bit 模式一次读 2 个 byte
*pMDMA_D0_START_ADDR = pDest;
*pMDMA_D0_X_COUNT = 8;
*pMDMA_D0_X_MODIFY = 2;
*pMDMA_S0_PERIPHERAL_MAP = 0x0040; //配置使用的 DMA 通道
*pMDMA_D0_PERIPHERAL_MAP = 0x0040;

*pMDMA_S0_CONFIG = 0x0024; //配置源 DMA 工作模式
*pMDMA_D0_CONFIG = 0x00a6; //配置目的 DMA 工作模式
*pSIC_IAR5 = 0xfffff6ff; //设置中断等级
register_handler(ik_ivg13, MDMA_ISR); //注册中断
*pSIC_IMASK1 = 0x00000400; //打开中断屏蔽

代码实现功能

代码实现了将源地址 buffer 中的 8 个数据搬到目的地址中,完成搬运后会进入中断程序,然后在中断中再次使能 MDMA,重复搬运数据。

在中断函数中打个断点,运行代码后,Src_Buf 中的数据会被搬运到 Dest_Buf 中去,完成搬运后会进入中断函数,通过 Visual DSP 下的 memory 窗口,可以查看 Dest_Buf 中的数据。

在这里插入图片描述

完整代码

  1. CPU.C

#include <cdefBF533.h>

void Set_PLL(int pmsel,int pssel)
{
int new_PLL_CTL;
*pPLL_DIV = pssel;
asm(“ssync;”);
new_PLL_CTL = (pmsel & 0x3f) << 9;
*pSIC_IWR |= 0xffffffff;
if (new_PLL_CTL != *pPLL_CTL)
{
*pPLL_CTL = new_PLL_CTL;
asm(“ssync;”);
asm(“idle;”);
}
}

void Init_SDRAM(void)
{
*pEBIU_SDRRC = 0x00000817;
*pEBIU_SDBCTL = 0x00000013;
*pEBIU_SDGCTL = 0x0091998d;
ssync();
}

void Init_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0x7bb07bb0;
*pEBIU_AMGCTL = 0x000f;
}

  1. MDMA.c

#include <cdefBF533.h>
#include <ccblkfn.h>
#include <sys/exception.h>
#include “cpu.h”

//*pSrc :源地址
//*pDest :目的地址
void Init_MDMA(unsigned short *pSrc,unsigned short *pDest)
{
*pMDMA_S0_START_ADDR = pSrc; //设置源地址
*pMDMA_S0_X_COUNT = 8; //传输次数 8次
*pMDMA_S0_X_MODIFY = 2; //地址修改增量2,16bit模式一次读2个byte

*pMDMA_D0_START_ADDR = pDest;			
*pMDMA_D0_X_COUNT = 8;
*pMDMA_D0_X_MODIFY = 2;

*pMDMA_S0_PERIPHERAL_MAP = 0x0040;		//配置使用的DMA通道
*pMDMA_D0_PERIPHERAL_MAP = 0x0040;

*pMDMA_S0_CONFIG = 0x0024;				//配置源DMA工作模式
*pMDMA_D0_CONFIG = 0x00a6;				//配置目的DMA工作模式

}

void MDMA_Enable(void) //使能MDMA
{
*pMDMA_S0_CONFIG |= 0x0001;
*pMDMA_D0_CONFIG |= 0x0001;
}

EX_INTERRUPT_HANDLER(MDMA_ISR) //中断函数
{
*pMDMA_D0_IRQ_STATUS=0x1; //清楚中断标志位
MDMA_Enable(); //使能MDMA继续传输
}

void Init_MDMA_Interrupt(void) //初始化中断
{
*pSIC_IAR2 = 0xff6fffff; //设置中断等级
register_handler(ik_ivg13, MDMA_ISR); //注册中断
*pSIC_IMASK = 0x00200000; //打开中断屏蔽
}

  1. Main.c

#include <cdefBF533.h>
#include “cpu.h”

unsigned short Src_Buf[8]={1,2,3,4,5,6,7,8};
unsigned short Dest_Buf[8]; //目的buffer

void main(void)
{
Set_PLL(16,4); //配置内核时钟400MHz,系统时钟100MHz,25M*16/4
Init_EBIU(); //初始化EBIU
Init_SDRAM(); //初始化SDRAM

Init_MDMA_Interrupt();			//初始化MDMA中断
Init_MDMA(Src_Buf,Dest_Buf);	//初始化MDMA
MDMA_Enable();					//使能MDMA
while(1);	

}

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐