12/30/2020

Android PWM 과 GPIO 설정 및 Control Test App

1. Device Tree 관련설정 
 

Device Tree 기본문법이해 

Device Tree 기반 부팅방법

아래설정은 i.MX8에서 BSP에서 LSIO PWM 관련설정이 없어 어쩔수 없이 Datasheet를 보고 직접 만들어서 추가하였으며, MIPI에서 사용하는 PWM과 같이 i.mx27로 사용결정

$ vi *dts


/* PWM 사용을 위해서 PWM 사용과 GPIO PINMUX 설정 
iomuxc가 label 이므로  &iomuxc 사용 (iomuxc: pinctrl)  
*/

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;

	/* PINMUX 를 PWM과 GPIO 변경 
	*  IMX8QXP_UART1_RX  : PWM1
	*  IMX8QXP_UART1_TX  : GPIO 
	*/
	pinctrl_lppwm1: lppwm1grp {
		fsl,pins = <
			IMX8QXP_UART1_RX_LSIO_PWM1_OUT					0x00000020
			IMX8QXP_UART1_TX_LSIO_GPIO0_IO21				0x00000020		
		>;
	};
	/* PINMUX 를 PWM과 GPIO 변경 
	*  IMX8QXP_UART1_RTS_B  : PWM2 
	*  IMX8QXP_UART1_CTS_B  : GPIO
	*/
	pinctrl_lppwm2: lppwm2grp {
		fsl,pins = <
			IMX8QXP_UART1_RTS_B_LSIO_PWM2_OUT	0x00000020		
			IMX8QXP_UART1_CTS_B_LSIO_GPIO0_IO24	0x00000020	
		>;
	};	

};

/* MIPI의 PWM 부분 삭제 전부 label이므로 &적용  */

/delete-node/ &pwm_mipi_lvds0;
/delete-node/ &pwm_mipi_lvds1;

/delete-node/ &lvds_backlight0;
/delete-node/ &lvds_backlight1;

/* UART1 과 PWM PINMUX 충돌하여 미사용로 변경  */
&lpuart1 {
    status = "disabled";
};


/* 
    LSIO PWM 관련정의가 없어서 Datasheet를 보고 각 Address에 맞춰 정의
    MIPI도 i.MX6도 PWM을 im27-pwm 사용하여 나 또한 이것으로 사용하기로 결정 
    lsio_subsys를 main으로 넣기로함 

    / { 
    .....
     }
*/

/ {
	
	lsio_subsys: bus@5d000000 {
		compatible = "simple-bus";
		#address-cells = <1>;
		#size-cells = <1>;
		ranges = <0x5d000000 0x0 0x5d000000 0x1000000>,
			<0x08000000 0x0 0x08000000 0x10000000>;

/* 
i.MXQXP의 LSIO Datasheet 관련부분을 보면 상위 Memory Map Range 영역을 설정  
현재 child's address 1 , size 1만 존재 parent address가 없음 총 4개로 memory mapped io로 하는 것으로 생각됨 (추측)
- Physical Start 0x5d000000 0x0 
- Physical End   0x5d000000+0x1000000
- Virtual  Start 0x08000000 0x0
- Virtual  End   0x08000000+0x10000000
*/

		pwm1_lsio: pwm@5d010000 {
			compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
			reg = <0x5d010000 0x1000>;
			clocks = <&pwm1_lpcg 0>,
				 <&pwm1_lpcg 1>,
				 <&pwm1_lpcg 2>;				
			pinctrl-names = "default";
			pinctrl-0 = <&pinctrl_lppwm1>;					 
			clock-names = "per", "ipg","32k";
			assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
			assigned-clock-rates = <24000000>
			#pwm-cells = <2>
			power-domains = <&pd IMX_SC_R_PWM_1>;
			status = "okay";
		};	

		pwm2_lsio: pwm@5d020000 {
			compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
			reg = <0x5d020000 0x1000>;
			clocks = <&pwm2_lpcg 0>,
				 <&pwm2_lpcg 1>,
				 <&pwm2_lpcg 2>;				
			pinctrl-names = "default";
			pinctrl-0 = <&pinctrl_lppwm2>;					 
			clock-names = "per", "ipg","32k";
			assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
			assigned-clock-rates = <24000000>;
			#pwm-cells = <2>;
			power-domains = <&pd IMX_SC_R_PWM_2>;
			status = "okay";
		};	

	};

//#pwm-cells   pwm 기반으로 사용하는 다른 driver에서 이를 사용  (backlight) 
https://www.kernel.org/doc/Documentation/devicetree/bindings/pwm/pwm.txt
https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/pwm/pwm.txt

};


2. PWM Driver 기본구조분석

PWM Driver 기본구조 및 sys filesystem 사용법

  • PWM Driver (imx27)
  1. pwmchip_add()
  2. pwmchip_remove()

i.MX27 PWM Driver 


  • PWM 기반의 Driver (Back light)
  pwm_request()  기반으로 구현


2.1 sys filesystem PWM-TEST 

상위 imx27 Driver가 설정과 Clock 설정한 후 아래와 같이 설정가능하지만, 권한이 문제발생하여 아래와 같이 su 를 이용하여 root로 테스트 

  • PWM0 생성 및 기본제어방법
GPIO와 유사하게 export로 설정후 pwm0을 생성되어 자동마운트 된후 실제적인 설정진행 
  1. period : 주기를 설정 ( ns 단위) 
  2. duty_cycle: positive pulse width  (ns 단위) 
$ su 
# id
uid=0(root) gid=0(root) groups=0(root),1007(log),3009(readproc) context=u:r:su:s0

$ echo 0 > /sys/class/pwm/pwmchip0/export   // pwm0 생성됨 
$ echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period
$ echo 500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
$ echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
상위 설정은 1KHz의 주기를 가지고 Duty 즉, High Pulse는 반으로 설정 

아래와 같이 50Hz 주기 설정 후 half duty로 변경 및 다양한 duty 테스트 
//50Hz 20ms 주기 설정  
$ echo 20000000 > /sys/class/pwm/pwmchip0/pwm0/period 

//10000us (10ms) (half) Positive Pulse 
$ echo 10000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

//1000 us (1ms)
$ echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

//1250 us (1.25ms) 
$ echo 1250000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

//1500 us (1.5ms)
$ echo 1500000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

//1750 us (1.75ms) 
$ echo 1750000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

//2000 us (2.ms)
$ echo 2000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle 

PWM 관련설정 사항 

상위는 Android의 기본 shell에서 동작않아, 이를 해결하기 위해서 init.rc 에서 export 와 권한설정하기로 결정. 



2.2 Android init.hardware.rc 문법 수정  

Linux로 말하면, init script 이며, 이는 이부분 각 service와 초기화 관련부분을 담당  
  1. init.rc 
  2. init.%hardware%.rc

  • Android Init 관련문법 복습
Init 문법을 보면 크게 Action 과 Service 와 command 나누어지며, 다음과 같이 동작한다. 
//Action 기능 이며, trigger 와 command를 다양하게 지원
on <trigger> [&& <trigger>]*
   <command>
   <command>
   <command>
   
//Service 기능이며 관련 option은 아래 링크 참조      
service <name> <pathname> [ <argument> ]*
   <option>
   <option>
   ...     

Android init 문법의 세부내용 Manual 

  • Android의 기본 init.rc 확인 
기본 init.rc 위치 및 설정확인하였지만, 직접수정하지 않는 것이 좋을 것 같아 이부분은 그대로 유지 
$ vi system/core/rootdir/init.rc  // 
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

