Skip to content

Commit 9c78dea

Browse files
committed
update to 10.5.0-1
1 parent 43ba1c0 commit 9c78dea

File tree

7 files changed

+111
-150
lines changed

7 files changed

+111
-150
lines changed

doc/tick_sources.md

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,22 @@ The frequency of the Watchdog Oscillator is voltage and temperature dependent as
2828
Timing consistency may vary as much as 20% between two devices in same setup due to individual device differences, or between a prototype and production device due to setup differences.
2929

3030
## Alternative tick sources
31-
For applications requiring high precision timing, the Ticks can be sourced from a hardware timer or external clock.
31+
For applications requiring high precision timing, the Ticks can be sourced from one of the hardware timers or an external clock input.
3232

33-
First, you switch it in `FreeRTOSVariant.h` header by removing or undefining `portUSE_WDTO` and defining `portUSE_TIMER0`.
33+
First, you switch it in `FreeRTOSVariant.h` header by removing or undefining `portUSE_WDTO` and defining, here for example, the 8-bit Timer0 `portUSE_TIMER0`.
3434

3535
```cpp
3636
#undef portUSE_WDTO
3737
#define portUSE_TIMER0
38-
#define portTICK_PERIOD_MS 16
3938
```
4039

41-
Next, in your app you provide two pieces of code: the initialisation function and the ISR hook. Their implementation depends of what is your tick source.
40+
Next, in your app you provide two pieces of code: the initialisation functions and the ISR hook. Their implementation depends on your tick source.
41+
42+
## Timer specific initialisation and ISR functions
4243

