RL78 GCC: Save and restore all register banks.

This commit is contained in:
Richard Barry 2013-03-17 09:27:18 +00:00
parent 3b9d0819c9
commit 3b1ff85222
13 changed files with 696 additions and 422 deletions

View file

@ -72,8 +72,6 @@
mission critical applications that require provable dependability.
*/
/*_RB_ #include "FreeRTOSConfig.h" */
/* Variables used by scheduler */
.extern _pxCurrentTCB
.extern _usCriticalNesting
@ -86,32 +84,47 @@
*/
.macro portSAVE_CONTEXT
SEL RB0
/* Save AX Register to stack. */
PUSH AX
PUSH HL
#if __DATA_MODEL__ == __DATA_MODEL_FAR__
PUSH AX
PUSH HL
/* Save CS register. */
MOV A, CS
XCH A, X
MOV A, CS
XCH A, X
/* Save ES register. */
MOV A, ES
PUSH AX
#else
/* Save CS register. */
MOV A, CS
PUSH AX
#endif
/* Save the remaining general purpose registers. */
PUSH DE
PUSH BC
MOV A, ES
PUSH AX
/* Save the remaining general purpose registers from bank 0. */
PUSH DE
PUSH BC
/* Save the other register banks - only necessary in the GCC port. */
SEL RB1
PUSH AX
PUSH BC
PUSH DE
PUSH HL
SEL RB2
PUSH AX
PUSH BC
PUSH DE
PUSH HL
SEL RB3
PUSH AX
PUSH BC
PUSH DE
PUSH HL
SEL RB0
/* Save the usCriticalNesting value. */
MOVW AX, !_usCriticalNesting
PUSH AX
MOVW AX, !_usCriticalNesting
PUSH AX
/* Save the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, SP
MOVW [HL], AX
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, SP
MOVW [HL], AX
/* Switch stack pointers. */
movw sp,#_stack /* Set stack pointer */
.endm
@ -123,33 +136,46 @@
* of the selected task from the task stack
*/
.macro portRESTORE_CONTEXT MACRO
SEL RB0
/* Restore the Stack pointer. */
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, [HL]
MOVW SP, AX
MOVW AX, !_pxCurrentTCB
MOVW HL, AX
MOVW AX, [HL]
MOVW SP, AX
/* Restore usCriticalNesting value. */
POP AX
MOVW !_usCriticalNesting, AX
POP AX
MOVW !_usCriticalNesting, AX
/* Restore the alternative register banks - only necessary in the GCC
port. */
SEL RB3
POP HL
POP DE
POP BC
POP AX
SEL RB2
POP HL
POP DE
POP BC
POP AX
SEL RB1
POP HL
POP DE
POP BC
POP AX
SEL RB0
/* Restore the necessary general purpose registers. */
POP BC
POP DE
#if __DATA_MODEL__ == __DATA_MODEL_FAR__
POP BC
POP DE
/* Restore the ES register. */
POP AX
MOV ES, A
POP AX
MOV ES, A
/* Restore the CS register. */
XCH A, X
MOV CS, A
#else
POP AX
/* Restore the CS register. */
MOV CS, A
#endif
XCH A, X
MOV CS, A
/* Restore general purpose register HL. */
POP HL
POP HL
/* Restore AX. */
POP AX
POP AX
.endm

View file

