123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- * FreeRTOS Kernel V10.4.6
- * 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
- *
- */
- .file "portASM.S"
- #include "FreeRTOSConfig.h"
- #include "ISR_Support.h"
- .extern pxCurrentTCB
- .extern vTaskSwitchContext
- .extern vPortCentralInterruptHandler
- .extern xTaskIncrementTick
- .extern vPortAPICErrorHandler
- .extern pucPortTaskFPUContextBuffer
- .extern ulPortYieldPending
- .global vPortStartFirstTask
- .global vPortCentralInterruptWrapper
- .global vPortAPICErrorHandlerWrapper
- .global vPortTimerHandler
- .global vPortYieldCall
- .global vPortAPICSpuriousHandler
- .text
- /*-----------------------------------------------------------*/
- .align 4
- .func vPortYieldCall
- vPortYieldCall:
- /* Save general purpose registers. */
- pusha
- .if configSUPPORT_FPU == 1
- /* If the task has a buffer allocated to save the FPU context then save
- the FPU context now. */
- movl pucPortTaskFPUContextBuffer, %eax
- test %eax, %eax
- je 1f
- fnsave ( %eax )
- fwait
- 1:
- /* Save the address of the FPU context, if any. */
- push pucPortTaskFPUContextBuffer
- .endif /* configSUPPORT_FPU */
- /* Find the TCB. */
- movl pxCurrentTCB, %eax
- /* Stack location is first item in the TCB. */
- movl %esp, (%eax)
- call vTaskSwitchContext
- /* Find the location of pxCurrentTCB again - a callee saved register could
- be used in place of eax to prevent this second load, but that then relies
- on the compiler and other asm code. */
- movl pxCurrentTCB, %eax
- movl (%eax), %esp
- .if configSUPPORT_FPU == 1
- /* Restore address of task's FPU context buffer. */
- pop pucPortTaskFPUContextBuffer
- /* If the task has a buffer allocated in which its FPU context is saved,
- then restore it now. */
- movl pucPortTaskFPUContextBuffer, %eax
- test %eax, %eax
- je 1f
- frstor ( %eax )
- 1:
- .endif
- popa
- iret
- .endfunc
- /*-----------------------------------------------------------*/
- .align 4
- .func vPortStartFirstTask
- vPortStartFirstTask:
- /* Find the TCB. */
- movl pxCurrentTCB, %eax
- /* Stack location is first item in the TCB. */
- movl (%eax), %esp
- /* Restore FPU context flag. */
- .if configSUPPORT_FPU == 1
- pop pucPortTaskFPUContextBuffer
- .endif /* configSUPPORT_FPU */
- /* Restore general purpose registers. */
- popa
- iret
- .endfunc
- /*-----------------------------------------------------------*/
- .align 4
- .func vPortAPICErrorHandlerWrapper
- vPortAPICErrorHandlerWrapper:
- pusha
- call vPortAPICErrorHandler
- popa
- /* EOI. */
- movl $0x00, (0xFEE000B0)
- iret
- .endfunc
- /*-----------------------------------------------------------*/
- .align 4
- .func vPortTimerHandler
- vPortTimerHandler:
- /* Save general purpose registers. */
- pusha
- /* Interrupts are not nested, so save the rest of the task context. */
- .if configSUPPORT_FPU == 1
- /* If the task has a buffer allocated to save the FPU context then save the
- FPU context now. */
- movl pucPortTaskFPUContextBuffer, %eax
- test %eax, %eax
- je 1f
- fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
- fwait
- 1:
- /* Save the address of the FPU context, if any. */
- push pucPortTaskFPUContextBuffer
- .endif /* configSUPPORT_FPU */
- /* Find the TCB. */
- movl pxCurrentTCB, %eax
- /* Stack location is first item in the TCB. */
- movl %esp, (%eax)
- /* Switch stacks. */
- movl ulTopOfSystemStack, %esp
- movl %esp, %ebp
- /* Increment nesting count. */
- add $1, ulInterruptNesting
- call xTaskIncrementTick
- sti
- /* Is a switch to another task required? */
- test %eax, %eax
- je _skip_context_switch
- cli
- call vTaskSwitchContext
- _skip_context_switch:
- cli
- /* Decrement the variable used to determine if a switch to a system
- stack is necessary. */
- sub $1, ulInterruptNesting
- /* Stack location is first item in the TCB. */
- movl pxCurrentTCB, %eax
- movl (%eax), %esp
- .if configSUPPORT_FPU == 1
- /* Restore address of task's FPU context buffer. */
- pop pucPortTaskFPUContextBuffer
- /* If the task has a buffer allocated in which its FPU context is saved,
- then restore it now. */
- movl pucPortTaskFPUContextBuffer, %eax
- test %eax, %eax
- je 1f
- frstor ( %eax )
- 1:
- .endif
- popa
- /* EOI. */
- movl $0x00, (0xFEE000B0)
- iret
- .endfunc
- /*-----------------------------------------------------------*/
- .if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1
- .align 4
- .func vPortCentralInterruptWrapper
- vPortCentralInterruptWrapper:
- portFREERTOS_INTERRUPT_ENTRY
- movl $0xFEE00170, %eax /* Highest In Service Register (ISR) long word. */
- movl $8, %ecx /* Loop counter. */
- next_isr_long_word:
- test %ecx, %ecx /* Loop counter reached 0? */
- je wrapper_epilogue /* Looked at all ISR registers without finding a bit set. */
- sub $1, %ecx /* Sub 1 from loop counter. */
- movl (%eax), %ebx /* Load next ISR long word. */
- sub $0x10, %eax /* Point to next ISR long word in case no bits are set in the current long word. */
- test %ebx, %ebx /* Are there any bits set? */
- je next_isr_long_word /* Look at next ISR long word if no bits were set. */
- sti
- bsr %ebx, %ebx /* A bit was set, which one? */
- movl $32, %eax /* Destination operand for following multiplication. */
- mul %ecx /* Calculate base vector for current register, 32 vectors per register. */
- add %ebx, %eax /* Add bit offset into register to get final vector number. */
- push %eax /* Vector number is function parameter. */
- call vPortCentralInterruptHandler
- pop %eax /* Remove parameter. */
- wrapper_epilogue:
- portFREERTOS_INTERRUPT_EXIT
- .endfunc
- .endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
- /*-----------------------------------------------------------*/
- .align 4
- .func vPortAPISpuriousHandler
- vPortAPICSpuriousHandler:
- iret
- .endfunc
- .end
|