diff --git a/Demos/Host/ClassDriver/CDCHost/CDCHost.c b/Demos/Host/ClassDriver/CDCHost/CDCHost.c index 941cf7cc47..96b4b43ffb 100644 --- a/Demos/Host/ClassDriver/CDCHost/CDCHost.c +++ b/Demos/Host/ClassDriver/CDCHost/CDCHost.c @@ -42,9 +42,17 @@ */ USB_ClassInfo_CDC_Host_t VirtualSerial_CDC_Interface = { - .DataINPipeNumber = 1, - .DataOUTPipeNumber = 2, - .NotificationPipeNumber = 3, + .Config = + { + .DataINPipeNumber = 1, + .DataOUTPipeNumber = 2, + .NotificationPipeNumber = 3, + }, + + .State = + { + // Leave all state values to their defaults + } }; /** Main program entry point. This routine configures the hardware required by the application, then diff --git a/LUFA.pnproj b/LUFA.pnproj index 3601b36aab..354a4f5744 100644 --- a/LUFA.pnproj +++ b/LUFA.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/LUFA/Drivers/USB/Class/Host/CDC.c b/LUFA/Drivers/USB/Class/Host/CDC.c index 6eca8ae677..3a572f18ff 100644 --- a/LUFA/Drivers/USB/Class/Host/CDC.c +++ b/LUFA/Drivers/USB/Class/Host/CDC.c @@ -34,7 +34,7 @@ #define INCLUDE_FROM_CDC_CLASS_HOST_C #include "CDC.h" -static uint8_t CDC_Host_ProcessConfigDescriptor(void) +static uint8_t CDC_Host_ProcessConfigDescriptor(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) { uint8_t* ConfigDescriptorData; uint16_t ConfigDescriptorSize; @@ -59,13 +59,13 @@ static uint8_t CDC_Host_ProcessConfigDescriptor(void) return CDC_ENUMERROR_NoCDCInterfaceFound; } - while (FoundEndpoints != ((1 << CDC_NOTIFICATIONPIPE) | (1 << CDC_DATAPIPE_IN) | (1 << CDC_DATAPIPE_OUT))) + while (FoundEndpoints != (CDC_FOUND_DATAPIPE_IN | CDC_FOUND_DATAPIPE_OUT | CDC_FOUND_DATAPIPE_NOTIFICATION)) { if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, DComp_CDC_Host_NextInterfaceCDCDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found) { /* Check to see if the control interface's notification pipe has been found, if so search for the data interface */ - if (FoundEndpoints & (1 << CDC_NOTIFICATIONPIPE)) + if (FoundEndpoints & CDC_FOUND_DATAPIPE_NOTIFICATION) { /* Get the next CDC data interface from the configuration descriptor (CDC class has two CDC interfaces) */ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, @@ -79,11 +79,11 @@ static uint8_t CDC_Host_ProcessConfigDescriptor(void) { FoundEndpoints = 0; - Pipe_SelectPipe(CDC_NOTIFICATIONPIPE); + Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipeNumber); Pipe_DisablePipe(); - Pipe_SelectPipe(CDC_DATAPIPE_IN); + Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipeNumber); Pipe_DisablePipe(); - Pipe_SelectPipe(CDC_DATAPIPE_OUT); + Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipeNumber); Pipe_DisablePipe(); if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData, @@ -106,35 +106,38 @@ static uint8_t CDC_Host_ProcessConfigDescriptor(void) { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { - Pipe_ConfigurePipe(CDC_NOTIFICATIONPIPE, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, + Pipe_ConfigurePipe(CDCInterfaceInfo->Config.NotificationPipeNumber, EP_TYPE_INTERRUPT, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); + CDCInterfaceInfo->State.NotificationPipeSize = EndpointData->EndpointSize; Pipe_SetInfiniteINRequests(); Pipe_SetInterruptPeriod(EndpointData->PollingIntervalMS); - FoundEndpoints |= (1 << CDC_NOTIFICATIONPIPE); + FoundEndpoints |= CDC_FOUND_DATAPIPE_NOTIFICATION; } } else { if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN) { - Pipe_ConfigurePipe(CDC_DATAPIPE_IN, EP_TYPE_BULK, PIPE_TOKEN_IN, + Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); + CDCInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize; Pipe_SetInfiniteINRequests(); Pipe_Unfreeze(); - FoundEndpoints |= (1 << CDC_DATAPIPE_IN); + FoundEndpoints |= CDC_FOUND_DATAPIPE_IN; } else { - Pipe_ConfigurePipe(CDC_DATAPIPE_OUT, EP_TYPE_BULK, PIPE_TOKEN_OUT, + Pipe_ConfigurePipe(CDCInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT, EndpointData->EndpointAddress, EndpointData->EndpointSize, PIPE_BANK_SINGLE); + CDCInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize; Pipe_Unfreeze(); - FoundEndpoints |= (1 << CDC_DATAPIPE_OUT); + FoundEndpoints |= CDC_FOUND_DATAPIPE_OUT; } } } @@ -199,7 +202,7 @@ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo) switch (USB_HostState) { case HOST_STATE_Addressed: - if ((ErrorCode = CDC_Host_ProcessConfigDescriptor()) != SuccessfulConfigRead) + if ((ErrorCode = CDC_Host_ProcessConfigDescriptor(CDCInterfaceInfo)) != CDC_ENUMERROR_NoError) { USB_HostState = HOST_STATE_Unattached; } diff --git a/LUFA/Drivers/USB/Class/Host/CDC.h b/LUFA/Drivers/USB/Class/Host/CDC.h index e39333ee84..859c41d57a 100644 --- a/LUFA/Drivers/USB/Class/Host/CDC.h +++ b/LUFA/Drivers/USB/Class/Host/CDC.h @@ -50,18 +50,22 @@ #endif /* Public Interface - May be used in end-application: */ - /* Type Defines: */ + /* Type Defines: */ + /** Configuration information structure for \ref USB_ClassInfo_CDC_Host_t CDC host interface structures. */ + typedef struct + { + uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe */ + uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe */ + uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used */ + } USB_ClassInfo_CDC_Host_Config_t; + + /** Current State information structure for \ref USB_ClassInfo_CDC_Host_t CDC host interface structures. */ typedef struct { uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device */ - uint8_t DataINPipeNumber; /**< Pipe number of the CDC interface's IN data pipe */ uint16_t DataINPipeSize; /**< Size in bytes of the CDC interface's IN data pipe */ - - uint8_t DataOUTPipeNumber; /**< Pipe number of the CDC interface's OUT data pipe */ uint16_t DataOUTPipeSize; /**< Size in bytes of the CDC interface's OUT data pipe */ - - uint8_t NotificationPipeNumber; /**< Pipe number of the CDC interface's IN notification endpoint, if used */ uint16_t NotificationPipeSize; /**< Size in bytes of the CDC interface's IN notification endpoint, if used */ uint8_t ControlLineState; /**< Current control line states */ @@ -76,7 +80,27 @@ * CDCDevice_LineCodingParity_t enum */ uint8_t DataBits; /**< Bits of data per character of the virtual serial port */ - } LineEncoding; + } LineEncoding; + } USB_ClassInfo_CDC_Host_State_t; + + /** Class state structure. An instance of this structure should be made within the user application, + * and passed to each of the CDC class driver functions as the CDCInterfaceInfo parameter. This + * stores each CDC interface's configuration and state information. + */ + typedef struct + { + const USB_ClassInfo_CDC_Host_Config_t Config; /**< Config data for the USB class interface within + * the device. All elements in this section + * must be set or the interface will fail + * to enumerate and operate correctly. + */ + + USB_ClassInfo_CDC_Host_State_t State; /**< State data for the USB class interface within + * the device. All elements in this section + * may be set to initial values, but may + * also be ignored to default to sane values when + * the interface is enumerated. + */ } USB_ClassInfo_CDC_Host_t; /* Enums: */ @@ -96,16 +120,20 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) /* Macros: */ - #define CDC_CONTROL_CLASS 0x02 - #define CDC_CONTROL_SUBCLASS 0x02 - #define CDC_CONTROL_PROTOCOL 0x01 - #define CDC_DATA_CLASS 0x0A - #define CDC_DATA_SUBCLASS 0x00 - #define CDC_DATA_PROTOCOL 0x00 + #define CDC_CONTROL_CLASS 0x02 + #define CDC_CONTROL_SUBCLASS 0x02 + #define CDC_CONTROL_PROTOCOL 0x01 + #define CDC_DATA_CLASS 0x0A + #define CDC_DATA_SUBCLASS 0x00 + #define CDC_DATA_PROTOCOL 0x00 + + #define CDC_FOUND_DATAPIPE_IN (1 << 0) + #define CDC_FOUND_DATAPIPE_OUT (1 << 1) + #define CDC_FOUND_DATAPIPE_NOTIFICATION (1 << 2) /* Function Prototypes: */ #if defined(INCLUDE_FROM_CDC_CLASS_HOST_C) - static uint8_t CDC_Host_ProcessConfigDescriptor(void); + static uint8_t CDC_Host_ProcessConfigDescriptor(USB_ClassInfo_CDC_Host_t* CDCInterfaceInfo); static uint8_t DComp_CDC_Host_NextCDCControlInterface(void* CurrentDescriptor); static uint8_t DComp_CDC_Host_NextCDCDataInterface(void* CurrentDescriptor); static uint8_t DComp_CDC_Host_NextInterfaceCDCDataEndpoint(void* CurrentDescriptor); diff --git a/LUFA/ManPages/DevelopingWithLUFA.txt b/LUFA/ManPages/DevelopingWithLUFA.txt index 8c708af28f..5e44996642 100644 --- a/LUFA/ManPages/DevelopingWithLUFA.txt +++ b/LUFA/ManPages/DevelopingWithLUFA.txt @@ -17,5 +17,6 @@ * - \subpage Page_VIDPID Allocated USB VID and PID Values * - \subpage Page_BuildLibrary Building as a Linkable Library * - \subpage Page_WritingBoardDrivers How to Write Custom Board Drivers + * - \subpage Page_SchedulerOverview Overview of the Simple LUFA Scheduler (Deprecated) */ \ No newline at end of file diff --git a/LUFA/ManPages/MigrationInformation.txt b/LUFA/ManPages/MigrationInformation.txt index 34a1f97faa..ecd4e9e80e 100644 --- a/LUFA/ManPages/MigrationInformation.txt +++ b/LUFA/ManPages/MigrationInformation.txt @@ -13,8 +13,9 @@ * \section Sec_MigrationXXXXXX Migrating from 090605 to XXXXXX * * All - * - The "simple scheduler" has been removed, as it was little more than an abtracted loop and caused much confusion. User - * applications using the scheduler should switch to regular loops instead. + * - The "Simple Scheduler" has been deprecated, as it was little more than an abtracted loop and caused much confusion. User + * applications using the scheduler should switch to regular loops instead. The scheduler code will be removed in a future + * release. * - The "Dynamic Memory Block Allocator" has been removed, as it was unused in (and unrelated to) the LUFA library and never * used in user applications. The library is available from the author's website for those wishing to still use it in their * applications. diff --git a/LUFA/Scheduler/Scheduler.c b/LUFA/Scheduler/Scheduler.c new file mode 100644 index 0000000000..ff8946a0d2 --- /dev/null +++ b/LUFA/Scheduler/Scheduler.c @@ -0,0 +1,95 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +#include "Scheduler.h" + +volatile SchedulerDelayCounter_t Scheduler_TickCounter; +volatile uint8_t Scheduler_TotalTasks; + +bool Scheduler_HasDelayElapsed(const uint16_t Delay, SchedulerDelayCounter_t* const DelayCounter) +{ + SchedulerDelayCounter_t CurrentTickValue_LCL; + SchedulerDelayCounter_t DelayCounter_LCL; + + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + CurrentTickValue_LCL = Scheduler_TickCounter; + } + + DelayCounter_LCL = *DelayCounter; + + if (CurrentTickValue_LCL >= DelayCounter_LCL) + { + if ((CurrentTickValue_LCL - DelayCounter_LCL) >= Delay) + { + *DelayCounter = CurrentTickValue_LCL; + return true; + } + } + else + { + if (((MAX_DELAYCTR_COUNT - DelayCounter_LCL) + CurrentTickValue_LCL) >= Delay) + { + *DelayCounter = CurrentTickValue_LCL; + return true; + } + } + + return false; +} + +void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus) +{ + TaskEntry_t* CurrTask = &Scheduler_TaskList[0]; + + while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks]) + { + if (CurrTask->Task == Task) + { + CurrTask->TaskStatus = TaskStatus; + break; + } + + CurrTask++; + } +} + +void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus) +{ + TaskEntry_t* CurrTask = &Scheduler_TaskList[0]; + + while (CurrTask != &Scheduler_TaskList[Scheduler_TotalTasks]) + { + if (CurrTask->GroupID == GroupID) + CurrTask->TaskStatus = TaskStatus; + + CurrTask++; + } +} diff --git a/LUFA/Scheduler/Scheduler.h b/LUFA/Scheduler/Scheduler.h new file mode 100644 index 0000000000..44e6bb06c1 --- /dev/null +++ b/LUFA/Scheduler/Scheduler.h @@ -0,0 +1,289 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need + * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group. + * + * \deprecated This module is deprecated and will be removed in a future library release. + */ + +/** @defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h + * + * \deprecated This module is deprecated and will be removed in a future library release. + * + * \section Sec_Dependencies Module Source Dependencies + * The following files must be built with any user project that uses this module: + * - LUFA/Scheduler/Scheduler.c + * + * \section Module Description + * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need + * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group. + * + * For a task to yield it must return, thus each task should have persistent data marked with the static attribute. + * + * Usage Example: + * \code + * #include + * + * TASK(MyTask1); + * TASK(MyTask2); + * + * TASK_LIST + * { + * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 }, + * { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 }, + * } + * + * int main(void) + * { + * Scheduler_Start(); + * } + * + * TASK(MyTask1) + * { + * // Implementation Here + * } + * + * TASK(MyTask2) + * { + * // Implementation Here + * } + * \endcode + * + * @{ + */ + +#ifndef __SCHEDULER_H__ +#define __SCHEDULER_H__ + + /* Includes: */ + #include + #include + + #include + + #include "../Common/Common.h" + + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Creates a new scheduler task body or prototype. Should be used in the form: + * \code + * TASK(TaskName); // Prototype + * + * TASK(TaskName) + * { + * // Task body + * } + * \endcode + */ + #define TASK(name) void name (void) + + /** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list + * should be encased in curly braces and ended with a comma. + * + * Usage Example: + * \code + * TASK_LIST + * { + * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 }, + * // More task entries here + * } + * \endcode + */ + #define TASK_LIST TaskEntry_t Scheduler_TaskList[] = + + /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type + * SchedulerDelayCounter_t. + */ + #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1) + + /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */ + #define TASK_RUN true + + /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */ + #define TASK_STOP false + + /* Pseudo-Function Macros: */ + #if defined(__DOXYGEN__) + /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end + * of the user application's main() function, as it can never return to the calling function. + */ + void Scheduler_Start(void); + + /** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself + * is started. This must be executed before any scheduler function calls other than Scheduler_Start(), + * and can be omitted if no such functions could be called before the scheduler is started. + */ + void Scheduler_Init(void); + #else + #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS); + + #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS); + #endif + + /* Type Defines: */ + /** Type define for a pointer to a scheduler task. */ + typedef void (*TaskPtr_t)(void); + + /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay + * possible. + */ + typedef uint16_t SchedulerDelayCounter_t; + + /** Structure for holding a single task's information in the scheduler task list. */ + typedef struct + { + TaskPtr_t Task; /**< Pointer to the task to execute. */ + bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */ + uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */ + } TaskEntry_t; + + /* Global Variables: */ + /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type + * TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler + * functions should be used instead of direct manipulation. + */ + extern TaskEntry_t Scheduler_TaskList[]; + + /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to + * TASK_RUN or TASK_STOP. + * + * \note This value should be treated as read-only, and never altered in user-code. + */ + extern volatile uint8_t Scheduler_TotalTasks; + + /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions + * are used in the user code, this should be incremented each tick period so that the delays can be + * calculated. + */ + extern volatile SchedulerDelayCounter_t Scheduler_TickCounter; + + /* Inline Functions: */ + /** Resets the delay counter value to the current tick count. This should be called to reset the period + * for a delay in a task which is dependant on the current tick value. + * + * \param DelayCounter Counter which is storing the starting tick count for a given delay. + */ + static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter) + ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE; + static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + *DelayCounter = Scheduler_TickCounter; + } + } + + /* Function Prototypes: */ + /** Determines if the given tick delay has elapsed, based on the given . + * + * \param Delay The delay to test for, measured in ticks + * \param DelayCounter The counter which is storing the starting tick value for the delay + * + * \return Boolean true if the delay has elapsed, false otherwise + * + * Usage Example: + * \code + * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up + * + * // Task runs every 10000 ticks, 10 seconds for this demo + * if (Scheduler_HasDelayElapsed(10000, &DelayCounter)) + * { + * // Code to execute after delay interval elapsed here + * } + * \endcode + */ + bool Scheduler_HasDelayElapsed(const uint16_t Delay, + SchedulerDelayCounter_t* const DelayCounter) + ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2); + + /** Sets the task mode for a given task. + * + * \param Task Name of the task whose status is to be changed + * \param TaskStatus New task status for the task (TASK_RUN or TASK_STOP) + */ + void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus); + + /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their + * statuses changed at once. + * + * \param GroupID Value of the task group ID whose status is to be changed + * \param TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP) + */ + void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus); + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t)) + #define MAX_DELAYCTR_COUNT 0xFFFF + + /* Inline Functions: */ + static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE; + static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) + { + Scheduler_TotalTasks = TotalTasks; + } + + static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE; + static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) + { + Scheduler_InitScheduler(TotalTasks); + + for (;;) + { + TaskEntry_t* CurrTask = &Scheduler_TaskList[0]; + + while (CurrTask != &Scheduler_TaskList[TotalTasks]) + { + if (CurrTask->TaskStatus == TASK_RUN) + CurrTask->Task(); + + CurrTask++; + } + } + } + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif + +/** @} */