728x90
반응형
Embedded Linux에서 SPI Driver 작성하기 (Rockchip RK3399 기준)
SPI Driver란?
SPI(Serial Peripheral Interface)는 임베디드 시스템에서 주변 장치와 통신하기 위해 널리 사용되는 동기식 직렬 통신 프로토콜입니다. 이번 포스팅에서는 Rockchip RK3399를 기준으로 SPI Flash를 읽고 쓰는 방법을 포함하여 Linux Kernel에서 SPI 인터페이스를 사용하는 방법을 단계별로 설명합니다.
1. SPI 인터페이스 개요
SPI는 Master-Slave 구조를 기반으로 동작합니다. 주요 신호선은 아래와 같습니다:
- MOSI (Master Out Slave In): Master에서 Slave로 데이터 전송.
- MISO (Master In Slave Out): Slave에서 Master로 데이터 전송.
- SCLK (Serial Clock): Master가 생성하는 클록 신호.
- CS (Chip Select): Slave 선택 신호.
Linux Kernel에서는 SPI 장치를 "spidev"로 추상화하여 사용자 공간에서도 접근할 수 있습니다.
2. Linux Kernel에서 SPI Driver 개발 준비
2.1. Kernel Configuration
RK3399 보드에서 SPI 인터페이스를 활성화하려면 다음 Kernel 설정을 확인하거나 변경해야 합니다:
make menuconfig
Device Drivers
→SPI support
활성화.User mode SPI device driver support
활성화.- RK3399에 맞는 SPI 컨트롤러 드라이버 활성화.
3. SPI Flash 읽기/쓰기 드라이버 작성
3.1. SPI Driver 기본 구조
다음은 SPI Driver를 작성하기 위한 기본 구조입니다:
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/delay.h>
#define SPI_FLASH_READ 0x03
#define SPI_FLASH_WRITE 0x02
#define SPI_FLASH_SECTOR_SIZE 4096
struct spi_flash_dev {
struct spi_device *spi;
};
static int spi_flash_probe(struct spi_device *spi)
{
pr_info("SPI Flash driver probed\n");
return 0;
}
static int spi_flash_remove(struct spi_device *spi)
{
pr_info("SPI Flash driver removed\n");
return 0;
}
static const struct of_device_id spi_flash_of_match[] = {
{ .compatible = "spi-flash,example" },
{}
};
MODULE_DEVICE_TABLE(of, spi_flash_of_match);
static struct spi_driver spi_flash_driver = {
.driver = {
.name = "spi_flash",
.of_match_table = spi_flash_of_match,
},
.probe = spi_flash_probe,
.remove = spi_flash_remove,
};
module_spi_driver(spi_flash_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("소프트웨어 공장");
MODULE_DESCRIPTION("SPI Flash Driver Example");
3.2. SPI Flash Read/Write 구현
아래는 SPI Flash에서 데이터를 읽고 쓰는 함수 예제입니다:
static int spi_flash_read(struct spi_device *spi, u32 addr, u8 *buf, size_t len)
{
u8 tx_buf[4];
struct spi_transfer xfers[2];
struct spi_message msg;
tx_buf[0] = SPI_FLASH_READ;
tx_buf[1] = (addr >> 16) & 0xFF;
tx_buf[2] = (addr >> 8) & 0xFF;
tx_buf[3] = addr & 0xFF;
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
xfers[0].tx_buf = tx_buf;
xfers[0].len = 4;
spi_message_add_tail(&xfers[0], &msg);
xfers[1].rx_buf = buf;
xfers[1].len = len;
spi_message_add_tail(&xfers[1], &msg);
return spi_sync(spi, &msg);
}
static int spi_flash_write(struct spi_device *spi, u32 addr, const u8 *buf, size_t len)
{
u8 tx_buf[4];
struct spi_transfer xfers[2];
struct spi_message msg;
tx_buf[0] = SPI_FLASH_WRITE;
tx_buf[1] = (addr >> 16) & 0xFF;
tx_buf[2] = (addr >> 8) & 0xFF;
tx_buf[3] = addr & 0xFF;
spi_message_init(&msg);
memset(xfers, 0, sizeof(xfers));
xfers[0].tx_buf = tx_buf;
xfers[0].len = 4;
spi_message_add_tail(&xfers[0], &msg);
xfers[1].tx_buf = buf;
xfers[1].len = len;
spi_message_add_tail(&xfers[1], &msg);
return spi_sync(spi, &msg);
}
4. Device Tree 설정
SPI 장치를 활성화하려면 Device Tree를 수정해야 합니다. RK3399의 SPI Flash 노드 예시는 다음과 같습니다:
&spi0 {
status = "okay";
flash@0 {
compatible = "spi-flash,example";
reg = <0>;
spi-max-frequency = <50000000>;
};
};
5. 빌드 및 로드
5.1. Driver 빌드
Makefile을 작성하여 드라이버를 빌드합니다:
obj-m += spi_flash.o
빌드 명령어:
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
5.2. Driver 로드
sudo insmod spi_flash.ko
로그 확인:
dmesg | grep SPI
결론
이번 포스팅에서는 Rockchip RK3399을 기준으로 SPI Flash 드라이버를 작성하고 사용하는 방법을 설명했습니다. SPI는 임베디드 시스템에서 중요한 통신 프로토콜로, Linux Kernel에서 이를 활용하는 방법을 이해하면 다양한 하드웨어 장치를 제어할 수 있습니다.
반응형
'Linux > Kernel Driver' 카테고리의 다른 글
USB Device Driver 작성 및 Linux Kernel에서 USB 인터페이스 사용 방법 (0) | 2025.03.23 |
---|---|
USART Driver 작성 및 Linux Kernel에서의 USART 인터페이스 사용 방법 (0) | 2025.03.22 |
Embedded Linux Kernel: I2C 드라이버 작성 및 사용법 (0) | 2025.03.20 |
Embedded Linux Kernel: Platform Driver 작성하기 (0) | 2025.03.19 |
Device Driver에서 Sysfs 등록 (0) | 2025.03.18 |