| ;/* |
| ; * FreeRTOS Kernel <DEVELOPMENT BRANCH> |
| ; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| ; * |
| ; * SPDX-License-Identifier: MIT |
| ; * |
| ; * Permission is hereby granted, free of charge, to any person obtaining a copy of |
| ; * this software and associated documentation files (the "Software"), to deal in |
| ; * the Software without restriction, including without limitation the rights to |
| ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| ; * the Software, and to permit persons to whom the Software is furnished to do so, |
| ; * subject to the following conditions: |
| ; * |
| ; * The above copyright notice and this permission notice shall be included in all |
| ; * copies or substantial portions of the Software. |
| ; * |
| ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| ; * |
| ; * https://www.FreeRTOS.org |
| ; * https://github.com/FreeRTOS |
| ; * |
| ; */ |
| ; Note: Select the correct include files for the device used by the application. |
| #include "FreeRTOSConfig.h" |
| ;------------------------------------------------------------------------------ |
| |
| ; Functions used by scheduler |
| ;------------------------------------------------------------------------------ |
| EXTERN vTaskSwitchContext |
| EXTERN xTaskIncrementTick |
| |
| ; Variables used by scheduler |
| ;------------------------------------------------------------------------------ |
| EXTERN pxCurrentTCB |
| EXTERN usCriticalNesting |
| |
| ; Functions implemented in this file |
| ;------------------------------------------------------------------------------ |
| PUBLIC vPortYield |
| PUBLIC vPortStart |
| |
| ; Security ID definition |
| ;------------------------------------------------------------------------------ |
| #define CG_SECURITY0 0FFH |
| #define CG_SECURITY1 0FFH |
| #define CG_SECURITY2 0FFH |
| #define CG_SECURITY3 0FFH |
| #define CG_SECURITY4 0FFH |
| #define CG_SECURITY5 0FFH |
| #define CG_SECURITY6 0FFH |
| #define CG_SECURITY7 0FFH |
| #define CG_SECURITY8 0FFH |
| #define CG_SECURITY9 0FFH |
| |
| ; Tick ISR Prototype |
| ;------------------------------------------------------------------------------ |
| PUBWEAK `??MD_INTTM0EQ0??INTVEC 640` |
| PUBLIC MD_INTTM0EQ0 |
| |
| MD_INTTM0EQ0 SYMBOL "MD_INTTM0EQ0" |
| `??MD_INTTM0EQ0??INTVEC 640` SYMBOL "??INTVEC 640", MD_INTTM0EQ0 |
| |
| ;------------------------------------------------------------------------------ |
| ; portSAVE_CONTEXT MACRO |
| ; Saves the context of the remaining general purpose registers |
| ; and the usCriticalNesting Value of the active Task onto the task stack |
| ; saves stack pointer to the TCB |
| ;------------------------------------------------------------------------------ |
| portSAVE_CONTEXT MACRO |
| #if configDATA_MODE == 1 ; Using the Tiny data model |
| prepare {r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30},76,sp ; save general purpose registers |
| sst.w r19,72[ep] |
| sst.w r18,68[ep] |
| sst.w r17,64[ep] |
| sst.w r16,60[ep] |
| sst.w r15,56[ep] |
| sst.w r14,52[ep] |
| sst.w r13,48[ep] |
| sst.w r12,44[ep] |
| sst.w r11,40[ep] |
| sst.w r10,36[ep] |
| sst.w r9,32[ep] |
| sst.w r8,28[ep] |
| sst.w r7,24[ep] |
| sst.w r6,20[ep] |
| sst.w r5,16[ep] |
| sst.w r4,12[ep] |
| #else ; Using the Small/Large data model |
| prepare {r20,r21,r22,r23,r24,r26,r27,r28,r29,r30},72,sp ; save general purpose registers |
| sst.w r19,68[ep] |
| sst.w r18,64[ep] |
| sst.w r17,60[ep] |
| sst.w r16,56[ep] |
| sst.w r15,52[ep] |
| sst.w r14,48[ep] |
| sst.w r13,44[ep] |
| sst.w r12,40[ep] |
| sst.w r11,36[ep] |
| sst.w r10,32[ep] |
| sst.w r9,28[ep] |
| sst.w r8,24[ep] |
| sst.w r7,20[ep] |
| sst.w r6,16[ep] |
| sst.w r5,12[ep] |
| #endif /* configDATA_MODE */ |
| sst.w r2,8[ep] |
| sst.w r1,4[ep] |
| MOVHI hi1(usCriticalNesting),r0,r1 ; save usCriticalNesting value to stack |
| ld.w lw1(usCriticalNesting)[r1],r2 |
| sst.w r2,0[ep] |
| MOVHI hi1(pxCurrentTCB),r0,r1 ; save SP to top of current TCB |
| ld.w lw1(pxCurrentTCB)[r1],r2 |
| st.w sp,0[r2] |
| ENDM |
| ;------------------------------------------------------------------------------ |
| |
| ;------------------------------------------------------------------------------ |
| ; portRESTORE_CONTEXT MACRO |
| ; Gets stack pointer from the current TCB |
| ; Restores the context of the usCriticalNesting value and general purpose |
| ; registers of the selected task from the task stack |
| ;------------------------------------------------------------------------------ |
| portRESTORE_CONTEXT MACRO |
| MOVHI hi1(pxCurrentTCB),r0,r1 ; get Stackpointer address |
| ld.w lw1(pxCurrentTCB)[r1],sp |
| MOV sp,r1 |
| ld.w 0[r1],sp ; load stackpointer |
| MOV sp,ep ; set stack pointer to element pointer |
| sld.w 0[ep],r1 ; load usCriticalNesting value from stack |
| MOVHI hi1(usCriticalNesting),r0,r2 |
| st.w r1,lw1(usCriticalNesting)[r2] |
| sld.w 4[ep],r1 ; restore general purpose registers |
| sld.w 8[ep],r2 |
| #if configDATA_MODE == 1 ; Using Tiny data model |
| sld.w 12[ep],r4 |
| sld.w 16[ep],r5 |
| sld.w 20[ep],r6 |
| sld.w 24[ep],r7 |
| sld.w 28[ep],r8 |
| sld.w 32[ep],r9 |
| sld.w 36[ep],r10 |
| sld.w 40[ep],r11 |
| sld.w 44[ep],r12 |
| sld.w 48[ep],r13 |
| sld.w 52[ep],r14 |
| sld.w 56[ep],r15 |
| sld.w 60[ep],r16 |
| sld.w 64[ep],r17 |
| sld.w 68[ep],r18 |
| sld.w 72[ep],r19 |
| dispose 76,{r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30} |
| #else ; Using Small/Large data model |
| sld.w 12[ep],r5 |
| sld.w 16[ep],r6 |
| sld.w 20[ep],r7 |
| sld.w 24[ep],r8 |
| sld.w 28[ep],r9 |
| sld.w 32[ep],r10 |
| sld.w 36[ep],r11 |
| sld.w 40[ep],r12 |
| sld.w 44[ep],r13 |
| sld.w 48[ep],r14 |
| sld.w 52[ep],r15 |
| sld.w 56[ep],r16 |
| sld.w 60[ep],r17 |
| sld.w 64[ep],r18 |
| sld.w 68[ep],r19 |
| dispose 72,{r20,r21,r22,r23,r24,r26,r27,r28,r29,r30} |
| #endif /* configDATA_MODE */ |
| ENDM |
| ;------------------------------------------------------------------------------ |
| |
| ;------------------------------------------------------------------------------ |
| ; Restore the context of the first task that is going to run. |
| ; |
| ; Input: NONE |
| ; |
| ; Call: CALL vPortStart |
| ; |
| ; Output: NONE |
| ;------------------------------------------------------------------------------ |
| RSEG CODE:CODE |
| vPortStart: |
| portRESTORE_CONTEXT ; Restore the context of whichever task the ... |
| ld.w 0[sp],lp |
| ldsr lp,5 ; restore PSW |
| DI |
| ld.w 4[sp],lp ; restore LP |
| ld.w 8[sp],lp ; restore LP |
| ADD 0x0C,sp ; set SP to right position |
| EI |
| jmp [lp] |
| ;------------------------------------------------------------------------------ |
| |
| ;------------------------------------------------------------------------------ |
| ; Port Yield function to check for a Task switch in the cooperative and |
| ; preemptive mode |
| ; |
| ; Input: NONE |
| ; |
| ; Call: CALL vPortYield |
| ; |
| ; Output: NONE |
| ;------------------------------------------------------------------------------ |
| |
| RSEG CODE:CODE |
| vPortYield: |
| |
| add -0x0C,sp ; prepare stack to save necessary values |
| st.w lp,8[sp] ; store LP to stack |
| stsr 0,r31 |
| st.w lp,4[sp] ; store EIPC to stack |
| stsr 1,lp |
| st.w lp,0[sp] ; store EIPSW to stack |
| portSAVE_CONTEXT ; Save the context of the current task. |
| jarl vTaskSwitchContext,lp ; Call the scheduler. |
| portRESTORE_CONTEXT ; Restore the context of whichever task the ... |
| ; ... scheduler decided should run. |
| ld.w 0[sp],lp ; restore EIPSW from stack |
| ldsr lp,1 |
| ld.w 4[sp],lp ; restore EIPC from stack |
| ldsr lp,0 |
| ld.w 8[sp],lp ; restore LP from stack |
| add 0x0C,sp ; set SP to right position |
| |
| RETI |
| |
| ;------------------------------------------------------------------------------ |
| |
| ;------------------------------------------------------------------------------ |
| ; Perform the necessary steps of the Tick Count Increment and Task Switch |
| ; depending on the chosen kernel configuration |
| ; |
| ; Input: NONE |
| ; |
| ; Call: ISR |
| ; |
| ; Output: NONE |
| ;------------------------------------------------------------------------------ |
| #if configUSE_PREEMPTION == 1 ; use preemptive kernel mode |
| |
| MD_INTTM0EQ0: |
| |
| add -0x0C,sp ; prepare stack to save necessary values |
| st.w lp,8[sp] ; store LP to stack |
| stsr 0,r31 |
| st.w lp,4[sp] ; store EIPC to stack |
| stsr 1,lp |
| st.w lp,0[sp] ; store EIPSW to stack |
| portSAVE_CONTEXT ; Save the context of the current task. |
| jarl xTaskIncrementTick,lp ; Call the timer tick function. |
| jarl vTaskSwitchContext,lp ; Call the scheduler. |
| portRESTORE_CONTEXT ; Restore the context of whichever task the ... |
| ; ... scheduler decided should run. |
| ld.w 0[sp],lp ; restore EIPSW from stack |
| ldsr lp,1 |
| ld.w 4[sp],lp ; restore EIPC from stack |
| ldsr lp,0 |
| ld.w 8[sp],lp ; restore LP from stack |
| add 0x0C,sp ; set SP to right position |
| |
| RETI |
| ;------------------------------------------------------------------------------ |
| #else ; use cooperative kernel mode |
| |
| MD_INTTM0EQ0: |
| prepare {lp,ep},8,sp |
| sst.w r1,4[ep] |
| sst.w r5,0[ep] |
| jarl xTaskIncrementTick,lp ; Call the timer tick function. |
| sld.w 0[ep],r5 |
| sld.w 4[ep],r1 |
| dispose 8,{lp,ep} |
| RETI |
| #endif /* configUSE_PREEMPTION */ |
| |
| ;------------------------------------------------------------------------------ |
| COMMON INTVEC:CODE:ROOT(2) |
| ORG 640 |
| `??MD_INTTM0EQ0??INTVEC 640`: |
| JR MD_INTTM0EQ0 |
| |
| RSEG NEAR_ID:CONST:SORT:NOROOT(2) |
| `?<Initializer for usCriticalNesting>`: |
| DW 10 |
| |
| COMMON INTVEC:CODE:ROOT(2) |
| ORG 40H |
| `??vPortYield??INTVEC 40`: |
| JR vPortYield |
| |
| ;------------------------------------------------------------------------------ |
| ; set microcontroller security ID |
| |
| COMMON INTVEC:CODE:ROOT(2) |
| ORG 70H |
| `SECUID`: |
| DB CG_SECURITY0 |
| DB CG_SECURITY1 |
| DB CG_SECURITY2 |
| DB CG_SECURITY3 |
| DB CG_SECURITY4 |
| DB CG_SECURITY5 |
| DB CG_SECURITY6 |
| DB CG_SECURITY7 |
| DB CG_SECURITY8 |
| DB CG_SECURITY9 |
| |
| |
| END |