# Cgroups are mounted right before early-init using list from /etc/cgroups.json
on early-init
    # Disable sysrq from keyboard
    write /proc/sys/kernel/sysrq 0

    # Set the security context of /adb_keys if present.
    restorecon /adb_keys

    # Set the security context of /postinstall if present.
    restorecon /postinstall

    mkdir /acct/uid
.........    

$ cat out/target/product/mek_8q/root/init.rc   

  • i.MX8을 위한 init.hardware.rc 에 수정
각 hardware를 위한 init.rc 부분에 아래와 pwm관련설정부분을 추가를 해준다. 
상위 문법을 보면 trigger 로 조건이 맞을 경우 command로 action이 되어진다. 
$ vi ./device/fsl/imx8q/mek_8q/init.imx8qxp.rc
......
    # jhlee /sys filesystem mount가 된 경우 실행 
on property:sys.boot_completed=1
    #jhlee for PWM1/2  root 권한으로 실행됨  
    chmod 0777 /sys/class/pwm/pwmchip0
    chmod 0222 /sys/class/pwm/pwmchip0/export
    chmod 0222 /sys/class/pwm/pwmchip0/unexport
    chmod 0777 /sys/class/pwm/pwmchip1
    chmod 0222 /sys/class/pwm/pwmchip1/export
    chmod 0222 /sys/class/pwm/pwmchip1/unexport

    # PWM1 50Hz 20ms / 10ms (half)
    write /sys/class/pwm/pwmchip0/export 0
    write /sys/class/pwm/pwmchip0/pwm0/enable 1
    write /sys/class/pwm/pwmchip0/pwm0/period 20000000
    write /sys/class/pwm/pwmchip0/pwm0/duty_cycle 10000000

    # PWM2 50Hz 20ms / 10ms (half)
    write /sys/class/pwm/pwmchip1/export 0
    write /sys/class/pwm/pwmchip1/pwm0/enable 1
    write /sys/class/pwm/pwmchip1/pwm0/period 20000000
    write /sys/class/pwm/pwmchip1/pwm0/duty_cycle 10000000

    chmod 0666 /sys/class/pwm/pwmchip0/pwm0/period
    chmod 0666 /sys/class/pwm/pwmchip0/pwm0/duty_cycle
    chmod 0666 /sys/class/pwm/pwmchip0/pwm0/enable

    chmod 0666 /sys/class/pwm/pwmchip1/pwm0/period
    chmod 0666 /sys/class/pwm/pwmchip1/pwm0/duty_cycle
    chmod 0666 /sys/class/pwm/pwmchip1/pwm0/enable

    # GPIO UART1_TX 21
    write /sys/class/gpio/export 21
    write /sys/class/gpio/gpio21/direction "out"
    write /sys/class/gpio/gpio21/value 1

    # GPIO UART1_CTS_B 24
    write /sys/class/gpio/export 24
    write /sys/class/gpio/gpio24/direction "out"
    write /sys/class/gpio/gpio24/value 1

    chmod 0666 /sys/class/gpio/export
    chmod 0666 /sys/class/gpio/unexport
    chmod 0666 /sys/class/gpio/gpio21/direction
    chmod 0666 /sys/class/gpio/gpio21/value
    chmod 0666 /sys/class/gpio/gpio24/direction
    chmod 0666 /sys/class/gpio/gpio24/value
....    

$ cat out/target/product/mek_8q/vendor/etc/init/hw/init.freescale.imx8qxp.rc   // 빌드 후 실제 적용되어되었는지확인 

init.rc script이 root기반으로 동작되기 때문에 초반에 chmod를 하는것은 의미가 없다 

2.3 PWM ueventd.rc 문법 수정  

처음 착각했던 것이 export를  값을 넣어주면, uevent가 발생하여 관련부분이 pwm이 생기면서 이 script를 이용하여 permission을 변경할 줄 알았다. 

  1. ueventd.rc 
  2. ueventd.%hardware%.rc 



  • ueventd.rc 설정 
아래설정으로 하면 될 줄 알았는데, 실패했지만, 될 것이라고 생각되어 이곳에 기록하며 추후 재확인 
$ vi ./device/fsl/imx8q/mek_8q/ueventd.freescale.rc
# /sys file은 entry 5개 (주의)
# /dev file은 entry 4개 
# jhlee for pwmchip0 pwm0
/sys/devices/platform/bus@5d000000/5d010000.pwm/pwm/pwmchip0/pwm0  enable 0666 system system
/sys/devices/platform/bus@5d000000/5d010000.pwm/pwm/pwmchip0/pwm0  period 0666 system system
/sys/devices/platform/bus@5d000000/5d010000.pwm/pwm/pwmchip0/pwm0  duty_cycle 0666 system system
/sys/devices/platform/bus@5d000000/5d010000.pwm/pwm/pwmchip0/pwm0  polarity   0666 system system

# jhlee for pwmchip1 pwm0
/sys/devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip1/pwm0  enable 0666 system system
/sys/devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip1/pwm0  period 0666 system system
/sys/devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip1/pwm0  duty_cycle 0666 system system
/sys/devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip1/pwm0  polarity   0666 system system

# jhlee for pwm (0/1/2/3)
/sys/class/pwm/pwmchip*      export     0666 system system
/sys/class/pwm/pwmchip*      unexport   0666 system system
/sys/class/pwm/pwmchip*      enable     0666 system system
/sys/class/pwm/pwmchip*      period     0666 system system
/sys/class/pwm/pwmchip*      duty_cycle 0666 system system
/sys/class/pwm/pwmchip*      polarity   0666 system system
$ cat out/target/product/mek_8q/vendor/ueventd.rc  // /sys file은 entry 5개 사용 주의 
[    5.133113] ueventd: /vendor/ueventd.rc: 44: /sys/ lines must have 5 entries
[    5.140349] ueventd: /vendor/ueventd.rc: 45: /sys/ lines must have 5 entries
[    5.147472] ueventd: /vendor/ueventd.rc: 46: /sys/ lines must have 5 entries
[    5.154572] ueventd: /vendor/ueventd.rc: 47: /sys/ lines must have 5 entries

ueventd.rc pwm 과 gpio 관련예제 


ueventd 별도정리 필요 

  • android ueventd Main 소스 

  • ueventd.rc Parser 소스 
ParseConfig (ueventd.rc ) -> AddSingleLineParser->ParsePermissionsLine (각 sys or dev parsing 후 permision 설정 )
(sys 와 dev는 entry 갯수가 다르며, 이는 Cold boot를 위한 것이므로, Kernel에서 미리 설정되어야 한다)

  • ueventd의 handler 소스 
실제동작을 LOG_UEVENTS로 DEBUG 가능 

  • ueventd debug 방법 
상위 ueventd 소스를 보면 LOG_UEVENTS 설정에 따라 LOG를 볼 수 있으며 이를 강제로 선언하여 Debug를 한다. 

$ vi ./system/core/init/Android.mk 
.......
init_options += -DLOG_UEVENTS=1 \
    -DSEPOLICY_VERSION=$(POLICYVERS)
.......      


ueventd의 selinux 설정 


PWM의 sysfs의 구조 


  • root 권한으로  shell 에서 pwm 위치 찾기 

