]> git.sur5r.net Git - freertos/blobdiff - Source/portable/Renesas/RX600/port.c
Continue work on RX600 port - work in progress.
[freertos] / Source / portable / Renesas / RX600 / port.c
index 30531ac670b24bb97b891659fc489daa4602abb4..2998d30cdf0e71ed5bc327bec271647bf9a00607 100644 (file)
 /* Library includes. */\r
 #include "string.h"\r
 \r
+/* Hardware specifics. */\r
+#include "iodefine.h"\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Dimensions the array into which the floating point context is saved.  \r
-Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4\r
-bytes big.  If this number is changed then the 72 in portasm.src also needs\r
-changing. */\r
-#define portFLOP_REGISTERS_TO_STORE    ( 18 )\r
-#define portFLOP_STORAGE_SIZE          ( portFLOP_REGISTERS_TO_STORE * 4 )\r
+/* Tasks should start with interrupts enabled, therefore PSW is set with U,I,PM \r
+flags set and IPL clear. */\r
+/* \r
+ U = 1 User stack pointer.\r
+ I = 1 Interrupts enabled.\r
+ PM = 0 Supervisor mode.\r
+ IPL = 0 All interrupt priorities enabled.\r
+*/\r
+#define portINITIAL_PSW     ( ( portSTACK_TYPE ) 0x00030000 )\r
+#define portINITIAL_FPSW    ( ( portSTACK_TYPE ) 0x00000100 )\r
+\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -83,6 +91,14 @@ void vPortYield( void );
  */\r
 void vPortStartFirstTask( void );\r
 \r
