3 장치 트리의 프로세싱 코어


제 01 _ _ 소스 분석 커널은 DTB의 간단한 처리를 head.S를보기 바란다

부트 로더 실행 커널, R0, R1, R2 세 개의 레지스터를 설정하면,
R0는 일반적으로 0으로 설정하고,
R1이 일반적으로 (디바이스 트리를 사용하는 경우,이 파라미터는 사용되지 않는다) 컴퓨터 ID에 설정되고, 기판의 사용을 나타내는
ATAGS R2 제공된 발송 시작 주소 또는 DTB

: 커널 매개 변수는 부트 로더에 전달하는 두 가지 방법이 있습니다
ATAGS 또는 DTB는

"- 자신의 부트 로더를 쓰기 졸업 클래스 비디오"ATAGS 매개 변수 전달 방법의 경우, 우리는 참조 할 수 있습니다

 

__lookup_processor_type :. 어셈블러 명령은 CPU의 ID가합니다 (CPU, 정보 등의 초기화 기능 포함)이 ID에 따라 대응 proc_info_list 구조를 찾아 읽고
B의 __vet_atags :를 가능한 ATAGS 또는 DTB합니다 (DTB 파일이 있는지 여부를 판단 형식 또는 파일 형식 ATAGS R2)의 종류를 결정하는 위치
, 즉 가상 어드레스와 물리 어드레스 사이의 매핑, C __create_page_tables :. 페이지 테이블을 생성
D __enable_mmu :. MMU가 활성화되고, 필요한 가상 어드레스 후,
E. __mmap_switched : 상기 함수 __mmap_switched 호출한다
. R2는 부트 로더 파라미터를 전달 f를 가변 __atags_pointer에 저장
G 콜 C 함수 start_kernel.

-head.S를 / 헤드 common.S :
부트 로더 변수 C (R1)에 할당 된 값을 온 : __machine_arch_type
부트 로더는 변수 C에 할당 R2 값 온 : // __atags_pointer DTB 제 어드레스

제 02 _ 장치 트리 플랫폼 정보 (선택 machine_desc)의 처리
A. 호환 장치 속성 루트 노드는, 일련의 문자열을 나열
, 그것은 보드 이름과 호환되는지 나타내는
두 번째 자리에 "가장 호환"에서

B. 복수의 machine_desc 커널
보드 나타내는 문자열 배열을 가리키는 부재 dt_compat 상기 machine_desc 지원

., compatile 속성을 사용하여 (C)의 값
으로
각각 machine_desc.dt_compat
비교
은 "일관된 위치 compatile 속성 값"의 결과가

더욱 일치 점수 하부 해당 machine_desc 선택한다


