Brise
STM32 + FreeRTOS 이용시 printf를 수행하면 hardfault가 생기는 경우 본문
STM32를 사용하여 펌웨어를 작성할 때에 태스크 코드에서 printf를 수행할 때 특정 경우에 오류가 발생하는 것을 볼 수 있다.
또는 malloc을 사용하여 큰 용량의 데이터를 Heap에서 확보하고자 할때 오류가 발생한다.
malloc에서 보았다시피 이 문제는 FreeRTOS 때문에 생기는 문제다.
(정확히는 FreeRTOS와 STM32에서 기본적으로 제공하는 newlib의 Heap이 충돌하는 문제이다. 둘 모두 ST마이크로에서 제공하는 코드인 것은 함정)
자세히 내용을 설명하자면
newlib에서는 printf를 수행하거나 malloc을 수행할 때 특정 경우에 한하여 더 큰 메모리를 요구하여 메모리 영역을 확보하는 코드인 _sbrk함수를 호출한다.
기본적인 펌웨어에서는 힙이 스택을 침해하는 것을 막기 위하여 sbrk함수에서 스택의 위치인 스택포인터 값을 확인하여 메모리 블럭을 확보할 수 있는지를 확인하는 코드가 존재한다.
하지만 FreeRTOS를 사용하는 경우에는 해당 스택 포인터가 가리키는 곳이 메인 스택의 포인터가 아닌 FreeRTOS의 Heap영역 안에 존재하는 스택 포인터를 가리키게 된다. 그리고 이 영역은 메모리 중의 .bss영역에 속해 있기 때문에 Heap보다 아래 주소에 위치하게 된다.
(stm32에서 스택은 높은 메모리 영역에서 아래 방향으로, 힙은 낮은 메모리 영역에서 높은 방향으로, 변수들은 힙 아래 영역에 위치하게 되어있다.)
때문에 sbrk함수에서는 실제 메모리가 여유가 있더라도, 확보 할 수 없다는 메세지를 밷게 되어 있으며, 이 리턴 값 때문에 HardFault가 발생하게 된다.
이를 workaround를 하는 방법은 여러가지가 있을 수 있는데,
1. sbrk함수가 적정 값을 반환하도록 변경하는 방법
2. sbrk함수를 호출하지 않는 printf함수를 사용하는 방법
(3. sbrk함수를 호출하지 않도록 malloc을 오버라이딩하는 방법) --> newlib의 printf는 sbrk를 직접 호출하기 때문에 무용지물이다.
이 중에서 개인적으로는 2번방법을 선호한다.
http://www.nadler.com/embedded/newlibAndFreeRTOS.html
해당 글의 아래부분을 보면
https://github.com/mpaland/printf
이 오픈소스가 제공되어 있는데,
이 코드의 printf.c와 printf.h를 받은 뒤에 printf를 사용하는 코드에 printf.h 헤더를 포함하면된다.
또는 프로젝트 전체의 코드의 Define을 처리하여 사용하는 방법이 있을 수 있다.
'MCU' 카테고리의 다른 글
STM32F7(Cortex-M7) 캐시 Invalidate (0) | 2020.10.17 |
---|---|
원리부터 실무까지 쉽고 명확한 Arm 프로그래밍(Cortex-A9 중심으로) (0) | 2020.08.21 |
STM32F4 온도 센서 코드 (0) | 2020.03.15 |
USB ASP (0) | 2018.06.03 |
IAR EWARM에서 stm32 SWO로 printf 사용하기 (0) | 2018.03.20 |
Eclipse 기반의 AVR 개발 환경 구축하기 (0) | 2018.03.16 |
HAL SPI DMA 코드 (0) | 2017.12.24 |