검색어 xargs에 대한 글을 날짜를 기준으로 정렬하여 표시합니다. 관련순 정렬 모든 글 표시
검색어 xargs에 대한 글을 날짜를 기준으로 정렬하여 표시합니다. 관련순 정렬 모든 글 표시

9/14/2022

VS Code Extension

1. VS Code Extension 

이전에 VS Code 와 관련해서 사용했던 것들을 아래와 같이 링크 

  • VS Code 기본사용 및 Extension 추천 
이전에 설치하여 주로 사용하던 걸로 Remote Development 관련설명 

  • VS Code Extension 저장장소 (본인계정에 저장)
C:\Users\jhlee\.vscode\extensions 저장되어짐 
** 만약 설치시 문제 생기면 상위부분에 가서 각 extensions 직접 삭제

각각의 VS Code extensions program들이 존재 및 설정값도 직접확인 가능 


1.1 VS Code Extension Tools

VS Code Extension 이 2020 과 2022년 비교를 하면 많이 달라졌으며, 현재 내가 주로 사용하고있는 Extension List들을 표시한다. 
그리고, VS Code Extension Program이 계속 Update 되고 사용법도 매번 조금씩 변경되므로, 각 세부사항은 Manaul을 반드시 참조 

  • VS Code Extension- Remote Package 필수사용  
MS사에서 제공하는 Remote Package로 요즘 한꺼번에 다 설치를 해줌(이전과 다름)

  • VS Code Extension- Markdown 관련사항 
Markdown 쉽게 작성하기 위해서 사용 

  • VS Code Extension- Hex File 볼 경우 

  • VS Code Extension- Git 관련사항 

  • VS Code Extension- Cmake 관련사항 
흐음 필요사항을 아직 모름

  • VS Code Extension- C/C++ 관련사항 
C/C++ 관련것으로 소스 분석용 설치 


1.2 VS Code Extension Tools for Comments

주석(Comments)에 관련부분들은 따로 분류하여 링크를 한다. 

Better Comments
가장 많이 사용되어지는 Tool로 현재 나는 Disable 
간단한 사용법은 아래이며, 실제 사이트에서 가서 Update가 되므로 상위에서 확인  

