실리콘랩스의 EFR32FG1 시리즈를 개발하고 양산하는 도중, 꽤 많은 생산 불량이 나오기 시작했다.

한 7% 정도... ?

무한 재부팅이 되고, 와치 독을 빼면 어디선가 멈춰서 JTAG도 안되고, 멀쩡한 건 정상 부팅이 되고...

문제를 분석하기 위해 크리스털 발진을 찍어보니 발진을 하는 순간, 리셋이 되었다. 어디인지 보기 위해 디버깅 메시지를 이리저리 추가하니, RAIL_StartRx 함수가 실행되면 다음 리셋이 실행되는 것을 확인했다.

(https://docs.silabs.com/rail/latest/group-receive)

무선 RF 통신을 하는 장비가 통신을 하니 멈춘다니.. 우선 크리스털이 문제인가 해서 교체해 봤으나

문제는 해결되지 않았다. 냉납인가 해서 납땜도 다시 해봤으나, 해결된 건 없었다.

https://www.silabs.com/documents/public/application-notes/an0004.1-efm32-cmu.pdf

위 문서를 보면 HFXO 관련 start-up 및 calibrate 관련 내용이 있어서 프로젝트의 클럭 초기화 부분을 보기로 했다.

 

bsp_init.c

 
void BSP_initClocks(void)
{
  // --------------------------------
  // Initialize HFXO if present
 
#if BSP_CLK_HFXO_PRESENT
  // HFXO
  CMU_HFXOInit_TypeDef hfxoInit = BSP_CLK_HFXO_INIT;
  int ctune = -1;
 
#if defined(_DEVINFO_MODXOCAL_HFXOCTUNE_MASK) // Series 1
  if ((DEVINFO->MODULEINFO & _DEVINFO_MODULEINFO_HFXOCALVAL_MASK) == 0) {
    ctune = DEVINFO->MODXOCAL & _DEVINFO_MODXOCAL_HFXOCTUNE_MASK;
  }
#elif defined(_DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK) // Series 2
  if ((DEVINFO->MODULEINFO & _DEVINFO_MODULEINFO_HFXOCALVAL_MASK) == 0) {
    ctune = DEVINFO->MODXOCAL & _DEVINFO_MODXOCAL_HFXOCTUNEXIANA_MASK;
  }
#endif
 
  if ((ctune == -1&& (MFG_CTUNE_EN == 1&& (MFG_CTUNE_VAL != 0xFFFF)) {
    ctune = MFG_CTUNE_VAL;
  }
 
#if defined(BSP_CLK_HFXO_CTUNE) && BSP_CLK_HFXO_CTUNE >= 0
  if (ctune == -1) {
    ctune = BSP_CLK_HFXO_CTUNE;
  }
#endif
 
  if (ctune != -1) {
#if defined(_SILICON_LABS_32B_SERIES_1)
    hfxoInit.ctuneSteadyState = ctune;
#elif defined(_SILICON_LABS_32B_SERIES_2)
    hfxoInit.ctuneXoAna = ctune;
    hfxoInit.ctuneXiAna = ctune;
#endif
  }
  CMU_HFXOInit(&hfxoInit);
  SystemHFXOClockSet(BSP_CLK_HFXO_FREQ);
#endif // BSP_CLK_HFXO_PRESENT
cs

위 소스를 보면 CMU_HFXOInit 함수를 통해 HFXO를 초기화하고 있다.

로드 캐패시터 값 ctune을 입력받는데 BSP_CLK_HFXO_CTUNE 값을 사용하는 걸로… 알고 있는데 응?

MFG_CTUNE_VAL이라는 값을 먼저 넣는 것이 보인다. 또 설정하는 값이 있었다고?

위 설정에서는 MFG_CTUNE_EN 이 0으로 되어 있지만 처음엔 1 이었다.

MFG_CTUNE_ADDR는 0x0FE0로 시작하는 걸 보아.. USer Data 영역인 것을 확인했다.

 

어 그런데.. User Data 영역? 이번 제품은 제품번호와 설정값을 main flash가 아닌 User Data에 쓴다. 이유는 플래쉬를 erase 해도 설정값을 지우지 않기 위해서이다.


정상적인 케이스에는 문제가 없으나, 제품 설정 중 전원이 꺼지면 문제가 되는데..

User Data 영역에 잘못된 값이 저장되는 바람에 MFG_CTUNE_VAL 가 이상한 값이 나오면서 HFXO가

잘못 발진되어 CPU가 멈추는 증상이 나온 것이었다...

원래 저 위치에 값을 쓰지도 않기 때문에 이번 기회에 코드를 삭제해 버렸다.

해당 펌웨어를 다시 다운로드하니 문제가 되던 제품들이 정상 동작하기 시작했다...

DCDC 기능 설정 시에는 Device Info 영역의 데이터 읽어 오면서 왜 HXFO Ctune 값은 User Data 영역에서 읽어 오는지 모르겠다. 말 그대로 사용자 영역인데!!!!!

이번 일로 교훈을 얻은 것은 예제를 그대로 사용하지 말 것!! !!