BLDC 컨트롤의 이상한 소프트웨어 버그: '읽기 전용' 레지스터에 주의

시스템이 예상한 대로 작동하는 것 같지만 원격 측정 데이터에는 그렇지 않은 것으로 나타나는 매주 이상한 버그가 발생했습니다. 모터의 회전 속도를 결정하는 수요 입력이 85%로 보고되었지만 다행히도 모터는 회전하지 않았습니다. 중요한 문제가 아니며 원격 측정 구문 분석 소프트웨어에 문제가 있다고 말씀드리고 싶었지만, 뭔가 좀 이상했습니다. 시스템을 자세히 살펴보고 이 버그를 일으킨 원인을 확인했습니다.

이 시스템에서는 Allegro Microsystems A4964 브러시리스 DC(BLDC) 모터 구동기 칩을 사용했습니다. 이 칩은 제가 특별히 좋아하는 칩인데, 유연한 모터 구동 솔루션을 제공하고 마이크로 컨트롤러(MCU)에서 CPU 주기를 불러와 전용 하드웨어 칩으로 전달할 수 있는 모든 제어 코드를 가져옵니다(그림 1).

그림 1: A4964는 BLDC 모터 제어권을 MCU에서 전용 하드웨어로 전환하는 데 유용합니다. (이미지 출처: Allegro Microsystems)

이 시스템 구성에서는 SPI 통신 인터페이스를 활용하여 BLDC 모터를 구동 및 제어하는 방법을 결정하는 32 온칩 레지스터를 설정합니다.

초기화 루틴에서 설정 중에 원하는 모터 구성 파라미터를 포함하는 구성 테이블을 읽어서 응용 분야에 맞게 A4964를 구성합니다. 아래 나열된 의사 코드(예시용)(목록 1):

복사for(uint8_t WriteIndex = 0; WriteIndex < A4964MaxRegister; WriteIndex++)
{
    // Write value stored in A4964Config at index WriteIndex to the chip
}

목록 1: 모터 구성 파라미터를 읽는 초기화 루틴을 보여줍니다. (코드 출처: Jacob Beningo)

초기화의 관점에서 코드에 문제될 것이 별로 없으므로 응용 분야에서 주기적으로 호출되는 기본 논리를 검사하기로 신속히 결정했습니다. 이 코드는 좀 더 흥미롭습니다. 응용 분야 도메인은 RAM에 저장된 값에 영향을 줄 수 있는 방사선이 풍부한 환경입니다. 초기화 값은 시작할 때 A4964의 RAM에 기록되므로, 발생할 수 있는 비트 플립을 빠르게 처리하기 위해 A4964 메모리를 주기적으로 읽었습니다. 그리고 불일치가 발생하면 설정을 업데이트했습니다. 의사 코드는 다음과 비슷합니다(목록 2).

복사for(uint8_t Index = 0; Index < A4964MaxRegister; Index++)
{
    // Read the A4964 configuration register at location Index

   // If read value does not match expected value, write configuration value
}

목록 2: 로컬 방사선이 RAM에 저장되는 값에 영향을 줄 수 있으므로, 비트 플립을 처리하기 위해 A4964 메모리를 주기적으로 읽고 불일치가 발생할 경우 설정을 업데이트했습니다. (코드 출처: Jacob Beningo)

매우 간단한 코드라서 문제될 것이 별로 없는데, 또 다시 칩에 잘못된 수요 입력 값이 기록되었습니다. 올바른 값을 보고하기 전에 이 값이 일부 원격 측정에 일시적으로 나타나는 것처럼 보였는데, 결국에는 잘못된 값이 제공되었습니다. 이상한 일이죠.

더 이상한 점은 레지스터에 85%로 기록된 구성 값 또는 응용 제품 값은 없었다는 점입니다. 그렇다면 이 85%는 도대체 어디서 온 값일까요? 숫자 85는 16진수로 전환하면 0x55입니다. 코드베이스에서 0x55가 표시된 위치는 당연히 있습니다. 0x55는 SPI 버스에서 읽기 작업을 위한 더미 쓰기 문자로 사용됩니다. 하지만 읽기 작업을 쓰기 작업으로 어떻게 전환할까요?

A4964 규격서를 자세히 살펴보면 답변을 쉽게 알 수 있습니다(그림 2).

그림 2: 규격서의 코드 조각에서 문제를 확인할 수 있습니다. 레지스터 30은 쓰기 전용입니다. (이미지 출처: Allegro Microsystems)

모터에 대한 수요 입력(DI)을 관리하는 레지스터 30은 쓰기 전용 레지스터입니다. 레지스터에서 읽기를 시도하면 레지스터에 더미 바이트를 쓰는 효과가 있습니다. 단순 초기화 및 칩 새로 고침 기능은 수요 입력 레지스터를 읽어서 설정을 확인하려고 시도하여 의도치 않게 새 수요 입력을 기록합니다. 쓰기 레지스터를 읽고 항상 조금 지난 이후에 올바른 값이 기록되지만 잘못된 값이 시스템 원격 측정이 잘못된 값의 영향을 받을 정도로 빠르지 않으므로 시스템은 계속해서 예상한 대로 작동합니다.

A4964를 사용하면 소프트웨어 개발자가 메모리 맵 전반에서 구성 데이터를 쓸 수 없고, 레지스터 29 이후에 중지해야 합니다. 마지막 두 어드레서블 레지스터는 특별 쓰기 및 읽기 전용 레지스터입니다.

드라이버를 작성하거나 소프트웨어를 구현하기 위한 노력에 상관없이 항상 문제가 발생합니다. 이상한 버그는 하드웨어에 대한 새로운 것을 배우고 새로운 모범 사례를 생성할 기회가 되기도 합니다. '읽기/쓰기 전용 레지스터에 주의'하고 올바르게 상호 작용하기 위해 이 작고 이상한 버그를 내 목록에 추가했습니다. 그렇지 않으면 쓰기 전용 레지스터를 읽을 때 시스템 내에서 심각한 이벤트가 발생할 수 있습니다.

작성자 정보

Image of Jacob Beningo

Jacob Beningo는 임베디드 소프트웨어 컨설턴트로서 현재 십여 개국 이상의 국가에 있는 고객들과 협력하여 제품 품질, 비용, 출시 기간을 향상시켜 고객의 비즈니스를 극적으로 변화시키고 있습니다. 그는 인기 있는 강연자이자 기술 교육자이며 임베디드 소프트웨어 개발 기술에 대해 200개 이상의 기사를 발표했습니다. 그는 미시간 대학교 공학 석사 학위를 비롯하여 세 개의 학위를 소지하고 있습니다. 월간 Embedded Bytes 뉴스레터를 수신하려면 jacob@beningo.com 및 Jacob Beningo의 웹 사이트인 www.beningo.com으로 언제든지 문의해 주세요.

More posts by Jacob Beningo
 TechForum

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum