inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

FreeRTOS 프로그래밍

RTOS 커널 포팅의 핵심 원리

[문의] Exception Handler 관련

418

chucky2
1

안녕하세요. 금일 free-rtos 강좌를 완강했습니다. 강의 및 질의/응답을 통해서 부족한 부분을 많이 채웠습니다.

강의와 연관성이 없는 질문하나 드립니다. 개인적으로, 강사님이 알려주신 환경 (cubeide) 에 exception handler를 적용해보고 있는데, 쉽지 않네요.

exception handler는 cortex-m3 계열의 core와 IAR 컴파일러 환경에서 작성된 source같은데....cortex-m4f 및 gcc 기반으로 변경하려니 exception 발생 시 자동으로 stacking되는 register도 floating point 연산이 없는 core와 달리 늘어난 것 같고, assembler도 잘 모르겠고 .... 난항입니다.

혹시, cubeide, cortex-m4f 환경에서, exception handler가 적용된 참조할만한 예제가 있으면 도움 부탁드립니다.

답변 3

0

홍영기

안녕하세요. chucky2님!

완강을 축하드립니다. 질문도 많이하시고 ^^ 저도 즐거웠습니다.

이 강좌 마지막 챕터(포팅 사례와 소스코드)를 보시면 다양한 STM32-M4F 포팅 소스들이 있습니다.

혹시 원하시는 것이 다른 것이었다면 다시 글 남겨주세요.

마지막으로 감사드리며, 괜찮으시다면 수강평 부탁드려요. ㅎ~

 

 


 

0

chucky2

수강평은 남기도록 하죠~

궁금한 내용은 아래와 같습니다. 목적은 exception handler를 적용하여 hard/bus/memory management/usage fault 등 발생 시, stack 및 system control register를 정보를 활용하여 문제점을 확인하는 겁니다.

IAR 컴파일러 및 cortex-m3에서 작성된 내용을 cubeide 및 cortex-m4f 환경으로 변경해보고자 하는데, IAR vs GCC, floating point 유/무에 따라서 적용하는게 좀 다른가봅니다.

관련해서 참조할만한 자료가 있을까요? 컴파일러가 다르다는게 ....정말 간단하게 적용이 쉽지 않네요.

/* Call the clock system initialization function.*/
  bl  SystemInit   
/* Call static constructors */
    bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr    
.size  Reset_Handler, .-Reset_Handler

    .section  .text._HardFault_Handler,"ax",%progbits
  .weak  _HardFault_Handler
  .type  _HardFault_Handler, %function
_HardFault_Handler:
        PUSH  {r0, lr}
        ADD   r0, sp, #8
        LDR   r1, [sp, #4]
        MRS   r2, psp
        BL    HardFault_Handler
        POP   {r0, pc}
  .size  _HardFault_Handler, .-_HardFault_Handler

      .section  .text._UsageFault_Handler,"ax",%progbits
  .weak  _UsageFault_Handler
  .type  _UsageFault_Handler, %function
_UsageFault_Handler:
        PUSH  {r0, lr}
        /*BL    _Print_Reg*/
        ADD   r0, sp, #8
        LDR   r1, [sp, #4]
        MRS   r2, psp
        BL    UsageFault_Handler
        POP   {r0, pc}
  .size  _UsageFault_Handler, .-_UsageFault_Handler

        .section  .text._BusFault_Handler,"ax",%progbits
  .weak  _BusFault_Handler
  .type  _BusFault_Handler, %function
_BusFault_Handler:
          PUSH  {r0, lr}
        /*BL    _Print_Reg*/
        ADD   r0, sp, #8
        LDR   r1, [sp, #4]
        MRS   r2, psp
        BL    BusFault_Handler
        POP   {r0, pc}
.size  _BusFault_Handler, .-_BusFault_Handler

 

g_pfnVectors:
  .word  _estack
  .word  Reset_Handler
  .word  NMI_Handler
  .word  _HardFault_Handler /*.word  HardFault_Handler*/
  .word  _MemManage_Handler
  .word  _BusFault_Handler
  .word  _UsageFault_Handler
  .word  0
  .word  0
  .word  0
  .word  0

 

void HardFault_Handler(unsigned int * sp, unsigned int lr, unsigned int * psp);

void HardFault_Handler(unsigned int * sp, unsigned int lr, unsigned int * psp)
{
    int i;

    printf("Hard Fault!\n");
    printf("LR(EXC_RETURN)=0x%x\n", lr);
    printf("MSP=0x%p\n", sp);
    printf("PSP=0x%p\n", psp);

    if((lr & 0xF) == 0x1)
    {
        printf("Exception occurs from handler mode\n");

        for(i=0; i<(sizeof(Stack_reg)/sizeof(Stack_reg[0])); i++)
        {
            printf("MSP[%d],%s=0x%x\n", i, Stack_reg[i], sp[i]);
        }
    }

    else
    {
        printf("Exception occurs from thread mode\n");

        for(i=0; i<(sizeof(Stack_reg)/sizeof(Stack_reg[0])); i++)
        {
            if((lr & 0xF) == 0x9) printf("MSP[%d],%s=0x%x\n", i, Stack_reg[i], sp[i]);
            else printf("PSP[%d],%s=0x%x\n", i, Stack_reg[i], psp[i]);
        }
    }

    printf("HFSR(Hard Fault Reason) => 0x%lx\n", SCB->HFSR);
    printf("SHCSR => 0x%lx\n", SCB->SHCSR);
    printf("CFSR(Fault Reason) => 0x%lx\n", SCB->CFSR);
    printf("MMFAR => 0x%lx\n", SCB->MMFAR);
    printf("BFAR => 0x%lx\n", SCB->BFAR);

    SCB->HFSR = (1u << 31)|(30 << 1)|(1 << 1);
    SCB->CFSR = 0xffff << 0;

    for(;;);
}

이런 식으로 진행 중입니다....

0

홍영기

안녕하세요. chucky2님!

질문하신 내용이 FreeRTOS 와 직접적인 관계는 없는것이었군요. ㅎ
폴트와 같은 익셉션 발생시 문제 해결에 도움이 될만한 일종의 helper 를 만들고 싶어하시는 것으로 이해하였습니다.
IAR, KEIL, CUBEIDE(GCC) 모두 어셈블러 문법이 조금씩 다릅니다. 인스트럭션이야 동일하지만, 컴파일러마다 지시어(directives) 가 다른 것이지요.

이는 컴파일러 툴마다의 문법 차이를 확인하면서 일일이 수정하시는 수밖에 없습니다. 특별한 방법이란 있을 수 없죠. 이것도 분명히 일종의 포팅(PORTING)으로 보며, 컴파일러 이식 행위입니다.

CM3 과 달리 CM4 에는 FPU가 있습니다. 하지만, 이것을 사용하지 않는다면 디버깅시 fp 컨텍스트(e.g. d0, d1, d2 ... ) 는 고려하지 않으셔도 되요.

위에 샘플로 보여주신 것처럼 진행하시면 되겠네요. ^^ 적어주신 내용을 보면 어셈블리어도 직접 다루실 수 있는 것으로 보입니다. 혹시 어셈블리 언어에 대한 정리된 내용이 필요하시면 지난 6월에 론칭한 제 강좌('ARM CORTEX 프로세서 프로그래밍') 가 좋습니다. 참고해주세요 ㅎㅎ