+void vPortPendContextSwitch( void );\r
+\r
+static void prvStartFirstTask( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+extern void *pxCurrentTCB;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /* \r
@@ -90,6 +106,50 @@ void vPortStartFirstTask( void );
  */\r
 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
 {\r
+       /* R0 is not included as it is the stack pointer. */\r
+       \r
+       *pxTopOfStack = 0xdeadbeef;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = portINITIAL_PSW;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( portSTACK_TYPE ) pxCode;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xffffffff;     /* r15. */\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xeeeeeeee;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xdddddddd;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xcccccccc;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xbbbbbbbb;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0xaaaaaaaa;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x99999999;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x88888888;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x77777777;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x66666666;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x55555555;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x44444444;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x33333333;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x22222222;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R1 */\r
+       pxTopOfStack--;                         \r
+       *pxTopOfStack = portINITIAL_FPSW;\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x12345678; /* Accumulator. */\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = 0x87654321; /* Accumulator. */\r
+\r
        return pxTopOfStack;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -98,17 +158,26 @@ portBASE_TYPE xPortStartScheduler( void )
 {\r
 extern void vApplicationSetupTimerInterrupt( void );\r
 \r
-       /* Call an application function to set up the timer that will generate the\r
-       tick interrupt.  This way the application can decide which peripheral to \r
-       use.  A demo application is provided to show a suitable example. */\r
-       vApplicationSetupTimerInterrupt();\r
+       /* Use pxCurrentTCB just so it does not get optimised away. */\r
+       if( pxCurrentTCB != NULL )\r
+       {\r
+               /* Call an application function to set up the timer that will generate the\r
+               tick interrupt.  This way the application can decide which peripheral to \r
+               use.  A demo application is provided to show a suitable example. */\r
+               vApplicationSetupTimerInterrupt();\r
 \r
-       /* Start the first task.  This will only restore the standard registers and\r
-       not the flop registers.  This does not really matter though because the only\r
-       flop register that is initialised to a particular value is fpscr, and it is\r
-       only initialised to the current value, which will still be the current value\r
-       when the first task starts executing. */\r
-       //trapa( portSTART_SCHEDULER_TRAP_NO );\r
+               /* Enable the software interrupt. */            \r
+               _IEN( _ICU_SWINT ) = 1;\r
+               \r
+               /* Ensure the software interrupt is clear. */\r
+               _IR( _ICU_SWINT ) = 0;\r
+               \r
+               /* Ensure the software interrupt is set to the kernel priority. */\r
+               _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;\r
+       \r
+               /* Start the first task. */\r
+               prvStartFirstTask();\r
+       }\r
 \r
        /* Should not get here. */\r
        return pdFAIL;\r
@@ -121,61 +190,56 @@ void vPortEndScheduler( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vPortYield( void )\r
-{\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-portBASE_TYPE xPortUsesFloatingPoint( xTaskHandle xTask )\r
+#pragma interrupt ( vTickISR( vect = _VECT( configTICK_VECTOR ), enable ) )\r
+void vTickISR( void )\r
 {\r
-unsigned long *pulFlopBuffer;\r
-portBASE_TYPE xReturn;\r
-extern void * volatile pxCurrentTCB;\r
+static volatile unsigned long ul = 0;\r
 \r
-       /* This function tells the kernel that the task referenced by xTask is\r
-       going to use the floating point registers and therefore requires the\r
-       floating point registers saved as part of its context. */\r
-\r
-       /* Passing NULL as xTask is used to indicate that the calling task is the\r
-       subject task - so pxCurrentTCB is the task handle. */\r
-       if( xTask == NULL )\r
-       {\r
-               xTask = ( xTaskHandle ) pxCurrentTCB;\r
-       }\r
-\r
-       /* Allocate a buffer large enough to hold all the flop registers. */\r
-       pulFlopBuffer = ( unsigned long * ) pvPortMalloc( portFLOP_STORAGE_SIZE );\r
+       ul++;\r
        \r
-       if( pulFlopBuffer != NULL )\r
-       {\r
-               /* Start with the registers in a benign state. */\r
-               memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );\r
-               \r
-               /* The first thing to get saved in the buffer is the FPSCR value -\r
-               initialise this to the current FPSCR value. */\r
-//_RB_         *pulFlopBuffer = get_fpscr();\r
-               \r
-               /* Use the task tag to point to the flop buffer.  Pass pointer to just \r
-               above the buffer because the flop save routine uses a pre-decrement. */\r
-               vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) );                \r
-               xReturn = pdPASS;\r
-       }\r
-       else\r
-       {\r
-               xReturn = pdFAIL;\r
-       }\r
+       /* Clear the interrupt. */\r
+//     vTaskIncrementTick();\r
        \r
-       return xReturn;\r
+       #if( configUSE_PREEMPTION == 1 )\r
+//             taskYIELD();\r
+       #endif\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vPortSaveFlopRegisters( void *pvBuffer )\r
+#pragma interrupt ( vSoftwareInterruptISR( vect = _VECT( _ICU_SWINT ), enable ) )\r
+void vSoftwareInterruptISR( void )\r
 {\r
+static volatile unsigned long ul = 0;\r
+\r
+       ul++;\r
 }\r
-/*-----------------------------------------------------------*/\r
 \r
-void vPortRestoreFlopRegisters( void *pvBuffer )\r
+#pragma inline_asm prvStartFirstTask\r
+static void prvStartFirstTask( void )\r
 {\r
+       /* When starting the scheduler there is nothing that needs moving to the\r
+       interrupt stack because the function is not called from an interrupt.\r
+       Just ensure the current stack is the user stack. */\r
+       SETPSW      U\r
+\r
+       /* Obtain the location of the stack associated with which ever task \r
+       pxCurrentTCB is currently pointing to. */\r
+       MOV.L       #_pxCurrentTCB,R15\r
+       MOV.L       [R15],R15\r
+       MOV.L       [R15],R0\r
+\r
+       /* Restore the registers from the stack of the task pointed to by \r
+       pxCurrentTCB. */\r
+    POP                R15\r
+    MVTACLO    R15             /* Accumulator low 32 bits. */\r
+    POP                R15\r
+    MVTACHI    R15             /* Accumulator high 32 bits. */\r
+    POP                R15\r
+    MVTC       R15,FPSW        /* Floating point status word. */\r
+    POPM       R1-R15          /* R1 to R15 - R0 is not included as it is the SP. */\r
+    RTE                                        /* This pops the remaining registers. */\r
+    NOP\r
+    NOP\r
 }\r
-/*-----------------------------------------------------------*/\r
+\r
 \r