Small Office / Home Office (SOHO) Server
I describe here some facts about a SN986 chip and an accompanying firmware that I have learned during development of my own BSP for the Xiaofang WiFi camera.
I'm very grateful to the fang-hacks community for giving me the first knowledge about this camera and for pointers of how to hack it.
My work however is not related to the fang-hacks project. My aim is to develop a full-stack custom firmware that could be flashed to the internal SPI flash memory replacing the stock firmware. On the other hand the aim of the fang-hacks project is to provide an application-layer overlay for an existing firmware with an ability to enable or disable stock features at any time.
There is another reason for this wiki. There are a lot of useful information about a sn986-based camera in the fang-hacks community. Details are spread across dozens of GitHub issues and comments and are highly unstructured. It seems to be very useful to put together all that info in one place and provide a table of contents and an ability to search.
In the stock firmware there is the following code in the '/etc/init.d/rcS' file:
#power on sensor /bin/gpio_ms1 -n 6 -m 1 -v 1
'gpio_ms1' binary when compiled with '-DSN9866X' flag maps gpio_ms1…gpio_ms1 on aud…aud. In other words for each call with '-n X' flag where X is a number from 3 to 7 it internally calls 'gpio_aud' binary with argument 'Y' where Y is X minus 3. So that the line above means that aud is set to high.
aud line of the SOC is going to pin24 on the camera board connector. The line from the pin goes to the seat for a resistor which is left unsoldered. There are may be other vias under the socket however but the fact that even without setting aud high the sensor works well.
The speaker is driven by the SGM4895 power amp. The shutdown controlling line “nSHDN” of the speaker is connected to aud line of the SoC. So that you need to set aud gpio to high in order to play sound.
The 3V3 bus of the wifi module is sourced from the p-channel MOSFET WP3401 (sot23, mark WP1J). The gate of the transistor is pulled down by a resistor and connected to the line gpio of the SoC. If you need to hard-reset the wifi module then you should kill all networking software, unload the driver and set gpio to high for a few seconds.
The camera fails to work with some SD cards. I tried to use two identical micro SD cards by Transcend and in both cases U-Boot failed to properly load my kernel to the RAM. U-Boot complained that the CRC sum of uImage did not match in 90 percent of attempts. Well, there were a few successful tries actually but they were very rare.
Here is what a boot log looks like on a failed attempt:
U-Boot 2011.09 (Sep 21 2018 - 10:14:17) DRAM: 64 MiB MMC: MMC: 0 SPI FLASH: 16 MB In: serial Out: serial Err: serial GPIO is high Hit any key to stop autoboot: 0 reading uImage 2986304 bytes read reading initramfs.cpio.gz 533651 bytes read ## Booting kernel from Legacy Image at 01000000 ... Image Name: Linux-126.96.36.199 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2986240 Bytes = 2.8 MiB Load Address: 00008000 Entry Point: 00008040 Verifying Checksum ... Bad Data CRC ERROR: can't get kernel image! loadkernel 0x00007FFC 0x1;bootm 0x00008000 Wrong Image Format for bootm command ERROR: can't get kernel image! firmware backup support fail.... #
The card that I tried to use was a 16GB microSDHC I, C10, U1 class card, Transcend TS16GUSD300S.
However an older 8GB Transcend card with only C6 capability worked perfectly. Also 16GB Kingston C10 cards work as well.
The methods are described in chinese manuals under the 'firmware update'
or similar directories. The SN9866x series chip supports flashing u-boot
and hw-settings directly from sd card. Note that 60x series doesn't support
this feature. All you need is to prepare an sd card with the first partition
formatted to FAT32, obtain FIRMWARE_660R_F.bin file from the build system and
put it on the first partition of sd card. Hold the reset button of the device
and power it on. You can see in the terminal window connected to the serial
line that update is started. Alternatively, you can hold ESC key in your
terminal while powering the device on. You should see the BROM's prompt:
>>. Then type
There is a method to flash u-boot over a serial line using
ymodem but I were
not successful with it. See Notes on Ymodem
See Building a Self-Burninig Firmware Image for more information.
I had succesfully flashed FIRMWARE_660R_F.bin that comes with SN986_1.50_P2P_TUTK_043a_20160308_1000 sdk. The hw-settings of this firmware are exactly the same as in stock rom.
This is how U-Boot is stored in the packed fw file and in the flash:
<offset> <size> <desccription> 00000000 4B - 32-bit unsigned, size of (u-boot + padding + crc16) 00000004 ~258K - u-boot.bin, original image produced by u-boot make 000xxxxx <16B - padding, filled w/ 0xff, sizeof(u-boot.bin+padding)%16==0 000xxxyy 4B - 32-bit unsigned, crc16/modbus of (u-boot.bin+padding)
Vendor SDK provides a 'gdb' and 'gdbserver' tools. See the last section in 'sn9866_series_linux_environment_user_guide_v1_00.pdf' documents for more information.
The version of 'gcc' provided by vendor SDK is '4.5.2'. This version supports an output of debug information in formats 'dwarf' up to 'dwarf-4' and 'stabs'.
The version of 'gdb' and 'gdbserver' is '6.8'. This version supports an output of debug information in formats 'dwarf' up to 'dwarf-2' and 'stabs'.
When debugging programs written in pure C you are free to choose any format supported by both compiler and debugger. In this case it enough just to add '-g' option to CFLAGS and LDFLAGS. By default it enables 'dwarf-2' format. In order to choose different format use instead '-gdwarf-4' or '-gstabs' for example.
Troubles arise when you want to debug a C++ programs that contain non-POD C++ classes or namespaces. To be a non-POD (POD stands for plain old data) C++ class should contains for example an explicit constructor. The issue is that DWARF-2 does not support C++ namespaces. Support for C++ namespaces was first added in DWARF-3 format. However, to compile program with '-gdwarf-3' does not solve the issue because vendor's 'gdb' does not support this format. The actual solution is to compile and link C++ programs with '-gstabs+' flag. '-gstabs+' enables 'stabs' format plus some GNU-specific extensions which are incompatible with others debuggers but may be helpful when dealing with gdb.
Suppose your program is called 'rtsp_server' and it should be executed with arguments '-W 640 -H 480 -Q 10 -b 4096 -a'. Suppose you have a local copy of your target's root filesystem in '~/sdk/rootfs' directory on the host machine and toolchan in '~/sdk/toolchain' directory. In order to debug program from the remote host machine you should start gdbserver on the target machine:
# gdbserver :2000 rtsp_server -W 640 -H 480 -Q 10 -b 4096 -a
run gdb on the host side and connect to the target:
$ export PATH="~/sdk/toolchain/bin:$PATH" $ arm-linux-gdb --args rtsp_server -W 640 -H 480 -Q 10 -b 4096 -a > set sysroot '~/sdk/rootfs' > target remote 192.168.1.101:2000 > breakpoint main.cc:main > continue
One can automate previous steps by creating gdb init script file called '.gdbinit' in the current (working) directory on the host side:
$ cat > .gdbinit <<-EOF set sysroot '~/sdk/rootfs' target remote 192.168.1.101:2000 continue EOF
Here is what I did to compile 1.29:
tar xf busybox-1.22.1.tar.bz2 tar xf busybox-1.29.1.tar.bz2 cd busybox-1.22.1/configs cp ~/develop/xiaofang/sdk/SN986_1.60_QR_Scan_019a_20160606_0951/snx_sdk/filesystem/busybox-1.22.1/src/configs/sn9866x_defconfig . export PATH="/home/student/develop/xiaofang/sdk/SN986_1.60_QR_Scan_019a_20160606_0951/snx_sdk/toolchain/crosstool-4.5.2/bin:$PATH" make CROSS_COMPILE=arm-linux- sn9866x_defconfig cd ../busybox-1.29.1/ cp ../busybox-1.22.1/.config . make CROSS_COMPILE=arm-linux- oldconfig make CROSS_COMPILE=arm-linux- menuconfig make CROSS_COMPILE=arm-linux- -j5 diff -ru busybox-1.22.1 ~/develop/xiaofang/sdk/SN986_1.50_P2P_TUTK_043a_20160308_1000/snx_sdk/filesystem/busybox-1.22.1/src/ > diff_1.22.1_snx.txt
This is a list of applications which are ready to be run on the camera. Basically these applications are known programs configured and compiled by someone for the Xiaofang camera.
May 16, 2008
This was a simple fix, but took a while to figure out because of less than
informative error messages. While trying to transfer a file (a Linux kernel)
using minicom and ymodem we got a protocol failed error when using one machine
(my laptop) and it worked on another. After checking versions of minicom,
serial adapter drivers, ymodem config, etc… we noticed that minicom is setup to
use /usr/bin/rb and /usr/bin/sb for ymodem comm. Turns out, they weren’t
installed! On Debian (*buntu) the lrzsz package is what is needed. A quick
apt-get install lrzsz and we were up and running.
Gotta love cryptic error messages!
The following command prints the version numbers of uClibc library in use:
$ printf '#include <features.h>\n__UCLIBC_MAJOR__ __UCLIBC_MINOR__ __UCLIBC_SUBLEVEL__\n' | ./crosstool-4.5.2/bin/arm-linux-gcc -E - | tail -1