作者的话

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子卡

硬件链接

在这里插入图片描述
正文正式开始

我们从最基础的GPIO开始,先讲外设,这玩意不管是单片机,还是ARM,又或是FPGA,甚至SOC的芯片,都有GPIO,有共性,就好理解,让我们看看在ADI的DSP里头,GPIO是怎么一回事吧。

接口功能介绍

ADSP-BF53x 处理器上有 16 个 Programmable Flag 接口,简称 PF 接口,这些接口就是通常所有的 IO 接口,通过寄存器配置,可以输出电平和感知接口电平,每一个 PF 接口都可以作为外部中断接口。

在单片机上,通常如果设置一个 IO 接口输出时,直接将输出信号值付给该接口,如果作为输入时,直接通过该接口读取即可。

而Blackfin 处理器的 IO 使用与单片机不同,在使用前必须对该接口进行初始化,如告知接口的方向,如配置为输出接口,则直接配置输出接口电平信号,如配置为输入接口,需打开输入使能开关,配置输出信号触发方式,是否中断触发,是否双极性触发等等。初始化完成后,才能使用 PF 接口。

接口寄存器说明

在这里插入图片描述

核心代码分析

输入接口配置:

将 PF0 接口配置为输入接口,并且读出接口电平状态。
*pFIO_DIR &= ~PF0; //设置 PF0 为输入
*pFIO_INEN |= PF0; //输入使能
i = *pFIO_FLAG_D; //读取数据

输出接口配置:

将 PF0 接口配置为输出接口,使用两种方式设置 PF0 输出高低电平。
*pFIO_DIR |= PF0; //设置 PF0 为输出
*pFIO_FLAG_S |= PF0; //PF0 脚置高
*pFIO_FLAG_C |= PF0; //PF0 脚置低
*pFIO_FLAG_D |= PF0; //PF0 脚置高
*pFIO_FLAG_D &= ~PF0; //PF0 脚置低

代码实现功能

工程 BF53x_GPIO_IN.dpj 实现了读取 PF0 接口状态并打印出 PF 接口状态数据。

在这里插入图片描述

工程 BF53x_GPIO_OUT.dpj 实现了通过 PF0 接口不断的输出高低变化的电平。

完整源码展示

这里有两个工程,一个工程是IN,一个工程是OUT:

IN:

#include <cdefBF533.h>

#define pDEVICE_OE (volatile unsigned short *)0x20320000
#define PF0_SET 0x40

void Set_PLL(unsigned int pmsel,unsigned int pssel)
{
unsigned 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_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}

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

void Init_PF0_IN(void)
{
*pFIO_DIR &= ~PF0;
*pFIO_INEN |= PF0;
}

void Set_CPLD(void)
{
*pDEVICE_OE &= ~PF0_SET ; //设置CPLD释放PF0接口
}

void main(void)
{
int i;

Set_PLL(16,4);
Init_EBIU();	
Init_SDRAM();

Set_CPLD();	
Init_PF0_IN();
while(1)
{
	i = *pFIO_FLAG_D;
	printf("PF data is %d\n",i); 	
}

}

OUT

#include <cdefBF533.h>

#define pDEVICE_OE (volatile unsigned short *)0x20320000
#define PF0_SET 0x40

void Set_PLL(unsigned int pmsel,unsigned int pssel)
{
unsigned 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_EBIU(void)
{
*pEBIU_AMBCTL0 = 0x7bb07bb0;
*pEBIU_AMBCTL1 = 0xffc07bb0;
*pEBIU_AMGCTL = 0x000f;
}

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

void Init_PF0_OUT(void)
{
*pFIO_DIR |= PF0;
}

void Set_CPLD(void)
{
*pDEVICE_OE &= ~PF0_SET ; //设置CPLD释放PF0接口
}

void main(void)
{
int i;

Set_PLL(16,4);
Init_EBIU();	
Init_SDRAM();

Set_CPLD();
	
Init_PF0_OUT();
while(1)
{
	*pFIO_FLAG_S |= PF0;    //PF0脚置高
   	*pFIO_FLAG_C |= PF0;	//PF0脚置低
 	*pFIO_FLAG_D |= PF0;    //PF0脚置高
   	*pFIO_FLAG_D &= ~PF0;	//PF0脚置低      	 
}

}

关于ADI的DSP GPIO的原理以及源代码有任何问题均可以随时问我,本人很懂。

Logo

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

更多推荐