$ for i in /sys/class/pwm*/pwmchip*/pwm* ; do ls -l $i; cat $i; done
total 0
-r--r--r-- 1 root root 4096 2021-01-20 07:16 capture
-r--r--r-- 1 root root 4096 2021-01-20 07:16 consumers
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 duty_cycle
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 enable
-r--r--r-- 1 root root 4096 2021-01-20 07:16 output_type
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 period
-rw-r--r-- 1 root root 4096 2021-01-20 07:16 polarity
drwxr-xr-x 2 root root    0 2021-01-20 07:16 power
-r--r--r-- 1 root root 4096 2021-01-20 07:16 suppliers
-rw-r--r-- 1 root root 4096 2021-01-20 07:16 uevent
cat: /sys/class/pwm/pwmchip0/pwm0: Is a directory
total 0
-r--r--r-- 1 root root 4096 2021-01-20 07:17 capture
-r--r--r-- 1 root root 4096 2021-01-20 07:17 consumers
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 duty_cycle
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 enable
-r--r--r-- 1 root root 4096 2021-01-20 07:17 output_type
-rw-rw-rw- 1 root root 4096 2021-01-20 03:33 period
-rw-r--r-- 1 root root 4096 2021-01-20 07:17 polarity
drwxr-xr-x 2 root root    0 2021-01-20 07:17 power
-r--r--r-- 1 root root 4096 2021-01-20 07:17 suppliers
-rw-r--r-- 1 root root 4096 2021-01-20 07:17 uevent
cat: /sys/class/pwm/pwmchip1/pwm0: Is a directory

$ ls -alh /sys/class/pwm/          //ueventd.*.rc에 추가하 위해서 정확한 PATH 알기 (아래는 강제로 권한변경된 상태)
...
lrwxrwxrwx  1 root root 0 2020-12-30 06:06 pwmchip0 -> ../../devices/platform/bus@5d000000/5d010000.pwm/pwm/pwmchip0
lrwxrwxrwx  1 root root 0 2020-12-30 06:06 pwmchip1 -> ../../devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip1


2.4 SELinux 

  • i.MX8의 의 SElinux 문제발생 (동작안됨)
상위에서 write /sys/class/pwm/pwmchip0/export 0 할 경우 uevent가 발생할것이며, 아래와 같이 ls를 했을 경우 access 문제발생 

mek_8q:/sys/class/pwm/pwmchip0 $ ls -alh
drwxr-xr-x 3 root root    0 1970-01-01 00:00 .[  175.487816] type=1400 audit(1609308473.916:27): avc: denied { getattr } for comm="ls" path="/sys/devices/platform/bus@5d000000/5d020000.pwm/pwm/pwmchip0/uevent" dev="sysfs" ino=34845 scontext=u:r:shell:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1

  • BoardConfig.mk 관련수정
SElinux 를 허용모드(permissive) 강제로 변경후 별도의 추가 *.te를 할 필요가 없으므로 이를 간단히 해결 
$ find . -name BoardConfig.mk  // 기본위치파악 
device/Vendor/ARCH/BoardName/BoardConfig.mk

$ vi ./device/fsl/imx8q/mek_8q/BoardConfig.mk    // i.MX8 관련수정 

# NXP의 기본 Hardware 설정 
# NXP default config
BOARD_KERNEL_CMDLINE := init=/init androidboot.hardware=freescale firmware_class.path=/vendor/firmware loop.max_part=7

#
# permissive 추가 
BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

상위와 같이 permissive 로 변경할 경우, 상위와 같이 error는 발생하며, 경고는 하지만, 문제가 되지 않음 
하지만, 이는 개발시에는 사용해야하면, 제품 출하시에는 반드시 관련부분을 수정해야한다. 

Android SELinux (일반 Linux의 SELinux의 사용법과 좀 다름)

SELinux 관련부분 정리 

3. Android SDK/NDK/PDK 구분 

  • SDK
Software Development Kit 로 순수 Application 입장이라고 생각하면 되겠으며, Java기반으로 Android Studio에서 제작가능하며, Google 제공하는 SDK에서 개발가능 

Google에서 공식적인 제공하는 SDK 설치 한 후 이와 관련된 API 를 이용하여 사용자가 원할 경우 Custom으로 제작도 가능한 것으로 파악된다. 

  • NDK
Native Development Kit로 주로 C/C++로 기반으로 구현하며, JNI /HAL 을 제공하며,  Library만 구성을 하여도 Application에서 이를 가져다가 사용가능하다. 
Google에서 제공하는 NDK를 설치 한 후 이를 Build를 진행해야한다. 
 
  • PDK
Product(Platform) Development Kit로  SDK 와 NDK 의 동시에 사용할 경우를 말한다. 
가장 쉬운예제가 JNI기능을 포함 SDK Program이며, 이는 PDK라고 불리운다. 
상위에서 제공한 SDK 와 NDK를 설치한 후 이를 기반으로 작성가능하다. 


NDK/PDK기반의 예제 

상위를 간단히 분석을하면, Target의 /system/lib 에 본인이 구현한 library를 넣고 , 이를 기반으로 SDK에서 Class를 Loading하여 사용하면된다. 

Android Studio를 이용하거나, ASOP에서 직접 빌드를 하면된다. 


3.1 PWM PDK 작성방법 

Android Studio에서 Native C++ 로 기반으로 PDK 구현할 경우 문제는 SELinux의 domain 이 untrusted_app로 생성되며, 이를 허용하지 않아 
상위처럼 강제로 허용모드로 변경해야 했지만, Vendor입장에서 상위 untruested_app의 domain을 변경해서 사용해야 할 것 같다. 

  • Android Source 소스 수정 
  1. ASOP_SETTING : ASOP에서 직접 수정(Access 문제) 후 이를 Build 후 관련 Image 생성 
    상위 2.2 init.hardware.rc 관련부분 수정 (init.xxxx.rc 상위 이름 참조 chmod로 변경)
    상위 2.4 SELinux 의 Permissive , 즉 허용모드 변경   ( 접근허용으로 변경)

  • Android Studio 기반으로  Native C++  생성 
  1. Android Studio-> New -> Native C++ 선택 후 기본 생성 
  2. cpp -> CMakeLists.txt  변경 (기존 예제인 C++ 삭제)
  3. cpp -> GpioCtr.c / GpioCtr.h 추가 
  4. cpp -> PWMCtr.c / PWMCtr.h 추가 (예제인 C++ 삭제)
  5. java -> com.example.jhlee -> GpioCtr.java
  6. java -> com.example.jhlee -> PWMCtr.java
  7. java -> com.example.jhlee -> MainActivity.java

  • 관련 Sample 소스 



3.3 기타사항 


Android Application의 경우 AndroidManifest.xml 까지 추후에 봐야한다.

아래의 소스는 NDK 기반에서 /system/lib 에 넣고 SDK에서 이를 호출하여 동작하는 방식 



Anroid Thing Native

Android Thing 상용화 무료가 아님



상위 /sys/class/pwm/pwmchip0 권한문제

PWM- Back light 

12/28/2020

Android SDK Tools

1. UBOOT의 fastboot 명령 

  • Uboot의 fastboot 명령어 
=> fastboot --help
fastboot - run as a fastboot usb or udp device

Usage:
fastboot [-l addr] [-s size] usb <controller> | udp
        addr - address of buffer used during data transfers (0x98000000)
        size - size of buffer used during data transfers (0x19000000)

  • Uboot Fastboot Mode 설정 
fastboot usb 0을 설정 후 Window에서 USB Host에서 Board USB Gadget Download 생성됨 
=> fastboot 0
or 
=> fastboot usb 0


1.1 Android UBOOT CONFIG 관련설정 

Android Board에서 Uboot로 Booting 후 fastboot로 Android의 각 Partition을 Wrtie를 진행하면, 제대로 동작되지 않는데, 아래와 같이 Uboot 의 config를 수정  

CONFIG_FSL_FASTBOOT=y
CONFIG_FASTBOOT_LOCK=y  ## 이 부분제거해야 FAST_BOOT_LOCK이 되지 않는다.

UBOOT 관련내용 

Android Lock 관련내용 

A/B slot 문제


2.  Android SDK Tools 설치 및 실행 

