Bar Logo Dual Active Bridge Development Board (Part-No. )
 
Content
     
Loading...
Searching...
No Matches
os_scheduler_1ms.c
1
2//=======================================================================================================
3// @file os/os_scheduler_1ms.c
4//
5// @brief contains the main scheduler that calls all the tasks that need to be called regularly
6// two different timings priorities are available:
7// 1. 1ms Tasks called from the scheduler interrupt
8// the jitter that you will have in the 1ms realtime tasks called by the interrupt depends
9// on other interrupts that have a higher interrupt priority
10// 2. 1ms, 10ms, 100ms, 1s Tasks called from the main loop
11// these tasks are for soft realtime and not for hard realtime
12// so in average they are called with the required timing but the jitter can be very huge,
13// depending on the calls before.
14// use this for your non-timing critical application state machines
15//
16// @note put your application specific code in main/main_tasks.c
17// @note you might consider to implement a watchdog and put the watchdog triggering into some Task
18//
19// @version v1.0
20// @date 2019-08-09
21// @author M52409
22//
23//=======================================================================================================
24
25#include <stdint.h>
26#include <xc.h>
27#include "os_config.h"
28#if OS_FEATURE_WATCHDOG_ENABLED == 1
29#include "os_watchdog.h"
30#endif
31
32#if OS_USE_SCHEDULER_1ms == 1
33
34#ifndef OS_TIMER_NUMBER_OF_TIMERS
35#warning OS_TIMER_NUMBER_OF_TIMERS needs to be defined in main/project_setting.h
36#endif
37#ifndef OS_USE_SYSTIME
38#warning OS_USE_SYSTIME needs to be defined in main/project_setting.h
39#else
40#include "os_sys_time.h"
41#endif
42#include "os_scheduler.h"
43
48//extern void Tasks_Realtime_1ms(void);
49//extern void Tasks_1ms(void);
50//extern void Tasks_10ms(void);
51//extern void Tasks_100ms(void);
52//extern void Tasks_1s(void);
53//extern void Tasks_Background(void);
54
55//=======================================================================================================
56//
57// put your application specific code in the following functions in main/main_tasks.c
58// choose wisely between real-time and non-realtime!
59//
60// Interrupt Realtime Functions:
61// Tasks_Realtime_1ms : is called by the interrupt every ms - for time critical low jitter stuff
62//
63//
64// Mainloop Non-Realtime Functions:
65// Tasks_1ms : function is called by the main loop in average every 1ms
66// Tasks_10ms : function is called by the main loop in average every 10ms
67// Tasks_100ms : function is called by the main loop in average every 100ms
68// Tasks_1s : function is called by the main loop in average every second
69//
70// @note there could be some jitter here because it is not called directly by a timer interrupt
71// the timing in average is exact (keep in mind: in average), the jitter depends on the
72// called functions before
73//=======================================================================================================
74
75#if OS_TIMER_NUMBER_OF_TIMERS > 0
76 void OS_Timer_Tick(void);
77#endif
78
79static volatile uint16_t scheduler_interrupt_leader_1ms = 0;
80static volatile uint16_t scheduler_interrupt_follower_1ms = 0;
81volatile static uint16_t scheduler_1ms_timer = 0; // local counter for 1ms tasks
82volatile static uint16_t scheduler_10ms_timer = 0; // local counter for 10ms tasks
83volatile static uint16_t scheduler_100ms_timer = 0; // local counter for 100ms tasks
84volatile static uint16_t scheduler_1s_timer = 0; // local counter for 1s tasks
85
86// Timer 1 bit field settings
87#define T1ON 1 // 1 = En, 0 = disabled
88#define T1TCS 0 // 1 = External Clock, 0 = Peripheral Clock
89#define T1TCKPS 1 // 3 = 1:256, 2 = 1:64, 1 = 1:8, 0 = 1:1
90
91#if OS_USE_MCC_TIMER1 == 0
92static inline void OS_Scheduler_Init_Timer1(void)
93{
94 //Switch off Timer 1
95 T1CONbits.TON = 0; // Disable Timer1
96 IEC0bits.T1IE = 0; // Disable Timer1 interrupt
97
98 //Configure Timer 1
99 T1CONbits.TSIDL = 0; // Timer1 Stop in Idle Mode: Continues module operation in Idle mode
100 T1CONbits.TMWDIS = 0; // Asynchronous Timer1 Write Disable: Back-to-back writes are enabled in Asynchronous mode
101 T1CONbits.TMWIP = 0; // Asynchronous Timer1 Write in Progress: Write to the timer in Asynchronous mode is complete
102 T1CONbits.PRWIP = 0; // Asynchronous Period Write in Progress: Write to the Period register in Asynchronous mode is complete
103 //T1CONbits.TECS = 0b11; // Timer1 Extended Clock Select: FRC clock
104 T1CONbits.TECS = 0b01; //FCY
105 //T1CONbits.TGATE = 0; // Timer1 Gated Time Accumulation Enable: Gated time accumulation is disabled when TCS = 0
106 //T1CONbits.TCKPS = 0; // Timer1 Input Clock Prescale Select: 1:1
107 T1CONbits.TCKPS = 0b01; // Timer1 Input Clock Prescale Select: 1:8
108 T1CONbits.TSYNC = 0; // Timer1 External Clock Input Synchronization Select: Does not synchronize the External Clock input
109 //T1CONbits.TCS = 0; // Timer1 Clock Source Select: Internal peripheral clock
110 T1CONbits.TCS = 1; // Timer1 Clock Source Select: based on TECS value
111
112 TMR1 = 0x00; // Reset Timer Counter Register TMR to Zero;
113 PR1 = 9999; // Period = 0.0001 s; Frequency = 100000000 Hz; PR 9999
114
115 //TODO: these two lines are from the qi initialization: check/synchronize with the above init
116 // Initialize Timer 1 - Period: 1 ms
117 PR1 = (FCY / 1000 / 8);
118 T1CON = ((T1ON << 15) | (T1TCKPS << 4) | (T1TCS));
119
120 // in the master/slave version the slave had priority 4
121 IPC0bits.T1IP = 1; // Set interrupt priority to one (cpu is running on ip zero)
122 IFS0bits.T1IF = 0; // Reset interrupt flag bit
123
124 //Switch on Timer 1
125 IEC0bits.T1IE = 1; // Enable Timer1 interrupt
126 T1CONbits.TON = 1; // Enable Timer1
127}
128#endif
129
130//=======================================================================================================
131// @brief Initializes Scheduler
132// @note call this function in your main routine before calling the RunForever function
133//=======================================================================================================
134void OS_Scheduler_Init(void)
135{
136#if OS_USE_MCC_TIMER1 == 0
137 OS_Scheduler_Init_Timer1();
138#endif
139
140#if OS_USE_SYSTIME == 1
141 OS_SysTime_ResetTime();
142#endif //OS_USE_SYSTIME
143 scheduler_interrupt_leader_1ms = 0U; // reset directly before calling the Scheduler Loop
144 scheduler_interrupt_follower_1ms = 0U; // reset directly before calling the Scheduler Loop
145}
146
147//=======================================================================================================
148// @brief 1ms Timer 1 interrupt routine for generating the timing for the scheduler
149// @note with this simple implementation we do not lose any tick from the timer, even when the tasks
150// in the main loop take longer than 1ms
151//=======================================================================================================
152#if OS_USE_MCC_TIMER1 == 1
153/* TMR1_CallBack is a weak linked function in the tmr1.c */
154/* LDRA_EXCLUDE 34 D */
155void TMR1_CallBack(void)
156#else
157void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
158#endif
159{
160 scheduler_interrupt_leader_1ms++; //increment our counter for the scheduler, no tick gets lost
161 _T1IF = 0; //clear Timer1 interrupt flag
162#if OS_TIMER_NUMBER_OF_TIMERS > 0
163 OS_Timer_Tick();
164#endif
165#if OS_USE_SYSTIME == 1
166 OS_SysTime_IncrementTime_1ms();
167#endif //OS_USE_SYSTIME
169}
170
171//=======================================================================================================
172// @brief Scheduler function for calling all the Tasks regularly ( 1ms, 10ms, 100ms, 1s )
173// @note call this function in your main loop in main.c after calling the Init-function
174// if you have nothing else to call in your main loop then you can call the function
175// Main_Scheduler_RunForever() instead.
176// please consider that the timing of the calls are dependent on the duration of the last call
177// the resulting jitter therefore depends on the timing of the calls before
178//=======================================================================================================
179/* OS_Scheduler_RunOnce is called in main. But is being reported as not being
180 called */
181/* LDRA_EXCLUDE 61 D */
182void OS_Scheduler_RunOnce(void)
183{
184 if (scheduler_interrupt_follower_1ms != scheduler_interrupt_leader_1ms)
185 {
186 scheduler_interrupt_follower_1ms++;
187 Tasks_1ms(); //call 1 ms tasks
188 scheduler_10ms_timer += 1U;
189 if (scheduler_10ms_timer >= 10U)
190 {
191 scheduler_10ms_timer = 0U; //reset 10 ms timer
192 Tasks_10ms(); //call 10 ms tasks
193 scheduler_100ms_timer += 1U;
194 if (scheduler_100ms_timer >= 10U)
195 {
196 scheduler_100ms_timer = 0U; //reset 100 ms timer
197 Tasks_100ms(); //call 100 ms tasks
198 scheduler_1s_timer += 1U;
199 if (scheduler_1s_timer >= 10U)
200 {
201 scheduler_1s_timer = 0U;
202 #if OS_FEATURE_WATCHDOG_ENABLED == 1
203 OS_Watchdog_KeepAlivePing();
204 #endif
205 Tasks_1s(); //call 1 s tasks
206 }
207 }
208 }
209 }
210 else
211 {
212 Tasks_Background(); // run the background tasks with their own timing
213 }
214}
215
216//=======================================================================================================
217// @brief Scheduler function for calling all the Tasks regularly ( 1ms, 10ms, 100ms, 1s )
218// @note call this function as last function in main.c after calling the Init-function
219// please consider that the timing of the calls are dependent on the duration of the last call
220// the resulting jitter therefore depends on the timing of the calls before
221//=======================================================================================================
222void OS_Scheduler_RunForever(void)
223{
224 // do some initialization
225 scheduler_interrupt_leader_1ms = 0U; // reset directly before calling the Scheduler Loop
226 scheduler_interrupt_follower_1ms = 0U; // reset directly before calling the Scheduler Loop
227
228 /* LDRA_EXCLUDE 28 D */
229 while (1) // run that loop forever
230 {
231 /* OS_Scheduler_RunOnce() is not called in this application, but is
232 available to do so */
233 /* LDRA_EXCLUDE 61 D */
234 OS_Scheduler_RunOnce();
235 }
236}
237
238#endif //OS_USE_SCHEDULER_1ms
void __attribute__((weak))
Definition adc1.c:569
void Tasks_10ms(void)
Tasks_10ms gets called every 10ms, put your things in it that need to be called regularly.
Definition main_tasks.c:127
void Tasks_1ms(void)
Tasks_1ms gets called every millisecond, put your things in it that need to be called regularly.
Definition main_tasks.c:115
void Tasks_Realtime_1ms(void)
Tasks_Realtime_1ms gets called directly from the timer interrupt every millisecond.
Definition main_tasks.c:90
void Tasks_100ms(void)
Tasks_100ms gets called every 100 ms, put your things in it that need to be called regularly.
Definition main_tasks.c:141
void Tasks_Background(void)
Tasks_Background gets called all the time when no other of the above tasks are being called.
Definition main_tasks.c:170
void Tasks_1s(void)
Tasks_1s gets called every second, put your things in it that need to be called regularly.
Definition main_tasks.c:155