CategoriesnRF52 Lecture

Lecture 3. 버튼과 LED 제어하기(GPIOTE)

Lecture 3. 버튼과 LED 제어하기(GPIOTE)

강의목표

  • nRF52 개발 보드에 내장된 버튼의 입력을 받아 RGB LED를 제어할 수 있다.
  • GPIOTE(GPIO Task & Event) 레지스터를 제어할 수 있다.
  • GPIOTE의 인터럽트 기능을 활용하여 이벤트를 처리할 수 있다.

준비물

  • Roverdyn nRF52 개발 보드 × 1 (구매하기)
  • 전원 공급용 Type-C USB 케이블 × 1
  • Windows 데스크톱 혹은 랩톱 × 1
  • VS Code 개발 환경

GPIOTE 레지스터 설정 및 사용하기

GPIOTE는 General Purpose Input/Output Task & Event의 약자로서 말 그대로 GPIO의 작업과 이벤트를 담당하는 레지스터입니다. GPIO의 작업으로는 SET, CLEAR 등과 같이 핀의 출력을 설정하였을 때 어떠한 동작을 할 것인지 설정하는 것이 있으며 Event는 GPIO의 값의 변화에 따라 동작하는 모드입니다. GPIOTE는 단순히 GPIO를 이용하는 것 보다 더 간단하고 효율적으로 GPIO의 동작을 제어하거나 이벤트를 캡쳐하여 효율적인 펌웨어를 개발하는데 도움을 줍니다.

GPIOTE Event

GPIOTE 이벤트는 각 GPIO의 입력에 따라 동작하는 모드입니다. 각 이벤트는 다음과 같은 이벤트를 입력 받을 수 있습니다.

  • Rising Edge : GPIO핀 값이 Low -> High로 변할 때 동작
  • Falling Edge : GPIO핀 값이 High->Low로 변할 때 동작
  • Any changes : GPIO핀 값의 상태가 High 혹은 Low에서 다른 상태로 변할 때 동작

GPIOTE Task

GPIOTE Task는 GPIO의 입력 혹은 동작에 따라 특정 동작을 지정하여 실행시킬 수 있습니다. 매크로에 가까운 개념으로 인터럽트와 결합하여 다양한 동작을 수행시킬 수 있습니다.

본 튜토리얼은 GPIOTE의 Event 기능을 이용하여 내장 버튼의 입력을 받아 개발 보드의 LED를 제어합니다. 이를 위해서 GPIOTE의 핀 번호 할당, 인터럽트 설정을 하여 각 LED를 제어할 수 있습니다. 또한, LED 켜지는 순서를 제어하기 위해서 간단한 알고리즘을 구현하여야 합니다.

로버다인의 nRF52 개발 보드는 모두 세 개의 버튼이 있으며 이 중 하나는 Reset 핀에 연결되어 하드웨어 리셋을 수행할 수 있습니다. 각 버튼은 다음과 같은 핀에 연결되어 있습니다.

  • 버튼1 : P0.19
  • 버튼2 : p0.20
  • 리셋버튼 : p0.21/RESET

 리셋 버튼은 일반 GPIO포트인 P0.21로 변경하여 사용할 수 있으나 별도의 설정이 필요합니다.

GPIOTE 설정 및 사용하기

GPIO의 레지스터는 몇 가지 설정을 하여 사용할 수 있습니다. 다음은 기본적인 GPIO의 설정입니다.

  • NRF_GPIO->DIRSET : 핀의 출력 방향을 설정합니다.
  • NRF_GPIO->OUTSET : 핀을 출력으로 설정하였을 때 핀을 High로 설정합니다.
  • NRF_GPIO->OUTCLR : 핀을 출력으로 설정하였을 때 핀을 Low로 설정합니다.

