Skip to main content

NXP FRDM i.MX 93 Board TEVS Camera Usage Guide

πŸš€ Introduction​

This article guides you on how to get started using TechNexion camera modules on the NXP FRDM i.MX 93 board.


πŸ“Έ Supported Camera Modules​

Camera SeriesProducts
TEVS
TEVS-AR0144
TEVS-AR0145
TEVS-AR0234
TEVS-AR0521
TEVS-AR0522
TEVS-AR0821
TEVS-AR0822
TEVS-AR1335
Camera Sensor Comparison

πŸ”§ Hardware Setup Instructions​

Connect the Adapter Board and Camera Cable​

To set up the TechNexion camera, connect the adapter board and camera cable to the FPC 22-Pin connector on the board as shown in the image below.

warning

The RPI 22-pin connector on the adapter board has two directions. Please make sure the pin definition matches the adapter board.


🧰 Camera Installation Instructions​

We provide two methods to install camera drivers and device tree blobs. Depending on your needs, you can choose the most suitable method. If you are new to this, we recommend starting with Method 1. If you have a custom Linux kernel and device tree, you can try Method 2.


Method 1 - Using TechNexion Pre-built image​

Prepare Yocto demo image for testing TechNexion camera​

To test TechNexion TEVS Series cameras, you need a demo image that includes the required Device Tree Blobs (DTBs) and camera drivers. Pre-built demo images are available for download from TechNexion's server.

πŸ”— Supported Release List (Instructions for IMX93-FRDM)

Flashing the Image​

You can flash the image to an SD Card using the following methods:

Boot Mode

Make sure your board is set to boot from SD card or eMMC.
Refer to the official NXP guide πŸ”— Getting Started with the FRDM-IMX93

Use balenaEtcher to write the image to your SD card:

πŸ”—


Method 2 - Build custom Linux kernel with camera driver​

  1. Download the camera driver and device tree blobs.

    $ git clone https://github.com/TechNexion-Vision/nxp_evk_camera.git -b tn-imx_6.12.20_2.0.0-stable
  2. Copy files to your kernel source code.

    $ cd nxp_evk_camera/

    ~/nxp_evk_camera$ cp arch/arm64/boot/dts/freescale/imx93-11x11-frdm-tevs-rpi22.dtso <fetch_kernel_folder>/arch/arm64/boot/dts/freescale/
  3. Modify the Makefile to add the driver.

    $ cd <fetch_kernel_folder>/drivers/media/i2c/
    ~/<fetch_kernel_folder>/drivers/media/i2c/$ vi Makefile

    Add this line to the Makefile.

    obj-$(CONFIG_VIDEO_TEVS) += tevs/
  1. Modify Kconfig to add camera configuration.

    ~/<fetch_kernel_folder>/drivers/media/i2c/$ vi Kconfig

    Add this part under "Camera sensor devices" menu in Kconfig.

    config VIDEO_TEVS
    tristate "TechNexion TEVS sensor support"
    depends on OF
    depends on GPIOLIB && I2C && VIDEO_V4L2_SUBDEV_API
    depends on MEDIA_CAMERA_SUPPORT
    select V4L2_FWNODE
    default y
    help
    This is a Video4Linux2 sensor driver for the TechNexion
    TEVS camera sensor with a MIPI CSI-2 interface.
Build Environment
  1. Modify the Makefile to add the device tree.

    $ cd <fetch_kernel_folder>/arch/arm64/boot/dts/freescale/
    ~/<fetch_kernel_folder>/arch/arm64/boot/dts/freescale/$ vi Makefile

    Add these lines to the Makefile.

    imx93-11x11-frdm-tevs-rpi22-dtbs := imx93-11x11-frdm.dtb imx93-11x11-frdm-tevs-rpi22.dtbo
    dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm-tevs-rpi22.dtb
Build Environment
  1. Compile the kernel and module driver.

    Finally, you can start compiling your new Image files, then copy and replace the Image files on the SD card.


πŸ“Έ Camera Testing Instructions​

Specify Camera DTBO in U-Boot​

  1. Connect the debug console cable to the baseboard (via USB-C).

  2. Power on the board and interrupt the boot process. Keep pressing Enter when the following message appears: Hit any key to stop autoboot:

  3. Specify the appropriate device tree for your camera using the fdtfile environment variable in U-Boot:

u-boot=> setenv fdtfile imx93-11x11-frdm-tevs-rpi22.dtb
  1. Save and continue the boot process:
u-boot=> saveenv
u-boot=> boot

πŸŽ›οΈ Setup the media controller before camera streaming​

To verify that the camera has been properly connected and linked, use the media-ctl command:

$ media-ctl -p

This will display media controller information, such as:


Media controller API version 6.12.34

Media device information
------------------------
driver mxc-isi
model FSL Capture Media Device
serial
bus info platform:4ae40000.isi
hw revision 0x0
driver version 6.12.34

Device topology
- entity 1: crossbar (3 pads, 3 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
<- "csidev-4ae00000.csi":1 [ENABLED,IMMUTABLE]
pad1: Sink
<- "mxc_isi.output":0 [ENABLED,IMMUTABLE]
pad2: Source
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:lim-range]
-> "mxc_isi.0":0 [ENABLED,IMMUTABLE]

- entity 5: mxc_isi.0 (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
compose.bounds:(0,0)/1920x1080
compose:(0,0)/1920x1080]
<- "crossbar":2 [ENABLED,IMMUTABLE]
pad1: Source
[stream:0 fmt:YUV8_1X24/1920x1080 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1920x1080
crop:(0,0)/1920x1080]
-> "mxc_isi.0.capture":0 [ENABLED,IMMUTABLE]

- entity 8: mxc_isi.0.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "mxc_isi.0":1 [ENABLED,IMMUTABLE]

- entity 16: mxc_isi.output (1 pad, 1 link)
type Node subtype V4L flags 0
pad0: Source
-> "crossbar":1 [ENABLED,IMMUTABLE]

- entity 23: csidev-4ae00000.csi (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:smpte170m xfer:709 ycbcr:601 quantization:lim-range]
<- "tevs 2-0048":0 []
pad1: Source
[stream:0 fmt:UYVY8_1X16/1920x1080 field:none colorspace:smpte170m xfer:709 ycbcr:601 quantization:lim-range]
-> "crossbar":0 [ENABLED,IMMUTABLE]

- entity 28: tevs 2-0048 (1 pad, 1 link, 0 routes)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[stream:0 fmt:UYVY8_1X16/640x480@1/60 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/640x480
crop:(0,0)/640x480]
-> "csidev-4ae00000.csi":0 []

Showing the output as an image can make it easier to understand.

note

If you want to see the graph, you can use the --print-dot option.

$ media-ctl --print-dot > graph.dot
$ dot -Tpng graph.dot > graph.png
# If you don't have the tool, you need to install it as follows.
# sudo apt-get install -y graphviz.

We can observe that the link between β€˜tevs 2-0048 ’ to β€˜csidev-4ae00000.csi ’ is a dotted line. This means it's not available.

You need to enable the link between the TEVS and CSI device.

$ media-ctl -l "'tevs 2-0048':0 -> 'csidev-4ae00000.csi':0 [1]"

Set the resolution and format of all media entities to match the camera's output. This means all components in the media pipeline must align with the camera's output settings.

Use the v4l2-ctl command to check the camera's supported formats, resolutions, and frame intervals.

# formats
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-mbus-codes
ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE (pad=0,stream=0)
0x200f: MEDIA_BUS_FMT_UYVY8_1X16
0x300a: MEDIA_BUS_FMT_SGRBG10_1X10
0x3011: MEDIA_BUS_FMT_SGRBG12_1X12

# resolutions
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-framesize code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE (pad=0,stream=0)
Size Range: 640x480 - 640x480
Size Range: 1280x720 - 1280x720
Size Range: 1280x960 - 1280x960
Size Range: 1920x1080 - 1920x1080
Size Range: 2560x1440 - 2560x1440
Size Range: 2592x1944 - 2592x1944

# frame interval of resolution
$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=640,height=480,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.008s (120.000 fps)

$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1280,height=720,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)

$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1280,height=960,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)

$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=1920,height=1080,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.017s (60.000 fps)

$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=2560,height=1440,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.031s (32.000 fps)

$ v4l2-ctl -d /dev/v4l-subdev3 --list-subdev-frameintervals width=2592,height=1944,code=0x200f
ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL (pad=0,stream=0)
Interval: 0.042s (24.000 fps)

Set resolution to 1280Γ—720 for example.

