13 분 소요

어제(11/02)는 GPIO, 이더넷, UART, 보안칩, 릴레이, CP를 시험했다. 오늘은 나머지 주변장치를 같은 방식으로 켰다. MYiR DTS에서 설정을 찾고, 넷리스트로 확인하고, 6.6 DTS에 옮긴 뒤 커널과 DTB만 바꿔 시험하는 순서다.

항목 결과 DTS 변경
EM_INT (전력량계 인터럽트, PH14) ✅ 11/02 시험 없음 (GPIO 그대로)
QCA7005 PLC 모뎀 ✅ 펌웨어 적재, 부팅 때 자동 SPI1, Q_RST 줄 이름
USB OTG (J5, STUSB1600) ✅ 디바이스·호스트 모드 I2C4, USB OTG, Type-C 커넥터
WiFi (AP6212) ✅ AP 접속, DHCP, 인터넷, WiFi로 파일 전송 SDMMC3, 전원 시퀀스, 국가 코드 매핑
블루투스 (AP6212) ✅ 휴대폰 페어링, SPP 양방향 통신 (가끔 첫 명령 실패) UART7 아래 BT 노드, RFCOMM 커널 설정
외부 워치독 (TIM8) ✅ 킥 유지, 정지 시 리셋 TIM8 PWM

0. EM_INT — 어제 하고도 빠뜨린 것

어제 글에 쓰지 못한 항목이 하나 있다. 전력량계 인터럽트 EM_INT(PH14) 도 어제 시험해서 통과했다. GPIO 그대로 쓰는 신호라 DTS 변경은 없다.

PM_INT(PH12)와 RCD_INT(PH15)는 아직이다. PM_INT는 AC 부하가 있어야 하고, RCD_INT는 누전을 어떻게 흉내 낼지 회로 설계자와 먼저 정해야 한다.


1. QCA7005 PLC 모뎀 — 부팅할 때마다 펌웨어를 올려야 한다

1-1. 무엇을 하는 칩인가

QCA7005는 CP 선 위로 고주파 신호를 실어 차량과 데이터를 주고받는 HomePlug Green PHY 모뎀이다. ISO 15118(Plug & Charge, 고급 충전 제어)에 쓰인다. CPU와는 SPI로 연결되지만 리눅스에서는 이더넷 장치로 보인다.

&spi1 {
	pinctrl-0 = <&spi1_pins_a>;
	cs-gpios = <&gpioz 3 GPIO_ACTIVE_LOW>;	/* PZ3 */
	status = "okay";

	qca7000: ethernet@0 {
		compatible = "qca,qca7000";
		reg = <0>;
		interrupt-parent = <&gpiog>;
		interrupts = <7 IRQ_TYPE_EDGE_RISING>;	/* PG7 Q_INT */
		spi-cpha;
		spi-cpol;
		spi-max-frequency = <8000000>;
	};
};

ST 기본 설정에는 드라이버가 꺼져 있어서 설정 조각에 CONFIG_QCA7000_SPI=y를 추가했다. 모듈이 아니라 커널에 내장하면 SD 카드의 uImage만 바꾸면 된다.

qcaspi spi0.0: ver=0.2.7-i, clkspeed=8000000, burst_len=5000, pluggable=1
qcaspi spi0.0 eth0: SPI thread created

여기서 이름이 헷갈린다. end0가 보드의 유선 이더넷이고, eth0가 PLC 모뎀이다. 6.6 커널은 SoC 내장 이더넷에 end0라는 새 이름을 붙인다.

1-2. 칩에 플래시가 없다

eth0가 올라와도 모뎀은 아직 동작하지 않는다. 우리 보드의 QCA7005에는 펌웨어를 담을 플래시가 없다. 전원을 켤 때마다 호스트(CPU)가 펌웨어를 SPI로 내려 줘야 한다.

open-plc-utils의 plctool로 상태를 보면 부트로더만 떠 있다.

eth0 00:B0:52:00:00:01 QCA7005 BootLoader

