반응형

오랜만에 안드로이드 스튜디오 프로젝트를 열고 Gradle Sync 도중 위와 같은 오류가 발생하였다.

무언가 해당 Gradle 버전에 종속적인 문제가 발생한 것으로 예측된다.

 

이 때 간단히 해결할 수 있는 방법으로는 정상적으로 빌드될 수 있는 안정된 Gradle 버전을 찾는 것이다.

 

우선 내가 사용하고 있는 버전을 확인해보자.

안드로이드 스튜디오에서 File -> Project Structure -> Project 탭을 보면 아래와 같은 창을 확인할 수 있다.

내가 사용하는 플러그인 버전은 3.2.1이고, Gradle 버전은 5.1.1이다.

이 버전을 변경하기 위해서는 플러그인 버전에 따라 필요한 Gradle 버전이 무엇인지를 알아야 한다.

플러그인과 Gradle 버전 관계표

나는 기존 플러그인 버전이 3.4.1이었기 때문에 Gradle 버전을 5.1.1 버전을 사용했었다.

여기서 플러그인 버전을 3.2.1로 설정하고, Gradle 버전을 4.6으로 변경하여 사용할 것이다.

 

프로젝트 최상단 폴더의 build.gradle 을 열면 플러그인 버전을 변경할 수 있다.

위와 같이 기존 플러그인 버전 대신 3.2.1로 변경하고, 그 다음에는 Gradle 버전을 변경해주어야 한다.

프로젝트 폴더\gradle\wrapper\gradle-wrapper.properties 파일을 열면 버전을 수정할 수 있다.

위와 같이 기존 버전 대신 4.6 버전을 넣어주었다.

 

이제 위의 Try Again 버튼을 클릭하여 문제가 해결되었는지 확인하면 된다.

정상적으로 빌드까지 마친 것을 확인하였다.

혹시나 위의 버전으로도 오류가 난다면 위 '플러그인과 Gradle 버전 관계표'를 보고 적절한 버전을 찾아가야 할 수도 있다.

반응형
반응형

 

리액트를 빌드하던 중 위와 같이 멈추고 더 이상 진행되지 않는 경우가 있다.

메모리가 부족하게 되면 위 현상이 나타나게 된다.

특히 AWS 프리티어를 쓰는 경우 t2.micro 사양을 사용하게 되는데 램이 1기가밖에 되지 않는다.

조금만 빌드 규모가 커져도 위와 같은 증상을 발견하게 된다.

 

해결 방법은 여러가지가 있다. 

 

1. 빌드시 GENERATE_SOURCEMAP 옵션을 꺼준다.

위와 같이 package.json 파일을 열면 build 부분에 GENERATE_SOURCEMAP를 false로 설정해준다.

어짜피 프로덕션시에는 결국 이 옵션은 꺼주는게 맞기는 하다.

노출되지 않아야 하는 코드들을 보호해주는 역할도 해주기 때문이다.

그리고 해당 속성이 켜져있을 경우 디버깅 정보가 포함되어 빌드되기 때문에 빌드 용량이 커지게 되며,

이는 곧 메모리 부족으로 이어지므로 꺼주게 되면 어느정도 메모리 부족 현상도 해결해주게 된다.

 

2. 메모리 스왑을 통한 메모리 부족 현상 처리

위의 GENERATE_SOURCEMAP 옵션을 끄더라도 결국 빌드 규모가 커질 경우 메모리를 많이 차지할 수 밖에 없다.

즉, 1번 방법으로도 해결되지 않을 경우 이 메모리 스왑 방법을 써볼 수 있다.

메모리 스왑은 간단히 설명하면 메모리의 부족한 부분을 디스크의 일부를 사용하여 대신 사용할 수 있는 기능이다.

메모리에 비해 디스크가 속도가 훨씬 느리기 때문에 스왑 사용시 속도가 느려진다는 단점은 있다.

