123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /*
- * FreeRTOS Kernel V10.4.6
- * 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
- *
- */
- /*
- Changes from V1.00:
-
- + Call to taskYIELD() from within tick ISR has been replaced by the more
- efficient portSWITCH_CONTEXT().
- + ISR function definitions renamed to include the prv prefix.
- Changes from V1.2.0:
- + portRESET_PIC() is now called last thing before the end of the preemptive
- tick routine.
- Changes from V2.6.1
- + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
- macro to be consistent with the later ports.
- */
- /*-----------------------------------------------------------
- * Implementation of functions defined in portable.h for the Flashlite 186
- * port.
- *----------------------------------------------------------*/
- #include <stdlib.h>
- #include <i86.h>
- #include <dos.h>
- #include <setjmp.h>
- #include "FreeRTOS.h"
- #include "task.h"
- #include "portasm.h"
- /*lint -e950 Non ANSI reserved words okay in this file only. */
- #define portTIMER_EOI_TYPE ( 8 )
- #define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
- #define portTIMER_INT_NUMBER 0x12
- #define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
- #define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
- #define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
- /* Setup the hardware to generate the required tick frequency. */
- static void prvSetTickFrequency( uint32_t ulTickRateHz );
- /* Set the hardware back to the state as per before the scheduler started. */
- static void prvExitFunction( void );
- #if configUSE_PREEMPTION == 1
- /* Tick service routine used by the scheduler when preemptive scheduling is
- being used. */
- static void __interrupt __far prvPreemptiveTick( void );
- #else
- /* Tick service routine used by the scheduler when cooperative scheduling is
- being used. */
- static void __interrupt __far prvNonPreemptiveTick( void );
- #endif
- /* Trap routine used by taskYIELD() to manually cause a context switch. */
- static void __interrupt __far prvYieldProcessor( void );
- /*lint -e956 File scopes necessary here. */
- /* Set true when the vectors are set so the scheduler will service the tick. */
- static int16_t sSchedulerRunning = pdFALSE;
- /* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
- static void ( __interrupt __far *pxOldSwitchISR )();
- /* Used to restore the original DOS context when the scheduler is ended. */
- static jmp_buf xJumpBuf;
- /*lint +e956 */
- /*-----------------------------------------------------------*/
- BaseType_t xPortStartScheduler( void )
- {
- /* This is called with interrupts already disabled. */
- /* Remember what was on the interrupts we are going to use
- so we can put them back later if required. */
- pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
- /* Put our manual switch (yield) function on a known
- vector. */
- _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
- #if configUSE_PREEMPTION == 1
- {
- /* Put our tick switch function on the timer interrupt. */
- _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
- }
- #else
- {
- /* We want the timer interrupt to just increment the tick count. */
- _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
- }
- #endif
- prvSetTickFrequency( configTICK_RATE_HZ );
- /* Clean up function if we want to return to DOS. */
- if( setjmp( xJumpBuf ) != 0 )
- {
- prvExitFunction();
- sSchedulerRunning = pdFALSE;
- }
- else
- {
- sSchedulerRunning = pdTRUE;
- /* Kick off the scheduler by setting up the context of the first task. */
- portFIRST_CONTEXT();
- }
- return sSchedulerRunning;
- }
- /*-----------------------------------------------------------*/
- /* The tick ISR used depend on whether or not the preemptive or cooperative
- kernel is being used. */
- #if configUSE_PREEMPTION == 1
- static void __interrupt __far prvPreemptiveTick( void )
- {
- /* Get the scheduler to update the task states following the tick. */
- if( xTaskIncrementTick() != pdFALSE )
- {
- /* Switch in the context of the next task to be run. */
- portSWITCH_CONTEXT();
- }
- /* Reset the PIC ready for the next time. */
- portRESET_PIC();
- }
- #else
- static void __interrupt __far prvNonPreemptiveTick( void )
- {
- /* Same as preemptive tick, but the cooperative scheduler is being used
- so we don't have to switch in the context of the next task. */
- xTaskIncrementTick();
- portRESET_PIC();
- }
- #endif
- /*-----------------------------------------------------------*/
- static void __interrupt __far prvYieldProcessor( void )
- {
- /* Switch in the context of the next task to be run. */
- portSWITCH_CONTEXT();
- }
- /*-----------------------------------------------------------*/
- void vPortEndScheduler( void )
- {
- /* Jump back to the processor state prior to starting the
- scheduler. This means we are not going to be using a
- task stack frame so the task can be deleted. */
- longjmp( xJumpBuf, 1 );
- }
- /*-----------------------------------------------------------*/
- static void prvExitFunction( void )
- {
- const uint16_t usTimerDisable = 0x0000;
- uint16_t usTimer0Control;
- /* Interrupts should be disabled here anyway - but no
- harm in making sure. */
- portDISABLE_INTERRUPTS();
- if( sSchedulerRunning == pdTRUE )
- {
- /* Put back the switch interrupt routines that was in place
- before the scheduler started. */
- _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
- }
- /* Disable the timer used for the tick to ensure the scheduler is
- not called before restoring interrupts. There was previously nothing
- on this timer so there is no old ISR to restore. */
- portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
- /* Restart the DOS tick. */
- usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
- usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
- portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
- portENABLE_INTERRUPTS();
- }
- /*-----------------------------------------------------------*/
- static void prvSetTickFrequency( uint32_t ulTickRateHz )
- {
- const uint16_t usMaxCountRegister = 0xff5a;
- const uint16_t usTimerPriorityRegister = 0xff32;
- const uint16_t usTimerEnable = 0xC000;
- const uint16_t usRetrigger = 0x0001;
- const uint16_t usTimerHighPriority = 0x0000;
- uint16_t usTimer0Control;
- /* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
- const uint32_t ulClockFrequency = 0x7f31a0;
- uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
- portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
- portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
- portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
- /* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
- usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
- usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
- portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
- }
- /*lint +e950 */
|