09-07-2017 02:28 AM
Hello,
I used Xillybus on Xillinux 2.0a on Zybo Zynq-7000 and could successfully acces to PL through /dev/xillybus_read_32 and /dev/xillybus_write_32 in previous codes.
Now I'm trying to implement a code based on a Sobel Operator, where the PS do all the data management, and the PS run the calculations. I synthesized the PL code with Vivado HLS 2016.4 and exported the RTL file, and I added it to the Vivado 2016.4 project 'xillinux-eval-zybo-2.0a' and generated the bitstream.
When I try to execute my host program on Xillinux it generates the following error: "Failed to open Xillybus device file(s): Device or resource busy".
I have searched for this error on the Internet and I have only found a reference in the 'Xillybus host application programming guide for Linux'. I understand what this error means, but I can not see what might be generating it. I have tried to limit the opening and closing of these device files, but it persists.
The device files remain busy because I tried to use "cat /dev/xillybus_read_32" on the terminal (when I'm not running the program) and it also says it is busy.
To introduce my code, I try to apply the Sobel filter on a 100x100 image in bmp format. Due to the memory limitations of the PL, I only send and save the first two rows of pixels on the image and the three first pixels of the third row; so I can make the first convolution, and then I shift all the array to the left and save the next pixel send from the PS in the last position of the array.
The host program is based on the example given in 'FPGA coprocessing for C/C++ programmers' tutorial -A practical host program-, but I have modified it to fit my application.
HOST PROGRAM:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#define N 203
#define BUFFER_SIZE 10000
#define ncols 100
#define header 1078
int main(int argc, char *argv[]) {
FILE *source;
FILE *destination;
unsigned char set[header];
int imfrompl[BUFFER_SIZE] = {0};
unsigned char buffer[BUFFER_SIZE];
unsigned char imgout[BUFFER_SIZE];
//Reading the original image
source = fopen("/root/Desktop/img100.bmp", "r");
//Reading the header and saving it in the output image
destination = fopen("hostsobelfork.bmp", "w");
fread(set, 1, header, source);
fwrite(set, 1, header, destination);
int fdr, fdw, rc, donebytes, i;
unsigned char *buf2pl;
int *buf2ps;
pid_t pid;
//Trying to limit the opening and closing
if (fdr == 0)
fdr = open("/dev/xillybus_read_32", O_RDONLY);
if (fdw == 0)
fdw = open("/dev/xillybus_write_32", O_WRONLY);
if ((fdr < 0) || (fdw < 0)) {
perror("Failed to open Xillybus device file(s)");
exit(1);
}
pid = fork();
if (pid < 0) {
perror("Failed to fork()");
exit(1);
}
//Sending data to PL
if (pid) {
close(fdr);
buf2pl = &buffer[0];
donebytes = 0;
while (donebytes < (BUFFER_SIZE) * sizeof(int)) {
rc = write(fdw, buf2pl + donebytes, (BUFFER_SIZE) * sizeof(int) - donebytes);
if ((rc < 0) && (errno == EINTR))
continue;
if (rc <= 0) {
perror("write() failed");
exit(1);
}
donebytes += rc;
}
close(fdw);
return 0;
}
//Receiving data from PL
else {
close(fdw);
buf2ps = &imfrompl[ncols+1];
donebytes = 0;
while (donebytes < (BUFFER_SIZE - N) * sizeof(int)) {
rc = read(fdr, buf2ps + donebytes, (BUFFER_SIZE - N) * sizeof(int) - donebytes);
if ((rc < 0) && (errno == EINTR))
continue;
if (rc < 0) {
perror("read() failed");
exit(1);
}
if (rc == 0) {
fprintf(stderr, "Reached read EOF!? Should never happen.\n");
exit(0);
}
donebytes += rc;
}
for (i=0; i<BUFFER_SIZE; i++) //Saving the results and cast data to unsigned char
imgout[i] = (unsigned char)imfrompl[i];
if (!fseek(destination, header, SEEK_SET)) //Filling out the output image
fwrite(imgout, 1, BUFFER_SIZE, destination);
fclose(source);
fclose(destination);
fclose(destination2);
close(fdr);
return 0;
}
}
**************************************************************************************************************
PROGRAM RUNNING ON THE PL:
#include <math.h>
#include <stdint.h>
#include "xilly_debug.h"
static int c1=0; //number of runs counter
void xillybus_wrapper(int *in, int *out) {
#pragma AP interface ap_fifo port=in
#pragma AP interface ap_fifo port=out
#pragma AP interface ap_ctrl_none port=return
int imin[203];
int k[9] = {1,0,-1,2,0,-2,1,0,-1};
int x, y, c, ncols, scale, pos, threshold;
ncols = 100;
scale = 8;
threshold=10;
pos=ncols+1;
c1 += 1;
// Receiving input data from PS
imin[202] = *in++;
if (c1 > 202){
// Carrying out the calculations of the Sobel kernel convolution
c = k[0]*imin[pos-ncols-1]+k[1]*imin[pos-ncols]+k[2]*imin[pos-ncols+1]+k[3]*imin[pos-1]+k[4]*imin[pos]+k[5]*imin[pos+1]+k[6]*imin[pos+ncols-1]+k[7]*imin[pos+ncols]+k[8]*imin[pos+ncols+1];
// Sending output data to PS
if (c/scale < threshold)
*out++ = 0;
else
*out++ = c/scale;
}
// Reset counter when finished
if (c1 > 9999)
c1 = 0;
for (y=0; y<202; y++) {
// Shifting the array to left to sort the data
imin[y] = imin[y+1];
}
//*out++ = 1; //I tried it, to ensure an output in each run, and the error still the same
// Debug output
xilly_puts("count=");
xilly_decprint(count, 1);
xilly_puts("\n");
}
***************************************************************************************************************
Any guess of where this problem could come from?
Thanks in advance.
Best regards,
Marc
09-07-2017 09:17 PM
Hello,
The first thing that comes to mind is that you use check if fdr and fdw are zero even though you haven't initialized them. I suggest compiling with the -Wall flag (I believe it would have told you that you're using an uninitialized variable). Not that I understand the logic behind that check. But this is probably not the issue anyhow.
As for the error itself -- does it occur on a freshly booted system? It's the easiest way to see if it's a matter of some process really holding the file.
Have you tried using "lsof" to find the process that may hold the file? Maybe you have some child process remaining alive, holding the file? Keep in mind that you'll get a shell prompt when the father process finishes, but the child can go on. In fact, the proper way to finish up the father process is to wait() or waitpid() for the child.
Regards,
Eli