Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HAL_CM3.c Source File

HAL_CM3.c

Go to the documentation of this file.
00001 /**
00002  * @file    HAL_CM3.c
00003  * @brief   HAL for Cortex-M3
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "rt_TypeDef.h"
00023 #include "RTX_Config.h"
00024 #include "rt_System.h"
00025 #include "rt_HAL_CM.h"
00026 #include "rt_Task.h"
00027 #include "rt_List.h"
00028 #include "rt_MemBox.h"
00029 
00030 
00031 /*----------------------------------------------------------------------------
00032  *      Global Variables
00033  *---------------------------------------------------------------------------*/
00034 
00035 BIT dbg_msg;
00036 
00037 /*----------------------------------------------------------------------------
00038  *      Functions
00039  *---------------------------------------------------------------------------*/
00040 
00041 
00042 /*--------------------------- rt_set_PSP ------------------------------------*/
00043 
00044 __asm void rt_set_PSP (U32 stack) {
00045         MSR     PSP,R0
00046         BX      LR
00047 }
00048 
00049 
00050 /*--------------------------- rt_get_PSP ------------------------------------*/
00051 
00052 __asm U32 rt_get_PSP (void) {
00053         MRS     R0,PSP
00054         BX      LR
00055 }
00056 
00057 
00058 /*--------------------------- os_set_env ------------------------------------*/
00059 
00060 __asm void os_set_env (void) {
00061    /* Switch to Unprivileged/Privileged Thread mode, use PSP. */
00062         MOV     R0,SP                   ; PSP = MSP
00063         MSR     PSP,R0
00064         LDR     R0,=__cpp(&os_flags)
00065         LDRB    R0,[R0]
00066         LSLS    R0,#31
00067         MOVNE   R0,#0x02                ; Privileged Thread mode, use PSP
00068         MOVEQ   R0,#0x03                ; Unprivileged Thread mode, use PSP
00069         MSR     CONTROL,R0
00070         BX      LR
00071 
00072         ALIGN
00073 }
00074 
00075 
00076 /*--------------------------- _alloc_box ------------------------------------*/
00077 
00078 __asm void *_alloc_box (void *box_mem) {
00079    /* Function wrapper for Unprivileged/Privileged mode. */
00080         LDR     R12,=__cpp(rt_alloc_box)
00081         MRS     R3,IPSR
00082         LSLS    R3,#24
00083         BXNE    R12
00084         MRS     R3,CONTROL
00085         LSLS    R3,#31
00086         BXEQ    R12
00087         SVC     0
00088         BX      LR
00089 
00090         ALIGN
00091 }
00092 
00093 
00094 /*--------------------------- _free_box -------------------------------------*/
00095 
00096 __asm int _free_box (void *box_mem, void *box) {
00097    /* Function wrapper for Unprivileged/Privileged mode. */
00098         LDR     R12,=__cpp(rt_free_box)
00099         MRS     R3,IPSR
00100         LSLS    R3,#24
00101         BXNE    R12
00102         MRS     R3,CONTROL
00103         LSLS    R3,#31
00104         BXEQ    R12
00105         SVC     0
00106         BX      LR
00107 
00108         ALIGN
00109 }
00110 
00111 
00112 /*-------------------------- SVC_Handler ------------------------------------*/
00113 
00114 __asm void SVC_Handler (void) {
00115         PRESERVE8
00116 
00117 #ifdef  IFX_XMC4XXX
00118         EXPORT  SVC_Handler_Veneer
00119 SVC_Handler_Veneer
00120 #endif
00121 
00122         IMPORT  SVC_Count
00123         IMPORT  SVC_Table
00124         IMPORT  rt_stk_check
00125 
00126         MRS     R0,PSP                  ; Read PSP
00127         LDR     R1,[R0,#24]             ; Read Saved PC from Stack
00128         LDRB    R1,[R1,#-2]             ; Load SVC Number
00129         CBNZ    R1,SVC_User
00130 
00131         LDM     R0,{R0-R3,R12}          ; Read R0-R3,R12 from stack
00132         BLX     R12                     ; Call SVC Function
00133 
00134         MRS     R12,PSP                 ; Read PSP
00135         LDR     R3,=__cpp(&os_tsk)
00136         LDM     R3,{R1,R2}              ; os_tsk.run, os_tsk.new
00137         CMP     R1,R2
00138         BEQ     SVC_Exit                ; no task switch
00139 
00140         CBZ     R1,SVC_Restore          ; Runtask deleted?
00141 
00142         PUSH    {R2,R3}
00143         MOV     R3,#1
00144         STRB    R3,[R1,#TCB_RETUPD]     ; os_tsk.run->ret_upd = 1
00145         STMDB   R12!,{R4-R11}           ; Save Old context
00146         STR     R12,[R1,#TCB_TSTACK]    ; Update os_tsk.run->tsk_stack
00147         BL      rt_stk_check            ; Check for Stack overflow
00148         POP     {R2,R3}
00149 
00150 SVC_Restore
00151         STR     R2,[R3]                 ; os_tsk.run = os_tsk.new
00152 
00153         LDR     R12,[R2,#TCB_TSTACK]    ; os_tsk.new->tsk_stack
00154         LDMIA   R12!,{R4-R11}           ; Restore New Context
00155         LDRB    R3,[R2,#TCB_RETUPD]     ; Update ret_val?
00156         MSR     PSP,R12                 ; Write PSP
00157 
00158         CBZ     R3,SVC_Return
00159         LDRB    R0,[R2,#TCB_RETVAL]     ; Write os_tsk.new->ret_val
00160 
00161 SVC_Exit
00162         STR     R0,[R12]                ; Function return value
00163 
00164 SVC_Return
00165         MVN     LR,#:NOT:0xFFFFFFFD     ; set EXC_RETURN value
00166 #ifdef  IFX_XMC4XXX
00167         PUSH    {LR}
00168         POP     {PC}
00169 #else
00170         BX      LR
00171 #endif
00172 
00173         /*------------------- User SVC ------------------------------*/
00174 
00175 SVC_User
00176         PUSH    {R4,LR}                 ; Save Registers
00177         LDR     R2,=SVC_Count
00178         LDR     R2,[R2]
00179         CMP     R1,R2
00180         BHI     SVC_Done                ; Overflow
00181 
00182         LDR     R4,=SVC_Table-4
00183         LDR     R4,[R4,R1,LSL #2]       ; Load SVC Function Address
00184 
00185         LDM     R0,{R0-R3,R12}          ; Read R0-R3,R12 from stack
00186         BLX     R4                      ; Call SVC Function
00187 
00188         MRS     R12,PSP
00189         STM     R12,{R0-R3}             ; Function return values
00190 SVC_Done
00191         POP     {R4,PC}                 ; RETI
00192 
00193         ALIGN
00194 }
00195 
00196 
00197 /*-------------------------- PendSV_Handler ---------------------------------*/
00198 
00199 __asm void PendSV_Handler (void) {
00200         PRESERVE8
00201 
00202 #ifdef  IFX_XMC4XXX
00203         EXPORT  PendSV_Handler_Veneer
00204 PendSV_Handler_Veneer
00205 #endif
00206 
00207         BL      __cpp(rt_pop_req)
00208 
00209 Sys_Switch
00210         LDR     R3,=__cpp(&os_tsk)
00211         LDM     R3,{R1,R2}              ; os_tsk.run, os_tsk.new
00212         CMP     R1,R2
00213         BEQ     Sys_Exit
00214 
00215         PUSH    {R2,R3}
00216         MOV     R3,#0
00217         STRB    R3,[R1,#TCB_RETUPD]     ; os_tsk.run->ret_upd = 0
00218         MRS     R12,PSP                 ; Read PSP
00219         STMDB   R12!,{R4-R11}           ; Save Old context
00220         STR     R12,[R1,#TCB_TSTACK]    ; Update os_tsk.run->tsk_stack
00221         BL      rt_stk_check            ; Check for Stack overflow
00222 
00223         POP     {R2,R3}
00224         STR     R2,[R3]                 ; os_tsk.run = os_tsk.new
00225 
00226         LDR     R12,[R2,#TCB_TSTACK]    ; os_tsk.new->tsk_stack
00227         LDMIA   R12!,{R4-R11}           ; Restore New Context
00228         MSR     PSP,R12                 ; Write PSP
00229 
00230         LDRB    R3,[R2,#TCB_RETUPD]     ; Update ret_val?
00231         CBZ     R3,Sys_Exit
00232         LDRB    R3,[R2,#TCB_RETVAL]     ; Write os_tsk.new->ret_val
00233         STR     R3,[R12]
00234 Sys_Exit
00235         MVN     LR,#:NOT:0xFFFFFFFD     ; set EXC_RETURN value
00236 #ifdef  IFX_XMC4XXX
00237         PUSH    {LR}
00238         POP     {PC}
00239 #else
00240         BX      LR                      ; Return to Thread Mode
00241 #endif
00242 
00243         ALIGN
00244 }
00245 
00246 
00247 /*-------------------------- SysTick_Handler --------------------------------*/
00248 
00249 __asm void SysTick_Handler (void) {
00250         PRESERVE8
00251 
00252 #ifdef  IFX_XMC4XXX
00253         EXPORT  SysTick_Handler_Veneer
00254 SysTick_Handler_Veneer
00255 #endif
00256 
00257         BL      __cpp(rt_systick)
00258         B       Sys_Switch
00259 
00260         ALIGN
00261 }
00262 
00263 
00264 /*-------------------------- OS_Tick_Handler --------------------------------*/
00265 
00266 __asm void OS_Tick_Handler (void) {
00267         PRESERVE8
00268 
00269         BL      __cpp(os_tick_irqack)
00270         BL      __cpp(rt_systick)
00271         B       Sys_Switch
00272 
00273         ALIGN
00274 }
00275 
00276 
00277 /*--------------------------- rt_init_stack ---------------------------------*/
00278 
00279 void rt_init_stack (P_TCB p_TCB, FUNCP task_body) {
00280   /* Prepare TCB and saved context for a first time start of a task. */
00281   U32 *stk,i,size;
00282 
00283   /* Prepare a complete interrupt frame for first task start */
00284   size = p_TCB->priv_stack >> 2;
00285   if (size == 0) {
00286     size = (U16)os_stackinfo >> 2;
00287   }
00288 
00289   /* Write to the top of stack. */
00290   stk = &p_TCB->stack[size];
00291 
00292   /* Auto correct to 8-byte ARM stack alignment. */
00293   if ((U32)stk & 0x04) {
00294     stk--;
00295   }
00296 
00297   stk -= 16;
00298 
00299   /* Default xPSR and initial PC */
00300   stk[15] = INITIAL_xPSR;
00301   stk[14] = (U32)task_body;
00302 
00303   /* Clear R1-R12,LR registers. */
00304   for (i = 0; i < 14; i++) {
00305     stk[i] = 0;
00306   }
00307 
00308   /* Assign a void pointer to R0. */
00309   stk[8] = (U32)p_TCB->msg;
00310 
00311   /* Initial Task stack pointer. */
00312   p_TCB->tsk_stack = (U32)stk;
00313 
00314   /* Task entry point. */
00315   p_TCB->ptask = task_body;
00316 
00317   /* Set a magic word for checking of stack overflow. */
00318   p_TCB->stack[0] = MAGIC_WORD;
00319 }
00320 
00321 
00322 /*--------------------------- dbg_init --------------------------------------*/
00323 
00324 void dbg_init (void) {
00325   if ((DEMCR & DEMCR_TRCENA)     &&
00326       (ITM_CONTROL & ITM_ITMENA) &&
00327       (ITM_ENABLE & (1UL << 31))) {
00328     dbg_msg = __TRUE;
00329   }
00330 }
00331 
00332 
00333 /*--------------------------- dbg_task_notify -------------------------------*/
00334 
00335 void dbg_task_notify (P_TCB p_tcb, BOOL create) {
00336   while (ITM_PORT31_U32 == 0);
00337   ITM_PORT31_U32 = (U32)p_tcb->ptask;
00338   while (ITM_PORT31_U32 == 0);
00339   ITM_PORT31_U16 = (create << 8) | p_tcb->task_id;
00340 }
00341 
00342 
00343 /*--------------------------- dbg_task_switch -------------------------------*/
00344 
00345 void dbg_task_switch (U32 task_id) {
00346   while (ITM_PORT31_U32 == 0);
00347   ITM_PORT31_U8 = task_id;
00348 }
00349 
00350 
00351 /*----------------------------------------------------------------------------
00352  * end of file
00353  *---------------------------------------------------------------------------*/
00354