123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- ;/*
- ; * 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
- ; *
- ; */
- #include "porthardware.h"
- ; Declare all extern symbols here - including any ISRs that are referenced in
- ; the vector table.
- ; ISR functions
- ; -------------
- EXTERN TICK_INT
- ; Functions used by scheduler
- ; ---------------------------
- EXTERN vTaskSwitchContext
- EXTERN pxCurrentTCB
- EXTERN xTaskIncrementTick
- EXTERN uxCriticalNesting
- ; Functions implemented in this file
- ; ----------------------------------
- PUBLIC vPortYield
- PUBLIC vPortYieldFromTick
- PUBLIC vPortYieldFromISR
- PUBLIC vPortStart
- ; Interrupt vector table.
- ; -----------------------
- ;
- ; For simplicity the RTOS tick interrupt routine uses the __task keyword.
- ; As the IAR compiler does not permit a function to be declared using both
- ; __task and __interrupt, the use of __task necessitates that the interrupt
- ; vector table be setup manually.
- ;
- ; To write an ISR, implement the ISR function using the __interrupt keyword
- ; but do not install the interrupt using the "#pragma vector=ABC" method.
- ; Instead manually place the name of the ISR in the vector table using an
- ; ORG and jmp instruction as demonstrated below.
- ; You will also have to add an EXTERN statement at the top of the file.
- ASEG
- ORG TICK_INT_vect ; Vector address
- jmp TICK_INT ; ISR
- RSEG CODE
- CLR_INT MACRO FLAG_REG, FLAG_MASK
- st -y, r16
- ldi r16, FLAG_MASK
- sts FLAG_REG, r16
- ld r16, y+
-
- ENDM
- ; Saving and Restoring a Task Context and Task Switching
- ; ------------------------------------------------------
- ;
- ; The IAR compiler does not fully support inline assembler, so saving and
- ; restoring a task context has to be written in an asm file.
- ;
- ; vPortYield() and vPortYieldFromTick() are usually written in C. Doing
- ; so in this case would required calls to be made to portSAVE_CONTEXT() and
- ; portRESTORE_CONTEXT(). This is dis-advantageous as the context switch
- ; function would require two extra jump and return instructions over the
- ; WinAVR equivalent.
- ;
- ; To avoid this I have opted to implement both vPortYield() and
- ; vPortYieldFromTick() in this assembly file. For convenience
- ; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
- portSAVE_CONTEXT MACRO
- st -y, r0 ; First save the r0 register - we need to use this.
- in r0, SREG ; Obtain the SREG value so we can disable interrupts...
- cli ; ... as soon as possible.
- st -y, r0 ; Store the SREG as it was before we disabled interrupts.
- in r0, RAMPZ
- st -y, r0
- in r0, SPL ; Next store the hardware stack pointer. The IAR...
- st -y, r0 ; ... compiler uses the hardware stack as a call stack ...
- in r0, SPH ; ... only.
- st -y, r0
- st -y, r1 ; Now store the rest of the registers. Dont store the ...
- st -y, r2 ; ... the Y register here as it is used as the software
- st -y, r3 ; stack pointer and will get saved into the TCB.
- st -y, r4
- st -y, r5
- st -y, r6
- st -y, r7
- st -y, r8
- st -y, r9
- st -y, r10
- st -y, r11
- st -y, r12
- st -y, r13
- st -y, r14
- st -y, r15
- st -y, r16
- st -y, r17
- st -y, r18
- st -y, r19
- st -y, r20
- st -y, r21
- st -y, r22
- st -y, r23
- st -y, r24
- st -y, r25
- st -y, r26
- st -y, r27
- st -y, r30
- st -y, r31
- lds r0, uxCriticalNesting
- st -y, r0 ; Store the critical nesting counter.
- lds r26, pxCurrentTCB ; Finally save the software stack pointer (Y ...
- lds r27, pxCurrentTCB + 1 ; ... register) into the TCB.
- st x+, r28
- st x+, r29
- ENDM
- portRESTORE_CONTEXT MACRO
- lds r26, pxCurrentTCB
- lds r27, pxCurrentTCB + 1 ; Restore the software stack pointer from ...
- ld r28, x+ ; the TCB into the software stack pointer (...
- ld r29, x+ ; ... the Y register).
- ld r0, y+
- sts uxCriticalNesting, r0
- ld r31, y+ ; Restore the registers down to R0. The Y
- ld r30, y+ ; register is missing from this list as it
- ld r27, y+ ; has already been restored.
- ld r26, y+
- ld r25, y+
- ld r24, y+
- ld r23, y+
- ld r22, y+
- ld r21, y+
- ld r20, y+
- ld r19, y+
- ld r18, y+
- ld r17, y+
- ld r16, y+
- ld r15, y+
- ld r14, y+
- ld r13, y+
- ld r12, y+
- ld r11, y+
- ld r10, y+
- ld r9, y+
- ld r8, y+
- ld r7, y+
- ld r6, y+
- ld r5, y+
- ld r4, y+
- ld r3, y+
- ld r2, y+
- ld r1, y+
- ld r0, y+ ; The next thing on the stack is the ...
- out SPH, r0 ; ... hardware stack pointer.
- ld r0, y+
- out SPL, r0
- ld r0, y+
- out RAMPZ, r0
- ld r0, y+ ; Next there is the SREG register.
- out SREG, r0
- ld r0, y+ ; Finally we have finished with r0, so restore r0.
- ENDM
- ; vPortYield(), vPortYieldFromTick() and vPortYieldFromISR()
- ; -------------------------------------
- ;
- ; Manual and preemptive context switch functions respectively.
- ; The IAR compiler does not fully support inline assembler,
- ; so these are implemented here rather than the more usually
- ; place of within port.c.
- vPortYield:
- portSAVE_CONTEXT ; Save the context of the current task.
- call vTaskSwitchContext ; Call the scheduler.
- portRESTORE_CONTEXT ; Restore the context of whichever task the ...
- ret ; ... scheduler decided should run.
- vPortYieldFromTick:
- CLR_INT INT_FLAGS, INT_MASK ; Clear tick interrupt flag
- portSAVE_CONTEXT ; Save the context of the current task.
- call xTaskIncrementTick ; Call the timer tick function.
- tst r16
- breq SkipTaskSwitch
- call vTaskSwitchContext ; Call the scheduler.
- SkipTaskSwitch:
- portRESTORE_CONTEXT ; Restore the context of whichever task the ...
- reti ; ... scheduler decided should run.
- vPortYieldFromISR:
- portSAVE_CONTEXT ; Save the context of the current task.
- call vTaskSwitchContext ; Call the scheduler.
- portRESTORE_CONTEXT ; Restore the context of whichever task the ...
- reti ; ... scheduler decided should run.
- ; vPortStart()
- ; ------------
- ;
- ; Again due to the lack of inline assembler, this is required
- ; to get access to the portRESTORE_CONTEXT macro.
- vPortStart:
- portRESTORE_CONTEXT
- ret
- ; Just a filler for unused interrupt vectors.
- vNoISR:
- reti
- END
|