마이크로칩의 MCC Melody가 내 코드를 덮어쓰지 못하게 하는 방법

마이크로칩의 MCC (MPLAB Code Configurator)는 마이크로컨트롤러 설정을 간단하게 할 수 있도록 설계된 그래픽 인터페이스 도구로 문서화가 잘되어 있습니다. 규격서를 몇 시간씩 뒤지며 주변장치를 수동으로 설정하는 대신, 프로그래머는 몇 분 만에 직관적으로 마이크로컨트롤러를 설정할 수 있습니다.

이 글에서 함수 등록은 MCC가 생성한 코드와 프로그래머의 main.c 프로그램을 연결하는 핵심 연결 고리임을 보여줍니다. 이는 매우 명쾌한 해결책이지만, 동시에 초보 프로그래머를 쉽게 함정에 빠뜨릴 수 있는 포인트이기도 합니다. 함수 등록을 올바르게 사용하면, MCC 도구가 여러분의 코드를 더 이상 덮어쓰지는 못할 것입니다.

예제로는 PIC16F13145 Curiosity 평가 보드를 사용합니다 (그림 1). 초기 프로그램은 아래에서 다운로드할 수 있습니다.

Digital.X.zip (957.8 KB)

그림 1: 브레드보드 위에 장착된 PIC16F13145 Curiosity 보드와 이를 보조하는 푸시버튼 및 LED.

MCC 사용하기

일반적인 MCC 프로젝트는 그림 2와 같습니다. 이 예제에서는 구성 가능 로직 블록 (Configurable Logic Block, CLB)과 타이머 0 (TMR0)이 프로젝트에 추가되어 있습니다. 또한 인터럽트 서비스 루틴 (ISR)을 비롯해, 클록 및 핀 설정과 같은 시스템 수준의 구성 요소들도 포함되어 있습니다.

글을 간결하게 유지하기 위해, 강조 표시된 “Generate” 버튼을 눌렀을 때 무슨 일이 발생하는지에 초점을 맞추겠습니다. 추가 정보는 이 페이지를 참고하시기 바랍니다.

그림 2: MPLAB MCC을 사용한 PIC16 프로젝트 설정 화면 (Generate 버튼 강조).

MCC 코드 생성기는 어디에 코드를 저장하는가?

그림 3은 프로젝트의 파일 구조를 보여줍니다. MCC가 생성한 코드는 글자 그대로 mcc_generated_files 디렉터리에 저장됩니다.

MCC에 대해 반드시 알아야 할 사항

  • 그림 2의 Generate 버튼을 누를 때마다 MCC는 mcc_generated_files 디렉터리의 내용을 덮어씁니다.
  • 이 파일들에 저장된 코드들은 모두 사라질 수 있기 때문에 엄청난 좌절감을 불러올 수도 있습니다.
  • 이 디렉터리 외부의 파일은 건드리지 않습니다. 예를 들어 main.c는 MCC에 의해 수정되지 않습니다.

그림 3: MPLAB 프로젝트 파일 구조.

MCC가 생성한 파일과 main.c를 어떻게 연결할 것인가?

이 부분이 이 글의 핵심입니다. MCC가 생성한 파일을 직접 수정하는 대신, C 언어에 내장된 함수 등록 메커니즘을 활용합니다.

함수 등록 예제

main()에서 호출되는 Bob()이라는 함수가 있다고 가정하겠습니다. 기계 수준에서 보면, 함수 Bob은 하나의 메모리 주소에 위치하며, 프로그램 카운터가 그 주소를 가리킬 때 실행됩니다. 함수 포인터를 사용해 Bob()을 Alice()로 리디렉션합니다. 이제 Bob()을 호출하면, 실제로 동작하는 것은 Alice()입니다.
선호하는 MPLAB 코드 템플릿이 다음 목록에 나와 있습니다:

  • 슈퍼 루프는 아무 동작도 하지 않는다.
  • TMR0 ISR에서 수행되는 동작 로직이 My_1ms_Callback 함수로 정리되어 있습니다.
    • TMR0는 1ms 주기의 인터럽트를 생성합니다.
    • 포트 B의 핀 5에 연결된 LED는 1초에 한 번 토글 됩니다.
#include "mcc_generated_files/system/system.h"