GPIO 레지스터의 값을 입력하기 위해서는 설정하고자 하는 핀의 비트를 0 혹은 1로 설정하여 제어할 수 있습니다. 이를 확인하기 위해 먼저 nRF52 시리즈의 데이터 시트를 확인합니다.

 위 데이터시트는 nRF52832의 데이터시트입니다. GPIO 레지스터 챕터에서 확인할 수 있는 내용으로, NRFGPIO->DIRSET 레지스터에 관한 내용입니다. 해당 데이터시트를 자세히 보면 Bit number가 0인  부분의 아이디는 ‘A’로 표시되어 있으며, 해당 비트를 0으로 설정하면 해당 핀(PIN0)을 Input으로 설정하고 1로 설정하면 Output으로 설정됩니다. 만약 22번핀(P0.22)를 출력으로 설정하고자 한다면 NRF_GPIO->DIRSET = (1 << 22) 으로 설정하면 위 데이터시트상 ID가 ‘W’인 22번 핀의 입출력 방향이 출력으로 설정됩니다. 만약 중복으로 설정하고자 한다면 Or(|) 연산자를 붙여 설정하면 됩니다.

 Zephyr RTOS는 간단한 Sleep 함수가 있습니다. 메인 쓰레드에서 사용할 수 있는 k_msleep 이라는 함수는 매개 변수로  밀리초(ms) 단위로 입력받아 CPU의 동작을 중지 시킬 수 있습니다. 예를 들어 k_msleep(1000)으로 설정하면 1초간 지연 시킨다는 뜻입니다. 또 다른 함수로는 k_usleep이 있으며 k_msleep 함수와 비슷하지만 매개 변수로는 마이크로초 단위(us)를 입력 받습니다.

 보다 자세한 내용은 아래 소스코드를 참조해주세요.

소스 코드

				
					/*
        MIT License

        Copyright (c) 2024. Seonguk Jeong, Roverdyn Inc.

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
*/
#include <zephyr/kernel.h>

/* Button pin no. definition */
#define USER_BTN1       19
#define USER_BTN2       20

/* LED pin no. definition */
#define LED_RED         22
#define LED_GREEN       23
#define LED_BLUE        24

/* Define Event Lisenter */
void GPIOTE_IRQHandler();

/* Global Variables */
static uint8_t led_order = 0;

int main(void)
{
        // Debug message for start
        printk("Application start.\n");

        // Set gpio direction for LEDs & turn off
        NRF_GPIO->DIRSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
        NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);

        // Set Button GPIO as Input
        NRF_GPIO->PIN_CNF[USER_BTN1] = 0x0C;
        NRF_GPIO->PIN_CNF[USER_BTN2] = 0x0C;

        // Set Interrupt Event for buttons
        NRF_GPIOTE->INTENSET = 0x01;                    // Enable EVENT_IN[0]
        NRF_GPIOTE->INTENSET = (0x01 << 4);                   // Enable EVENT_IN[4]
        
        // Set GPIOTE for user button 1
        NRF_GPIOTE->CONFIG[0] = 0x01;                   // Set Event mode for EVENT_IN[0]
        NRF_GPIOTE->CONFIG[0] |= (USER_BTN1 << 8);      // Set pin no. for EVENT_IN[0]
        NRF_GPIOTE->CONFIG[0] |= (0x02 << 16);          // Set HiToLo polarity for EVENT_IN[0]
        
        // Set GPIOTE for user button 2
        NRF_GPIOTE->CONFIG[4] = 0x01;                   // Set Event mode for EVENT_IN[4]
        NRF_GPIOTE->CONFIG[4] |= (USER_BTN2 << 8);      // Set pin no. for EVENT_IN[4]
        NRF_GPIOTE->CONFIG[4] |= (0x02 << 16);          // Set HiToLo polarity for EVENT_IN[4]
        
        // Enable IRQHandler for interrupt
        IRQ_DIRECT_CONNECT(GPIOTE_IRQn, 0, GPIOTE_IRQHandler, 0);
        irq_enable(GPIOTE_IRQn);

        // Main loop
        while(true){
                k_usleep(1);
        }
        return 0;
}

void GPIOTE_IRQHandler(){
        // Interrupt event for button 1
        if(NRF_GPIOTE->EVENTS_IN[0] == 1){
                // Button 1 : Shift color to left
                NRF_GPIOTE->EVENTS_IN[0] = 0;
                if(led_order == 0){
                        led_order = 2;
                }else{
                        led_order--;
                }

                // Turn off all LEDs
                NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
                switch(led_order){
                        case 0:
                                printk("Button 1 pressed : LED Red\n");
                                NRF_GPIO->OUTCLR = (1 << LED_RED);
                        break;
                        case 1:
                                printk("Button 1 pressed : LED Green\n");
                                NRF_GPIO->OUTCLR = (1 << LED_GREEN);
                        break;
                        case 2:
                                printk("Button 1 pressed : LED Blue\n");
                                NRF_GPIO->OUTCLR = (1 << LED_BLUE);
                        break;
                }                
        }

        // Interrupt event for button 2
        if(NRF_GPIOTE->EVENTS_IN[4] == 1){
                // Button 2 : Shift color to right
                NRF_GPIOTE->EVENTS_IN[4] = 0;
                if(led_order == 2){
                        led_order = 0;
                }else{
                        led_order++;
                }

                // Turn off all LEDs
                NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
                switch(led_order){
                        case 0:
                                printk("Button 2 pressed : LED Red\n");
                                NRF_GPIO->OUTCLR = (1 << LED_RED);
                        break;
                        case 1:
                                printk("Button 2 pressed : LED Green\n");
                                NRF_GPIO->OUTCLR = (1 << LED_GREEN);
                        break;
                        case 2:
                                printk("Button 2 pressed : LED Blue\n");
                                NRF_GPIO->OUTCLR = (1 << LED_BLUE);
                        break;
                }  
        }
}
				
			