함수 호출 :
start_kernel // 초기화 / 메인 이 .c
  setup_arch (COMMAND_LINE) // 아치 / ARM / 커널 / setup.c
    MDESC = setup_machine_fdt (__ atags_pointer) // 아치 / ARM / 커널 / devtree.c
      early_init_dt_verify (phys_to_virt (dt_phys)이 결정 // 유효한 DTB 여부, 드라이버 / ftd.c /의
          initial_boot_params = params 객체를 파라미터,
      MDESC = of_flat_dt_match_machine (mdesc_best, arch_get_next_mach); //이 / ftd.c의 / 드라이버 최고의 경기 machine_desc을 찾을
      그동안 ((데이터 = get_next_compat (의 compat))) {
점수 = of_flat_dt_match (dt_root,의 compat)
IF (점수> 0 && 점수 <BEST_SCORE) {
best_data = 데이터;
BEST_SCORE = 점수;
}
}

machine_desc = MDESC;



구성 제 03 처리 정보 _ 때 장치 트리를 실행합니다

函数调用过程:
start_kernel // 초기화 / main.c에
setup_arch (COMMAND_LINE); // 아치 / 팔 / 커널 / setup.c
MDESC = setup_machine_fdt (__ atags_pointer); // 아치 / 팔 / 커널 / devtree.c의
early_init_dt_scan_nodes (); // 드라이버 / / ftd.c의
에 / * / * 선택된 노드 /로부터 각종 정보를 검색
(early_init_dt_scan_chosen, boot_command_line) of_scan_flat_dt 단계;

/ * 초기화는 {크기는 주소} 정보 * / β- 세포
of_scan_flat_dt (early_init_dt_scan_root, NULL);

/ * 설정 메모리, * / early_init_dt_add_memory_arch 호출
of_scan_flat_dt (early_init_dt_scan_memory, NULL을);

. 글로벌 변수에 저장된 속성 값 bootargs / 선택된 노드 : boot_command_line의
B는 두 개의 루트 속성 값 :. # 어드레스 셀 #의 결정 크기 셀
글로벌 변수에 저장된 : dt_root_addr_cells, dt_root_size_cells를
. 분석 C 속성 메모리 / 등록 추출 "기본 크기"최종 통화 memblock_add (염기 크기)


부 04 device_node을 _dtb 변환된다 (패턴 화 해제)

函数调用过程:
start_kernel // 초기화 / main.c에
setup_arch (COMMAND_LINE); // 아치 / 팔 / 커널 / setup.c
arm_memblock_init (MDESC); // 아치 / 팔 / 커널 / setup.c
early_init_fdt_reserve_self를 ();
/ *으로 예약 DTB 영역 * /
//把DTB所占区域保留下来,调用即: memblock_reserve의
early_init_dt_reserve_memory_arch (__ PA (initial_boot_params)를
fdt_totalsize (initial_boot_params),
0);
early_init_fdt_scan_reserved_mem (); //根据DTB中的memreserve信息,调用memblock_reserve

unflatten_device_tree (); // 아치 / 팔 / 커널 / setup.c
__unflatten_device_tree (initial_boot_params, NULL, & of_root,
early_init_dt_alloc_memory_arch, 거짓); // 드라이버 / / fdt.c의

/ * 첫 번째 패스, 크기 * 스캔 /
크기 = unflatten_dt_nodes (BLOB, NULL, 아빠, NULL);

/ * 확장 장치 트리를위한 메모리를 할당 * /
MEM = dt_alloc (크기 + 4, __ (구조체 device_node __alignof));

/ * 번째 패스, 실제 unflattening * / 수행
unflatten_dt_nodes (BLOB, MEM, 아빠, mynodes)를;
populate_node의
NP = unflatten_dt_alloc (MEM,는 sizeof (구조체 device_node) + allocl,
__alignof __ (구조체 device_node));

NP-> FULL_NAME = FN = ((숯 *) NP) +는 sizeof (* NP);

populate_properties의
(MEM,는 sizeof (구조체의 특성), PP = unflatten_dt_alloc
__ (구조체 속성 __alignof));

PP-> NAME = (숯 *) PNAME;
PP-> 길이 = SZ;
PP-> 값 = (__be32 *) 발;

가. DTB 파일에서
태그의 각 노드 (FDT_BEGIN_NODE가가 0x00000001) 시작하고, 노드가 다른 노드에 중첩 될 수 있고,
각각의 속성은 (FDT_PROP, 0x00000003) TAG 시작

. 구조로 전환 각 노드 device_node을 B :
구조체 {device_node의
CONST 숯불 * 이름 // name 속성 노드에서 속성이 아닌 경우는,이 "NULL"로 설정
CONST 숯불 * 입력]에서 // 노드 이 "NULL"세트 속성없이 DEVICE_TYPE 속성
에 pHandle에 pHandle;
CONST * CHAR FULL_NAME // 노드의 이름, 노드 이름 [@ 단위 주소]
구조체 fwnode_handle fwnode;

구조체의 특성 * 특성; // 속성 노드의
구조체 속성 * deadprops / * 제거 속성 * /
구조체 device_node * 부모; // 노드 아버지
구조체 device_node * 아이, 어린이 (자식 노드) // 노드
구조체 device_node * 형제; // 형제 노드 (피어 노드)
(CONFIG_OF_KOBJ) 정의의 #if
상기 kobject Kobj 구조체
#endif 다음
부호 긴 _flags를,
무효 * 데이터,
정의의 #if (CONFIG_SPARC)
CONST 숯 *의 path_component_name]
부호 INT UNIQUE_ID;
구조체 of_irq_controller * irq_trans;
#endif 다음
};

. C device_node 구조 속성 가진다 노드의 특성을 나타낸다
: 구조의 속성에 대응하는 속성의 각
구조체 속성 {
CHAR * 이름 // 속성 이름, 문자열 DTB의 파일 포인터
INT 길이 // 속성 길이 값
무효 * 값; // 속성 값, 포인트 값 DTB 위치 파일 데이터가 여전히 큰 엔디안에 저장되어있는
구조체 * 속성 다음;
(CONFIG_OF_DYNAMIC) || 정의 (CONFIG_SPARC) 정의 #IF
서명되지 않은 긴 _flags;
#endif // 이는
# (CONFIG_OF_PROMTREE) IF 정의
부호 INT UNIQUE_ID;
#endif // 이는
정의 (CONFIG_OF_KOBJ)의 #if
; 구조체 bin_attribute의 ATTR
#endif 다음
}

