I can't get the camera sample program to work.
-
Hi!
I'm having trouble getting my camera program to work and would really appreciate your help.Previously, the camera sample program worked fine, but since I created my own camera program, I get link errors when I try to build only the camera sample program.
The error was as follows.arm-none-eabi-ld: /Users/gyps/spresense/nuttx/staging/libapps.a(camera_main.c.Users.gyps.spresense.sdk.apps.examples.camera.o): in function `camera_main': /Users/gyps/spresense/sdk/apps/examples/camera/camera_main.c:766: undefined reference to `video_uninitialize' arm-none-eabi-ld: /Users/gyps/spresense/sdk/apps/examples/camera/camera_main.c:507: undefined reference to `video_initialize' arm-none-eabi-ld: /Users/gyps/spresense/nuttx/staging/libapps.a(my_camera_main.c.Users.gyps.spresense.myapps.mycamera.o): in function `mycamera_main': /Users/gyps/spresense/myapps/mycamera/my_camera_main.c:62: undefined reference to `video_initialize' arm-none-eabi-ld: /Users/gyps/spresense/myapps/mycamera/my_camera_main.c:198: undefined reference to `video_uninitialize' make[2]: *** [nuttx] Error 1 make[1]: *** [nuttx] Error 2 make: *** [all] Error 2
◯ What I tried
1, Run only the camera sample after doing make distclean.
→The same error occurred.2, run source spresenseenv/setup.
→The same error occurred.3, Try the same thing in another environment (wsl2 ).
→The same error occurred.◯ Environment
OS: mac OS Big Sur version 11.6
Ubuntu 20.04 LTS (WSL2)
SDK version: 2.6 -
The following shows the process from the time the environment is created until the error occurs.
1, Make a new environment.
(Download spresense again via git clone.)2, Get the camera sample working.
(at this point it works and I can make the camera work)3, Run "make distclean", delete the camera sample settings in the config menu, and build my own camera program with "make -j".
I got a link error as shown below.arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(my_camera_main.c.home.gyps.spresense.myapps.my_camera.o): in function `my_camera_main': /home/gyps/spresense/myapps/my_camera/my_camera_main.c:59: undefined reference to `video_initialize' arm-none-eabi-ld: /home/gyps/spresense/myapps/my_camera/my_camera_main.c:195: undefined reference to `video_uninitialize' make[2]: *** [Makefile:156: nuttx] Error 1 make[1]: *** [tools/Makefile.unix:420: nuttx] Error 2 make: *** [Makefile:114: all] Error 2
4, Execute "make distclean", delete the program you created by myself in the config menu, and build the camera sample with "make -j".
The following link error occurs.arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(camera_main.c.home.gyps.spresense.sdk.apps.examples.camera.o): in function `camera_main': /home/gyps/spresense/sdk/apps/examples/camera/camera_main.c:507: undefined reference to `video_initialize' arm-none-eabi-ld: /home/gyps/spresense/sdk/apps/examples/camera/camera_main.c:766: undefined reference to `video_uninitialize' arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(camera_bkgd.c.home.gyps.spresense.sdk.apps.examples.camera.o): in function `nximage_listener': /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:134: undefined reference to `nx_eventhandler' arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(camera_bkgd.c.home.gyps.spresense.sdk.apps.examples.camera.o): in function `nximage_initialize': /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:241: undefined reference to `nx_connectinstance' arm-none-eabi-ld: /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:273: undefined reference to `nx_setbgcolor' arm-none-eabi-ld: /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:274: undefined reference to `nx_requestbkgd' arm-none-eabi-ld: /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:278: undefined reference to `nx_disconnect' arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(camera_bkgd.c.home.gyps.spresense.sdk.apps.examples.camera.o): in function `nximage_draw': /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:320: undefined reference to `nx_bitmap' arm-none-eabi-ld: /home/gyps/spresense/nuttx/staging/libapps.a(camera_bkgd.c.home.gyps.spresense.sdk.apps.examples.camera.o): in function `nximage_finalize': /home/gyps/spresense/sdk/apps/examples/camera/camera_bkgd.c:337: undefined reference to `nx_disconnect' make[2]: *** [Makefile:156: nuttx] Error 1 make[1]: *** [tools/Makefile.unix:420: nuttx] Error 2 make: *** [Makefile:114: all] Error 2
-
Hello, @gyps
This problem usually happens when you don't have the right configurations for the sdk.
For example: The message "undefined reference to `video_uninitialize'" will appear if you don't have the DRIVERS_VIDEO configuration enabled on the sdk.Can I ask how are you creating your own application?
-
Thanks for the reply.
I took the camera sample project to the MYAPPS directory and corrected the "Kconfig", "Makefile" and "Make.defs" as usual, and also rewrote the main program to get only one image.In addition, I have merged c files into one, and removed programs I deemed unnecessary.
Also, the device driver settings in the config menu have not been changed.
For reference, the modified files other than my_camera_main.c are shown below.
Kconfig
config MYAPPS_CAMERA tristate "My Camera example" default y ---help--- Enable the camera example if MYAPPS_CAMERA config MYAPPS_CAMERA_PROGNAME string "Program name" default "mycamera" ---help--- This is the name of the program that will be use when the NSH ELF program is installed. config MYAPPS_CAMERA_PRIORITY int "Camera task priority" default 100 config MYAPPS_CAMERA_STACKSIZE int "Camera stack size" default 2048 config MYAPPS_CAMERA_OUTPUT_LCD bool "Output to LCD" default n ---help--- This enables to output the captured RGB565 image to LCD. endif
Makefile
include $(APPDIR)/Make.defs include $(SDKDIR)/Make.defs PROGNAME = $(CONFIG_MYAPPS_CAMERA_PROGNAME) PRIORITY = $(CONFIG_MYAPPS_CAMERA_PRIORITY) STACKSIZE = $(CONFIG_MYAPPS_CAMERA_STACKSIZE) MODULE = $(CONFIG_MYAPPS_CAMERA) MAINSRC = my_camera_main.c include $(APPDIR)/Application.mk
Make.defs
ifneq ($(CONFIG_MYAPPS_CAMERA),) CONFIGURED_APPS += mycamera endif
and my_camera_main.c
-
A simplified my_camera_main.c is shown below.
#include <nuttx/config.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <sys/time.h> #include <sys/ioctl.h> #include <time.h> #include <nuttx/video/video.h> #include <stdint.h> #include <sys/types.h> #define IMAGE_RGB_SIZE (320*240*2) #define IMAGE_FILENAME_LEN (32) #define STILL_BUFNUM (1) struct v_buffer { uint32_t *start; uint32_t length; }; typedef struct v_buffer v_buffer_t; static void free_buffer(struct v_buffer *buffers, uint8_t bufnum) { uint8_t cnt; if (buffers){ for (cnt = 0; cnt < bufnum; cnt++){ if (buffers[cnt].start){ free(buffers[cnt].start); } } free(buffers); } } int main(void){ int ret; int fd; int buffernum = 2; int cnt; struct v4l2_format fmt = {0}; struct v4l2_requestbuffers req = {0}; struct v4l2_buffer buf ={0}; struct v_buffer *buffers_still = NULL; static char s_fname[IMAGE_FILENAME_LEN]; static int s_framecount = 0; FILE *fp; ret = video_initialize("/dev/video"); if (ret != 0){ printf("ERROR: Failed to initialize video: errno = %d\n", errno); return ERROR; } fd = open("/dev/video", 0); if (fd < 0){ printf("ERROR: Failed to open video.errno = %d\n", errno); return ERROR; } fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = VIDEO_HSIZE_QVGA; fmt.fmt.pix.height = VIDEO_VSIZE_QVGA; fmt.fmt.pix.field = V4L2_FIELD_ANY; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565; ret = ioctl(fd, VIDIOC_REQBUFS, (unsigned long)&fmt); if (ret < 0){ printf("Failed to VIDIOC_REQBUFS: errno = %d\n",errno); return ERROR; } req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_USERPTR; req.count = buffernum; req.mode = V4L2_BUF_MODE_RING; ret = ioctl(fd, VIDIOC_REQBUFS, (unsigned long)&req); if (ret < 0){ printf("Failed to VIDIOC_REQBUFS: errno = %d\n", errno); return ERROR; } buffers_still = malloc(sizeof(v_buffer_t) * buffernum); if (!(buffers_still)){ printf("Out of memory for array of v_buffer_t[%d]\n", buffernum); return ERROR; } for (cnt = 0; cnt < buffernum; cnt++){ (buffers_still)[cnt].length = IMAGE_RGB_SIZE;//QVGA_RGB(320,240,2) (buffers_still)[cnt].start = memalign(32, IMAGE_RGB_SIZE); if (!(buffers_still)[cnt].start){ printf("Out of memory for image buffer of %d/%d\n",cnt, buffernum); while (cnt){ cnt--; free((buffers_still)[cnt].start); } free(buffers_still); buffers_still = NULL; return ERROR; } } for (cnt = 0; cnt < buffernum; cnt++){ memset(&buf, 0, sizeof(v4l2_buffer_t)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_USERPTR; buf.index = cnt; buf.m.userptr = (unsigned long)(buffers_still)[cnt].start; buf.length = (buffers_still)[cnt].length; ret = ioctl(fd, VIDIOC_QBUF, (unsigned long)&buf); if (ret){ printf("Fail QBUF %d\n", errno); free_buffer(buffers_still, buffernum); buffers_still = NULL; return ERROR; } } int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ret = ioctl(fd, VIDIOC_STREAMON, (unsigned long)&type); if (ret < 0){ printf("Failed to VIDIOC_STREAMON: errno = %d\n", errno); free_buffer(buffers_still, buffernum); buffers_still = NULL; return ERROR; } memset(&buffers_still, 0, sizeof(v4l2_buffer_t)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_USERPTR; ret = ioctl(fd, VIDIOC_DQBUF, (unsigned long)buffers_still); if (ret){ printf("Fail DQBUF %d\n", errno); return ERROR; } s_framecount++; if (s_framecount >= 1000){ s_framecount =1; } memset(s_fname, 0, sizeof(s_fname)); snprintf(s_fname, IMAGE_FILENAME_LEN, "%s/VIDEO/%03d.%s", "/mnt/spif", s_framecount,"RGB"); printf("FILENAME:%s\n", s_fname); fp = fopen(s_fname, "wb"); if (NULL == fp){ printf("fopen error : %d\n", errno); return ERROR; } if (buf.bytesused != fwrite((uint8_t *)buf.m.userptr, 1, (size_t)buf.bytesused, fp)){ printf("fwrite error : %d\n", errno); } fclose(fp); ret = ioctl(fd, VIDIOC_QBUF, (unsigned long)&buffers_still); if(ret){ printf("Fail QBUF %d\n",errno); return ERROR; } close(fd); free_buffer(buffers_still, STILL_BUFNUM); video_uninitialize(); return 0; }
-
So you created a new MYAPPS directory.
Did you remember to copy Makefile, Make.defs and .sdksubdirs from the examples directory and put those in your MYAPPS directory?
Like mentioned in: https://developer.sony.com/develop/spresense/docs/sdk_set_up_en.html#_add_to_a_different_directory
-
I didn't copy them, but created a directory like "tools/mkappsdir.py myapps "My Apps"".
-
This post is deleted! -
Hey, @gyps
I'm trying to reproduce your process on my side to see if I can figure out what went wrong, but I'm just thinking..
You know what is a quick way to figure out if your issue is with your own code or with the process of creating a new app is to slowly modify the actual camera example and see in which point it stops working.
-
@CamilaSouza
Thank you for your thoughts.
I changed the camera sample and was able to build it successfully. I think it may be due to the environment, not the code. I don't know the specific cause yet, but I will fill in the details as soon as I find out. -
Thank you for the feedback!
-
@CamilaSouza I have built the camera program since then, but only when enabling multi_webcam from the Kconfig file or from the OS settings, it does not work and I often get the aforementioned error.
Also If I do the following, I can enable it successfully without any problem.. /tools/config.py examples/multiwebcam