Android SDK Tool은 아래 사이트에서 각 OS에 맞게 Download가 가능하다 

Android Studio가 설치가 되어있다면, SDK Manager에서 설치가능 


2.1 Window Android SDK Tools 


Uboot에서 Fastboot Mode 진입하면 아래와 같이 USB를 인식하여 Fastboot로 진행이 안됨

  • USB Download gadget
 


  • Android Studio->SDK Manager->SDK Tools 
  1. Android SDK Platform-Tools
  2. Google USB Driver 


상위와 같이 설치 했음에도 불구하구 Window 10에서 미인식됨 
하지만 이것을 Virtual Box에 Ubuntu 설치하여 이 USB Device를 Virtual Box로 넘기면, Virtual Box의 Ubuntu에서는 동작이 제대로 됨 

결론적으로 Window용 USB Driver를 별도 설치를 해야하며, WinUSB를 수정해야하는 것으로 파악된다. 
추후 이부분은 더 자세히 알아보도록하자. 



2.2 Linux Android SDK Tools 설치 및 실행 

Window에서 fastboot가 잘되지 않아 Virtual Box에 Linux 설치 후 테스트 진행했더니, 동작이 잘되어 아래와 같이 적어논다.





  • adb와 fastboot 설치 
$ sudo apt-get install android-tools-adb android-tools-fastboot 

  • 기본적인 fastboot 사용법 
$ fastboot --help
usage: fastboot [ <option> ] <command>