D device_node 이러한 트리를 구성하고, 루트 노드는 : of_root.

 

제 05 _device_node는 platform_device로 변환

DTS -> DTB -> device_node -> platform_device

두 가지 문제 :
변환 할 수있는 device_node는 platform_device합니다.?
이 포함 된 루트 노드의 자식 노드가 compatile 속성
( "간단한 버스를", " 단순 MFD", "ISA를" 만약이 특정 값을 포함 compatile 노드 속성 "암, AMBA 버스" ) 하나 compatile 필수 속성을 포함 다음 자식 노드 ()가 또한 platform_device로 전환 될 수
등 I2C, SPI 버스 노드에서 하위 노드 버스 드라이버에 대응하여 처리 될 그들은 platform_device로 변환 할 수 없습니다한다

. B? 어떻게 변환
platform_device 자원 배열을 포함가 등록 device_node에서 유래 속성을 방해;
platform_device.dev.of_node 포인트 device_node 다른 속성 그것에 의해 얻을 수있다

이 섹션에서는 요약

. A는 커널 함수 of_platform_default_populate_init, device_node 트리 순회 platform_device의 생성
. B의 device_node 모든이 platform_device로 변환됩니다
만 다음 device_node 변환 :
B.1 노드가 호환 속성이 포함되어야합니다
자식 노드 B.2 루트 (노드가 있어야합니다 호환 속성)
자식 노드 B.3 노드 (자식 노드가 호환 속성을 포함한다) 호환 특별한 속성이 포함되어
이러한 특수 compatilbe 속성 : "간단한 버스", " 단순 MFD", "ISA", "팔을, AMBA 버스 "

B.4 예는 :
같은 노드로,
/ MYTEST가 platform_device로 변환됩니다
은 "단순한 버스"와 호환이기 때문에 자식 노드는 / MYTEST / MYTEST 변환됩니다 @ 0 platform_device하기

/ I2C I2C 나타내어 노드 컨트롤러가, 또, 해당 커널 platform_driver을 platform_device 전환 될 것이다
/ I2C / AT24C02 노드하지이 완전히 상위 노드에 의해 결정된 처리 방법 platform_device로 변환 platform_driver 일반적 그것은 i2c_client로 만들었습니다.

유사은 / 일반적 SPI 컨트롤러를 나타내는 데 사용되는 SPI 노드는, 또, 해당 커널 platform_driver을 platform_device 변환된다 갖는다
/ SPI / @ 플래시없는 처리 방식, 노드 0 platform_device로 변환 platform_driver 완전히 spi_device 일반적으로 생성 된 부모 노드에 의해 결정된다.

/ {
MYTEST {
compatile = "MYTEST", "단순 버스";
MYTEST 0 {@
= "mytest_0"compatile;
};
};

I2C {
compatile = "삼성, I2C";
AT24C02 {
compatile = "AT24C02";
};
};

SPI는 {
compatile = "삼성, SPI";
0 {@ 플래시
호환 = "WINBOND, w25q32dw";
SPI-최대 주파수 = <25,000,000을>;
레지 = <0>;
};
};
};