AWS에서 프리티어는 써야하고 메모리 부족 현상은 해결해야 할 때 써볼만 할 것이다.

 

위 스크린샷은 SSH를 통해 AWS의 메모리 현황을 표시해본 것이다.

보면 기본적으로 AWS 인스턴스는 스왑 메모리가 지정되어있지 않아서 0으로 표시된다.

 

(1) sudo dd if=/dev/zero of=/mnt/swapfile bs=1M count=2048

(2) sudo mkswap /mnt/swapfile

(3) sudo swapon /mnt/swapfile

위 세 명령어를 입력하여 스왑 메모리를 생성해준다.

 

 

위와 같이 메모리를 확인해보면 스왑 메모리가 2기가가 잡혀있는 것을 확인할 수 있다.

그리고 다시 빌드하면 메모리 부족 현상으로 인한 빌드 멈춤 문제는 해결될 것이다.

 

하지만 이처럼 가상 메모리를 쓰게 되면 퍼포먼스의 문제가 발생하므로 임시 방편으로 쓰고 사양을 올릴 것을 추천한다.

 

※ 스왑메모리 해제 방법

sudo swapoff -v /mnt/swapfile
sudo rm /mnt/swapfile

위 두 명령어로 스왑메모리를 해제할 수 있다.

 

이상 리액트 빌드시 멈춤 현상을 해결하는 방법에 대해 설명하였다.

이 외에도 다른 방법들도 있기는 하다. 빌드 규모를 줄이기 위한 코드 스플리팅이나,

위 메모리 스왑 이전에 캐시 메모리가 많이 존재한다면 캐시 메모리를 초기화해주는 방법 등이 있다.

필자 또한 임시적으로 문제를 해결해야 했기 때문에 위에 언급한 2가지 문제로 충분히 해결이 가능했다.

반응형
반응형

 

SVG 이미지는 픽셀 단위로 이루어진 비트맵 방식의 PNG와 다르게 벡터 이미지 방식을 사용하고 있다.

장점은 크기를 자유롭게 조정하여도 이미지 깨짐이 발생하지 않는다는 것이다.

 

휴대폰은 기종별로 다양한 해상도를 갖고 있으며, 개발자들은 이에 대응할 수 있어야 한다.

PNG 파일 하나를 이용해서 해상도별로 크기를 조정해가면서 사용할 경우 이미지 깨짐이 발생할 수 있고,

그렇다고 PNG 파일을 해상도별로 나누어 사용하기에는 소모 비용이 너무 크다.

 

이 때 사용할 수 있는 것이 바로 SVG 이미지이다.

플러터에서는 SVG를 쉽게 사용할 수 있도록 제공하는 플러그인이 존재한다.

 

flutter_svg 라는 플러그인인데, 아래의 순서대로 따라해보도록 하자.

 

위와 같이 pubspec.yaml 파일을 열고 flutter_svg: 0.17.4 를 추가해준다.

 

실제로 사용할 이미지를 추가해준다.

경로는 원하는 곳에 넣어도 상관없다.

 

위에서 추가한 파일을 pubspec.yaml에도 적어준다.

flutter pub get 명령으로 해당 내용을 반영해준다.

 

이제 flutter_svg 플러그인을 사용하기 위해 위와 같이 import 해준다.

 

위와 같이 SvgPicture 객체를 사용하여 SVG 이미지를 뿌려줄 수 있다.

width, height 속성을 이용하여 크기를 자유롭게 변경할 수 있으며,

SVG 벡터 이미지이므로 이미지 깨짐이 없다.

 

아주 깔끔하게 출력되었다.

 

참고로 SvgPicture.network() 함수를 통해 외부 네트워크에 있는 이미지를 표시할 수도 있다.

 

앱 내에서 아이콘이 차지하는 비중이 상당히 높기 때문에 SVG 파일을 이용하면,

이미지 용량도 절약할 수 있고 사이즈에 구애 받지 않기 때문에 더 효율적인 작업이 가능하다.

 

