[※] 이번 chapter에서는 지금까지 여러 차례 언급했던 각 device 및 HW를 어떻게 제어할 수 있는지에 대해 배워봅시다.
1. Device control
[※] 작은 것부터 큰 것까지 순서대로 register → memory → memory controller —> LCD(peripheral device)를 제어하는 방법에 대해 알아봅시다.
Device는 MCU 외부에 달려있는 IP를 의미하며, 대략 아래와 같은 구성과 흐름으로 이뤄진다.
- CS핀 (Chip select) : 이 device를 사용하겠다고 활성화시키는 역할을 하는 핀으로 CE(Chip Enable)핀이라고 표기되기도 한다. CS/로 표기되는데, 슬래시는 ‘low active’라는 뜻이다. 따라서 이 device를 사용할 때는 0을 입력해야 한다.
- Data핀 : 양방향 핀으로 명령어 또는 데이터를 주고받는 용도로 사용하는 핀이다. 여러 개의 핀으로 구성될수도 있고, I2C/ SPI 등으로 한두가닥의 bus로 구현될 수도 있다.
- CS를 low로 만들어서 ‘널 쓸거야’ 라고 알려준다.
- Data핀으로 slave에게 command sequence를 보내서 명령한다.
- Data핀으로 device는 제대로 수신했고 ready 상태임을 master에게 알려준다.
- Data핀으로 데이터를 쓰거나 읽는다.
- CE를 high로 만들어서 사용을 종료한다.
1.1. Register
레지스터 설정은 1) 레지스터의 주소에 접근, 2) 값을 쓰거나 읽음 2가지로 구성돼있다.
- SW적으로는 굉장히 간단하지만, 내부 과정에는 복잡한 HW 과정이 포함돼있다.
- SW 개발자 입장에서는 내부 latch 제어 과정까지는 자세히 알지 못해도 괜찮다.
- 하지만, 주의할 점은 레지스터는 부분 접근이 불가하다는 점이다.
- 예를 들어, 0x12345678에 있는 32-bit 레지스터 A가 있다고 가정하자.
- A의 12번째 bit인 A[11]에 접근하기 위해 1-byte 뒤인 0x12345678 + 0x1에 접근해서는 안 된다.
- 왜냐하면, ‘memory mapped I/O’라는 개념에 의해 레지스터든, 메모리든, 외부 peripheral이든 모두 메모리에 접근하듯 align된 주소를 통해 접근 및 제어가 가능하기 때문이다. Memory mapped I/O란, 레지스터와 외부 I/O controller 등을 특정하는 주소를 메모리의 일부 영역에 할당해서 별다른 조치를 취하지 않고도 메모리를 제어하듯 레지스터와 외부 장치를 제어하는 기능을 말한다. 따라서 레지스터, 메모리, I/O peripheral 모두 특정 address에 접근하는 것으로 제어할 수 있다.
1.2. Memory & Memory controller
- ARM core와 memory 사이에는 양방향 데이터 흐름을 제어하는 controller가 있다.
- 메모리도 위에서 배운 device 동작과정과 거의 동일한 과정을 거쳐서 제어할 수 있다.
- CS를 low로 만들어 enable 한다.
- OE(Output Enable)을 low(read) 또는 high(write)로 만든다.
- Address line에 읽거나 쓰기를 원하는 주소를 지정한다.
- ([※] 보통 여기에 ALE (Address Latch Enable) 이라는 핀이 있어서, OE와 address가 준비되면 권총 트리거를 당겨서 쏘듯 slave에게 정보를 보내는 역할을 하는 핀이 추가로 있습니다.)
- Data line에 read할 데이터가 뜨거나, write할 데이터를 보낸다.
- CS를 high로 만들어 종료한다.
- 위 그림의 메모리는 address line이 26개이므로 2^24 == 64MB이고 data line은 8개이므로 주소당 1-byte를 저장할 수 있는 메모리다.
- 하지만, ARM core는 address line은 32개, data line도 32개를 가지고 있기 때문에 이런 메모리를 사용하기 위해서는 address line을 24개로, data line은 8개로 바꿔주는 회로가 필요하다.
- 바로 이 역할을 memory controller가 해준다.
- Memory controller는 ARM core의 address line의 LSB 24-bit만 사용하고, data line의 LSB 8-bit만 사용해서 메모리에 접근할 수 있도록 도와준다.
- 만일 메모리를 하나 더 추가하거나 기존 메모리를 변경해서 128MB 구성이 된다면, controller 속의 bus sizer 레지스터를 제어해서 address line의 bit를 1개만 더 사용하도록 만들면 된다.
1.3. LCD
- 지금까지 배운 내용을 토대로 LCD 인터페이스를 제어하는 방법에 응용해보자.
- 어떤 MCP의 datasheet 속 memory map을 확인해보니 address 0x2000_0000부터 3MB 크기가 LCD_CS_N이라는 이름으로 선언돼있었다.
- _N이라는 접미사가 붙은 것으로 보아 이 device의 CS핀은 low active임을 예측할 수 있다.
- 3MB이므로 0x2000_0000 ~ 0x202F_FFFF영역이 LCD를 위한 영역임을 알 수 있다.
- 이제 datasheet를 넘겨서 LCD controller에 대한 회로를 설명하는 부분으로 넘어가보자.
- 이 controller는 특이하게도 address line의 7번 bit를 통해 command/ data 여부를 결정한다.
- CS와 WD 그리고 RD는 모두 low active이고, 16개의 data line을 주고받는다.
- 위 정보들을 습득했으면 이제 SW개발자는 LCD를 제어할 수 있는 최소한의 정보를 얻은 것이다.
; Command Issue
LDR R0, #0x20000080 ; A[7] = HIGH
LDR R1, #0xABCD ; 명령을 보냄
STR R1, [R0]
; Data Issue
; Command Issue
LDR R0, #0x20000000 ; A[7] = LOW
LDR R1, #0x1234 ; 데이터를 보냄
STR R1, [R0]
- 어셈블리로 작성하면 위와 같다.
- Address line의 7번 bit를 통해 command를 보낼지, data를 보낼지 결정한다.
- 위 어셈블리를 C언어로 작성하면 아래와 같다. ([※] #define 문 MACRO 테크닉은 3.2절에서 다룹니다.)
#define Main_LCD_Write_cmd (cmd) (*(volatile word *)(0x200000080) = cmd
#define Main_LCD_Write_data (data) (*(volatile word *)(0x200000000) = data
Main_LCD_Write_cmd (0xABCD);
Main_LCD_Write_data (0x1234);
'하드웨어 해킹 및 임베디드' 카테고리의 다른 글
Bluetooth 공격 기법 (0) | 2023.06.30 |
---|---|
ISO 21434 CAL Level (0) | 2023.06.29 |
Car Hacking Training (0) | 2023.05.18 |
SecOC(Secure On-board. Communication) (1) | 2023.05.16 |
Embedded Recipes (0) | 2023.04.11 |