Doxygen Documentation Generator
Doxygen 과 Comment를 쉽게 생성하는방법 
소스위치에서 ( /** 만 입력한 후 엔터 ) 입력하며, Function 위/ File 맨위 각 다르게 생성 

Auto Comment Blocks
주석을 자동으로 Blocking 관리 ( /** or /*!  입력한 후 엔터) 입력 
상위를 이용하면 불필요

TODO Highlight
주석(Comment) 에 TODO/FIXME 쉽게 파악 

이외 Google Translate를 이용하여 주석 자동으로 번역해주는 기능을 비롯하여 다양하다.

1.3 VS Code Extension ESP-IDF

  • VS Code Extension (ESP-IDF 설치)
ESP-IDF 설치 
이전과 변경되어있으며, 쉽게 IDF를 설치를 진행한다.

최근꺼는 MS 의 Email 기반으로도 VS Code Extesion을 Sync를 맞출수 있는 것으로 보여진다.

Espressif IDF VS Code Extension (Node.js 소스)

VS Code Extension 설치위치 
  C:\Users\jhlee\.vscode\extensions


2. VS Code Extension 사용법


이전에 내가 작성한 VS Code Extension Tools 사용법들을 아래에 링크 


2.1 VS Code Remote Package 

VS Code에서 Remote에 있는 Linux Server or WSL를 연결하여 사용하는 법 

VS Code 에서 Remote X11 연결방법 
현재 필요 WSL을 사용하면 필요가 없어보이며, 외부에서 사용할 경우에만 필요 

VS Code 에서 WSL 설치 후 Remote 진행 


2.2 VS Code Git 사용 

VS Code는 기본적으로 Git Package가 없으므로 반드시 먼저 Git을 먼저 설치 한후 사용진행 
세부내용은 아래링크 확인 
 
VS Code에서 Git 사용법 

VS Code VersionControl 


2.3 VS Code JTAG 설정 및 Debug

이 부분은 매번 조금씩 변경되어왔으므로, 만약 더 최신버전을 사용한다면, 반드시 Manaul 참조


ESP32의 OpenOCD 관련설정 (거의 유사하지만 쉽게 설정가능)

  • launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "name": "ESP32 Debugger",
            "type": "espidf", 
            "request": "launch",
            "gdbinitFile":"${workspaceFolder}/.vscode/gdbinit",    
                    
        }
    ]
}  

상위와 같이 ${workspaceFolder} 변수 이용 

  • settings.json 
{
// ESP-IDF 기반으로 개인적으로 생성하여,설정한 설정값들 (불편한것은, 직접 Setting.json에서 변경해야함)     
    "idf.RS485Port": "COM8",     
    "idf.RS485Baudrate": "921600",  
    "idf.RS485ResponseTimeout": "0.100", //0.050 -> 0.100
    "idf.RS485MaxUnit": "5",       
    "idf.RS485TimerInterval": "1", 
    "idf.RS485TesTimeHour": "10",      
    
//ESP-IDF 설치 후 환경설정 값들 (VS Code의 아래 버튼으로 변경가능)     
    "idf.adapterTargetName": "esp32",  
    "idf.flashType": "UART",
    "idf.portWin": "COM3",                  
    "idf.svdFilePath": "${workspaceFolder}/esp32.svd",  //OpenOCD를 위해서 Register Map을 보기 위한 도구 https://github.com/espressif/svd
    "idf.openOcdConfigs": [                             //OpenOCD의 설정 이부분이 이해가 안된다면, OpenOCD를 참조 
        "interface/ftdi/esp32_devkitj_v1.cfg",
        "target/esp32.cfg"
    ]
} 

상위 설정된 값은 tasks.json의 command에서 사용가능하며, template으로 숨겨진 설정값도 존재한다. 

VS Code에 Espressif IDF 포함된 Template 으로 좀 더 다양하게 확인가능 
Command가 Window/Linux 지원해야하므로, 두개로 분리 운영 

상위 소스는 C:\Users\jhlee\.vscode\extensions\espressif.esp-idf-extension-xxxx\\templates\.vscode 존재하며, 나의 경우 직접 수정해서 사용함 

  • gdbinit
target remote :3333
set remote hardware-watchpoint-limit 2
symbol-file ./build/xxxxx.elf
mon reset halt
flushregs
thb app_main
c

2.4 VS Code Task 설정 및 사용법  

각 Project 마다 본인의 Task를 만들어서 TEST Program들을 쉽게 설치하고, Chainging도 가능하므로, 각 자동화도 가능하다. 

우선 내부적으로 사용되어지는 환경변수 및 VS Coe Extesion Tools 내부에서만 사용하는 환경변수들을 알아 두면 좋다. 
또한 dependson을 이용하여 다른 Task 와 Chaining도 가능하다. 

  • tasks.json (Window용)
아래와 같이 자동화 및 Window에서도 Powershell을 이용하여 다양하게 확장가능하다.
만약 Linux/Window 같이 사용하고 자하면 command 위에 별도의 window용을 별도로 설정
{
// See task.json Manual in VSCode
// for the documentation about the tasks.json format
// 아래의 예제들은 내가 간단하게 사용하는 예제 중 일부를 가져온 것이며, 나의 경우, TEST Task가 너무 많아 이를 Chain해서 사용한다. 

    "version": "2.0.0",
    "tasks": [
        {
            "label": "IP Config",
            "type": "shell",
            "command": "ipconfig"
        }, 
// 기본 실행되는 위치가 workspaceFoder가 아닐 경우, 
//다음과 같이 Command를 연속해서 실행가능하며,아래와 같이 ; 세미콜론을 사용하자 (PowerShell Script는 관련 Manaul 참조하도록)   
        {
            "label": "TEST Release",
            "type": "shell",
            "command": "cd ${workspaceFolder}/release; ./makeFirmware.ps1"
        },          
        {
            "label": "ESP-IDF Erase ALL",
            "type": "shell",
            "command": "${userHome}/.espressif/python_env/idf4.2_py3.8_env/Scripts/python.exe ${userHome}/esp/esp-idf/components/esptool_py/esptool/esptool.py -p ${config:idf.portWin}  -b 460800 --before default_reset --after hard_reset --chip ${config:idf.adapterTargetName} erase_flash"
        },       
//아래와 같이 dependson을 사용하여 각 Command의 Label로 적어 Macro로 형식으로, Chain하여 사용하자
//아래처럼 실행하하면, TEST Release -> ESP-IDF Erase ALL -> ESP-IDF WRITE ALL        
        {
            "label": "ESP-IDF WRITE ALL",
            "type": "shell",
            "command": "${config:idf.pythonBinPathWin} ${userHome}/esp/esp-idf/components/esptool_py/esptool/esptool.py -p ${config:idf.portWin} -b 460800 --before default_reset --after hard_reset --chip ${config:idf.adapterTargetName} write_flash --flash_mode dio --flash_freq 80m --flash_size detect 0x070000 ${workspaceFolder}/release/firmware/mxx610-app.bin 0x1000 ${workspaceFolder}/release/firmware/bootloader.bin 0x10000 ${workspaceFolder}/release/firmware/partition-table.bin 0x15000 ${workspaceFolder}/release/firmware/ota_data_initial.bin 0x17000 ${workspaceFolder}/release/firmware/phy_init_data.bin 0x39000 ${workspaceFolder}/release/firmware/storage_data.bin",       
            "dependsOrder": "sequence",
            "dependsOn": ["TEST Release", "ESP-IDF Erase ALL", "ESP-IDF WRITE ALL"]
        
        },
//아래의 경우, 상위 내가 정의한 변수를 이용하여 각각 Python TEST Program을 Jenkins 처럼 사용하고 있다. 
        {
            "label": "TEST MODBUS-CHK-EventGR",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/modbus/modbus_test_check_rspevent_general.py -p ${config:idf.RS485Port} -b ${config:idf.RS485Baudrate}  "
        },
        {
            "label": "TEST MODBUS-CHK-EventBT",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/modbus/modbus_test_check_rspevent_burst.py -p ${config:idf.RS485Port} -b ${config:idf.RS485Baudrate}  -r ${config:idf.RS485ResponseTimeout}  -u ${config:idf.RS485MaxUnit}  -i ${config:idf.RS485TimerInterval} -t ${config:idf.RS485TesTimeHour}  "
        },
        {
            "label": "TEST MODBUS-CHK-SystemInfo",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/modbus/modbus_test_check_systeminfo.py -p ${config:idf.RS485Port} -b ${config:idf.RS485Baudrate}  -r ${config:idf.RS485ResponseTimeout}  -u ${config:idf.RS485MaxUnit}  -i ${config:idf.RS485TimerInterval} -t ${config:idf.RS485TesTimeHour}  "
        },
        
//나의 경우는 다양하게 최대한 편한게 사용하도록 하고 있으며, Jenkins가 없이 쉽게 Task로 모든 TEST 가 가능하다 
        {
            "label": "TEST MQTT ONLY Subscribe",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/mqtt/mqtt_only_subscribe.py"
        },
        {
            "label": "TEST MQTT General Publish",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/mqtt/mqtt_publish_general.py"
        },
        {
            "label": "TEST MQTT RSPSetup Publish",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe ${workspaceFolder}/main/module/mqtt/mqtt_publish_rspsetup.py"
        },    
        
//다만 현재 Window인데, Embedded Python으로 설치해서 사용해야 다른 이에게 동일한 환경을 전해줄 수 있으므로, 추천         
// Linux에서도 VS Code가 사용가능한데, 좀 더 화려하게 사용가능하다. (grep.xargs,sed/awk 비롯하여 tee 등)  Python venv 기반으로 추천  
// EPS-IDF는 Window or Linux 이건 Python은 venv되어있지만, Window에서는 좀 venv를 사용하기가 좀 귀찮다. (export.ps1) 
        {
            "label": "TEST Python List",
            "type": "shell",
            "command": "& D:/Tools/python/python-3.7.5-embed-amd64/python.exe -m pip list  "
        },      
        
// 아래와 같이 Powershell에서 Linux의 Pipe를 비롯하여 간단한 명령어 비롯하여, tee 역시 지원가능하다, 
// Powershell이 매번 Upgrade 될때마다, 매번 Linux Command를 좀 더 다양하게 지원해주는 것 같다.              
        {
            "label": "TEST Shell",
            "type": "shell",
            "command": "echo Hellow | tee ${workspaceFolder}/test.log  "
        }           
     ]
}

모든예제를 기록할 수 없지만, 아래의 predefined 변수(variable)을 비롯하여, Powershell 변수(variable) 이외 외부 설정된 변수 (variable)가능 
더불어 조금 더 고급스럽게 사용하고자 한다면, Node.js는 필수인것 같다. 
이 부분은 추후 다시 사용하도록 하자 

참고로 VS Code도 계속 업그레이드 중이며, Task 내부 Command도 업그레이드 되면서 새로 추가된 것이니, 추후에도 계속 VS Code Manual는 봐야한다.
앞으로 계속 추가되어 변경되어질테니 ㅋㅋㅋ (나중에 Jenkins 없이 자동화로 해도 되겠다)

  • 상위 Tasks.json 과 launch.json 에 사용되어지는 내부환경변수(predefined)
  1. ${workspaceFolder}  : Project PATH
  2. ${userHome} : User Home PATH
VS Code에서 predefined-variables 내부변수로 반드시 확인 
각 값들은 기본으로 알아두도록하자 

  • Tasks.Json 세부 구성방법 
세부사항은 VS Code도 항상 업데이트 되므로 아래 사이트에서 사용방법과 구조를 확인
매번 VS Code가 업데이트 될때 마다 조금씩 변경됨 (Node.js도 지원됨) 
  1. version
  2. configurations
  3. tasks
  4. inputs

  • PowerShell 변수 사용법 
PowerShell에서 사용하는 변수를 동일하게 사용가능 

  • Tasks.json에서 외부 설정된 변수값 (settings.json) 사용법 
VS Extension에 이미 설정되어진것의 값 or settings.json 에서도 변수 값 가져와 tasks.json에서 사용가능하다.

예를들면 VS Code의 extension인 ESP-IDF를 설치하면, 아래에서 각 값들을 찾을수 있다. 
or VS Code의 각 Extension manual을 보면 각 값의 용도 설명을 알려준다. 

ESP-IDF 의 vscode-esp-idf-extension Github
설사 상위 Manual이 없다고 해도 .vscode/extensions/xxxxx 관련부분을 본인이 직접 분석하면된다. 

외부의 환경변수 값을 사용할 경우, 
아래와 같이 ${config:xxxxx} 로 형태로 사용하면된다.  
  1. ${config:idf.portWin} : 현재 settings.json 설정된 Port
  2. ${config:idf.adapterTargetName}: 현재 settings.json 설정된 Target
  3. ${config:idf.pythonBinPathWin} : ESP-IDF Python PATH

ESP-IDF ${config:xxxxx} 의 다양한 예제 
VS Extension에는 이미 숨겨진 환경값도 많으니, 관련사항을  찾아 보도록 하자
더불어 Task도 depends on을 이용하여 Chaining도 가능  


  • Tasks.json에서 Command들 간의 종속연결(depends) 
Tasks.json에서 Command를 많이 만들 경우, 한꺼번에 연속으로 실행하여, 자동화를 하고 싶을 경우가 많을 것이다.  
이 때 사용하는게 dependsOrder dependson 이며 이를 이용하여 쉽게 각 Command들을 종속연결하여 실행가능하다  
상위와 같이 간단히 자동화를 할수 있다. 

  • VSCode JSON 기본사용법 
JSON의 기본문법으로 어떻게 사용하는지 확인 



3. VS Code Tips Update 

주로 사용하는 것이 멀티커서 에디팅이며 다른 Tips들도 알아두도록하자. 

VS Code의 사용 Tips 관련사항 

VS Code Multi Cursor
좌측으로 이동정렬: Shift+Tab
우측으로 이동정렬: Tab



VS Code Markdown View

VS code Search / Modify (Regular Expression)

VS Code에서 diff 기능 

3/15/2020

Raspberry Pi3 에 Yocto 와 Qt 적용한 Image (정리못함)

1. Raspberry Pi 와 Qt5 관련정보사항 


Yocto Recipe 작성방법 


기본적으로 Raspberry Pi 기반으로 나만의 Qt를 이용하여 나만의 Yocto로 구성하고자하는 마음으로 이것을 시작했다. 

  • Raspberry Pi용 Image 생성 (Yocto 기반)
Raspberry Pi에 적용할 Yocto 기반으로 구성된 Qt를 포함 Image를 생성하는 방법 
  1. 이미 구성된 Yocto Layer들과 Recipe들을 직접 Download 
  2. Yocto의 각 Layer들 별로 Download 후 별도의 Image Recipe를 구성하여 빌드 

간단하게만 Build 테스트 만 했지만, 실제로 Image를 Write해서 다 확인하지는 않았으며, 틀린부분은 추후 시간이 있을 때 수정하여 보완하도록 하자.

  • 상위 진행결과   
완벽히는 구성을 못했지만, Qt기반으로 실행가능한 정도로만 구성하여 동작확인을 하였다. 
아래와 같이 Laptop이 아래와 같이 Ubuntu Laptop 지워져서 정리 포기함  

상위 부분은 앞으로 진행못할 거 같으며, 추후 기회가 있다면 그때 다시 하도록 하자. 
그리고, 아래의 내용은 이전에 정리해둔 것이므로 나중에 참조만 하도록하자.
이후 변경된 내용은 백업을 못한 내 잘못이 더 크다. 

그리고, 칩제조사 TI/NXP에서 제공하는 Yocto가 아닌 Poky 와 OpenEmbedded 기반으로 간단하게 구성하여 누구나 할 수 있다. 


1.1  이미 구성된 Yocto 기반으로 Image 생성 

Yocto를 별도로 구성할 필요 없이 repo를 이용하여 Yocto를 전체 Layer들을 직접 Download 한 후 Manual 대로 설정 한 후 bitbake로 실행하여 Image 생성 


QT 관련설치
  https://doc.qt.io/QtForDeviceCreation/qtee-custom-embedded-linux-image.html
  https://code.qt.io/cgit/yocto/boot2qt-manifest.git/tree/

  • 기존에 존재하는 Yocto (QT 테스트)
아래와 같이 처음 Qt 테스트 진행 
$ sudo apt-get install gawk curl git-core git-lfs diffstat unzip texinfo build-essential \
chrpath libsdl1.2-dev xterm gperf bison gcc-multilib g++-multilib repo

$ cd rasp-qt

$ repo init -u git://code.qt.io/yocto/boot2qt-manifest -m warrior.xml  // ok

$ repo init -u git://code.qt.io/yocto/boot2qt-manifest -m zeus.xml // not work 

$ repo sync

$ MACHINE=raspberrypi3 source ./setup-environment.sh

$ bitbake b2qt-embedded-qt5-image

$ bitbake meta-toolchain-b2qt-embedded-qt5-sdk


2. Yocto 의 Layer를 직접 구성 후 Image 생성 

본인이 Yocto의 Main인 Poky 부터 필요한 Layer들을 각 모아서 구성한 후, 필요한 Image recipe 역시 직접 만들어서 구성한 후, 
이 기반으로 최종 Raspberry Pi Image 생성 

  • 이전에 구성한 Raspberry Pi Yocto 

  • Yocto에서 먼저확인 해봐야할 것
Yocto의 Version 정보와 Dependencies 이 될 것 같다. 
항상 최신버전만을 받았지만, 이번에는 다양한 Version을 받아보기 위해서 일단 아래에서 branch 정보를 파악해서 원하는 것으로 받기로 했다.

  • QT 설치방법 
현재 Image가 안되며, layer를 추가한 후 아래 medium을 똑같이 해보자
  https://makersweb.net/embedded/12540
  https://medium.com/@shigmas/yocto-pi-and-qt-e9f2df38a610
  https://jumpnowtek.com/rpi/Raspberry-Pi-Systems-with-Yocto.html

  • Yocto Version(Branch) 정보확인 
Yocto에 Version에 부여된 이름이 각각 존재 (zeus로 version(branch) 결정)

  • 본인 설치할 Layer 선택
  1. ref -> Branch 및 Tag  확인 
  2. about->Dependencies 확인 
  http://git.yoctoproject.org/cgit.cgi/
  https://www.yoctoproject.org/software-overview/layers/
  http://layers.openembedded.org/layerindex/branch/master/layers/


  • meta-raspberrypi 의 branch 파악
Yocto version: zeus 파악
  http://git.yoctoproject.org/cgit.cgi/meta-raspberrypi/refs/
  https://js94.tistory.com/entry/Yocto-Project-Reference-manual-chap3-35

  • Yocto 의 Layer를 각 구성 방법  
  1. 상위와는 다르게 각각의 Layer들을 별도로 다운받아 본인 직접구성 (poky, openembedded)
  2. 별도의 Layer들을 추가하는 방식으로 구성
  3. 추후 더 필요하다면 확장하는 방식으로 구성 
$ mkdir -p works/raspberrypi/sources

$ cd works/raspberrypi/source

$ pwd
/home/jhlee/works/raspberrypi/sources

$ git clone -b zeus  git://git.yoctoproject.org/poky
$ git clone -b zeus  git://git.openembedded.org/meta-openembedded
$ git clone -b zeus  https://github.com/agherzan/meta-raspberrypi
$ git clone -b zeus  git://github.com/meta-qt5/meta-qt5.git       // 처음에 못찾다가 상위 Layer에서 찾음 


  • 기본구성 후 conf/machine 확인 
우선 machine Layer 의 설정을 알기 위해서 검색 
물론 QEMU도 확인가능 
$ find . -name machine | xargs ls   // conf/machine 관련된 부분 전부 검색 
./meta-raspberrypi/conf/machine:
include     raspberrypi0-wifi.conf  raspberrypi3-64.conf  raspberrypi4-64.conf  raspberrypi-cm3.conf  raspberrypi.conf
raspberrypi0.conf  raspberrypi2.conf    raspberrypi3.conf  raspberrypi4.conf     raspberrypi-cm.conf

./poky/meta/conf/machine:
include  qemuarm.conf qemumips64.conf  qemuppc.conf    qemux86-64.conf
qemuarm64.conf qemuarmv5.conf qemumips.conf  qemuriscv64.conf  qemux86.conf

./poky/meta-selftest/conf/machine:
qemux86copy.conf

./poky/meta-yocto-bsp/conf/machine:
beaglebone-yocto.conf  edgerouter.conf genericx86-64.conf  genericx86.conf  include  mpc8315e-rdb.conf 

MACHINE 설정부터 BBLAYERS 확인  
$ find . -name local.conf*  // conf/local.conf 부분 검색 
./poky/meta-poky/conf/local.conf.sample
./poky/meta-poky/conf/local.conf.sample.extended


$ vi ./poky/meta-poky/conf/local.conf.sample  // 추후 build에 이 파일 기준으로 적용됨 
....
MACHINE ?= "raspberrypi3-64"
# This sets the default machine to be qemux86-64 if no other machine is selected:
#MACHINE ??= "qemux86-64"


$ vi ./poky/meta-poky/conf/bblayers.conf.sample // 추후 build에 이 파일 기준으로 적용됨, Build 설정 이후로 수정하기로 결정  

BBLAYERS ?= " \
  ##OEROOT##/meta \
  ##OEROOT##/meta-poky \
  ##OEROOT##/meta-yocto-bsp \
  "

  • 현재 구성된 Yocto 구성도 

$ pwd
/home/jhlee/works/raspberrypi/sources

$ tree -t -L 2   // Yocto 전체 Layer와 각 구성확인 
.
├── meta-openembedded
│   ├── contrib
│   ├── COPYING.MIT
│   ├── meta-filesystems
│   ├── meta-gnome
│   ├── meta-initramfs
│   ├── meta-multimedia
│   ├── meta-networking
│   ├── meta-oe
│   ├── meta-perl
│   ├── meta-python
│   ├── meta-webserver
│   ├── meta-xfce
│   └── README
├── meta-raspberrypi
│   ├── classes
│   ├── conf
│   ├── COPYING.MIT
│   ├── docs
│   ├── dynamic-layers
│   ├── files
│   ├── README.md
│   ├── recipes-bsp
│   ├── recipes-connectivity
│   ├── recipes-core
│   ├── recipes-devtools
│   ├── recipes-graphics
│   ├── recipes-kernel
│   ├── recipes-multimedia
│   └── wic
├── poky
│   ├── bitbake
│   ├── contrib
│   ├── documentation
│   ├── LICENSE
│   ├── LICENSE.GPL-2.0-only
│   ├── LICENSE.MIT
│   ├── meta
│   ├── meta-poky
│   ├── meta-selftest
│   ├── meta-skeleton
│   ├── meta-yocto-bsp
│   ├── oe-init-build-env
│   ├── README.hardware -> meta-yocto-bsp/README.hardware
│   ├── README.OE-Core
│   ├── README.poky -> meta-poky/README.poky
│   ├── README.qemu
│   └── scripts
└── meta-qt5
    ├── classes
    ├── conf
    ├── COPYING.MIT
    ├── files
    ├── lib
    ├── licenses
    ├── README.md
    ├── recipes-connectivity
    ├── recipes-devtools
    ├── recipes-multimedia
    ├── recipes-python
    └── recipes-qt

  • Build 환경구성 
기본 Build 환경구성 확인 과 Build 
$ cd ..

$ pwd
/home/jhlee/works/raspberrypi

$ source sources/poky/oe-init-build-env rpi-build  // Yocto Poky 기반으로 Build 환경설정 
or
$ . sources/poky/oe-init-build-env rpi-build

### Shell environment set up for builds. ###

You can now run 'bitbake <target>'

Common targets are:
    core-image-minimal
    core-image-sato
    meta-toolchain
    meta-ide-support

You can also run generated qemu images with a command like 'runqemu qemux86'


Other commonly useful commands are:
 - 'devtool' and 'recipetool' handle common recipe tasks
 - 'bitbake-layers' handles common layer tasks
 - 'oe-pkgdata-util' handles common target package task

$ pwd
/home/jhlee/works/raspberrypi/rpi-build

  • Build 환경구성 확장  
BBLAYERS에 추가된 Layer들을 추가하여 확장하여 이를 확장 
$ cd .. 

$ pwd
/home/jhlee/works/raspberrypi

$ tree -t -L 2  // Yocto 전체 Layer 와 Build 관련부분 파악 
.
├── sources
│   ├── meta-openembedded
│   ├── meta-raspberrypi
│   ├── meta-qt5
│   └── poky
└── rpi-build
    └── conf

$ cd ./rpi-build  // Build 환경으로 다시  

$ JHLEE=$HOME/works/raspberrypi/sources

$ echo $JHLEE
/home/jhlee/raspberrypi/sources

$ cat conf/bblayers.conf 
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /home/jhlee/works/raspberrypi/sources/poky/meta \
  /home/jhlee/works/raspberrypi/sources/poky/meta-poky \
  /home/jhlee/works/raspberrypi/sources/poky/meta-yocto-bsp \
  "

//meta-raspberrypi 필요한 Layer들 별도로 추가 (dependecies)
$ echo "BBLAYERS += \"$JHLEE/meta-openembedded/meta-oe\"" >> conf/bblayers.conf
$ echo "BBLAYERS += \"$JHLEE/meta-openembedded/meta-multimedia\"" >> conf/bblayers.conf
$ echo "BBLAYERS += \"$JHLEE/meta-openembedded/meta-networking\"" >> conf/bblayers.conf
$ echo "BBLAYERS += \"$JHLEE/meta-openembedded/meta-python\"" >> conf/bblayers.conf

$ echo "BBLAYERS += \"$JHLEE/meta-raspberrypi\"" >> conf/bblayers.conf
$ echo "BBLAYERS += \"$JHLEE/meta-qt5\"" >> conf/bblayers.conf

$ cat conf/bblayers.conf    // 최종 bitbake Layer 관련설정 확인  
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  /home/jhlee/works/raspberrypi/sources/poky/meta \
  /home/jhlee/works/raspberrypi/sources/poky/meta-poky \
  /home/jhlee/works/raspberrypi/sources/poky/meta-yocto-bsp \
  "
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-oe"
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-multimedia"
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-networking"
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-python"
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-raspberrypi"
BBLAYERS += "/home/jhlee/works/raspberrypi/sources/meta-qt5"

// priority 의 경우 어떻게 측정되는 지 추후 더 파악 (만약 Package가 제대로 설치되어있지 않으면 실행이 안됨) 
$ bitbake-layers show-layers  
NOTE: Starting bitbake server...
layer                 path                                      priority
==========================================================================
meta                  /home/jhlee/works/raspberrypi/sources/poky/meta  5
meta-poky             /home/jhlee/works/raspberrypi/sources/poky/meta-poky  5
meta-yocto-bsp        /home/jhlee/works/raspberrypi/sources/poky/meta-yocto-bsp  5
meta-oe               /home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-oe  6
meta-multimedia       /home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-multimedia  6
meta-networking       /home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-networking  5
meta-python           /home/jhlee/works/raspberrypi/sources/meta-openembedded/meta-python  7
meta-raspberrypi      /home/jhlee/works/raspberrypi/sources/meta-raspberrypi  9
meta-qt5              /home/jhlee/works/raspberrypi/sources/meta-qt5  7


  • 전체 Image Recipe 찾기 
현재 사용중인 Image Recipe를 찾아 역으로 분석하여 기본구조를 파악하자 
$ find ../sources -name *image*.bb   // bitbake 의 image bb recipe 파일 전부 검색  
../sources/meta-openembedded/meta-filesystems/recipes-filesystems/images/meta-filesystems-image-base.bb
../sources/meta-openembedded/meta-filesystems/recipes-filesystems/images/meta-filesystems-image.bb
../sources/meta-openembedded/meta-webserver/recipes-core/images/meta-webserver-image-base.bb
../sources/meta-openembedded/meta-webserver/recipes-core/images/meta-webserver-image.bb
../sources/meta-openembedded/meta-multimedia/recipes-multimedia/images/meta-multimedia-image-base.bb
../sources/meta-openembedded/meta-multimedia/recipes-multimedia/images/meta-multimedia-image.bb
../sources/meta-openembedded/meta-initramfs/recipes-bsp/images/initramfs-debug-image.bb
../sources/meta-openembedded/meta-initramfs/recipes-bsp/images/initramfs-kexecboot-klibc-image.bb
../sources/meta-openembedded/meta-initramfs/recipes-bsp/images/initramfs-kexecboot-image.bb
../sources/meta-openembedded/meta-initramfs/recipes-core/images/meta-initramfs-image.bb
../sources/meta-openembedded/meta-networking/recipes-core/images/meta-networking-image.bb
../sources/meta-openembedded/meta-networking/recipes-core/images/meta-networking-image-base.bb
../sources/meta-openembedded/meta-xfce/recipes-core/images/core-image-minimal-xfce.bb
../sources/meta-openembedded/meta-python/recipes-core/images/meta-python-image-base.bb
../sources/meta-openembedded/meta-python/recipes-core/images/meta-python-ptest-image.bb
../sources/meta-openembedded/meta-python/recipes-core/images/meta-python-image.bb
../sources/meta-openembedded/meta-oe/recipes-core/images/meta-oe-image-base.bb
../sources/meta-openembedded/meta-oe/recipes-core/images/meta-oe-ptest-image.bb
../sources/meta-openembedded/meta-oe/recipes-core/images/meta-oe-image.bb
../sources/meta-openembedded/meta-oe/recipes-graphics/libsdl/libsdl-image_1.2.12.bb
../sources/meta-openembedded/meta-oe/recipes-graphics/libsdl/libsdl2-image_2.0.3.bb
../sources/meta-openembedded/meta-oe/recipes-support/imagemagick/imagemagick_7.0.8.bb
../sources/meta-openembedded/meta-perl/recipes-perl/images/meta-perl-ptest-image.bb
../sources/meta-openembedded/meta-perl/recipes-perl/images/meta-perl-image.bb
../sources/meta-raspberrypi/recipes-core/images/rpi-hwup-image.bb
../sources/meta-raspberrypi/recipes-core/images/rpi-basic-image.bb
../sources/meta-raspberrypi/recipes-core/images/rpi-test-image.bb
../sources/poky/meta-skeleton/recipes-multilib/images/core-image-multilib-example.bb
../sources/poky/meta-selftest/recipes-test/container-image/container-image-testpkg.bb
../sources/poky/meta-selftest/recipes-test/container-image/container-test-image.bb
../sources/poky/meta-selftest/recipes-test/images/wic-image-minimal.bb
../sources/poky/meta-selftest/recipes-test/images/test-empty-image.bb
../sources/poky/meta-selftest/recipes-test/images/error-image.bb
../sources/poky/meta-selftest/recipes-test/images/oe-selftest-image.bb
../sources/poky/meta-selftest/recipes-test/multiconfig/multiconfig-image-packager_0.1.bb
../sources/poky/meta/recipes-extended/images/core-image-kernel-dev.bb
../sources/poky/meta/recipes-extended/images/core-image-testmaster.bb
../sources/poky/meta/recipes-extended/images/core-image-full-cmdline.bb
../sources/poky/meta/recipes-extended/images/core-image-testmaster-initramfs.bb
../sources/poky/meta/recipes-rt/images/core-image-rt.bb
../sources/poky/meta/recipes-rt/images/core-image-rt-sdk.bb
../sources/poky/meta/recipes-core/images/core-image-minimal.bb
../sources/poky/meta/recipes-core/images/core-image-tiny-initramfs.bb
../sources/poky/meta/recipes-core/images/core-image-minimal-dev.bb
../sources/poky/meta/recipes-core/images/build-appliance-image_15.0.0.bb
../sources/poky/meta/recipes-core/images/core-image-minimal-mtdutils.bb
../sources/poky/meta/recipes-core/images/core-image-minimal-initramfs.bb
../sources/poky/meta/recipes-core/images/core-image-base.bb
../sources/poky/meta/recipes-core/ovmf/ovmf-shell-image.bb
../sources/poky/meta/recipes-sato/images/core-image-sato-dev.bb
../sources/poky/meta/recipes-sato/images/core-image-sato-ptest-fast.bb
../sources/poky/meta/recipes-sato/images/core-image-sato-sdk.bb
../sources/poky/meta/recipes-sato/images/core-image-sato-sdk-ptest.bb
../sources/poky/meta/recipes-sato/images/core-image-sato.bb
../sources/poky/meta/recipes-graphics/images/core-image-weston.bb
../sources/poky/meta/recipes-graphics/images/core-image-clutter.bb
../sources/poky/meta/recipes-graphics/images/core-image-x11.bb
../sources/poky/meta/recipes-graphics/xorg-lib/xcb-util-image_0.4.0.bb
../sources/meta-qt5/recipes-qt/qt5/qtimageformats_git.bb

$ cd ../sources/meta-qt5
$ mkdir -p recipes-core/images
$ cd recipes-core/images

$ vi core-image-qt5.bb     // Qt기반으로 Image Recipe 파일 직접구성 (기본은 core-image-base) 
$ cat core-image-qt5.bb 
SUMMARY = "Qt5 image that fully supports the target device hardware."
LICENSE="MIT"

include recipe-core/images/core-image-base.bb

QT_BASE = " \
    qtbase \
    qtbase-dev \
    qtbase-mkspecs \
    qtbase-plugins \
    qtbase-tools \
"
 
QT_PKGS = " \
    qt3d \
    qt3d-dev \
    qt3d-mkspecs \
    qtcharts \
    qtcharts-dev \
    qtcharts-mkspecs \
    qtconnectivity-dev \
    qtconnectivity-mkspecs \
    qtquickcontrols2 \
    qtquickcontrols2-dev \
    qtquickcontrols2-mkspecs \
    qtdeclarative \
    qtdeclarative-dev \
    qtdeclarative-mkspecs \
    qtgraphicaleffects \
    qtgraphicaleffects-dev \
"

IMAGE_INSTALL += " \
    ${QT_BASE} \
    ${QT_PKGS} \
"

export IMAGE_BASENAME = "core-image-qt5"

$ bitbake core-image-qt5

$ devtool build core-image-qt5 source 

$ bitbake -e |grep IMAGE_FSTYPE

$ find .. -name bitbake.conf
../sources/poky/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf
../sources/poky/meta/conf/bitbake.conf

Build는 되지만, Image가 생성이 안되었으며,  간단하게 따라한 것이니, 추후에 시간이 있을 경우, QT Package 와 함께 
그때 세부적 분석한 후 관련 Recipe들을 수정하여 구성하자. 
너무 대충 구성한 것 같음. 


  • 아래는 Image Recipe를 만들때, 너무 좋은 예제인 것 같아, 추후에 참조 
LoRa 작업을 하면서 아래 Recipe를 각각 다 만들었는데,  괜찮게 만든 것 같아 추후에 다시 참조하며, Raspberry Pi3에 넣도록 하자 
Raspberry Pi3 와 LoRa Gateway 검색해보면 관련자료는 많이 나온다. 

LoRa Gateway 와 Packet Forwarder 

더불어 QT에도 추후에 추가도 가능하며, 이 부분은 Background로 돌리수도 있다. 

$ vi ../sources/meta-lora-net/recipes-core/images/core-lora-image.bb
SUMMARY = "Lora Gateway Image dev image"

include recipes-core/images/core-image-base.bb

IMAGE_INSTALL += "lora-gateway lora-pkt-fwd"

export IMAGE_BASENAME = "core-lora-image"

my_postprocess_function() {
   echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}

ROOTFS_POSTPROCESS_COMMAND += "my_postprocess_function; "


$ sample ROOTFS_POSTPROCESS_COMMAND
#
# Copyright (C) 2010 Intel Corporation.
#
require recipes-core/images/poky-image-minimal.bb

SRC_URI = "file://interfaces"

IMAGE_INSTALL += "dropbear mediatomb task-poky-nfs-server"

LICENSE = "MIT"

ROOTFS_POSTPROCESS_COMMAND += "setup_target_image ; "

# Manual workaround for lack of auto eth0 (see bug #875)
setup_target_image() {
       install -m 0644 ${WORKDIR}/interfaces ${IMAGE_ROOTFS}/etc/network/interfaces
}

$ gateway.bb

SUMMARY = "LoRa Gateway project"
SECTION = "libs/network"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=a2bdef95625509f821ba00460e3ae0eb"

SRC_URI = "https://github.com/Lora-net/lora_gateway/archive/v${PV}.tar.gz"

SRC_URI[md5sum] = "5d07f8471e1a67920787e3879afe0cb6"
SRC_URI[sha256sum] = "1a0447d5e8183d08e6dce5f739f6872b9c57824b98f4078830d5ee21b15782c1"

S = "${WORKDIR}/lora_gateway-${PV}"

CFLAGS_append = "-I ${S}/libloragw/inc -I ${S}/libloragw -I ${S}/util_pkt_logger/inc "

do_install() {
 bbplain "--------    Lora Gateway Install -----------------"
 install -d ${D}${bindir}
 install -d ${D}${docdir}
 install -d ${D}${libdir}/libloragw/inc
 install -d ${D}${includedir}/libloragw
 
 install -D -m 0644 ${B}/libloragw/inc/* ${D}${includedir}/libloragw
 
 install -D -m 0644 ${B}/libloragw/inc/* ${D}${libdir}/libloragw/inc
 install -D -m 0644 ${B}/libloragw/libloragw.a ${D}${libdir}/libloragw/libloragw.a
 install -D -m 0644 ${S}/libloragw/library.cfg ${D}${libdir}/libloragw/library.cfg
 
 install ${B}/libloragw/test_* ${D}${bindir}
 install ${B}/util_*/util_* ${D}${bindir}
 install ${S}/*.sh ${D}${bindir}
 
 install -D -m 0644 ${S}/readme.md ${D}${docdir}/libloragw/changelog.md
 install -D -m 0644 ${S}/libloragw/readme.md ${D}${docdir}/libloragw/README.md
 install -D -m 0644 ${S}/util_lbt_test/readme.md ${D}${docdir}/libloragw/util_lbt_test.md
 install -D -m 0644 ${S}/util_pkt_logger/readme.md ${D}${docdir}/libloragw/util_pkt_logger.md
 install -D -m 0644 ${S}/util_spectral_scan/readme.md ${D}${docdir}/libloragw/util_spectral_scan.md
 install -D -m 0644 ${S}/util_spi_stress/readme.md ${D}${docdir}/libloragw/util_spi_stress.md
 install -D -m 0644 ${S}/util_tx_continuous/readme.md ${D}${docdir}/libloragw/util_tx_continuous.md
 install -D -m 0644 ${S}/util_tx_test/readme.md ${D}${docdir}/libloragw/util_tx_test.md
 
 install -D -m 0644 ${S}/util_pkt_logger/global_conf.json ${D}${docdir}/libloragw/global_conf.json
 install -D -m 0644 ${S}/util_pkt_logger/local_conf.json ${D}${docdir}/libloragw/local_conf.json
}

PACKAGE_DEBUG_SPLIT_STYLE = "debug-without-src"

PACKAGES = "${PN}-dbg ${PN} ${PN}-doc ${PN}-dev ${PN}-staticdev"

# Avoid QA Issue: No GNU_HASH in the elf binary
INSANE_SKIP_${PN} = "ldflags"

FILES_${PN}-dbg = " \
 ${bindir}/.debug \
 ${libdir}/libloragw/.debug \
"
FILES_${PN} = " \
 ${bindir}/* \
 ${docdir}/* \
"
FILES_${PN}-dev = " \
 ${includedir}/libloragw/* \
"
FILES_${PN}-staticdev = " \
 ${libdir}/libloragw/inc/*.h \
 ${libdir}/libloragw/*.a \
 ${libdir}/libloragw/*.cfg \
"
FILES_${PN}-doc = " \
 ${docdir} \
"




$ packet.bb
SUMMARY = "LoRa network packet forwarder project"
SECTION = "libs/network"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=22af7693d7b76ef0fc76161c4be76c45"

SRC_URI = "https://github.com/Lora-net/packet_forwarder/archive/v${PV}.tar.gz"

SRC_URI[md5sum] = "a1f942e0cc7b02d604b11c8cb5f2a029"
SRC_URI[sha256sum] = "e68fadf6f1d2e5e7b601e504d5efb48b0a8f374c2c29c0476ab2fe9db68d33ae"

DEPENDS += "lora-gateway" 

S = "${WORKDIR}/packet_forwarder-${PV}"

CFLAGS_append = "-I ${includedir}/libloragw -I ${S}/lora_pkt_fwd/inc -I ${S}/util_tx_test/inc "

do_configure_prepend() {
 export LGW_PATH="${STAGING_LIBDIR}/libloragw"
}

do_compile_prepend() {
 export LGW_PATH="${STAGING_LIBDIR}/libloragw"
}

do_install() {
        bbplain "--------    Lora Packet Forward Install -----------------"
 install -d ${D}${bindir}
 install -d ${D}${docdir}/lora-pkt-fwd/conf
 
 install ${B}/lora_pkt_fwd/lora_pkt_fwd ${D}${bindir}
 install ${B}/util_*/util_* ${D}${bindir}
 
 install -D -m 0644 ${S}/PROTOCOL.TXT ${D}${docdir}/lora-pkt-fwd/PROTOCOL.TXT
 install -D -m 0644 ${S}/lora_pkt_fwd/readme.md ${D}${docdir}/lora-pkt-fwd/readme.md
 install -D -m 0644 ${S}/lora_pkt_fwd/global_conf.json ${D}${docdir}/lora-pkt-fwd/global_conf.json
 install -D -m 0644 ${S}/lora_pkt_fwd/local_conf.json ${D}${docdir}/lora-pkt-fwd/local_conf.json
 install -D -m 0755 ${S}/lora_pkt_fwd/update_gwid.sh ${D}${docdir}/lora-pkt-fwd
 install -D -m 0644 ${S}/lora_pkt_fwd/cfg/*.json.* ${D}${docdir}/lora-pkt-fwd/conf
 
 rm -f ${D}${bindir}/util_tx_test
 rm -f ${D}${bindir}/.debug/util_tx_test
}

PACKAGE_DEBUG_SPLIT_STYLE = "debug-without-src"

PACKAGES = "${PN}-dbg ${PN} ${PN}-doc"

# 상위에서 설명한 QA관련에러 
# Avoid QA Issue: No GNU_HASH in the elf binary
INSANE_SKIP_${PN} = "ldflags"

FILES_${PN}-dbg = " \
 ${bindir}/.debug \
"
FILES_${PN} = " \
 ${bindir}/* \
 ${docdir}/* \
"
FILES_${PN}-doc = " \
 ${docdir} \
"

$ packet.bbappend

## files로 만들경우, 기본 FILEPATH에 포함이 되어있으므로, 간단히 관리되며, Package 와 Version 별로 관리시 다음과 같이 관리  
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
#FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}:"
#FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}"
SRC_URI += "file://001_packet_forwarder_lora_pkt_fwd.c.patch"
SRC_URI += "file://002_packet_forwarder_global_conf.json.patch"



ROOTFS_PREPROCESS_COMMAND
ROOTFS_POSTPROCESS_COMMAND
SDK_POSTPROCESS_COMMAND
POPULATE_SDK_POST_TARGET_COMMAND
POPULATE_SDK_POST_HOST_COMMAND
IMAGE_POSTPROCESS_COMMAND
IMAGE_PREPROCESS_COMMAND

ROOTFS_POSTINSTALL_COMMAND
           
  https://www.yoctoproject.org/docs/latest/ref-manual/ref-manual.html#migration-1.6-variable-changes-variable-entry-behavior

Yocto PTEST
  https://wiki.yoctoproject.org/wiki/Ptest
  https://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#testing-packages-with-ptest


Image BB File 예제
  https://github.com/openembedded/openembedded-core/blob/master/meta/recipes-core/images/build-appliance-image_15.0.0.bb

Image BB File 예제와 PATCH
  https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842475/PetaLinux+Yocto+Tips

MD5 Checksum
  https://docs.windriver.com/bundle/Wind_River_Linux_Toolchain_and_Build_System_Users_Guide_8.0_1/page/tan1478821620236.html

  http://variwiki.com/index.php?title=Yocto_Build_Release

2/13/2020

SD/MMC 와 udev 재분석 과 Rule 생성

1.  SD/MMC Spec 및 기본확인법 

MMC 혹은 SDCard 관련 Spec을 다시 확인하고자 한다면 아래의 사이트에서 확인




  • MMC(SDCARD) 관련 Spec
  1. Part 1. Physical Layer Simplified Specification 
  2. Part A2. SD Host Controller Simplified Specification
  3. Part E1. SDIO Simplified Specification 
  4. Part E7. Wireless LAN Simplified Addendum
  5. 이외 
대부분의 기본적인 내용은 Part1. Physical Layer Simplified Specification 을 보면 구조 및 기본동작이 이해가가능하며,
UHS-II 관련부분이나 다른 SD 확장 API를 본다면 해당 문서를 참조

SD/MMC 관련 Spec Download
  https://www.sdcard.org/downloads/pls/

1.1 SD/MMC 정보확인 

SD/MMC 기본 Register


  • SD/MMC Register 확인 
$ find /sys -name cid  // CID Register 제조사 및 제품정보 파악가능 (Spec참조)
/sys/devices/soc0/soc/2100000.aips-bus/219c000.usdhc/mmc_host/mmc3/mmc3:0001/cid     //eMMC
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/cid     //SDCard 

$ find /sys -name csd //CSD를 통해 MMC의 Spec 및 성능파악 (Spec참조)
/sys/devices/soc0/soc/2100000.aips-bus/219c000.usdhc/mmc_host/mmc3/mmc3:0001/csd //eMMC
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/csd //SDCard 

$ find /sys -name scr // SDCard에 설정된 기본정보 (Databit,SDCard 종류) 확인가능 (Spec)
/sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/scr  //SDCard 

$ find /sys -name dsr or rca or ocr //기타정보들 
  • SD/MMC 기본정보파악 
$ find /sys -name ios // 쉽게 MMC의 정보파악 
/sys/kernel/debug/mmc3/ios  //eMMC
/sys/kernel/debug/mmc2/ios  //SDCard

$ cat /sys/kernel/debug/mmc3/ios  //eMMC 8bit
clock:          198000000 Hz
actual clock:   198000000 Hz
vdd:            21 (3.3 ~ 3.4 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      3 (8 bits)
timing spec:    9 (mmc HS200)
signal voltage: 1 (1.80 V)
driver type:    0 (driver type B)

$ cat /sys/kernel/debug/mmc2/ios  //SD Card 4bit
clock:          50000000 Hz
actual clock:   49500000 Hz
vdd:            18 (3.0 ~ 3.1 V)
bus mode:       2 (push-pull)
chip select:    0 (don't care)
power mode:     2 (on)
bus width:      2 (4 bits)
timing spec:    2 (sd high-speed)
signal voltage: 0 (3.30 V)
driver type:    0 (driver type B) 
  • SD Card의 경우 CD(Card Detection)/WP(Write Protection) 
$ cat /proc/interrupts | egrep "(mmc|cd)" // SDCard는 Hotplug를 위해 CD필요 
 63:        676       GPC  24 Level     mmc2  //SDCard
 64:       9336       GPC  25 Level     mmc3  //eMMC 
 78:          0       GPC   6 Edge      2224000.lcdif
126:          3  gpio-mxc  10 Edge      2198000.usdhc cd  //SDCard Card Detection (Hotplug)

// SD Card Detection의 GPIO 및 Trigger 및 IRQ 확인 
$ cat /sys/kernel/debug/gpio | grep cd  
 gpio-42  (                    |cd                  ) in  hi IRQ 
SD Card의 경우 CD 와 WP Pin을 GPIO로 연결하여 사용가능하며, 주로 CD 사용할 경우 Hotplug가능. WP 미사용

eMMC/SD Card 관련참고사항
  https://developer.toradex.com/knowledge-base/sd-mmc-card-(linux)

1.2 SD/MMC의 Kernel 관련정보 

  • i.MX Kernel Config
  1. MMC/SD/SDIO (CONFIG_MMC)
  2. MMC block (CONFIG_MMC_BLOCK)
  3. Secure Digital Host Controller Interface support (CONFIG_MMC_SDHCI)
  4. SDHCI support on the platform-specific bus (CONFIG_MMC_SDHCI_PLTFM)
  5. SDHCI platform support for the NXP eSDHC i.MX controller (CONFIG_MMC_SDHCI_ESDHC_IMX)

  • Kernel source의 drivers/mmc/host/  
  1. sdhci.c standard stack code
  2. sdhci-pltfm.c sdhci platform layer
  3. sdhci-esdhc.c uSDHC driver
  4. sdhci-esdhc-imx.c uSDHC driver header file

세부사항은 아래사이트 참고

  • i.MX 관련설정 (출처) 
MMC/SDCard/SDIO Kernel 설정을 비롯하여Device Tree 설정정보를제공
  https://www.digi.com/resources/documentation/digidocs/90001546/reference/bsp/cc6/r_mmc-sd-sdio.htm


  • MMC/SD Device Driver 세부분석 
새로 SD/MMC를 분석할 필요는 없는 것 같아 아래사이트를 참조하여 이해만하고 넘어감
  http://egloos.zum.com/furmuwon/v/11167927

  • SDCard 관련부분 Uboot 및 Kernel 설정 (Sitara/i.MX)
아래사이트에서 쉽게 설정이 가능하도록 제공
  https://www.digikey.com/eewiki/pages/viewpage.action?pageId=35193201#BeagleBoneBlack-uEnv.txtbasedbootscript
  https://www.digikey.com/eewiki/display/linuxonarm/i.MX6+SABRE+Lite
  https://developer.toradex.com/knowledge-base/sd-mmc-card-(linux)


1.3  Kernel의 Netlink uevent 와 udev 통신 

Kernel은 udevNETLINK_KOBJECT_UEVENT로 통신을 하고 있으며, 이곳에 add_uevent_var의 환경설정값을 추가하여 통신을 진행한다.
Kernel은 이외에도 다른 NETLINK도 사용하니 이것만 사용한다고 착각하지말자.

  • udev의 NETLINK_KOBJECT_UEVENT
ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
user에서 socket으로 protocol을 NETLINK_KOBJECT_UEVENT로 설정 
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L751

  • SD/MMC 관련소스
아래부분은 SD/MMC에서 공통으로사용되는 부분으로 필요할때만 보고, Chip Vendor관련부분은 상위에서 처럼 관련부분은 별도로 보자.
  https://elixir.bootlin.com/linux/v4.17.19/source/drivers/mmc/core
  https://elixir.bootlin.com/linux/v4.17.19/source/drivers/mmc/core/mmc.c

  • kobject_uevent->kobject_uevent_env
보통 uevent는 아래와 같이 동작을 하며, 아래와 같이 각각의 환경변수값을 uevent와 함께보내면, udevd은 이를 받아 database로 기록하여 사용한다고한다.
  1. retval = add_uevent_var(env, "ACTION=%s", action_string);
  2. retval = add_uevent_var(env, "DEVPATH=%s", devpath);
  3. retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
  4. retval = add_uevent_var(env, "%s", envp_ext[i]);  // 상위 NULL 이지만 sys에서 설정가능
  5. retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
  6. 기타 값 
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L454


  • kobject_synth_uevent 관련함수
  https://elixir.bootlin.com/linux/v4.20.4/source/lib/kobject_uevent.c#L192


  • kobject_uevent_env 의 확장값을 넣어 전송
  1. LEASE=1    :  상위 3번의 envp_ext[i] 값 설정 
  2. HOTPLUG=1 : 상위 3번의 envp_ext[i] 값 설정 
  https://elixir.bootlin.com/linux/v4.20.4/source/drivers/gpu/drm/drm_sysfs.c#L322
  https://elixir.bootlin.com/linux/v4.20.4/source/drivers/gpu/drm/drm_sysfs.c#L304


  • kobject 와 sysfiletem을 세부적으로 분석 (반드시 참고)
*** 관련내용을 찾다가 아래사이트에서 자세히 분석해줘서 이해하기가 더 쉬움 (감사할 따름)
  http://jake.dothome.co.kr/kobject/


  • device driver의 attribute의 구성을 쉽게 이해가능 (sys file system 구성)
attribute는 sys filesystem의 구성이기때문에 반드시 사용법 숙지하며, 이외에도 가끔 소스를 보면 다른 것도 존재하는 것 같은데, 그 부분은 추후 추가
  1. device_attribute
  2. bus_attribute
  3. class_attribute
  4. driver_attribute

오래전의 linux kernel과 attribute설정방법은 조금 다르지만 거의 비슷함
  http://jake.dothome.co.kr/device-driver-1/

2. udev 분석 및 테스트진행 

현재 udevadm command로 통합이되어 관련명령어를 모두 사용이 가능하며, 이를 이용하여 udev의 정보 및 테스트도 진행이 가능하다.

$ udevadm -h
udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]

Send control commands or test the device manager.

Commands:
  info          Query sysfs or the udev database  //
  trigger       Request events from the kernel
  settle        Wait for pending udev events
  control       Control the udev daemon
  monitor       Listen to kernel and udev events
  test          Test an event run
  test-builtin  Test a built-in command


  http://fibrevillage.com/sysadmin/93-udevadm-command-examples

2.1 udevadm info 기본분석방법 

udevadm info를 이용하여 udev의 database 정보와 sysfs 정보를 확인가능하므로, 이를 이용하여 udev 분석이 쉬어진다.

$ udevadm info  -h
udevadm info [OPTIONS] [DEVPATH|FILE]

Query sysfs or the udev database.

  -h --help                   Print this message
  -V --version                Print version of the program
  -q --query=TYPE             Query device information:
       name                     Name of device node
       symlink                 Pointing to node
       path                     sysfs device path
       property                The device properties
       all                      All values
  -p --path=SYSPATH           sysfs device path used for query or attribute walk
  -n --name=NAME              Node or symlink name used for query or attribute walk
  -r --root                   Prepend dev directory to path names
  -a --attribute-walk         Print all key matches walking along the chain
                              of parent devices
  -d --device-id-of-file=FILE Print major:minor of device containing this file
  -x --export                 Export key/value pairs
  -P --export-prefix          Export the key name with a prefix
  -e --export-db              Export the content of the udev database
  -c --cleanup-db             Clean up the udev database



  • sys filesystem의 uevent의 환경변수 값 확인 (udev database정보)
$ udevadm info  /dev/mmcblk2p1 
or
$ udevadm info  -q all /dev/mmcblk2p1 
or
$ udevadm info  /sys/block/mmcblk2/mmcblk2p1  // 3개의 정보들이 거의 동일하지만,DEVLINKS정보가 조금씩 다름 
// /sys/device/..../mmcblk2p1의 uevnet 파악가능 (P는 /sys PATH)
P: /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1     
N: mmcblk2p1   // /dev의 device node /dev/mmcblk2p1 
S: disk/by-id/mmc-SA02G_0x207dfb75-part1       // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-id/mmc-SA02G_0x207dfb75-part1
S: disk/by-partuuid/0006c3b0-01                // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-partuuid/0006c3b0-0
S: disk/by-path/platform-2198000.usdhc-part1   // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-path/platform-2198000.usdhc-part1
S: disk/by-uuid/1497-59AD                      // 상위 N의 /dev/mmcblk2p1 의 link file /dev/disk/by-uuid/1497-59AD
E: DEVLINKS=/dev/disk/by-path/platform-2198000.usdhc-part1 /dev/disk/by-uuid/1497-59AD /dev/disk/by-partuuid/0006c3b0-01 /dev/disk/by-id/mmc-SA02G_0x207dfb75-part1
E: DEVNAME=/dev/mmcblk2p1
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1
E: DEVTYPE=partition
E: ID_FS_TYPE=vfat
E: ID_FS_USAGE=filesystem
E: ID_FS_UUID=1497-59AD
E: ID_FS_UUID_ENC=1497-59AD
E: ID_FS_VERSION=FAT32
E: ID_NAME=SA02G
E: ID_PART_ENTRY_DISK=179:24
E: ID_PART_ENTRY_NUMBER=1
E: ID_PART_ENTRY_OFFSET=73036
E: ID_PART_ENTRY_SCHEME=dos
E: ID_PART_ENTRY_SIZE=3002164
E: ID_PART_ENTRY_TYPE=0xc
E: ID_PART_ENTRY_UUID=0006c3b0-01
E: ID_PART_TABLE_TYPE=dos
E: ID_PART_TABLE_UUID=0006c3b0
E: ID_PATH=platform-2198000.usdhc
E: ID_PATH_TAG=platform-2198000_usdhc
E: ID_SERIAL=0x207dfb75
E: MAJOR=179
E: MINOR=25
E: PARTN=1
E: SUBSYSTEM=block
E: TAGS=:systemd:                   //  systemd의 *.device로 파일에서 추가됨 
E: USEC_INITIALIZED=7347510      //  cat /proc/uptime 갱신된 정보시간 (boot이후)

$ udevadm info  /dev/mmcblk2
or
$ udevadm info  -q all /dev/mmcblk2
or
$ udevadm info  /sys/block/mmcblk2
P: /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 // uevent 정보확인 
N: mmcblk2
S: disk/by-id/mmc-SA02G_0x207dfb75
S: disk/by-path/platform-2198000.usdhc
E: DEVLINKS=/dev/disk/by-id/mmc-SA02G_0x207dfb75 /dev/disk/by-path/platform-2198000.usdhc
E: DEVNAME=/dev/mmcblk2
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2
E: DEVTYPE=disk
E: ID_NAME=SA02G
E: ID_PART_TABLE_TYPE=dos
E: ID_PART_TABLE_UUID=0006c3b0
E: ID_PATH=platform-2198000.usdhc
E: ID_PATH_TAG=platform-2198000_usdhc
E: ID_SERIAL=0x207dfb75
E: MAJOR=179
E: MINOR=24
E: SUBSYSTEM=block
E: TAGS=:systemd:             //  systemd의 *.device로 파일에서 추가됨 
E: USEC_INITIALIZED=6995415  //  cat /proc/uptime 갱신된 정보시간 (boot이후)


TAGS=:systemd 일 경우 systemd의 *.device로 udev rule에 추가
  https://www.freedesktop.org/software/systemd/man/systemd.device.html

systemd-udevd service 

  • 좌측 Node 의미 및 분석방법 
  1. N: is for device Name in /dev
  2. S: is for Symlinks to that device name in /dev  (추후 udev/rules/에서 SYMLINK)
  3. P: is for device Path in /sys
  4. E: is for device properties in udev
  https://askubuntu.com/questions/725951/what-do-devices-environment-variable-lists-prefixes-p-n-s-e-mean


  • P: Node는 /sys의 device path이므로 이곳의 uevent 를 확인중요
uevent 중심으로 분석을 해야함
$ cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1/uevent
MAJOR=179
MINOR=25
DEVNAME=mmcblk2p1
DEVTYPE=partition
PARTN=1

$ cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/uevent
MAJOR=179
MINOR=24
DEVNAME=mmcblk2
DEVTYPE=disk


  • N: /dev의 device name 확인
$ ls /dev/mmcblk*
/dev/mmcblk2       /dev/mmcblk3       /dev/mmcblk3boot1  /dev/mmcblk3p2
/dev/mmcblk2p1     /dev/mmcblk3boot0  /dev/mmcblk3p1     /dev/mmcblk3rpmb 

  • S:  상위 N: /dev의 device name의 symbolic link list 
상위 N:의 /dev/mmclbk2 or /dev/mmcblk2p1의 /dev 내의 symbolic link 말하며,이는 DEVLINKS와 동일하다.
rule에서도 SYMLINK을 이용하여 추가도 가능함

$ ls /dev/disk/by-id/
mmc-S0J57X_0x09231300        mmc-SA02G_0x207dfb75
mmc-S0J57X_0x09231300-part1  mmc-SA02G_0x207dfb75-part1
mmc-S0J57X_0x09231300-part2

$ ls /dev/disk/by-path/
platform-2198000.usdhc        platform-219c000.usdhc-boot1
platform-2198000.usdhc-part1  platform-219c000.usdhc-part1
platform-219c000.usdhc        platform-219c000.usdhc-part2
platform-219c000.usdhc-boot0

  • E: uevent를 통해 udev 설정된 환경값 
이부분은 아래와 기본정보는 /sys 의 uevent 로 확인가능하며, 다른정보는 database에서 가져옴

  • 이외 다른 uevent 값 검색 분석 
$ find /sys -name uevent | xargs cat  // 대부분 Device 정보 와 호환정보(연결)
....
MAJOR=253
MINOR=0
DEVNAME=rtc0
OF_NAME=snvs
OF_FULLNAME=/soc/aips-bus@2000000/snvs@20cc000
OF_COMPATIBLE_0=fsl,sec-v4.0-mon
OF_COMPATIBLE_1=syscon
OF_COMPATIBLE_2=simple-mfd
OF_COMPATIBLE_N=3
...
$ find /sys -name uevent | xargs cat | grep DEVLINKS
없음 
$ find /sys -name uevent | xargs cat | grep DEVNAME
DEVNAME=mem
DEVNAME=zero
DEVNAME=kmsg
DEVNAME=full
DEVNAME=urandom
DEVNAME=null
DEVNAME=random
DEVNAME=pxp_device
DEVNAME=hwrng
DEVNAME=autofs
......

2.2 udevadm info 의 attribute 분석 

udev의 기본적인 uevent의 정보와 sys filesystem의 attribute를 분석할때, -a를 옵션을 주어 분석이 가능하다.
ATTR{x}는 해당 /sys file 주소의 값들을 출력을 해주며, 추후 rule에서도 이를 적용가능하다.

  1. uevent 정보(KERNEL/SUBSYSTEM/DRIVER) 
  2. attribute 정보(ATTR{xxx}  

parent기반으로 분석되기때문에 호출되는 순서를 파악가능하며 최종단을 주목

$ udevadm info -a /dev/mmcblk2   // /dev node로  모든 attribute를 출력 
or
$ udevadm info -a /sys/block/mmcblk2  //sys filesystem의 모든 attribute를 출력 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
// 아래 looking at device 위치에 /sys file의 uevent node 확인 (최종 device의 길이 중요)
  looking at device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2':  
    KERNEL=="mmcblk2"     //device의 node name (상위 device의 마지막 node)  uevent 정보는 별도의 db를 가지고 있음 
    SUBSYSTEM=="block"    //mmcblk2의 SUBSYSTEM   
    DRIVER==""            //uevent 의 정보 
    ATTR{alignment_offset}=="0"      // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/alignment_offset
    ATTR{capability}=="50"           // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/capability
    ATTR{discard_alignment}=="0"     // cat /sys/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/ext_range
    ATTR{ext_range}=="256"           //  ATTR{x} 모두 상동  
    ATTR{force_ro}=="0"
    ATTR{hidden}=="0"
    ATTR{inflight}=="       0        0"
    ATTR{range}=="8"
    ATTR{removable}=="0"
    ATTR{ro}=="0"
    ATTR{size}=="3842048"
    ATTR{stat}=="      95       16     6363      545        0        0        0        0        0      400      440        0        0        0        0"
// Parent device 의 uevent이며, 분석에 중요하며, SD Card Device의 정보를 얻은 시점 
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234':  //   
    KERNELS=="mmc2:1234"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="02544d534130324704207dfb7500a800"     // MMC의 Register CID  
    ATTRS{csd}=="002e00325b5aa3a9ffffff800a800000"     // MMC의 Register CSD   
    ATTRS{date}=="08/2010"                             // 날짜정보, Filesystem 기준으로 생각됨  
    ATTRS{dsr}=="0x404"                                // MMC의 Register DSR  
    ATTRS{erase_size}=="512"                           // MMC의 경우 512 block 단위임  
    ATTRS{fwrev}=="0x4"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x000002"                          // 제조사 ID  
    ATTRS{name}=="SA02G"                               // SD Card Name 
    ATTRS{ocr}=="0x00040000"                           // MMC의 Register OCR  
    ATTRS{oemid}=="0x544d"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{rca}=="0x1234"                               // MMC의 Register RCA  
    ATTRS{scr}=="0225800001000000"                     // MMC의 Register SCR  
    ATTRS{serial}=="0x207dfb75"
    ATTRS{ssr}=="00000000000000280202900100aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"                                   // SD Card 임, eMMC가 아님  
// Parent device 의 uevent  SD Card Device를 찾은시점 
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2':
    KERNELS=="mmc2"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc':
    KERNELS=="2198000.usdhc"
    SUBSYSTEMS=="platform"
    DRIVERS=="sdhci-esdhc-imx"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"

$ udevadm info -a  /dev/mmcblk2p1  // 각 Partition 정보와 비교 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
// uevent node 확인가능. 상위 node에 mmcblk2p1 추가되었으며,나머지는 동일
  looking at device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1':
    KERNEL=="mmcblk2p1"
    SUBSYSTEM=="block"
    DRIVER==""
    ATTR{alignment_offset}=="0"
    ATTR{discard_alignment}=="354304"
    ATTR{inflight}=="       0        0"
    ATTR{partition}=="1"
    ATTR{ro}=="0"
    ATTR{size}=="3002164"
    ATTR{start}=="73036"
    ATTR{stat}=="      53       16     4275      309        0        0        0        0        0      260      270        0        0        0        0"
// 상위 (udevadm info -a /dev/mmcblk2)  동일한 device node 이며 상위와 완전동일  
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2':
    KERNELS=="mmcblk2"
    SUBSYSTEMS=="block"
    DRIVERS==""
    ATTRS{alignment_offset}=="0"
    ATTRS{capability}=="50"
    ATTRS{discard_alignment}=="0"
    ATTRS{ext_range}=="256"
    ATTRS{force_ro}=="0"
    ATTRS{hidden}=="0"
    ATTRS{inflight}=="       0        0"
    ATTRS{range}=="8"
    ATTRS{removable}=="0"
    ATTRS{ro}=="0"
    ATTRS{size}=="3842048"
    ATTRS{stat}=="      95       16     6363      545        0        0        0        0        0      400      440        0        0        0        0"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234':
    KERNELS=="mmc2:1234"
    SUBSYSTEMS=="mmc"
    DRIVERS=="mmcblk"
    ATTRS{cid}=="02544d534130324704207dfb7500a800"
    ATTRS{csd}=="002e00325b5aa3a9ffffff800a800000"
    ATTRS{date}=="08/2010"
    ATTRS{dsr}=="0x404"
    ATTRS{erase_size}=="512"
    ATTRS{fwrev}=="0x4"
    ATTRS{hwrev}=="0x0"
    ATTRS{manfid}=="0x000002"
    ATTRS{name}=="SA02G"
    ATTRS{ocr}=="0x00040000"
    ATTRS{oemid}=="0x544d"
    ATTRS{preferred_erase_size}=="4194304"
    ATTRS{rca}=="0x1234"
    ATTRS{scr}=="0225800001000000"
    ATTRS{serial}=="0x207dfb75"
    ATTRS{ssr}=="00000000000000280202900100aa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
    ATTRS{type}=="SD"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2':
    KERNELS=="mmc2"
    SUBSYSTEMS=="mmc_host"
    DRIVERS==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2198000.usdhc':
    KERNELS=="2198000.usdhc"
    SUBSYSTEMS=="platform"
    DRIVERS=="sdhci-esdhc-imx"
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus':
    KERNELS=="2100000.aips-bus"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""
    ATTRS{driver_override}=="(null)"

  looking at parent device '/devices/soc0':
    KERNELS=="soc0"
    SUBSYSTEMS=="soc"
    DRIVERS==""
    ATTRS{family}=="Freescale i.MX"
    ATTRS{revision}=="1.4"
    ATTRS{soc_id}=="i.MX6SX"


2.3  udevadm monitor를 이용확인

udevadm의 monitor를 이용하여 sdcard의 card detection 부분을 체크

$ udevadm monitor  -h
udevadm monitor [OPTIONS]

Listen to kernel and udev events.

  -h --help                                Show this help
  -V --version                             Show package version
  -p --property                            Print the event properties
  -k --kernel                              Print kernel uevents
  -u --udev                                Print udev events
  -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem
  -t --tag-match=TAG                       Filter events by tag


실시간 모니터로 아래와 같이 uevent를 볼수 있으며 옵션을 추가하여 각 event를 더 확인하자.

$ udevadm monitor
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

mmc2: card 1234 removed
KERNEL[179853.651358] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
KERNEL[179853.654058] remove   /devices/virtual/bdi/179:24 (bdi)
KERNEL[179853.654755] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
UDEV  [179853.662386] remove   /devices/virtual/bdi/179:24 (bdi)
KERNEL[179853.671233] unbind   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
KERNEL[179853.671436] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179853.699415] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
UDEV  [179853.704243] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
UDEV  [179853.715698] unbind   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179853.716975] remove   /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
mmc2: host does not support reading read-only switch, assuming write-enable
mmc2: new high speed SD card at address 1234
KERNEL[179860.947683] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179860.956872] add      /devices/soc0/soc/2100000.aips-bummcblk2: mmc2:1234 SA02G 1.83 GiB
s/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
KERNEL[179860.966523] add      /devices/virtual/bd mmcblk2: p1
i/179:24 (bdi)
UDEV  [179860.977474] add      /devices/virtual/bdi/179:24 (bdi)
KERNEL[179860.978045] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
KERNEL[179860.980267] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
KERNEL[179860.983182] bind     /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)
UDEV  [179861.117857] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2 (block)
FAT-fs (mmcblk2p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
UDEV  [179861.423592] add      /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234/block/mmcblk2/mmcblk2p1 (block)
UDEV  [179861.426851] bind     /devices/soc0/soc/2100000.aips-bus/2198000.usdhc/mmc_host/mmc2/mmc2:1234 (mmc)


3. udev Rule 만드는 법 

udevadm info 와 monitor를 통해 기본 udev의 정보와 sys file system의 정보를 이용하여 udev rule을 간단히 만들어보자.

  • udev rule의 기본저장장소
  1. /lib/udev/rules.d/
  2. /etc/udev/rules.d/  : User는 이곳에 설정하여 추가해서 넣자 
  3. /dev/udev/rules.d/

  • Rule에서 기본적으로 match되는 정보  
  1. KERNEL : device의 kernel 이름 , device의 이름과 match
  2. SUBSYSTEM : device의 subsystem과 match
  3. DRIVER: device와 관련된 driver name과 match
  4. NAME:  /dev 에서 사용되어지는 device node와 match  
  5. SYMLINK: NAME의 대신에 사용되어지는 symbloic link list
  6. ATTRS{x}: 상위 sys filesystem의 정보와 match
  7. ENV{DEVLINKS}: 상위 E: Node 정보와 match 

  • matching 할때 pattern 
  1. *:  어느 문자들이든 match
  2. ?:  어느 한 문자만  match
  3. []:  범위를 정해서 match

  • Event 와 실행 
  1. ACTION: 해당 정보의 device가 add or remove , change가 있을 경우 
  2. RUN : 조건이 충족되면 실행을 하는 command 

RUN에 ENV{ } 정보를 출력하고 싶다면, %E{xx}로 사용가능
SYMLINK를 이용하여 /dev에 새로 device node의 symblolic link 생성가능
좀 더 사용을 하면 GOTO와 LABEL을 사용하며, 예제를 보면 쉽게 이해가 가능


3.1  MMC Device 와 udev Rule 생성 

  • MMC의 동작 rule 생성 및 적용 
mmcblk2p 가 Hotplug 될 때, add와 remove에 맞게 간단히 RUN을 사용하여 작성

$ cat /etc/udev/rules.d/10-mmc.rules  //RUN을 추가하여 지속적으로 실행가능 
# Mount and remove mmc partitions manually for 32G  
# udevadm info /dev/mmcblk2 에서 E DEVNAME 부분확인 , 상위 환경변수부분 참조

ACTION=="add" KERNEL=="mmcblk[2]p[0-9]", RUN+="/bin/mkdir -p /media/card", RUN+="/bin/mount %E{DEVNAME} /media/card"
ACTION=="remove" KERNEL=="mmcblk[2]p[0-9]", RUN+="/bin/umount -f /media/card" , RUN+="/bin/rmdir /media/card"


udev Basic Rule 사용법 (systemd-udevd.service에서 관리)
  https://www.freedesktop.org/software/systemd/man/udev.html#
  http://www.reactivated.net/writing_udev_rules.html
  https://wiki.debian.org/udev

udev Rule의 예제 및 udevadm 사용법
  https://gnu-linux.org/writing-udev-rules-for-flash-drive.html
  https://kernel.googlesource.com/pub/scm/linux/hotplug/udev/+/1ed38f41749dde482e164e692255b60c38b5d876/etc/udev/rules.d/80-drivers.rules

udev 관련 Kernel 설정
  https://wiki.gentoo.org/wiki/Udev/ko


3.2 다른 Device 와 systemd 의 Service 연결적용 

  • udev 의 device(ttyACM0) 기본분석

일반적으로 많이 사용되는 USB Serial ttyACM에 udev에 연결하여 systemd 와 함께 service 할 수 있도록 설정.

$ ls /dev/ttyACM0                // USB serial 존재파악 

$ udevadm info -a -n /dev/ttyACM0                    // udev 값 분석 및 각 ATTRS 값 확인 


// 분석방법은 아래와 같이 최종 driver 단 기준부터 그 위의 KERNEL/SUBSYSTEM/ ATTRS  중심으로 파악  
...........
  looking at device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0':
    KERNEL=="ttyACM0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0':
    KERNELS=="1-1.1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="cdc_acm"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="02"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bInterfaceProtocol}=="01"
    ATTRS{bInterfaceSubClass}=="02"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{bmCapabilities}=="7"
    ATTRS{iad_bFirstInterface}=="00"
    ATTRS{iad_bFunctionClass}=="02"
    ATTRS{iad_bFunctionProtocol}=="01"
    ATTRS{iad_bFunctionSubClass}=="02"
    ATTRS{iad_bInterfaceCount}=="02"
    ATTRS{interface}=="PLSx"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1':
    KERNELS=="1-1.1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="ef"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="02"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}=="14"
    ATTRS{bcdDevice}=="1730"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="5"
    ATTRS{devpath}=="1.1"
    ATTRS{devspec}=="  (null)"
    ATTRS{idProduct}=="005b"
    ATTRS{idVendor}=="1e2d"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Cinterion Wireless Modules"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="PLSx"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{rx_lanes}=="1"
    ATTRS{speed}=="480"
    ATTRS{tx_lanes}=="1"
    ATTRS{urbnum}=="122"
    ATTRS{version}==" 2.00"
.............
  looking at parent device '/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{authorized_default}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0419"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{idProduct}=="0002"
    ATTRS{idVendor}=="1d6b"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.19.35-1.1.0+g0f9917c ehci_hcd"
    ATTRS{maxchild}=="1"
    ATTRS{product}=="EHCI Host Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{rx_lanes}=="1"
    ATTRS{serial}=="ci_hdrc.1"
    ATTRS{speed}=="480"
    ATTRS{tx_lanes}=="1"
    ATTRS{urbnum}=="25"
    ATTRS{version}==" 2.00"
.....

// USB CDC 중 ACM은 일반적으로 USB Serial로 많이 사용되지만, 꼭 Serial으로만 사용해야하는 것은 아니다. 
// 세부사항은 USB CDC 종류에서 각각 파악하자  

$ udevadm info -a -n /dev/ttyACM0 | grep serial  // ttyACM0을 USB Serial로 사용하기 위해 serial 이름파악 
ATTRS{serial}=="ci_hdrc.1"

  • udev 의 device(ttyACM0) 와 systemd 의 service 연결
각 udev rule에서 ttyACM 관련부분을 검색 한 후 이를 분석한 후, 직접 수정
$ find /etc/udev/rules.d/  -name *ttyACM*  // udev file 찾기 (우선순위 etc -> lib) 못찾으면 grep 사용 
$ find /lib/udev/rules.d/  -name *ttyACM*  

// 나의 경우, KERENL에, ttyACM0을 넣고, serial을 더 좀 더 확실히 하기 위해 ATTRS{serial} 추가했지만, 자기 구성대로 변경
// SYSTEMD_WANTS 사용시 udev database에 TAG+="systemd" 넣지 않는다면, systemd에서 찾지 못한다 (세부내용은 Manual)  
// 이기능은 systemd의 Want=에 추가되며, 추후 systemd의 *.socket 의 BindToDevice= 와 연결가능 

$ cat /etc/udev/rules.d/20-ttyACM0.rules  // KERNEL의 Device 와 Serial 이름으로 동작 
KERNEL=="ttyACM0", ATTRS{serial}=="ci_hdrc.1" , TAG+="systemd", ENV{SYSTEMD_WANTS}="my.service"

udev Rule에 TAG+="systemd"와 ENV{SYSTEMD_WANTS} 와 udev Database
  https://www.freedesktop.org/software/systemd/man/systemd.device.html
  https://www.freedesktop.org/software/systemd/man/udev.html#

  • 연결될 systemd의 service 구성

systemd의 service 중 (BindToDevice대신) BindTo 와 After 부분설정을 위해 각 값 검색
$ systemctl list-units --all --full   //  systemctl list-units --all --full 의 정보가 너무 많음 
$ systemctl list-units --all --full | grep ".device"   //  systemctl list-units --all --full 의 정보가 너무 많아 device만 찾음 

// device 구성을 보면, parent가 존재하므로, 점점 node가 길어지면, 최종으로 load되는 부분을 찾아야함 
// systemd.device에서 ttyACM0 or 상위 ATTR 값을 넣어 검색범위를 좁힘 
$ systemctl list-units --all --full | grep ".device" | grep "ci_hdrc.1" // systemd.device 에 상위 ATTR 값 동일부분확인
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.0.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.2.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.4.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.6.device                                              loaded    active   plugged   PLSx         
  dev-serial-by\x2dpath-platform\x2dci_hdrc.1\x2dusb\x2d0:1.1:1.8.device                                              loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.10-net-usb0.device   loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.12-net-usb1.device   loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.2-tty-ttyACM1.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.4-tty-ttyACM2.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.6-tty-ttyACM3.device loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.8-tty-ttyACM4.device loaded    active   plugged   PLSx

$ systemctl list-units --all --full | grep ".device" | grep "ttyACM0" // systemd.device 에 ttyACM0 재확인 
  dev-ttyACM0.device                                                                                                  loaded    active   plugged   PLSx         
  sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device loaded    active   plugged   PLSx

udev Rule에 같이 동작할 systemd 의 service 설정
**system unit 과 system.service manual 참조
//상위 udev의 Rule에서 적용했던 부분이 동작할 경우 실행 (ttyACM0) 
//Unit의 BindTo 와 After를 *.service로만 한정지어 생각했는데, device를 비롯하여 mount 등 모두 가능
//Unit의 대상은 모든 systemd의 설정의 기본이며, service/socket/device/mount/등 모두 적용대상
$ vi /lib/systemd/system/my.service 
or 
$ vi /etc/systemd/system/my.service 
[Unit]
Description=TEST Service for ttyACM0
BindsTo=sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device
After=sys-devices-soc0-soc-2100000.aips\x2dbus-2184200.usb-ci_hdrc.1-usb1-1\x2d1-1\x2d1.1-1\x2d1.1:1.0-tty-ttyACM0.device

# BindsTo 는 Requires 와 유사하게 dependencies를 요구하는 설정이며, Requres 보다 좀 더 강력하다고 하며, 
# After와 함께 같이 사용할때 최적이라고 한다.
# 주의 할 것은 Fail 될 경우, Skip되므로 이 부분 주의하며, 상위 Device가 연결될때 Timing을 기다림

[Service]
ExecStart=test start 

[Install]
WantedBy=multi-user.target

  1. udev에서 ttyACM0 상위정보의 uevent가 오면 이를 udev에 TAG를 사용하여 systemd에 노출하고 service로 연결
  2. 상위 service에서 AfterBindsTo는 systemd의 service에 연결하여 Timing을 조절(제대로 붙기전에는 실행 불가능) 

아래의 사이트에서 쉽게 찾아 연결했으며, 세부내용은 아래사이트 참조

systemd의 unit 과 service 설정정보
  https://www.freedesktop.org/software/systemd/man/systemd.unit.html
  https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Mapping%20of%20unit%20properties%20to%20their%20inverses
  https://www.freedesktop.org/software/systemd/man/systemd.service.html#


$ udevadm info /dev/ttyACM0 // 상위 실행 후 동작확인 
P: /devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0
N: ttyACM0
S: serial/by-id/usb-Cinterion_Wireless_Modules_PLSx-if00
S: serial/by-path/platform-ci_hdrc.1-usb-0:1.1:1.0
E: DEVLINKS=/dev/serial/by-path/platform-ci_hdrc.1-usb-0:1.1:1.0 /dev/serial/by-id/usb-Cinterion_Wireless_Modules_PLSx-if00
E: DEVNAME=/dev/ttyACM0
E: DEVPATH=/devices/soc0/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/tty/ttyACM0
E: ID_BUS=usb
E: ID_MODEL=PLSx
E: ID_MODEL_ENC=PLSx
E: ID_MODEL_ID=005b
E: ID_PATH=platform-ci_hdrc.1-usb-0:1.1:1.0
E: ID_PATH_TAG=platform-ci_hdrc_1-usb-0_1_1_1_0
E: ID_REVISION=1730
E: ID_SERIAL=Cinterion_Wireless_Modules_PLSx
E: ID_TYPE=generic
E: ID_USB_CLASS_FROM_DATABASE=Miscellaneous Device
E: ID_USB_DRIVER=cdc_acm
E: ID_USB_INTERFACES=:020201:0a0000:020200:020600:
E: ID_USB_INTERFACE_NUM=00
E: ID_USB_PROTOCOL_FROM_DATABASE=Interface Association
E: ID_VENDOR=Cinterion_Wireless_Modules
E: ID_VENDOR_ENC=Cinterion\x20Wireless\x20Modules
E: ID_VENDOR_ID=1e2d
E: MAJOR=166
E: MINOR=0
E: SUBSYSTEM=tty
E: SYSTEMD_WANTS=my.service   // systemd service 확인 
E: TAGS=:systemd:             // TAG의 systemd 추가 확인 
E: USEC_INITIALIZED=19217285

udev 와 systemd 연결
  https://unix.stackexchange.com/questions/89691/how-do-i-connect-a-3g-dongle-using-systemd

systemd 기본사용법
  https://ahyuo79.blogspot.com/2020/01/systemd.html


4. udevadm test 와 trigger를 이용하여 테스트 

새로 만든 udev rule에 ACTION Event를 주어 SW로만 테스트 진행가능하며, 본인이 좀 더 세부 테스트를 한다면, 다양한 옵션설정도 가능.

아래의 두가지 방식으로 테스트 가능

  • udev 의 테스트 방식 

$ udevadm test -h
$ udevadm test [OPTIONS] DEVPATH

Test an event run.

  -h --help                            Show this help
  -V --version                         Show package version
  -a --action=ACTION                   Set action string
  -N --resolve-names=early|late|never  When to resolve names


  • udev에 uevent를 주어 테스트 진행 

 $ udevadm trigger  -h
udevadm trigger [OPTIONS] DEVPATH

Request events from the kernel.

  -h --help                         Show this help
  -V --version                      Show package version
  -v --verbose                      Print the list of devices while running
  -n --dry-run                      Do not actually trigger the events
  -t --type=                        Type of events to trigger
          devices                     sysfs devices (default)
          subsystems                  sysfs subsystems and drivers
  -c --action=ACTION                Event action value, default is "change"
  -s --subsystem-match=SUBSYSTEM    Trigger devices from a matching subsystem
  -S --subsystem-nomatch=SUBSYSTEM  Exclude devices from a matching subsystem
  -a --attr-match=FILE[=VALUE]      Trigger devices with a matching attribute
  -A --attr-nomatch=FILE[=VALUE]    Exclude devices with a matching attribute
  -p --property-match=KEY=VALUE     Trigger devices with a matching property
  -g --tag-match=KEY=VALUE          Trigger devices with a matching property
  -y --sysname-match=NAME           Trigger devices with this /sys path
     --name-match=NAME              Trigger devices with this /dev name
  -b --parent-match=NAME            Trigger devices with that parent device
  -w --settle                       Wait for the triggered events to complete


실제테스트 진행 
  • 상위 만들어진 rule에 SW로 테스트 진행 (문제발생)
$ udevadm test -a remove /dev/mmcblk2
or
$ udevadm test -a remove  /sys/block/mmcblk2
calling: test
version 239
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

Load module index
Skipping empty file: /etc/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /etc/udev/rules.d/10-imx.rules
Reading rules file: /etc/udev/rules.d/30-mmc.rules
Reading rules file: /lib/udev/rules.d/50-firmware.rules
Reading rules file: /lib/udev/rules.d/50-udev-default.rules
Reading rules file: /lib/udev/rules.d/60-block.rules
Reading rules file: /lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /lib/udev/rules.d/60-drm.rules
Reading rules file: /lib/udev/rules.d/60-evdev.rules
Reading rules file: /lib/udev/rules.d/60-input-id.rules
Reading rules file: /lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /lib/udev/rules.d/60-sensor.rules
Reading rules file: /lib/udev/rules.d/60-serial.rules
Reading rules file: /lib/udev/rules.d/64-btrfs.rules
Reading rules file: /lib/udev/rules.d/70-joystick.rules
Reading rules file: /lib/udev/rules.d/70-mouse.rules
Reading rules file: /lib/udev/rules.d/70-power-switch.rules
Reading rules file: /lib/udev/rules.d/70-touchpad.rules
Reading rules file: /lib/udev/rules.d/70-uaccess.rules
Reading rules file: /lib/udev/rules.d/71-seat.rules
Reading rules file: /lib/udev/rules.d/73-seat-late.rules
Reading rules file: /lib/udev/rules.d/75-net-description.rules
Reading rules file: /lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /lib/udev/rules.d/78-sound-card.rules
Reading rules file: /lib/udev/rules.d/80-drivers.rules
Reading rules file: /lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /lib/udev/rules.d/90-vconsole.rules
Reading rules file: /lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Reading rules file: /etc/udev/rules.d/touchscreen.rules
rules contain 24576 bytes tokens (2048 * 12 bytes), 11107 bytes strings
1602 strings (19400 bytes), 1040 de-duplicated (8856 bytes), 563 trie nodes used
unable to open device '/sys/dev/mmcblk2'   //문제발생 /sys/dev/의 구조가 다르며, /sys로 변경해도 동일, /dev/mmcblk2 현재없어서 인것 같음 
Unload module index
Unloaded link configuration context.

$ udevadm test -a add /dev/mmcblk2 
$ udevadm test -a add  /sys/block/mmcblk2

다시 trigger 기반으로 테스트진행시 문제없음 
  • 상위 만들어진 rule에 SW로 테스트 진행 (문제없음)
$ udevadm trigger -c add /dev/mmcblk2   // RUN 동작확인 
$ udevadm trigger -c remove /dev/mmcblk2 // RUN 동작확인