빌드 및 컴파일, 다운로드

작성한 소스 코드는 빌드 및 컴파일을 한 후 최종적으로는 디버거 혹은 프로그래머 장비를 이용하여 개발 보드에 다운로드할 수 있습니다. 개발 보드에 관한 설정은 “nRF52  개발환경 구축하기” 튜토리얼을 확인하여 설정할 수 있습니다.

 작성한 코드를 빌드하기 위해서는 우선 다운로드 하고자 하는 보드를 설정해주어야 합니다. 대상 보드를 정의하기 위하여 좌측 패널의 메뉴 중 “Run and Debug” 메뉴를 클릭한 후 “NRF CONNECT:WELCOME” 패널 내부의 “Create a new board” 메뉴를 클릭합니다.

화면 상단에 패널이 나타나면 새로운 보드의 이름을 작성한 후 엔터키를 눌러줍니다. 보드의 이름은 영문으로 작성하여야 합니다.

다음으로 보드의 이름을 한번 더 작성합니다. 다만 이 이름은 기계가 인식할 수 있는 방법으로 작성합니다. 대게 자동으로 작성되어 있으므로 엔터키를 눌러 다음으로 넘어갑니다.

보드가 사용하는 MCU의 종류를 입력합니다. nRF52 개발 보드는 nRF52810-QFAA 혹은 nRF52832-QFAA 두 종류를 사용합니다.

새로 작성한 보드의 정보가 저장될 위치를 설정합니다. 기본적으로 프로젝트 내부의 “board” 폴더가 지정되어 있습니다.

마지막으로 보드의 제조사를 설정합니다. 해당 내용은 작성하지 않아도 동작에 지장이 없습니다.

위와 같이 새 보드의 정의 및 파일 생성이 완료되었다면 빌드 환경을 구성할 수 있습니다. 빌드 환경은 위의 보드 추가 방법과 같이 동일한 “Run & Debug” 패널의 “NRF CONNECT: APPLICATION” 항목에서 설정할 수 있습니다.

 APPLICATION 패널 중 우측에 위치한 “Add Build Configuration” 아이콘을 눌러 설정창을 열어줍니다.

빌드 환경 설정 창이 나타나면 위 그림과 같이 “Custom board” 항목을 눌러준 다음 이전에 생성한 보드를 선택합니다. 위 예제에서는 “nrf52_devboard_52832” 항목을 선택하였습니다. 이는 사용자가 만든 보드 이름에 따라 달라질 수 있습니다. 또한 Configuration 항목을 prj.conf 로 선택합니다. 이후 우측 하단의 “Build configuration” 버튼을 눌러 빌드 환경을 구성합니다.

이상 없이 빌드가 완료되었다면 다시 APPLICATION  패널로 이동하여 “Flash All Linked Devices” 항목을 눌러 컴파일된 펌웨어의 다운로드를 시작합니다. 이 때, 타겟 보드는 컴퓨터와 Jlink 혹은 기타 디버거, 프로그래머와 연결이 되어 있어야 합니다.

위와 같이 빌드를 시작하며 컴파일이 완료된 후 자동으로 컴파일된 펌웨어를 개발 보드로 전송합니다. 전송이 완료되면 개발 보드를 재부팅 하거나 전원을 분리하였다가 다시 꽂으면 새로운 펌웨어로 동작합니다.

동작 시켜보기

이 예제를 실행시키기 위해서는 프로그램을 컴파일 및 다운로드한 후 리셋 버튼을 누르거나 전원을 분리 후 재인가 하여 동작 시킬 수 있습니다. 

 동작 시 보드에 내장된 버튼을 눌러 각 LED의 색상을 변경할 수 있습니다. 1번 버튼을 누를 경우 파랑->초록->빨강 순서대로 색상이 변경되며 2번 버튼을 누를 경우 빨강->초록->파랑 순서대로 색상이 변경됩니다.

위 코드를 수정하여 버튼의 동작을 바꿀 수 있습니다. 예를 들어 1회 클릭이 아닌 두 번 클릭으로 색상이 변경되도록 하던지, 아니면 두 버튼을 동시에 누르면 LED가 꺼지도록 할 수 있습니다.

 다양한 방법으로 이 예제를 활용해 보시기 바랍니다.