함수 호출 :
. 호출 절차 (드라이버 / platform.c /의)는 of_platform_default_populate_init :
start_kernel // 초기화 / main.c에
rest_init ();
PID = kernel_thread (kernel_init, NULL, CLONE_FS)
kernel_init
kernel_init_freeable ();
do_basic_setup하기 ();
do_initcalls ()
대 (레벨 = 0 레벨 <ARRAY_SIZE (initcall_levels) - (1)]. 단계 ++)
]. (3) do_initcall_level (레벨) // 같은 do_initcall_level
[. 3. (FN = initcall_levels 용; FN <initcall_levels [3 +1] 상기 FN ++)
do_one_initcall (initcall_from_entry합니다 (FN))에 정의 // 호출 "arch_initcall_sync (FN)"FN 함수

. ㄱ of_platform_default_populate_init (/ /의 드라이버 platform.c) platform_device 생성 과정 :
of_platform_default_populate_init의
of_platform_default_populate (NULL, NULL, NULL);
of_platform_populate (NULL, of_default_bus_match_table, NULL, NULL)
for_each_child_of_node (루트, 어린이) {
RC = of_platform_bus_create (아동, 일치 룩업), 상위 사실 // 콜 절차는 아래 참조
DEV = of_device_alloc (NP, bus_id, 부모) // 자원 세트 노드 platform_device 속성 device_node에 따라
IF (RC) {
(자식) of_node_put;
BREAK;
}
}

호출 프로세스의 C의 of_platform_bus_create (버스, 성냥, ...) (프로세스 버스 노드가 platform_devie를 생성하고 자식 노드를 가지고 여부를 결정).
DEV = of_platform_device_create_pdata (버스, bus_id, platform_data, 부모); // 생성 된 버스 platform_device 노드 구조
경우 (DEV || of_match_node (경기! // 버스)!) compatile 속성은 노드가 테이블에 일치하는 버스와 일치하지 않는 경우에 자식 노드가 처리하지 않는
0을 반환;

for_each_child_of_node (버스, 자녀) {// 각 자식 노드 추출
pr_debug는 ( "자식 만들기 : POF % \ N-", 어린이),
RC = of_platform_bus_create (아동, 성냥, 조회, dev-> dev에, 엄격한); // 과정을 자식 노드 of_platform_bus_create 재귀 호출은
{(RC) IF
; of_node_put (자식)
; BREAK
}
}

D I2C 버스 노드 처리 :.
/ I2C의 I2C 나타내어 노드 컨트롤러가 platform_device 변환한다에서 대응 커널 platform_driver,
프로브 기능 platform_driver의 i2c_add_numbered_adapter를 호출한다 :

i2c_add_numbered_adapter // 드라이버 / I2C / I2C 코어 - base.c
__i2c_add_numbered_adapter
i2c_register_adapter
of_i2c_register_devices (ADAP) // 드라이버 / I2C / I2C 코어 - of.c
for_each_available_child_of_node (버스 노드) {
클라이언트 = of_i2c_register_device (ADAP 노드);
클라이언트 = i2c_new_device (ADAP, 정보는 ) // I2C 디바이스 트리의 자식 노드 i2c_client 변환된다
}

E SPI 버스 프로세싱 노드 :.
/ SPI SPI 나타내어 노드 컨트롤러, 커널 platform_device 변환 될 대응 platform_driver에서,
프로브는 함수의 platform_driver spi_register_master를 호출, 즉 spi_register_controller :

spi_register_controller // 드라이버 / SPI는 / spi.c
of_register_spi_devices // 드라이버 / SPI는 / spi.c의
for_each_available_child_of_node (ctlr-> dev.of_node, NC) {
SPI = of_register_spi_device (CTLR, NC) , SPI 트리에서 // 자식 노드 장치는 spi_device로 변환
SPI = spi_alloc_device (CTLR),
RC = of_spi_parse_dt (CTLR, SPI, NC),
RC = spi_add_device (SPI);
}


platform_driver와 제 06 _platform_device 일치

드라이버 / 기본 / platform.c

. platform_driver의 등록 처리 :
platform_driver_register
__platform_driver_register
Drv-> driver.probe = platform_drv_probe;
driver_register
bus_add_driver
klist_add_tail (priv-> knode_bus, 버스 -> P->를 klist_drivers) //에서 드라이버 목록에 platform_bus_type platform_driver 넣어
driver_attach
bus_for_each_dev ( drv-> 버스, NULL, DRV, __driver_attach); // plarform_bus_type 아래의 각 디바이스에 대한 호출 __driver_attach
__driver_attach
RET = driver_match_device (DRV, DEV) 일치 성공 DRV의 여부를 판정하고 // DEV
복귀 drv-> 버스 - > 경기 drv-> 버스 -> 경기 ( DEV, DRV) :? 1; // 호출 platform_bus_type.match의
driver_probe_device (DRV, DEV)
really_probe
drv-> // platform_drv_probe 프로브
platform_drv_probe
구조체 platform_driver * = to_platform_driver DRV (_dev-> 드라이버);
drv-> 프로브

B. 注册platform_device的过程:
platform_device_register
platform_device_add
device_add
bus_add_device
klist_add_tail (dev-> P-> knode_bus, 버스 -> P-> klist_devices); //把platform_device放入platform_bus_type的장치链表中의
bus_probe_device (DEV);
device_initial_probe
__device_attach
RET = bus_for_each_drv (dev-> 버스, NULL, 데이터 __device_attach_driver); //对于plarform_bus_type下的每一个드라이버调用__device_attach_driver
__device_attach_driver
RET = driver_match_device (DRV, DEV);
drv-> 버스 -> 경기를 반환? drv-> 버스 -> 경기 (DEV, DRV) : 1; //调用platform_bus_type.


매칭 함수 platform_bus_type.match, 즉 platform_match이며,
우선 순위에 따라 다음과 같다 매칭 처리 :
.되는 비교 및 platform_dev.driver_override platform_driver.drv-> 이름
호환 Platform_dev.dev.of_node B의 비교 및 platform_driver.drv-> of_match_table.
C 비교 platform_dev.name platform_driver.id_table 및
D와 비교 platform_dev.name platform_driver.drv-> 이름은
A가 성공적 즉, 정합이 성공한 존재


어제, 참가자 증가, 2 절 다음 자신의 조언을 매우 감사 기록 제안
은 제안이있는 경우,. 알려 주시기 바랍니다
, 녹화 품질이 내 목표 내가 증가 된 작업 부하에 대해 걱정하지 않아요.
"자신을 만들기 위해 기쁘게하기 내 제품에 만족하지 않은 경우 "어떻게 당신이 만족 될 수 있는가?

장치 트리 커널의 기능 조작부 07 _

인클루드 / 리눅스 / 디렉토리의 시작 부분에 헤더 많이 있습니다 :

DTB -> device_node -> platform_device
. 프로세스 DTB
상관 함수 작업 of_fdt.h // DTB 문서, 우리 커널 DTB 파일로보다 일반적 이하 (쉽게 사용할 수) 트리를 device_node로 변환 된

B. 처리 device_node
of.h // 장치 트리 일반적인 처리 기능과 같은 of_property_read_u32 (U32은 속성 값을 읽는) of_get_child_count (a device_node 취득 하위 노드)를 제공
// 주소 관련 기능 of_address.h 이러한 of_get_address (REG 특성 수득 ADDR, 사이즈 값)
of_match_device (배열이 일치로부터 가장 제거 장치의 현재 일치)
of_dma.h // DMA 장치 트리 특성 함수 관계
of_gpio.h // GPIO 관련 기능
관련 드라이브에 사용 // 기능 GPU of_graph.h은, GPU는 장치 트리에서 정보를 얻을
거의 사용되지 // of_iommu.h
of_irq.h // 관련 기능 중단
of_mdio.h // MDIO을 (이더넷 PHY를 ) API
of_net.h // 네트워크 장치에 대한 도우미.
of_pci.h // PCI-상관 함수
of_pdt.h // 거의 사용되지
of_reserved_mem.h // reserved_mem의 상관 함수

C. 폐기 platform_device
of_platform.h // 함수 변환 platform_device의 device_node 때 사용
// 같은 of_device_alloc (할당 platform_device 제공 device_node)
// of_find_device_by_node은 (있어서 device_node를 찾을 platform_device)
// of_platform_bus_probe (device_node 프로세싱 자식 노드)
등 of_match_device 등 // 기능 관련 장비 of_device.h,

 

제 08 _보기 장치 트리의 루트 파일 시스템 (유용한 디버깅을위한)

가. / SYS / 펌웨어 / FDT // 원본 파일 DTB

16 진 덤프 -C / SYS / 펌웨어 / FDT

DTB 파일의 디렉토리 구조 / devicetree // 현재 경로 나. / SYS / 펌웨어, 기본 디렉토리는 루트 노드에 해당하는 각 노드는 파일이 각 속성에 해당 디렉토리에 해당

다. / SYS / 디바이스 / 플랫폼 // 모든 platform_device 시스템이 장치에서 나무가 아니라 등록이 .c 파일을 가지고
장치 트리에서 platform_device를 들어,
당신은 / SYS / 디바이스 / 플랫폼 / <장치 이름을 입력 할 수 있습니다 > / of_node 장치 트리의 속성을 보려면

라. / proc 디렉토리 / devicetree이 링크 파일 포인트 / SYS / 펌웨어 / devicetree / 기본

 

추천

출처www.cnblogs.com/liusiluandzhangkun/p/11784597.html