Wednesday 25 April 2018

HI3518 Camera Module - Part 8 - I2C

Introduction

There are a number of HI3518 camera module designs available on sites such as Aliexpress. At least some of them, including the two modules I have got, have FM24C08 (AT24C08) EEPROM chips on them. I thought I would give a go at reading the EEPROM and also see if I could hook into the I2C lines and use them to control other devices.

HI3518 Camera Module - Part 7 - Hi3518 and HC-SR501 PIR Sensor Build

Introduction

In my previous blog post I managed to work out how to read the alarm pin found on the Hi3518 camera module I have been playing with. With this worked out, I decided to combine the Hi3518 with an HC-SR501 PIR sensor so that, with a bit of software written based on the samples in the Hi3518 SDK, I could save images from the camera whenever the PIR sensor detected motion. This worked well, so I ended up putting together a waterproof enclosure to house the camera and sensor.

Tuesday 24 April 2018

HI3518 Camera Module - Part 6 - Alarm/IR-Cut/GPIO Pins

Introduction

The HI3518 camera modules come in a range of designs. One common design has, in addition to connectors for power, serial and ethernet, two connectors for controlling an IR-cut filter, and a connnector that is shared by USB, audio and and an alarm input.

The following is an image provided on an Aliexpress listing:

https://ae01.alicdn.com/kf/HTB1aRdsKVXXXXXwXpXXq6xXFXXXW/XMEYE-WiFi-IP-Camera-Module-chip-board-Audio-input-1-4-OV9712-HI3518-1-0mp-720P.jpg

To make use of the IR cut and alarm features you need to know which pins on the SOC they are connected to.

Pins

I managed to work out the following pins:

  • IR-cut (ICR/IRC): GPIO4_6/GPIO4_7
  • Day/Night sensor input: GPIO3_0
  • Alarm in: GPIO6_1

The IR-cut control uses two pins connected to a BA6208 reversible motor driver. The day/night sensor input is designed to be connected to a light sensitive resistor. The alarm input has a pull-up resistor and blocking diode.

Controlling GPIO Pins

There are two ways to control the GPIO pins: directly or using the GPIO Sysfs Interface. In both cases you will need to refer to the HI3518 datasheet .

Direct Control

To control the pins using direct register writes you will need to configure the function of the pins using the IO configuration registers (0x200F_xxxx) and then configure the GPIO functionality.

An example of setting up the IR-cut filter pins you would use:

devmem 0x200F004C 8 0x00
devmem 0x200F0048 8 0x00
devmem 0x20180400 8 0xC0

To flip the IR-cut filter in one direction you would use:

devmem 0x20180300 32 0x40

To flip the IR-cut filter back in the other direction you would use:

devmem 0x20180300 32 0x80

GPIO Sysfs Interface

Alternatively, you can use the GPIO Sysfs interface. For the GPIO Sysfs interface to work you will need to have compiled support into the kernel.

If this is the case, you can then interact with the GPIO pins through the /sys/class/gpio directory.

The first thing you need to do is work out the name of the GPIO pin in the sysfs. The GPIO sysfs interface does not use the same names as the HI3518 datasheet for the pins. In the datasheet the pins are numbered in banks of 8, but in the sysfs they are sequentially numbered.

You will need to use the following formula to work out the pin number:

sysfs_pin_number = bank_number * 8 + pin_number

For example, the alarm pin is GPIO6_1. This means it is pin 1 of bank 6.

6 * 8 + 1 = 49

Once you know this you can interact with the pin using the standard GPIO sysfs interface. For example, to set up the alarm pin you would use:

devmem 0x200F0084 8 0x0
echo 49 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio49/direction

You will notice the first command is using a direct write to the IO configuration registers. I found this to be necessary even when using the sysfs interface.

You can then read the GPIO pin state using:

cat /sys/class/gpio/gpio49/value

HI3518 Camera Module - Part 5 - Filesystem Overlay

Introduction

The HI35xx targeted version of buildroot I've been using in this series of blog posts has support for an overlay filesystem. An init script has been added to the skeleton filesystem that uses arguments provided through the kernels command line parameters to mount the overlay. When it works, the result is that the overlay gets merged into the root filesystem at boot. However, I had some trouble getting it working.

Getting the Overlay Filesystem Working

The init script has been written to look for "overlay" and "overlayfstype" arguments in the kernel command line parameters. The typical use case is that you create a jffs2 partition on the flash and then set the "overlay" argument to point to that partition and set the "overlayfstype" argument to jffs2. I gave this a go but it did not work. After spending a bit of time investigating I realised the init script was not getting run. The idea is that the init script should get run as the first process and it should in turn run /sbin/init. However, it looked as if the kernel was running /sbin/init directly and skipping the init script. The solution was to explicitly tell the kernel to run the init script using the "init" kernel command line argument.

An example of the resulting boot arguments I needed to pass to the kernel was:

setenv bootargs mem=42M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=cramfs mtdparts=hi_sfc:256K(boot),1472K(uImage),5760K(rootfs),512K(overlay) overlay=/dev/mtdblock3 overlayfstype=jffs2 init=/init

Monday 23 April 2018

HI3518 Camera Module - Part 4 - NFS Root Filesystem

Introduction

In previous blog posts on the HI3518 I used an initramfs image, which combines the root filesystem (rootfs) and the Linux kernel into a single image. Instead of doing this you can also keep the root filesystem separate from the kernel and use the command line parameters passed to the kernel at boot to tell it how to mount the root filesystem. One option for where to store the root filesystem is on a network file share (NFS).

Mounting an NFS Root Filesystem

When the HI3518 module boots the first thing that gets run is U-Boot. If you have connected to the serial port on the module, you can press CTRL+C to drop into the U-Boot prompt.

From there you can boot a kernel by:

  • Loading the kernel into RAM, usually from FLASH or TFTP
  • Setting the bootargs
  • Running the bootm command

An example of booting a kernel stored on a TFTP server and mounting an NFS root filesystem would be:

tftp 0x82000000 uImage
setenv bootargs mem=40M console=ttyAMA0,115200 root=/dev/nfs rw nfsroot=192.168.2.1:/srv/nfs/hi3518-rootfs,v3,tcp ip=192.168.2.2::192.168.2.1:255.255.255.0:camera:eth0:off
bootm 0x82000000

Notes:

  • The kernel will need to have been compiled with support for an NFS root filesystem. If using buildroot run "make linux-menuconfig" and check File systems > Network File Systems > Root file system on NFS
  • You need to set the nfsroot argument to point to the location of the NFS.
  • The kernel needs to have been compiled with support for auto configuring the network. You can confirm this by checking: Networking support > Networking options > IP: kernel level autoconfiguration
  • In this example the IP address of the HI3518 module has been set to a static address of 192.168.2.2, it is also possible to use DHCP (see the kernel configuration in the previous bullet point).
  • Attention needs to the paid to the comma separated list of NFS options specified at the end of the nfsroot argument (i.e. "v3, tcp"). Getting these wrong will cause the kernel to fail to mount the root filesystem. You may need to use different options.