1차 작업(MYiR 5.4) 때 만든 적재 스크립트를 그대로 가져왔다. 칩을 리셋한 뒤 plcboot로 펌웨어(.nvm)와 설정(.pib)을 내려 준다.

eth0 00:B0:52:00:00:01 Write .../MAC-QCA7000-QCA7005-GP-v3.3.0.0031-00-X-CS.nvm (1) (00000040:7104)
eth0 00:B0:52:00:00:01 Write .../QCA7005-EVSE-SpiSlave-Automotive.pib (1) (00200000:9796)
eth0 00:B0:52:00:00:01 Write .../MAC-QCA7000-QCA7005-GP-v3.3.0.0031-00-X-CS.nvm (5) (002CDD30:367784)
eth0 00:B0:52:00:00:01 MAC-QCA7005-3.3.0.31-00-20231004-CS is running

open-plc-utils 바이너리도 1차 때 MYiR SDK로 빌드한 것을 그대로 썼다. 요구하는 glibc 버전이 낮아서(GLIBC_2.4) 새 OS에서도 돌아간다.

1-3. libgpiod v2 때문에 리셋 부분만 고쳤다

스크립트에서 바꿔야 할 곳은 칩 리셋(Q_RST, PC3) 부분 하나였다. 1차 스크립트는 libgpiod v1 문법을 썼는데, 새 이미지는 v2라서 그대로는 동작하지 않는다.

칩 번호와 줄 번호를 스크립트에 박아 두는 대신, DTS에서 이 줄에 이름을 붙였다.

&gpioc {
	gpio-line-names = "", "", "", "Q_RST";
};

v2에서는 이름으로 바로 줄을 찾을 수 있다.

hw_reset() {
	gpioinfo Q_RST >/dev/null 2>&1 || { log "Q_RST 라인 없음 - DTB 확인"; return 1; }
	gpioset -t0 Q_RST=0 || return 1
	sleep 0.1
	gpioset -t0 Q_RST=1
}

systemd 서비스(oneshot)로 등록했다. 재부팅한 뒤에도 펌웨어가 자동으로 올라오는 것을 확인했다.

Active: active (exited) ... 20s ago
eth0 00:B0:52:00:00:01 QCA7005 MAC-QCA7005-3.3.0.31-00-20231004-CS

남은 일이 두 가지 있다.

  • 모뎀 MAC이 PIB 기본값 00:B0:52:00:00:01이다. 충전기마다 다른 값을 넣어야 한다.
  • 스크립트, 서비스, 펌웨어 파일은 보드에 손으로 설치한 상태다. 이미지에 넣는 작업은 M6에서 한다.

2. USB OTG — Type-C 컨트롤러가 역할을 정한다

2-1. 구성

J5는 USB Type-C 커넥터다. 보드에 연결된 것이 PC인지 USB 메모리인지는 STUSB1600(I2C4, 주소 0x28)이 CC 핀으로 판단한다. 판단 결과는 USB 컨트롤러(dwc2)에 전달되고, 컨트롤러가 디바이스나 호스트 역할로 바뀐다.

&i2c4 {
	stusb1600@28 {
		compatible = "st,stusb1600";
		reg = <0x28>;
		interrupt-parent = <&gpiog>;
		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;	/* PG3 ALERT# */
		vdd-supply = <&vin>;

		connector {
			compatible = "usb-c-connector";
			power-role = "dual";
			port {
				con_usbotg_hs_ep: endpoint {
					remote-endpoint = <&usbotg_hs_ep>;
				};
			};
		};
	};
};

&usbotg_hs {
	usb-role-switch;
	port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;
		};
	};
};

커넥터 노드와 USB 컨트롤러가 endpoint로 서로를 가리킨다. 부팅 로그의 Fixed dependency cycle(s) 메시지는 이렇게 서로 참조할 때 커널이 순서를 정리했다는 알림이다. 오류가 아니다.

2-2. 디바이스 모드 — PC에 연결

PC와 연결하자 역할이 device로 바뀌었다. ST 이미지에는 USB 네트워크(NCM) 가젯이 기본으로 들어 있다. 그래서 PC 쪽에 네트워크 장치가 생기고, 보드는 usb0 192.168.7.1을 갖는다.