44+
For implementation examples for many different timers, including the RTC Timer2 available on some devices, please refer to `port.c` in the [AVRfreeRTOS Repository](https://github.com/feilipu/avrfreertos/tree/master/freeRTOS10xx/portable).
4345

44-
## Hardware timer Timer0
45-
### Timer initialisation function
46+
### Hardware timer Timer0
4647
_NOTE: This code snippet is verified to work on Atmega2560. Full code available [here](./tick_sources_timer0.cpp)._
4748

4849
```cpp
@@ -89,44 +90,101 @@ void prvSetupTimerInterrupt( void )
8990
}
9091
```
9192
93+
To switch to an alternative tick source, here for example Timer0, insert this block in `FreeRTOSVariant.h`:
94+
95+
```cpp
96+
#undef portUSE_WDTO
97+
#define portUSE_TIMER0
98+
#define portTICK_PERIOD_MS 16
99+
100+
/*
101+
* When a tick source other than WDT is used, configuring the tick source becomes the user's responsibility.
102+
* E.g., when using Timer0 for the tick source, you can use the following snippet:
103+
*/
104+
105+
// Formula for the frequency is:
106+
// f = F_CPU / (PRESCALER * (1 + COUNTER_TOP)
107+
//
108+
// Assuming the MCU clock of 16MHz, prescaler 1024 and counter top 249, the resulting tick period is 16 ms (62.5 Hz).
109+
//
110+
111+
#define TICK_PERIOD_16MS 249
112+
#define PRESCALER 1024
113+
114+
#if (portTICK_PERIOD_MS != (PRESCALER * (1 + TICK_PERIOD_16MS) * 1000 / F_CPU))
115+
#warning portTICK_PERIOD_MS defined in FreeRTOSVariant.h differs from your timer configuration
116+
#endif
117+
*
118+
// For register TCCR0A:
119+
#define NO_PWM (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0)
120+
#define MODE_CTC_TCCR0A (1 << WGM01) | (0 << WGM00)
121+
122+
// For register TCCR0B:
123+
#define MODE_CTC_TCCR0B (0 << WGM02)
124+
#define PRESCALER_1024 (1 << CS02) | (0 << CS01) | (1 << CS00)
125+
126+
// For register TIMSK0:
127+
#define INTERRUPT_AT_TOP (1 << OCIE0A)
128+
129+
extern "C"
130+
void prvSetupTimerInterrupt( void )
131+
{
132+
// In case Arduino platform has pre-configured the timer,
133+
// disable it before re-configuring here to avoid unpredicted results:
134+
TIMSK0 = 0;
135+
136+
// Now configure the timer:
137+
TCCR0A = NO_PWM | MODE_CTC_TCCR0A;
138+
TCCR0B = MODE_CTC_TCCR0B | PRESCALER_1024;
139+
OCR0A = TICK_PERIOD_16MS;
140+
141+
// Prevent missing the top and going into a possibly long wait until wrapping around:
142+
TCNT0 = 0;
143+
144+
// At this point the global interrupt flag is NOT YET enabled,
145+
// so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler.
146+
TIMSK0 = INTERRUPT_AT_TOP;
147+
}
148+
```
149+
92150
Though Timer0 is given as example here, any timer can be used. A 16-bit timer (e.g., Timer1) is needed for time slices longer than ~20 milliseconds.
93151

94-
### ISR hook
95-
For **preemptive** scheduler use `naked` attribute to reduce the call overhead:
152+
### Hardware timer ISR hook
153+
For **preemptive** scheduler use `ISR_NAKED` attribute to reduce the call overhead:
96154

97155
```cpp
98156
ISR(TIMER0_COMPA_vect, ISR_NAKED) __attribute__ ((hot, flatten));
99157
ISR(TIMER0_COMPA_vect) {
100-
portSchedulerTick();
158+
vPortYieldFromTick();
101159
__asm__ __volatile__ ( "reti" );
102160
}
103161
```
104162
105-
The context is saved at the start of `portSchedulerTick()`, then the tick count is incremented, finally the new context is loaded - so no dirtying occurs.
163+
The register context is saved at the start of `vPortYieldFromTick()`, then the tick count is incremented, finally the new context is loaded - so no dirtying occurs.
106164
107165
108-
For **cooperative** scheduler, the context is not saved because no switching is intended; therefore `naked` attribute cannot be applied because cooperative `portSchedulerTick()` dirties the context.
166+
For **cooperative** scheduler, the register context is not saved because no switching is intended; therefore `naked` attribute cannot be applied because cooperative `xTaskIncrementTick()` dirties the context.
109167
110168
```cpp
111169
ISR(TIMER0_COMPA_vect) __attribute__ ((hot, flatten));
112170
ISR(TIMER0_COMPA_vect) {
113-
portSchedulerTick();
171+
xTaskIncrementTick();
114172
}
115173
```
116174

117-
Use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler:
175+
Use `ISR_NOBLOCK` where there is an important timer running, that should preempt the scheduler:
118176
```cpp
119177
ISR(portSCHEDULER_ISR, ISR_NAKED ISR_NOBLOCK) __attribute__ ((hot, flatten));
120178
```
121179
122-
Attributes `hot` and `flatten` help inlining all the code found inside your ISR thus reducing the call overhead.
180+
The attributes `hot` and `flatten` help inlining all the code found inside your ISR thus reducing the call overhead.
181+
Note: NO comma before `ISR_NOBLOCK`.
123182
124183
125-
## External clock
126-
### Input configuration function
127-
_NOTE: This code snippet was not verified on actual MCU._
184+
### External clock
185+
_NOTE: This code snippet example has not been verified to work._
128186
129-
Assuming the external clock is connected to data pin 21 (function INT0):
187+
Assuming the external clock is connected to data pin 21 (external interrupt `INT0`):
130188
131189
```cpp
132190
// For register EICRA:
@@ -150,13 +208,13 @@ void prvSetupTimerInterrupt( void )
150208
```
151209

152210

153-
### ISR hook
211+
### External clock ISR hook
154212
Similar to Timer0 ISR, for **preemptive** scheduler:
155213

156214
```cpp
157215
ISR(INT0_vect, ISR_NAKED) __attribute__ ((hot, flatten));
158216
ISR(INT0_vect) {
159-
portSchedulerTick();
217+
vPortYieldFromTick();
160218
__asm__ __volatile__ ( "reti" );
161219
}
162220
```
@@ -165,7 +223,7 @@ For **cooperative** scheduler:
165223
```cpp
166224
ISR(INT0_vect) __attribute__ ((hot, flatten));
167225
ISR(INT0_vect) {
168-
portSchedulerTick();
226+
xTaskIncrementTick();
169227
}
170228
```
171229

doc/tick_sources_timer0.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ void prvSetupTimerInterrupt( void )
4747
ISR(TIMER0_COMPA_vect, ISR_NAKED) __attribute__ ((hot, flatten));
4848
ISR(TIMER0_COMPA_vect)
4949
{
50-
portSchedulerTick();
50+
vPortYieldFromTick();
5151
__asm__ __volatile__ ( "reti" );
5252
}

library.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
name=FreeRTOS
2-
version=10.5.0-0
2+
version=10.5.0-1
33
author=Richard Barry <[email protected]>
44
maintainer=Phillip Stevens <[email protected]>
5-
sentence=<h3>FreeRTOS Real Time Operating System implemented for AVR (Uno, Nano, Leonardo, Mega).</h3>
5+
sentence=FreeRTOS Real Time Operating System implemented for AVR (Uno, Nano, Leonardo, Mega).
66
paragraph=The primary design goals are: Easy to use, Small footprint, Robust. Uses Watchdog Timer for 15ms resolution. Slow blink = stack overflow. Fast blink = heap malloc() failure.
77
category=Timing
88
url=https://github.com/feilipu/Arduino_FreeRTOS_Library

readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ See the [Code of conduct](https://github.com/feilipu/Arduino_FreeRTOS_Library/bl
8787
## Contributors ✨
8888

8989
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
90-
[![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors-)
90+
[![All Contributors](https://img.shields.io/badge/all_contributors-6-green.svg?style=flat-square)](#contributors-)
9191
<!-- ALL-CONTRIBUTORS-BADGE:END -->
9292

9393
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -97,12 +97,12 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
9797
<!-- markdownlint-disable -->
9898
<table>
9999
<tr>
100-
<td align="center"><a href="https://feilipu.me/"><img src="https://avatars.githubusercontent.com/u/3955592" width="100px;" alt=""/><br /><sub><b>Phillip Stevens</b></sub></a><br /><a title="Maintenance">🚧</a><a title="Code">💻</a><a title="Reviewed Pull Requests">👀</a></td>
100+
<td align="center"><a href="https://feilipu.me/"><img src="https://avatars.githubusercontent.com/u/3955592" width="100px;" alt=""/><br /><sub><b>Phillip Stevens</b></sub></a><br /><a title="Maintenance">🚧</a><a title="Code">💻</a><a title="Reviewed Pull Requests">👀</a><a title=Documentation">📖</a></td>
101101
<td align="center"><a href="https://www.blackleg.es/"><img src="https://avatars.githubusercontent.com/u/4323228" width="100px;" alt=""/><br /><sub><b>Hector Espert</b></sub></a><br /><a title="Code">💻</a></td>
102102
<td align="center"><a href="https://github.com/Floessie"><img src="https://avatars.githubusercontent.com/u/10133457" width="100px;" alt=""/><br /><sub><b>Floessie</b></sub></a><br /><a title="Code">💻</a></td>
103103
<td align="center"><a href="https://github.com/Derekduke"><img src="https://avatars.githubusercontent.com/u/30068270" width="100px;" alt=""/><br /><sub><b>Derekduke</b></sub></a><br /><a title="Code">💻</a></td>
104-
<td align="center"><a href="https://github.com/balaji"><img src="https://avatars.githubusercontent.com/u/29356302" width="100px;" alt=""/><br /><sub><b>Balaji.V</b></sub></a><br /><a title="Code">💻</a></td>
105-
<td align="center"><a href="https://github.com/neboskreb"><img src="https://avatars.githubusercontent.com/u/35344069" width="100px;" alt=""/><br /><sub><b>John Y. Pazekha</b></sub></a><br /><a title="Code">💻</a></td>
104+
<td align="center"><a href="https://github.com/balaji"><img src="https://avatars.githubusercontent.com/u/29356302" width="100px;" alt=""/><br /><sub><b>Balaji.V</b></sub></a><br /><a title="Code">💻</a><a title=Documentation">📖</a></td>
105+
<td align="center"><a href="https://github.com/neboskreb"><img src="https://avatars.githubusercontent.com/u/35344069" width="100px;" alt=""/><br /><sub><b>John Y. Pazekha</b></sub></a><br /><a title="Code">💻</a><a title=Documentation">📖</a></td>
106106
</tr>
107107
</table>
108108

src/FreeRTOSVariant.h

Lines changed: 10 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ extern "C" {
3636
// System Tick - Scheduler timer
3737
// Use the Watchdog timer, and choose the rate at which scheduler interrupts will occur.
3838

39+
/* Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet. */
40+
3941
#ifndef portUSE_WDTO
4042
#define portUSE_WDTO WDTO_15MS // portUSE_WDTO to use the Watchdog Timer for xTaskIncrementTick
4143
#endif
@@ -50,94 +52,15 @@ extern "C" {
5052
WDTO_2S
5153
*/
5254

53-
/* Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet. */
54-
#define configTICK_RATE_HZ ( (TickType_t)( (uint32_t)128000 >> (portUSE_WDTO + 11) ) ) // 2^11 = 2048 WDT scaler for 128kHz Timer
55-
56-
/*-----------------------------------------------------------*/
57-
// To switch to an alternative tick source, uncomment this block:
58-
// #undef portUSE_WDTO
59-
// #define portUSE_TIMER0
60-
// #define portTICK_PERIOD_MS 16
55+
#if defined( portUSE_WDTO )
6156

62-
/*
63-
* When a tick source other than WDT is used, configuring the tick source becomes the user's responsibility.
64-
* E.g., when using Timer0 for the tick source, you can use the following snippet:
65-
*
66-
* // Formula for the frequency is:
67-
* // f = F_CPU / (PRESCALER * (1 + COUNTER_TOP)
68-
* //
69-
* // Assuming the MCU clock of 16MHz, prescaler 1024 and counter top 249, the resulting tick period is 16 ms (62.5 Hz).
70-
* //
71-
* #define TICK_PERIOD_16MS 249
72-
* #define PRESCALER 1024
73-
* #if (portTICK_PERIOD_MS != (PRESCALER * (1 + TICK_PERIOD_16MS) * 1000 / F_CPU))
74-
* #warning portTICK_PERIOD_MS defined in FreeRTOSVariant.h differs from your timer configuration
75-
* #endif
76-
*
77-
* // For register TCCR0A:
78-
* #define NO_PWM (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0)
79-
* #define MODE_CTC_TCCR0A (1 << WGM01) | (0 << WGM00)
80-
*
81-
* // For register TCCR0B:
82-
* #define MODE_CTC_TCCR0B (0 << WGM02)
83-
* #define PRESCALER_1024 (1 << CS02) | (0 << CS01) | (1 << CS00)
84-
*
85-
* // For register TIMSK0:
86-
* #define INTERRUPT_AT_TOP (1 << OCIE0A)
87-
*
88-
* extern "C"
89-
* void prvSetupTimerInterrupt( void )
90-
* {
91-
* // In case Arduino platform has pre-configured the timer,
92-
* // disable it before re-configuring here to avoid unpredicted results:
93-
* TIMSK0 = 0;
94-
*
95-
* // Now configure the timer:
96-
* TCCR0A = NO_PWM | MODE_CTC_TCCR0A;
97-
* TCCR0B = MODE_CTC_TCCR0B | PRESCALER_1024;
98-
* OCR0A = TICK_PERIOD_16MS;
99-
*
100-
* // Prevent missing the top and going into a possibly long wait until wrapping around:
101-
* TCNT0 = 0;
102-
*
103-
* // At this point the global interrupt flag is NOT YET enabled,
104-
* // so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler.
105-
* TIMSK0 = INTERRUPT_AT_TOP;
106-
* }
107-
*/
108-
void prvSetupTimerInterrupt( void );
109-
110-
/*
111-
* When a tick source other than WDT is used, calling the scheduler becomes the user's responsibility.
112-
* E.g., when using Timer0 for the tick source, you'll have a timer compare IRS wherein you call portSCHEDULER_ISR().
113-
*
114-
* Implement your ISR handler efficiently:
115-
*
116-
* For PREEMPTIVE scheduler use a `naked` attribute to reduce the call overhead:
117-
*
118-
* ISR(portSCHEDULER_ISR, ISR_NAKED) __attribute__ ((hot, flatten)) {
119-
* portSchedulerTick();
120-
* __asm__ __volatile__ ( "reti" );
121-
* }
122-
*
123-
* The context is saved at the start of `portSchedulerTick()`, then the tick count is incremented, finally
124-
* the new context is loaded - so no dirtying occurs.
125-
*
126-
*
127-
* For COOPERATIVE scheduler, the context is not saved because no switching is intended; therefore `naked` attribute
128-
* cannot be applied because cooperative `portSchedulerTick()` dirties the context.
129-
*
130-
* ISR(portSCHEDULER_ISR) __attribute__ ((hot, flatten)) {
131-
* portSCHEDULER_ISR();
132-
* }
133-
*
134-
* Use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler:
135-
*
136-
* ISR(portSCHEDULER_ISR, ISR_NAKED ISR_NOBLOCK) __attribute__ ((hot, flatten));
137-
*
138-
* Attributes `hot` and `flatten` help inlining all the code found inside your ISR thus reducing the call overhead.
139-
*/
140-
void portSchedulerTick( void ) __attribute__ ((hot, flatten));
57+
#define configTICK_RATE_HZ ( (TickType_t)( (uint32_t)128000 >> (portUSE_WDTO + 11) ) ) // 2^11 = 2048 WDT scaler for 128kHz Timer
58+
#define portTICK_PERIOD_MS ( (TickType_t) _BV( portUSE_WDTO + 4 ) )
59+
#else
60+
#warning "Variant configuration must define `configTICK_RATE_HZ` and `portTICK_PERIOD_MS` as either a macro or a constant"
61+
#define configTICK_RATE_HZ 1
62+
#define portTICK_PERIOD_MS ( (TickType_t) 1000 / configTICK_RATE_HZ )
63+
#endif
14164

14265
/*-----------------------------------------------------------*/
14366

0 commit comments

Comments
 (0)