CategoriesnRF52 Lecture

Lecture 2. LED 제어하기(GPIO)

Lecture 2. LED 제어하기(GPIO)

강의목표

  • nRF52 개발 보드에 내장된 RGB LED를 켜고 끌 수 있다.
  • 딜레이 함수를 이용하여 시간을 지연시킬 수 있다.
  • nRF52 시리즈의 GPIO 제어 방법을 알 수 있다.
  • 기본적인 nRF52 레지스터 사용법을 알 수 있다.

준비물

  • Roverdyn nRF52 개발 보드 × 1 (구매하기)
  • 전원 공급용 Type-C USB 케이블 × 1
  • Windows 데스크톱 혹은 랩톱 × 1
  • VS Code 개발 환경

GPIO 레지스터로 LED 제어하기

nRF52시리즈는 레지스터를 이용하여 직접 하드웨어를 제어할 수 있습니다. 이를 바탕으로 사용자는 각 하드웨어를 제어하기 위한 드라이버를 제작할 수 있으며 그 중 GPIO는 General Purpose Input/Output의 약자로 기본적인 입출력을 제어할 수 있습니다. GPIO는 입력 및 출력 제어를 각각 할 수 있으며, 입력 제어는 핀으로 들어오는 값이 False/True인지 알 수 있으며 출력은 반대로 False/True 출력이 가능합니다.

GPIO 출력(Output)

 만약 Active Low인 LED가 22번핀에 연결되어 있다면 22번 핀의 출력을 Flase(0)으로 설정하는 것으로 LED를 활성화(=켬) 할 수 있습니다. 만약 GPIO를 High 값으로 설정할 경우 GPIO는 MCU 칩의 Vref 값에 따라 전압이 출력되며, 만약 Vref = 3.3V인 경우 High로 GPIO핀을 설정하면 3.3V 값이 출력됩니다.

GPIO 입력(Input)

GPIO 핀으로 입력을 받는 경우에는 반대로 외부의 전원 혹은 IC로부터 False 혹은 True 값을 입력 받을 수 있습니다. 만약 외부의 신호원으로부터 0.8V 이상의 전압이 입력된다면 GPIO는 High로 인식되며 0.8V 미만의 전압이 입력될 경우 Low로 인식됩니다.

본 튜토리얼은 GPIO의 Output 기능을 이용하여 개발 보드에 내장된 LED를 제어합니다. 이를 위해서 GPIO핀의 입출력 방향 설정, 입출력 값 설정 등을 하여야 하며 그 결과 개별 LED를 제어할 수 있습니다.

로버다인의 nRF52 개발 보드는 빨강(Red), 초록(Green), 파랑(Blue) 색상의 LED가 내장되어 있으며 각각 다음 핀에 연결 되어 있습니다.

  • 빨강 : P0.22
  • 초록 : P0.23
  • 파랑 : p0.24

LED는 Active Low이므로 해당 핀의 출력을 0(Low)로 설정 하여야 LED가 켜지며 반대로 1(High)로 설정할 경우 LED가 꺼지게 됩니다. 

GPIO 설정 및 사용하기

GPIO의 레지스터는 몇 가지 설정을 하여 사용할 수 있습니다. 다음은 기본적인 GPIO의 설정입니다.

  • NRF_GPIO->DIRSET : 핀의 출력 방향을 설정합니다.
  • NRF_GPIO->OUTSET : 핀을 출력으로 설정하였을 때 핀을 High로 설정합니다.
  • NRF_GPIO->OUTCLR : 핀을 출력으로 설정하였을 때 핀을 Low로 설정합니다.