host [device]          ← typec data_role
configured             ← udc state
inet 192.168.7.1/24 ... usb0

2-3. 호스트 모드 — 실수 한 번

호스트 모드를 시험하다가 결과가 계속 “디바이스”로 나왔다. 확인해 보니 PC 케이블을 빼지 않은 상태였다. dmesg에 PC가 다시 붙을 때마다 생기는 new address 11 같은 줄이 남아 있어서 알 수 있었다. 레지스터와 역할 값이 그대로였던 것도 같은 이유였다.

케이블을 빼고, OTG 젠더에 USB 카드리더를 꽂아 다시 시험했다. 카드리더에는 마침 남는 SD 카드가 없어서 기존 MYiR OS 카드를 넣었다.

[host] device
[source] sink
sd 0:0:0:1: [sdb] 31116288 512-byte logical blocks: (15.9 GB/14.8 GiB)
 sdb: sdb1 sdb2 sdb3 sdb4 sdb5 sdb6 sdb7 sdb8

역할이 호스트와 전원 공급(source)으로 바뀌었고, USB 저장장치가 인식됐다. STUSB1600의 레지스터 0x27도 VBUS를 내보내는 상태(0x01)로 바뀌었다.

교훈: 결과가 이상하면 명령보다 먼저 케이블 상태를 확인하라. 같은 명령을 다시 돌려도 결과는 같다.

dwc2가 supply vusb_d not found, using dummy regulator 경고를 낸다. 동작에는 영향이 없지만 M6에서 정리한다.


3. WiFi/BT (AP6212) — 이미지에 펌웨어가 없었다

3-1. 구성

AP6212는 Broadcom BCM43430A1 칩을 쓴 WiFi와 블루투스 복합 모듈이다.

  WiFi 블루투스
연결 SDMMC3 (SDIO 4비트) UART7 (RTS/CTS 흐름 제어)
전원 켜기 WL_REG_ON = PF3 BT_REG_ON = PF15
리눅스 드라이버 brcmfmac hci_uart (Broadcom)
전원 핀 제어 MMC 코어 (mmc-pwrseq-simple) BT 드라이버 (shutdown-gpios)
wifi_pwrseq: wifi-pwrseq {
	compatible = "mmc-pwrseq-simple";
	reset-gpios = <&gpiof 3 GPIO_ACTIVE_LOW>;
};

&sdmmc3 {
	non-removable;
	cap-sdio-irq;
	bus-width = <4>;
	mmc-pwrseq = <&wifi_pwrseq>;
	...
	brcmf: wifi@1 {
		reg = <1>;
		compatible = "brcm,bcm4329-fmac";
	};
};

&uart7 {
	uart-has-rtscts;
	bluetooth {
		compatible = "brcm,bcm43438-bt";
		shutdown-gpios = <&gpiof 15 GPIO_ACTIVE_HIGH>;
		max-speed = <2000000>;
	};
};

블루투스 전원 핀(PF15)을 드라이버에 넘긴 것이 1차 작업과 다른 점이다. 10/28 MYiR 5.4에서 시험했을 때 블루투스는 부팅마다 결과가 달랐다. DTS에 BT 전원 핀이 없어서(No reset resource) 한 번 실패하면 드라이버가 칩을 다시 켜 볼 방법이 없었다. 이번에는 shutdown-gpios로 핀을 넘겨, 드라이버가 칩을 켜는 시점과 명령을 보내는 시점을 직접 관리하게 했다.

3-2. 펌웨어가 없다

처음 부팅했을 때 SDIO 카드는 보였지만 wlan0이 생기지 않았다.

mmc2: new high speed SDIO card at address 0001
brcmfmac mmc2:0001:1: Direct firmware load for brcm/brcmfmac43430-sdio.bin failed with error -2

-2는 “파일 없음”이다. ST 이미지에는 Broadcom 펌웨어 패키지가 들어 있지 않았다. 빌드 PC에는 패키지(linux-firmware-addons-bcm43xx)가 만들어져 있어서, 거기서 BCM43430 파일 4개만 꺼내 보드에 넣었다.

