当前位置:首页 > 嵌入式 > 嵌入式软件

  摘要:本文实现了一种基于 ARM-的 程序加载方法,详细讨论了加载过程中各个阶段程序对配置管脚的操作,给出了硬件实现,编写了运行于 ARM处理器的嵌入式 上的驱动程序。

  1、引言

  在系统上电时,需要从外部载入所要运行的程序,此过程被称为程序加载。多数情况下,从外部专用的 读入程序。这种方式速度慢,而且只能加载固定的程序。显然,当系统需要容量大而且 FPGA要加载的程序可以根据需要有选择的加载时不能采用这种方法。本文实现了一种基于外部处理器的加载方法,速度快,而且可以根据设置给FPGA加载相应的程序。

  对于 公司的 FPGA芯片,有五种加载方式:JTAG模式,串行从模式,串行主模式,并行从模式和并行主模式。JTAG模式常用于调试时,将主机好的程序加载到FPGA,优先级高于几种模式。加载模式取决于 FPGA上加载模式管脚(M0,M1,M2)的设置。

  用外部处理器给 FPGA加载程序时,可以采用串行从模式、并行从模式,甚至于 JTAG模式。本文选择并行从模式,原因在于更高的配置速率。

  2、 FPGA程序数据的产生

  FGPA的程序加载即是要把好的程序文件按一定的时序写入FPGA。而 的开发环境可以根据用户的选择产生多种文件格式,以不同的后缀名区分。不同的文件格式包含了不同的信息,有不同的用途。

  本文选择了.bin格式的文件。此文件是只包含有程序数据的二进制文件。产生此文件,要在bitgen 参数里增加-g :yes 选项。

  此外,需要说明的是,通常的微处理器 D0位是最低有效位,而 的 FPGA在接收程序数据时,D0位是最高有效位。因此,在按字节读取.bin格式的文件之后,需要有一个转换的过程。如从文件读到一个字节,0x7D,即二进制的 0111 1101,需转换为:1011 1110。

  加载过程开始时,就要从.bin文件序按字节读出数据,然后在 CCLK的上升沿写入 FPGA。在.bin文件中的数据都被写入 FPGA后,CCLK需要多出四个时钟周期,以使得 FPGA完成启动过程。

  3、硬件设计

  在FPGA上,与配置有关的管脚分为两类:专用管脚,包括_B,HSWAP_EN,TDI, TMS,,TCK,TDO,CCLK,DONE,和M0-M2。还有一类是可复用管脚,这类管脚在配置阶段作为配置管脚,配置结束后可以配置为通用普通的IO管脚,也可以继续作为配置管脚。在并行从模式下,涉及到的配置管脚和功能如下:

  CS_B:片选信号,低有效; RDWR_B:写信号,低有效; BUSY:FPGA忙指示,高有效,一般只有在并行加载时钟速率大于50M时才有可能用到;D0-D7:数据线; _B:芯片被复位后,此管脚为输出信号,输出低电平指示FPGA正在自行复位内部

  寄存器。复位结束后,此管脚浮空,处于输入状态。因此需要上拉电阻,指示复位结束。内部寄存器复位结束后,此管脚若被拉低,则会推迟FPGA的程序加载过程。在程序加载过程中,此管脚又变回输入状态,对外输出低电平指示加载的程序数据存在CRC校验错误。

  _B:异步复位信号,下降沿有效,此信号为低电平时复位FPGA,复位后,FPGA芯片处于内部寄存器自行复位过程,_B被FPGA芯片拉低,此过程结束后,FPGA不再驱动_B管脚,INIT_B管脚处于浮空状态,此时,INIT_B有上拉电阻时,INIT_B呈现高电平,依次可以指示FPGA的内部寄存器自行复位结束。程序加载状态。

  DONE:加载成功指示。 CCLK:程序加载时,数据在此信号的上升沿被写入FPGA。在本设计中,ARM芯片采用的是 SUMSUN公司的,与 FPGA配置管脚相连的是此芯片的通用 IO管脚 D组。硬件连接如图[1]所示。在 ARM的程序中,ARM管脚在程序加载的各阶段的输入输出设置如下:首先,设置 GPD[10](与 FPGA的 INIT_B相连)、GPD[11](与 FPGA的 BUSY相连)为输入管脚,以监视 FPGA内部寄存器自行复位结束和忙闲状态。其次,设置GPD[12](与 FPGA的 _B相连)为输出状态,并使其输出低脉冲,使 FPGA复位。然后依次设置 GPD[8](与 FPGA的 CS_B相连)、GPD[9](与 FPGA的 RDWR_B相连)、GPD[14] (与 FPGA的 CCLK相连)为输出管脚,并使其输出低电平,使 FPGA处于被选可接受数据状态;接着设置D[0..7]为输出状态。

  至此,ARM中的程序开始轮询GPD[10]的状态,检测到此信号为高时,有两种选择,其一是因为需要而推迟 FPGA的程序加载,可以通过设置 GPD[10]为输出,并使其输出为低电平直至程序加载开始。其二是开始给 FPGA加载程序,FPGA在 CCLK的上升沿接收数据,在给 FPGA加载程序的过程中,程序需要监视GPD[10]管脚的状态,一旦为低,FPGA指示程序数据加载 CRC校验出错。此时需要复位FPGA,重新加载.

  4、嵌入式 的驱动实现

  本文以模块形式实现了运行于上的驱动程序,源文件如下(有关寄存器

  的设置参考的数据手册,以下源代码未包含头文件):

  #define GPIO_va_ 0x0F6000000

  //基于S3C2410 上的Linux内核IO控制寄存器首地址映射后的虚拟地址

  #define ARM_GPDCON PIO_va_+0x30);

  #define ARM_GPDUP PIO_va_+0x38);

  #define ARM__wr(addr,) *(volatile unsigned int*)(addr)=)

  //定义输出

  #define FPGA_CS 8

  #define FPGA_RW 9

  #define FPGA_PROG 12

  #define FPGA_CCLK 14

  //定义操作

  #define ARM_GPDDAT (*(volatile u32 *)(GPIO_va_base+0x34))

  #define set_register_bit(x) ARM_GPDDAT=(1<<x)|ARM_GPDDAT

  #define _register_bit(x) ARM_GPDDAT=(~(1<<x))&ARM_GPDDAT

  //定义输入

  #define FPGA_INIT ((ARM_GPDDAT>>10)&1)

  #define FPGA_BUSY ((ARM_GPDDAT>>11)&1)

  #define FPGA_DONE ((ARM_GPDDAT>>13)&1)

  #define FPGA 211

  //定义主设备号,和mknod /dev/ c 211 0匹配

  typedef __t;

  static __t fpga_s[257];

   buf[1000000];

  int fpga_(struct inode *, struct file *);

  ssize_t fpga_write(struct file *, *,size_t ,loff_t *);

  int fpga_(struct inode*, struct file *);

  //初始化ARM的D组通用IO管脚

  void _fpga(void){

  ARM__wr(GPIO_va_base+0x30,0x55555555);

  //FPGA_BUSY FPGA_DONE FPGA_INIT be set input

  ARM__wr(GPIO_va_base+0x34,0xFFFF);

  ARM_port_wr(GPIO_va_base+0x30,0x51055555);

  ARM_port_wr(GPIO_va_base+0x38,0);// put up

  set_register_bit(FPGA_CCLK);//set GCLK

  }

  static struct file_operations fpga_ctl_fops= {

  : fpga_,

  write: fpga_write,

  : fpga_,};

  int _(void) {

  printk(",word,Now preparing FPGA......\n");

  printk("register FPGA......\n");

  register_chrdev(FPGA, "fpga", &fpga_ctl_fops);

  printk("Done!\n");

  printk(",word,success!\n");

   0;

  }

  int fpga_open(struct inode *inode, struct file *filp){

  int minor;

  minor = MINOR(inode->i_rdev);

  _fpga();

  fpga_[minor]++;

  printk("FPGA is ready.\n");

   0;

  }

  ssize_t fpga_write(struct file *, char *buffer,size_t count,loff_t

  *ppos){

  int i;

  if(__(buf,buffer,count)){

  printk("error \n");

   -EFAULT;

  }

  printk("%d s have been received!\n",count);

  printk("The is:%d\n",count);

  for(i=0;i<count;i++){

  ARM_GPDDAT=(ARM_GPDDAT&0x3F00)|buf[i];

  set_register_bit(FPGA_CCLK);

  }

  printk("data write finished\n");

  for(i=0;i<4;i++){

  set_register_bit(FPGA_CCLK);

  _register_bit(FPGA_CCLK);

  }

  return count;

  }

  int fpga_release(struct inode *inode, struct file *filp){

  int minor;

  minor = MINOR(inode->i_rdev);

  if (fpga_[minor])

  fpga_[minor]--;

  printk("Goodbye cruel world\n");

  return 0;

  }

  void cleanup_(void){

  printk("Goodbye cruel world\n");

  }

  5、结束语

  本文的创新点:基于ARM-Linux平台,实现了一种FPGA的程序加载模式,加载速度快,灵活高效。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