Skip to content

Commit 421bf57

Browse files
committed
revise delay() for #114
1 parent ea1a7fa commit 421bf57

File tree

9 files changed

+90
-54
lines changed

9 files changed

+90
-54
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=FreeRTOS
2-
version=10.4.6-3
2+
version=10.4.6-4
33
author=Richard Barry <[email protected]>
44
maintainer=Phillip Stevens <[email protected]>
55
sentence=<h3>FreeRTOS Real Time Operating System implemented for AVR (Uno, Nano, Leonardo, Mega).</h3>

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ Watchdog period options:
3636
* `WDTO_1S`
3737
* `WDTO_2S`
3838

39-
Note that Timer resolution is affected by integer math division and the time slice selected. Trying to measure 50ms, using a 120ms time slice for example, won't work. Also, trying to delay for less than 15ms, with the default time slice, will not work.
39+
Note that Timer resolution (or granularity) is affected by integer math division and the time slice selected. Trying to measure 50ms, using a 120ms time slice for example, won't work.
4040

41-
The Arduino `delay()` function has been defined to automatically use the FreeRTOS `vTaskDelay()` function, so that simple Arduino example sketches and tutorials work with no change. If you would like to measure a short millisecond delay of less than one Tick (Watchdog period), then use [`millis()`](https://www.arduino.cc/reference/en/language/functions/time/millis/) (or with greater granularity use [`micros()`](https://www.arduino.cc/reference/en/language/functions/time/micros/)) to achieve this outcome (for example see [BlinkWithoutDelay](https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay)).
41+
The Arduino `delay()` function has been redefined to automatically use the FreeRTOS `vTaskDelay()` function when the delay required is one Tick or longer, so that simple Arduino example sketches and tutorials work as expected. If you would like to measure a short millisecond delay of less than one Tick, then preferably use [`millis()`](https://www.arduino.cc/reference/en/language/functions/time/millis/) (or with greater granularity use [`micros()`](https://www.arduino.cc/reference/en/language/functions/time/micros/)) to achieve this outcome (for example see [BlinkWithoutDelay](https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay)). However, when the delay requested is less than one Tick then the original Arduino `delay()` function will be automatically selected.
4242

4343
The 8-bit AVR Timer0 has been added as an option for the experienced user. Please examine the source code to figure out how to use it. Reconfiguring Timer0 for FreeRTOS will break Arduino `millis()` and `micros()` though, as these functions rely on Timer0.
4444

src/FreeRTOSVariant.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ extern "C" {
4949
WDTO_1S
5050
WDTO_2S
5151
*/
52-
// xxx Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet.
52+
53+
/* Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet. */
5354
#define configTICK_RATE_HZ ( (TickType_t)( (uint32_t)128000 >> (portUSE_WDTO + 11) ) ) // 2^11 = 2048 WDT scaler for 128kHz Timer
5455

5556
/*-----------------------------------------------------------*/

src/mpu_wrappers.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,15 @@
163163
* macro so applications can place data in privileged access sections
164164
* (useful when using statically allocated objects). */
165165
#define PRIVILEGED_FUNCTION
166-
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
166+
#define PRIVILEGED_DATA __attribute__ ((section( "privileged_data" )))
167167
#define FREERTOS_SYSTEM_CALL
168168

169169
#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
170170

171171
/* Ensure API functions go in the privileged execution section. */
172-
#define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) )
173-
#define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) )
174-
#define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) )
172+
#define PRIVILEGED_FUNCTION __attribute__ ((section( "privileged_functions" )))
173+
#define PRIVILEGED_DATA __attribute__ ((section( "privileged_data" )))
174+
#define FREERTOS_SYSTEM_CALL __attribute__ ((section( "freertos_system_calls" )))
175175

176176
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
177177

src/port.c

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -629,18 +629,41 @@ BaseType_t xPortStartScheduler( void )
629629

630630
void vPortEndScheduler( void )
631631
{
632-
/* It is unlikely that the ATmega port will get stopped. If required simply
632+
/* It is unlikely that the ATmega port will get stopped. If required simply
633633
* disable the tick interrupt here. */
634634

635635
wdt_disable(); /* disable Watchdog Timer */
636636
}
637637
/*-----------------------------------------------------------*/
638638

639-
/*
640-
* Manual context switch. The first thing we do is save the registers so we
641-
* can use a naked attribute.
642-
*/
643-
void vPortYield( void ) __attribute__ ( ( hot, flatten, naked ) );
639+
/*
640+
* Choose which delay function to use.
641+
* Arduino delay() is a millisecond granularity busy wait, that
642+
* that breaks FreeRTOS. So its use is limited to less than one
643+
* System Tick (portTICK_PERIOD_MS milliseconds).
644+
* FreeRTOS vTaskDelay() is relies on the System Tick which here
645+
* has a granularity of portTICK_PERIOD_MS milliseconds (15ms).
646+
*/
647+
648+
#ifdef delay
649+
#undef delay
650+
#endif
651+
652+
void vPortDelay( const uint32_t ms ) __attribute__ ((hot, flatten));
653+
void vPortDelay( const uint32_t ms )
654+
{
655+
if ( ms < portTICK_PERIOD_MS )
656+
delay( ms );
657+
else
658+
vTaskDelay( (TickType_t) (ms) / portTICK_PERIOD_MS );
659+
}
660+
/*-----------------------------------------------------------*/
661+
662+
/*
663+
* Manual context switch. The first thing we do is save the registers so we
664+
* can use a naked attribute.
665+
*/
666+
void vPortYield( void ) __attribute__ ((hot, flatten, naked));
644667
void vPortYield( void )
645668
{
646669
portSAVE_CONTEXT();
@@ -651,12 +674,12 @@ void vPortYield( void )
651674
}
652675
/*-----------------------------------------------------------*/
653676

654-
/*
655-
* Manual context switch callable from ISRs. The first thing we do is save
656-
* the registers so we can use a naked attribute.
657-
*/
658-
void vPortYieldFromISR(void) __attribute__ ( ( hot, flatten, naked ) );
659-
void vPortYieldFromISR(void)
677+
/*
678+
* Manual context switch callable from ISRs. The first thing we do is save
679+
* the registers so we can use a naked attribute.
680+
*/
681+
void vPortYieldFromISR( void ) __attribute__ ((hot, flatten, naked));
682+
void vPortYieldFromISR( void )
660683
{
661684
portSAVE_CONTEXT();
662685
vTaskSwitchContext();
@@ -666,13 +689,13 @@ void vPortYieldFromISR(void)
666689
}
667690
/*-----------------------------------------------------------*/
668691

669-
/*
670-
* Context switch function used by the tick. This must be identical to
671-
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
672-
* difference from vPortYield() is the tick count is incremented as the
673-
* call comes from the tick ISR.
674-
*/
675-
void vPortYieldFromTick( void ) __attribute__ ( ( hot, flatten, naked ) );
692+
/*
693+
* Context switch function used by the tick. This must be identical to
694+
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
695+
* difference from vPortYield() is the tick count is incremented as the
696+
* call comes from the tick ISR.
697+
*/
698+
void vPortYieldFromTick( void ) __attribute__ ((hot, flatten, naked));
676699
void vPortYieldFromTick( void )
677700
{
678701
portSAVE_CONTEXT();
@@ -688,9 +711,9 @@ void vPortYieldFromTick( void )
688711
/*-----------------------------------------------------------*/
689712

690713
#if defined(portUSE_WDTO)
691-
/*
692-
* Setup WDT to generate a tick interrupt.
693-
*/
714+
/*
715+
* Setup WDT to generate a tick interrupt.
716+
*/
694717
void prvSetupTimerInterrupt( void )
695718
{
696719
/* reset watchdog */
@@ -701,9 +724,9 @@ void prvSetupTimerInterrupt( void )
701724
}
702725

703726
#elif defined (portUSE_TIMER0)
704-
/*
705-
* Setup Timer0 compare match A to generate a tick interrupt.
706-
*/
727+
/*
728+
* Setup Timer0 compare match A to generate a tick interrupt.
729+
*/
707730
static void prvSetupTimerInterrupt( void )
708731
{
709732
uint32_t ulCompareMatch;

src/portable.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,23 @@
5454
#endif
5555

5656
#if portBYTE_ALIGNMENT == 32
57-
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
57+
#define portBYTE_ALIGNMENT_MASK ( 0x001f )
5858
#elif portBYTE_ALIGNMENT == 16
59-
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
59+
#define portBYTE_ALIGNMENT_MASK ( 0x000f )
6060
#elif portBYTE_ALIGNMENT == 8
61-
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
61+
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
6262
#elif portBYTE_ALIGNMENT == 4
63-
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
63+
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
6464
#elif portBYTE_ALIGNMENT == 2
65-
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
65+
#define portBYTE_ALIGNMENT_MASK ( 0x0001 )
6666
#elif portBYTE_ALIGNMENT == 1
67-
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
67+
#define portBYTE_ALIGNMENT_MASK ( 0x0000 )
6868
#else /* if portBYTE_ALIGNMENT == 32 */
6969
#error "Invalid portBYTE_ALIGNMENT definition"
7070
#endif /* if portBYTE_ALIGNMENT == 32 */
7171

7272
#ifndef portUSING_MPU_WRAPPERS
73-
#define portUSING_MPU_WRAPPERS 0
73+
#define portUSING_MPU_WRAPPERS 0
7474
#endif
7575

7676
#ifndef portNUM_CONFIGURABLE_REGIONS
@@ -82,7 +82,16 @@
8282
#endif
8383

8484
#ifndef portARCH_NAME
85-
#define portARCH_NAME NULL
85+
#define portARCH_NAME NULL
86+
#endif
87+
88+
/*
89+
* Delay is implemented as either Arduino delay() if the delay is less than one Tick,
90+
* or otherwise FreeRTOS vTaskDelay().
91+
*
92+
*/
93+
#ifndef delay
94+
#define delay vPortDelay
8695
#endif
8796

8897
#ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP

src/portmacro.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,20 @@ typedef uint8_t UBaseType_t;
9696
#define portTICK_PERIOD_MS ( (TickType_t) 1000 / configTICK_RATE_HZ )
9797
#endif
9898

99-
#define delay(ms) vTaskDelay((TickType_t)(ms)/portTICK_PERIOD_MS)
100-
10199
#define portBYTE_ALIGNMENT 1
102100
#define portNOP() __asm__ __volatile__ ( "nop" );
103101
/*-----------------------------------------------------------*/
104102

105103
/* Kernel utilities. */
106-
extern void vPortYield( void ) __attribute__ ( ( naked ) );
104+
105+
extern void vPortDelay( const uint32_t ms );
106+
#define portDELAY( ms ) vPortDelay( ms )
107+
108+
extern void vPortYield( void );
107109
#define portYIELD() vPortYield()
108110

109-
extern void vPortYieldFromISR( void ) __attribute__ ( ( naked ) );
110-
#define portYIELD_FROM_ISR() vPortYieldFromISR()
111+
extern void vPortYieldFromISR( void );
112+
#define portYIELD_FROM_ISR() vPortYieldFromISR()
111113
/*-----------------------------------------------------------*/
112114

113115
#if defined(__AVR_3_BYTE_PC__)

src/tasks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ typedef struct TaskControlBlock_t
333333

334334
/*lint -save -e956 A manual analysis and inspection has been used to determine
335335
* which static variables must be declared volatile. */
336-
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB __attribute__((used)) = NULL;
336+
PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB __attribute__ ((used)) = NULL;
337337

338338
/* Lists for ready and blocked tasks. --------------------
339339
* xDelayedTaskList1 and xDelayedTaskList2 could be moved to function scope but

src/variantHooks.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ extern void loop(void);
4343
/*-----------------------------------------------------------*/
4444

4545
void initVariant(void) __attribute__ ((OS_main));
46+
4647
void initVariant(void)
4748
{
4849
// As the Task stacks are on heap before Task allocated heap variables,
@@ -68,7 +69,7 @@ void initVariant(void)
6869
* NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK.
6970
*
7071
*/
71-
void vApplicationIdleHook( void ) __attribute__((weak));
72+
void vApplicationIdleHook( void ) __attribute__ ((weak));
7273

7374
void vApplicationIdleHook( void )
7475
{
@@ -149,7 +150,7 @@ void prvBlinkMainLed( void )
149150
This routine will never return.
150151
This routine is referenced in the task.c file of FreeRTOS as an extern.
151152
\*---------------------------------------------------------------------------*/
152-
void vApplicationMallocFailedHook( void ) __attribute__((weak));
153+
void vApplicationMallocFailedHook( void ) __attribute__ ((weak));
153154

154155
void vApplicationMallocFailedHook( void )
155156
{
@@ -169,10 +170,10 @@ void vApplicationMallocFailedHook( void )
169170
#if ( configCHECK_FOR_STACK_OVERFLOW >= 1 )
170171

171172
void vApplicationStackOverflowHook( TaskHandle_t xTask,
172-
char * pcTaskName ) __attribute__((weak));
173+
char * pcTaskName ) __attribute__ ((weak));
173174

174-
void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__((unused)),
175-
char * pcTaskName __attribute__((unused)) )
175+
void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__ ((unused)),
176+
char * pcTaskName __attribute__ ((unused)) )
176177
{
177178

178179
prvSetMainLedOn(); // Main LED on.
@@ -191,7 +192,7 @@ void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__((unused)),
191192

192193
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
193194
StackType_t ** ppxIdleTaskStackBuffer,
194-
configSTACK_DEPTH_TYPE * pulIdleTaskStackSize ) __attribute__((weak));
195+
configSTACK_DEPTH_TYPE * pulIdleTaskStackSize ) __attribute__ ((weak));
195196

196197
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
197198
StackType_t ** ppxIdleTaskStackBuffer,
@@ -209,7 +210,7 @@ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
209210

210211
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
211212
StackType_t ** ppxTimerTaskStackBuffer,
212-
configSTACK_DEPTH_TYPE * pulTimerTaskStackSize ) __attribute__((weak));
213+
configSTACK_DEPTH_TYPE * pulTimerTaskStackSize ) __attribute__ ((weak));
213214

214215
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
215216
StackType_t ** ppxTimerTaskStackBuffer,

0 commit comments

Comments
 (0)