3-3. nvram은 모듈마다 다르다

WiFi 칩은 펌웨어(.bin) 말고도 nvram(.txt) 이 필요하다. 안테나와 크리스털 같은 모듈 고유 값이 들어 있는 파일이다. ST 패키지의 nvram은 ST 평가보드의 Murata 모듈용이라 크리스털이 37.4MHz로 적혀 있다. AP6212는 26MHz를 쓴다.

기존 MYiR OS 카드(앞에서 USB 시험에 쓴 그 카드)를 읽기 전용으로 마운트하고 AP6212용 파일을 가져왔다. brcmfmac는 nvram을 찾을 때 보드의 compatible 이름이 붙은 파일을 먼저 찾는다. 로그에 brcmfmac43430-sdio.knv,stm32mp157a-sc6.bin을 먼저 찾는 줄이 보이는 이유다. 그래서 기본 파일을 덮어쓰지 않고 보드 이름으로 복사했다.

brcmfmac43430-sdio.knv,stm32mp157a-sc6.txt   ← MYiR의 AP6212 nvram
BCM43430A1.knv,stm32mp157a-sc6.hcd           ← 블루투스 패치

블루투스 패치(.hcd)도 같은 규칙으로 보드 이름이 붙은 파일을 먼저 찾는다.

brcmfmac: Firmware: BCM43430/1 wl0: Aug 16 2022 03:05:14 version 7.45.98.125
Bluetooth: hci0: BCM43438A1 26MHz AP6212A1_CL1 BT4.0 OTP-BD-0061
Bluetooth: hci0: BCM43430A1 (001.002.009) build 0264

WiFi는 주변 AP 목록을 받아 왔다. 블루투스는 칩이 자기 이름을 알려 줬고 패치(build 0264)가 적용됐다. 칩이 보고한 26MHz도 가져온 nvram과 맞다.

여기까지는 “칩이 응답한다”는 확인일 뿐이다. 실제로 AP에 접속하고 휴대폰과 통신하는 시험은 뒤의 3-5, 3-6에서 했고, 거기서 진짜 문제가 나왔다.

3-4. 블루투스는 가끔 첫 명령을 놓친다

펌웨어를 넣기 전 첫 부팅에서는 블루투스가 완전히 실패했다.

Bluetooth: hci0: command 0xfc18 tx timeout
Bluetooth: hci0: BCM: failed to write update baudrate (-110)
Bluetooth: hci0: BCM: Reset failed (-110)

0xfc18은 Broadcom 전용 “통신 속도 변경” 명령이다. 드라이버가 칩 전원을 켜고 제일 먼저 보내는 명령인데, 칩이 응답하지 않았다.

드라이버 코드(hci_bcm.c)를 보면 전원 핀을 올린 뒤 100~120ms만 기다리고 바로 명령을 보낸다. 칩이 그 안에 준비되지 않으면 첫 명령을 놓친다. 그래서 부팅을 여러 번 반복해 봤다.

부팅 결과
처음 (커널 교체 직후 콜드) ❌ 완전 실패
reboot 1 ✅ 성공
재부팅 2회 (하나는 reboot, 하나는 방식 기록 못 함) 🔶 첫 명령 타임아웃 뒤 회복
콜드 1~3 ✅ 성공

펌웨어를 넣은 뒤 6번은 모두 최종적으로 동작했다. 첫 명령을 놓쳐도 드라이버가 다음 단계에서 회복한다. 다만 7번 중 1번 완전히 실패한 기록이 있다. 현장에서 “가끔 블루투스가 안 된다”는 불량이 될 수 있다.

대책은 M6에서 정한다.

  • 블루투스가 실패했으면 칩 전원을 다시 켜는 서비스를 둔다.
  • 또는 드라이버의 대기 시간을 늘리는 커널 패치를 넣는다.

칩의 전원 순서와 32kHz 클럭 안정 시간은 회로 설계자에게 확인을 요청할 생각이다.

3-5. WiFi 접속 — “비밀번호가 틀렸다”는 거짓말이었다

스캔이 되니 접속도 될 거라 생각했다. wpa_passphrase로 설정 파일을 만들고 wpa_supplicant를 띄웠더니 이렇게 나왔다.

wlan0: Associated with bc:9f:e4:57:07:02
brcmf_link_down: WLC_DISASSOC failed (-52)
wlan0: CTRL-EVENT-REGDOM-CHANGE init=COUNTRY_IE type=COUNTRY alpha2=KR
wlan0: WPA: 4-Way Handshake failed - pre-shared key may be incorrect
wlan0: CTRL-EVENT-SSID-TEMP-DISABLED ... reason=WRONG_KEY
brcmf_run_escan: error (-52)        ← 이후 1초마다 반복

AP에 붙은 직후 암호 확인 단계에서 끊기고, wpa_supplicant는 “비밀번호가 틀렸을 수 있다”고 한다. 그 뒤로는 스캔조차 -52로 실패하고, 재부팅해야 풀렸다.

같은 보드는 9월에 MYiR 5.4에서 같은 AP(KNVISION)에 접속한 기록이 있었다. 당시에는 connman으로 붙었는데, 기억 속의 “다른 값”은 connman 서비스 ID(wifi_<MAC>_4b4e564953494f4e_managed_psk)였다. 가운데 16진수가 KNVISION이다. 그러니 AP와 하드웨어는 문제가 아니다. 의심 가는 것을 하나씩 지워 나갔다.

의심 시험 결과
WiFi Direct(P2P) p2p_disabled=1 같음
실행 방식 wpa_supplicant@wlan0 서비스로 실행 같음
펌웨어 (ST 2022) MYiR 2018 펌웨어를 보드 이름으로 넣음 같음
펌웨어가 대신 하는 4-way handshake brcmfmac feature_disable=0x2000 같음
국가 코드 AP 없이 iw reg set KR만 실행 스캔이 바로 깨짐

단서는 로그의 REGDOM-CHANGE ... alpha2=KR 한 줄이었다. AP에 붙으면 AP가 알려 주는 국가 정보로 리눅스가 무선 규정을 바꾼다. 6.6 brcmfmac 소스를 보니, 국가 코드 매핑표가 없을 때 BCM43430에는 ISO 코드를 리비전 0으로 그대로 넣는 코드가 있었다.

