개요

사실 별 동작을 하진 않고, 아래와 같이 지정된 스택 (r1)에 fake stack frame을 생성한다.

생성된 이상 ‘스택 프레임’으로 동작하겠지만, 원래 시스템에 의해서 생성되어야할 것을 임의로 만들었기 때문에 그렇게 부르는 것으로 보인다.

대문자 LR, 소문자 lr 모두 링크 레지스터를 가리키는데 LR은 예외 발생시 해당하는 함수의 링크 레지스터를 저장(디버깅)하는 용도로 사용되고 lr은 현재 스택 프레임의 링크 레지스터를 의미한다.

xPSR은 확장 Program Status Register를 의미한다. 또한 설정된 T-bit는 Thumb 모드로 사용됨을 의미한다.

Thumb모드는 성능은 조금 떨어질 수 있지만, 코드(명령어)의 크기가 작은 모드라고 할 수 있다. (명령어가 32bit 에서 16bit로 저장된다)

코드

// VOID   _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
// {
    PUBLIC  _tx_thread_stack_build
_tx_thread_stack_build:
    /* Build a fake interrupt frame.  The form of the fake interrupt stack
       on the Cortex-M should look like the following after it is built:
 
       Stack Top:
                       LR          Interrupted LR (LR at time of PENDSV)
                       r4          Initial value for r4
                       r5          Initial value for r5
                       r6          Initial value for r6
                       r7          Initial value for r7
                       r8          Initial value for r8
                       r9          Initial value for r9
                       r10         Initial value for r10
                       r11         Initial value for r11
                       r0          Initial value for r0    (Hardware stack starts here!!)
                       r1          Initial value for r1
                       r2          Initial value for r2
                       r3          Initial value for r3
                       r12         Initial value for r12
                       lr          Initial value for lr
                       pc          Initial value for pc
                       xPSR        Initial value for xPSR
 
    Stack Bottom: (higher memory address)  */
 
    LDR     r2, [r0, #16]                           // Pickup end of stack area
    BIC     r2, r2, #0x7                            // Align frame for 8-byte alignment
    SUB     r2, r2, #68                             // Subtract frame size
#ifdef TX_SINGLE_MODE_SECURE
    LDR     r3, =0xFFFFFFFD                         // Build initial LR value for secure mode
#else
    LDR     r3, =0xFFFFFFBC                         // Build initial LR value to return to non-secure PSP
#endif
    STR     r3, [r2, #0]                            // Save on the stack
 
    /* Actually build the stack frame.  */
 
    MOV     r3, #0                                  // Build initial register value
    STR     r3, [r2, #4]                            // Store initial r4
    STR     r3, [r2, #8]                            // Store initial r5
    STR     r3, [r2, #12]                           // Store initial r6
    STR     r3, [r2, #16]                           // Store initial r7
    STR     r3, [r2, #20]                           // Store initial r8
    STR     r3, [r2, #24]                           // Store initial r9
    STR     r3, [r2, #28]                           // Store initial r10
    STR     r3, [r2, #32]                           // Store initial r11
 
    /* Hardware stack follows.  */
 
    STR     r3, [r2, #36]                           // Store initial r0
    STR     r3, [r2, #40]                           // Store initial r1
    STR     r3, [r2, #44]                           // Store initial r2
    STR     r3, [r2, #48]                           // Store initial r3
    STR     r3, [r2, #52]                           // Store initial r12
    MOV     r3, #0xFFFFFFFF                         // Poison EXC_RETURN value
    STR     r3, [r2, #56]                           // Store initial lr
    STR     r1, [r2, #60]                           // Store initial pc
    MOV     r3, #0x01000000                         // Only T-bit need be set
    STR     r3, [r2, #64]                           // Store initial xPSR
 
    /* Setup stack pointer.  */
    // thread_ptr -> tx_thread_stack_ptr =  r2;
 
    STR     r2, [r0, #8]                            // Save stack pointer in thread's
                                                    //   control block
    BX      lr                                      // Return to caller
// }
    END

코드를 보면 스택이 끝에서 반대로 저장되는 것을 확인할 수 있다.