FreeRTOS v8.0.1 STM32 데모 예제를 공개용 툴체인 GNU GCC 4.8(현재 최신 버전)로 빌드할 때 

core_cm.c 부분에서 아래와 같은 에러가 날 수 있습니다. 보통 ST에서 배포하는 CMSIS 버전이 v1.3인데

이 버전에서 컴파일 최적화 옵션에 따라 이러한 문제가 발생할 수 있다고 합니다. FreeRTOS에서 배포한

CMSIS버전도 역시나 같은 버전이네요.


 Error: registers may not be the same -- `strexb r0,r0,[r1]'

 Error: registers may not be the same -- `strexh r0,r0,[r1]'


구글링을 해보니 해당 에러가 아래와 같은 이유로 에러가 나타나는 것이라고 합니다.

The reason  is that the ARM manual says that the result of these instructions are undefined if the registers are the same.

 

아래와 같이 코드를 수정하면 신기하게도 깨끗히 빌드가 됩니다.


at Line 732 : uint32_t __STREXB(uint8_t value, uint8_t *addr)

Replace
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
To 

__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );

 

and 
 

at Line 749 : uint32_t __STREXH(uint16_t value, uint16_t *addr)

Replace
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
To
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );


또는 함수의 prototype 앞에 컴파일 최적화 옵션 O0로 빌드하도록 아래 attribute를 추가해도 해결 됩니다.


__attribute__( ( always_inline , optimize("O0")) ) static __INLINE

uint32_t __STREXB(uint8_t value, uint8_t *addr)

{

   uint32_t result=0;

  

   __ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );

   return(result);

}

__attribute__( ( always_inline , optimize("O0")) ) static __INLINE

uint32_t __STREXH(uint16_t value, uint16_t *addr)

{

   uint32_t result=0;

  

   __ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );

   return(result);

}



다행히 ST에서 배포한 StdPeriph driver v3.5.0 은 이렇게 수정되어서 배포가 되고 있습니다.

아래 링크를 보시면 더 자세한 내용을 볼 수 있습니다.

http://www.atollic.com/index.php/kb/1-kb_building/117-kb_error_in_strexb


문제가 생겼던 STREXB나 STREXH에 대한 정보는 아래 ARM info페이지를 참조하시면 됩니다.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204hk/Cihbghef.html