| ;/*
|
| ; * 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
|
| ; *
|
| ; */
|
|
|
| #include <iom323.h>
|
|
|
| ; Declare all extern symbols here - including any ISRs that are referenced in
|
| ; the vector table.
|
|
|
| ; ISR functions
|
| ; -------------
|
| EXTERN SIG_OUTPUT_COMPARE1A
|
| EXTERN SIG_UART_RECV
|
| EXTERN SIG_UART_DATA
|
|
|
|
|
| ; Functions used by scheduler
|
| ; ---------------------------
|
| EXTERN vTaskSwitchContext
|
| EXTERN pxCurrentTCB
|
| EXTERN xTaskIncrementTick
|
| EXTERN uxCriticalNesting
|
|
|
| ; Functions implemented in this file
|
| ; ----------------------------------
|
| PUBLIC vPortYield
|
| PUBLIC vPortYieldFromTick
|
| 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 TIMER1_COMPA_vect ; Vector address
|
| jmp SIG_OUTPUT_COMPARE1A ; ISR
|
|
|
| ORG USART_RXC_vect ; Vector address
|
| jmp SIG_UART_RECV ; ISR
|
|
|
| ORG USART_UDRE_vect ; Vector address
|
| jmp SIG_UART_DATA ; ISR
|
|
|
|
|
| RSEG CODE
|
|
|
|
|
|
|
| ; 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, 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+ ; Next there is the SREG register.
|
| out SREG, r0
|
|
|
| ld r0, y+ ; Finally we have finished with r0, so restore r0.
|
|
|
| ENDM
|
|
|
|
|
|
|
| ; vPortYield() and vPortYieldFromTick()
|
| ; -------------------------------------
|
| ;
|
| ; 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:
|
| 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 ...
|
| ret ; ... 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
|
|
|