단, 아이콘이 아닌 복잡한 형태의 이미지는 PNG를 사용하는 것이 낫다.

단순하지 않은 이미지는 오히려 PNG 이미지보다 용량이 더 커질 수 있고, 속도에도 영향을 미칠 수 있기 때문이다.

반응형
반응형

 

firebase_admob: ^0.9.0+9

image_picker : ^0.6.2+1

 

위 두개의 패키지를 사용하고, 빌드하는데 다음과 같은 오류가 발생하였다.

 

WARNING: Conflict with dependency 'androidx.core:core' in project ':app'. Resolved versions for runtime
classpath (1.0.2) and compile classpath (1.0.0) differ. This can lead to runtime crashes. To resolve this issue follow
advice at https://developer.android.com/studio/build/gradle-tips#configure-project-wide-properties. Alternatively, you
can try to fix the problem by adding this snippet to
C:\temp\android\app\build.gradle:
[ +4 ms] dependencies {
[ +3 ms] implementation("androidx.core:core:1.0.2")
[ +1 ms] }
[ +2 ms] WARNING: Conflict with dependency 'androidx.annotation:annotation' in project ':app'. Resolved versions for
runtime classpath (1.0.2) and compile classpath (1.0.0) differ. This can lead to runtime crashes. To resolve this issue
follow advice at https://developer.android.com/studio/build/gradle-tips#configure-project-wide-properties.
Alternatively, you can try to fix the problem by adding this snippet to
C:\temp\android\app\build.gradle:
[ +1 ms] dependencies {
[ +2 ms] implementation("androidx.annotation:annotation:1.0.2")


[ +5 ms] *******************************************************************************************
[ +3 ms] The Gradle failure may have been because of AndroidX incompatibilities in this Flutter app.
[ +2 ms] See https://goo.gl/CP92wY for more information on the problem and how to fix it.
[ +1 ms] *******************************************************************************************
[ +5 ms] "flutter appbundle" took 40,539ms.
Gradle task bundleRelease failed with exit code 1

#0 throwToolExit (package:flutter_tools/src/base/common.dart:28:3)
#1 _buildGradleProjectV2 (package:flutter_tools/src/android/gradle.dart:751:5)
#2 _asyncThenWrapperHelper. (dart:async-patch/async_patch.dart:71:64)
#3 _rootRunUnary (dart:async/zone.dart:1132:38)
#4 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#5 _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
#6 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
#7 Future._propagateToListeners (dart:async/future_impl.dart:707:32)
#8 Future._completeWithValue (dart:async/future_impl.dart:522:5)
#9 _AsyncAwaitCompleter.complete (dart:async-patch/async_patch.dart:30:15)
#10 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:288:13)
#11 runCommandAndStreamOutput (package:flutter_tools/src/base/process.dart)
#12 _asyncThenWrapperHelper. (dart:async-patch/async_patch.dart:71:64)
#13 _rootRunUnary (dart:async/zone.dart:1132:38)
#14 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#15 _FutureListener.handleValue (dart:async/future_impl.dart:137:18)
#16 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45)
#17 Future._propagateToListeners (dart:async/future_impl.dart:707:32)
#18 Future._completeWithValue (dart:async/future_impl.dart:522:5)
#19 Future._asyncComplete. (dart:async/future_impl.dart:552:7)
#20 _rootRun (dart:async/zone.dart:1124:13)
#21 _CustomZone.run (dart:async/zone.dart:1021:19)
#22 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
#23 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23)
#24 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#25 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#26 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13)
#27 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5)

 

위 문제를 해결하기 위해서 프로젝트 폴더의 android/build.gradle 파일을 열고 

아래 추가 부분에 해당하는 코드를 추가해주고 다시 빌드해본다.

 

buildscript {
  ext.kotlin_version = '1.3.0'
  repositories {
    google()
    jcenter()
  }

  dependencies {
    classpath 'com.android.tools.build:gradle:3.3.2'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  }

  //--------------추가 부분-----------
  subprojects {
    project.configurations.all {
      resolutionStrategy.eachDependency { details ->
        if (details.requested.group == 'com.android.support'
            && !details.requested.name.contains('multidex') ) {
          details.useVersion "27.1.1"
        }

        if (details.requested.group == 'androidx.core'
            && !details.requested.name.contains('androidx') ) {
          details.useVersion "1.0.1"
        }
      }
    }
  }
  //----------------여기까지------------
}

반응형
반응형

위와 같은 오류 발생시 대처 방법

 

[1] 아래와 같이 android/app/build.gradle 에 아래 코드를 추가한다.

packagingOptions {
    exclude 'META-INF/proguard/androidx-annotations.pro'
}

위와 같이 buildTypes{} 아래에 새로 추가해준다.

 

[2] android/build.gradle 에서 gradle 버전을 3.3.0 으로(혹은 그 이후 버전) 변경해준다.

classpath 'com.android.tools.build:gradle:3.3.0'

위 코드처럼 수정해주면 되며, 기존에 버전이 3.2.1 이하 버전이었다면, gradle 버전 문제일 확률이 높다.

즉, [1]번 해결책보다 [2]번 해결책이 더욱 적합하다.

 

 

반응형
반응형

이 포스트에서는 Node.js 설치와 Node.js를 이용하여 간단히 동작 테스트를 해본다.

 

Node.js 를 간략하게 설명하면 주로 백엔드(서버 사이드)를 개발하기 위한 하나의 플랫폼이다.

확장자에서 알 수 있듯이 자바스크립트로 개발을 하게 되며,

클라이언트(프론트엔드)에서 요청하는 이벤트에 따라 실시간으로 대응이 가능하다.

요즘 실시간으로 동작하는 웹게임들을 볼 수 있는데 그와 같은 것도 node.js를 이용했다고 보면 된다.

 

이제 설치 방법에 대해 알아보겠다.

 

먼저 https://nodejs.org/ 사이트로 이동한다.

 

위와 같은 화면을 볼 수 있는데 두가지 버전을 제공한다.

좌측에 있는 LTS 버전은 안정된 버전이라 보면 되며, 

우측의 Current는 현재의 최신 버전이라 보면 된다.

백엔드로 동작하는 서버는 안정성이 중요하므로 LTS 버전으로 다운 받을 것을 권장한다.

 

다운 받은 파일을 위와 같이 실행하여 설치한다.

그냥 쭉 Next를 눌러주면 된다.

 

설치를 모두 완료하였다면 명령 프롬프트를 띄우고 'npm -v' 를 입력해본다.

위와 같이 버전 정보가 나온다면 정상적으로 설치되었다고 볼 수 있다.

 

이제 설치는 모두 완료하였으므로 간단히 코드를 작성하여 Node.js를 테스트해볼 것이다.

먼저 명령 프롬프트에서 자신이 코드 작업할 경로로 이동한다.

(나는 C:\node_server\ 에서 작업하였다.)

 

그리고 아래와 같이 패키지 초기화 작업을 해줍니다.

 

위와 같이 'npm init' 명령을 입력 후 정보를 입력(입력하지 않을 경우는 계속 엔터)해준다.

그러면 package.json 파일이 생성되며, 이 파일은 앞으로 npm을 통해 필요한 여러 패키지를

설치할 때 의존성 관리를 위해 사용된다. 예로 다른 개발자에게 똑같은 환경 설정을 제공해주고자

할 경우 이 package.json 도 같이 넘겨주면 똑같은 환경으로 패키지를 설치할 수 있게 된다.

 

단순히 node.js 코드 테스트에는 필요없지만 결국에는 필요한 내용이므로 만들어보았다.

이제 node.js 동작 테스트를 위해 index.js 파일을 만들어보겠다.

 

이와 같이 'touch index.js' 명령으로 간단히 빈 파일을 만들 수 있다.

이제 편집을 해야하는데 나는 VS Code를 이용해서 편집하였다.

VS Code는 네이버에서 검색하여 다운받을 수 있다.

(메모장으로 편집하여도 상관없으나 VS Code가 깔끔하고 편하다.)

 

위와 같이 코드를 입력해주고 저장한다.

위에 보면 hostname에 0.0.0.0이라고 입력되어있는데, any라는 의미로 해석하면 된다.

127.0.0.1로 해서 로컬 서버를 열어주어도 되지만, 외부에서는 접속이 불가능하다.

이제 위 파일을 서버로 동작시켜보겠다.

 

위와 같이 명령 프롬프트에서 'node index.js' 를 입력해준다.

그럼 코드에서 입력해주었던 로그가 그대로 표시된다.

 

이제 웹브라우저에서 해당 페이지를 확인해볼 차례다.

 

위와 같이 http://localhost/ 로 접속해보면,

작성한 코드에서 응답으로 보내주는 'TEST'가 정상적으로 표시되었다.

 

간단하게 Node.js를 테스트해보았는데,

이것을 응용하여 많은 것들을 할 수 있으니 익혀두면 좋을 것 같다.

반응형
반응형

 

이 포스트에서는 안드로이드 스튜디오에 플러터를 설치해보기로 한다.

 

당연히 플러터를 설치하기 전에 기본적으로 안드로이드 스튜디오가 설치되어있어야 한다.

(필자는 안드로이드 스튜디오 3.4.2 버전이 설치되어있음)

 

먼저 https://flutter.dev/ 로 이동하여 'Get started' 버튼을 클릭한다.

 

 

그 다음 설치할 OS를 지정한다.(필자는 Windows에 설치할 것이므로 Windows를 선택했다.)

그 후에는 파일을 다운로드할 수 있는 버튼이 아래와 같이 생기며 해당 파일을 다운로드해준다.

 

모두 다운로드되었다면 압축을 풀어준다.

압축을 푼 내용 자체가 안드로이드 스튜디오 자체에서 참조할 SDK 경로가 된다.

(나는 C:\flutter\flutter 에 압축을 풀었다.)

 

압축 푼 경로로 이동하여 'flutter_console.bat' 을 실행한다.

 

위와 같이 해당 경로에서 'flutter doctor' 를 입력해준다.

이 명령어를 통해 어떤 부분이 부족한지를 확인할 수 있다.

 

보면 세가지의 문제가 있다. 

먼저 X 표시가 되어있는 플러터와 다트 플러그인 설치가 되지 않은 부분을 해결해보자.

 

안드로이드 스튜디오를 켠다. 프로젝트를 불러오기 전 Configure -> Plugins 을 선택한다.

(프로젝트를 불러온 상태라면 File->Setting->Plugins 로 들어가면 된다.)

아래의 창이 뜨면 flutter, dart를 각각 검색하여 설치해주기만 하면 된다.

 

위와 같이 Dart 플러그인을 설치했다면, 이제 flutter를 검색한다.

 

이제 플러그인은 모두 설치했으니 다시 flutter_console.bat 을 실행하여, 'flutter doctor' 를 입력해보자.

 

플러그인 부분은 해결이 되었고,

안드로이드 라이센스가 허가되어있지 않다고 나와있는 부분만 해결하면 된다.

이 부분은 위에 나와있는대로 해당 명령어만 쳐주면 해결된다.

 

위와 같이 입력 후 나오는 문구는 모두 y를 입력해준다.

그리고 다시 'flutter doctor'를 쳐보면 모두 해결되어있을 것이다.

 

위와 같이 안드로이드 스튜디오를 실행하면,

플러터 프로젝트가 생겨난 것을 확인할 수 있다.

반응형
반응형

이번에는 플러터에서 Stateful, Stateless의 차이점에 대해 알아보려고 한다.

 

이 두개의 개념은 플러터에서 상당히 중요한 위치를 차지하고 있고

 

이것을 모르고는 플러터 개발을 원활히 진행할 수 없다.

 

하지만 복잡하지는 않다.

 

Stateful

이것은 뜻 그대로 해석하면 '상태가 있는'을 의미하며,

의미 그대로 상태를 가질 수 있는 위젯을 사용하기 위해 사용한다.

예를 들면, CheckBox, Slider 등의 위젯이 있다.

CheckBox를 예로 들면 체크, 체크안함 이 두가지 상태를 갖고 있으며 사용자의

액션에 따라 상태가 변하게 된다. 즉, 이러한 상태를 갖는 위젯을 사용할 때는

Stateful을 사용해야 한다.

 

Stateless

위 Stateful과 반대로 '상태가  없는'을 의미하며,

사용자의 동작과 상호작용이 필요없는 위젯을 사용할 때 사용한다.

Container, Row, Column, Icon, Text 등이 있습니다.

이 위젯들은 사용자와 상호작용을 하지 않는 위젯들입니다.

CheckBox 같은 위젯과 달리 Container를 예로 들면

해당 위젯을 터치해서 무언가 반응을 해야할 필요가 없기 때문이죠.

 

여기서 어떤 분은 이런 의문을 품을 수도 있을 것 같습니다.

Text 내의 글자를 변경하게 된다면 그것은 Stateful에 해당되는 것이 아니냐?

Text 내의 글자를 변경하는 것은 사용자와 상호 작용을 하는 것이 아니므로

Stateful에 해당하지 않습니다. CheckBox와 Slider, Radio 등의 위젯처럼

사용자가 터치 등의 동작이 있을 때 반응해야 하는 위젯만이 Stateful 위젯에 해당됩니다.

 

왜 이렇게 나누어놓았는가?

우선 Stateful과 Stateless의 LifeCycle이 다릅니다.

당연히 상호작용이 필요없는 Stateless가 LifeCycle이 더 빠르게 동작하므로,

반응에 대한 비용을 절약할 수 있습니다.(Stateless가 속도가 빠름을 의미)

Stateful과 같이 상호작용이 필요한 부분은 사용자와 상호작용시마다

그 상태를 새로 업데이트해주어야 하기 때문에 LifeCycle 시간이 더 걸리게 됩니다.

즉, 더 효율적인 개발을 위해 위와 같이 나누어진 것이라고 보시면 되겠습니다.

반응형
반응형

플러터에서 앱 아이콘을 변경하는 방법을 설명한다.

 

해당 내용을 검색하다가 어이없는 설명을 발견...

 

플러터 사용자라면 모두가 알다시피 멀티플랫폼 개발이 가능하게 해주는 도구이다.

 

따라서, 앱 아이콘 또한 플러터에서만 한번 세팅을 해주면

 

각각의 플랫폼별로 세팅을 하지 않아도 자동적으로 동작하여야 한다.

 

그런데 내가 보았던 자료 중 하나는 각 플랫폼별로 직접 아이콘을 세팅해주는 내용이었다.

 

그러한 비효율적인 작업은 하지 않길 바라며 이 글을 작성해본다.

 

우선 원하는 아이콘을 구한 뒤 아래와 같이 세팅한다. (아이콘은 512x512로 작업하였다.)

 

위와 같이 프로젝트 루트에 icon 폴더를 만들고 아이콘 파일을 넣는다.

(경로는 자유롭게 지정하여도 된다.)

 

위와 같이 pubspec.yml 파일을 열어서 빨간박스의 내용들을 입력해준다.

image_path는 아이콘을 넣어준 경로를 지정하면 된다.

 

android: true

ios: true

이 두 부분이 플러터 자체에서 해당 아이콘을 알아서 각각의 플랫폼에 덮어씌워주는 역할을 한다.

 

거의 다 됐다. 

이제 실제로 위와 설정된 파일과 이미지를 패키지에 넣어주는 일만 해주면 된다.

 

위와 같이 Terminal 로 이동하여 위 두 명령어를 입력해주기만 하면 끝이 난다.

참고로 나는 플러터의 경로를 환경변수에 넣어주지 않아서 저렇게 실행 경로를 지정해주었으나,

환경변수에 넣어주면 실행파일명만 입력하면 된다

 

그리고 저 명령을 실행하는 위치는 반드시 자신의 프로젝트 경로에서 실행하여야 한다.

그렇지 않으면 오류가 발생하게 된다.

 

위처럼 완료되었다면 앱을 실행해보자.

아이콘이 바뀌어있는 것을 확인할 수 있을 것이다.

반응형
반응형

이 포스트는 STM32 칩을 쓰시는 분들 중 IAR을 사용하시는 분들에게 해당되는 내용이다.

 

위와 같은 오류를 한번쯤 경험했을 것이다.

 

일반적으로는 ST-LINK와 MCU간의 핀 맵핑이 잘못되어있거나,

MCU가 불량이거나, 전원이 제대로 들어가지 않거나 하는 등의 내용이 원인이다.

 

하지만 나의 경우는 더 난감한 경우를 경험하였다.

잘못된 코드를 다운로드하여 ST-LINK와 MCU와 연결을 할 수 없는 상태가 발생할 수 있는데

바로 이 상황을 겪었다.

 

문제의 코드는 바로 위의 '_HAL_AFIO_REMAP_SWJ_NOJTAG();'이다.

이것은 해당 ST-LINK가 다운로드 전용으로 사용하는 핀을 리맵핑하여

GPIO 등 다른 목적으로 쓰게 만들어준다.

하지만, 문제는 이렇게 하는 즉시 그 이후로는 다운로드 핀으로는 사용할 수 없게 되어버린다.

그 이후로는 맨 위의 디바이스를 찾을 수 없다는 메세지만 뜨게 된다.

해당 다운로드 핀을 반드시 써야하는게 아니라면 위의 코드는 쓰지 않는 것을 추천한다.

 

나는 보통 초기 MCU PIN 세팅 및 기본적인 세팅은 STM32CubeMX을 통해 코드화한다.

(STM32 칩을 쓰는 개발자라면 대부분이 이용할 것이다.)

나는 STM32CubeMX에서 각 기능을 세팅할 때 SYS의 Debug에 대해 관심을 갖지 않았었다.

하지만 저 부분을 Default인 'No Debug'로 두면 JTAG 혹은 ST-LINK와 같은 디버깅 툴을 사용하지

않는 것으로 간주하고, _HAL_AFIO_REMAP_SWJ_NOJTAG(); 코드를 생성해버린다.

 

위와 같이 ST-LINK를 사용한다면 Serial Wire, 그 외의 툴을 사용한다면 그에 맞게 지정하면 된다.

그리하면 위와 같은 코드가 생기지 않으며, 디버깅 툴을 문제없이 사용할 수 있게 된다.

 

이제 이미 잘못된 코드를 실수로 다운로드하여 더 이상 디버깅이 되지 않는 경우를

복구하는 방법을 설명할 것이다.

 

데이타시트를 보면 위와 같은 내용이 있다.

일반적으로 BOOT0을 GND에 붙여 사용하는데, BOOT0을 강제로 HIGH를 주고 전원을 넣을 경우

MCU는 메인 프로그램을 실행하지 않는다. 이 때는 디버깅 툴의 사용이 가능해지기 때문에,

해당 코드를 수정한 상태로 다운로드하고 원상복귀 시켜주면 해결이 된다.

 

이 외에도 Flash Loader를 이용해서 펌웨어를 다시 심는 방법도 있는데,

위 방법이 가장 간단한 것 같다.

반응형

+ Recent posts