www.freertos.org test on stm32f0
Fork of FreeRTOS by
Diff: Source/portable/RVDS/ARM_CM0/port.c
- Revision:
- 1:fc62ab66aa39
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/portable/RVDS/ARM_CM0/port.c Fri Mar 02 09:46:03 2018 +0000 @@ -0,0 +1,340 @@ +/* + FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that has become a de facto standard. * + * * + * Help yourself get started quickly and support the FreeRTOS * + * project by purchasing a FreeRTOS tutorial book, reference * + * manual, or both from: http://www.FreeRTOS.org/Documentation * + * * + * Thank you! * + * * + *************************************************************************** + + 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 modification 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. Full license text is available from the following + link: http://www.freertos.org/a00114.html + + 1 tab == 4 spaces! + + *************************************************************************** + * * + * Having a problem? Start by reading the FAQ "My application does * + * not run, what could be wrong?" * + * * + * http://www.FreeRTOS.org/FAQHelp.html * + * * + *************************************************************************** + + http://www.FreeRTOS.org - Documentation, books, training, latest versions, + license and Real Time Engineers Ltd. contact details. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High + Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the ARM CM0 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Constants required to manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL ( ( volatile unsigned long *) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned long *) 0xe000e014 ) +#define portNVIC_INT_CTRL ( ( volatile unsigned long *) 0xe000ed04 ) +#define portNVIC_SYSPRI2 ( ( volatile unsigned long *) 0xe000ed20 ) +#define portNVIC_SYSTICK_CLK 0x00000004 +#define portNVIC_SYSTICK_INT 0x00000002 +#define portNVIC_SYSTICK_ENABLE 0x00000001 +#define portNVIC_PENDSVSET 0x10000000 +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) + +/* Constants required to set up the initial stack. */ +#define portINITIAL_XPSR ( 0x01000000 ) + +/* Constants used with memory barrier intrinsics. */ +#define portSY_FULL_READ_WRITE ( 15 ) + +/* Each task maintains its own interrupt status in the critical nesting +variable. */ +static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; + +/* + * Setup the timer to generate the tick interrupts. + */ +static void prvSetupTimerInterrupt( void ); + +/* + * Exception handlers. + */ +void xPortPendSVHandler( void ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ); + +/* + * Start first task is a separate function so it can be tested in isolation. + */ +static void prvPortStartFirstTask( void ); + +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) +{ + /* Simulate the stack frame as it would be created by a context switch + interrupt. */ + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11..R4. */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler( void ) +{ + /* This function is no longer used, but retained for backward + compatibility. */ +} +/*-----------------------------------------------------------*/ + +__asm void prvPortStartFirstTask( void ) +{ + extern pxCurrentTCB; + + PRESERVE8 + + /* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector + table offset register that can be used to locate the initial stack value. + Not all M0 parts have the application vector table at address 0. */ + + ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */ + ldr r1, [r3] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + adds r0, #32 /* Discard everything up to r0. */ + msr psp, r0 /* This is now the new top of stack to use in the task. */ + movs r0, #2 /* Switch to the psp stack. */ + msr CONTROL, r0 + pop {r0-r5} /* Pop the registers that are saved automatically. */ + mov lr, r5 /* lr is now in r5. */ + cpsie i /* The first task has its context and interrupts can be enabled. */ + pop {pc} /* Finally, pop the PC to jump to the user defined task code. */ + + ALIGN +} +/*-----------------------------------------------------------*/ + +/* + * See header file for description. + */ +portBASE_TYPE xPortStartScheduler( void ) +{ + /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */ + *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI; + *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI; + + /* Start the timer that generates the tick ISR. Interrupts are disabled + here already. */ + prvSetupTimerInterrupt(); + + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; + + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should not get here! */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* It is unlikely that the CM0 port will require this function as there + is nothing to return to. */ +} +/*-----------------------------------------------------------*/ + +void vPortYield( void ) +{ + /* Set a PendSV to request a context switch. */ + *( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET; + + /* Barriers are normally not required but do ensure the code is completely + within the specified behaviour for the architecture. */ + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) +{ + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __dsb( portSY_FULL_READ_WRITE ); + __isb( portSY_FULL_READ_WRITE ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) +{ + uxCriticalNesting--; + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +__asm unsigned long ulSetInterruptMaskFromISR( void ) +{ + mrs r0, PRIMASK + cpsid i + bx lr +} +/*-----------------------------------------------------------*/ + +__asm void vClearInterruptMaskFromISR( unsigned long ulMask ) +{ + msr PRIMASK, r0 + bx lr +} +/*-----------------------------------------------------------*/ + +__asm void xPortPendSVHandler( void ) +{ + extern vTaskSwitchContext + extern pxCurrentTCB + + PRESERVE8 + + mrs r0, psp + + ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ + ldr r2, [r3] + + subs r0, #32 /* Make space for the remaining low registers. */ + str r0, [r2] /* Save the new top of stack. */ + stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */ + mov r4, r8 /* Store the high registers. */ + mov r5, r9 + mov r6, r10 + mov r7, r11 + stmia r0!, {r4-r7} + + push {r3, r14} + cpsid i + bl vTaskSwitchContext + cpsie i + pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */ + + ldr r1, [r2] + ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ + adds r0, #16 /* Move to the high registers. */ + ldmia r0!, {r4-r7} /* Pop the high registers. */ + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + + msr psp, r0 /* Remember the new top of stack for the task. */ + + subs r0, #32 /* Go back for the low registers that are not automatically restored. */ + ldmia r0!, {r4-r7} /* Pop low registers. */ + + bx r3 + ALIGN +} +/*-----------------------------------------------------------*/ + +void xPortSysTickHandler( void ) +{ +unsigned long ulPreviousMask; + + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); +} +/*-----------------------------------------------------------*/ + +/* + * Setup the systick timer to generate the tick interrupts at the required + * frequency. + */ +void prvSetupTimerInterrupt( void ) +{ + /* Configure SysTick to interrupt at the requested rate. */ + *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; +} +/*-----------------------------------------------------------*/ +