;/*
;    FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
;
;    ***************************************************************************
;    *                                                                         *
;    * If you are:                                                             *
;    *                                                                         *
;    *    + New to FreeRTOS,                                                   *
;    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
;    *    + Looking for basic training,                                        *
;    *    + Wanting to improve your FreeRTOS skills and productivity           *
;    *                                                                         *
;    * then take a look at the FreeRTOS eBook                                  *
;    *                                                                         *
;    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
;    *                  http://www.FreeRTOS.org/Documentation                  *
;    *                                                                         *
;    * A pdf reference manual is also available.  Both are usually delivered   *
;    * to your inbox within 20 minutes to two hours when purchased between 8am *
;    * and 8pm GMT (although please allow up to 24 hours in case of            *
;    * exceptional circumstances).  Thank you for your support!                *
;    *                                                                         *
;    ***************************************************************************
;
;    This file is part of the FreeRTOS distribution.
;
;    FreeRTOS is free software; you can redistribute it and/or modify it under
;    the terms of the GNU General Public License (version 2) as published by the
;    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
;    ***NOTE*** The exception to the GPL is included to allow you to distribute
;    a combined work that includes FreeRTOS without being obliged to provide the
;    source code for proprietary components outside of the FreeRTOS kernel.
;    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
;    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
;    more details. You should have received a copy of the GNU General Public 
;    License and the FreeRTOS license exception along with FreeRTOS; if not it 
;    can be viewed here: http://www.freertos.org/a00114.html and also obtained 
;    by writing to Richard Barry, contact details for whom are available on the
;    FreeRTOS WEB site.
;
;    1 tab == 4 spaces!
;
;    http://www.FreeRTOS.org - Documentation, latest information, license and
;    contact details.
;
;    http://www.SafeRTOS.com - A version that is certified for use in safety
;    critical systems.
;
;    http://www.OpenRTOS.com - Commercial support, development, porting,
;    licensing and training services.
;*/

#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 vTaskIncrementTick
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 vTaskIncrementTick		; Call the timer tick function.
	call vTaskSwitchContext		; Call the scheduler.
	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