$ media-ctl -V "'crossbar':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'mxc_isi.0':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'csidev-4ae00000.csi':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"
$ media-ctl -V "'tevs 2-0048':0 [fmt:UYVY8_1X16/1280x720 field:none colorspace:srgb xfer:srgb ycbcr:601]"

πŸŽ₯ Start Camera Video Stream via GStreamer​

🎬 Launch GStreamer Pipeline​

Specify the capture device you just obtained and start GStreamer to get the video stream on screen.
Replace <res_w> and <res_h> with your selected resolution and screen dimensions:

$ gst-launch-1.0 v4l2src device=/dev/video0 ! \
"video/x-raw, format=YUY2, width=<res_w>, height=<res_h>" ! \
waylandsink sync=false

βœ… Check Media Controller​

We can use media-ctl -p to check the media controller again after setting the resolution and media link as shown below:

Media controller API version 6.12.34

Media device information
------------------------
driver mxc-isi
model FSL Capture Media Device
serial
bus info platform:4ae40000.isi
hw revision 0x0
driver version 6.12.34

Device topology
- entity 1: crossbar (3 pads, 3 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev0
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
<- "csidev-4ae00000.csi":1 [ENABLED,IMMUTABLE]
pad1: Sink
<- "mxc_isi.output":0 [ENABLED,IMMUTABLE]
pad2: Source
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
-> "mxc_isi.0":0 [ENABLED,IMMUTABLE]

- entity 5: mxc_isi.0 (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev1
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none
compose.bounds:(0,0)/1280x720
compose:(0,0)/1280x720]
<- "crossbar":2 [ENABLED,IMMUTABLE]
pad1: Source
[stream:0 fmt:YUV8_1X24/1280x720 field:none colorspace:jpeg xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1280x720
crop:(0,0)/1280x720]
-> "mxc_isi.0.capture":0 [ENABLED,IMMUTABLE]

- entity 8: mxc_isi.0.capture (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video0
pad0: Sink
<- "mxc_isi.0":1 [ENABLED,IMMUTABLE]

- entity 16: mxc_isi.output (1 pad, 1 link)
type Node subtype V4L flags 0
pad0: Source
-> "crossbar":1 [ENABLED,IMMUTABLE]

- entity 23: csidev-4ae00000.csi (2 pads, 2 links, 0 routes)
type V4L2 subdev subtype Unknown flags 0
device node name /dev/v4l-subdev2
pad0: Sink
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
<- "tevs 2-0048":0 [ENABLED]
pad1: Source
[stream:0 fmt:UYVY8_1X16/1280x720 field:none]
-> "crossbar":0 [ENABLED,IMMUTABLE]

- entity 28: tevs 2-0048 (1 pad, 1 link, 0 routes)
type V4L2 subdev subtype Sensor flags 0
device node name /dev/v4l-subdev3
pad0: Source
[stream:0 fmt:UYVY8_1X16/1280x720@1/60 field:none colorspace:srgb xfer:srgb ycbcr:601 quantization:full-range
crop.bounds:(0,0)/1280x720
crop:(0,0)/1280x720]
-> "csidev-4ae00000.csi":0 [ENABLED]

🚨 Troubleshooting​

Verify Camera Initialization​

Use dmesg to check if the TEVS camera module was initialized correctly.

  $ dmesg -t | grep tevs
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42800000/csi@4ae00000: Fixed dependency cycle(s) with /soc@0/bus@42000000/i2c@42530000/tevs@48
/soc@0/bus@42000000/i2c@42530000/tevs@48: Fixed dependency cycle(s) with /soc@0/bus@42800000/csi@4ae00000
tevs 2-0048: tevs_probe() device node: tevs@48
tevs 2-0048: Version:25.3.0.2
tevs 2-0048: Product:TEVS-AR0144, HeaderVer:3, MIPI_Rate:800
tevs 2-0048: Chip ID: 0x0000
tevs 2-0048: probe success

Confirm Board and Camera DTB​

Check if the correct DTB is loaded with a matching camera model.

  $ dmesg -t | grep -i model
Machine model: NXP FRDM-IMX93

Check Available Video Devices​

Verify that the video devices are available.

  $ v4l2-ctl --list-device

Example output:

mxc-isi-cap (platform:4ae40000.isi):
/dev/video0
/dev/video1
/dev/media0