GPIO 레지스터의 값을 입력하기 위해서는 설정하고자 하는 핀의 비트를 0 혹은 1로 설정하여 제어할 수 있습니다. 이를 확인하기 위해 먼저 nRF52 시리즈의 데이터 시트를 확인합니다.

 위 데이터시트는 nRF52832의 데이터시트입니다. GPIO 레지스터 챕터에서 확인할 수 있는 내용으로, NRFGPIO->DIRSET 레지스터에 관한 내용입니다. 해당 데이터시트를 자세히 보면 Bit number가 0인  부분의 아이디는 ‘A’로 표시되어 있으며, 해당 비트를 0으로 설정하면 해당 핀(PIN0)을 Input으로 설정하고 1로 설정하면 Output으로 설정됩니다. 만약 22번핀(P0.22)를 출력으로 설정하고자 한다면 NRF_GPIO->DIRSET = (1 << 22) 으로 설정하면 위 데이터시트상 ID가 ‘W’인 22번 핀의 입출력 방향이 출력으로 설정됩니다. 만약 중복으로 설정하고자 한다면 Or(|) 연산자를 붙여 설정하면 됩니다.

 Zephyr RTOS는 간단한 Sleep 함수가 있습니다. 메인 쓰레드에서 사용할 수 있는 k_msleep 이라는 함수는 매개 변수로  밀리초(ms) 단위로 입력받아 CPU의 동작을 중지 시킬 수 있습니다. 예를 들어 k_msleep(1000)으로 설정하면 1초간 지연 시킨다는 뜻입니다. 또 다른 함수로는 k_usleep이 있으며 k_msleep 함수와 비슷하지만 매개 변수로는 마이크로초 단위(us)를 입력 받습니다.

 보다 자세한 내용은 아래 소스코드를 참조해주세요.

소스 코드

				
					/*
        MIT License

        Copyright (c) 2024. Seonguk Jeong, Roverdyn Inc.

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
*/

#include <zephyr/kernel.h>

/* LED pin no. definition */
#define LED_RED         22
#define LED_GREEN       23
#define LED_BLUE        24

int main(void)
{
        // Debug message for start
        printk("Application start.\n");

        // Set gpio direction for LEDs & turn off
        NRF_GPIO->DIRSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
        NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);

        // Main loop
        while(true){
                // Turn off all LEDs & Turn on Red
                NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
                NRF_GPIO->OUTCLR = (1 << LED_RED);
                printk("Red LED on\n");
                k_msleep(1000);

                // Turn off all LEDs & Turn on Green
                NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
                NRF_GPIO->OUTCLR = (1 << LED_GREEN);
                printk("Green LED on\n");
                k_msleep(1000);

                // Turn off all LEDs & Turn on Blue
                NRF_GPIO->OUTSET = (1 << LED_RED) | (1 << LED_GREEN) | (1 << LED_BLUE);
                NRF_GPIO->OUTCLR = (1 << LED_BLUE);
                printk("Blue LED on\n");
                k_msleep(1000);
        }
        return 0;
}

				
			

빌드 및 컴파일, 다운로드

작성한 소스 코드는 빌드 및 컴파일을 한 후 최종적으로는 디버거 혹은 프로그래머 장비를 이용하여 개발 보드에 다운로드할 수 있습니다. 개발 보드에 관한 설정은 “nRF52  개발환경 구축하기” 튜토리얼을 확인하여 설정할 수 있습니다.

 작성한 코드를 빌드하기 위해서는 우선 다운로드 하고자 하는 보드를 설정해주어야 합니다. 대상 보드를 정의하기 위하여 좌측 패널의 메뉴 중 “Run and Debug” 메뉴를 클릭한 후 “NRF CONNECT:WELCOME” 패널 내부의 “Create a new board” 메뉴를 클릭합니다.

화면 상단에 패널이 나타나면 새로운 보드의 이름을 작성한 후 엔터키를 눌러줍니다. 보드의 이름은 영문으로 작성하여야 합니다.

다음으로 보드의 이름을 한번 더 작성합니다. 다만 이 이름은 기계가 인식할 수 있는 방법으로 작성합니다. 대게 자동으로 작성되어 있으므로 엔터키를 눌러 다음으로 넘어갑니다.

보드가 사용하는 MCU의 종류를 입력합니다. nRF52 개발 보드는 nRF52810-QFAA 혹은 nRF52832-QFAA 두 종류를 사용합니다.

새로 작성한 보드의 정보가 저장될 위치를 설정합니다. 기본적으로 프로젝트 내부의 “board” 폴더가 지정되어 있습니다.

마지막으로 보드의 제조사를 설정합니다. 해당 내용은 작성하지 않아도 동작에 지장이 없습니다.

위와 같이 새 보드의 정의 및 파일 생성이 완료되었다면 빌드 환경을 구성할 수 있습니다. 빌드 환경은 위의 보드 추가 방법과 같이 동일한 “Run & Debug” 패널의 “NRF CONNECT: APPLICATION” 항목에서 설정할 수 있습니다.

 APPLICATION 패널 중 우측에 위치한 “Add Build Configuration” 아이콘을 눌러 설정창을 열어줍니다.