volatile uint16_t msTicks = 0;

static void My_1ms_Callback(void){
    if (++msTicks >= 500) {
        msTicks = 0;
        LATBbits.LATB5 ^= 1;
    }
}

int main(void){
    
    SYSTEM_Initialize();
    
    /*
      * Register the custom 1ms callback with MCC’s timer module.
    */
    TMR0_OverflowCallbackRegister(My_1ms_Callback);

    INTERRUPT_GlobalInterruptEnable(); 
    INTERRUPT_PeripheralInterruptEnable(); 

    while(1){
        ;
    }    
}

목록 1: 함수 등록 과정을 보여주는 최소한의 코드.

함수 등록의 동작 원리

우리의 목표는 MCC 파일을 수정하지 않고도 그림 3의 mcc_generated_files 디렉터리에 포함된 코드를 사용하는 것입니다 - MCC 파일을 수정하면 코드가 덮어써집니다. 해결책은 My_1ms_Callback 함수를 MCC 생성 코드에 등록하는 것입니다. 앞서 설명한 예제와 동일하게, Bob()을 호출하지만 실제로 일을 하는 것은 Alice()입니다.

함수 등록은 아래 단 한 줄의 코드로 수행됩니다:

    TMR0_OverflowCallbackRegister(My_1ms_Callback);

바로 이 한 줄이 main()을 MCC 생성 코드에 안전하게 연결하는 핵심입니다. 함수 등록이 이러한 연결을 가능하게 합니다.

기술 팁: MCC는 숙련된 프로그래머에게는 매우 훌륭한 도구입니다. 하지만 초보자라면 레지스터를 직접 설정해 보는 것이 더 도움이 됩니다. 몇 주 동안 규격서를 깊게 살펴보는 것만으로도 실력이 크게 향상됩니다. 개인적인 생각으로는, 자전거 타는 법을 배우는 것과 같습니다. 몸이 기억한 규격서는 문제가 발생했을 때 큰 자산이 됩니다. 또한 이 글에 다룬 PIC16과 같이 하나의 마이크로컨트롤러를 깊이 있게 공부하는 것은 32비트 MCU를 포함한 다른 장치로 넘어가는 관문이 됩니다.

요즘은 종이로 된 규격서가 없는 것이 아쉽습니다. 예전에는 버그 부분을 항상 강조 표시하고 이중 밑줄을 그어 두었습니다. 포트가 아닌 TRIS에 쓰는 실수와 같은 경우인데, 그 작은 버그 하나의 문제 해결에 몇 시간을 날린 적이 있습니다.

글을 맺으며

솔직히 말해, 저 역시 마이크로칩 문서를 제대로 읽지 않았던 시절이 있었습니다. 도구 때문에 답답함을 느꼈던 적도 많았습니다. 이 팁이 여러분의 시간을 조금이라도 절약해 줄 것이라고 믿습니다.

마지막으로, 함수 포인터를 우리에게 선물한 Kernighan과 Ritchie에게 경의를 표하며 글을 마칩니다.

감사합니다.

APDahlen

저자의 관련 게시글

이 글을 흥미롭게 읽었다면, 다음 글들도 도움이 될 수 있습니다:

저자 소개

미합중국 해안경비대(USCG) 소령(LCDR)으로 전역한 Aaron Dahlen은 디지키에서 애플리케이션 엔지니어로 근무하고 있습니다. 27년간의 군 복무 동안 기술자 및 엔지니어로서 쌓아온 그 만의 전자 및 자동화에 대한 지식은 12년간의 교단을 통해 (상호 연계되어) 더욱 향상되었습니다. 미네소타 주립대학, Mankato에서 전기공학 석사(MSEE) 학위를 받은 Dahlen은 ABET(Accreditation Board for Engineering and Technology, 미국 공학 기술 인증 위원회) 공인 전기공학 과정을 가르치고, EET(Electrical Engineering Technology, 전기공학 기술) 과정의 프로그램 조정관으로 일했으며, 군 전자 기술자에게 부품 수준의 수리에 대해 가르쳤습니다. 미네소타 주 북부의 집으로 돌아와 이런 류의 연구와 글쓰기를 즐기고 있습니다.



영문 원본: Preventing Microchip’s MCC Melody from Overwriting Your Code