static bool brmcf_use_iso3166_ccode_fallback(struct brcmf_pub *drvr)
{
	...
	switch (drvr->bus_if->chip) {
	case BRCM_CC_43430_CHIP_ID:	/* ← 우리 칩 */
	case BRCM_CC_4345_CHIP_ID:
	...
		return true;

칩 펌웨어의 국가별 규정 데이터(CLM)에는 “KR, 리비전 0”이 없다. 그래서 채널이 0개가 되고, 접속 중이던 링크는 끊기며, 그 뒤로는 스캔할 채널이 없다. AP 없이 확인해 보니 정확히 그랬다.

iw dev wlan0 scan | grep -c SSID:     → 12
iw reg set KR
iw dev wlan0 scan                     → command failed: Invalid argument (-22)

nvram의 기본값은 ccode=ALL(모든 채널)이라 부팅 직후에는 스캔이 잘 됐던 것이다. 1차(5.4)에서 접속이 됐던 이유도 이것으로 설명된다. 5.4의 드라이버는 국가 코드를 칩에 넣지 않았다.

해결은 DTS 한 줄이다. 매핑표(brcm,ccode-map)가 있으면 드라이버는 ISO 코드를 그대로 넣지 않고 표에서 찾는다. 표에 KR이 없으면 아무것도 바꾸지 않는다.

brcmf: wifi@1 {
	reg = <1>;
	compatible = "brcm,bcm4329-fmac";
	brcm,ccode-map = "XX-XX-0";	/* KR 과 맞는 항목 없음 -> 펌웨어 국가 설정 유지 */
};
iw reg set KR 후 스캔                → 12
wpa_state=COMPLETED
udhcpc: lease of 192.168.45.178 obtained from 192.168.45.1
64 bytes from 8.8.8.8: seq=0 ttl=116 time=40.138 ms

ST 펌웨어(2022)로 되돌려도 똑같이 접속됐다. 펌웨어는 원인이 아니었다. 마지막으로 보드의 랜 케이블을 뽑고, 빌드 PC에서 WiFi IP로 파일(뒤에 나올 rfcomm.ko)을 scp로 보내 WiFi만으로 데이터가 오가는 것까지 확인했다.

남은 과제가 있다. 지금은 칩이 ALL(모든 채널)로 동작하고, 한국에서 쓸 수 없는 채널은 리눅스 규정이 막는다. 전파 인증을 받으려면 칩도 한국 규정의 출력 제한으로 동작해야 한다. 그러려면 CLM에서 올바른 KR 리비전을 찾아 "KR-KR-<번호>"로 넣어야 한다. 모듈 업체에 물어볼 항목이다.

3-6. 블루투스 — 페어링, 그리고 바로 끊기는 이유

휴대폰과 페어링부터 했다. 처음에는 연결됐다가 숫자 확인 없이 바로 끊겼다.

hci0 78:F2:38:58:DD:79 type BR/EDR connected eir_len 20
hci0 78:F2:38:58:DD:79 type BR/EDR disconnected with reason 2

원인은 휴대폰에 남아 있던 10/28의 페어링 기록이었다. BT 주소는 칩에 고정된 값이라 OS를 바꿔도 같다. 휴대폰은 예전 키로 바로 붙으려 하고, 새 OS에는 그 키가 없으니 보드가 끊는다. 휴대폰에서 예전 등록을 해제하자 정상 절차로 진행됐다.

[agent] Confirm passkey 585086 (yes/no): yes
hci0 new_link_key 78:F2:38:58:DD:79 type 0x05 pin_len 0 store_hint 1
[CHG] Device 78:F2:38:58:DD:79 Bonded: yes
[CHG] Device 78:F2:38:58:DD:79 UUIDs: 00001105-...   ← 휴대폰 기능 목록 15개
[CHG] Device 78:F2:38:58:DD:79 Paired: yes
hci0 78:F2:38:58:DD:79 type BR/EDR disconnected with reason 2

페어링은 됐는데 여전히 바로 끊긴다. 이건 고장이 아니다. 클래식 블루투스는 쓸 기능(프로파일)이 있을 때만 연결을 유지한다. 보드에는 오디오도 시리얼도 열려 있지 않으니, 휴대폰이 기능 목록만 확인하고 연결을 정리한 것이다.

연결을 유지하며 통신하려면 보드에 기능을 열어야 한다. 가장 간단한 SPP(블루투스 시리얼) 로 시험했다. 그런데 첫 명령부터 막혔다.

rfcomm listen /dev/rfcomm0 1
Can't open RFCOMM control socket: Protocol not supported

ST 기본 커널 설정에는 블루투스 코어만 있고 RFCOMM(SPP의 기반)이 꺼져 있었다. 설정 조각에 추가했다.

CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y

블루투스 코어가 모듈(=m)이라 그 위에 얹는 RFCOMM도 모듈로만 만들 수 있다. 그래서 이번에는 uImage만 바꾸는 것으로 끝나지 않았다. 새로 만든 rfcomm.ko를 보드의 /lib/modules/6.6.129/에 넣고 depmod를 돌렸다. 이 파일을 보낸 길이 앞의 WiFi다.

시리얼 포트를 SDP에 등록하는 sdptool은 bluetoothd가 호환 모드(-C)로 돌아야 동작한다. 서비스 원본은 두고 덮어쓰기 설정(drop-in)을 넣었다.

# /etc/systemd/system/bluetooth.service.d/compat.conf
[Service]
ExecStart=
ExecStart=/usr/libexec/bluetooth/bluetoothd -C
bluetoothctl power on; bluetoothctl pairable on; bluetoothctl discoverable on
sdptool add --channel=1 SP
rfcomm listen /dev/rfcomm0 1 &
cat /dev/rfcomm0 &
echo "hello from SC6" > /dev/rfcomm0

휴대폰에서는 시리얼 터미널 앱(Serial Bluetooth Terminal)으로 보드에 접속했다. 보드가 보낸 글자가 앱에 나오고, 앱에서 보낸 글자가 보드 콘솔에 찍혔다. 이번에는 연결이 끊기지 않고 유지됐다.

다만 sdptool과 호환 모드는 BlueZ에서 오래전에 사라질 예정으로 표시된 방식이다. 제품에서 블루투스를 무엇에 쓸지(점검용 시리얼인지, 전용 앱용 BLE인지) 정한 뒤에 방식을 다시 고른다.


4. 외부 워치독 — 너무 빨라도 리셋하는 칩

4-1. 회로

PI2 (TIM8_CH4, PWM_WDI) → U10 TPS3813K33 WDI → /RESET → SW1-4 (DIP 스위치) → NRST
  • TPS3813은 윈도 워치독이다. 킥(WDI 엣지)이 너무 늦어도 리셋하고, 너무 빨라도 리셋한다. 소프트웨어가 멈춘 경우뿐 아니라, 폭주해서 킥을 마구 보내는 경우도 잡아낸다.
  • 타이밍 커패시터 C90(10nF)으로 계산한 허용 킥 간격은 약 0.2~3초다.
  • SW1-4가 OFF면 리셋 선이 끊긴다. 개발 중에는 OFF로 둔다.

10/22에 MYiR 5.4에서 한 번 시험했는데, 그때는 “킥을 주는 중에 SW1-4를 켜도 버티는지”를 확인하지 못했다.

4-2. DTS

ST 커널에 PI2를 TIM8_CH4로 쓰는 핀 그룹(pwm8_pins_a)이 이미 있다. 그래서 TIM8 노드만 켰다.

&timers8 {
	/delete-property/dmas;
	/delete-property/dma-names;
	status = "okay";

	pwm {
		pinctrl-names = "default", "sleep";
		pinctrl-0 = <&pwm8_pins_a>;
		pinctrl-1 = <&pwm8_sleep_pins_a>;
		status = "okay";
	};
};

DMA를 지운 이유는 TIM2와 같다. PWM 출력에는 DMA가 필요 없고, 남겨 두면 DMA 채널만 차지한다.

4-3. 시험

TIM8은 pwmchip4로 잡혔다. CH4는 그 안의 pwm3이다. 1Hz, 듀티 50%로 신호를 내면 0.5초마다 엣지가 생긴다.

C=/sys/class/pwm/pwmchip4
echo 3 > $C/export
echo 1000000000 > $C/pwm3/period
echo 500000000 > $C/pwm3/duty_cycle
echo 1 > $C/pwm3/enable
단계 결과
킥 시작 (SW1-4 OFF) 변화 없음
킥 중 SW1-4 ON, 10초 이상 대기 ✅ 리셋 없음
킥 정지 (enable = 0) ✅ 약 2초 뒤 리셋
SW1-4 OFF로 되돌림 ✅ 정상 부팅

리셋까지 약 2초는 눈으로 잰 값이다. 계산상 3초 안에만 킥하면 안전해야 하는데 그보다 짧게 느껴졌다. 지금 쓰는 0.5초 간격은 여유가 충분하다. 그래도 제품에 쓰기 전에 오실로스코프로 실제 시간을 잴 생각이다.

SW1-4를 늘 ON으로 둘 수는 아직 없다. 리눅스가 뜬 뒤에야 킥이 시작되는데, 부팅에는 3초보다 훨씬 오래 걸린다. ON으로 두면 부팅 도중 리셋이 걸려 계속 재부팅한다. U-Boot나 M4 코어에서 부팅 초기부터 킥을 주거나, C90을 키워서 허용 간격을 늘려야 한다.


5. 정리

커밋

(커밋 전) Linux 6.6: 블루투스 RFCOMM 커널 설정 추가 (SPP 통과)
e1deab6 Linux 6.6: WiFi 국가 코드 매핑 추가 (AP 접속 통과)
33f2e08 Linux 6.6: 외부 워치독(TIM8) 추가 (킥/리셋 경로 통과)
a1649a0 Linux 6.6: WiFi/BT(AP6212) 추가 (스캔/칩 응답 통과)
a823875 Linux 6.6: USB OTG(J5) + STUSB1600 추가 (디바이스/호스트 모드 통과)
acf0cdb Linux 6.6: QCA7005 PLC (SPI1) 추가 (펌웨어 자동 적재 통과)

오늘 배운 것

  1. 플래시 없는 칩은 OS가 펌웨어를 책임진다. QCA7005와 AP6212 모두 부팅할 때마다 리눅스가 펌웨어를 올린다. 펌웨어 파일과 적재 서비스가 이미지에 없으면 장치가 살아 있어도 쓸 수 없다.
  2. 펌웨어는 같은 칩이라도 모듈별 파일이 있다. WiFi nvram은 크리스털 주파수가 다르면 맞지 않는다. 보드 compatible 이름을 붙인 파일을 쓰면 기본 파일을 건드리지 않고 보드용 파일을 줄 수 있다.
  3. GPIO 줄에 이름을 붙이면 스크립트가 덜 깨진다. 칩 번호 대신 Q_RST라는 이름으로 찾게 했더니, 핀 번호가 바뀌어도 DTS만 고치면 된다.
  4. 결과가 이상하면 물리 상태부터 확인하라. USB 호스트 시험은 PC 케이블을 빼지 않은 것이 원인이었다.
  5. 간헐적인 문제는 반복해서 숫자로 남긴다. 블루투스는 한 번 성공했다고 끝낼 것이 아니었다. 7번 부팅하고 나서야 “첫 명령을 놓치지만 대부분 회복한다”는 모습이 보였다.
  6. 에러 메시지가 말하는 원인을 그대로 믿지 마라. wpa_supplicant의 “비밀번호가 틀렸을 수 있다”는 암호 확인 단계가 어떤 이유로든 실패하면 나오는 문구다. 실제 원인은 그 직전 줄의 국가 코드 변경이었다.
  7. “예전엔 됐다”는 기록이 범위를 좁혀 준다. 같은 보드와 같은 AP로 접속한 9월 기록이 있었기에 하드웨어와 AP를 의심하지 않고 소프트웨어 차이만 볼 수 있었다. 의심을 하나씩 바꿔 보는 표를 만들면 헤매는 시간이 줄어든다.
  8. “스캔된다”, “칩이 응답한다”는 기능 시험의 시작일 뿐이다. 실제로 접속하고 데이터를 주고받아 봐야 국가 코드나 커널 설정(RFCOMM) 같은 빠진 조각이 드러난다.

기능 시험 현황

지금 장비로 할 수 있는 시험은 모두 끝났다.

남은 항목 필요한 것
PM_INT (PH12) AC 부하
RCD_INT (PH15) 누전 시험 방법 (설계자와 협의)
이더넷 1G 1G 공유기나 스위치

다음 할 일 (M6, 이미지 완성)

  • 손으로 설치한 것들을 레이어에 넣기: QCA7005 펌웨어와 적재 서비스, PLC 도구, AP6212 펌웨어와 nvram, rfcomm.ko
  • WiFi 자동 접속 (wpa_supplicant@wlan0 활성화, DHCP), 유선과 무선이 같은 대역일 때의 라우팅
  • 블루투스 재시도 서비스 또는 대기 시간 패치, 블루투스 용도에 맞는 방식(SPP/BLE) 결정
  • MAC 주소 (이더넷, PLC 모뎀), 호스트 이름 (지금은 휴대폰 화면에 긴 이름이 그대로 보인다), 시간대
  • 모듈 업체 문의: CLM의 한국(KR) 리비전
  • PLC eth0이 DHCP를 시도하지 않게 하기
  • 그다음은 EVerest를 실제 하드웨어에 연결하기 (M7)

댓글남기기