빌드 환경 설정 창이 나타나면 위 그림과 같이 “Custom board” 항목을 눌러준 다음 이전에 생성한 보드를 선택합니다. 위 예제에서는 “nrf52_devboard_52832” 항목을 선택하였습니다. 이는 사용자가 만든 보드 이름에 따라 달라질 수 있습니다. 또한 Configuration 항목을 prj.conf 로 선택합니다. 이후 우측 하단의 “Build configuration” 버튼을 눌러 빌드 환경을 구성합니다.

이상 없이 빌드가 완료되었다면 다시 APPLICATION  패널로 이동하여 “Flash All Linked Devices” 항목을 눌러 컴파일된 펌웨어의 다운로드를 시작합니다. 이 때, 타겟 보드는 컴퓨터와 Jlink 혹은 기타 디버거, 프로그래머와 연결이 되어 있어야 합니다.

위와 같이 빌드를 시작하며 컴파일이 완료된 후 자동으로 컴파일된 펌웨어를 개발 보드로 전송합니다. 전송이 완료되면 개발 보드를 재부팅 하거나 전원을 분리하였다가 다시 꽂으면 새로운 펌웨어로 동작합니다.

동작 시켜보기

이 예제를 실행시키기 위해서는 프로그램을 컴파일 및 다운로드한 후 리셋 버튼을 누르거나 전원을 분리 후 재인가 하여 동작시킬 수 있습니다. 동작 시 LED는 1초 간격으로 내장된 LED가 켜지거나 꺼집니다. 켜지는 순서는 순서대로 빨강(Red) – 초록(Green) – 파랑(Blue)이며 무한히 반복됩니다.

위 소스코드를 수정하여 RGB 색상을 조합하여 다양한 색상을 만들 수 있습니다. 예를 들어 보라색을 표현하고자 한다면 빨간색 LED와 파란색 LED를 켜면 됩니다. 반대로 노란색을 얻고자 한다면 빨간색 LED와 초록색 LED를 켜면 됩니다. 흰색 LED는 모든 LED를 켜서 얻을 수 있습니다.

CategoriesnRF52 Lecture

Lecture 1. nRF52 개발환경 구축하기

Lecture 1. 개발 환경 구축하기

강의목표

  • Microsoft Visual Studio Code 기반의 nRF52 시리즈의 개발환경 구축
  • SEGGER J-Link 기반의 디버깅/프로그래밍 환경 구축
  • nRF Conenct SDK 설치 및 환경 설정
  • VS Code의 기본 환경 설정

준비물

  • Roverdyn nRF52 개발 보드 × 1 (구매하기)
  • 전원 공급용 Type-C USB 케이블 × 1
  • Windows 데스크톱 혹은 랩톱 × 1

nRF52 시리즈 소개

nRF52 시리즈는 Cortex-M4 혹은 Cortex-M4F CPU 코어를 탑재하고 BluetoothLE 5.2를 제공하는 Nordic Semiconductor 사의 시스템 온 칩(SoC) 제품입니다. 하나의 단일 CPU로 블루투스 저에너지(BLE), I2C, SPI, UART 등의 대부분의 임베디드 환경에서 필요한 기능을 제공하고 있습니다. nRF52 시리즈는 64MHz의 클럭을 가지는CPU를 내장하고 있어 다양한 수학적 연산을 수행할 수 있으며 nRF52832 이상 시리즈는 단 정밀도 부동 소수점 연산기(Single precision FPU)를 내장하고 있어 수학 연산 등을 더욱 빠르게 수행할 수 있습니다.

nRF Command Line Tools 설치

nRF52 개발 환경을 구축하기 위해서는 먼저 Nordic Semiconductor 사에서 제공하는 몇 가지의 툴을 설치하여야 합니다. 이 중 nRF Line Command Tools는 다양한 작업을 하기 위한 기본이 되는 툴로서 반드시 설치하여야 합니다. 또한 nRF Connect for Desktop 등의 소프트웨어를 설치하면 좀 더 편한 개발 환경을 구축할 수 있습니다. 권장하는 설치 프로그램은 다음과 같습니다.

  • nRF Command Line Tools(필수)
  • nRF Connect for Desktop(선택)

nRF Command Line Tools는 다음 링크에서 다운로드 할 수 있습니다.

다운로드 링크(클릭)

 

위 링크에 접속한 후 아래로 스크롤하여 설치 파일을 다운로드 할 수 있습니다. 다운로드 페이지의 좌측에서 사용하고 있는 OS에 맞는 설치 파일을 선택할 수 있습니다. 다운로드 한 설치 파일은 [마우스 좌측 클릭] – [관리자 권한으로 실행] 하여 관리자 권한으로 설치를 진행합니다. 설치 시 별도의 설정 변경 없이 설치를 진행하는 것이 좋습니다.

