UART Daisy Chain
This article explains how to use multiple UART ports on ODROID-C2 with the Android OS.
We used three UART ports and implemented a data flow like a ring. We call it Daisy Chain.
TX port(the first UART) ⇒ RX port (the second UART) TX port ⇒ RX port (the third UART) TX port ⇒ back to the RX port of the first UART.
You have to use the latest Android 6.0.1 image version 3.6 or higher to use three UART ports simultaneously.
Hardware
☛ Download Frizing : uart_daisychain.fzz
Check J2 2×20 pins out this link
odroid-c2:hardware:expansion_connectors#j2_-_2x20_pins
PORT | PIN | |
---|---|---|
TX | RX | |
UART_A (ttyS1) | 8 | 10 |
UART_B (ttyS2) | 3 | 5 |
UART_C (ttyS3) | 32 | 26 |
Software setup
Modify Device-Tree file
You have to modify Device-Tree file to enable UART_B(ttyS2) and UART_C(ttyS3) since our stock Android image enables only one UART_A(ttyS1) port by default.
Other pins for ttyS2 and ttyS3 are used for other purpose like GPIO/I2C.
If you download our Android kernel source tree, you can find the Device-Tree file in this directory.
kernel/arch/arm64/boot/dts/meson64_odroidc2.dts
Disable I2C
diff --git a/arch/arm64/boot/dts/meson64_odroidc2.dts b/arch/arm64/boot/dts/meson64_odroidc2.dts index e6a25b0..db09b04 100755 --- a/arch/arm64/boot/dts/meson64_odroidc2.dts +++ b/arch/arm64/boot/dts/meson64_odroidc2.dts @@ -813,18 +813,6 @@ }; -&i2c_a { - status = "okay"; - - /* Hardkernel I2C RTC */ - pcf8563: pcf8563@51 { - status = "disabled"; - compatible = "nxp,pcf8563"; - reg = <0x51>; - #clock-cells = <0>; - }; -}; - &i2c_b { status = "okay";
Add UART_B and UART_C definitions
diff --git a/arch/arm64/boot/dts/meson64_odroidc2.dts b/arch/arm64/boot/dts/meson64_odroidc2.dts index e6a25b0..fd41552 100755 --- a/arch/arm64/boot/dts/meson64_odroidc2.dts +++ b/arch/arm64/boot/dts/meson64_odroidc2.dts @@ -31,6 +31,8 @@ aliases { serial0 = &uart_AO; serial1 = &uart_A; + serial2 = &uart_B; + serial3 = &uart_C; }; gpu_dvfs_tbl: gpu_dvfs_tbl { @@ -459,6 +461,32 @@ pinctrl-0 = <&a_uart_pins>; }; + uart_B: serial@c11084dc { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xc11084dc 0x0 0x18>; + interrupts = <0 75 1>; + status = "okay"; + clocks = <&clock CLK_XTAL>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&b_uart_pins>; + resets = <&clock GCLK_IDX_UART1>; + }; + + uart_C: serial@c1108700 { + compatible = "amlogic, meson-uart"; + reg = <0x0 0xc1108700 0x0 0x14>; + interrupts = <0 93 1>; + status = "okay"; + clocks = <&clock CLK_XTAL>; + clock-names = "clk_uart"; + fifosize = < 64 >; + pinctrl-names = "default"; + pinctrl-0 = <&c_uart_pins>; + resets = <&clock GCLK_IDX_UART2>; + }; + canvas { compatible = "amlogic, meson, canvas"; dev_name = "amlogic-canvas";
Compile dts to dtb
$ make odroidc2_[i2c_]defconfig KBUILD_CFLAGS_MODULE:-DMODULE # # configuration written to .config # #### make completed successfully #### [~/projects/c2/marshmallow/kernel]$ make dtbs KBUILD_CFLAGS_MODULE:-DMODULE KBUILD_CFLAGS_MODULE:-DMODULE scripts/kconfig/conf --silentoldconfig Kconfig KBUILD_CFLAGS_MODULE:-DMODULE WRAP arch/arm64/include/generated/asm/bug.h WRAP arch/arm64/include/generated/asm/bugs.h WRAP arch/arm64/include/generated/asm/checksum.h WRAP arch/arm64/include/generated/asm/clkdev.h WRAP arch/arm64/include/generated/asm/cputime.h WRAP arch/arm64/include/generated/asm/current.h WRAP arch/arm64/include/generated/asm/delay.h WRAP arch/arm64/include/generated/asm/div64.h WRAP arch/arm64/include/generated/asm/dma.h WRAP arch/arm64/include/generated/asm/emergency-restart.h WRAP arch/arm64/include/generated/asm/early_ioremap.h WRAP arch/arm64/include/generated/asm/errno.h WRAP arch/arm64/include/generated/asm/ftrace.h WRAP arch/arm64/include/generated/asm/hw_irq.h WRAP arch/arm64/include/generated/asm/ioctl.h WRAP arch/arm64/include/generated/asm/ioctls.h WRAP arch/arm64/include/generated/asm/ipcbuf.h WRAP arch/arm64/include/generated/asm/irq_regs.h WRAP arch/arm64/include/generated/asm/kdebug.h WRAP arch/arm64/include/generated/asm/kmap_types.h WRAP arch/arm64/include/generated/asm/kvm_para.h WRAP arch/arm64/include/generated/asm/local.h WRAP arch/arm64/include/generated/asm/local64.h WRAP arch/arm64/include/generated/asm/mman.h WRAP arch/arm64/include/generated/asm/msgbuf.h WRAP arch/arm64/include/generated/asm/mutex.h WRAP arch/arm64/include/generated/asm/pci.h WRAP arch/arm64/include/generated/asm/poll.h WRAP arch/arm64/include/generated/asm/posix_types.h WRAP arch/arm64/include/generated/asm/resource.h WRAP arch/arm64/include/generated/asm/scatterlist.h WRAP arch/arm64/include/generated/asm/sections.h WRAP arch/arm64/include/generated/asm/segment.h WRAP arch/arm64/include/generated/asm/sembuf.h WRAP arch/arm64/include/generated/asm/serial.h WRAP arch/arm64/include/generated/asm/shmbuf.h WRAP arch/arm64/include/generated/asm/simd.h WRAP arch/arm64/include/generated/asm/sizes.h WRAP arch/arm64/include/generated/asm/socket.h WRAP arch/arm64/include/generated/asm/sockios.h WRAP arch/arm64/include/generated/asm/switch_to.h WRAP arch/arm64/include/generated/asm/swab.h WRAP arch/arm64/include/generated/asm/termbits.h WRAP arch/arm64/include/generated/asm/termios.h WRAP arch/arm64/include/generated/asm/topology.h WRAP arch/arm64/include/generated/asm/trace_clock.h WRAP arch/arm64/include/generated/asm/types.h WRAP arch/arm64/include/generated/asm/unaligned.h WRAP arch/arm64/include/generated/asm/user.h WRAP arch/arm64/include/generated/asm/vga.h WRAP arch/arm64/include/generated/asm/xor.h WRAP arch/arm64/include/generated/asm/preempt.h WRAP arch/arm64/include/generated/asm/hash.h WRAP arch/arm64/include/generated/uapi/asm/kvm_para.h HOSTCC scripts/dtc/checks.o HOSTCC scripts/dtc/data.o SHIPPED scripts/dtc/dtc-lexer.lex.c SHIPPED scripts/dtc/dtc-parser.tab.h HOSTCC scripts/dtc/dtc-lexer.lex.o SHIPPED scripts/dtc/dtc-parser.tab.c HOSTCC scripts/dtc/dtc-parser.tab.o HOSTCC scripts/dtc/dtc.o HOSTCC scripts/dtc/flattree.o HOSTCC scripts/dtc/fstree.o HOSTCC scripts/dtc/livetree.o HOSTCC scripts/dtc/srcpos.o HOSTCC scripts/dtc/treesource.o HOSTCC scripts/dtc/util.o HOSTLD scripts/dtc/dtc CC scripts/mod/empty.o HOSTCC scripts/mod/mk_elfconfig MKELF scripts/mod/elfconfig.h CC scripts/mod/devicetable-offsets.s GEN scripts/mod/devicetable-offsets.h HOSTCC scripts/mod/file2alias.o HOSTCC scripts/mod/modpost.o HOSTCC scripts/mod/sumversion.o HOSTLD scripts/mod/modpost HOSTCC scripts/selinux/genheaders/genheaders HOSTCC scripts/selinux/mdp/mdp HOSTCC scripts/kallsyms HOSTCC scripts/pnmtologo HOSTCC scripts/conmakehash HOSTCC scripts/bin2c HOSTCC scripts/recordmcount HOSTCC scripts/sortextable DTC arch/arm64/boot/dts/meson64_odroidc2.dtb Warning (reg_format): "reg" property in /spi-gpio/spi-gpio@0 has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) Warning (avoid_default_addr_size): Relying on default #address-cells value for /spi-gpio/spi-gpio@0 Warning (avoid_default_addr_size): Relying on default #size-cells value for /spi-gpio/spi-gpio@0 #### make completed successfully (4 seconds) ####
Pre-compiled dtb file for this project. meson64_odroidc2.dtb
Install modified dtb file
You need to connect a micro-USB cable between your host PC and C2 board for fastboot protocol interface.
- host
$ sudo fastboot flash dtb out/target/product/odroidc2/obj/KERNEL_OBJ/arch/arm64/boot/dts/meson64_odroidc2.dtb
You have to edit [/storage]/internal/boot.ini file to load an alternative Kernel image
There is an alternative kernel image to switch the I2C function to UART.
#movi read boot 0 ${loadaddr} fatload mmc 0:1 ${loadaddr} Image_android
Edit ueventd.odroidc2.rc
Change the permission of ttyS2 and ttyS3 for system access.
shell@odroidc2:/ $ su root@odroidc2:/ # mount -o rw,remount / [ 1243.002784@2] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null) root@odroidc2:/ # vi /ueueventd.odroidc2.rc ueventd.rc root@odroidc2:/ # vi /ueventd.odroidc2.rc /dev/ttyS* 0666 system system
Download and build an Android app example code
Download NDK library and App project from github.
- host
$ sudo apt install git $ git clone https://github.com/codewalkerster/example-wiringPi -b odroid-c_3_uart
You can build the project with Android Studio. Refer this another example for building a NDK app.
Having a fun with GPIO on Android!
What we can see and learn
Wire connection for three UART ports in Daisy Chain loop
Type a string to send
Result of test