nRF52832 개발일지 (번외)

치삼이·2021년 7월 15일
0
post-thumbnail

💡 nRF52832 개발일지 (번외) : 나의 UART는 UART_ISR로 점프할까?

nRF52832 SoC 에는 하나의 UART와 UARTE 모듈이 존재합니다. 이는 서로 비슷한 기능하며 공유하는 자원이 같지만(register 등) 완전히 같은 모듈은 아닙니다. 이번 번외편에서는 초반에 UART Interrupt Service Routine(혹은 Interrupt Handler)을 관찰하면서 겪었던 이야기를 하겠습니다.

1. 기: Compile Error ❌

우선 기본 예제부터 다시 살펴보겠습니다. 👨‍💻 개발일지 (1) 의 마지막 단락 예제를 참고 하겠습니다.

예제를 SoC 에 다운로드하기 전 브레이크 포인트를 설정한 뒤, UART_ISR 인지 혹은 UARTE_ISR 인지를 판단하겠습니다. 각각 nrfx_uart.cnrfx_uarte.c 의 최하단 Interrupt Service Routine에 브레이크 포인트를 걸겠습니다.

001

브레이크 포인트를 걸고 실행해 보시면 알게되겠지만 이 UARTE의 Interrupt Service Routine에 접근합니다. 🤔 우리가 원하는건 UARTE가 아닌 UART의 ISR이므로 sdk_config.h를 편집해 UARTE를 프로젝트에서 제외시키겠습니다.

002

CMSIS Configuration Wizard를 열어 NRFX_UARTE_ENABLEDNRFX_PRS_ENABLE 의 체크박스를 해제하겠습니다. (PRS 모듈은 추후 다뤄보도록 하겠습니다.)

003

004

NRFX_UARTE_ENABLED 의 체크박스를 해제해도 계속 UARTE의 Interrupt Service Routine으로 접근하네요.. 🤔 이번에는 아예 프로젝트에서 제외시키도록 하겠습니다. Project Explorer nrfx_uarte.c 를 제거하겠습니다.

005

006

어쩌란건지.. 모르겠네...🤬

2. 승: Error Debuging 🐛

에러를 잡기위해 어떤 에러가 났는지 로그를 확인하겠습니다.

007

nrf_drv_uart.h 에서 Error가 발생했고 내용은 nrfx_uarte_rx(), nrfx_uarte_tx(), nrfx_uarte_init() 함수가 없다고 합니다. 사실 nrf_drv_uart.h 상단에 보면 위같은 내용을 해결하기 위해 정의된 매크로가 있습니다.

#ifndef NRF_DRV_UART_H__
#define NRF_DRV_UART_H__

#include <nrfx.h>

#if defined(UARTE_PRESENT) && NRFX_CHECK(NRFX_UARTE_ENABLED)
    #define NRF_DRV_UART_WITH_UARTE
#endif
#if defined(UART_PRESENT) && NRFX_CHECK(NRFX_UART_ENABLED)
    #define NRF_DRV_UART_WITH_UART
#endif

#if defined(NRF_DRV_UART_WITH_UARTE)
    #include <nrfx_uarte.h>
    #define NRF_DRV_UART_CREATE_UARTE(id) \
        .uarte = NRFX_UARTE_INSTANCE(id),
#else
    // Compilers (at least the smart ones) will remove the UARTE related code
    // (blocks starting with "if (NRF_DRV_UART_USE_UARTE)") when it is not used,
    // but to perform the compilation they need the following definitions.
    #define nrfx_uarte_init(...)                0
    #define nrfx_uarte_uninit(...)
    #define nrfx_uarte_task_address_get(...)    0
    #define nrfx_uarte_event_address_get(...)   0

...

#endif

#ifdef __cplusplus

#else 밑의 내용이 UARTE를 사용하지 않을때를 대비하기 위한 매크로 입니다. 혹시 UARTE를 사용하지 않으면 UARTE에 관련된 모든 함수들을 매크로 처리를 통해 아무 일도 하지 않게 만들어 버립니다. 아래는 이러한 UARTE를 사용 여부를 판단하기 위한 매크로 및 조건입니다.

#if defined(UARTE_PRESENT) && NRFX_CHECK(NRFX_UARTE_ENABLED)
    #define NRF_DRV_UART_WITH_UARTE
#endif
#if defined(UART_PRESENT) && NRFX_CHECK(NRFX_UART_ENABLED)
    #define NRF_DRV_UART_WITH_UART
#endif

"만약 UARTE 모듈을 지원(존재)하고 동시에 UARTE를 실행시킨다면 NRF_DRV_UART_WITH_UARTE 를 정의하겠다." 라는 의미이며 NRFX_UARTE_ENABLEDsdk_config.h 파일에서 수정할 수 있습니다. 근데... 아까 분명히... NRFX_UARTE_ENABLED 를 수정 했던거 같은디... 🤔

3. 전: 매크로 찾기 🔍

sdk_config.h 에서 NRFX_UARTE_ENABLED 은 분명 0으로 셋팅이 되어 있습니다.

008

오늘 우리는 저 NRFX_UARTE_ENABLED 를 계속 1로 바꿔주는 파일을 찾아야 합니다. 🔍

#if NRFX_UARTE_ENABLED
#define  where?
#endif

바로 위에 구문을 각각의 헤더파일 사이사이에 끼워 넣어 NRFX_UARTE_ENABLED 이 1로 바뀌는 곳을 색깔의 변화로 찾아 나가겠습니다. (별로 좋은 방법이 아닌건 알지만...)

009

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @defgroup nrfx_glue nrfx_glue.h
 * @{
 * @ingroup nrfx
 *
 * @brief This file contains macros that should be implemented according to
 *        the needs of the host environment into which @em nrfx is integrated.
 */

#include <legacy/apply_old_config.h>

#include <soc/nrfx_irqs.h>

//------------------------------------------------------------------------------

#include <nrf_assert.h>

010

nrfx_glue.h 에서 #include <legacy/apply_old_config.h> 으로 밝혀졌습니다. 저 include를 주석처리해주면 NRFX_UARTE_ENABLED 이 0으로 제대로 바뀌는 것을 확인할 수 있습니다.

4. 결: UART는 UART로...

이제 UART의 Interrupt Service Routine으로 제대로 점프 하는걸 확인했습니다. 🙌🙌🙌

011

위에 글이 너무 긴 관계로 요약을 하자면 다음과 같습니다.

UART Interrupt Service Routine을 명확하게 이용하려면 nrfx_glue.h#include <soc/nrfx_irqs.h> 주석처리를 하고 NRFX_UARTE_ENABLEsdk_config.h 에서 0으로 설정한다. 😊

사실 Nordic사에서 만든 SDK를 편집하면서 많은 생각을 하게 되었습니다. 유명 기업에서 만든 SDK이고, 또 이렇게 만들어 놓은 이유가 있지는 않을까..? 라는 생각이 자꾸 들었지만... 이렇게 만들게 된 이유가 있다면 이 SoC 및 SDK를 다루다보면 알 수 있을것 같아 깊은 고민은 하지 않기로 했습니다. 🤣

0개의 댓글