commands:
  update <filename>                        Reflash device from update.zip.
                                           Sets the flashed slot as active.
  flashall                                 Flash boot, system, vendor, and --
                                           if found -- recovery. If the device
                                           supports slots, the slot that has
                                           been flashed to is set as active.
                                           Secondary images may be flashed to
                                           an inactive slot.
  flash <partition> [ <filename> ]         Write a file to a flash partition.
  flashing lock                            Locks the device. Prevents flashing.
  flashing unlock                          Unlocks the device. Allows flashing
                                           any partition except
                                           bootloader-related partitions.
  flashing lock_critical                   Prevents flashing bootloader-related
                                           partitions.
  flashing unlock_critical                 Enables flashing bootloader-related
                                           partitions.
  flashing get_unlock_ability              Queries bootloader to see if the
                                           device is unlocked.
  flashing get_unlock_bootloader_nonce     Queries the bootloader to get the
                                           unlock nonce.
  flashing unlock_bootloader <request>     Issue unlock bootloader using request.
  flashing lock_bootloader                 Locks the bootloader to prevent
                                           bootloader version rollback.
  erase <partition>                        Erase a flash partition.
  format[:[<fs type="">][:[<size>]] <partition>
                                           Format a flash partition. Can
                                           override the fs type and/or size
                                           the bootloader reports.
  getvar <variable>                        Display a bootloader variable.
  set_active <slot>                        Sets the active slot. If slots are
                                           not supported, this does nothing.
  boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.
  flash:raw <bootable-partition> <kernel> [ <ramdisk> [ <second> ] ]
                                           Create bootimage and flash it.
  devices [-l]                             List all connected devices [with
                                           device paths].
  continue                                 Continue with autoboot.
  reboot [bootloader|emergency]            Reboot device [into bootloader or emergency mode].
  reboot-bootloader                        Reboot device into bootloader.
  oem <parameter1> ... <parametern>        Executes oem specific command.
  stage <infile>                           Sends contents of <infile> to stage for
                                           the next command. Supported only on
                                           Android Things devices.
  get_staged <outfile>                     Receives data to <outfile> staged by the
                                           last command. Supported only on Android
                                           Things devices.
  help                                     Show this help message.

options:
  -w                                       Erase userdata and cache (and format
                                           if supported by partition type).
  -u                                       Do not erase partition before
                                           formatting.
  -s <specific device="">                     Specify a device. For USB, provide either
                                           a serial number or path to device port.
                                           For ethernet, provide an address in the
                                           form <protocol>:<hostname>[:port] where
                                           <protocol> is either tcp or udp.
  -c <cmdline>                             Override kernel commandline.
  -i <vendor id="">                           Specify a custom USB vendor id.
  -b, --base <base_addr>                   Specify a custom kernel base
                                           address (default: 0x10000000).
  --kernel-offset                          Specify a custom kernel offset.
                                           (default: 0x00008000)
  --ramdisk-offset                         Specify a custom ramdisk offset.
                                           (default: 0x01000000)
  --tags-offset                            Specify a custom tags offset.
                                           (default: 0x00000100)
  -n, --page-size <page size="">              Specify the nand page size
                                           (default: 2048).
  -S <size>[K|M|G]                         Automatically sparse files greater
                                           than 'size'. 0 to disable.
  --slot <slot>                            Specify slot name to be used if the
                                           device supports slots. All operations
                                           on partitions that support slots will
                                           be done on the slot specified.
                                           'all' can be given to refer to all slots.
                                           'other' can be given to refer to a
                                           non-current slot. If this flag is not
                                           used, slotted partitions will default
                                           to the current active slot.
  -a, --set-active[=<slot>]                Sets the active slot. If no slot is
                                           provided, this will default to the value
                                           given by --slot. If slots are not
                                           supported, this does nothing. This will
                                           run after all non-reboot commands.
  --skip-secondary                         Will not flash secondary slots when
                                           performing a flashall or update. This
                                           will preserve data on other slots.
  --skip-reboot                            Will not reboot the device when
                                           performing commands that normally
                                           trigger a reboot.
  --disable-verity                         Set the disable-verity flag in the
                                           the vbmeta image being flashed.
  --disable-verification                   Set the disable-verification flag in the vbmeta image being flashed.
  --wipe-and-use-fbe                       On devices which support it,
                                           erase userdata and cache, and
                                           enable file-based encryption
  --unbuffered                             Do not buffer input or output.
  --version                                Display version.
  -h, --help                               show this message.

2.1 Fastboot 실행 및 확인 

  • fastboot 준비사항 
우선 상위 Board의 Uboot에서 Fastboot Mode로 설정 후 Host에서 fastboot 명령어로 제어를 진행한다. 

  • fastboot device 정보 확인 
Board 의 Uboot에서 Fastboot 모드 일 경우 아래와 같이 Board 정보 확인가능 
$ sudo fastboot devices
051a700e828e4289	fastboot


  • fastboot flash unlock 진행 
나의 경우는 아래와 같이 fastboot flashing unlock 만 했더니 lock이 되었는데, 현재 각각의 차이점들은 알아가야 할 것 같다. 
$ sudo fastboot oem unlock

$ sudo fastboot flashing unlock

$ sudo fastboot flashing unlock_critical 


  • fastboot로 각 Partition write 진행 
각 Partition의 이름을 알아야 하면, 현재 a/b slot으로 구성되어있으므로, 각각의 Image를 write 후 reboot 진행 
$ sudo fastboot flash dtbo_a dtbo-imx8qxp-mipi.img

$ sudo fastboot flash boot_a boot.img

$ sudo fastboot reboot

관련내용참조 
  https://m.blog.naver.com/PostView.nhn?blogId=searphiel9&logNo=221367977833&proxyReferer=https:%2F%2Fwww.google.com%2F

12/24/2020

i.MX mfgtools/uuu

1. SoC의 I.MX Series 의 Window/Linux Tool

UUU(Universal Update Utility) 약어로 NXP사의 i.MX Series를 처음 Download할 때 필요한 Tool이며, fastboot와 연결해주는 역할까지 해주는 것으로 파악된다.
UUU는 기본적으로 libusb를 사용하며, 별도의 driver가 필요없으며, Window에서 i.MX Series 찾을 경우 USB HID Interface로 인식한다.


  • MFGTools/ UUU Download 
uuu program 과 uuu.pdf manual download 
  https://github.com/NXPmicro/mfgtools/releases

  • 기본사용법 아래링크에서 확인
상위 release에서 제공하는 uuu.pdf manual을 참고 


1.1 UUU기반의 기본 Batch 파일생성 

uuu를 download 했으면, 기본적으로 매번 uuu로 명령어를 실행하기가 귀찮기 때문에 batch file or shell script로 이를 만들어 필요한 부분만을 
본인이 정하고 사용한다. 

  • Burn_eMMC.bat 파일 예제
아래와 같이 쉽게 Window에서 쉽게 batch file or shell script를 만들어서 실행가능 
소스르 간단히 분석하면 setESC는 Window에서 색을 표시하기 위해서 넣었다. 
동작은 아래와 같이 동작한다.
  1. uuu -lsusb : uuu에 연결된 USB Device Vendor/Product ID 확인 
  2. uuu -b emmc_all u-boot.imx core-image-imx6sxsabresd.sdcard.bz2/*: u-boot.imx로 boot 후 core-image-imx6sxsabresd.sdcard.bz2 안에 file들을 write eMMC에 wirte
  3. uuu FB: ucmd setenv ethaddr 26:E1:2C:C4:C7:C6 : uuu script로 uboot에게 명령어 전달
  4. uuu FB: ucmd setenv eth1addr c2:42:5a:9f:cd:09 : 상동
  5. uuu FB: ucmd saveenv: 상동 (uboot의 정보 저장)

@ECHO OFF
TITLE Jeonghun's i.MX6 Burn_eMMC.bat
rem  
rem  * Author:  Jeonghun Lee
rem  * Description: 
rem    - This batch file is used for burning a Image into eMMC
rem    
setlocal
call :setESC
echo %ESC%[1;31m 
ECHO ------------------------------------------------------------------------------------------------------
ECHO ---------------------------      CAUTION           ---------------------------------------------------
ECHO ------------------------------------------------------------------------------------------------------
echo %ESC%[0m
ECHO Ready to burn an image on eMMC in iMX6 board 
ECHO Please check your bootmode or usb connection on your board if not work properly
echo %ESC%[1;31m
ECHO *** Please check "Connected Known USB devices" below
ECHO.     
ECHO     Chip          Vid         Pid
ECHO     -------------------------------
ECHO                  0x0525    0xA4A5 
ECHO      MX6SX       0x15A2    0x0071 
echo %ESC%[0m
ECHO.
uuu -lsusb
ECHO.  
echo %ESC%[1;31m
ECHO *** Please check "Success 1" and "Done" below after writing the Image  
echo %ESC%[0m
ECHO.   
uuu -b emmc_all u-boot.imx core-image-imx6sxsabresd.sdcard.bz2/*
ECHO.  
ECHO.  
ECHO.
echo %ESC%[1;31m
ECHO *** Please check "Okay" below after sending information into Uboot
echo %ESC%[0m
ECHO.
ECHO.
uuu FB: ucmd setenv ethaddr 26:E1:2C:C4:C7:C6
ECHO.
uuu FB: ucmd setenv eth1addr c2:42:5a:9f:cd:09
ECHO.
uuu FB: ucmd saveenv
echo %ESC%[1;31m 
ECHO ------------------------------------------------------------------------------------------------------
ECHO ----------------------------------   END        ------------------------------------------------------
ECHO ------------------------------------------------------------------------------------------------------
ECHO *** Please close your window
echo %ESC%[0m
PAUSE
:setESC
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set ESC=%%b
  exit /B 0
)
exit /B 0

1.2 UUU Script 기반의 Batch 파일생성

상위기능은 기본적인 기능만을 사용하는 것으로, 좀 더 복잡하게 사용하고자 하면, uuu 내부 script를 연동하여 이를 batch file로 생성하여 만들어 사용하자. 

  • UUU Script (List) 관련내용(필독) 
  1. SDPS: Stream download 로  MX8QXPB0 이후 버전만 가능
  2. SDP:  iMX6/iMX7 HID download protocol로 SDPS로 동일기능이지만 HID로 download
  3. FB: Fastboot protocol 이용 
나머지 내용은 아래 링크 참조 

Linux Image는 간단하게 하나의 Image로 생성해서 만들어서 구우면 되지만, Android의 경우, 각 Partition을 만들어서 Write해야 하므로 
조금 복잡하므로 UUU list (Script)를 만들어서 실행해어야 한다. 

이전에 사용했던 batch file이 Linux Image이라고 생각하면 되겠다. 

  • uuu-list.txt 생성 (uuu script)
아래의 예제는 i.MX8QXP부터 가능하며, 동작방식은 u-boot를 booting 후 아래의 uboot command들을 직접 실행을 하는 것이다.
uuu_version 1.3.74 
SDPS: boot -f u-boot-imx8qxp-mek-c0-uuu.imx
FB: ucmd setenv fastboot_dev mmc 
FB: ucmd setenv mmcdev 0 
FB: ucmd mmc dev 0 
FB: ucmd mmc dev 0 0 
FB: ucmd mmc erase 0x2000 0x10 
FB: ucmd mmc partconf 0 1 1 1 
FB[-t 600000]: flash bootloader0 u-boot-imx8qxp-c0.imx
FB[-t 600000]: flash gpt partition-table-7GB.img
FB: ucmd setenv fastboot_dev sata 
FB: ucmd setenv fastboot_dev mmc 
FB[-t 600000]: flash dtbo_a dtbo-imx8qxp-mipi.img
FB[-t 600000]: flash boot_a boot.img
FB[-t 600000]: flash vbmeta_a vbmeta-imx8qxp-mipi.img
FB[-t 600000]: flash super super.img
FB[-t 600000]: erase misc
FB[-t 600000]: erase presistdata
FB[-t 600000]: erase fbmisc
FB[-t 600000]: erase metadata
FB: set_active a
FB[-t 600000]: erase userdata
FB: done 

상위 동작은 board에 u-boot-imx8qxp-mek-c0-uuu.imx booting 후 UUU가 동작한 후 ucmd로 별도의 u-boot-imx8qxp-c0.imx Write 진행한다. 
  1. u-boot-imx8qxp-mek-c0-uuu.imx : UBOOT Config UUU 지원
  2. u-boot-imx8qxp-c0.imx : UBOOT Config UUU 미지원
두개의 uboot를 사용이유는 보안문제로 이기 때문인것으로 파악되며, 외부에서 함부로 bootloader를 접근못하게 하는 것이다. 
또한 이 문제로 Android의 경우 u-boot-imx8qxp-mek-c0-uuu.imx write를 진행을 하지만 실제 bootloader는 u-boot-imx8qxp-c0.imx 기반으로 동작된다. 

이 문제로 인하여 uuu로는 단일 Partition write가 힘들지만, Android 소스를 변경했을 경우 빌드 진행 후 vbmeta 정보가 변경되어 (Partition의 hash 값이 변경)
단일 Partition write가 uuu로는 불가능하다. 

하지만 Android 전체빌드 후 전체 Partition Write 상위와 같이 가능하다. 


마지막에 a/b slot의 설정의 a 영역으로 설정진행 (fastboot 기능)
  1. SDPS: Stream download after MX8QXPB0
  2. SDP:  iMX6/iMX7 HID download protocol.
  3. FB[-t timeout]:\Fastboot: android fastboot protocol. unit of timeout is ms
  4. FBK: community with kernel with fastboot protocol. DO NOT compatible with fastboot tools.

mmc partconf 0 1 1 1 

  • 상위 uuu-list 적용 batch 파일
이전의 batch 파일과 거의 동일하지만, 대신에 uuu-list.txt를 만들어 직접 설정하도록함
@ECHO OFF
TITLE Jeonghun's i.MX6 Burn_eMMC.bat
rem  
rem  * Author:  Jeonghun Lee
rem  * Description: 
rem    - This batch file is used for burning a Image into eMMC
rem    
setlocal
call :setESC
echo %ESC%[1;31m 
ECHO ------------------------------------------------------------------------------------------------------
ECHO ---------------------------      CAUTION           ---------------------------------------------------
ECHO ------------------------------------------------------------------------------------------------------
echo %ESC%[0m
ECHO Ready to burn an image on eMMC in iMX6 board 
ECHO Please check your bootmode or usb connection on your board if not work properly
echo %ESC%[1;31m
ECHO *** Please check "Connected Known USB devices" below
ECHO.     
ECHO     Chip          Vid         Pid
ECHO     -------------------------------
ECHO                  0x0525    0xA4A5 
ECHO      MX6SX       0x15A2    0x0071 
echo %ESC%[0m
ECHO.
uuu -lsusb
ECHO.  
echo %ESC%[1;31m
ECHO *** Please check "Success 1" and "Done" below after writing the Image  
echo %ESC%[0m
ECHO.   
uuu  uuu-list.txt
ECHO.  
ECHO.  
ECHO.
echo %ESC%[1;31m
ECHO *** Please check "Okay" below after sending information into Uboot
echo %ESC%[0m
ECHO.
echo %ESC%[1;31m 
ECHO ------------------------------------------------------------------------------------------------------
ECHO ----------------------------------   END        ------------------------------------------------------
ECHO ------------------------------------------------------------------------------------------------------
ECHO *** Please close your window
echo %ESC%[0m
PAUSE
:setESC
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set ESC=%%b
  exit /B 0
)
exit /B 0

2. i.MX 의 Android flashtool 예제 분석 

Android 용 uuu flash batch file인데, batch file로는 너무 좋은예제인 것 같아 아래와 같이 넣어 놓는다. 
사실 상위 uuu.list는 아래의 batch file의 결과를 수정하여 만들 것이므로, i.MX에서 제공하는 아래의 batch file을 사용할 필요가 없다.  
직접 본인이 만들어 사용하는 것이 편하다. 

동작원리는 최종결과물에 uuu.lst를 상위와 거의동일한 script 만들어가면서, 이때 파일의 심볼릭링크 link를 같이 이용한다.
나의 경우는 link 대신 직접 파일이름을 넣어 이전 uuu.list를 작성했다.  

최종동작원리는 uuu 와 uuu.lst를 같이 동작한 후 이를 삭제하도록 하는 구조이며 이부분만 파악하면된다. (463 Line)

  • uuu_imx_android_flash.bat

12/19/2020

MIPI DSI(Display Serial Interface) 와 SW 구조

1. MIPI  Data 전송방식  

MIPI-DSI Hardware 구조 

ST MIPI-DSI 구조 (필독 자세한 설명이 나옴)

MIPI 관련내용


MIPI의 기본전송방식은 크게 Long Packet/ Short Packet 구조로 두개로 나누어지며, 세부적으로 Data ID에 따라 변경이 된다.  

https://www.st.com/resource/en/application_note/dm00287601-dsi-host-on-stm32f469-479-stm32f7x8-x9-and-stm32l4r9-s9-mcus-stmicroelectronics.pdf

  1. PH(Packet Header):  Header는 ECC로 검증이가능
  2. Data Paylod 
  3. PF(Packet Footer): Checksum으로 전체 Data가 검증가능 

만약 S/W에서 MIPI 전송오류가 발생한다면, ECC or Checksum Error가 발생할 것이며, 이는 곳 MIPI가 고속 Serial 통신이므로, 
HW 관련부분을 점검해봐야 할 것이다. 


  • 일반적인 HS(High Speed )모드 전송 방식 


  • Short Packet 전송 HS Mode 


  • Long Packet 전송 HS Mode (2 Lane)


1.1  Long Packet 과 Short Packet 

MIPI에서 알아야 할 기본구조 전송방식이며, DataID 값도 같이 알아야 정확한 이해가 가능하다. 

  • Long Packet 
  1. SoT(Start Of Transmission)
  2. Data ID(Virtual Channel ID) : 1byte
  3. Word Count: 2 bytes (Payload Size)
  4. ECC: 1 byte
  5. Data: Payload
  6. CheckSum: 2bytes 
  7. EoT(End Of Transmission)











Kernel(drivers/gpu/drm/drm_mipi_dsi.c)
mipi_dsi_packet_format_is_long  ( 이 함수를 보면 long packet의 종류를 파악)

  • Short Packet 
  1. SoT(Start Of Transmission)
  2. Data ID(Virtual Channel ID) : 1 byte
  3. Data 1/2: 2 bytes
  4. ECC: 1byte
  5. EoT(End Of Transmission)








Kernel (drivers/gpu/drm/drm_mipi_dsi.c)
mipi_dsi_packet_format_is_short  ( 이 함수를 보면 short packet의 종류를 파악)
  https://elixir.bootlin.com/linux/latest/source/drivers/gpu/drm/drm_mipi_dsi.c#L369

long/short packet (mipi_dsi_msg *msg ) 자체가 packet header 와 payload 가 포함됨 


1.2 Packet 의 Data ID의 구조 


  • DI(Data ID) 에서 Virtual Channel ID 사용 



  • Virtual ID로 Logical Channel 구분 


  • Virtual Channel로 구성 









1.2.1  Data ID->Data Type 의 값 


  • Data ID-> Data Type Class 
아래와 같이 Data Type의 종류를 간단히 보고 세부 값들을 보자. 


  • Data Type 의 다양한 값의 의미  
Packet 이 Short 과 Long으로 구분이 되며, 아래의 Data Type은 Data ID 값이며, DSI Mode에서 Both인 EOT를 반드시 기억하자.
  1. Video: Display 관련 Video Signal 
  2. Both: Master /Slave 동시사용
  3. Command: Master에서 주로 Command를 주는 것 


  1. DCS: DCI 기반으로 DCS로 Display Command 가능 
  2. VD(Video Display Packet)
  3. GN(General Packet)



상위 Data ID (DI) 값과 동일하며, Linux Source에서  동일하며, 상위 값 이외에도 다양하게 확장중이며, 아래와 같이 각 함수마다 호출되는 곳이 다르다. (주의)


  • Linux Kernel 의 Data Type 값 

//include/video/mipi_display.h
/* MIPI DSI Processor-to-Peripheral transaction types */
enum {
	MIPI_DSI_V_SYNC_START                         = 0x01,
	MIPI_DSI_V_SYNC_END                           = 0x11,
	MIPI_DSI_H_SYNC_START                         = 0x21,
	MIPI_DSI_H_SYNC_END                           = 0x31,

	MIPI_DSI_COMPRESSION_MODE                     = 0x07,  //mipi_dsi_compression_mode()
	MIPI_DSI_END_OF_TRANSMISSION            = 0x08,  //주의 SOT는 없어도 EOT는 별도로 존재

	MIPI_DSI_COLOR_MODE_OFF                       = 0x02,
	MIPI_DSI_COLOR_MODE_ON				          = 0x12,
	MIPI_DSI_SHUTDOWN_PERIPHERAL                  = 0x22,   //mipi_dsi_shutdown_peripheral()
	MIPI_DSI_TURN_ON_PERIPHERAL                   = 0x32,   //mipi_dsi_turn_on_peripheral()

	MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM    = 0x03,     //mipi_dsi_generic_write -> mipi_dsi_device_transfer()
	MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM 	= 0x13,    //mipi_dsi_generic_write -> mipi_dsi_device_transfer()
	MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM		= 0x23,     //mipi_dsi_generic_write -> mipi_dsi_device_transfer()

	MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM     = 0x04,     //mipi_dsi_generic_read -> mipi_dsi_device_transfer()
	MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM 	= 0x14,     //mipi_dsi_generic_read -> mipi_dsi_device_transfer()
	MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM 	= 0x24,     //mipi_dsi_generic_read -> mipi_dsi_device_transfer()

	MIPI_DSI_DCS_SHORT_WRITE 		= 0x05,       //mipi_dsi_dcs_write_buffer->mipi_dsi_device_transfer()
	MIPI_DSI_DCS_SHORT_WRITE_PARAM		= 0x15,        //mipi_dsi_dcs_write_buffer->mipi_dsi_device_transfer()

	MIPI_DSI_DCS_READ				= 0x06,
	MIPI_DSI_EXECUTE_QUEUE				= 0x16,

	MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE		= 0x37,  //mipi_dsi_set_maximum_return_packet_size()

	MIPI_DSI_NULL_PACKET				= 0x09,
	MIPI_DSI_BLANKING_PACKET			= 0x19,
	MIPI_DSI_GENERIC_LONG_WRITE		= 0x29,          //mipi_dsi_generic_write
	MIPI_DSI_DCS_LONG_WRITE			= 0x39,         // mipi_dsi_dcs_write_buffer

	MIPI_DSI_PICTURE_PARAMETER_SET            = 0x0a,  //mipi_dsi_picture_parameter_set()->pps정의 
	MIPI_DSI_COMPRESSED_PIXEL_STREAM		= 0x0b,

	MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20	= 0x0c,
	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24		= 0x1c,
	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16		= 0x2c,

	MIPI_DSI_PACKED_PIXEL_STREAM_30			= 0x0d,
	MIPI_DSI_PACKED_PIXEL_STREAM_36			= 0x1d,
	MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12		= 0x3d,

	MIPI_DSI_PACKED_PIXEL_STREAM_16			= 0x0e,
	MIPI_DSI_PACKED_PIXEL_STREAM_18			= 0x1e,
	MIPI_DSI_PIXEL_STREAM_3BYTE_18			= 0x2e,
	MIPI_DSI_PACKED_PIXEL_STREAM_24			= 0x3e,
};
Kernel (include/video/mipi_display.h)
상위값으로 Data ID 값을 확인 


1.3  DSI-DCS(Display Command Set) 

DCS를 비롯하여, 모든 Data는 상위 Long Packet 과 Short Packet 구조를 가지고 있으며, DCS도 아래와 같이 Long Packet / Short Packet으로 구분 

  • DCS(Display Command Set)
Data ID만 변경하면 Long Packet/ Short Packet 구분되어 Header 구성되며, Payload에 DCS가 전달되는 구조임  (아래그림참조)



  • DCS Command는 아래 참조 (Linux Kernel)
//include/video/mipi_display.h
/* MIPI DCS commands */
enum {
	MIPI_DCS_NOP			= 0x00,
	MIPI_DCS_SOFT_RESET		= 0x01,
	MIPI_DCS_GET_COMPRESSION_MODE	= 0x03,
	MIPI_DCS_GET_DISPLAY_ID		= 0x04,
	MIPI_DCS_GET_ERROR_COUNT_ON_DSI	= 0x05,
	MIPI_DCS_GET_RED_CHANNEL	= 0x06,
	MIPI_DCS_GET_GREEN_CHANNEL	= 0x07,
	MIPI_DCS_GET_BLUE_CHANNEL	= 0x08,
	MIPI_DCS_GET_DISPLAY_STATUS	= 0x09,
	MIPI_DCS_GET_POWER_MODE		= 0x0A,
	MIPI_DCS_GET_ADDRESS_MODE	= 0x0B,
	MIPI_DCS_GET_PIXEL_FORMAT	= 0x0C,
	MIPI_DCS_GET_DISPLAY_MODE	= 0x0D,
	MIPI_DCS_GET_SIGNAL_MODE	= 0x0E,
	MIPI_DCS_GET_DIAGNOSTIC_RESULT	= 0x0F,
	MIPI_DCS_ENTER_SLEEP_MODE	= 0x10,
	MIPI_DCS_EXIT_SLEEP_MODE	= 0x11,
	MIPI_DCS_ENTER_PARTIAL_MODE	= 0x12,
	MIPI_DCS_ENTER_NORMAL_MODE	= 0x13,
	MIPI_DCS_GET_IMAGE_CHECKSUM_RGB	= 0x14,
	MIPI_DCS_GET_IMAGE_CHECKSUM_CT	= 0x15,
	MIPI_DCS_EXIT_INVERT_MODE	= 0x20,
	MIPI_DCS_ENTER_INVERT_MODE	= 0x21,
	MIPI_DCS_SET_GAMMA_CURVE	= 0x26,
	MIPI_DCS_SET_DISPLAY_OFF	= 0x28,
	MIPI_DCS_SET_DISPLAY_ON		= 0x29,
	MIPI_DCS_SET_COLUMN_ADDRESS	= 0x2A,
	MIPI_DCS_SET_PAGE_ADDRESS	= 0x2B,
	MIPI_DCS_WRITE_MEMORY_START	= 0x2C,
	MIPI_DCS_WRITE_LUT		= 0x2D,
	MIPI_DCS_READ_MEMORY_START	= 0x2E,
	MIPI_DCS_SET_PARTIAL_ROWS	= 0x30,		/* MIPI DCS 1.02 - MIPI_DCS_SET_PARTIAL_AREA before that */
	MIPI_DCS_SET_PARTIAL_COLUMNS	= 0x31,
	MIPI_DCS_SET_SCROLL_AREA	= 0x33,
	MIPI_DCS_SET_TEAR_OFF		= 0x34,
	MIPI_DCS_SET_TEAR_ON		= 0x35,
	MIPI_DCS_SET_ADDRESS_MODE	= 0x36,
	MIPI_DCS_SET_SCROLL_START	= 0x37,
	MIPI_DCS_EXIT_IDLE_MODE		= 0x38,
	MIPI_DCS_ENTER_IDLE_MODE	= 0x39,
	MIPI_DCS_SET_PIXEL_FORMAT	= 0x3A,
	MIPI_DCS_WRITE_MEMORY_CONTINUE	= 0x3C,
	MIPI_DCS_SET_3D_CONTROL		= 0x3D,
	MIPI_DCS_READ_MEMORY_CONTINUE	= 0x3E,
	MIPI_DCS_GET_3D_CONTROL		= 0x3F,
	MIPI_DCS_SET_VSYNC_TIMING	= 0x40,
	MIPI_DCS_SET_TEAR_SCANLINE	= 0x44,
	MIPI_DCS_GET_SCANLINE		= 0x45,
	MIPI_DCS_SET_DISPLAY_BRIGHTNESS = 0x51,		/* MIPI DCS 1.3 */
	MIPI_DCS_GET_DISPLAY_BRIGHTNESS = 0x52,		/* MIPI DCS 1.3 */
	MIPI_DCS_WRITE_CONTROL_DISPLAY  = 0x53,		/* MIPI DCS 1.3 */
	MIPI_DCS_GET_CONTROL_DISPLAY	= 0x54,		/* MIPI DCS 1.3 */
	MIPI_DCS_WRITE_POWER_SAVE	= 0x55,		/* MIPI DCS 1.3 */
	MIPI_DCS_GET_POWER_SAVE		= 0x56,		/* MIPI DCS 1.3 */
	MIPI_DCS_SET_CABC_MIN_BRIGHTNESS = 0x5E,	/* MIPI DCS 1.3 */
	MIPI_DCS_GET_CABC_MIN_BRIGHTNESS = 0x5F,	/* MIPI DCS 1.3 */
	MIPI_DCS_READ_DDB_START		= 0xA1,
	MIPI_DCS_READ_PPS_START		= 0xA2,
	MIPI_DCS_READ_DDB_CONTINUE	= 0xA8,
	MIPI_DCS_READ_PPS_CONTINUE	= 0xA9,
};
  
  


  • DCS 로 제어는 아래의 함수이용  
  1. mipi_dsi_dcs_write
  2. mipi_dsi_dcs_write_buffer

 

1.4  일반적인 DSI Write

우선 LCD Initial Code는 이전에 병렬에서 맞춰주던 Hsync/Vsync를 비롯하여, LCD의 Data Format 및 기타 설정을 위해서 MIPI Interface로 설정을 해준다. 

  • 일반적인으로  DSI 사용되는 함수 
  1. mipi_dsi_generic_write
  2. mipi_dsi_generic_read 
상위 함수를 이용하여  자동으로 Long or Short 선택되어 Header가 구성되어 read/write 되지만, 상위 Data ID는 상위에 정해짐 


반드시 LCD Datasheet를 참조하여, Payload에 들어가는 Header에 Data ID도 확인가능하다며 확인하자.

본인이 LCD Spec에서 DCS Command 사용여부에  맞게 선택해서 함수도 맞게 넣어 개발하는 것이 맞을 것이라고 본다. 

  • 기타 MIPI-DSI Debug 관련내용 


2. GPU의 DRM (Direct Rendering Manager)

처음 DRM의 약자를 Digital Right Management로 착각했으며, 예전에 HDMI Device Driver 개발당시 HDCP와 유사한 기능이라고 착각했다.
DRM은 GPU기반으로 빠른 Rendering을 지원하기 위해서 제공해주는 기능이며, 이전에 Frame buffer Driver만 개발했던 나에게 다소 생소했는데, 
각 여러 Layer들을 쉽게 Rotate/Scale/Crop/Overlay되는 것을 보고 이 기능에 조금 놀라웠다. 

이전에 TI DSP기반으로했던, Davinci의 경우 Scale 과 Crop은 가능했던걸로 기억하지만, 많은 Layer들은 제어하지는 못했는데, DRM은 GPU를 통해서 다양한 기능을 제공한다.
한마디로 GPU에서 확장된 Frame Buffer라고 생각하면 될 것 같으며, Overlay 기능역시 GPU에 따라 다른 것 같다. 

  • FrameBuffer 와 DRM(Direct Rendering Manager) 비교 


Kernel DRM Driver 기본구조

Kernel GPU DRM-KMS(Kernel Mode Setting) 
상위 MIPI-DSI의 HW Dispaly 관련 출력설정 

TI사의 DSS와 DRM 부분 


2.2  Frame Buffer vs DRM 기반의 Pannel 

  • Frame Buffer LCD Initial Code 
Frame Buffer 기반으로 DCS Command 입력 후 Initial Code 입력 SPI/GPIO 기반으로 입력 

  • DRM 기반의 LCD Initial Code
DRM기반의 실제 Panel Driver들의 다양한 예제이며, SPI와 I2C 및 GPIO와도 연결되어 구성되므로 참고

DRM(Direct Rendering Manager)로 GPU기반으로 DBI (이전의 ST 칩의 DBI라고 생각하면됨)

mipi_dsi_dcs_xxx 함수들은 내부적으로 dcs command를 호출


  • i.MX 의 경우 i.MX6는 Framebuffer Driver
Table 64. MIPI DSI Driver Files  // Frame buffer 기반 Driver 와 DRM 기반 Driver들 
File Description
drveirs/video/fbdev/mxc/mipi_dsi.c                                        MIPI DSI IP Frame buffer driver source file
drivers/video/fbdev/mxc/mipi_dsi.h                                        MIPI DSI IP Frame bufferdriver header file
drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c                   MIPI DSI Frame bufferDisplay Panel driver source file
drivers/video/fbdev/mxc/mipi_dsi_samsung.c                       MIPI DSI Frame buffer Samsung source file
drivers/video/fbdev/mxc/mipi_dsi_northwest.c                      MIPI DSI Frame buffer Northwest source file
drivers/video/fbdev/mxc/mxcfb_hx8363_wvga.c                   i.MX 7 Frame buffer Truly WVGA Panel TFT3P5581E
drivers/video/fbdev/mxc/mxcfb_hx8369_wvga.c                   i.MX 6 Frame buffer Truly WVGA sync panel
drivers/video/fbdev/mxc/mxcfb_otm808b_wvga.c                 Truly Frame buffer WVGA Panel TFT3P5079E
  •  i.MX의 경우 i.MX 8은 DRM Driver  
drivers/gpu/drm/imx/sec_mipi_dsmi-imx.c Samsung            DRM driver
drivers/gpu/drm/imx/nwl_dsi-imx.c Northwest                        DRM driver



Device Tree 

12/18/2020

MIPI DSI(Display Serial Interface)

1. MIPI-DSI 구조 

MIPI(Mobile Industry Processor Interface)의 DSI는 LCD Interface를 고속 Serial Interface를 이용하는 예로 이번기회에 정리하고자 한다.  
세부내용들은 아래의 링크들에서 자세히 잘 설명해주고 있다. 

LCD Interface 관련내용

ST MIPI-DSI 관련내용 

MIPI(Mobile Industry Processor Interface)

MIPI-DSI(Display Serial Interface)

MIPI-PHY 관련내용 

LCD Pannel Spec


1.1 MIPI DSI 의 구조 

MIPI-DSI

  • MIPI DSI 의 기본구조
DSI Interface로 DCS로 Command로 구성이 되어져 이를 제어한다. 



  • MIPI의 D-PHY 구조 
  1. Clock Lane: One-way (단방향)
  2. Data Lane: One-way (단방향)
  3. Data Lane: Two-way (양방향)

One-way Clocl Lane/ Data Lane
Master: 
    


https://www.programmersought.com/article/42054062840/





2. NXP 사의 i.MX Series 구조 

i.MX6 과 8의  MIPI Interface를 비교하고 관련 부분을 간단히 비교해보자. 

2.1  NXP사의 MIPI-DSI (i.MX6) 

상위에서 기본적인 MIPI를 알았으니, 실제 AP인 i.MX의 경우를 보면 어떻게 세부적으로 동작하는지 알수 있을 것이다. 
두개다 D-PHY는 내부에 포함이 되어있으며, 동작구조가 유사하지만, 점점 변경되어가는 것을 볼 수 있다. 

  • i.MX6 MIPI DSI(Host Controller) 
상위 ST와 거의 유사하며, 별로 다르게 없다.  
  • i.MX6  DSI 내부구조 

i.MX6의 LVDS는 병렬 LCD제어에서 Bridge로 변경되어 제어됨 




2.2  NXP사의 MIPI-DSI (i.MX8) 

  • i.MX8의 MIPI-DSI or LVDS 
기존의 i.MX6와 다르게 MIPI-DSI 와 LVDS PHY를 합쳐서 사용하며, 외부 칩 제어를 위해 i2C 와 GPIO를 설정 (IO Expander 및 레귤레이터)  및 
Bakclight를 위한 PWM제어를 한 묶음으로 변경하여 보기쉽게 변경되었다.
 

아래의 구조는 쉽게 이해하고자 한다면, 이전에 ST 버전하고 거의 동일하다고 생각하면 될 것같다. 
DSI Controller (DSI Host) 로 LCD의 Device를 연결한다.