이전 게시글에서는 라즈베리 파이 피코 2에 SparkFun의 9DoF IMU ICM-20948 평가 기판을 연결하고 Zephyr OS 셸에서 I2C 슬레이브 주소를 스캔하는 방법을 설명하였다면, 이번 글에서는 피코 2에서 Zephyr OS 기반 애플리케이션을 빌드하는 과정과 이를 위해 필요한 필수 파일 및 디렉터리 구조에 대해 설명하겠습니다. 먼저, 피코 2의 출력을 확인하는 데 사용할 minicom 터미널을 실행합니다. Zephyr OS 애플리케이션은 피코 2에서 실행됩니다.
$ minicom -D /dev/ttyACM0
Welcome to minicom 2.8
OPTIONS: I18n
Port /dev/ttyACM0, 12:41:43
Press CTRL-A Z for help on special keys
Zephyr 디렉터리 내에 myproject라는 폴더를 생성한 다음, 해당 폴더 안에 다음 파일들을 생성합니다.
CMake 파일 (파일명 CMakeLists.txt)
cmake_minimum_required(VERSION 3.25.1)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(i2c_scanner)
target_sources(app PRIVATE src/main.c)
Zephyr OS 설정 파일 (파일명 prj.conf)
CONFIG_I2C=y
Zephyr OS 오버레이 파일 (파일명 RP2350.overlay, I2C 포트 정의 - 본 예제에서는 피코 2의 I2C0)
/ {
aliases {
scan-i2c = &i2c0;
};
};
main.c 프로그램 (새로운 하위 폴더 src 내에 위치)
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/printk.h>
#define CONFIG_I2C_SCAN_ADDR_START 0x00
#define CONFIG_I2C_SCAN_ADDR_STOP 0x99
static const struct device *scan_dev = DEVICE_DT_GET(DT_ALIAS(scan_i2c));
int main(void)
{
k_sleep(K_SECONDS(5));
if (!scan_dev) {
printk("I2C: Device driver not found.\n");
return -1;
}
printk("*** Digikey I2C scanner started ***\n");
printk("Board: %s\n", CONFIG_BOARD);
printk("I2C device: %s\n", scan_dev->name);
/* Print pin information if available in devicetree */
if (!device_is_ready(scan_dev)) {
printk("I2C device not ready\n");
return -1;
}
printk("Digikey Scanning on I2C bus...\n\n");
printk(" | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f |\n");
printk("****|*********************************************************************************");
uint8_t error = 0u;
uint8_t dst;
uint8_t i2c_dev_cnt = 0;
struct i2c_msg msgs[1];
msgs[0].buf = &dst;
msgs[0].len = 1U;
msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
uint16_t slave_addr = 0;
/* Use the full range of I2C address for display purpose */
for (uint16_t x = 0; x <= 0x7f; x++) {
/* New line every 0x10 address */
if (x % 0x10 == 0) {
printk("|\n0x%02x| ",x);
}
/* Range the test with the start and stop value configured in the kconfig */
if (x >= CONFIG_I2C_SCAN_ADDR_START && x <= CONFIG_I2C_SCAN_ADDR_STOP) {
/* Send the address to read from */
error = i2c_transfer(scan_dev, &msgs[0], 1, x);
/* I2C device found on current address */
if (error == 0) {
printk("0x%02x ",x);
slave_addr = x;
++i2c_dev_cnt;
}
else {
printk("#### ");
}
} else {
/* Scan value out of range, not scanned */
printk(" ");
}
k_sleep(K_MSEC(15));
}
printk("|\n");
printk("\nI2C device(s) found on the bus by Digikey: %d\nScanning complete!\n\n", i2c_dev_cnt);
}
myproject 폴더의 전체 구조는 다음과 같습니다.
|-- CMakeLists.txt
|-- prj.conf
|-- RP2350.overlay
`-- src
`-- main.c
이제 RP2350.overlay 파일을 사용하여 피코 2용 Zephyr OS 애플리케이션을 다음과 같이 빌드합니다.
(venv) $ west build -p always -b rpi_pico2/rp2350a/m33 -S cdc-acm-console -- -DCONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y -DEXTRA_DTC_OVERLAY_FILE=RP2350.overlay
다음은 디지키에서 구매 가능한 평가용 브레드보드에 또 다른 게시글에서 소개한 SparkFun 8채널 USB 로직 분석기와 함께 실제 구성한 사진입니다.
아래 사진과 같이, 피코 2의 I2C 버스인 PIN6 (I2C0 SDA), PIN7 (I2C0 SCL), 그리고 PIN38 (GND)을 모니터링하기 위해 Qwiic 케이블을 사용하였습니다.
로직 분석기를 I2C 버스 신호인 SCL, SDA와 GND에 연결하였지만, 긴 케이블로 인해 1차 등가 RC 시정수가 증가하고, I2C 버스에 왜곡이 발생할 수 있어서 최적의 연결 방법은 아닙니다. 이제 Zephyr OS 애플리케이션을 빌드하고 피코 2에 플래시 합니다.
(venv) $ west flash --runner uf2
minicom 터미널에서는 피코 2의 출력이 아래와 같이 표시될 것입니다.
*** Booting Zephyr OS build v4.2.0-5176-ge5838ffc2176 ***
*** Digikey I2C scanner started ***
Board: rpi_pico2
I2C device: i2c@40090000
Digikey Scanning on I2C bus...
| 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f |
****|*********************************************************************************|
0x00| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x10| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x20| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x30| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x40| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x50| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
0x60| #### #### #### #### #### #### #### #### #### 0x69 #### #### #### #### #### #### |
0x70| #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### #### |
I2C device(s) found on the bus by Digikey: 1
Scanning complete!
피코 2에서 실행중인 Zephyr OS 애플리케이션이 I2C 슬레이브 주소를 0x69로 정상적으로 인식하였으며, 이전 글에서 사용된 I2C 장치 i2c@40090000와도 일치합니다. 이를 검증하기 위해 SparkFun 8채널 USB 로직 분석기를 2채널만 표시하도록 구성하고, 샘플링 속도는 4 MHz, 샘플 수는 1억으로 설정하였으며, 그리고 I2C 프로토콜 디코더를 사용하도록 구성하였습니다. 다음 I2C 버스 스냅샷은 Zephyr OS 프로그램을 리셋하는 동안 로직 분석기로 캡처한 것입니다. 첫 번째 캡처는 앞서 설명한 Zephyr OS main.c 프로그램이 수행한 I2C 주소 스캔 전체 시퀀스를 보여줍니다.
피코 2가 전송한 I2C 메시지를 확대해 보면, 0xB0 I2C 슬레이브 주소를 스캔한 경우 I2C 슬레이브 장치로부터 응답이 없음을 나타내는 NACK (아래 그림에서 빨간색)를 확인할 수 있습니다.
마지막으로 주소가 0x69인 I2C 슬레이브 장치가 감지된 경우를 확인해 보면, Zephyr OS가 실행중인 피코 2에 ACK (아래 그림에서 보라색)가 반환된 것을 확인할 수 있습니다.
이로써 라즈베리 파이 피코 2를 기반으로 Zephyr OS I2C 인터페이스를 구성하고 SparkFun의 9DoF IMU Qwiic 플랫폼 평가 보드와 연동하는 과정이 모두 완료되었습니다.
좋은 하루 보내세요!
영문 원본: Zephyr OS on Raspberry Pico 2 I2C interface to SPARKFUN 9DOF IMU (Linux) Part 3




