<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>js_ryu.log</title>
        <link>https://velog.io/</link>
        <description>자동차와 여행을 좋아하는 개발자 지망생.</description>
        <lastBuildDate>Thu, 24 Feb 2022 11:42:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>js_ryu.log</title>
            <url>https://images.velog.io/images/js_ryu/profile/128745e9-0360-4f51-9f7c-ea614a1d0bcc/KakaoTalk_20210523_211955613.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. js_ryu.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/js_ryu" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[nRF52840 스터디] blinky SDK를 이용하여 GPIO 제어해보기]]></title>
            <link>https://velog.io/@js_ryu/nRF52840-%EC%8A%A4%ED%84%B0%EB%94%94-blinky-SDK%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-GPIO-%EC%A0%9C%EC%96%B4%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@js_ryu/nRF52840-%EC%8A%A4%ED%84%B0%EB%94%94-blinky-SDK%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-GPIO-%EC%A0%9C%EC%96%B4%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 24 Feb 2022 11:42:04 GMT</pubDate>
            <description><![CDATA[<h3 id="서론">서론</h3>
<p>개발 블로그를 만들겠다고 마음을 먹고, velog를 개설한 뒤에 첫글이 임베디드가 될 줄은 몰랐다.
왜냐면 나는 임베디드의 E자도 모르는 사람이기 때문이다... 어쩌다보니 개발이 필요한 상황이 되어서, 얼렁뚱땅 개발에 투입이 되었고 부족한 지식을 채우기 위해 스터디한 내용을 기록해보고자 한다.  </p>
<p>다행히 복잡한 기능들을 구현해야되는 것은 아니여서 기초적인 예제들을 수정하면 되는 수준인 것 같긴한데, 워낙 임베디드 쪽 지식이 전무하다보니 좀 어렵긴하다.</p>
<p>내가 스터디를 진행하는 환경은 아래와 같다.</p>
<ul>
<li>Arduino Nano 33 Ble(nRF52840)</li>
<li>J-Link debugger</li>
<li>Segger Embedded Studio</li>
</ul>
<p>Segger에서 제공하는 nRF5의 SDK를 활용하였고, 가장 먼저 제일 쉬워보이는 &#39;blinky&#39; 예제를 한 줄씩 살펴보면서 GPIO 제어를 위한 기초를 다져(?)보고자 한다.</p>
<p>기본적으로는 보드에 붙어있는 LED를 제어하는 코드이지만, 살짝만 수정하여 GPIO pin을 제어할 수 있을 것이라는 생각이 들었다.</p>
<h3 id="본론">본론</h3>
<pre><code>#include &lt;stdbool.h&gt;
#include &lt;stdint.h&gt;
#include &quot;nrf_delay.h&quot;
#include &quot;boards.h&quot;

int main(void)
{
    /* Configure board. */
    bsp_board_init(BSP_INIT_LEDS);

    /* Toggle LEDs. */
    while (true)
    {
        for (int i = 0; i &lt; LEDS_NUMBER; i++)
        {
            bsp_board_led_invert(i);
            nrf_delay_ms(500);
        }
    }
}</code></pre><p>위 코드가 blinky 예제의 <code>main.c</code>이다.
다행히(?) 그리 길지는 않다.</p>
<p><code>bsp_board_init(BSP_INIT_LEDS);</code>부터 살펴보자.</p>
<p><code>bsp_board_init</code>을 선언한 <code>boards.c</code>를 보면, 넣어주는 argument를 기반으로 LED를 초기화할 것인지, button을 초기화 할 것인지 정한다.</p>
<pre><code>void bsp_board_init(uint32_t init_flags)
{
    #if defined(BOARDS_WITH_USB_DFU_TRIGGER) &amp;&amp; defined(BOARD_PCA10059)
    (void) nrf_dfu_trigger_usb_init();
    #endif

    #if LEDS_NUMBER &gt; 0
    if (init_flags &amp; BSP_INIT_LEDS)
    {
        bsp_board_leds_init();
    }
    #endif //LEDS_NUMBER &gt; 0

    #if BUTTONS_NUMBER &gt; 0
    if (init_flags &amp; BSP_INIT_BUTTONS)
    {
        bsp_board_buttons_init();
    }
    #endif //BUTTONS_NUMBER &gt; 0
}</code></pre><p>지금 보고 있는 코드에서는 <code>BSP_INIT_LEDS</code>를 전달하였으므로, <code>bsp_board_leds_init()</code>로 LED를 초기화 한다.</p>
<p>사전에 LED의 개수와 핀 번호를 매핑해두었는데, 각 LED를 <code>nrf_gpio_cfg_output()</code>을 이용하여 초기화 한다. 이는 설정한 pin을 output으로 설정해주는 함수이다. LED의 핀 번호가 13이면 <code>nrf_gpio_cfg_output(13)</code>으로 설정할 수 있다. </p>
<p>그 이후에는 <code>bsp_board_leds_off()</code>을 부르는데, 이는 결국 <code>nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 0 : 1)</code>을 실행하는 것이다.</p>
<p><code>m_board_led_list[led_idx]</code>는 단순히 LED의 핀번호(e.g. 13)인데, 뒤에 조건이 무엇인지 알아보자.</p>
<p>공식 문서는 아래 사진과 같다.
<img src="https://images.velog.io/images/js_ryu/post/cceafa3c-c9c9-4972-aece-bf5de8a67142/%EC%9D%B4%EB%AF%B8%EC%A7%80%20001.png" alt="image_1"></p>
<p><code>value</code>에 0이 들어가면 pin을 clear하는 것이고, 1 이상의 값이 들어가면 pin을 set한다는 건데...임베디드 알못인 나는 무슨 뜻인지를 모른다....</p>
<p>다만, 직접 해보니까 set일 경우는 gpio핀에 전압이 나오고, clear일 경우엔 나오지 않는다. 정확한 내용은 모르지만 일단 set일때 led를 켜고, clear일 때 led를 끌 수 있다는 사실을 알게되었다.</p>
<p><code>LEDS_ACTIVE_STATE ? 0 : 1</code>는 삼항 연산자니까, <code>LED_ACTIVE_STATE</code>가 True면 0, False면 1을 return하게 된다. 그러니까 <code>LED_ACTIVE_STATE</code>가 0일 때면 1을 반환하고, 1일때면 0을 반환해주는 것이다.
다시 한 번 말해서(..) LED가 켜져있으면 꺼주고, 꺼져있으면 켜주는 역할을 하는 듯 하다.</p>
<p>이제 while문 안으로 들어가보자.
for문은 단순히 사전에 설정해준 LED 개수에 맞추어 같은 작업을 해주기 위해 돌아가는 것이다.</p>
<p><code>bsp_board_led_invert(i);</code>는 <code>nrf_gpio_pin_toggle()</code>을 부르는 함수이고, argument로는 pin number가 들어간다. <code>nrf_gpio_pin_toggle()</code>은 아래와 같다.</p>
<pre><code>__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number)
{
    NRF_GPIO_Type * reg        = nrf_gpio_pin_port_decode(&amp;pin_number);
    uint32_t        pins_state = reg-&gt;OUT;

    reg-&gt;OUTSET = (~pins_state &amp; (1UL &lt;&lt; pin_number));
    reg-&gt;OUTCLR = (pins_state &amp; (1UL &lt;&lt; pin_number));
}</code></pre><p>토글 기능도 단순히, LED가 켜져있으면 clear해서 꺼주고, 꺼져있으면 set해서 켜주는 것이다.</p>
<p>토글 기능 말고, 내 맘대로 켜고 끄는 명령을 주려면 어떻게 해야할까 보다가 토글을 설명하고 있는 공식문서 근처에 <code>nrf_gpio_pin_set</code>을 설명하고 있는 함수가 있었고 찾아보니 <code>nrf_gpio_pin_clear</code>도 있었다.</p>
<p>이미 예상했겠지만, argument로 pin 번호만 넣어주면 아주 잘 작동한다. (e.g. <code>nrf_gpio_pin_set(21);</code>)</p>
<p><img src="https://images.velog.io/images/js_ryu/post/f6a39c75-333f-45f1-a01c-93bddd6d48fd/20220224_202630.jpg" alt="image_2"></p>
<p>(의미 없는 작동 사진 / 빨간 LED만 켰음)</p>
<h3 id="ps">P.S.</h3>
<p>위에서도 말했듯이, 나는 Arduino Nano 33 Ble를 사용했는데 놀랍게도 nRF5 SDK에 define되어 있는 <code>ARDUINO_13_PIN</code> 등은 실제 아두이노 핀 번호랑 무슨 상관이 있는지 모르겠다.(물론 아두이노가 모델이 많으니까 그렇겠지만...) 코드가 잘못된 줄 알고, 이것 때문에 한참 고생했었는데 그냥 <a href="https://content.arduino.cc/assets/NANO33BLE_V4.0_sch.pdf">schematics</a>를 다운 받아서 보면 해결되는 문제였다.</p>
<p><img src="https://images.velog.io/images/js_ryu/post/4b1d38d4-3adb-4c31-8372-547243f4f511/%EC%9D%B4%EB%AF%B8%EC%A7%80%20ddd.png" alt="image_3"></p>
<p>P뒤에 x.y의 형태로 숫자가 표시되어 있는데, x가 0인 경우는 y만 argument로 넣어주면 된다. (e.g. D7핀에 꽂았으면 코드에서는 23)</p>
<p><a href="https://devzone.nordicsemi.com/f/nordic-q-a/39609/52840-pin-number">한 Q&amp;A 페이지</a>를 보니 규칙은 아래와 같다고 한다.</p>
<blockquote>
</blockquote>
<p>P0.0 = 0, P0.1 = 1 .... P0.31 = 31 P1.0 = 32, P1.1 = 33. </p>
<p><code>pca10056.h</code>파일을 봤을 때는 <code>NRF_GPIO_PIN_MAP(1, 11)</code> 이런식으로 작성하여 어떻게 활용할 수도 있을 것 같은데, 귀찮아서 아직 못 알아봤다..</p>
<p>이렇게 첫 번째 스터디는 끝!</p>
]]></description>
        </item>
    </channel>
</rss>