Microsoft Visual Studio Code 설치하기

Microsoft Visual Studio Code(이하 VS Code)는 Microsoft 사에서 제작한 텍스트 에디터로, OpenJS 재단에서 개발한 Electron 프레임 워크를 기반으로 합니다. 텍스트 에디터인 만큼 VSCode 자체적으로 컴파일이나 다운로드할 수 없지만, 다양한 애드온(Add-on)을 활용하여 통합 개발 환경(IDE)처럼 사용할 수 있습니다. 또한 다양한 운영체제에서 사용할 수 있어 유연한 개발 환경을 구축할 수 있습니다. VS Code는 다음과 같은 플랫폼에서 동작합니다.

  • Windows 10(64비트) 이상
  • Linux Ubuntu 20.04 이상
  • Linux Debian 10 이상
  • Red Hat Linux Pedora 36 이상
  • MacOS 10.13 High Sierra 이상

본 강의에서는 Windows 11 기반의 운영체제에서 개발 환경을 구축하였습니다.

먼저 VSCode를 다운로드 합니다. VSCode는 Microsoft사의 홈페이지나 아래 링크를 통하여 다운로드 할 수 있습니다.

 

다운로드 링크(클릭)

 

링크에 접속하여 위 이미지와 같은 화면이 나타나면 VS Code 설치 파일을 다운로드 할 수 있습니다. 위 화면에서 붉은색 사각형 원 내부에 있는 다운로드 버튼을 눌러서 다운로드할 수 있으며 만약 다른 운영체제를 사용중이라면 버튼 우측의 아래쪽 방향 화살 모양 아이콘을 눌러 사용하는 운영체제에 맞는 설치 파일을 내려받을 수 있습니다.

설치 파일이 다운로드 완료된 후 설치 파일을 [마우스 오른쪽 버튼] – [펼침 메뉴에서 관리자 권한으로 실행]을 눌러 관리자 권한으로 설치를 진행합니다. 설치 시 설정을 별도로 바꾸지 않고 기본 설정대로 설치를 진행합니다. 만약 필요한 경우 설치 경로 등을 별도로 설정할 수 있습니다.

VS Code의 설치가 완료되었다면 플러그인 설치 및 개발 환경 설정을 위해 프로그램을 실행합니다.  먼저 좌측 메뉴 중 [Extensions] 메뉴를 클릭합니다.

위 이미지에서 다음 확장 기능을 검색하여 설치합니다.

  • C/C++
  • C/C++ Extension Pack
  • CMake Tools
  • nRF Connect for VS Code Extension

모든 프로그램을 설치한 후 VSCode를 재실행합니다.

SEGGER J-Link 설치

SEGGER J-Link 독일의 SEGGER Microcontroller GmBH사에서 만든 디버깅 및 프로그래밍 하드웨어 및 소프트웨어 툴입니다. J-Link는 Cortex-M 시리즈 외에도 Cortex-A 시리즈, Cortex-R 시리즈 CPU 코어를 지원합니다. J-Link는 nRF 시리즈의 SWD 핀과 연결하여 사용하며, 컴파일된 바이너리 파일을 MCU로 다운로드하여 프로그래밍 하거나 동작을 모니터링하는 디버깅 기능 등을 제공합니다. J-Link 장비는 별도로 구매하여서 사용하여야 하며 만약 J-Link의 가격이 부담될 경우 OpenOCD를 활용하여 가격이 보다 저렴한 ST-Link V2 등과 같은 다양한 Debugger/Programmer를 사용할 수 있습니다. J-Link를 사용하기 위해서는 드라이버 및 소프트웨어 패키지를 설치하여야 합니다. 아래 링크를 클릭하여 다운로드 할 수 있습니다.

 

다운로드 링크(클릭)

 

다운로드 링크를 클릭하여 접속하면 다운로드 페이지가 나타나며 ” J-Link Software and Documentation Pack” 항목에서 설치파일을 다운로드 할 수 있습니다. 위 이미지를 참조하여 사용하는 OS에 맞는 설치 파일을 다운로드합니다. 다운로드 한 소프트웨어는 [관리자 권한으로 실행] 하여 설치를 진행 하는 것을 권장합니다. 설치 시 별도의 설정 변경 없이 설치를 진행 하는 것을 권장합니다.

Toolchain 및 SDK 설치

이제 개발을 위한 마지막 단계입니다. VS Code의 Extension에서 nRF Connect for VS Code Extension 을 설치하였다면 좌측 메뉴에서 “nRF Connect” 아이콘을 확인할 수 있습니다. 해당 아이콘을 클릭하여 Toolchain 및 nRF SDK를 설치할 수 있습니다.

