学fpga(hls之驱动代码)
Posted 费晓行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学fpga(hls之驱动代码)相关的知识,希望对你有一定的参考价值。
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
利用hls编写好了ip之后,那么驱动代码如何编写?好在hls sdk已经提前考虑到了这一点,在export rtl的时候,除了正常输出verilog和vhdl代码之外,也会提前帮助我们写好驱动代码。驱动代码有两种格式,一种是逻辑系统的驱动,类似于rtos里面用到的驱动;还有一种是linux驱动,但是也是在用户层对设备进行访问,不是真正的kernel module文件。
1、hls代码,主要是一个按键和s_axilite控制的led闪烁功能
#include <ap_cint.h>
extern "C" void led_twinkle(uint1 key, uint32 num, uint2* led)
#pragma HLS INTERFACE s_axilite port=num
#pragma HLS INTERFACE ap_none port=key
#pragma HLS INTERFACE ap_none port=led
#pragma HLS INTERFACE ap_ctrl_none port=return
int i;
if(key)
for(i = 0; i < num; i++)
if(i < num/2)
*led = 1;
else
*led = 2;
else
*led = 0;
2、导出的驱动代码位置
3、驱动代码的内容
4、驱动的组成
如果是裸机系统,需要的文件是
xled_twinkle_sinit.c、xled_twinkle.c
如果是linux系统,需要的文件时
xled_twinkle_linux.c、xled_twinkle.c
5、裸机系统的初始化函数,见xled_twinkle_sinit.c
int XLed_twinkle_Initialize(XLed_twinkle *InstancePtr, u16 DeviceId)
XLed_twinkle_Config *ConfigPtr;
Xil_AssertNonvoid(InstancePtr != NULL);
ConfigPtr = XLed_twinkle_LookupConfig(DeviceId);
if (ConfigPtr == NULL)
InstancePtr->IsReady = 0;
return (XST_DEVICE_NOT_FOUND);
return XLed_twinkle_CfgInitialize(InstancePtr, ConfigPtr);
6、linux驱动并不内核代码,而是通过user layer访问kernel layer,见xled_twinkle_linux.c
int XLed_twinkle_Initialize(XLed_twinkle *InstancePtr, const char* InstanceName)
XLed_twinkle_uio_info *InfoPtr = &uio_info;
struct dirent **namelist;
int i, n;
char* s;
char file[ MAX_UIO_PATH_SIZE ];
char name[ MAX_UIO_NAME_SIZE ];
int flag = 0;
assert(InstancePtr != NULL);
n = scandir("/sys/class/uio", &namelist, 0, alphasort);
if (n < 0) return XST_DEVICE_NOT_FOUND;
for (i = 0; i < n; i++)
strcpy(file, "/sys/class/uio/");
strcat(file, namelist[i]->d_name);
strcat(file, "/name");
if ((line_from_file(file, name) == 0) && (strcmp(name, InstanceName) == 0))
flag = 1;
s = namelist[i]->d_name;
s += 3; // "uio"
InfoPtr->uio_num = atoi(s);
break;
if (flag == 0) return XST_DEVICE_NOT_FOUND;
uio_info_read_name(InfoPtr);
uio_info_read_version(InfoPtr);
for (n = 0; n < MAX_UIO_MAPS; ++n)
uio_info_read_map_addr(InfoPtr, n);
uio_info_read_map_size(InfoPtr, n);
sprintf(file, "/dev/uio%d", InfoPtr->uio_num);
if ((InfoPtr->uio_fd = open(file, O_RDWR)) < 0)
return XST_OPEN_DEVICE_FAILED;
// NOTE: slave interface 'Axilites' should be mapped to uioX/map0
InstancePtr->Axilites_BaseAddress = (u32)mmap(NULL, InfoPtr->maps[0].size, PROT_READ|PROT_WRITE, MAP_SHARED, InfoPtr->uio_fd, 0 * getpagesize());
assert(InstancePtr->Axilites_BaseAddress);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
return XST_SUCCESS;
int XLed_twinkle_Release(XLed_twinkle *InstancePtr)
XLed_twinkle_uio_info *InfoPtr = &uio_info;
assert(InstancePtr != NULL);
assert(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
munmap((void*)InstancePtr->Axilites_BaseAddress, InfoPtr->maps[0].size);
close(InfoPtr->uio_fd);
return XST_SUCCESS;
7、寄存器设置代码,见xled_twinkle.c代码
void XLed_twinkle_Set_num(XLed_twinkle *InstancePtr, u32 Data)
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
XLed_twinkle_WriteReg(InstancePtr->Axilites_BaseAddress, XLED_TWINKLE_AXILITES_ADDR_NUM_DATA, Data);
u32 XLed_twinkle_Get_num(XLed_twinkle *InstancePtr)
u32 Data;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Data = XLed_twinkle_ReadReg(InstancePtr->Axilites_BaseAddress, XLED_TWINKLE_AXILITES_ADDR_NUM_DATA);
return Data;
8、测试与验证
在一开始设计ip的时候,可以通过简单的逻辑系统+驱动代码的方式进行验证。等到后期成熟了,再转成linux驱动、或者是linux kernel驱动,都是可以的。
以上是关于学fpga(hls之驱动代码)的主要内容,如果未能解决你的问题,请参考以下文章