Skip to content
Go DevBJ
Go back

lwIP 타이머가 안 돈다: NO_SYS에서 sys_check_timeouts() 빠지면 생기는 증상

Edit page

lwIP로 bring-up 할 때, 이상하게 “가끔만” 문제 생기는 케이스가 있다.

캡처를 떠도 애매하다.
패킷은 오가는데, 내부 상태가 이상하게 굳어있다.

이럴 때 제일 먼저 확인하는 게 난 이거다.

타이머 루프가 실제로 돌고 있나?

왜 NO_SYS에서 더 자주 터지나

lwIP는 내부에서 여러 타이머 이벤트를 돌린다.

RTOS + tcpip_thread 모델이면,
이 타이머는 보통 스레드가 알아서 돈다.

그런데 NO_SYS(bare-metal)로 쓰면 얘기가 달라진다.

네가 주기적으로 타이머 함수를 불러줘야
lwIP가 앞으로 간다

그 역할을 하는 게 sys_check_timeouts()다.

sys_check_timeouts()가 빠졌을 때 전형적인 증상

현장에서 자주 보이는 패턴은 이렇다.

1) DHCP가 “랜덤하게” 안 된다

어떤 네트워크에서는 되는데,
어떤 네트워크에서는 초기 Discover/Request 이후에 진행이 멈춘다.

“DHCP 서버가 이상한가?”로 넘어가기 전에,
타이머 처리가 실제로 돌아가서 재전송/백오프가 수행되는지부터 봐야 한다.

2) ARP가 오래된 엔트리를 계속 믿는다

링크를 뺐다 꼈거나,
상대가 바뀌었는데도,
장비가 이전 MAC으로 계속 때리는 것처럼 보일 때가 있다.

이때도 aging/refresh 쪽 타이머가 멈춰 있으면 상태가 쉽게 꼬인다.

3) TCP가 “죽었는데 안 죽은 것처럼” 남는다

타이머가 안 돌면 “재전송/정리”가 멈춘다.
그러면 부하가 올라갈수록 더 이상한 형태가 된다.

어디서 호출하는 게 제일 덜 아픈가

원칙은 단순하다.

NO_SYS 환경에서는
주기적으로 sys_check_timeouts()를 호출

호출 위치는 프로젝트 구조에 따라 다르지만,
실무에서 덜 아픈 패턴은 보통 둘 중 하나다.

1) main loop에서 주기적으로 호출

for (;;) {
  ethernet_poll();         // RX/TX 처리(보드 구현에 따라 다름)
  sys_check_timeouts();    // lwIP 타이머
  app_poll();
}

이 구조의 장점은 단순하다.

2) 1ms/10ms tick에서 호출 (주의: ISR에서 오래 돌리지 말기)

tick 기반으로 돌리는 것도 가능하지만,
ISR에서 오래 잡고 있지 않게만 주의하면 된다.

“얼마나 자주”가 적당하냐

정답은 프로젝트마다 다르지만,
bring-up 단계에서 가장 안전한 기준은 이거다.

여기서 포인트는 “정확한 주기”보다,
굶지 않게 돌리는 거다.

특히 main loop가 가끔 길어지면(플래시/센서/로그),
타이머가 순간적으로 굶을 수 있다.
그때부터 “가끔만” 문제가 시작된다.

빠른 디버깅 체크리스트

  1. NO_SYS 설정을 다시 확인(내가 RTOS 모델인지, bare-metal인지)
  2. sys_check_timeouts()가 호출되는지 grep
  3. 호출 주기가 가끔 100ms 이상 늘어나는 구간이 없는지(로그/플래시/연산)
  4. DHCP/ARP/TCP 문제가 섞여 나오면 타이머 굶김부터 의심
  5. RTOS 모델이라면 반대로 “두 군데에서 동시에 돌리는 실수”가 없는지 확인

결론

NO_SYS에서 lwIP는 “네가 시간을 흘려줘야” 앞으로 간다. DHCP/ARP/TCP가 가끔만 이상해지면, sys_check_timeouts() 호출 여부와 호출 주기부터 잡는 게 가장 싸고 빠르다.


DevBJ | No Bio, Just Log 기술 삽질로그


Edit page
Share this post on:

Previous Post
기술 블로그 주제가 너무 좁을 때, 유입용 카테고리 다시 잡는 법
Next Post
DoIP는 붙었는데 진단이 안 된다: Entity Status/Power Mode로 상태부터 확인하기