먼저 Toolchain을 설치하도록 하겠습니다. 위 이미지를 참조하여 툴 체인 설치 버튼을 찾을 수 있습니다. [Install Toolchain] 버튼을 눌러 툴 체인 설치를 시작합니다.

툴 체인 버전을 선택합니다. beta 버전을 제외한 최신 버전을 설치하는 것을 권장합니다.

툴 체인을 선택하면 자동으로 다운로드 및 설치를 진행합니다. 설치가 완료되면 좌측 메뉴가 변경되며 이제 SDK를 설치할 수 있게 됩니다.

SDK를 설치하기 위해서 좌측 “NRF CONNECT” 패널에서 [Manage SDKs]를 클릭하여 설치 창을 열어주세요. 설치 창이 열리면 [Install SDK]를 눌러 SDK 설치를 진행합니다.

SDK 버전을 선택합니다. SDK 버전은 Toolchain 버전에 맞추어 설치 하는 것을 권장합니다. beta 혹은 dev 버전을 제외하고 선택합니다. 최신 버전에 따라 설치 방법이 다소 달라질 수 있습니다.

SDK 버전을 선택하고 나면 SDK가 설치 될 폴더의 경로를 설정합니다. 직접 경로를 입력 할 수 있고 또한 우측 상단의 폴더 모양 아이콘을 클릭하면 폴더를 대화상자로 선택할 수 있습니다.

다운로드 및 설치는 자동으로 진행됩니다. 설치가 완료되면 우측 하단에 설치가 완료되었음을 알리는 알림창이 나타나며 여기서 [Use this SDK] 버튼을 클릭하여 SDK를 활성화 합니다. SDK 설치가 완료되면 좌측의 “NRF CONNECT” 패널에 설치한 SDK의 버전이 나타납니다. 모든 SDK가 설치 완료되면 VS Code를 재부팅합니다.

첫 프로젝트 생성 및 컴파일

위 세 가지 소프트웨어와 Toolchain 및 SDK를 모두 설치하였다면 nRF52 시리즈 개발을 위한 기본 환경이 구축되었다고 할 수 있습니다. 이제 VS Code와 J-Link를 활용하여 나만의 펌웨어를 개발 할 수 있습니다. nRF52 시리즈는 C/C++ 언어를 사용하여 펌웨어를 개발할 수 있습니다. 이제 새로운 개발 프로젝트를 만들어 보겠습니다. 모든 개발의 시작은 프로젝트를 새로이 만드는 것부터 시작됩니다.

 VS Code에서 새 개발 프로젝트를 만들기 위해서 먼저 좌측의 메뉴 아이콘 중 [Run and Debug] 메뉴를 클릭한 후 [NRF CONNECT: WELCOM] 패널 – [Create a new application] 메뉴를 눌러줍니다. 만약 [Run and Debug] 메뉴가 없다면 [nRF CONNECT] 아이콘을 클릭하면 새 프로젝트를 생성할 수 있는 패널이 나타납니다.

[Create a blank application] 메뉴가 나타납니다. 해당 메뉴에서 “Create a blank application”을 선택합니다. 만약 샘플 코드를 로드하려면 “Copy a sample” 메뉴를 선택합니다.

새 프로젝트를 저장할 폴더의 위치를 선택할 수 있습니다. 경로를 직접 작성하여 선택할 수 있으며 또한 우측 상단의 폴더 모양 아이콘을 클릭하면 대화 상자를 이용하여 저장할 경로를 설정할 수 있습니다. 이 때 선택 되는 폴더는 프로젝트 폴더가 선택되는 위치입니다.(선택한 폴더 밑에 프로젝트 폴더가 새로이 생성됩니다)

새로운 프로젝트가 생성 완료되면 위와 같이 새 프로젝트가 생성되었음을 알리는 창이 나타납니다. 이 때 [Open] 버튼을 누르면 열린 VS Code 창에서 새 프로젝트가 실행되며 [Open in New Window] 버튼을 누르면 새로운 VS Code가 실행되며 프로젝트가 로드 됩니다.

프로젝트가 성공적으로 생성되면 왼쪽의 [Explorer] 패널에 프로젝트 파일이 자동으로 생성됨을 확인할 수 있습니다. 기본적으로 src 폴더 내부에 main.c 파일이 생성되며, CmakeList, prj.conf 등의 파일이 생성됩니다. 해당 파일의 역할은 다음 예제 프로젝트에서 확인할 수 있습니다. 이제 펌웨어를 개발하기 위한 모든 준비가 완료되었습니다.