fpga在线升级 linux_2011/12/16 linux主机名 用户密码、静态IP设置及通过SPI实现FPGA的在线升级...
代码量不大,而且有参考,但是这段代码有几点需要提醒注意一下:对于指针的认识应该清楚,指针p加1指向的地址空间到底是加了1字节还是4字节,是由指针类型和平台决定的,不同类型指针的转换也要熟悉;大端小端存储得考虑一下吧,不过一般都是小端存储方式;关于/dev/mem,参考
出现问题及解决:
(1)
mmap函数调用失败,返回-1
主要是对该函数(可以百度搜索)参数的理解,void * mmap(void *start, size_t
length, int prot , int flags, int fd, off_t
offset);首先怀疑参数prot与打开/dev/mem时设置的方式不匹配,检查后排除(都为可读或者可读写);其次怀疑length的大小有限制,不知道看到哪里的介绍好像要是页大小的整数倍,检查后排除,其实没有该限制的;最后又不知道看到哪个论坛有提到offset要是页大小的整数倍,这下才仔细看了相关介绍,之前是张冠李戴了,确实是这个offset必须是页大小的整数倍,而一般的页大小是4K=0x1000
byte,这下才恍然大悟,之前还认为参考资料里的mask是多余的,所以不一定就能从我们希望的内存偏移量开始映射。这样映射后得到的地址需要加上偏移量,才得到想操作的内存起始地址映射后对应的起始地址。解决。
(2)
示波器测试时钟DCLK没有输出波形(其实不光是这个引脚,其他引脚都没有正确的输出)
(惭愧啊,其实之前还没有实际使用过ARM的GPIO,移植的过程基本都是在改代码,看到一个引脚要设置什么A,B功能,上拉与否,屏蔽与否,中断,输入输出等等就有点怯,很不解ARM
为什么把一个IO搞这么复杂,所以对代码很不自信,于是就学习了ARM
datasheet关于PIO的一章,发现其实不复杂,寄存器虽多但是是很清楚简单的。呵呵,言归正传。)主要是对单片机的认识错误的放在ARM上了。由于并没有使用过/mem/dev
和mmap()方法直接操作IO,怀疑该法能否正确实现IO操作。通过配置IO寄存器前后打印输出寄存器内容,排除了该考虑;也就是在上一个步骤中,重新看了一遍各个寄存器,突然发现ARM
设置某个引脚输出0是通过将该引脚对应的PCOD寄存器的对应位置1实现的,设置某个引脚输出1是通过将该引脚对应的PSOD寄存器的对应位置1实现的,操作的是两个不同的寄存器,不像单片机,就一个数据寄存器,置0输出0,置1输出1。所以是定义的宏clr_pin_output(pin)和宏set_pin_output(pin)错了(都操作PSDO寄存器了),解决。
(3)
程序正常执行,FPGA加载后执行程序正常,但是操作系统好像崩溃了,终端下输入各种命令都有部分报错信息,cp报“input/output
error”,ls报“.jffs2
warning:****”等等,一会就死机了。
主要是FPGA和NORFLASH共用地址线的问题。开始考虑是程序的bug,是不是直接对内存操作存在bug,比如读写地址没有对齐,文件打开没有关闭,映射后没有释放映射,检查后排除;硬件工程师提出,FPGA启动后会发送信号到地址线上,很有可能是该信号干扰了对FLASH的读写,考虑该可能性很大,因为linux命令ls、
cp等都涉及到FLASH的访问,如果FLASH访问有问题那自然都会报错。修改FPGA配置文件,屏蔽该信号,问题解决。
(4)
上面的代码是利用fpga的.ttf格式的配置文件直接将配置数据作为数组放在了作为程序的一部分了,做简单的修改就可以通过读文件(.rbf格式)方式加载配置数据了。至于不同格式配置文件差别,直接打开看看就知道了,当然有百度。
代码如下:
(至于硬件连接很简单,就5根线,具体可参考手册):
//include neccessary
headers
#include
#include
#include
#include
#include
#include "fpga_cfg_tab.h"
//header contains the configuration data table array
fpga_tab[],generated from source (.tty format)
//macros for common PIO register
#define PIO_PER
0x00
#define PIO_PDR
0x04
#define PIO_PSR
0x08
#define PIO_OER
0x10
#define PIO_ODR
0x14
#define PIO_OSR
0x18
#define PIO_IFER
0x20
#define PIO_IFDR
0x24
#define PIO_IFSR
0x28
#define PIO_SODR 0x30
#define PIO_CODR 0x34
#define PIO_ODSR 0x38
#define PIO_PDSR
0x3c
#define PIO_IER
0x40
#define PIO_IDR
0x44
#define PIO_IMR
0x48
#define PIO_ISR
0x4c
#define PIO_MDER 0x50
#define PIO_MDDR 0x54
#define PIO_MDSR 0x58
#define PIO_PUDR
0x60
#define PIO_PUER
0x64
#define PIO_PUSR
0x68
#define PIO_ASR
0x70
#define PIO_BSR
0x74
#define PIO_ABSR
0x78
#define PIO_OWER 0xa0
#define PIO_OWDR 0xa4
#define PIO_OWSR 0xa8
//global variable as the mapped address for PIOD
unsigned char *piod_vt_base;
//macros for mapped PIOD register
#define PIOD_PER (*(volatile unsigned int*)
(piod_vt_base PIO_PER))
#define PIOD_PDR (*(volatile unsigned int*)
(piod_vt_base PIO_PDR))
#define PIOD_PSR (*(volatile unsigned int*)
(piod_vt_base PIO_PSR))
#define PIOD_OER (*(volatile unsigned int*)
(piod_vt_base PIO_OER))
#define PIOD_ODR (*(volatile unsigned int*) (piod_vt_base
PIO_ODR))
#define PIOD_OSR (*(volatile unsigned int*) (piod_vt_base
PIO_OSR))
#define PIOD_IFER (*(volatile unsigned int*) (piod_vt_base
PIO_IFER))
#define PIOD_IFDR (*(volatile unsigned int*) (piod_vt_base
PIO_IFDR))
#define PIOD_IFSR (*(volatile unsigned int*) (piod_vt_base
PIO_IFSR))
#define PIOD_SODR (*(volatile unsigned int*)
(piod_vt_base PIO_SODR))
#define PIOD_CODR (*(volatile unsigned int*)
(piod_vt_base PIO_CODR))
#define PIOD_ODSR (*(volatile unsigned int*)
(piod_vt_base PIO_ODSR))
#define PIOD_PDSR (*(volatile
unsigned int*) (piod_vt_base PIO_PDSR))
#define PIOD_IER (*(volatile unsigned int*)
(piod_vt_base PIO_IER))
#define PIOD_IDR (*(volatile unsigned int*)
(piod_vt_base PIO_IDR))
#define PIOD_IMR (*(volatile unsigned int*)
(piod_vt_base PIO_IMR))
#define PIOD_ISR (*(volatile unsigned int*)
(piod_vt_base PIO_ISR))
#define PIOD_MDER (*(volatile unsigned int*)
(piod_vt_base PIO_MDER))
#define PIOD_MDDR (*(volatile unsigned int*)
(piod_vt_base PIO_MDDR))
#define PIOD_MDSR (*(volatile unsigned int*)
(piod_vt_base PIO_MDSR))
#define PIOD_PUER (*(volatile
unsigned int*) (piod_vt_base PIO_PUER))
#define PIOD_PUDR (*(volatile
unsigned int*) (piod_vt_base PIO_PUDR))
#define PIOD_PUSR (*(volatile
unsigned int*) (piod_vt_base PIO_PUSR))
#define PIOD_ASR (*(volatile unsigned int*)
(piod_vt_base PIO_ASR))
#define PIOD_BSR (*(volatile unsigned int*)
(piod_vt_base PIO_BSR))
#define PIOD_ABSR (*(volatile
unsigned int*) (piod_vt_base PIO_ABSR))
#define PIOD_OWER (*(volatile unsigned int*)
(piod_vt_base PIO_OWER))
#define PIOD_OWDR (*(volatile unsigned int*)
(piod_vt_base PIO_OWDR))
#define PIOD_OWSR (*(volatile unsigned int*)
(piod_vt_base PIO_OWSR))
//macros for each pin
#define AT91_PIN_PD0 (((unsigned int)0x00000001)
<< 0)
#define AT91_PIN_PD1 (((unsigned int)0x00000001)
<< 1)
#define AT91_PIN_PD2 (((unsigned int)0x00000001)
<< 2)
#define AT91_PIN_PD3 (((unsigned int)0x00000001)
<< 3)
#define AT91_PIN_PD4 (((unsigned int)0x00000001)
<< 4)
#define AT91_PIN_PD5 (((unsigned int)0x00000001)
<< 5)
#define AT91_PIN_PD6 (((unsigned int)0x00000001)
<< 6)
#define AT91_PIN_PD7 (((unsigned int)0x00000001)
<< 7)
#define AT91_PIN_PD8 (((unsigned int)0x00000001)
<< 8)
#define AT91_PIN_PD9 (((unsigned int)0x00000001)
<< 9)
#define AT91_PIN_PD10 (((unsigned int)0x00000001)
<< 10)
#define AT91_PIN_PD11 (((unsigned int)0x00000001)
<< 11)
#define AT91_PIN_PD12 (((unsigned int)0x00000001)
<< 12)
#define AT91_PIN_PD13 (((unsigned int)0x00000001)
<< 13)
#define AT91_PIN_PD14 (((unsigned int)0x00000001)
<< 14)
#define AT91_PIN_PD15 (((unsigned int)0x00000001)
<< 15)
#define AT91_PIN_PD16 (((unsigned int)0x00000001)
<< 16)
#define AT91_PIN_PD17 (((unsigned int)0x00000001)
<< 17)
#define AT91_PIN_PD18 (((unsigned int)0x00000001)
<< 18)
#define AT91_PIN_PD19 (((unsigned int)0x00000001)
<< 19)
#define AT91_PIN_PD20 (((unsigned int)0x00000001)
<< 20)
#define AT91_PIN_PD21 (((unsigned int)0x00000001)
<< 21)
#define AT91_PIN_PD22 (((unsigned int)0x00000001)
<< 22)
#define AT91_PIN_PD23 (((unsigned int)0x00000001)
<< 23)
#define AT91_PIN_PD24 (((unsigned int)0x00000001)
<< 24)
#define AT91_PIN_PD25 (((unsigned int)0x00000001)
<< 25)
#define AT91_PIN_PD26 (((unsigned int)0x00000001)
<< 26)
#define AT91_PIN_PD27 (((unsigned int)0x00000001)
<< 27)
#define AT91_PIN_PD28 (((unsigned int)0x00000001)
<< 28)
#define AT91_PIN_PD29 (((unsigned int)0x00000001)
<< 29)
#define AT91_PIN_PD30 (((unsigned int)0x00000001)
<< 30)
#define AT91_PIN_PD31 (((unsigned int)0x00000001)
<< 31)
//macros for operation on each pin
#define get_pin_input(pin) ((pin & (PIOD_PDSR)) ? 1:0)
#define set_pin_output(pin) ((PIOD_SODR) = (PIOD_SODR) | pin)
#define clr_pin_output(pin) ((PIOD_CODR) =(PIOD_CODR) | pin)
//macros for hardware specific
#define FPGA_CFGDONE AT91_PIN_PD20
#define FPGA_STA AT91_PIN_PD21
#define FPGA_CFG AT91_PIN_PD22
#define FPGA_DCLK AT91_PIN_PD23
#define FPGA_DATA0 AT91_PIN_PD26
//macros for mmap()
#define PIOD_OFFSET 0xfffff800
#define OFF_MASK 0xfff
#define MAP_SIZE 0xA00
//function to init the relative pins
void init_portd(void);
//function to complete reset task for
configuration
int reset_fpga(void);
//function to complete data transfor for
configuration
int cfg_fpga(void);
//function to end configuration end enter user mode
int init_fpga(void);
int main(int argc,char **argv)
{
int fd;
unsigned char
*mem_mapped_base;
if((fd=open("/dev/mem",O_RDWR|O_SYNC))==(-1))
{
printf("open /dev/mem failed!\n\r");
return 1;
}
printf("/dev/mem
opened.\n\r");
//get the base addr of the
whole ARM mem so that we can directly control PIOD in
application
mem_mapped_base=mmap (NULL,
(size_t)MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd,
(off_t)(PIOD_OFFSET & (~OFF_MASK)));
if(mem_mapped_base == (void
*) -1)
{
printf("mmap error!\n\r");
goto exit;
}
printf("memory mapped at
address:0x%X\n\r",mem_mapped_base);
//get
mapped addr for PIOD
piod_vt_base=mem_mapped_base
(PIOD_OFFSET & OFF_MASK);
init_portd();
if(0 == reset_fpga())
goto exit;
if(0 == cfg_fpga())
goto exit;
if(0 == init_fpga())
goto exit;
munmap(mem_mapped_base,MAP_SIZE);
close(fd);
return 0;
exit:
munmap(mem_mapped_base,MAP_SIZE);
close(fd);
return 1;
}
void init_portd(void)
{
PIOD_PER=FPGA_CFGDONE|FPGA_STA|FPGA_CFG|FPGA_DCLK|FPGA_DATA0;
//all relative pins used as
GPIO
PIOD_OER|=FPGA_CFG |
FPGA_DCLK | FPGA_DATA0; //set
output pins
PIOD_ODR|=FPGA_CFGDONE |
FPGA_STA; //set input pins
PIOD_IFER|=FPGA_CFGDONE |
FPGA_STA; //input pins with
input filter on
PIOD_CODR|=FPGA_CFG |
FPGA_DCLK | FPGA_DATA0; //clear
all output
PIOD_IDR|=FPGA_CFGDONE|FPGA_STA|FPGA_CFG|FPGA_DCLK|FPGA_DATA0;
//all relative pins not used
not as interrupt
PIOD_MDDR|=FPGA_CFG |
FPGA_DCLK | FPGA_DATA0; //output
pins with multi-driver off
PIOD_PUDR|=FPGA_CFGDONE|FPGA_STA|FPGA_CFG|FPGA_DCLK|FPGA_DATA0;
//all relative pins with
pull-up resistor unused(FPGA has internel pull-up res)
PIOD_OWDR|=FPGA_CFGDONE|FPGA_STA|FPGA_CFG|FPGA_DCLK|FPGA_DATA0;
//all relative pins with
output write disabled
}
int reset_fpga(void)
{
unsigned int i;
printf("FPGA reset
stage...\n\r");
clr_pin_output(FPGA_CFG);
//set CONFIG low to reset FPGA
for(i=0;i<10000 &&
(1== get_pin_input(FPGA_STA));i ); //CONFIG keeps low for at least
2us and wait for STAUS low
if(10000 == i)
{
printf(" error:wait for pin
STATUS low time out!\n\r");
return 0;
}
usleep(2);
set_pin_output(FPGA_CFG);
//set
CONFIG high to start config
for(i=0;i<10000 &&
(0== get_pin_input(FPGA_STA));i ); //wait for FPGA ready
if(10000 == i)
{
printf(" error:wait for pin
STATUS high time out!\n\r");
return 0;
}
printf("FPGA reset stage
end!\n\r");
return 1;
}
int cfg_fpga(void)
{
unsigned int i;
char j;
for(i=0;i
{
if(0 == get_pin_input(FPGA_STA))
//check if
STATUS change error during configuration
{
printf("
error:pin STATUS low during config
stage\n\r");
return
0;
}
if(1 == get_pin_input(FPGA_CFGDONE))
//check if CONF_DONE change error during
configuration
{
printf("
error:pin CONF_DONE high during config
stage\n\r");
return
0;
}
for(j=0;j<8;j )
//transfer one byte (the
least significant bit first)
{
clr_pin_output(FPGA_DCLK);
((fpga_tab[i] &
(0x01<
set_pin_output(FPGA_DATA0):clr_pin_output(FPGA_DATA0);//prepare
data
set_pin_output(FPGA_DCLK); //send
data while raising edge
j ;
j--;
}
}
printf("
data transfer finished!\n\r");
for(i=0;i<10000 &&
(0==get_pin_input(FPGA_CFGDONE));i ) //check if
CONF_DONE returns to high after data tranfer finished
{
if(0 == get_pin_input(FPGA_STA))
//check if
STATUS change error during configuration
{
printf("
error:pin STATUS low during config
stage\n\r");
return
0;
}
clr_pin_output(FPGA_DCLK); //more clk after the data transfer finished
according to the timing waveform
clr_pin_output(FPGA_DATA0);
set_pin_output(FPGA_DCLK);
}
if(10000 == i)
{
printf(" error:wait for pin
CONF_DONE high time out\n\r");
return 0;
}
set_pin_output(FPGA_DCLK);
//DCLK
should not be left floating
set_pin_output(FPGA_DATA0);
//DATA0
should not be left floating
printf("FPGA config stage
end\n\r");
return 1;
}
int init_fpga(void)
{
printf("FPGA initialization
stage...\n\r");
if(0 ==
get_pin_input(FPGA_CFGDONE))
{
printf(" error:pin CONF_DONE
low during init stage\n\r");
return 0;
}
printf("
use default clock source for
initialization\n\r"); //extra CLK maybe needed if
use CLKUSR
printf("
initialise without delay\n\r");
//delay is allowed between finishing
configuration and entering user mode for fpga
printf(" no
use of INIT_DONE\n\r"); //interrup
signal can be captured to indicate init stage end
usleep(50);
printf("FPGA initialization
stage end\n\r");
return 1;
}
fpga在线升级 linux_2011/12/16 linux主机名 用户密码、静态IP设置及通过SPI实现FPGA的在线升级...相关推荐
- Shell脚本之批量修改linux主机系统用户密码
一.需求说明 数据中心运维根据等保要求我们需要定期修改操作系统用户密码,一般是要求3个月修改一次.一个一个的修改很浪费时间,我们需要批量修改,此脚本就是批量修改Linux系统的操作系统账户密码,此 ...
- Chrome 谷歌浏览器升级后不再自动保存账号名和密码
Chrome 谷歌浏览器升级后不再自动保存账号名和密码 1.检查设置:是否开启自动保存密码设置 设置>密码:开启保存密码 2.如果设置没有问题,依然不能保存密码,进行如下操作: 关闭浏览器: 删 ...
- linux ps1 目录颜色,Linux主机名颜色设置,ps1设置,然linux有颜色 -电脑资料
RedHat的字体和背景颜色的改变方法: 命令: PS1="[\e[32;1m\u@\h \W]\\$" 或 export PS1="[\e[32;1m\u@\h \W] ...
- 如何修改Linux主机名
Linux 下什么都比较麻烦,就连修改主机名也不例外.我们就下文说一下具体方法. Linux 安装好后,其默认的主机名是 localhost.修改 Linux 主机名需要3步. 使用 hostname ...
- Linux主机名那点事儿
Linux主机名那点事儿 和windows一样,liunx同样有自己的主机名,主要用于识别机器和远成访问. 事儿一./etc/hosts文件 主机和IP配置文件 该文件其实就是告诉本机哪些域名对应那些 ...
- 修改Linux主机名
Linux 安装好后,其默认的主机名是 localhost.修改 Linux 主机名需要3步. 使用 hostname 修改当前主机名. hostname new-hostname 修改 /etc/s ...
- linux主机名的修改
导读 在一个局域网中,每台机器都有一个主机名,便于主机与主机之间的区分,因此为每台机器设置主机名,以容易记忆的方法来相互访问.比如我们在局域网中可以为根据每台机器的功用来为其命名. 查看主机名命令 [ ...
- 修改 Linux 主机名
Linux 下什么都比较麻烦,就连修改主机名也不例外. Linux 安装好后,其默认的主机名是 localhost.修改 Linux 主机名需要3步. 使用 hostname 修改当前主机名. hos ...
- linux主机名和工作组的修改方法
linux主机名和工作组的修改方法 在Windows下有计算机名和工作组,所以在Linux下也当然有计算机名和工作组了(好吧,说实话,我用Linux时间也不算短了,计算机名这个东东我一直知道,但是在L ...
最新文章
- 跨平台PHP调试器设计及使用方法——高阶封装
- Chrome现在也能编辑pdf文件了!64位安卓版上线,网页加载快10%,还有良心标签管理功能...
- 使用组策略部署exe软件
- 20140417--Linux课程讲解目录索引
- 框架:Hibernate和Mybatis的区别
- python定位文件位置_python使用相对定位,绝对定位,选取同级别文件下的指定文件(csv,excel)...
- 用Windows组件库文件快速部署Visual C
- 基于visual Studio2013解决算法导论之011快排改良
- python开发框架 代码生成_我的第一个python web开发框架(31)——定制ORM(七)...
- python显示no matching distribution,Python使用pip安装No matching distribution found for PyYaml==5.3.1...
- Linux平台上DPDK入门指南
- 2019-04-01
- 图解Web服务器网关接口WSGI(Web Server Gateway Interface)
- 备考2022年软考论文写作注意要点
- 材料科学基础考研计算机,2017年西安工业大学计算机学院805材料科学基础考研仿真模拟题...
- html+css基础教程入门学习之CSS表格
- SF中对象发出消息后在chatter上显示名字的问题
- 微信小程序入门与实战笔记
- 阿里发布虚拟美女“俪知”,会说东北话、四川话、河南话和粤语等
- mysql多条件count_Mysql中使用count加条件统计