Azure RTOSでRXマイコンが使えるようになったのですね

こんにちは。NoMaYです。

Azure RTOSでRXマイコンが使えるようになったのですね。コンパイラはGNURXが使われていました。

Getting started with the Renesas Starter Kit+ for RX65N-2MB (英文です。)
02/05/2021 Ryan Winter
docs.microsoft.com/ja-jp/samples/azure-rtos/getting-started/getting-started-with-the-renesas-starter-kit-for-rx65n-2mb/
 

Parents
  • 今度はTick割り込みとContext Switching割り込みを覗いてみました。割り込みルーチン先頭で割り込み許可にしているわけではありませんでした。(なお、Context Switching割り込みは、あくまでContext Switchingする処理なので、例えば、ユーザがセマフォを操作して、RTOSがセマフォを制御して、RTOSがタスクの優先度を変化させて、RTOSがタスクを実行可能状態へ遷移させ、RTOSが実行可能タスクのリストに追加して、といった処理の流れの部分は含んで無いです。)

    続く。

    libs/threadx/ports/rxv3/ccrx/src/tx_timer_interrupt.src (FITのCMTモジュールと結合する都合によりサブルーチンです)

    ;VOID   _tx_timer_interrupt(VOID)
    ;{
        .GLB __tx_timer_interrupt
    __tx_timer_interrupt:
    ;
    ;    /* Upon entry to this routine, it is assumed that all interrupts are locked
    ;       out and the stack looks like the following:
    ;                            SP+4 ->   Interrupted PC
    ;                            SP+8->    Interrupted SR
    ;   */
    ;
    ;    /* Increment the system clock.  */
    ;    _tx_timer_system_clock++;
    ;
        PUSHM    R14-R15
        PUSHM    R1-R5

        MOV.L    #__tx_timer_system_clock, R1       ; Pickup address of system clock
        MOV.L    [R1], R2                           ; Pickup system clock
        ADD      #1, R2                             ; Increment system clock
        MOV.L    R2,[R1]                            ; Store new system clock
    ;
    ;    /* Test for time-slice expiration.  */
    ;    if (_tx_timer_time_slice)
    ;    {
    ;
        MOV.L   #__tx_timer_time_slice, R1          ; Pickup address of time slice
        MOV.L   [R1], R2                            ; Pickup the current time slice
        CMP     #0, R2                              ; Is a time slice active?
        BEQ     __tx_timer_no_time_slice            ; No, skip timer slice processing
    ;
    ;       /* Decrement the time_slice.  */
    ;       _tx_timer_time_slice--;
    ;
        SUB     #1, R2                              ; Decrement the time-slice
        MOV.L   R2, [R1]                            ; Store time-slice
    ;
    ;       /* Check for expiration.  */
    ;       if (__tx_timer_time_slice == 0)
    ;
        CMP     #0, R2                              ; Has it expired?
        BNE     __tx_timer_no_time_slice            ; No, time-slice has not expired
    ;
    ;       /* Set the time-slice expired flag.  */
    ;       _tx_timer_expired_time_slice =  TX_TRUE;
    ;
        MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup address of expired time-slice
        MOV.L   #1, R2                              ; Build expired value
        MOV.L   R2, [R1]                            ; Set expired time slice variable
    ;    }
    ;
    __tx_timer_no_time_slice:
    ;
    ;    /* Test for timer expiration.  */
    ;    if (*_tx_timer_current_ptr)
    ;    {
    ;
        MOV.L   #__tx_timer_current_ptr, R1         ; Pickup address of current timer ptr
        MOV.L   [R1], R2                            ; Pickup current pointer
        MOV.L   [R2+], R1                           ; Pickup timer list entry, _tx_timer_current_ptr++
        CMP     #0, R1                              ; Is timer pointer NULL?
        BEQ     __tx_timer_no_timer                 ; Yes, no timer has expired
            
    ;
    ;        /* Set expiration flag.  */
    ;        _tx_timer_expired =  TX_TRUE;
    ;
        MOV.L   #__tx_timer_expired,R2              ; Build address of expired flag
        MOV.L   #1, R1                              ; Build expired value
        MOV.L   R1, [R2]    
        BRA     __tx_timer_done                     ; Finished with timer processing
    ;
    ;    }
    ;    else
    ;    {
    __tx_timer_no_timer:
    ;
    ;        /* No timer expired, increment the timer pointer.  */
    ;        _tx_timer_current_ptr++;
    ;
    ;       /* R2 already contains __tx_timer_current_ptr++ */                         
    ;
    ;        /* Check for wrap-around.  */
    ;        if (_tx_timer_current_ptr == _tx_timer_list_end)
    ;
        MOV.L   #__tx_timer_list_end, R1            ; Pickup the timer list end ptr
        MOV.L   [R1], R1                            ; Pickup actual timer list end
        CMP     R1, R2                              ; Are we at list end?
        BNE     __tx_timer_skip_wrap                ; No, don't move pointer to the
                                                    ;   top of the list
    ;
    ;            /* Wrap to beginning of list.  */
    ;            _tx_timer_current_ptr =  _tx_timer_list_start;
    ;
        MOV.L   #__tx_timer_list_start, R2          ; Pickup the timer list start ptr
        MOV.L   [R2], R2                            ; Pickup the start of the list
    ;    }
    ;
    __tx_timer_skip_wrap:
        MOV.L   #__tx_timer_current_ptr,R1     
        MOV.L   R2, [R1]                            ; Store in updated pointer in  _tx_timer_current_ptr  
        
    __tx_timer_done:
    ;
    ;    /* See if anything has expired.  */
    ;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
    ;    {
    ;
        MOV.L  #__tx_timer_expired_time_slice, R1   ; Pickup expired time slice addr
        MOV.L  [R1], R1                             ; Pickup expired time slice
        MOV.L   #__tx_timer_expired, R2             ; Pickup expired timer flag address
        MOV.L   [R2], R2                            ; Pickup actual flag
        OR      R1, R2                              ; Or flags together
        BEQ     __tx_timer_nothing_expired          ; If Z set, nothing has expired

    __tx_something_expired:
    ;    /* Did a timer expire?  */
    ;    if (_tx_timer_expired)
    ;    {
        MOV.L   #__tx_timer_expired,R1              ; Pickup expired flag address
        MOV.L   [R1], R1                            ; Pickup expired flag
        CMP     #0,R1                               ; Is the expired timer flag set?
        BEQ     __tx_timer_dont_activate            ; No, skip timer activation
    ;
    ;        /* Process timer expiration.  */
    ;        _tx_timer_expiration_process();
    ;
        BSR    __tx_timer_expiration_process        ; Call the timer expiration handling routine
    ;
    ;    }
    __tx_timer_dont_activate:
    ;
    ;    /* Did time slice expire?  */
    ;    if (_tx_timer_expired_time_slice)
    ;    {
    ;
        MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup time-slice expired flag addr
        MOV.L   [R1], R1                            ; Pickup actual flag
        CMP     #0,R1                               ; Has time-slice expired?
        BEQ      __tx_timer_not_ts_expiration       ; No, skip time-slice expiration
    ;
    ;        /* Time slice interrupted thread.  */
    ;        _tx_thread_time_slice();

        BSR     __tx_thread_time_slice              ; Call time-slice processing

    ;   /* Check if we must trigger a context switch. */
        MOV.L   #__tx_thread_preempt_disable, R1     ; Load prempt disable flag.
        MOV.L  [R1], R1
        CMP    #0, R1
        BNE    __tx_timer_not_ts_expiration          ; Skip if prempt disabled.

        MOV.L   #__tx_thread_execute_ptr, R1
        MOV.L  [R1], R1
        MOV.L   #__tx_thread_current_ptr, R2
        MOV.L  [R2], R2
        CMP    R1, R2
        BEQ    __tx_timer_not_ts_expiration

        MOV.L   #SWI0, R1
        MOV.L   #1, [R1]

    ;    }
    ;
    __tx_timer_not_ts_expiration:

    __tx_timer_nothing_expired:

        POPM R1-R5
        POPM R14-R15
    ;
        RTS                                         ; Return to point of interrupt
    ;
    ;}

     
    src/hardware_setup.c (FITのCMTモジュールと結合する都合によりコールバックルーチンです)

    /* CMT Timer callback used as the system tick. */
    void timer_callback(void * pdata)
    {
        _tx_timer_interrupt();
    }

    void platform_setup(void)
    {
        uint32_t chan;

        /* Create periodic timer for the system tick. */
        R_CMT_CreatePeriodic(TX_TIMER_TICKS_PER_SECOND, timer_callback, &chan);
        
    }

     
    libs/threadx/ports/rxv3/ccrx/src/tx_thread_schedule.src (こちらは割り込みルーチンです)

    ; Software triggered interrupt used to perform context switches.
    ; The priority of this interrupt is set to the lowest priority within
    ; tx_initialize_low_level() and triggered by ThreadX when calling
    ; _tx_thread_system_return().
    .RVECTOR 27, _tx_software_interrupt_entry
    .GLB _tx_software_interrupt_entry
    _tx_software_interrupt_entry:

        PUSHM R1-R2

        BSR __tx_thread_context_save

        BRA __tx_thread_context_restore

     

Reply
  • 今度はTick割り込みとContext Switching割り込みを覗いてみました。割り込みルーチン先頭で割り込み許可にしているわけではありませんでした。(なお、Context Switching割り込みは、あくまでContext Switchingする処理なので、例えば、ユーザがセマフォを操作して、RTOSがセマフォを制御して、RTOSがタスクの優先度を変化させて、RTOSがタスクを実行可能状態へ遷移させ、RTOSが実行可能タスクのリストに追加して、といった処理の流れの部分は含んで無いです。)

    続く。

    libs/threadx/ports/rxv3/ccrx/src/tx_timer_interrupt.src (FITのCMTモジュールと結合する都合によりサブルーチンです)

    ;VOID   _tx_timer_interrupt(VOID)
    ;{
        .GLB __tx_timer_interrupt
    __tx_timer_interrupt:
    ;
    ;    /* Upon entry to this routine, it is assumed that all interrupts are locked
    ;       out and the stack looks like the following:
    ;                            SP+4 ->   Interrupted PC
    ;                            SP+8->    Interrupted SR
    ;   */
    ;
    ;    /* Increment the system clock.  */
    ;    _tx_timer_system_clock++;
    ;
        PUSHM    R14-R15
        PUSHM    R1-R5

        MOV.L    #__tx_timer_system_clock, R1       ; Pickup address of system clock
        MOV.L    [R1], R2                           ; Pickup system clock
        ADD      #1, R2                             ; Increment system clock
        MOV.L    R2,[R1]                            ; Store new system clock
    ;
    ;    /* Test for time-slice expiration.  */
    ;    if (_tx_timer_time_slice)
    ;    {
    ;
        MOV.L   #__tx_timer_time_slice, R1          ; Pickup address of time slice
        MOV.L   [R1], R2                            ; Pickup the current time slice
        CMP     #0, R2                              ; Is a time slice active?
        BEQ     __tx_timer_no_time_slice            ; No, skip timer slice processing
    ;
    ;       /* Decrement the time_slice.  */
    ;       _tx_timer_time_slice--;
    ;
        SUB     #1, R2                              ; Decrement the time-slice
        MOV.L   R2, [R1]                            ; Store time-slice
    ;
    ;       /* Check for expiration.  */
    ;       if (__tx_timer_time_slice == 0)
    ;
        CMP     #0, R2                              ; Has it expired?
        BNE     __tx_timer_no_time_slice            ; No, time-slice has not expired
    ;
    ;       /* Set the time-slice expired flag.  */
    ;       _tx_timer_expired_time_slice =  TX_TRUE;
    ;
        MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup address of expired time-slice
        MOV.L   #1, R2                              ; Build expired value
        MOV.L   R2, [R1]                            ; Set expired time slice variable
    ;    }
    ;
    __tx_timer_no_time_slice:
    ;
    ;    /* Test for timer expiration.  */
    ;    if (*_tx_timer_current_ptr)
    ;    {
    ;
        MOV.L   #__tx_timer_current_ptr, R1         ; Pickup address of current timer ptr
        MOV.L   [R1], R2                            ; Pickup current pointer
        MOV.L   [R2+], R1                           ; Pickup timer list entry, _tx_timer_current_ptr++
        CMP     #0, R1                              ; Is timer pointer NULL?
        BEQ     __tx_timer_no_timer                 ; Yes, no timer has expired
            
    ;
    ;        /* Set expiration flag.  */
    ;        _tx_timer_expired =  TX_TRUE;
    ;
        MOV.L   #__tx_timer_expired,R2              ; Build address of expired flag
        MOV.L   #1, R1                              ; Build expired value
        MOV.L   R1, [R2]    
        BRA     __tx_timer_done                     ; Finished with timer processing
    ;
    ;    }
    ;    else
    ;    {
    __tx_timer_no_timer:
    ;
    ;        /* No timer expired, increment the timer pointer.  */
    ;        _tx_timer_current_ptr++;
    ;
    ;       /* R2 already contains __tx_timer_current_ptr++ */                         
    ;
    ;        /* Check for wrap-around.  */
    ;        if (_tx_timer_current_ptr == _tx_timer_list_end)
    ;
        MOV.L   #__tx_timer_list_end, R1            ; Pickup the timer list end ptr
        MOV.L   [R1], R1                            ; Pickup actual timer list end
        CMP     R1, R2                              ; Are we at list end?
        BNE     __tx_timer_skip_wrap                ; No, don't move pointer to the
                                                    ;   top of the list
    ;
    ;            /* Wrap to beginning of list.  */
    ;            _tx_timer_current_ptr =  _tx_timer_list_start;
    ;
        MOV.L   #__tx_timer_list_start, R2          ; Pickup the timer list start ptr
        MOV.L   [R2], R2                            ; Pickup the start of the list
    ;    }
    ;
    __tx_timer_skip_wrap:
        MOV.L   #__tx_timer_current_ptr,R1     
        MOV.L   R2, [R1]                            ; Store in updated pointer in  _tx_timer_current_ptr  
        
    __tx_timer_done:
    ;
    ;    /* See if anything has expired.  */
    ;    if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
    ;    {
    ;
        MOV.L  #__tx_timer_expired_time_slice, R1   ; Pickup expired time slice addr
        MOV.L  [R1], R1                             ; Pickup expired time slice
        MOV.L   #__tx_timer_expired, R2             ; Pickup expired timer flag address
        MOV.L   [R2], R2                            ; Pickup actual flag
        OR      R1, R2                              ; Or flags together
        BEQ     __tx_timer_nothing_expired          ; If Z set, nothing has expired

    __tx_something_expired:
    ;    /* Did a timer expire?  */
    ;    if (_tx_timer_expired)
    ;    {
        MOV.L   #__tx_timer_expired,R1              ; Pickup expired flag address
        MOV.L   [R1], R1                            ; Pickup expired flag
        CMP     #0,R1                               ; Is the expired timer flag set?
        BEQ     __tx_timer_dont_activate            ; No, skip timer activation
    ;
    ;        /* Process timer expiration.  */
    ;        _tx_timer_expiration_process();
    ;
        BSR    __tx_timer_expiration_process        ; Call the timer expiration handling routine
    ;
    ;    }
    __tx_timer_dont_activate:
    ;
    ;    /* Did time slice expire?  */
    ;    if (_tx_timer_expired_time_slice)
    ;    {
    ;
        MOV.L   #__tx_timer_expired_time_slice, R1  ; Pickup time-slice expired flag addr
        MOV.L   [R1], R1                            ; Pickup actual flag
        CMP     #0,R1                               ; Has time-slice expired?
        BEQ      __tx_timer_not_ts_expiration       ; No, skip time-slice expiration
    ;
    ;        /* Time slice interrupted thread.  */
    ;        _tx_thread_time_slice();

        BSR     __tx_thread_time_slice              ; Call time-slice processing

    ;   /* Check if we must trigger a context switch. */
        MOV.L   #__tx_thread_preempt_disable, R1     ; Load prempt disable flag.
        MOV.L  [R1], R1
        CMP    #0, R1
        BNE    __tx_timer_not_ts_expiration          ; Skip if prempt disabled.

        MOV.L   #__tx_thread_execute_ptr, R1
        MOV.L  [R1], R1
        MOV.L   #__tx_thread_current_ptr, R2
        MOV.L  [R2], R2
        CMP    R1, R2
        BEQ    __tx_timer_not_ts_expiration

        MOV.L   #SWI0, R1
        MOV.L   #1, [R1]

    ;    }
    ;
    __tx_timer_not_ts_expiration:

    __tx_timer_nothing_expired:

        POPM R1-R5
        POPM R14-R15
    ;
        RTS                                         ; Return to point of interrupt
    ;
    ;}

     
    src/hardware_setup.c (FITのCMTモジュールと結合する都合によりコールバックルーチンです)

    /* CMT Timer callback used as the system tick. */
    void timer_callback(void * pdata)
    {
        _tx_timer_interrupt();
    }

    void platform_setup(void)
    {
        uint32_t chan;

        /* Create periodic timer for the system tick. */
        R_CMT_CreatePeriodic(TX_TIMER_TICKS_PER_SECOND, timer_callback, &chan);
        
    }

     
    libs/threadx/ports/rxv3/ccrx/src/tx_thread_schedule.src (こちらは割り込みルーチンです)

    ; Software triggered interrupt used to perform context switches.
    ; The priority of this interrupt is set to the lowest priority within
    ; tx_initialize_low_level() and triggered by ThreadX when calling
    ; _tx_thread_system_return().
    .RVECTOR 27, _tx_software_interrupt_entry
    .GLB _tx_software_interrupt_entry
    _tx_software_interrupt_entry:

        PUSHM R1-R2

        BSR __tx_thread_context_save

        BRA __tx_thread_context_restore

     

Children
No Data