@ -85,7 +85,7 @@ interrupts don't accidentally become enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING ( ( unsigned short ) 10 )
/* Initial PSW value allocated to a newly created task.
* 1100011000000000
* 11000110
* ||||||||-------------- Fill byte
* |||||||--------------- Carry Flag cleared
* |||||----------------- In-service priority Flags set to low level
@ -95,7 +95,8 @@ interrupts don't accidentally become enabled before the scheduler is started. */
* |--------------------- Zero Flag set
* ---------------------- Global Interrupt Flag set (enabled)
*/
#define portPSW ( 0xc6UL )
//#define portPSW ( 0xc6UL )
#define portPSW ( 0x86UL )
/* The address of the pxCurrentTCB variable, but don't know or need to know its
type. */
@ -137,67 +138,24 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
{
unsigned long *pulLocal;
#if __DATA_MODEL__ == __DATA_MODEL_FAR__
{
/* Parameters are passed in on the stack, and written using a 32bit value
hence a space is left for the second two bytes. */
pxTopOfStack--;
/* Write in the parameter value. */
pulLocal = ( unsigned long * ) pxTopOfStack;
*pulLocal = ( unsigned long ) pvParameters;
pxTopOfStack--;
/* These values are just spacers. The return address of the function
would normally be written here. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;
pxTopOfStack--;
/* The start address / PSW value is also written in as a 32bit value,
so leave a space for the second two bytes. */
pxTopOfStack--;
/* Task function start address combined with the PSW. */
pulLocal = ( unsigned long * ) pxTopOfStack;
*pulLocal = ( ( ( unsigned long ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--;
/* An initial value for the AX register. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x1111;
pxTopOfStack--;
}
#else
{
/* Task function address is written to the stack first. As it is
written as a 32bit value a space is left on the stack for the second
two bytes. */
pxTopOfStack--;
/* Task function start address combined with the PSW. */
pulLocal = ( unsigned long * ) pxTopOfStack;
*pulLocal = ( ( ( unsigned long ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--;
/* The parameter is passed in AX. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
pxTopOfStack--;
}
#endif
#ifdef This_was_an_alternative_to_the_two_above
/* Parameters are passed in on the stack. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
/* Parameters are passed in on the stack, and written using a 32bit value
hence a space is left for the second two bytes. */
pxTopOfStack--;
#warning Why is the offset necessary? Presumably because the parameter could be 20 bits.
pxTopOfStack--;
/* Write in the parameter value. */
pulLocal = ( unsigned long * ) pxTopOfStack;
*pulLocal = ( unsigned long ) pvParameters;
pxTopOfStack--;
/* Task function address is written to the stack first. As it is
written as a 32bit value a space is left on the stack for the second
two bytes. */
/* These values are just spacers. The return address of the function
would normally be written here. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;
pxTopOfStack--;
/* The start address / PSW value is also written in as a 32bit value,
so leave a space for the second two bytes. */
pxTopOfStack--;
/* Task function start address combined with the PSW. */
@ -206,9 +164,9 @@ unsigned long *pulLocal;
pxTopOfStack--;
/* An initial value for the AX register. */
*pxTopOfStack = ( portSTACK_TYPE ) 0xaaaa;
*pxTopOfStack = ( portSTACK_TYPE ) 0x1111;
pxTopOfStack--;
#endif
/* An initial value for the HL register. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x2222;
pxTopOfStack--;
@ -217,11 +175,9 @@ unsigned long *pulLocal;
*pxTopOfStack = ( portSTACK_TYPE ) 0x0F00;
pxTopOfStack--;
/* Finally the remaining general purpose registers DE and BC */
*pxTopOfStack = ( portSTACK_TYPE ) 0xDEDE;
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0xBCBC;
pxTopOfStack--;
/* The remaining general purpose registers bank 0 (DE and BC) and the other
three register banks.. */
pxTopOfStack -= 14;
/* Finally the critical section nesting count is set to zero when the task
first starts. */

View file

@ -86,6 +86,7 @@
.extern _vTaskIncrementTick
.text
.align 2
/* FreeRTOS yield handler. This is installed as the BRK software interrupt
handler. */
@ -101,6 +102,7 @@ _vPortYield:
/* Starts the scheduler by restoring the context of the task that will execute
first. */
.align 2
_vPortStartFirstTask:
/* Restore the context of whichever task will execute first. */
portRESTORE_CONTEXT
@ -109,6 +111,7 @@ _vPortStartFirstTask:
/* FreeRTOS tick handler. This is installed as the interval timer interrupt
handler. */
.align 2
_vPortTickISR:
/* Save the context of the currently executing task. */

View file

@ -156,7 +156,7 @@ extern volatile unsigned short usCriticalNesting; \
/*-----------------------------------------------------------*/
/* Task utilities. */
#define portYIELD() __asm volatile ( "BRK" )
#define portYIELD() __asm volatile ( "BRK" )
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#define portNOP() __asm volatile ( "NOP" )
/*-----------------------------------------------------------*/