Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 시스템 소프트웨어 개발을 위한 ARM 아키텍처의 구조와 원리
- arm
- 실무PT후기
- 코멘토실무PT
- 빌드 시스템
- 코멘토
- udemy
- ARM 아키텍처: 메모리모델과 배리어
- BSP
- 인프런
- yocto
- Arm 아키텍처: 메모리 모델과 배리어
- Arm 아키텍처: 캐시
- Kernel
- ARM 아키텍쳐: 메모리 모델과 배리어
Archives
- Today
- Total
반도체 소프트웨어
코멘토 실무PT 후기 챌린지_"반도체 SW 엔지니어를 위한 새로운 SoC 위에 리눅스 디바이스 드라이버 포팅하기" 강의 2주 차 후기 본문
교육/코멘토 직무PT
코멘토 실무PT 후기 챌린지_"반도체 SW 엔지니어를 위한 새로운 SoC 위에 리눅스 디바이스 드라이버 포팅하기" 강의 2주 차 후기
반도체 소프트웨어 엔지니어 2024. 1. 21. 17:18<학습 소감>
mmio라는 것을 단순히 사용만 해봤었지 실제로 하드웨어 레벨에서 구현해보고 소스코드를 고민해본 적은 없었다. 그래서인지 요번 수업을 들으면서 기존에 지녔던 하드웨어, 디바이스 드라이버, 응용 프로그램에 대한 개념이 흔들리면서 강의 내용을 이해하기가 어려웠었다. 그러나 꾸준히 복습하고, 과제를 진행하고, 리드멘토님께 많은 질문을 하여 더 깊은 이해를 얻을 수 있었다. 실무적인 내용을 배울 수 있는 실무PT에 정말 많은 도움을 받고 있다.
<실습 중>
<이번 주 수업 내용 리뷰>
[2024/01/17(수) 20:00]
- 작주 복습
- MM은 메모리 맵을 의미하고 MMIO는 MM기반 페리페럴을 의미
- RISC-V 오픈소스로 IP제공
- 디바이스트리를 통해서 리눅스 커널 빌드와 독립적으로 하드웨어, 페리페럴들을 다룰수있게 편리하게 다룰수있게되었음
- SMP: CPU코어가 메모리 공유
- UART는 CLOCK이 있어야 통신 가능
- MENUCONFIG랑 DEFCONFIG 없어지지않도록 하는 사항 추가하는거 교재에있음
- 각 UART마다 독립적인 시작주소와 인터럽트 번호를 사용해야함
- serial_hd()는 번호 지정해주는 것
- 어떤 디바이스올라왔는지도 cat /proc/iomem 으로 확인 가능
- ttyAMA0은 맨처음에 콘솔로 지정해서 이미 쓰고있는거고 ttyAMA1은 아무데도 연결되지 않은 상태
- MMIO
- AMBA
- ARM은 AMBA를 시스템버스로 사용함
- SOC 내에서 사용하기 위해 개발한 버스(주소, 제어, 데이터 라인 사용)
- 버스는 확장하기 좋은 병렬적인 구조이지만 순서대로 통신이 되므로 이를 중재하기 위한 프로토콜이필요함
- 시스템버스가 결국 uart 핀과 gic 핀을 연결해주는것 (RTL로 AMBA위에서 동작하는 회로를 짠다고함) (qemu에서는 sysbus가 곧 AMBA이며 시스템 버스라고 가정됨)
- 소스코드
- SYS_BUS_DEVICE는 devicestatus에서 형변환, 캐스팅한다고보면됨
- 개념
- 메모리맵과 디바이스의 메모리를 연결시키면, 메모리에 데이터쓰면 하드웨어 메모리(레지스터)에 데이터가 쓰인다
- AMBA는 SOC내에서 사용하는 시스템 버스
- I2C, SPI는 SOC외부 디바이스와 연결하기 위한 시스템 버스, 즉 이것도 버스의 일종임
- 메모리맵연결 / 인터럽트 연결 이라는 두가지를 진행해야함
- MMIO(memory mapped I/O)
- 디바이스의 입출력 레지스터가 메모리 주소를 점유하는 형태를 사용
- 점유하고 있는 주소를 사용하면 디바이스의 입출력 레지스터에 값 R/W 가능
- MMIO에서는 물리주소에 메모리가 매핑되기도 하고 디바이스가 매핑되기도하고 등등
- MMIO 과정: 주소, 제어, 데이터 시스템 버스 라인에다가 CPU 명령에 관련된 내용을 담아서 뿌리는데 디바이스는 이걸 읽어서 자신에게 해당되는 내용이면 해석해서 처리함
- MMIO가 아닌 다른 방식
- PMIO(port)
- 메모리주소가 아닌 I/O포트라는 별개의 주소를 사용하는 방식
- i/o포트를 위한 별개의 라인이 요구됨
- x86에서만 사용, x86에서 MMIO는 PCI버스를 위해 사용됨 (cat /proc/ioports)
- PMIO(port)
- 명령어 설계 방식
- RISC, CISC: CPU 명령어를 설계하는 방식
- CISC
- 하위호환성을 위해서 자꾸 명령어를 추가하다보니 복잡하고 많은 개수의 명령어를 사용하게되었음
- SIMD 명령어를 지원하기에 명령어 한개로 큰 용량의 데이터를 다룰수있는 강점은 있음
- RISC
- 간단하고 적은 명령어를 사용하는 특징
- 이제는 RISC가 훨씬빠름
- 파이프라이닝에 강점이 있음
- AMBA
[2024/01/17(수) 21:00]
- MMIO 레지스터를 어떻게 사용할지는 장치 설계자가 마음대로 할 수 있음
- 그러나 일반적으로 사용하는 예시를 보여드림
- Control, data, flag는 기본적으로 사용하는 레지스터임
- 인터럽트가발생한것뿐만아니라 활성화되어있어야 cpu가 처리하는것임 (인터럽트 발생 흐름 도표보면 더 자세히 이해 가능)
- 일반적인 MMIO 레지스터 종류
- Control Register: 각 비트를 통해 해당하는 기능을 활성화/비활성화
- Data Register: 데이터를 수신하거나 송신할 때 사용
- Flag Register: 각 비트를 통해 해당하는 상태를 나타냄
- Raw Interrupt Status Register: 각 비트를 통해 해당하는 인터럽트 발생 상태를 나타냄
- Interrupt Clear Register: 각 비트를 통해 해당하는 인터럽트 발생을 끔
- Interrupt Mask Set/Clear Register: 각 비트를 통해 해당하는 인터럽트 활성화/비활성화
- Masked Interrupt Status Register: 활성화된 인터럽트의 발생 상태를 나타냄
- 인터럽트란
- 인터럽트의 반대가 폴링
- 보통 드라이버는 디바이스의 상태 변화를 기다리는게 일반적임
- 이걸 반복문으로 폴링돌면 cpu가 아무 작업도 처리를 못함
- 결론적으로 하드웨어가 cpu를 호출하는 것이 인터럽트
- 상태 변화를 알려줄 때 등 사용
- 인터럽트가발생하면 cpu는 인터럽트 핸들러를 실행하도록 아키텍처적으로 설계되어있음
- 인터럽트 발생 흐름
- 인터럽트 발생 감지(raw interrupt)
- 처리하도록 인터럽트 마스킹(mask register)
- 인터럽트 처리한 이후에 clear register로 인터럽트를 꺼야 인터럽트가 발생하지 않음
- 인터럽트 주의 사항
- 인터럽트 핸들러가 실행되는 동안은 다른 인터럽트가 발생하지 않음(타이머 조차 멈춤)
- 뮤텍스나 스핀락 사용은 최대한 지양해야함
- 불필요한 인터럽트 발생하지않도록 마스킹 필요
- 인터럽트는 빠르게 처리되고 해제되어야함
- TOP/BOTTOM Half (효율적인 인터럽트 개발 방법론)
- 위 방식으로 인터럽트를 구현함. 즉 인터럽트핸들러에서 모든 인터럽트 처리를 하지 않음
- TOP Half
- 인터럽트 핸들러의 구현
- 인터럽트 핀의 신호를 빨리 끄는 것이 목적
- BOTTOM Half
- 하드웨어의 구체적인 처리 구현
- 커널 스레드로 실행이됨
- 현업에서는 AMBA ID구성하기를 피피티와는 다르게 사용할 가능성이 많음
- 거의 현업하고 비슷한 mmio.c 코드임
- MMIO랑 DMA는 코드를 분석하는게 도움이됨
[2024/01/17(수) 22:00]
- 링버퍼는 dd구현시에도 많이 사용함. 디바이스내에 데이터 임시보관하는 용도
- 하드웨어 내에서 링버퍼 해놓고 여기에 값을 쓰고 읽고하는 거네
- QMP: 동작중인 QEMU 속성 보는 프로토콜
- UEVENT사용하면 MKNOD안하고 자동으로 디바이스 노드 자동으로 생성해줌
- devm접두어: 디바이스 등 메모리 사라지면 알아서 메모리 없애줌
- ioremap: 물리주소와 가상주소를 매핑해주는것
- 단순히 메모리맵에 할당하는것뿐만아니라 ioremap 사용해서 가상주소로까지 매핑해줘야함
- 폴링방식으로 돌리면 볼리니깐 대기큐, 워크큐 사용해서 스케줄링으로 후처리돌림
- 대기큐: 원하는 조건이 아니면(필드값이 아직 설정안되었으면) 큐에 현재 프로세스를 넣고 sleep 상태가 됨 -> 대기큐랑 워크큐는 다름. 폴링안하려고 사용(wakeup_event_interriuptible())
- 데이터가 버퍼에 꽉찼기에 인터럽트 발생
- 예를들면 1M바이트 데이터를 버퍼에서 뺴려면 오래걸리는데 이걸 인터럽트핸들러에서 하면 안됨. 그래서 바텀하프를 쉽게구현할수있는 방식중하나가 워크큐임(스레드풀 개념)
- 확실히 워크큐나 하드웨어를 기반으로 디바이스드라이버를 개발하면서 배우니깐 확실히 어떻게 적용되는지 알겠네