테스트 하고 있는 MCU에서 gcc 최적화 옵션을 어떻게 설정하느냐에 따라서 다른 결과를 경험했다. 이것도 모르고 일주일 정도 삽질을 했다. Cortex-M4 MCU를 gcc-arm을 이용하여 빌드 시에, gcc Option 및 MCU 속도에 따라서 정상적인 결과가 나오기도 하고, 원하지 않는 엉뚱한 결과가 나오기도 했다. 처음에는 gcc 최적화 옵션의 문제인지 모르고 다른 쪽의 문제인지 알고 한참을 검토했으나, 결국 최적화 옵션이 문제였다.
아래는 gcc 옵션에 따라서 알고리즘의 정상 동작/비정상 동작의 결과를 정리한 것이다.
Cortex-M4 기반 MCU |
Clock |
-Os 옵션 |
-O0, -O3 옵션 |
STM32F4 |
168 MHz |
알고리즘 정상 동작 |
알고리즘 정상 동작 |
STM32F3 |
72 MHz |
알고리즘 출력값 이상 |
알고리즘 정상 동작 |
위와 같이 결과가 나온 정확한 원인은 모르겠는데, 아마 -Os로 최적화 하면서 코드 사이즈가 자동으로 줄면서 오류가 발생한 듯하다. Uart로 값을 읽어서 처리하는 것인데, Uart로 읽고 알고리즘 처리하는 것이 Clock속도와도 관계가 있는 듯 하다. 같은 코어(Cortex-M4)를 이용하더라도, gcc 최적화 옵션과 Clock 속도에 따라서 다른 결과를 보였다. 혹, 알고리즘이 잘못 작성되어 그런지는 모르겠으나, 어디가 문제인지는 정확하게 모르겠다.
컴파일 옵션에 따라서 수행 속도나 코드 사이즈가 차이가나는데, 정확히 어떠한 옵션을 써야 되는지는 판단이 어렵다. 아래의 출처를 보니, 개발 시에는 -O0 옵션을 이용하여 디버깅하면서 개발하고하고, 개발 완료 해서 배포할 때는 보통 -O2 옵션을 이용한다고 한다. -O3나 -Os는 특별한 경우에만 사용하는 듯 하다.
참조: http://www.network-theory.co.uk/docs/gccintro/gccintro_49.html
6.4 Optimization levels
In order to control compilation-time and compiler memory usage, and the trade-offs between speed and space for the resulting executable, GCC provides a range of general optimization levels, numbered from 0--3, as well as individual options for specific types of optimization.
An optimization level is chosen with the command line option -OLEVEL
, where LEVEL
is a number from 0 to 3. The effects of the different optimization levels are described below:
-O0
or no-O
option (default)- At this optimization level GCC does not perform any optimization and compiles the source code in the most straightforward way possible. Each command in the source code is converted directly to the corresponding instructions in the executable file, without rearrangement. This is the best option to use when debugging a program and is the default if no optimization level option is specified.
-O1
or-O
- This level turns on the most common forms of optimization that do not require any speed-space tradeoffs. With this option the resulting executables should be smaller and faster than with
-O0
. The more expensive optimizations, such as instruction scheduling, are not used at this level. Compiling with the option-O1
can often take less time than compiling with-O0
, due to the reduced amounts of data that need to be processed after simple optimizations. -O2
- This option turns on further optimizations, in addition to those used by
-O1
. These additional optimizations include instruction scheduling. Only optimizations that do not require any speed-space tradeoffs are used, so the executable should not increase in size. The compiler will take longer to compile programs and require more memory than with-O1
. This option is generally the best choice for deployment of a program, because it provides maximum optimization without increasing the executable size. It is the default optimization level for releases of GNU packages. -O3
- This option turns on more expensive optimizations, such as function inlining, in addition to all the optimizations of the lower levels
-O2
and-O1
. The-O3
optimization level may increase the speed of the resulting executable, but can also increase its size. Under some circumstances where these optimizations are not favorable, this option might actually make a program slower. -funroll-loops
- This option turns on loop-unrolling, and is independent of the other optimization options. It will increase the size of an executable. Whether or not this option produces a beneficial result has to be examined on a case-by-case basis.
-Os
- This option selects optimizations which reduce the size of an executable. The aim of this option is to produce the smallest possible executable, for systems constrained by memory or disk space. In some cases a smaller executable will also run faster, due to better cache usage.
It is important to remember that the benefit of optimization at the highest levels must be weighed against the cost. The cost of optimization includes greater complexity in debugging, and increased time and memory requirements during compilation. For most purposes it is satisfactory to use -O0
for debugging, and -O2
for development and deployment.
'프로그래밍 > 임베디드' 카테고리의 다른 글
STM32F3xx 에서 SPI 이용하기 (0) | 2013.11.09 |
---|---|
STM32 DFU를 활용한 다운로드 (0) | 2013.11.08 |
ARM Cortex-M의 효과적인 코딩 방법 소개 (0) | 2013.02.03 |
.bin 파일과 .hex 파일의 이해 (0) | 2013.02.03 |
ARM Cortex-M에서 빌드 정보로 Flash(ROM) 및 RAM 사이즈 계산 (0) | 2013.02.03 |