├── demo_makefile ├── .gitignore ├── main.c └── makefile ├── LICENSE.md ├── FreeRTOSBoardDefs.h ├── heap_3.c ├── readme.md ├── FreeRTOSConfig.h ├── portmacro.h ├── projdefs.h ├── stack_macros.h ├── list.c ├── portable.h ├── hooks.c ├── mpu_wrappers.h ├── list.h ├── event_groups.c └── event_groups.h /demo_makefile/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore binaries from examples 2 | *.o 3 | *.d 4 | *.map 5 | *.lss 6 | *.elf 7 | *.bin 8 | *.sym 9 | *.hex -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /demo_makefile/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.c 3 | * 4 | * @author Tiago Lobao 5 | * 6 | * @brief Blink example based on the example for atmega328p 7 | * https://github.com/feilipu/avrfreertos/blob/master/UnoBlink/main.c 8 | * 9 | */ 10 | 11 | /* Scheduler include files. */ 12 | #include "FreeRTOS.h" 13 | #include "task.h" 14 | 15 | /*-----------------------------------------------------------*/ 16 | static void TaskBlinkLED(void *pvParameters); 17 | /*-----------------------------------------------------------*/ 18 | 19 | int main(void) 20 | { 21 | xTaskCreate( 22 | TaskBlinkLED 23 | , (const char *)"GreenLED" 24 | , 256 25 | , NULL 26 | , 3 27 | , NULL ); 28 | 29 | 30 | vTaskStartScheduler(); 31 | } 32 | 33 | /*-----------------------------------------------------------*/ 34 | static void TaskBlinkLED(void *pvParameters) // Main Green LED Flash 35 | { 36 | (void) pvParameters; 37 | TickType_t xLastWakeTime; 38 | 39 | xLastWakeTime = xTaskGetTickCount(); 40 | 41 | DDRB |= _BV(DDB5); 42 | 43 | for(;;) 44 | { 45 | PORTB |= _BV(PORTB5); // main (red PB5) LED on. Arduino LED on 46 | vTaskDelayUntil( &xLastWakeTime, ( 500 / portTICK_PERIOD_MS ) ); 47 | 48 | PORTB &= ~_BV(PORTB5); // main (red PB5) LED off. Arduino LED off 49 | vTaskDelayUntil( &xLastWakeTime, ( 500 / portTICK_PERIOD_MS ) ); 50 | 51 | } 52 | } 53 | 54 | /*---------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- /demo_makefile/makefile: -------------------------------------------------------------------------------- 1 | # Make file based on 2 | # https://github.com/peakhunt/freertos_atmega328p/blob/master/Makefile 3 | # and modified by Tiago Lobao 4 | # 5 | # 6 | # make (default) = compile project 7 | # 8 | # make clean = delete all binaries 9 | # 10 | # make program = flash through AVRDUDE 11 | # 12 | 13 | # --------------------------------------- 14 | # -------- MAKEFILE USER DEFINES -------- 15 | # --------------------------------------- 16 | 17 | # --------------------------------------- 18 | # Microcontroller specific 19 | MCU=atmega328p 20 | F_CPU=16000000UL 21 | 22 | # --------------------------------------- 23 | # Directiory for the freeRTOS 24 | FREERTOS_DIR=.. 25 | 26 | # --------------------------------------- 27 | # Flashing options 28 | # using standard arduino bootloader 29 | AVRDUDE_PROGRAMMER = arduino 30 | AVRDUDE_PORT = COM3 31 | AVRDUDE_BAUDRATE = 115200 32 | 33 | # --------------------------------------- 34 | # Target file name options 35 | TARGET=main 36 | 37 | # --------------------------------------- 38 | # compiler / programmer options 39 | CC=avr-gcc 40 | AVRDUDE = avrdude 41 | 42 | # --------------------------------------- 43 | # Sources/includes to be used 44 | FREERTOS_SRC := \ 45 | $(FREERTOS_DIR)/list.c \ 46 | $(FREERTOS_DIR)/timers.c \ 47 | $(FREERTOS_DIR)/stream_buffer.c \ 48 | $(FREERTOS_DIR)/heap_3.c \ 49 | $(FREERTOS_DIR)/event_groups.c \ 50 | $(FREERTOS_DIR)/hooks.c \ 51 | $(FREERTOS_DIR)/port.c \ 52 | $(FREERTOS_DIR)/queue.c \ 53 | $(FREERTOS_DIR)/tasks.c 54 | 55 | 56 | SOURCES := $(FREERTOS_SRC) \ 57 | main.c 58 | 59 | INC_PATH=-I$(FREERTOS_DIR) -I./ 60 | 61 | 62 | # --------------------------------------- 63 | # ---------- MAKEFILE CODE -------------- 64 | # --------------------------------------- 65 | 66 | AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex 67 | AVRDUDE_FLAGS = -p $(MCU) -b $(AVRDUDE_BAUDRATE) 68 | AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) 69 | AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) 70 | 71 | MCUFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) 72 | 73 | CFLAGS = $(MCUFLAGS) $(INC_PATH) -c $(SOURCES) 74 | LFLAGS = $(MCUFLAGS) -o $(TARGET).elf *.o 75 | 76 | # --------------------------------------- 77 | # Optimization choice 78 | # This will avoid not used code and guarantee proper delays 79 | CFLAGS += -ffunction-sections -O2 80 | LFLAGS += -Wl,--gc-sections 81 | 82 | all: $(TARGET) 83 | 84 | $(TARGET): 85 | $(CC) $(CFLAGS) 86 | $(CC) $(LFLAGS) 87 | avr-objcopy -O ihex $(TARGET).elf $(TARGET).hex 88 | 89 | program: 90 | $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) 91 | 92 | clean: 93 | @echo "Cleaning $(TARGET)" 94 | rm -f $(BINARY) 95 | rm -f $(MAPFILE) 96 | rm -f $(SYMFILE) 97 | rm -f $(LSSFILE) 98 | @echo "Cleaning Objects" 99 | rm -f *.o 100 | rm -f $(TARGET)*.hex 101 | rm -f $(TARGET)*.elf 102 | rm -rf obj 103 | rm -rf .dep 104 | -------------------------------------------------------------------------------- /FreeRTOSBoardDefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Phillip Stevens All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | * 21 | * 22 | * This file is NOT part of the FreeRTOS distribution. 23 | * 24 | */ 25 | 26 | /* freeRTOSBoardDefs.h 27 | * 28 | * Board (hardware) specific definitions for the AVR boards that I use regularly. 29 | * This includes 30 | * Arduino UNO with ATmega328p 31 | * Goldilocks with ATmega1284p 32 | * Arduino MEGA with ATmega2560 33 | * 34 | * And also Pololu SVP with ATmega1284p 35 | * 36 | * This file is NOT part of the FreeRTOS distribution. 37 | * 38 | */ 39 | 40 | #ifndef freeRTOSBoardDefs_h 41 | #define freeRTOSBoardDefs_h 42 | 43 | #include 44 | #include 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | // System Tick - Scheduler timer 51 | // Use the Watchdog timer, and choose the rate at which scheduler interrupts will occur. 52 | 53 | /* Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet. */ 54 | 55 | #ifndef portUSE_WDTO 56 | #define portUSE_WDTO WDTO_15MS // portUSE_WDTO to use the Watchdog Timer for xTaskIncrementTick 57 | #endif 58 | 59 | /* Watchdog period options: WDTO_15MS 60 | WDTO_30MS 61 | WDTO_60MS 62 | WDTO_120MS 63 | WDTO_250MS 64 | WDTO_500MS 65 | WDTO_1S 66 | WDTO_2S 67 | */ 68 | 69 | #if defined( portUSE_WDTO ) 70 | 71 | #define configTICK_RATE_HZ ( (TickType_t)( (uint32_t)128000 >> (portUSE_WDTO + 11) ) ) // 2^11 = 2048 WDT scaler for 128kHz Timer 72 | #define portTICK_PERIOD_MS ( (TickType_t) _BV( portUSE_WDTO + 4 ) ) 73 | #else 74 | #warning "Variant configuration must define `configTICK_RATE_HZ` and `portTICK_PERIOD_MS` as either a macro or a constant" 75 | #define configTICK_RATE_HZ 1 76 | #define portTICK_PERIOD_MS ( (TickType_t) ( 1000 / configTICK_RATE_HZ ) ) 77 | #endif 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif // freeRTOSBoardDefs_h 84 | -------------------------------------------------------------------------------- /heap_3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | 30 | /* 31 | * Implementation of pvPortMalloc() and vPortFree() that relies on the 32 | * compilers own malloc() and free() implementations. 33 | * 34 | * This file can only be used if the linker is configured to to generate 35 | * a heap memory area. 36 | * 37 | * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the 38 | * memory management pages of https://www.FreeRTOS.org for more information. 39 | */ 40 | 41 | #include 42 | 43 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 44 | * all the API functions to use the MPU wrappers. That should only be done when 45 | * task.h is included from an application file. */ 46 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 47 | 48 | #include "FreeRTOS.h" 49 | #include "task.h" 50 | 51 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 52 | 53 | #if( configSUPPORT_DYNAMIC_ALLOCATION > 0 ) 54 | 55 | /*-----------------------------------------------------------*/ 56 | 57 | void * pvPortMalloc( size_t xWantedSize ) 58 | { 59 | void * pvReturn; 60 | 61 | vTaskSuspendAll(); 62 | { 63 | pvReturn = malloc( xWantedSize ); 64 | traceMALLOC( pvReturn, xWantedSize ); 65 | } 66 | ( void ) xTaskResumeAll(); 67 | 68 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 69 | { 70 | if( pvReturn == NULL ) 71 | { 72 | vApplicationMallocFailedHook(); 73 | } 74 | } 75 | #endif 76 | 77 | return pvReturn; 78 | } 79 | /*-----------------------------------------------------------*/ 80 | 81 | void vPortFree( void * pv ) 82 | { 83 | if( pv != NULL ) 84 | { 85 | vTaskSuspendAll(); 86 | { 87 | free( pv ); 88 | traceFREE( pv, 0 ); 89 | } 90 | ( void ) xTaskResumeAll(); 91 | } 92 | } 93 | /*-----------------------------------------------------------*/ 94 | 95 | #endif /* ( configSUPPORT_DYNAMIC_ALLOCATION > 0 ) */ 96 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | AVR ATmega port of freeRTOS. A port of freeRTOS configured to use the Watchdog Timer on AVR ATmega devices and will operate with almost any classic Arduino device from Arduino, SeeedStudio, Sparkfun, Freetronics or Pololu. 4 | 5 | The [Goldilocks Analogue story of adding a dual channel DAC to a 1284p classic Arduino board is told here](https://feilipu.me/?s=Goldilocks+Analogue). 6 | The [Goldilocks Analogue - Kickstarter Campaign](https://www.kickstarter.com/projects/feilipu/goldilocks-analogue-classic-arduino-audio-superpow/) was successfully funded. 7 | It was also a Hackaday Prize 2015 Quarter Finalist. 8 | 9 | ![Goldilocks Analogue](https://a.fsdn.com/con/app/proj/avrfreertos/screenshots/Title%20Image.JPG "Goldilocks Analogue") 10 | 11 | The first [Goldilocks 1284p story is here](https://feilipu.me/2013/03/08/goldilocks-1284p-arduino-uno-clone/). 12 | Ths idea was launched as a [Pozible campaign in 2013](https://www.pozible.com/goldilocks/). 13 | It was successfully funded and the [Goldilocks](https://freetronics.com/goldilocks/) was developed and supported by Freetronics. 14 | 15 | The main repo has been hosted on [Sourceforge avrfreertos](https://sourceforge.net/projects/avrfreertos/) since 2011, and has been [downloaded over 35,000 times](https://sourceforge.net/projects/avrfreertos/files/stats/timeline?dates=2011-09-22+to+2022-12-31). 16 | 17 | Over the past few years freeRTOS development has become increasingly 32-bit orientated, with little change or improvement for the 8-bit world. As such I'm treating this 22nd April 2024 v11.1.0 release as my LTS release. 18 | 19 | Going forward Sourceforge will be updated less often and only with major releases. 20 | 21 | Please [follow @_feilipu](https://twitter.com/_feilipu) on Twitter. 22 | 23 | # Getting Started 24 | 25 | To get started, follow the instructions on [freeRTOS & libraries for AVR ATmega](https://feilipu.me/freertos-and-libraries-for-avr-atmega). 26 | Then do some further reading on the [freeRTOS Beginner's Guide](https://www.freertos.org/Documentation/01-FreeRTOS-quick-start/01-Beginners-guide/00-Overview). 27 | 28 | For the Arduino platform there is a [freeRTOS Library](https://github.com/feilipu/Arduino_FreeRTOS_Library) 29 | available in the Arduino IDE Library manager, or by directly downloading the ZIP file and importing it into your Arduino IDE. 30 | 31 | # Features 32 | The freeRTOS scheduler can be driven by any of the AVR ATmega timers, down to one millisecond (or less) time slices, depending on the application requirements. 33 | By using the Watchdog Timer for scheduling no externally useful system resources are consumed, but time slicing is limited to 15 millisecond increments. 34 | Generally, I use the freeRTOS scheduler for loose timing (15ms) and hardware timers for tight (microsecond) timing, but each application is different. 35 | 36 | FreeRTOS has a multitude of configuration options, which can be specified from within the FreeRTOSConfig.h file., but some sensible defaults have been selected. 37 | 38 | The AVR Watchdog Timer is configured to generate 15ms time slices, but Tasks that finish before their allocated time will hand execution back to the Scheduler. 39 | Time slices can be selected from 15ms up to 500ms. Slower time slicing can allow the Arduino MCU to sleep for longer, without the complexity of a Tickless idle. 40 | 41 | Note that Timer resolution is affected by integer math division and the time slice selected. Trying to measure 100ms accurately, using a 60ms time slice for example, won't work. 42 | 43 | Watchdog period options: 44 | * WDTO_15MS 45 | * WDTO_30MS 46 | * WDTO_60MS 47 | * WDTO_120MS 48 | * WDTO_250MS 49 | * WDTO_500MS 50 | 51 | There are [multiple options for configuring the heap in freeRTOS](https://www.freertos.org/a00111.html). Please read the freeRTOS descriptions for the appropriate solution relevant to the application. 52 | Heap 3 has been implemented for this repository. 53 | 54 | # Compatibility 55 | 56 | * ATmega328 @ 16MHz : Arduino UNO, Arduino Duemilanove, Arduino Diecimila, etc. 57 | * ATmega328 @ 16MHz : Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini 58 | * ATmega328 @ 16MHz : Seeed Studio Stalker 59 | * ATmega328 @ 16MHz : Freetronics Eleven 60 | * ATmega328 @ 12MHz : Adafruit Pro Trinket 3V 61 | * ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0 62 | * ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro 63 | * ATmega1284p @ 24.576MHz : Seeed Studio Goldilocks, Seeed Studio Goldilocks Analogue 64 | * ATmega2560 @ 16MHz : Arduino Mega, Arduino ADK 65 | * ATmega2560 @ 16MHz : Seeed Studio ADK 66 | * ATmegaXXXX @ XXMHz : Anything with an ATmega MCU, really. 67 | 68 | # Errors 69 | 70 | * Stack Overflow: If any stack (for the loop() or) for any Task overflows, there will be a slow LED blink, with 4 second cycle. 71 | * Heap Overflow: If any Task tries to allocate memory and that allocation fails, there will be a fast LED blink, with 100 millisecond cycle. 72 | 73 | # Further Reading 74 | 75 | The canonical source for information is the [FreeRTOS Web Site](https://www.freertos.org/). 76 | Within this site, the [Getting Started](httpshttps://www.freertos.org/Documentation/01-FreeRTOS-quick-start/01-Beginners-guide/02-Quick-start-guide://www.freertos.org/FreeRTOS-quick-start-guide.html) page is very useful. 77 | It is worth having a view from another user, and [manicbug](https://maniacbug.wordpress.com/2012/01/31/freertos/) has some interesting examples. 78 | This AVRfreeRTOS Repository has plenty of examples, ranging from [Blink](https://github.com/feilipu/avrfreertos/blob/master/MegaBlink/main.c) through to a [Synthesiser](https://github.com/feilipu/avrfreertos/tree/master/GA_Synth) for the Goldilocks Analogue. 79 | -------------------------------------------------------------------------------- /FreeRTOSConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef FREERTOS_CONFIG_H 30 | #define FREERTOS_CONFIG_H 31 | 32 | #include 33 | 34 | /*----------------------------------------------------------- 35 | * Application specific definitions. 36 | * 37 | * These definitions should be adjusted for your particular hardware and 38 | * application requirements. 39 | * 40 | * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE 41 | * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. 42 | * 43 | * See https://www.freertos.org/a00110.html. 44 | 45 | *----------------------------------------------------------*/ 46 | 47 | /* And on to the things the same no matter the AVR type... */ 48 | #define configUSE_PREEMPTION 1 49 | 50 | #define configCPU_CLOCK_HZ ( ( uint32_t ) F_CPU ) // This F_CPU variable set by the environment 51 | #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_16_BITS 52 | 53 | #define configMAX_PRIORITIES 4 54 | #define configMAX_TASK_NAME_LEN 16 55 | 56 | /* Set the stack depth type to be uint16_t, otherwise it defaults to StackType_t */ 57 | #define configSTACK_DEPTH_TYPE uint16_t 58 | 59 | #define configMINIMAL_STACK_SIZE 92 60 | #define configCHECK_FOR_STACK_OVERFLOW 0 61 | #define configUSE_TRACE_FACILITY 0 62 | 63 | #define configUSE_MUTEXES 1 64 | #define configUSE_RECURSIVE_MUTEXES 1 65 | #define configUSE_COUNTING_SEMAPHORES 1 66 | #define configUSE_TIME_SLICING 1 67 | 68 | #define configUSE_QUEUE_SETS 0 69 | #define configUSE_APPLICATION_TASK_TAG 0 70 | #define configUSE_MALLOC_FAILED_HOOK 0 71 | #define configQUEUE_REGISTRY_SIZE 0 72 | #define configSUPPORT_DYNAMIC_ALLOCATION 1 73 | #define configSUPPORT_STATIC_ALLOCATION 0 74 | 75 | #define configUSE_IDLE_HOOK 1 76 | #define configIDLE_SHOULD_YIELD 1 77 | #define configUSE_TICK_HOOK 0 78 | 79 | /* Timer definitions. */ 80 | #define configUSE_TIMERS 1 81 | #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES-1 ) 82 | #define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE 83 | #define configTIMER_QUEUE_LENGTH 10 84 | 85 | /* Set the following definitions to 1 to include the API function, or zero 86 | to exclude the API function. */ 87 | 88 | /* Set the following INCLUDE_* constants to 1 to incldue the named API function, 89 | * or 0 to exclude the named API function. Most linkers will remove unused 90 | * functions even when the constant is 1. */ 91 | #define INCLUDE_vTaskPrioritySet 1 92 | #define INCLUDE_uxTaskPriorityGet 1 93 | #define INCLUDE_vTaskDelete 1 94 | #define INCLUDE_vTaskSuspend 1 95 | #define INCLUDE_xTaskResumeFromISR 1 96 | #define INCLUDE_xTaskDelayUntil 1 97 | #define INCLUDE_vTaskDelay 1 98 | #define INCLUDE_xTaskGetSchedulerState 0 99 | #define INCLUDE_xTaskGetCurrentTaskHandle 1 100 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 101 | #define INCLUDE_xTaskGetIdleTaskHandle 0 102 | #define INCLUDE_eTaskGetState 0 103 | #define INCLUDE_xEventGroupSetBitFromISR 1 104 | #define INCLUDE_xTimerPendFunctionCall 0 105 | #define INCLUDE_xTaskAbortDelay 0 106 | #define INCLUDE_xTaskGetHandle 0 107 | 108 | #define configMAX(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) 109 | #define configMIN(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) 110 | 111 | /** 112 | * configASSERT macro: https://www.freertos.org/a00110.html#configASSERT 113 | */ 114 | #ifndef configASSERT 115 | #define configDEFAULT_ASSERT 0 116 | #else 117 | /** 118 | * Enable configASSERT macro if it is defined. 119 | */ 120 | #ifndef configDEFAULT_ASSERT 121 | #define configDEFAULT_ASSERT 1 122 | #endif 123 | 124 | /** 125 | * Define a hook method for configASSERT macro if configASSERT is enabled. 126 | */ 127 | #if configDEFAULT_ASSERT == 1 128 | extern void vApplicationAssertHook(); 129 | #define configASSERT( x ) if (( x ) == 0) { vApplicationAssertHook(); } 130 | #endif 131 | #endif 132 | 133 | 134 | #endif /* FREERTOS_CONFIG_H */ 135 | -------------------------------------------------------------------------------- /portmacro.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef PORTMACRO_H 30 | #define PORTMACRO_H 31 | 32 | #include 33 | 34 | /* *INDENT-OFF* */ 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | /* *INDENT-ON* */ 39 | 40 | /*----------------------------------------------------------- 41 | * Port specific definitions. 42 | * 43 | * The settings in this file configure FreeRTOS correctly for the 44 | * given hardware and compiler. 45 | * 46 | * These settings should not be altered. 47 | *----------------------------------------------------------- 48 | */ 49 | 50 | /* Type definitions. */ 51 | 52 | #define portPOINTER_SIZE_TYPE uint16_t 53 | 54 | typedef uint8_t StackType_t; 55 | typedef int8_t BaseType_t; 56 | typedef uint8_t UBaseType_t; 57 | 58 | #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) 59 | typedef uint16_t TickType_t; 60 | #define portMAX_DELAY ( TickType_t ) ( 0xffffU ) 61 | #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) 62 | typedef uint32_t TickType_t; 63 | #define portMAX_DELAY ( TickType_t ) ( 0xffffffffUL ) 64 | #else 65 | #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. 66 | #endif 67 | /*-----------------------------------------------------------*/ 68 | 69 | /* Critical section management. */ 70 | 71 | #define portENTER_CRITICAL() \ 72 | __asm__ __volatile__ ( \ 73 | "in __tmp_reg__, __SREG__" "\n\t" \ 74 | "cli" "\n\t" \ 75 | "push __tmp_reg__" "\n\t" \ 76 | ::: "memory" \ 77 | ) 78 | 79 | 80 | #define portEXIT_CRITICAL() \ 81 | __asm__ __volatile__ ( \ 82 | "pop __tmp_reg__" "\n\t" \ 83 | "out __SREG__, __tmp_reg__" "\n\t" \ 84 | ::: "memory" \ 85 | ) 86 | 87 | 88 | #define portDISABLE_INTERRUPTS() __asm__ __volatile__ ( "cli" ::: "memory" ) 89 | #define portENABLE_INTERRUPTS() __asm__ __volatile__ ( "sei" ::: "memory" ) 90 | /*-----------------------------------------------------------*/ 91 | 92 | /* Architecture specifics. */ 93 | 94 | /* System Tick - Scheduler timer 95 | * Prefer to use the enhanced Watchdog Timer, but also Timer0 is ok. 96 | */ 97 | 98 | #define sleep_reset() do { _SLEEP_CONTROL_REG = 0; } while(0) /* reset all sleep_mode() configurations. */ 99 | 100 | #if defined( WDIE ) && defined( WDIF ) /* If Enhanced WDT with interrupt capability is available */ 101 | 102 | #define portUSE_WDTO WDTO_15MS /* use the Watchdog Timer for xTaskIncrementTick */ 103 | 104 | /* Watchdog period options: WDTO_15MS 105 | * WDTO_30MS 106 | * WDTO_60MS 107 | * WDTO_120MS 108 | * WDTO_250MS 109 | * WDTO_500MS 110 | * WDTO_1S 111 | * WDTO_2S 112 | */ 113 | 114 | #else 115 | 116 | #define portUSE_TIMER0 /* use the 8-bit Timer0 for xTaskIncrementTick */ 117 | 118 | #endif 119 | 120 | #define portSTACK_GROWTH ( -1 ) 121 | 122 | /* Timing for the scheduler. 123 | * Watchdog Timer is 128kHz nominal, 124 | * but 120 kHz at 5V DC and 25 degrees is actually more accurate, 125 | * from data sheet. 126 | */ 127 | #if defined( portUSE_WDTO ) 128 | #define portTICK_PERIOD_MS ( ( TickType_t ) _BV( portUSE_WDTO + 4 ) ) 129 | #else 130 | #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) 131 | #endif 132 | 133 | #define portBYTE_ALIGNMENT 1 134 | #define portNOP() __asm__ __volatile__ ( "nop" ); 135 | /*-----------------------------------------------------------*/ 136 | 137 | /* Kernel utilities. */ 138 | 139 | extern void vPortYield( void ) __attribute__( ( naked ) ); 140 | #define portYIELD() vPortYield() 141 | 142 | extern void vPortYieldFromISR( void ) __attribute__( ( naked ) ); 143 | #define portYIELD_FROM_ISR() vPortYieldFromISR() 144 | /*-----------------------------------------------------------*/ 145 | 146 | #if defined( __AVR_3_BYTE_PC__ ) 147 | /* Task function macros as described on the FreeRTOS.org WEB site. */ 148 | 149 | /* Add .lowtext tag from the avr linker script avr6.x for ATmega2560 and ATmega2561 150 | * to make sure functions are loaded in low memory. 151 | */ 152 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( section( ".lowtext" ) ) ) 153 | #else 154 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) 155 | #endif 156 | 157 | #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) 158 | 159 | /* *INDENT-OFF* */ 160 | #ifdef __cplusplus 161 | } 162 | #endif 163 | /* *INDENT-ON* */ 164 | 165 | #endif /* PORTMACRO_H */ 166 | -------------------------------------------------------------------------------- /projdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef PROJDEFS_H 30 | #define PROJDEFS_H 31 | 32 | /* 33 | * Defines the prototype to which task functions must conform. Defined in this 34 | * file to ensure the type is known before portable.h is included. 35 | */ 36 | typedef void (* TaskFunction_t)( void * arg ); 37 | 38 | /* Converts a time in milliseconds to a time in ticks. This macro can be 39 | * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the 40 | * definition here is not suitable for your application. */ 41 | #ifndef pdMS_TO_TICKS 42 | #define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInMs ) * ( uint64_t ) configTICK_RATE_HZ ) / ( uint64_t ) 1000U ) ) 43 | #endif 44 | 45 | /* Converts a time in ticks to a time in milliseconds. This macro can be 46 | * overridden by a macro of the same name defined in FreeRTOSConfig.h in case the 47 | * definition here is not suitable for your application. */ 48 | #ifndef pdTICKS_TO_MS 49 | #define pdTICKS_TO_MS( xTimeInTicks ) ( ( TickType_t ) ( ( ( uint64_t ) ( xTimeInTicks ) * ( uint64_t ) 1000U ) / ( uint64_t ) configTICK_RATE_HZ ) ) 50 | #endif 51 | 52 | #define pdFALSE ( ( BaseType_t ) 0 ) 53 | #define pdTRUE ( ( BaseType_t ) 1 ) 54 | #define pdFALSE_SIGNED ( ( BaseType_t ) 0 ) 55 | #define pdTRUE_SIGNED ( ( BaseType_t ) 1 ) 56 | #define pdFALSE_UNSIGNED ( ( UBaseType_t ) 0 ) 57 | #define pdTRUE_UNSIGNED ( ( UBaseType_t ) 1 ) 58 | 59 | #define pdPASS ( pdTRUE ) 60 | #define pdFAIL ( pdFALSE ) 61 | #define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) 62 | #define errQUEUE_FULL ( ( BaseType_t ) 0 ) 63 | 64 | /* FreeRTOS error definitions. */ 65 | #define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) 66 | #define errQUEUE_BLOCKED ( -4 ) 67 | #define errQUEUE_YIELD ( -5 ) 68 | 69 | /* Macros used for basic data corruption checks. */ 70 | #ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 71 | #define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 72 | #endif 73 | 74 | #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) 75 | #define pdINTEGRITY_CHECK_VALUE 0x5a5a 76 | #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) 77 | #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL 78 | #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS ) 79 | #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5a5a5a5a5aULL 80 | #else 81 | #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. 82 | #endif 83 | 84 | /* The following errno values are used by FreeRTOS+ components, not FreeRTOS 85 | * itself. */ 86 | #define pdFREERTOS_ERRNO_NONE 0 /* No errors */ 87 | #define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ 88 | #define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ 89 | #define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ 90 | #define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ 91 | #define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ 92 | #define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ 93 | #define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ 94 | #define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ 95 | #define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ 96 | #define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ 97 | #define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ 98 | #define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ 99 | #define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ 100 | #define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ 101 | #define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ 102 | #define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ 103 | #define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ 104 | #define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ 105 | #define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ 106 | #define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ 107 | #define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ 108 | #define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ 109 | #define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ 110 | #define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ 111 | #define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ 112 | #define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ 113 | #define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 114 | #define pdFREERTOS_ERRNO_EAFNOSUPPORT 97 /* Address family not supported by protocol */ 115 | #define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ 116 | #define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ 117 | #define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ 118 | #define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ 119 | #define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ 120 | #define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ 121 | #define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ 122 | #define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ 123 | #define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ 124 | #define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ 125 | #define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ 126 | #define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ 127 | 128 | /* The following endian values are used by FreeRTOS+ components, not FreeRTOS 129 | * itself. */ 130 | #define pdFREERTOS_LITTLE_ENDIAN 0 131 | #define pdFREERTOS_BIG_ENDIAN 1 132 | 133 | /* Re-defining endian values for generic naming. */ 134 | #define pdLITTLE_ENDIAN pdFREERTOS_LITTLE_ENDIAN 135 | #define pdBIG_ENDIAN pdFREERTOS_BIG_ENDIAN 136 | 137 | 138 | #endif /* PROJDEFS_H */ 139 | -------------------------------------------------------------------------------- /stack_macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef STACK_MACROS_H 30 | #define STACK_MACROS_H 31 | 32 | /* 33 | * Call the stack overflow hook function if the stack of the task being swapped 34 | * out is currently overflowed, or looks like it might have overflowed in the 35 | * past. 36 | * 37 | * Setting configCHECK_FOR_STACK_OVERFLOW to 1 will cause the macro to check 38 | * the current stack state only - comparing the current top of stack value to 39 | * the stack limit. Setting configCHECK_FOR_STACK_OVERFLOW to greater than 1 40 | * will also cause the last few stack bytes to be checked to ensure the value 41 | * to which the bytes were set when the task was created have not been 42 | * overwritten. Note this second test does not guarantee that an overflowed 43 | * stack will always be recognised. 44 | */ 45 | 46 | /*-----------------------------------------------------------*/ 47 | 48 | /* 49 | * portSTACK_LIMIT_PADDING is a number of extra words to consider to be in 50 | * use on the stack. 51 | */ 52 | #ifndef portSTACK_LIMIT_PADDING 53 | #define portSTACK_LIMIT_PADDING 0 54 | #endif 55 | 56 | #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH < 0 ) ) 57 | 58 | /* Only the current stack state is to be checked. */ 59 | #define taskCHECK_FOR_STACK_OVERFLOW() \ 60 | do { \ 61 | /* Is the currently saved stack pointer within the stack limit? */ \ 62 | if( pxCurrentTCB->pxTopOfStack <= pxCurrentTCB->pxStack + portSTACK_LIMIT_PADDING ) \ 63 | { \ 64 | char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 65 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 66 | } \ 67 | } while( 0 ) 68 | 69 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 70 | /*-----------------------------------------------------------*/ 71 | 72 | #if ( ( configCHECK_FOR_STACK_OVERFLOW == 1 ) && ( portSTACK_GROWTH > 0 ) ) 73 | 74 | /* Only the current stack state is to be checked. */ 75 | #define taskCHECK_FOR_STACK_OVERFLOW() \ 76 | do { \ 77 | \ 78 | /* Is the currently saved stack pointer within the stack limit? */ \ 79 | if( pxCurrentTCB->pxTopOfStack >= pxCurrentTCB->pxEndOfStack - portSTACK_LIMIT_PADDING ) \ 80 | { \ 81 | char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 82 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 83 | } \ 84 | } while( 0 ) 85 | 86 | #endif /* configCHECK_FOR_STACK_OVERFLOW == 1 */ 87 | /*-----------------------------------------------------------*/ 88 | 89 | #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH < 0 ) ) 90 | 91 | #define taskCHECK_FOR_STACK_OVERFLOW() \ 92 | do { \ 93 | const uint32_t * const pulStack = ( uint32_t * ) pxCurrentTCB->pxStack; \ 94 | const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5U; \ 95 | \ 96 | if( ( pulStack[ 0 ] != ulCheckValue ) || \ 97 | ( pulStack[ 1 ] != ulCheckValue ) || \ 98 | ( pulStack[ 2 ] != ulCheckValue ) || \ 99 | ( pulStack[ 3 ] != ulCheckValue ) ) \ 100 | { \ 101 | char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 102 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 103 | } \ 104 | } while( 0 ) 105 | 106 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 107 | /*-----------------------------------------------------------*/ 108 | 109 | #if ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) && ( portSTACK_GROWTH > 0 ) ) 110 | 111 | #define taskCHECK_FOR_STACK_OVERFLOW() \ 112 | do { \ 113 | int8_t * pcEndOfStack = ( int8_t * ) pxCurrentTCB->pxEndOfStack; \ 114 | static const uint8_t ucExpectedStackBytes[] = { tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 115 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 116 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 117 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, \ 118 | tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE, tskSTACK_FILL_BYTE }; \ 119 | \ 120 | \ 121 | pcEndOfStack -= sizeof( ucExpectedStackBytes ); \ 122 | \ 123 | /* Has the extremity of the task stack ever been written over? */ \ 124 | if( memcmp( ( void * ) pcEndOfStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) != 0 ) \ 125 | { \ 126 | char * pcOverflowTaskName = pxCurrentTCB->pcTaskName; \ 127 | vApplicationStackOverflowHook( ( TaskHandle_t ) pxCurrentTCB, pcOverflowTaskName ); \ 128 | } \ 129 | } while( 0 ) 130 | 131 | #endif /* #if( configCHECK_FOR_STACK_OVERFLOW > 1 ) */ 132 | /*-----------------------------------------------------------*/ 133 | 134 | /* Remove stack overflow macro if not being used. */ 135 | #ifndef taskCHECK_FOR_STACK_OVERFLOW 136 | #define taskCHECK_FOR_STACK_OVERFLOW() 137 | #endif 138 | 139 | 140 | 141 | #endif /* STACK_MACROS_H */ 142 | -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | 30 | #include 31 | 32 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 33 | * all the API functions to use the MPU wrappers. That should only be done when 34 | * task.h is included from an application file. */ 35 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 36 | 37 | #include "FreeRTOS.h" 38 | #include "list.h" 39 | 40 | /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be 41 | * defined for the header files above, but not in this file, in order to 42 | * generate the correct privileged Vs unprivileged linkage and placement. */ 43 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 44 | 45 | /*----------------------------------------------------------- 46 | * PUBLIC LIST API documented in list.h 47 | *----------------------------------------------------------*/ 48 | 49 | void vListInitialise( List_t * const pxList ) 50 | { 51 | traceENTER_vListInitialise( pxList ); 52 | 53 | /* The list structure contains a list item which is used to mark the 54 | * end of the list. To initialise the list the list end is inserted 55 | * as the only list entry. */ 56 | pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); 57 | 58 | listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) ); 59 | 60 | /* The list end value is the highest possible value in the list to 61 | * ensure it remains at the end of the list. */ 62 | pxList->xListEnd.xItemValue = portMAX_DELAY; 63 | 64 | /* The list end next and previous pointers point to itself so we know 65 | * when the list is empty. */ 66 | pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); 67 | pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); 68 | 69 | /* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */ 70 | #if ( configUSE_MINI_LIST_ITEM == 0 ) 71 | { 72 | pxList->xListEnd.pvOwner = NULL; 73 | pxList->xListEnd.pxContainer = NULL; 74 | listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) ); 75 | } 76 | #endif 77 | 78 | pxList->uxNumberOfItems = ( UBaseType_t ) 0U; 79 | 80 | /* Write known values into the list if 81 | * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 82 | listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ); 83 | listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ); 84 | 85 | traceRETURN_vListInitialise(); 86 | } 87 | /*-----------------------------------------------------------*/ 88 | 89 | void vListInitialiseItem( ListItem_t * const pxItem ) 90 | { 91 | traceENTER_vListInitialiseItem( pxItem ); 92 | 93 | /* Make sure the list item is not recorded as being on a list. */ 94 | pxItem->pxContainer = NULL; 95 | 96 | /* Write known values into the list item if 97 | * configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 98 | listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); 99 | listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ); 100 | 101 | traceRETURN_vListInitialiseItem(); 102 | } 103 | /*-----------------------------------------------------------*/ 104 | 105 | void vListInsertEnd( List_t * const pxList, 106 | ListItem_t * const pxNewListItem ) 107 | { 108 | ListItem_t * const pxIndex = pxList->pxIndex; 109 | 110 | traceENTER_vListInsertEnd( pxList, pxNewListItem ); 111 | 112 | /* Only effective when configASSERT() is also defined, these tests may catch 113 | * the list data structures being overwritten in memory. They will not catch 114 | * data errors caused by incorrect configuration or use of FreeRTOS. */ 115 | listTEST_LIST_INTEGRITY( pxList ); 116 | listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); 117 | 118 | /* Insert a new list item into pxList, but rather than sort the list, 119 | * makes the new list item the last item to be removed by a call to 120 | * listGET_OWNER_OF_NEXT_ENTRY(). */ 121 | pxNewListItem->pxNext = pxIndex; 122 | pxNewListItem->pxPrevious = pxIndex->pxPrevious; 123 | 124 | /* Only used during decision coverage testing. */ 125 | mtCOVERAGE_TEST_DELAY(); 126 | 127 | pxIndex->pxPrevious->pxNext = pxNewListItem; 128 | pxIndex->pxPrevious = pxNewListItem; 129 | 130 | /* Remember which list the item is in. */ 131 | pxNewListItem->pxContainer = pxList; 132 | 133 | ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U ); 134 | 135 | traceRETURN_vListInsertEnd(); 136 | } 137 | /*-----------------------------------------------------------*/ 138 | 139 | void vListInsert( List_t * const pxList, 140 | ListItem_t * const pxNewListItem ) 141 | { 142 | ListItem_t * pxIterator; 143 | const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; 144 | 145 | traceENTER_vListInsert( pxList, pxNewListItem ); 146 | 147 | /* Only effective when configASSERT() is also defined, these tests may catch 148 | * the list data structures being overwritten in memory. They will not catch 149 | * data errors caused by incorrect configuration or use of FreeRTOS. */ 150 | listTEST_LIST_INTEGRITY( pxList ); 151 | listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); 152 | 153 | /* Insert the new list item into the list, sorted in xItemValue order. 154 | * 155 | * If the list already contains a list item with the same item value then the 156 | * new list item should be placed after it. This ensures that TCBs which are 157 | * stored in ready lists (all of which have the same xItemValue value) get a 158 | * share of the CPU. However, if the xItemValue is the same as the back marker 159 | * the iteration loop below will not end. Therefore the value is checked 160 | * first, and the algorithm slightly modified if necessary. */ 161 | if( xValueOfInsertion == portMAX_DELAY ) 162 | { 163 | pxIterator = pxList->xListEnd.pxPrevious; 164 | } 165 | else 166 | { 167 | /* *** NOTE *********************************************************** 168 | * If you find your application is crashing here then likely causes are 169 | * listed below. In addition see https://www.FreeRTOS.org/FAQHelp.html for 170 | * more tips, and ensure configASSERT() is defined! 171 | * https://www.FreeRTOS.org/a00110.html#configASSERT 172 | * 173 | * 1) Stack overflow - 174 | * see https://www.FreeRTOS.org/Stacks-and-stack-overflow-checking.html 175 | * 2) Incorrect interrupt priority assignment, especially on Cortex-M 176 | * parts where numerically high priority values denote low actual 177 | * interrupt priorities, which can seem counter intuitive. See 178 | * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html and the definition 179 | * of configMAX_SYSCALL_INTERRUPT_PRIORITY on 180 | * https://www.FreeRTOS.org/a00110.html 181 | * 3) Calling an API function from within a critical section or when 182 | * the scheduler is suspended, or calling an API function that does 183 | * not end in "FromISR" from an interrupt. 184 | * 4) Using a queue or semaphore before it has been initialised or 185 | * before the scheduler has been started (are interrupts firing 186 | * before vTaskStartScheduler() has been called?). 187 | * 5) If the FreeRTOS port supports interrupt nesting then ensure that 188 | * the priority of the tick interrupt is at or below 189 | * configMAX_SYSCALL_INTERRUPT_PRIORITY. 190 | **********************************************************************/ 191 | 192 | for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) 193 | { 194 | /* There is nothing to do here, just iterating to the wanted 195 | * insertion position. */ 196 | } 197 | } 198 | 199 | pxNewListItem->pxNext = pxIterator->pxNext; 200 | pxNewListItem->pxNext->pxPrevious = pxNewListItem; 201 | pxNewListItem->pxPrevious = pxIterator; 202 | pxIterator->pxNext = pxNewListItem; 203 | 204 | /* Remember which list the item is in. This allows fast removal of the 205 | * item later. */ 206 | pxNewListItem->pxContainer = pxList; 207 | 208 | ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems + 1U ); 209 | 210 | traceRETURN_vListInsert(); 211 | } 212 | /*-----------------------------------------------------------*/ 213 | 214 | UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) 215 | { 216 | /* The list item knows which list it is in. Obtain the list from the list 217 | * item. */ 218 | List_t * const pxList = pxItemToRemove->pxContainer; 219 | 220 | traceENTER_uxListRemove( pxItemToRemove ); 221 | 222 | pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious; 223 | pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext; 224 | 225 | /* Only used during decision coverage testing. */ 226 | mtCOVERAGE_TEST_DELAY(); 227 | 228 | /* Make sure the index is left pointing to a valid item. */ 229 | if( pxList->pxIndex == pxItemToRemove ) 230 | { 231 | pxList->pxIndex = pxItemToRemove->pxPrevious; 232 | } 233 | else 234 | { 235 | mtCOVERAGE_TEST_MARKER(); 236 | } 237 | 238 | pxItemToRemove->pxContainer = NULL; 239 | ( pxList->uxNumberOfItems ) = ( UBaseType_t ) ( pxList->uxNumberOfItems - 1U ); 240 | 241 | traceRETURN_uxListRemove( pxList->uxNumberOfItems ); 242 | 243 | return pxList->uxNumberOfItems; 244 | } 245 | /*-----------------------------------------------------------*/ 246 | -------------------------------------------------------------------------------- /portable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | /*----------------------------------------------------------- 30 | * Portable layer API. Each function must be defined for each port. 31 | *----------------------------------------------------------*/ 32 | 33 | #ifndef PORTABLE_H 34 | #define PORTABLE_H 35 | 36 | /* Each FreeRTOS port has a unique portmacro.h header file. Originally a 37 | * pre-processor definition was used to ensure the pre-processor found the correct 38 | * portmacro.h file for the port being used. That scheme was deprecated in favour 39 | * of setting the compiler's include path such that it found the correct 40 | * portmacro.h file - removing the need for the constant and allowing the 41 | * portmacro.h file to be located anywhere in relation to the port being used. 42 | * Purely for reasons of backward compatibility the old method is still valid, but 43 | * to make it clear that new projects should not use it, support for the port 44 | * specific constants has been moved into the deprecated_definitions.h header 45 | * file. */ 46 | //#include "deprecated_definitions.h" 47 | 48 | /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h 49 | * did not result in a portmacro.h header file being included - and it should be 50 | * included here. In this case the path to the correct portmacro.h header file 51 | * must be set in the compiler's include path. */ 52 | #ifndef portENTER_CRITICAL 53 | #include "portmacro.h" 54 | #endif 55 | 56 | #if portBYTE_ALIGNMENT == 32 57 | #define portBYTE_ALIGNMENT_MASK ( 0x001f ) 58 | #elif portBYTE_ALIGNMENT == 16 59 | #define portBYTE_ALIGNMENT_MASK ( 0x000f ) 60 | #elif portBYTE_ALIGNMENT == 8 61 | #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) 62 | #elif portBYTE_ALIGNMENT == 4 63 | #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) 64 | #elif portBYTE_ALIGNMENT == 2 65 | #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) 66 | #elif portBYTE_ALIGNMENT == 1 67 | #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) 68 | #else /* if portBYTE_ALIGNMENT == 32 */ 69 | #error "Invalid portBYTE_ALIGNMENT definition" 70 | #endif /* if portBYTE_ALIGNMENT == 32 */ 71 | 72 | #ifndef portUSING_MPU_WRAPPERS 73 | #define portUSING_MPU_WRAPPERS 0 74 | #endif 75 | 76 | #ifndef portNUM_CONFIGURABLE_REGIONS 77 | #define portNUM_CONFIGURABLE_REGIONS 1 78 | #endif 79 | 80 | #ifndef portHAS_STACK_OVERFLOW_CHECKING 81 | #define portHAS_STACK_OVERFLOW_CHECKING 0 82 | #endif 83 | 84 | #ifndef portARCH_NAME 85 | #define portARCH_NAME NULL 86 | #endif 87 | 88 | #ifndef configSTACK_DEPTH_TYPE 89 | #define configSTACK_DEPTH_TYPE StackType_t 90 | #endif 91 | 92 | #ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 93 | /* Defaults to 0 for backward compatibility. */ 94 | #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 95 | #endif 96 | 97 | #include "mpu_wrappers.h" 98 | 99 | /* *INDENT-OFF* */ 100 | #ifdef __cplusplus 101 | extern "C" { 102 | #endif 103 | /* *INDENT-ON* */ 104 | 105 | /* 106 | * Setup the stack of a new task so it is ready to be placed under the 107 | * scheduler control. The registers have to be placed on the stack in 108 | * the order that the port expects to find them. 109 | * 110 | */ 111 | #if ( portUSING_MPU_WRAPPERS == 1 ) 112 | #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) 113 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 114 | StackType_t * pxEndOfStack, 115 | TaskFunction_t pxCode, 116 | void * pvParameters, 117 | BaseType_t xRunPrivileged, 118 | xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; 119 | #else 120 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 121 | TaskFunction_t pxCode, 122 | void * pvParameters, 123 | BaseType_t xRunPrivileged, 124 | xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; 125 | #endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */ 126 | #else /* if ( portUSING_MPU_WRAPPERS == 1 ) */ 127 | #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) 128 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 129 | StackType_t * pxEndOfStack, 130 | TaskFunction_t pxCode, 131 | void * pvParameters ) PRIVILEGED_FUNCTION; 132 | #else 133 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 134 | TaskFunction_t pxCode, 135 | void * pvParameters ) PRIVILEGED_FUNCTION; 136 | #endif 137 | #endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */ 138 | 139 | /* Used by heap_5.c to define the start address and size of each memory region 140 | * that together comprise the total FreeRTOS heap space. */ 141 | typedef struct HeapRegion 142 | { 143 | uint8_t * pucStartAddress; 144 | size_t xSizeInBytes; 145 | } HeapRegion_t; 146 | 147 | /* Used to pass information about the heap out of vPortGetHeapStats(). */ 148 | typedef struct xHeapStats 149 | { 150 | size_t xAvailableHeapSpaceInBytes; /* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */ 151 | size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ 152 | size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ 153 | size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ 154 | size_t xMinimumEverFreeBytesRemaining; /* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */ 155 | size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ 156 | size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ 157 | } HeapStats_t; 158 | 159 | /* 160 | * Used to define multiple heap regions for use by heap_5.c. This function 161 | * must be called before any calls to pvPortMalloc() - not creating a task, 162 | * queue, semaphore, mutex, software timer, event group, etc. will result in 163 | * pvPortMalloc being called. 164 | * 165 | * pxHeapRegions passes in an array of HeapRegion_t structures - each of which 166 | * defines a region of memory that can be used as the heap. The array is 167 | * terminated by a HeapRegions_t structure that has a size of 0. The region 168 | * with the lowest start address must appear first in the array. 169 | */ 170 | void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; 171 | 172 | /* 173 | * Returns a HeapStats_t structure filled with information about the current 174 | * heap state. 175 | */ 176 | void vPortGetHeapStats( HeapStats_t * pxHeapStats ); 177 | 178 | /* 179 | * Map to the memory management routines required for the port. 180 | */ 181 | void * pvPortMalloc( size_t xWantedSize ) PRIVILEGED_FUNCTION; 182 | void * pvPortCalloc( size_t xNum, 183 | size_t xSize ) PRIVILEGED_FUNCTION; 184 | void vPortFree( void * pv ) PRIVILEGED_FUNCTION; 185 | void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; 186 | size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; 187 | size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; 188 | 189 | #if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 ) 190 | void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION; 191 | void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION; 192 | #else 193 | #define pvPortMallocStack pvPortMalloc 194 | #define vPortFreeStack vPortFree 195 | #endif 196 | 197 | /* 198 | * This function resets the internal state of the heap module. It must be called 199 | * by the application before restarting the scheduler. 200 | */ 201 | void vPortHeapResetState( void ) PRIVILEGED_FUNCTION; 202 | 203 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 204 | 205 | /** 206 | * task.h 207 | * @code{c} 208 | * void vApplicationMallocFailedHook( void ) 209 | * @endcode 210 | * 211 | * This hook function is called when allocation failed. 212 | */ 213 | void vApplicationMallocFailedHook( void ); 214 | #endif 215 | 216 | /* 217 | * Setup the hardware ready for the scheduler to take control. This generally 218 | * sets up a tick interrupt and sets timers for the correct tick frequency. 219 | */ 220 | BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; 221 | 222 | /* 223 | * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so 224 | * the hardware is left in its original condition after the scheduler stops 225 | * executing. 226 | */ 227 | void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; 228 | 229 | /* 230 | * The structures and methods of manipulating the MPU are contained within the 231 | * port layer. 232 | * 233 | * Fills the xMPUSettings structure with the memory region information 234 | * contained in xRegions. 235 | */ 236 | #if ( portUSING_MPU_WRAPPERS == 1 ) 237 | struct xMEMORY_REGION; 238 | void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, 239 | const struct xMEMORY_REGION * const xRegions, 240 | StackType_t * pxBottomOfStack, 241 | configSTACK_DEPTH_TYPE uxStackDepth ) PRIVILEGED_FUNCTION; 242 | #endif 243 | 244 | /** 245 | * @brief Checks if the calling task is authorized to access the given buffer. 246 | * 247 | * @param pvBuffer The buffer which the calling task wants to access. 248 | * @param ulBufferLength The length of the pvBuffer. 249 | * @param ulAccessRequested The permissions that the calling task wants. 250 | * 251 | * @return pdTRUE if the calling task is authorized to access the buffer, 252 | * pdFALSE otherwise. 253 | */ 254 | #if ( portUSING_MPU_WRAPPERS == 1 ) 255 | BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer, 256 | uint32_t ulBufferLength, 257 | uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION; 258 | #endif 259 | 260 | /** 261 | * @brief Checks if the calling task is authorized to access the given kernel object. 262 | * 263 | * @param lInternalIndexOfKernelObject The index of the kernel object in the kernel 264 | * object handle pool. 265 | * 266 | * @return pdTRUE if the calling task is authorized to access the kernel object, 267 | * pdFALSE otherwise. 268 | */ 269 | #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 270 | 271 | BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION; 272 | 273 | #endif 274 | 275 | /* *INDENT-OFF* */ 276 | #ifdef __cplusplus 277 | } 278 | #endif 279 | /* *INDENT-ON* */ 280 | 281 | #endif /* PORTABLE_H */ 282 | -------------------------------------------------------------------------------- /hooks.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2024 Phillip Stevens All Rights Reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | * this software and associated documentation files (the "Software"), to deal in 6 | * the Software without restriction, including without limitation the rights to 7 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 8 | * the Software, and to permit persons to whom the Software is furnished to do so, 9 | * subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in all 12 | * copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 16 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 17 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 18 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | * 21 | * 22 | * This file is NOT part of the FreeRTOS distribution. 23 | * 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | /* FreeRTOS includes. */ 34 | #include "FreeRTOS.h" 35 | #include "task.h" 36 | #include "timers.h" 37 | #include "stack_macros.h" 38 | 39 | /*-----------------------------------------------------------*/ 40 | #if ( configUSE_IDLE_HOOK == 1 ) 41 | 42 | void vApplicationIdleHook( void ) __attribute__ ((weak)); 43 | 44 | void vApplicationIdleHook( void ) 45 | { 46 | // Digital Input Disable on Analogue Pins 47 | // When this bit is written logic one, the digital input buffer on the corresponding ADC pin is disabled. 48 | // The corresponding PIN Register bit will always read as zero when this bit is set. When an 49 | // analogue signal is applied to the ADC7..0 pin and the digital input from this pin is not needed, this 50 | // bit should be written logic one to reduce power consumption in the digital input buffer. 51 | 52 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Arduino Mega with 2560 53 | DIDR0 = 0xFF; 54 | DIDR2 = 0xFF; 55 | 56 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // with 1284p 57 | DIDR0 = 0xFF; 58 | 59 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino with 328p 60 | DIDR0 = 0x3F; 61 | 62 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 63 | DIDR0 = 0xF3; 64 | DIDR2 = 0x3F; 65 | 66 | #endif 67 | 68 | // Analogue Comparator Disable 69 | // When the ACD bit is written logic one, the power to the Analogue Comparator is switched off. 70 | // This bit can be set at any time to turn off the Analogue Comparator. 71 | // This will reduce power consumption in Active and Idle mode. 72 | // When changing the ACD bit, the Analogue Comparator Interrupt must be disabled by clearing the ACIE bit in ACSR. 73 | // Otherwise an interrupt can occur when the ACD bit is changed. 74 | ACSR &= ~_BV(ACIE); 75 | ACSR |= _BV(ACD); 76 | 77 | // There are several macros provided in this header file to actually put the device into sleep mode. 78 | // The simplest way is to optionally set the desired sleep mode using set_sleep_mode() 79 | // (it usually defaults to idle mode where the CPU is put on sleep but all peripheral clocks are still running), 80 | // and then call sleep_mode(). This macro automatically sets the sleep enable bit, 81 | // goes to sleep, and clears the sleep enable bit. 82 | 83 | // SLEEP_MODE_IDLE (0) 84 | // SLEEP_MODE_ADC _BV(SM0) 85 | // SLEEP_MODE_PWR_DOWN _BV(SM1) 86 | // SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1)) 87 | // SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2)) 88 | // SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2)) 89 | 90 | set_sleep_mode( SLEEP_MODE_IDLE ); 91 | 92 | portENTER_CRITICAL(); 93 | sleep_enable(); 94 | 95 | #if defined(BODS) && defined(BODSE) // only if there is support to disable the BOD. 96 | sleep_bod_disable(); 97 | #endif 98 | 99 | portEXIT_CRITICAL(); 100 | sleep_cpu(); // good night. 101 | 102 | sleep_reset(); // reset the sleep_mode() faster than sleep_disable(); 103 | } 104 | 105 | #endif /* configUSE_IDLE_HOOK == 1 */ 106 | /*-----------------------------------------------------------*/ 107 | 108 | 109 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 110 | 111 | void vApplicationMallocFailedHook( void ) __attribute__ ((weak)); 112 | 113 | void vApplicationMallocFailedHook( void ) 114 | { 115 | /*---------------------------------------------------------------------------*\ 116 | Usage: 117 | called by task system when a malloc failure is noticed 118 | Description: 119 | Malloc failure handler -- Shut down all interrupts, send serious complaint 120 | to command port. FAST Blink. 121 | Arguments: 122 | pxTask - pointer to task handle 123 | pcTaskName - pointer to task name 124 | Results: 125 | 126 | Notes: 127 | This routine will never return. 128 | This routine is referenced in the task.c file of FreeRTOS as an extern. 129 | \*---------------------------------------------------------------------------*/ 130 | 131 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Arduino Mega with 2560 132 | DDRB |= _BV(DDB7); 133 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 134 | 135 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 136 | DDRB |= _BV(DDB7); 137 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 138 | 139 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 140 | DDRB |= _BV(DDB5); 141 | PORTB |= _BV(PORTB5); // Main (red PB5) LED on. Main LED on. 142 | 143 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 144 | DDRC |= _BV(DDC7); 145 | PORTC |= _BV(PORTC7); // Main (red PC7) LED on. Main LED on. 146 | 147 | #endif 148 | 149 | for(;;) 150 | { 151 | _delay_ms(50); 152 | 153 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Mega with 2560 154 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. Main LED fast blink. 155 | 156 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 157 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. Main LED fast blink. 158 | 159 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 160 | PINB |= _BV(PINB5); // Main (red PB5) LED toggle. Main LED fast blink. 161 | 162 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 163 | PINC |= _BV(PINC7); // Main (red PC7) LED toggle. Main LED fast blink. 164 | 165 | #endif 166 | 167 | } 168 | } 169 | 170 | #endif /* configUSE_MALLOC_FAILED_HOOK == 1 */ 171 | /*-----------------------------------------------------------*/ 172 | 173 | 174 | #if ( configCHECK_FOR_STACK_OVERFLOW >= 1 ) 175 | 176 | void vApplicationStackOverflowHook( TaskHandle_t xTask, 177 | char * pcTaskName ) __attribute__ ((weak)); 178 | 179 | void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__ ((unused)), 180 | char * pcTaskName __attribute__ ((unused)) ) 181 | { 182 | /*---------------------------------------------------------------------------*\ 183 | Usage: 184 | called by task system when a stack overflow is noticed 185 | Description: 186 | Stack overflow handler -- Shut down all interrupts, send serious complaint 187 | to command port. SLOW Blink. 188 | Arguments: 189 | pxTask - pointer to task handle 190 | pcTaskName - pointer to task name 191 | Results: 192 | 193 | Notes: 194 | This routine will never return. 195 | This routine is referenced in the task.c file of FreeRTOS as an extern. 196 | \*---------------------------------------------------------------------------*/ 197 | 198 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Arduino Mega with 2560 199 | DDRB |= _BV(DDB7); 200 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 201 | 202 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 203 | DDRB |= _BV(DDB7); 204 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 205 | 206 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 207 | DDRB |= _BV(DDB5); 208 | PORTB |= _BV(PORTB5); // Main (red PB5) LED on. Main LED on. 209 | 210 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 211 | DDRC |= _BV(DDC7); 212 | PORTC |= _BV(PORTC7); // Main (red PC7) LED on. Main LED on. 213 | 214 | #endif 215 | 216 | for(;;) 217 | { 218 | _delay_ms(2000); 219 | 220 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Arduino Mega with 2560 221 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. Main LED slow blink. 222 | 223 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 224 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. Main LED slow blink. 225 | 226 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 227 | PINB |= _BV(PINB5); // Main (red PB5) LED toggle. Main LED slow blink. 228 | 229 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 230 | PINC |= _BV(PINC7); // Main (red PC7) LED toggle. Main LED slow blink. 231 | 232 | #endif 233 | 234 | } 235 | } 236 | 237 | #else 238 | 239 | void vApplicationStackOverflowHook( TaskHandle_t xTask, 240 | char * pcTaskName ) __attribute__ ((weak)); 241 | 242 | void vApplicationStackOverflowHook( TaskHandle_t xTask, 243 | char * pcTaskName ) 244 | { 245 | /*---------------------------------------------------------------------------*\ 246 | Usage: 247 | called by task system when a stack overflow is noticed 248 | Description: 249 | Stack overflow handler -- Shut down all interrupts, send serious complaint 250 | to command port. 251 | Arguments: 252 | pxTask - pointer to task handle 253 | pcTaskName - pointer to task name 254 | Results: 255 | 256 | Notes: 257 | This routine will never return. 258 | This routine is referenced in the task.c file of FreeRTOS as an extern. 259 | \*---------------------------------------------------------------------------*/ 260 | 261 | uint8_t* pC; 262 | uint16_t baud; 263 | 264 | extern uint8_t * LineBuffer; // line buffer on heap (with pvPortMalloc). 265 | 266 | /* shut down all interrupts */ 267 | portDISABLE_INTERRUPTS(); 268 | 269 | 270 | /* take over the command line buffer to generate our error message */ 271 | pC = (uint8_t*) LineBuffer; 272 | 273 | strcat_P( (char*) pC, PSTR("\r\n")); 274 | strcat( (char*) pC, (char*) pcTaskName ); 275 | strcat_P( (char*) pC, PSTR("\r\n")); 276 | 277 | pC = (uint8_t*) LineBuffer; 278 | 279 | /* Force the UART control register to be the way we want, just in case */ 280 | 281 | UCSR0C = ( _BV( UCSZ01 ) | _BV( UCSZ00 ) ); // 8 data bits 282 | UCSR0B = _BV( TXEN0 ); // only enable transmit 283 | UCSR0A = 0; 284 | 285 | /* Calculate the baud rate register value from the equation in the 286 | * data sheet. This calculation rounds to the nearest factor, which 287 | * means the resulting rate may be either faster or slower than the 288 | * desired rate (the old calculation was always faster). 289 | * 290 | * If the system clock is one of the Magic Frequencies, this 291 | * computation will result in the exact baud rate 292 | */ 293 | baud = ( ( ( configCPU_CLOCK_HZ / ( ( 16UL * 38400 ) / 2UL ) ) + 1UL ) / 2UL ) - 1UL; 294 | UBRR0 = baud; 295 | 296 | /* Send out the message, without interrupts. Hard wired to USART 0 */ 297 | while ( *pC ) 298 | { 299 | while (!(UCSR0A & (1 << UDRE0))); 300 | UDR0 = *pC; 301 | pC++; 302 | } 303 | 304 | while(1){ PINB |= _BV(PINB7); _delay_ms(100); } // main (red PB7) LED flash and die. 305 | } 306 | 307 | #endif /* configCHECK_FOR_STACK_OVERFLOW >= 1 */ 308 | /*-----------------------------------------------------------*/ 309 | 310 | #if ( configSUPPORT_STATIC_ALLOCATION >= 1 ) 311 | 312 | void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 313 | StackType_t ** ppxIdleTaskStackBuffer, 314 | configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ) __attribute__ ((weak)); 315 | 316 | void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 317 | StackType_t ** ppxIdleTaskStackBuffer, 318 | configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ) 319 | { 320 | static StaticTask_t xIdleTaskTCB; 321 | static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; 322 | 323 | *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; 324 | *ppxIdleTaskStackBuffer = uxIdleTaskStack; 325 | *puxIdleTaskStackSize = configMINIMAL_STACK_SIZE; 326 | } 327 | 328 | #if ( configUSE_TIMERS >= 1 ) 329 | 330 | void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, 331 | StackType_t ** ppxTimerTaskStackBuffer, 332 | configSTACK_DEPTH_TYPE * puxTimerTaskStackSize ) __attribute__ ((weak)); 333 | 334 | void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, 335 | StackType_t ** ppxTimerTaskStackBuffer, 336 | configSTACK_DEPTH_TYPE * puxTimerTaskStackSize ) 337 | { 338 | static StaticTask_t xTimerTaskTCB; 339 | static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; 340 | 341 | *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; 342 | *ppxTimerTaskStackBuffer = uxTimerTaskStack; 343 | *puxTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; 344 | } 345 | 346 | #endif /* configUSE_TIMERS >= 1 */ 347 | 348 | #endif /* configSUPPORT_STATIC_ALLOCATION >= 1 */ 349 | 350 | -------------------------------------------------------------------------------- /mpu_wrappers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef MPU_WRAPPERS_H 30 | #define MPU_WRAPPERS_H 31 | 32 | /* This file redefines API functions to be called through a wrapper macro, but 33 | * only for ports that are using the MPU. */ 34 | #if ( portUSING_MPU_WRAPPERS == 1 ) 35 | 36 | /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is 37 | * included from queue.c or task.c to prevent it from having an effect within 38 | * those files. */ 39 | #ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 40 | 41 | /* 42 | * Map standard (non MPU) API functions to equivalents that start 43 | * "MPU_". This will cause the application code to call the MPU_ 44 | * version, which wraps the non-MPU version with privilege promoting 45 | * then demoting code, so the kernel code always runs will full 46 | * privileges. 47 | */ 48 | 49 | /* Map standard task.h API functions to the MPU equivalents. */ 50 | #define vTaskDelay MPU_vTaskDelay 51 | #define xTaskDelayUntil MPU_xTaskDelayUntil 52 | #define xTaskAbortDelay MPU_xTaskAbortDelay 53 | #define uxTaskPriorityGet MPU_uxTaskPriorityGet 54 | #define eTaskGetState MPU_eTaskGetState 55 | #define vTaskGetInfo MPU_vTaskGetInfo 56 | #define vTaskSuspend MPU_vTaskSuspend 57 | #define vTaskResume MPU_vTaskResume 58 | #define xTaskGetTickCount MPU_xTaskGetTickCount 59 | #define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks 60 | #define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark 61 | #define uxTaskGetStackHighWaterMark2 MPU_uxTaskGetStackHighWaterMark2 62 | #define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag 63 | #define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag 64 | #define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer 65 | #define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer 66 | #define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle 67 | #define uxTaskGetSystemState MPU_uxTaskGetSystemState 68 | #define ulTaskGetIdleRunTimeCounter MPU_ulTaskGetIdleRunTimeCounter 69 | #define ulTaskGetIdleRunTimePercent MPU_ulTaskGetIdleRunTimePercent 70 | #define xTaskGenericNotify MPU_xTaskGenericNotify 71 | #define xTaskGenericNotifyWait MPU_xTaskGenericNotifyWait 72 | #define ulTaskGenericNotifyTake MPU_ulTaskGenericNotifyTake 73 | #define xTaskGenericNotifyStateClear MPU_xTaskGenericNotifyStateClear 74 | #define ulTaskGenericNotifyValueClear MPU_ulTaskGenericNotifyValueClear 75 | #define vTaskSetTimeOutState MPU_vTaskSetTimeOutState 76 | #define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut 77 | #define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle 78 | #define xTaskGetSchedulerState MPU_xTaskGetSchedulerState 79 | 80 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 81 | #define ulTaskGetRunTimeCounter MPU_ulTaskGetRunTimeCounter 82 | #define ulTaskGetRunTimePercent MPU_ulTaskGetRunTimePercent 83 | #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 84 | 85 | /* Privileged only wrappers for Task APIs. These are needed so that 86 | * the application can use opaque handles maintained in mpu_wrappers.c 87 | * with all the APIs. */ 88 | #define xTaskCreate MPU_xTaskCreate 89 | #define xTaskCreateStatic MPU_xTaskCreateStatic 90 | #define vTaskDelete MPU_vTaskDelete 91 | #define vTaskPrioritySet MPU_vTaskPrioritySet 92 | #define xTaskGetHandle MPU_xTaskGetHandle 93 | #define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook 94 | 95 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 96 | #define pcTaskGetName MPU_pcTaskGetName 97 | #define xTaskCreateRestricted MPU_xTaskCreateRestricted 98 | #define xTaskCreateRestrictedStatic MPU_xTaskCreateRestrictedStatic 99 | #define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions 100 | #define xTaskGetStaticBuffers MPU_xTaskGetStaticBuffers 101 | #define uxTaskPriorityGetFromISR MPU_uxTaskPriorityGetFromISR 102 | #define uxTaskBasePriorityGet MPU_uxTaskBasePriorityGet 103 | #define uxTaskBasePriorityGetFromISR MPU_uxTaskBasePriorityGetFromISR 104 | #define xTaskResumeFromISR MPU_xTaskResumeFromISR 105 | #define xTaskGetApplicationTaskTagFromISR MPU_xTaskGetApplicationTaskTagFromISR 106 | #define xTaskGenericNotifyFromISR MPU_xTaskGenericNotifyFromISR 107 | #define vTaskGenericNotifyGiveFromISR MPU_vTaskGenericNotifyGiveFromISR 108 | #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 109 | 110 | /* Map standard queue.h API functions to the MPU equivalents. */ 111 | #define xQueueGenericSend MPU_xQueueGenericSend 112 | #define xQueueReceive MPU_xQueueReceive 113 | #define xQueuePeek MPU_xQueuePeek 114 | #define xQueueSemaphoreTake MPU_xQueueSemaphoreTake 115 | #define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting 116 | #define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable 117 | #define xQueueGetMutexHolder MPU_xQueueGetMutexHolder 118 | #define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive 119 | #define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive 120 | #define xQueueAddToSet MPU_xQueueAddToSet 121 | #define xQueueSelectFromSet MPU_xQueueSelectFromSet 122 | 123 | #if ( configQUEUE_REGISTRY_SIZE > 0 ) 124 | #define vQueueAddToRegistry MPU_vQueueAddToRegistry 125 | #define vQueueUnregisterQueue MPU_vQueueUnregisterQueue 126 | #define pcQueueGetName MPU_pcQueueGetName 127 | #endif /* #if ( configQUEUE_REGISTRY_SIZE > 0 ) */ 128 | 129 | /* Privileged only wrappers for Queue APIs. These are needed so that 130 | * the application can use opaque handles maintained in mpu_wrappers.c 131 | * with all the APIs. */ 132 | #define vQueueDelete MPU_vQueueDelete 133 | #define xQueueCreateMutex MPU_xQueueCreateMutex 134 | #define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic 135 | #define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore 136 | #define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic 137 | #define xQueueGenericCreate MPU_xQueueGenericCreate 138 | #define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic 139 | #define xQueueGenericReset MPU_xQueueGenericReset 140 | #define xQueueCreateSet MPU_xQueueCreateSet 141 | #define xQueueRemoveFromSet MPU_xQueueRemoveFromSet 142 | 143 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 144 | #define xQueueGenericGetStaticBuffers MPU_xQueueGenericGetStaticBuffers 145 | #define xQueueGenericSendFromISR MPU_xQueueGenericSendFromISR 146 | #define xQueueGiveFromISR MPU_xQueueGiveFromISR 147 | #define xQueuePeekFromISR MPU_xQueuePeekFromISR 148 | #define xQueueReceiveFromISR MPU_xQueueReceiveFromISR 149 | #define xQueueIsQueueEmptyFromISR MPU_xQueueIsQueueEmptyFromISR 150 | #define xQueueIsQueueFullFromISR MPU_xQueueIsQueueFullFromISR 151 | #define uxQueueMessagesWaitingFromISR MPU_uxQueueMessagesWaitingFromISR 152 | #define xQueueGetMutexHolderFromISR MPU_xQueueGetMutexHolderFromISR 153 | #define xQueueSelectFromSetFromISR MPU_xQueueSelectFromSetFromISR 154 | #endif /* if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 155 | 156 | /* Map standard timer.h API functions to the MPU equivalents. */ 157 | #define pvTimerGetTimerID MPU_pvTimerGetTimerID 158 | #define vTimerSetTimerID MPU_vTimerSetTimerID 159 | #define xTimerIsTimerActive MPU_xTimerIsTimerActive 160 | #define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle 161 | #define xTimerGenericCommandFromTask MPU_xTimerGenericCommandFromTask 162 | #define pcTimerGetName MPU_pcTimerGetName 163 | #define vTimerSetReloadMode MPU_vTimerSetReloadMode 164 | #define uxTimerGetReloadMode MPU_uxTimerGetReloadMode 165 | #define xTimerGetPeriod MPU_xTimerGetPeriod 166 | #define xTimerGetExpiryTime MPU_xTimerGetExpiryTime 167 | 168 | /* Privileged only wrappers for Timer APIs. These are needed so that 169 | * the application can use opaque handles maintained in mpu_wrappers.c 170 | * with all the APIs. */ 171 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 172 | #define xTimerGetReloadMode MPU_xTimerGetReloadMode 173 | #define xTimerCreate MPU_xTimerCreate 174 | #define xTimerCreateStatic MPU_xTimerCreateStatic 175 | #define xTimerGetStaticBuffer MPU_xTimerGetStaticBuffer 176 | #define xTimerGenericCommandFromISR MPU_xTimerGenericCommandFromISR 177 | #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 178 | 179 | /* Map standard event_group.h API functions to the MPU equivalents. */ 180 | #define xEventGroupWaitBits MPU_xEventGroupWaitBits 181 | #define xEventGroupClearBits MPU_xEventGroupClearBits 182 | #define xEventGroupSetBits MPU_xEventGroupSetBits 183 | #define xEventGroupSync MPU_xEventGroupSync 184 | 185 | #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 186 | #define uxEventGroupGetNumber MPU_uxEventGroupGetNumber 187 | #define vEventGroupSetNumber MPU_vEventGroupSetNumber 188 | #endif /* #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */ 189 | 190 | /* Privileged only wrappers for Event Group APIs. These are needed so that 191 | * the application can use opaque handles maintained in mpu_wrappers.c 192 | * with all the APIs. */ 193 | #define xEventGroupCreate MPU_xEventGroupCreate 194 | #define xEventGroupCreateStatic MPU_xEventGroupCreateStatic 195 | #define vEventGroupDelete MPU_vEventGroupDelete 196 | 197 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 198 | #define xEventGroupGetStaticBuffer MPU_xEventGroupGetStaticBuffer 199 | #define xEventGroupClearBitsFromISR MPU_xEventGroupClearBitsFromISR 200 | #define xEventGroupSetBitsFromISR MPU_xEventGroupSetBitsFromISR 201 | #define xEventGroupGetBitsFromISR MPU_xEventGroupGetBitsFromISR 202 | #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 203 | 204 | /* Map standard message/stream_buffer.h API functions to the MPU 205 | * equivalents. */ 206 | #define xStreamBufferSend MPU_xStreamBufferSend 207 | #define xStreamBufferReceive MPU_xStreamBufferReceive 208 | #define xStreamBufferIsFull MPU_xStreamBufferIsFull 209 | #define xStreamBufferIsEmpty MPU_xStreamBufferIsEmpty 210 | #define xStreamBufferSpacesAvailable MPU_xStreamBufferSpacesAvailable 211 | #define xStreamBufferBytesAvailable MPU_xStreamBufferBytesAvailable 212 | #define xStreamBufferSetTriggerLevel MPU_xStreamBufferSetTriggerLevel 213 | #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes 214 | 215 | /* Privileged only wrappers for Stream Buffer APIs. These are needed so that 216 | * the application can use opaque handles maintained in mpu_wrappers.c 217 | * with all the APIs. */ 218 | 219 | #define xStreamBufferGenericCreate MPU_xStreamBufferGenericCreate 220 | #define xStreamBufferGenericCreateStatic MPU_xStreamBufferGenericCreateStatic 221 | #define vStreamBufferDelete MPU_vStreamBufferDelete 222 | #define xStreamBufferReset MPU_xStreamBufferReset 223 | 224 | #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) 225 | #define xStreamBufferGetStaticBuffers MPU_xStreamBufferGetStaticBuffers 226 | #define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR 227 | #define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR 228 | #define xStreamBufferSendCompletedFromISR MPU_xStreamBufferSendCompletedFromISR 229 | #define xStreamBufferReceiveCompletedFromISR MPU_xStreamBufferReceiveCompletedFromISR 230 | #define xStreamBufferResetFromISR MPU_xStreamBufferResetFromISR 231 | #endif /* #if ( configUSE_MPU_WRAPPERS_V1 == 0 ) */ 232 | 233 | #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) 234 | 235 | #define vGrantAccessToTask( xTask, xTaskToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToGrantAccess ) ) 236 | #define vRevokeAccessToTask( xTask, xTaskToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTaskToRevokeAccess ) ) 237 | 238 | #define vGrantAccessToSemaphore( xTask, xSemaphoreToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToGrantAccess ) ) 239 | #define vRevokeAccessToSemaphore( xTask, xSemaphoreToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xSemaphoreToRevokeAccess ) ) 240 | 241 | #define vGrantAccessToQueue( xTask, xQueueToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToGrantAccess ) ) 242 | #define vRevokeAccessToQueue( xTask, xQueueToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueToRevokeAccess ) ) 243 | 244 | #define vGrantAccessToQueueSet( xTask, xQueueSetToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToGrantAccess ) ) 245 | #define vRevokeAccessToQueueSet( xTask, xQueueSetToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xQueueSetToRevokeAccess ) ) 246 | 247 | #define vGrantAccessToEventGroup( xTask, xEventGroupToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToGrantAccess ) ) 248 | #define vRevokeAccessToEventGroup( xTask, xEventGroupToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xEventGroupToRevokeAccess ) ) 249 | 250 | #define vGrantAccessToStreamBuffer( xTask, xStreamBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToGrantAccess ) ) 251 | #define vRevokeAccessToStreamBuffer( xTask, xStreamBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xStreamBufferToRevokeAccess ) ) 252 | 253 | #define vGrantAccessToMessageBuffer( xTask, xMessageBufferToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToGrantAccess ) ) 254 | #define vRevokeAccessToMessageBuffer( xTask, xMessageBufferToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xMessageBufferToRevokeAccess ) ) 255 | 256 | #define vGrantAccessToTimer( xTask, xTimerToGrantAccess ) vGrantAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToGrantAccess ) ) 257 | #define vRevokeAccessToTimer( xTask, xTimerToRevokeAccess ) vRevokeAccessToKernelObject( ( xTask ), ( int32_t ) ( xTimerToRevokeAccess ) ) 258 | 259 | #endif /* #if ( ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */ 260 | 261 | #endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ 262 | 263 | #define PRIVILEGED_FUNCTION __attribute__( ( section( "privileged_functions" ) ) ) 264 | #define PRIVILEGED_DATA __attribute__( ( section( "privileged_data" ) ) ) 265 | #define FREERTOS_SYSTEM_CALL __attribute__( ( section( "freertos_system_calls" ) ) ) 266 | 267 | #else /* portUSING_MPU_WRAPPERS */ 268 | 269 | #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Mega with 2560 270 | #define PRIVILEGED_FUNCTION __attribute__ ((hot)) 271 | #define PRIVILEGED_DATA 272 | #define FREERTOS_SYSTEM_CALL __attribute__ ((hot)) 273 | #define portUSING_MPU_WRAPPERS 0 274 | #elif defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega664P__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Goldilocks with 1284p 275 | #define PRIVILEGED_FUNCTION __attribute__ ((hot)) 276 | #define PRIVILEGED_DATA 277 | #define FREERTOS_SYSTEM_CALL __attribute__ ((hot)) 278 | #define portUSING_MPU_WRAPPERS 0 279 | #else // Uno with 328p or Leonardo with 32u4 280 | #define PRIVILEGED_FUNCTION __attribute__ ((hot)) 281 | #define PRIVILEGED_DATA 282 | #define FREERTOS_SYSTEM_CALL __attribute__ ((hot)) 283 | #define portUSING_MPU_WRAPPERS 0 284 | #endif 285 | 286 | #endif /* portUSING_MPU_WRAPPERS */ 287 | 288 | 289 | #endif /* MPU_WRAPPERS_H */ 290 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | /* 30 | * This is the list implementation used by the scheduler. While it is tailored 31 | * heavily for the schedulers needs, it is also available for use by 32 | * application code. 33 | * 34 | * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a 35 | * numeric value (xItemValue). Most of the time the lists are sorted in 36 | * ascending item value order. 37 | * 38 | * Lists are created already containing one list item. The value of this 39 | * item is the maximum possible that can be stored, it is therefore always at 40 | * the end of the list and acts as a marker. The list member pxHead always 41 | * points to this marker - even though it is at the tail of the list. This 42 | * is because the tail contains a wrap back pointer to the true head of 43 | * the list. 44 | * 45 | * In addition to it's value, each list item contains a pointer to the next 46 | * item in the list (pxNext), a pointer to the list it is in (pxContainer) 47 | * and a pointer to back to the object that contains it. These later two 48 | * pointers are included for efficiency of list manipulation. There is 49 | * effectively a two way link between the object containing the list item and 50 | * the list item itself. 51 | * 52 | * 53 | * \page ListIntroduction List Implementation 54 | * \ingroup FreeRTOSIntro 55 | */ 56 | 57 | 58 | #ifndef LIST_H 59 | #define LIST_H 60 | 61 | #ifndef INC_FREERTOS_H 62 | #error "FreeRTOS.h must be included before list.h" 63 | #endif 64 | 65 | /* 66 | * The list structure members are modified from within interrupts, and therefore 67 | * by rights should be declared volatile. However, they are only modified in a 68 | * functionally atomic way (within critical sections of with the scheduler 69 | * suspended) and are either passed by reference into a function or indexed via 70 | * a volatile variable. Therefore, in all use cases tested so far, the volatile 71 | * qualifier can be omitted in order to provide a moderate performance 72 | * improvement without adversely affecting functional behaviour. The assembly 73 | * instructions generated by the IAR, ARM and GCC compilers when the respective 74 | * compiler's options were set for maximum optimisation has been inspected and 75 | * deemed to be as intended. That said, as compiler technology advances, and 76 | * especially if aggressive cross module optimisation is used (a use case that 77 | * has not been exercised to any great extend) then it is feasible that the 78 | * volatile qualifier will be needed for correct optimisation. It is expected 79 | * that a compiler removing essential code because, without the volatile 80 | * qualifier on the list structure members and with aggressive cross module 81 | * optimisation, the compiler deemed the code unnecessary will result in 82 | * complete and obvious failure of the scheduler. If this is ever experienced 83 | * then the volatile qualifier can be inserted in the relevant places within the 84 | * list structures by simply defining configLIST_VOLATILE to volatile in 85 | * FreeRTOSConfig.h (as per the example at the bottom of this comment block). 86 | * If configLIST_VOLATILE is not defined then the preprocessor directives below 87 | * will simply #define configLIST_VOLATILE away completely. 88 | * 89 | * To use volatile list structure members then add the following line to 90 | * FreeRTOSConfig.h (without the quotes): 91 | * "#define configLIST_VOLATILE volatile" 92 | */ 93 | #ifndef configLIST_VOLATILE 94 | #define configLIST_VOLATILE 95 | #endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ 96 | 97 | /* *INDENT-OFF* */ 98 | #ifdef __cplusplus 99 | extern "C" { 100 | #endif 101 | /* *INDENT-ON* */ 102 | 103 | /* Macros that can be used to place known values within the list structures, 104 | * then check that the known values do not get corrupted during the execution of 105 | * the application. These may catch the list data structures being overwritten in 106 | * memory. They will not catch data errors caused by incorrect configuration or 107 | * use of FreeRTOS.*/ 108 | #if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) 109 | /* Define the macros to do nothing. */ 110 | #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE 111 | #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE 112 | #define listFIRST_LIST_INTEGRITY_CHECK_VALUE 113 | #define listSECOND_LIST_INTEGRITY_CHECK_VALUE 114 | #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) 115 | #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) 116 | #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) 117 | #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) 118 | #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) 119 | #define listTEST_LIST_INTEGRITY( pxList ) 120 | #else /* if ( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) */ 121 | /* Define macros that add new members into the list structures. */ 122 | #define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; 123 | #define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; 124 | #define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; 125 | #define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; 126 | 127 | /* Define macros that set the new structure members to known values. */ 128 | #define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE 129 | #define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE 130 | #define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE 131 | #define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE 132 | 133 | /* Define macros that will assert if one of the structure members does not 134 | * contain its expected value. */ 135 | #define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) 136 | #define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) 137 | #endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ 138 | 139 | 140 | /* 141 | * Definition of the only type of object that a list can contain. 142 | */ 143 | struct xLIST; 144 | struct xLIST_ITEM 145 | { 146 | listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 147 | configLIST_VOLATILE TickType_t xItemValue; /**< The value being listed. In most cases this is used to sort the list in ascending order. */ 148 | struct xLIST_ITEM * configLIST_VOLATILE pxNext; /**< Pointer to the next ListItem_t in the list. */ 149 | struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; /**< Pointer to the previous ListItem_t in the list. */ 150 | void * pvOwner; /**< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ 151 | struct xLIST * configLIST_VOLATILE pxContainer; /**< Pointer to the list in which this list item is placed (if any). */ 152 | listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 153 | }; 154 | typedef struct xLIST_ITEM ListItem_t; 155 | 156 | #if ( configUSE_MINI_LIST_ITEM == 1 ) 157 | struct xMINI_LIST_ITEM 158 | { 159 | listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 160 | configLIST_VOLATILE TickType_t xItemValue; 161 | struct xLIST_ITEM * configLIST_VOLATILE pxNext; 162 | struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; 163 | }; 164 | typedef struct xMINI_LIST_ITEM MiniListItem_t; 165 | #else 166 | typedef struct xLIST_ITEM MiniListItem_t; 167 | #endif 168 | 169 | /* 170 | * Definition of the type of queue used by the scheduler. 171 | */ 172 | typedef struct xLIST 173 | { 174 | listFIRST_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 175 | configLIST_VOLATILE UBaseType_t uxNumberOfItems; 176 | ListItem_t * configLIST_VOLATILE pxIndex; /**< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ 177 | MiniListItem_t xListEnd; /**< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ 178 | listSECOND_LIST_INTEGRITY_CHECK_VALUE /**< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ 179 | } List_t; 180 | 181 | /* 182 | * Access macro to set the owner of a list item. The owner of a list item 183 | * is the object (usually a TCB) that contains the list item. 184 | * 185 | * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER 186 | * \ingroup LinkedList 187 | */ 188 | #define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) 189 | 190 | /* 191 | * Access macro to get the owner of a list item. The owner of a list item 192 | * is the object (usually a TCB) that contains the list item. 193 | * 194 | * \page listGET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER 195 | * \ingroup LinkedList 196 | */ 197 | #define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) 198 | 199 | /* 200 | * Access macro to set the value of the list item. In most cases the value is 201 | * used to sort the list in ascending order. 202 | * 203 | * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE 204 | * \ingroup LinkedList 205 | */ 206 | #define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) 207 | 208 | /* 209 | * Access macro to retrieve the value of the list item. The value can 210 | * represent anything - for example the priority of a task, or the time at 211 | * which a task should be unblocked. 212 | * 213 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE 214 | * \ingroup LinkedList 215 | */ 216 | #define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) 217 | 218 | /* 219 | * Access macro to retrieve the value of the list item at the head of a given 220 | * list. 221 | * 222 | * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE 223 | * \ingroup LinkedList 224 | */ 225 | #define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) 226 | 227 | /* 228 | * Return the list item at the head of the list. 229 | * 230 | * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY 231 | * \ingroup LinkedList 232 | */ 233 | #define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) 234 | 235 | /* 236 | * Return the next list item. 237 | * 238 | * \page listGET_NEXT listGET_NEXT 239 | * \ingroup LinkedList 240 | */ 241 | #define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) 242 | 243 | /* 244 | * Return the list item that marks the end of the list 245 | * 246 | * \page listGET_END_MARKER listGET_END_MARKER 247 | * \ingroup LinkedList 248 | */ 249 | #define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) 250 | 251 | /* 252 | * Access macro to determine if a list contains any items. The macro will 253 | * only have the value true if the list is empty. 254 | * 255 | * \page listLIST_IS_EMPTY listLIST_IS_EMPTY 256 | * \ingroup LinkedList 257 | */ 258 | #define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE ) 259 | 260 | /* 261 | * Access macro to return the number of items in the list. 262 | */ 263 | #define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) 264 | 265 | /* 266 | * Access function to obtain the owner of the next entry in a list. 267 | * 268 | * The list member pxIndex is used to walk through a list. Calling 269 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list 270 | * and returns that entry's pxOwner parameter. Using multiple calls to this 271 | * function it is therefore possible to move through every item contained in 272 | * a list. 273 | * 274 | * The pxOwner parameter of a list item is a pointer to the object that owns 275 | * the list item. In the scheduler this is normally a task control block. 276 | * The pxOwner parameter effectively creates a two way link between the list 277 | * item and its owner. 278 | * 279 | * @param pxTCB pxTCB is set to the address of the owner of the next list item. 280 | * @param pxList The list from which the next item owner is to be returned. 281 | * 282 | * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY 283 | * \ingroup LinkedList 284 | */ 285 | #if ( configNUMBER_OF_CORES == 1 ) 286 | #define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ 287 | do { \ 288 | List_t * const pxConstList = ( pxList ); \ 289 | /* Increment the index to the next item and return the item, ensuring */ \ 290 | /* we don't return the marker used at the end of the list. */ \ 291 | ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ 292 | if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ 293 | { \ 294 | ( pxConstList )->pxIndex = ( pxConstList )->xListEnd.pxNext; \ 295 | } \ 296 | ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ 297 | } while( 0 ) 298 | #else /* #if ( configNUMBER_OF_CORES == 1 ) */ 299 | 300 | /* This function is not required in SMP. FreeRTOS SMP scheduler doesn't use 301 | * pxIndex and it should always point to the xListEnd. Not defining this macro 302 | * here to prevent updating pxIndex. 303 | */ 304 | #endif /* #if ( configNUMBER_OF_CORES == 1 ) */ 305 | 306 | /* 307 | * Version of uxListRemove() that does not return a value. Provided as a slight 308 | * optimisation for xTaskIncrementTick() by being inline. 309 | * 310 | * Remove an item from a list. The list item has a pointer to the list that 311 | * it is in, so only the list item need be passed into the function. 312 | * 313 | * @param uxListRemove The item to be removed. The item will remove itself from 314 | * the list pointed to by it's pxContainer parameter. 315 | * 316 | * @return The number of items that remain in the list after the list item has 317 | * been removed. 318 | * 319 | * \page listREMOVE_ITEM listREMOVE_ITEM 320 | * \ingroup LinkedList 321 | */ 322 | #define listREMOVE_ITEM( pxItemToRemove ) \ 323 | do { \ 324 | /* The list item knows which list it is in. Obtain the list from the list \ 325 | * item. */ \ 326 | List_t * const pxList = ( pxItemToRemove )->pxContainer; \ 327 | \ 328 | ( pxItemToRemove )->pxNext->pxPrevious = ( pxItemToRemove )->pxPrevious; \ 329 | ( pxItemToRemove )->pxPrevious->pxNext = ( pxItemToRemove )->pxNext; \ 330 | /* Make sure the index is left pointing to a valid item. */ \ 331 | if( pxList->pxIndex == ( pxItemToRemove ) ) \ 332 | { \ 333 | pxList->pxIndex = ( pxItemToRemove )->pxPrevious; \ 334 | } \ 335 | \ 336 | ( pxItemToRemove )->pxContainer = NULL; \ 337 | ( ( pxList )->uxNumberOfItems ) = ( UBaseType_t ) ( ( ( pxList )->uxNumberOfItems ) - 1U ); \ 338 | } while( 0 ) 339 | 340 | /* 341 | * Inline version of vListInsertEnd() to provide slight optimisation for 342 | * xTaskIncrementTick(). 343 | * 344 | * Insert a list item into a list. The item will be inserted in a position 345 | * such that it will be the last item within the list returned by multiple 346 | * calls to listGET_OWNER_OF_NEXT_ENTRY. 347 | * 348 | * The list member pxIndex is used to walk through a list. Calling 349 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. 350 | * Placing an item in a list using vListInsertEnd effectively places the item 351 | * in the list position pointed to by pxIndex. This means that every other 352 | * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before 353 | * the pxIndex parameter again points to the item being inserted. 354 | * 355 | * @param pxList The list into which the item is to be inserted. 356 | * 357 | * @param pxNewListItem The list item to be inserted into the list. 358 | * 359 | * \page listINSERT_END listINSERT_END 360 | * \ingroup LinkedList 361 | */ 362 | #define listINSERT_END( pxList, pxNewListItem ) \ 363 | do { \ 364 | ListItem_t * const pxIndex = ( pxList )->pxIndex; \ 365 | \ 366 | /* Only effective when configASSERT() is also defined, these tests may catch \ 367 | * the list data structures being overwritten in memory. They will not catch \ 368 | * data errors caused by incorrect configuration or use of FreeRTOS. */ \ 369 | listTEST_LIST_INTEGRITY( ( pxList ) ); \ 370 | listTEST_LIST_ITEM_INTEGRITY( ( pxNewListItem ) ); \ 371 | \ 372 | /* Insert a new list item into ( pxList ), but rather than sort the list, \ 373 | * makes the new list item the last item to be removed by a call to \ 374 | * listGET_OWNER_OF_NEXT_ENTRY(). */ \ 375 | ( pxNewListItem )->pxNext = pxIndex; \ 376 | ( pxNewListItem )->pxPrevious = pxIndex->pxPrevious; \ 377 | \ 378 | pxIndex->pxPrevious->pxNext = ( pxNewListItem ); \ 379 | pxIndex->pxPrevious = ( pxNewListItem ); \ 380 | \ 381 | /* Remember which list the item is in. */ \ 382 | ( pxNewListItem )->pxContainer = ( pxList ); \ 383 | \ 384 | ( ( pxList )->uxNumberOfItems ) = ( UBaseType_t ) ( ( ( pxList )->uxNumberOfItems ) + 1U ); \ 385 | } while( 0 ) 386 | 387 | /* 388 | * Access function to obtain the owner of the first entry in a list. Lists 389 | * are normally sorted in ascending item value order. 390 | * 391 | * This function returns the pxOwner member of the first item in the list. 392 | * The pxOwner parameter of a list item is a pointer to the object that owns 393 | * the list item. In the scheduler this is normally a task control block. 394 | * The pxOwner parameter effectively creates a two way link between the list 395 | * item and its owner. 396 | * 397 | * @param pxList The list from which the owner of the head item is to be 398 | * returned. 399 | * 400 | * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY 401 | * \ingroup LinkedList 402 | */ 403 | #define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( ( &( ( pxList )->xListEnd ) )->pxNext->pvOwner ) 404 | 405 | /* 406 | * Check to see if a list item is within a list. The list item maintains a 407 | * "container" pointer that points to the list it is in. All this macro does 408 | * is check to see if the container and the list match. 409 | * 410 | * @param pxList The list we want to know if the list item is within. 411 | * @param pxListItem The list item we want to know if is in the list. 412 | * @return pdTRUE if the list item is in the list, otherwise pdFALSE. 413 | */ 414 | #define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( ( pxListItem )->pxContainer == ( pxList ) ) ? ( pdTRUE ) : ( pdFALSE ) ) 415 | 416 | /* 417 | * Return the list a list item is contained within (referenced from). 418 | * 419 | * @param pxListItem The list item being queried. 420 | * @return A pointer to the List_t object that references the pxListItem 421 | */ 422 | #define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pxContainer ) 423 | 424 | /* 425 | * This provides a crude means of knowing if a list has been initialised, as 426 | * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() 427 | * function. 428 | */ 429 | #define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) 430 | 431 | /* 432 | * Must be called before a list is used! This initialises all the members 433 | * of the list structure and inserts the xListEnd item into the list as a 434 | * marker to the back of the list. 435 | * 436 | * @param pxList Pointer to the list being initialised. 437 | * 438 | * \page vListInitialise vListInitialise 439 | * \ingroup LinkedList 440 | */ 441 | void vListInitialise( List_t * const pxList ) PRIVILEGED_FUNCTION; 442 | 443 | /* 444 | * Must be called before a list item is used. This sets the list container to 445 | * null so the item does not think that it is already contained in a list. 446 | * 447 | * @param pxItem Pointer to the list item being initialised. 448 | * 449 | * \page vListInitialiseItem vListInitialiseItem 450 | * \ingroup LinkedList 451 | */ 452 | void vListInitialiseItem( ListItem_t * const pxItem ) PRIVILEGED_FUNCTION; 453 | 454 | /* 455 | * Insert a list item into a list. The item will be inserted into the list in 456 | * a position determined by its item value (ascending item value order). 457 | * 458 | * @param pxList The list into which the item is to be inserted. 459 | * 460 | * @param pxNewListItem The item that is to be placed in the list. 461 | * 462 | * \page vListInsert vListInsert 463 | * \ingroup LinkedList 464 | */ 465 | void vListInsert( List_t * const pxList, 466 | ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; 467 | 468 | /* 469 | * Insert a list item into a list. The item will be inserted in a position 470 | * such that it will be the last item within the list returned by multiple 471 | * calls to listGET_OWNER_OF_NEXT_ENTRY. 472 | * 473 | * The list member pxIndex is used to walk through a list. Calling 474 | * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. 475 | * Placing an item in a list using vListInsertEnd effectively places the item 476 | * in the list position pointed to by pxIndex. This means that every other 477 | * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before 478 | * the pxIndex parameter again points to the item being inserted. 479 | * 480 | * @param pxList The list into which the item is to be inserted. 481 | * 482 | * @param pxNewListItem The list item to be inserted into the list. 483 | * 484 | * \page vListInsertEnd vListInsertEnd 485 | * \ingroup LinkedList 486 | */ 487 | void vListInsertEnd( List_t * const pxList, 488 | ListItem_t * const pxNewListItem ) PRIVILEGED_FUNCTION; 489 | 490 | /* 491 | * Remove an item from a list. The list item has a pointer to the list that 492 | * it is in, so only the list item need be passed into the function. 493 | * 494 | * @param uxListRemove The item to be removed. The item will remove itself from 495 | * the list pointed to by it's pxContainer parameter. 496 | * 497 | * @return The number of items that remain in the list after the list item has 498 | * been removed. 499 | * 500 | * \page uxListRemove uxListRemove 501 | * \ingroup LinkedList 502 | */ 503 | UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove ) PRIVILEGED_FUNCTION; 504 | 505 | /* *INDENT-OFF* */ 506 | #ifdef __cplusplus 507 | } 508 | #endif 509 | /* *INDENT-ON* */ 510 | 511 | #endif /* ifndef LIST_H */ 512 | -------------------------------------------------------------------------------- /event_groups.c: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | /* Standard includes. */ 30 | #include 31 | 32 | /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining 33 | * all the API functions to use the MPU wrappers. That should only be done when 34 | * task.h is included from an application file. */ 35 | #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE 36 | 37 | /* FreeRTOS includes. */ 38 | #include "FreeRTOS.h" 39 | #include "task.h" 40 | #include "timers.h" 41 | #include "event_groups.h" 42 | 43 | /* The MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined 44 | * for the header files above, but not in this file, in order to generate the 45 | * correct privileged Vs unprivileged linkage and placement. */ 46 | #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE 47 | 48 | /* This entire source file will be skipped if the application is not configured 49 | * to include event groups functionality. This #if is closed at the very bottom 50 | * of this file. If you want to include event groups then ensure 51 | * configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */ 52 | #if ( configUSE_EVENT_GROUPS == 1 ) 53 | 54 | typedef struct EventGroupDef_t 55 | { 56 | EventBits_t uxEventBits; 57 | List_t xTasksWaitingForBits; /**< List of tasks waiting for a bit to be set. */ 58 | 59 | #if ( configUSE_TRACE_FACILITY == 1 ) 60 | UBaseType_t uxEventGroupNumber; 61 | #endif 62 | 63 | #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) 64 | uint8_t ucStaticallyAllocated; /**< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */ 65 | #endif 66 | } EventGroup_t; 67 | 68 | /*-----------------------------------------------------------*/ 69 | 70 | /* 71 | * Test the bits set in uxCurrentEventBits to see if the wait condition is met. 72 | * The wait condition is defined by xWaitForAllBits. If xWaitForAllBits is 73 | * pdTRUE then the wait condition is met if all the bits set in uxBitsToWaitFor 74 | * are also set in uxCurrentEventBits. If xWaitForAllBits is pdFALSE then the 75 | * wait condition is met if any of the bits set in uxBitsToWait for are also set 76 | * in uxCurrentEventBits. 77 | */ 78 | static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, 79 | const EventBits_t uxBitsToWaitFor, 80 | const BaseType_t xWaitForAllBits ) PRIVILEGED_FUNCTION; 81 | 82 | /*-----------------------------------------------------------*/ 83 | 84 | #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 85 | 86 | EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) 87 | { 88 | EventGroup_t * pxEventBits; 89 | 90 | traceENTER_xEventGroupCreateStatic( pxEventGroupBuffer ); 91 | 92 | /* A StaticEventGroup_t object must be provided. */ 93 | configASSERT( pxEventGroupBuffer ); 94 | 95 | #if ( configASSERT_DEFINED == 1 ) 96 | { 97 | /* Sanity check that the size of the structure used to declare a 98 | * variable of type StaticEventGroup_t equals the size of the real 99 | * event group structure. */ 100 | volatile size_t xSize = sizeof( StaticEventGroup_t ); 101 | configASSERT( xSize == sizeof( EventGroup_t ) ); 102 | } 103 | #endif /* configASSERT_DEFINED */ 104 | 105 | /* The user has provided a statically allocated event group - use it. */ 106 | /* MISRA Ref 11.3.1 [Misaligned access] */ 107 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 108 | /* coverity[misra_c_2012_rule_11_3_violation] */ 109 | pxEventBits = ( EventGroup_t * ) pxEventGroupBuffer; 110 | 111 | if( pxEventBits != NULL ) 112 | { 113 | pxEventBits->uxEventBits = 0; 114 | vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); 115 | 116 | #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 117 | { 118 | /* Both static and dynamic allocation can be used, so note that 119 | * this event group was created statically in case the event group 120 | * is later deleted. */ 121 | pxEventBits->ucStaticallyAllocated = pdTRUE; 122 | } 123 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 124 | 125 | traceEVENT_GROUP_CREATE( pxEventBits ); 126 | } 127 | else 128 | { 129 | /* xEventGroupCreateStatic should only ever be called with 130 | * pxEventGroupBuffer pointing to a pre-allocated (compile time 131 | * allocated) StaticEventGroup_t variable. */ 132 | traceEVENT_GROUP_CREATE_FAILED(); 133 | } 134 | 135 | traceRETURN_xEventGroupCreateStatic( pxEventBits ); 136 | 137 | return pxEventBits; 138 | } 139 | 140 | #endif /* configSUPPORT_STATIC_ALLOCATION */ 141 | /*-----------------------------------------------------------*/ 142 | 143 | #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 144 | 145 | EventGroupHandle_t xEventGroupCreate( void ) 146 | { 147 | EventGroup_t * pxEventBits; 148 | 149 | traceENTER_xEventGroupCreate(); 150 | 151 | /* MISRA Ref 11.5.1 [Malloc memory assignment] */ 152 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 153 | /* coverity[misra_c_2012_rule_11_5_violation] */ 154 | pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); 155 | 156 | if( pxEventBits != NULL ) 157 | { 158 | pxEventBits->uxEventBits = 0; 159 | vListInitialise( &( pxEventBits->xTasksWaitingForBits ) ); 160 | 161 | #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 162 | { 163 | /* Both static and dynamic allocation can be used, so note this 164 | * event group was allocated statically in case the event group is 165 | * later deleted. */ 166 | pxEventBits->ucStaticallyAllocated = pdFALSE; 167 | } 168 | #endif /* configSUPPORT_STATIC_ALLOCATION */ 169 | 170 | traceEVENT_GROUP_CREATE( pxEventBits ); 171 | } 172 | else 173 | { 174 | traceEVENT_GROUP_CREATE_FAILED(); 175 | } 176 | 177 | traceRETURN_xEventGroupCreate( pxEventBits ); 178 | 179 | return pxEventBits; 180 | } 181 | 182 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 183 | /*-----------------------------------------------------------*/ 184 | 185 | EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, 186 | const EventBits_t uxBitsToSet, 187 | const EventBits_t uxBitsToWaitFor, 188 | TickType_t xTicksToWait ) 189 | { 190 | EventBits_t uxOriginalBitValue, uxReturn; 191 | EventGroup_t * pxEventBits = xEventGroup; 192 | BaseType_t xAlreadyYielded; 193 | BaseType_t xTimeoutOccurred = pdFALSE; 194 | 195 | traceENTER_xEventGroupSync( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTicksToWait ); 196 | 197 | configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 198 | configASSERT( uxBitsToWaitFor != 0 ); 199 | #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) 200 | { 201 | configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); 202 | } 203 | #endif 204 | 205 | vTaskSuspendAll(); 206 | { 207 | uxOriginalBitValue = pxEventBits->uxEventBits; 208 | 209 | ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet ); 210 | 211 | if( ( ( uxOriginalBitValue | uxBitsToSet ) & uxBitsToWaitFor ) == uxBitsToWaitFor ) 212 | { 213 | /* All the rendezvous bits are now set - no need to block. */ 214 | uxReturn = ( uxOriginalBitValue | uxBitsToSet ); 215 | 216 | /* Rendezvous always clear the bits. They will have been cleared 217 | * already unless this is the only task in the rendezvous. */ 218 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 219 | 220 | xTicksToWait = 0; 221 | } 222 | else 223 | { 224 | if( xTicksToWait != ( TickType_t ) 0 ) 225 | { 226 | traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ); 227 | 228 | /* Store the bits that the calling task is waiting for in the 229 | * task's event list item so the kernel knows when a match is 230 | * found. Then enter the blocked state. */ 231 | vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | eventCLEAR_EVENTS_ON_EXIT_BIT | eventWAIT_FOR_ALL_BITS ), xTicksToWait ); 232 | 233 | /* This assignment is obsolete as uxReturn will get set after 234 | * the task unblocks, but some compilers mistakenly generate a 235 | * warning about uxReturn being returned without being set if the 236 | * assignment is omitted. */ 237 | uxReturn = 0; 238 | } 239 | else 240 | { 241 | /* The rendezvous bits were not set, but no block time was 242 | * specified - just return the current event bit value. */ 243 | uxReturn = pxEventBits->uxEventBits; 244 | xTimeoutOccurred = pdTRUE; 245 | } 246 | } 247 | } 248 | xAlreadyYielded = xTaskResumeAll(); 249 | 250 | if( xTicksToWait != ( TickType_t ) 0 ) 251 | { 252 | if( xAlreadyYielded == pdFALSE ) 253 | { 254 | taskYIELD_WITHIN_API(); 255 | } 256 | else 257 | { 258 | mtCOVERAGE_TEST_MARKER(); 259 | } 260 | 261 | /* The task blocked to wait for its required bits to be set - at this 262 | * point either the required bits were set or the block time expired. If 263 | * the required bits were set they will have been stored in the task's 264 | * event list item, and they should now be retrieved then cleared. */ 265 | uxReturn = uxTaskResetEventItemValue(); 266 | 267 | if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) 268 | { 269 | /* The task timed out, just return the current event bit value. */ 270 | taskENTER_CRITICAL(); 271 | { 272 | uxReturn = pxEventBits->uxEventBits; 273 | 274 | /* Although the task got here because it timed out before the 275 | * bits it was waiting for were set, it is possible that since it 276 | * unblocked another task has set the bits. If this is the case 277 | * then it needs to clear the bits before exiting. */ 278 | if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor ) 279 | { 280 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 281 | } 282 | else 283 | { 284 | mtCOVERAGE_TEST_MARKER(); 285 | } 286 | } 287 | taskEXIT_CRITICAL(); 288 | 289 | xTimeoutOccurred = pdTRUE; 290 | } 291 | else 292 | { 293 | /* The task unblocked because the bits were set. */ 294 | } 295 | 296 | /* Control bits might be set as the task had blocked should not be 297 | * returned. */ 298 | uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; 299 | } 300 | 301 | traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ); 302 | 303 | /* Prevent compiler warnings when trace macros are not used. */ 304 | ( void ) xTimeoutOccurred; 305 | 306 | traceRETURN_xEventGroupSync( uxReturn ); 307 | 308 | return uxReturn; 309 | } 310 | /*-----------------------------------------------------------*/ 311 | 312 | EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, 313 | const EventBits_t uxBitsToWaitFor, 314 | const BaseType_t xClearOnExit, 315 | const BaseType_t xWaitForAllBits, 316 | TickType_t xTicksToWait ) 317 | { 318 | EventGroup_t * pxEventBits = xEventGroup; 319 | EventBits_t uxReturn, uxControlBits = 0; 320 | BaseType_t xWaitConditionMet, xAlreadyYielded; 321 | BaseType_t xTimeoutOccurred = pdFALSE; 322 | 323 | traceENTER_xEventGroupWaitBits( xEventGroup, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait ); 324 | 325 | /* Check the user is not attempting to wait on the bits used by the kernel 326 | * itself, and that at least one bit is being requested. */ 327 | configASSERT( xEventGroup ); 328 | configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 329 | configASSERT( uxBitsToWaitFor != 0 ); 330 | #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) 331 | { 332 | configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); 333 | } 334 | #endif 335 | 336 | vTaskSuspendAll(); 337 | { 338 | const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits; 339 | 340 | /* Check to see if the wait condition is already met or not. */ 341 | xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits ); 342 | 343 | if( xWaitConditionMet != pdFALSE ) 344 | { 345 | /* The wait condition has already been met so there is no need to 346 | * block. */ 347 | uxReturn = uxCurrentEventBits; 348 | xTicksToWait = ( TickType_t ) 0; 349 | 350 | /* Clear the wait bits if requested to do so. */ 351 | if( xClearOnExit != pdFALSE ) 352 | { 353 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 354 | } 355 | else 356 | { 357 | mtCOVERAGE_TEST_MARKER(); 358 | } 359 | } 360 | else if( xTicksToWait == ( TickType_t ) 0 ) 361 | { 362 | /* The wait condition has not been met, but no block time was 363 | * specified, so just return the current value. */ 364 | uxReturn = uxCurrentEventBits; 365 | xTimeoutOccurred = pdTRUE; 366 | } 367 | else 368 | { 369 | /* The task is going to block to wait for its required bits to be 370 | * set. uxControlBits are used to remember the specified behaviour of 371 | * this call to xEventGroupWaitBits() - for use when the event bits 372 | * unblock the task. */ 373 | if( xClearOnExit != pdFALSE ) 374 | { 375 | uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT; 376 | } 377 | else 378 | { 379 | mtCOVERAGE_TEST_MARKER(); 380 | } 381 | 382 | if( xWaitForAllBits != pdFALSE ) 383 | { 384 | uxControlBits |= eventWAIT_FOR_ALL_BITS; 385 | } 386 | else 387 | { 388 | mtCOVERAGE_TEST_MARKER(); 389 | } 390 | 391 | /* Store the bits that the calling task is waiting for in the 392 | * task's event list item so the kernel knows when a match is 393 | * found. Then enter the blocked state. */ 394 | vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait ); 395 | 396 | /* This is obsolete as it will get set after the task unblocks, but 397 | * some compilers mistakenly generate a warning about the variable 398 | * being returned without being set if it is not done. */ 399 | uxReturn = 0; 400 | 401 | traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ); 402 | } 403 | } 404 | xAlreadyYielded = xTaskResumeAll(); 405 | 406 | if( xTicksToWait != ( TickType_t ) 0 ) 407 | { 408 | if( xAlreadyYielded == pdFALSE ) 409 | { 410 | taskYIELD_WITHIN_API(); 411 | } 412 | else 413 | { 414 | mtCOVERAGE_TEST_MARKER(); 415 | } 416 | 417 | /* The task blocked to wait for its required bits to be set - at this 418 | * point either the required bits were set or the block time expired. If 419 | * the required bits were set they will have been stored in the task's 420 | * event list item, and they should now be retrieved then cleared. */ 421 | uxReturn = uxTaskResetEventItemValue(); 422 | 423 | if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 ) 424 | { 425 | taskENTER_CRITICAL(); 426 | { 427 | /* The task timed out, just return the current event bit value. */ 428 | uxReturn = pxEventBits->uxEventBits; 429 | 430 | /* It is possible that the event bits were updated between this 431 | * task leaving the Blocked state and running again. */ 432 | if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE ) 433 | { 434 | if( xClearOnExit != pdFALSE ) 435 | { 436 | pxEventBits->uxEventBits &= ~uxBitsToWaitFor; 437 | } 438 | else 439 | { 440 | mtCOVERAGE_TEST_MARKER(); 441 | } 442 | } 443 | else 444 | { 445 | mtCOVERAGE_TEST_MARKER(); 446 | } 447 | 448 | xTimeoutOccurred = pdTRUE; 449 | } 450 | taskEXIT_CRITICAL(); 451 | } 452 | else 453 | { 454 | /* The task unblocked because the bits were set. */ 455 | } 456 | 457 | /* The task blocked so control bits may have been set. */ 458 | uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES; 459 | } 460 | 461 | traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ); 462 | 463 | /* Prevent compiler warnings when trace macros are not used. */ 464 | ( void ) xTimeoutOccurred; 465 | 466 | traceRETURN_xEventGroupWaitBits( uxReturn ); 467 | 468 | return uxReturn; 469 | } 470 | /*-----------------------------------------------------------*/ 471 | 472 | EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 473 | const EventBits_t uxBitsToClear ) 474 | { 475 | EventGroup_t * pxEventBits = xEventGroup; 476 | EventBits_t uxReturn; 477 | 478 | traceENTER_xEventGroupClearBits( xEventGroup, uxBitsToClear ); 479 | 480 | /* Check the user is not attempting to clear the bits used by the kernel 481 | * itself. */ 482 | configASSERT( xEventGroup ); 483 | configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 484 | 485 | taskENTER_CRITICAL(); 486 | { 487 | traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ); 488 | 489 | /* The value returned is the event group value prior to the bits being 490 | * cleared. */ 491 | uxReturn = pxEventBits->uxEventBits; 492 | 493 | /* Clear the bits. */ 494 | pxEventBits->uxEventBits &= ~uxBitsToClear; 495 | } 496 | taskEXIT_CRITICAL(); 497 | 498 | traceRETURN_xEventGroupClearBits( uxReturn ); 499 | 500 | return uxReturn; 501 | } 502 | /*-----------------------------------------------------------*/ 503 | 504 | #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) 505 | 506 | BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, 507 | const EventBits_t uxBitsToClear ) 508 | { 509 | BaseType_t xReturn; 510 | 511 | traceENTER_xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ); 512 | 513 | traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ); 514 | xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL ); 515 | 516 | traceRETURN_xEventGroupClearBitsFromISR( xReturn ); 517 | 518 | return xReturn; 519 | } 520 | 521 | #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ 522 | /*-----------------------------------------------------------*/ 523 | 524 | EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) 525 | { 526 | UBaseType_t uxSavedInterruptStatus; 527 | EventGroup_t const * const pxEventBits = xEventGroup; 528 | EventBits_t uxReturn; 529 | 530 | traceENTER_xEventGroupGetBitsFromISR( xEventGroup ); 531 | 532 | /* MISRA Ref 4.7.1 [Return value shall be checked] */ 533 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#dir-47 */ 534 | /* coverity[misra_c_2012_directive_4_7_violation] */ 535 | uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); 536 | { 537 | uxReturn = pxEventBits->uxEventBits; 538 | } 539 | taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); 540 | 541 | traceRETURN_xEventGroupGetBitsFromISR( uxReturn ); 542 | 543 | return uxReturn; 544 | } 545 | /*-----------------------------------------------------------*/ 546 | 547 | EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, 548 | const EventBits_t uxBitsToSet ) 549 | { 550 | ListItem_t * pxListItem; 551 | ListItem_t * pxNext; 552 | ListItem_t const * pxListEnd; 553 | List_t const * pxList; 554 | EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits; 555 | EventGroup_t * pxEventBits = xEventGroup; 556 | BaseType_t xMatchFound = pdFALSE; 557 | 558 | traceENTER_xEventGroupSetBits( xEventGroup, uxBitsToSet ); 559 | 560 | /* Check the user is not attempting to set the bits used by the kernel 561 | * itself. */ 562 | configASSERT( xEventGroup ); 563 | configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 ); 564 | 565 | pxList = &( pxEventBits->xTasksWaitingForBits ); 566 | pxListEnd = listGET_END_MARKER( pxList ); 567 | vTaskSuspendAll(); 568 | { 569 | traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ); 570 | 571 | pxListItem = listGET_HEAD_ENTRY( pxList ); 572 | 573 | /* Set the bits. */ 574 | pxEventBits->uxEventBits |= uxBitsToSet; 575 | 576 | /* See if the new bit value should unblock any tasks. */ 577 | while( pxListItem != pxListEnd ) 578 | { 579 | pxNext = listGET_NEXT( pxListItem ); 580 | uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem ); 581 | xMatchFound = pdFALSE; 582 | 583 | /* Split the bits waited for from the control bits. */ 584 | uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES; 585 | uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES; 586 | 587 | if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 ) 588 | { 589 | /* Just looking for single bit being set. */ 590 | if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 ) 591 | { 592 | xMatchFound = pdTRUE; 593 | } 594 | else 595 | { 596 | mtCOVERAGE_TEST_MARKER(); 597 | } 598 | } 599 | else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor ) 600 | { 601 | /* All bits are set. */ 602 | xMatchFound = pdTRUE; 603 | } 604 | else 605 | { 606 | /* Need all bits to be set, but not all the bits were set. */ 607 | } 608 | 609 | if( xMatchFound != pdFALSE ) 610 | { 611 | /* The bits match. Should the bits be cleared on exit? */ 612 | if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 ) 613 | { 614 | uxBitsToClear |= uxBitsWaitedFor; 615 | } 616 | else 617 | { 618 | mtCOVERAGE_TEST_MARKER(); 619 | } 620 | 621 | /* Store the actual event flag value in the task's event list 622 | * item before removing the task from the event list. The 623 | * eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows 624 | * that is was unblocked due to its required bits matching, rather 625 | * than because it timed out. */ 626 | vTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET ); 627 | } 628 | 629 | /* Move onto the next list item. Note pxListItem->pxNext is not 630 | * used here as the list item may have been removed from the event list 631 | * and inserted into the ready/pending reading list. */ 632 | pxListItem = pxNext; 633 | } 634 | 635 | /* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT 636 | * bit was set in the control word. */ 637 | pxEventBits->uxEventBits &= ~uxBitsToClear; 638 | } 639 | ( void ) xTaskResumeAll(); 640 | 641 | traceRETURN_xEventGroupSetBits( pxEventBits->uxEventBits ); 642 | 643 | return pxEventBits->uxEventBits; 644 | } 645 | /*-----------------------------------------------------------*/ 646 | 647 | void vEventGroupDelete( EventGroupHandle_t xEventGroup ) 648 | { 649 | EventGroup_t * pxEventBits = xEventGroup; 650 | const List_t * pxTasksWaitingForBits; 651 | 652 | traceENTER_vEventGroupDelete( xEventGroup ); 653 | 654 | configASSERT( pxEventBits ); 655 | 656 | pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits ); 657 | 658 | vTaskSuspendAll(); 659 | { 660 | traceEVENT_GROUP_DELETE( xEventGroup ); 661 | 662 | while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( UBaseType_t ) 0 ) 663 | { 664 | /* Unblock the task, returning 0 as the event list is being deleted 665 | * and cannot therefore have any bits set. */ 666 | configASSERT( pxTasksWaitingForBits->xListEnd.pxNext != ( const ListItem_t * ) &( pxTasksWaitingForBits->xListEnd ) ); 667 | vTaskRemoveFromUnorderedEventList( pxTasksWaitingForBits->xListEnd.pxNext, eventUNBLOCKED_DUE_TO_BIT_SET ); 668 | } 669 | } 670 | ( void ) xTaskResumeAll(); 671 | 672 | #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) 673 | { 674 | /* The event group can only have been allocated dynamically - free 675 | * it again. */ 676 | vPortFree( pxEventBits ); 677 | } 678 | #elif ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) 679 | { 680 | /* The event group could have been allocated statically or 681 | * dynamically, so check before attempting to free the memory. */ 682 | if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) 683 | { 684 | vPortFree( pxEventBits ); 685 | } 686 | else 687 | { 688 | mtCOVERAGE_TEST_MARKER(); 689 | } 690 | } 691 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 692 | 693 | traceRETURN_vEventGroupDelete(); 694 | } 695 | /*-----------------------------------------------------------*/ 696 | 697 | #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 698 | BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, 699 | StaticEventGroup_t ** ppxEventGroupBuffer ) 700 | { 701 | BaseType_t xReturn; 702 | EventGroup_t * pxEventBits = xEventGroup; 703 | 704 | traceENTER_xEventGroupGetStaticBuffer( xEventGroup, ppxEventGroupBuffer ); 705 | 706 | configASSERT( pxEventBits ); 707 | configASSERT( ppxEventGroupBuffer ); 708 | 709 | #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 710 | { 711 | /* Check if the event group was statically allocated. */ 712 | if( pxEventBits->ucStaticallyAllocated == ( uint8_t ) pdTRUE ) 713 | { 714 | /* MISRA Ref 11.3.1 [Misaligned access] */ 715 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 716 | /* coverity[misra_c_2012_rule_11_3_violation] */ 717 | *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; 718 | xReturn = pdTRUE; 719 | } 720 | else 721 | { 722 | xReturn = pdFALSE; 723 | } 724 | } 725 | #else /* configSUPPORT_DYNAMIC_ALLOCATION */ 726 | { 727 | /* Event group must have been statically allocated. */ 728 | /* MISRA Ref 11.3.1 [Misaligned access] */ 729 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-113 */ 730 | /* coverity[misra_c_2012_rule_11_3_violation] */ 731 | *ppxEventGroupBuffer = ( StaticEventGroup_t * ) pxEventBits; 732 | xReturn = pdTRUE; 733 | } 734 | #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ 735 | 736 | traceRETURN_xEventGroupGetStaticBuffer( xReturn ); 737 | 738 | return xReturn; 739 | } 740 | #endif /* configSUPPORT_STATIC_ALLOCATION */ 741 | /*-----------------------------------------------------------*/ 742 | 743 | /* For internal use only - execute a 'set bits' command that was pended from 744 | * an interrupt. */ 745 | void vEventGroupSetBitsCallback( void * pvEventGroup, 746 | uint32_t ulBitsToSet ) 747 | { 748 | traceENTER_vEventGroupSetBitsCallback( pvEventGroup, ulBitsToSet ); 749 | 750 | /* MISRA Ref 11.5.4 [Callback function parameter] */ 751 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 752 | /* coverity[misra_c_2012_rule_11_5_violation] */ 753 | ( void ) xEventGroupSetBits( pvEventGroup, ( EventBits_t ) ulBitsToSet ); 754 | 755 | traceRETURN_vEventGroupSetBitsCallback(); 756 | } 757 | /*-----------------------------------------------------------*/ 758 | 759 | /* For internal use only - execute a 'clear bits' command that was pended from 760 | * an interrupt. */ 761 | void vEventGroupClearBitsCallback( void * pvEventGroup, 762 | uint32_t ulBitsToClear ) 763 | { 764 | traceENTER_vEventGroupClearBitsCallback( pvEventGroup, ulBitsToClear ); 765 | 766 | /* MISRA Ref 11.5.4 [Callback function parameter] */ 767 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 768 | /* coverity[misra_c_2012_rule_11_5_violation] */ 769 | ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear ); 770 | 771 | traceRETURN_vEventGroupClearBitsCallback(); 772 | } 773 | /*-----------------------------------------------------------*/ 774 | 775 | static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, 776 | const EventBits_t uxBitsToWaitFor, 777 | const BaseType_t xWaitForAllBits ) 778 | { 779 | BaseType_t xWaitConditionMet = pdFALSE; 780 | 781 | if( xWaitForAllBits == pdFALSE ) 782 | { 783 | /* Task only has to wait for one bit within uxBitsToWaitFor to be 784 | * set. Is one already set? */ 785 | if( ( uxCurrentEventBits & uxBitsToWaitFor ) != ( EventBits_t ) 0 ) 786 | { 787 | xWaitConditionMet = pdTRUE; 788 | } 789 | else 790 | { 791 | mtCOVERAGE_TEST_MARKER(); 792 | } 793 | } 794 | else 795 | { 796 | /* Task has to wait for all the bits in uxBitsToWaitFor to be set. 797 | * Are they set already? */ 798 | if( ( uxCurrentEventBits & uxBitsToWaitFor ) == uxBitsToWaitFor ) 799 | { 800 | xWaitConditionMet = pdTRUE; 801 | } 802 | else 803 | { 804 | mtCOVERAGE_TEST_MARKER(); 805 | } 806 | } 807 | 808 | return xWaitConditionMet; 809 | } 810 | /*-----------------------------------------------------------*/ 811 | 812 | #if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) 813 | 814 | BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 815 | const EventBits_t uxBitsToSet, 816 | BaseType_t * pxHigherPriorityTaskWoken ) 817 | { 818 | BaseType_t xReturn; 819 | 820 | traceENTER_xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ); 821 | 822 | traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ); 823 | xReturn = xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken ); 824 | 825 | traceRETURN_xEventGroupSetBitsFromISR( xReturn ); 826 | 827 | return xReturn; 828 | } 829 | 830 | #endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ 831 | /*-----------------------------------------------------------*/ 832 | 833 | #if ( configUSE_TRACE_FACILITY == 1 ) 834 | 835 | UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) 836 | { 837 | UBaseType_t xReturn; 838 | 839 | /* MISRA Ref 11.5.2 [Opaque pointer] */ 840 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 841 | /* coverity[misra_c_2012_rule_11_5_violation] */ 842 | EventGroup_t const * pxEventBits = ( EventGroup_t * ) xEventGroup; 843 | 844 | traceENTER_uxEventGroupGetNumber( xEventGroup ); 845 | 846 | if( xEventGroup == NULL ) 847 | { 848 | xReturn = 0; 849 | } 850 | else 851 | { 852 | xReturn = pxEventBits->uxEventGroupNumber; 853 | } 854 | 855 | traceRETURN_uxEventGroupGetNumber( xReturn ); 856 | 857 | return xReturn; 858 | } 859 | 860 | #endif /* configUSE_TRACE_FACILITY */ 861 | /*-----------------------------------------------------------*/ 862 | 863 | #if ( configUSE_TRACE_FACILITY == 1 ) 864 | 865 | void vEventGroupSetNumber( void * xEventGroup, 866 | UBaseType_t uxEventGroupNumber ) 867 | { 868 | traceENTER_vEventGroupSetNumber( xEventGroup, uxEventGroupNumber ); 869 | 870 | /* MISRA Ref 11.5.2 [Opaque pointer] */ 871 | /* More details at: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/MISRA.md#rule-115 */ 872 | /* coverity[misra_c_2012_rule_11_5_violation] */ 873 | ( ( EventGroup_t * ) xEventGroup )->uxEventGroupNumber = uxEventGroupNumber; 874 | 875 | traceRETURN_vEventGroupSetNumber(); 876 | } 877 | 878 | #endif /* configUSE_TRACE_FACILITY */ 879 | /*-----------------------------------------------------------*/ 880 | 881 | /* This entire source file will be skipped if the application is not configured 882 | * to include event groups functionality. If you want to include event groups 883 | * then ensure configUSE_EVENT_GROUPS is set to 1 in FreeRTOSConfig.h. */ 884 | #endif /* configUSE_EVENT_GROUPS == 1 */ 885 | -------------------------------------------------------------------------------- /event_groups.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FreeRTOS Kernel V11.1.0 3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: MIT 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | * this software and associated documentation files (the "Software"), to deal in 9 | * the Software without restriction, including without limitation the rights to 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | * the Software, and to permit persons to whom the Software is furnished to do so, 12 | * subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | * 24 | * https://www.FreeRTOS.org 25 | * https://github.com/FreeRTOS 26 | * 27 | */ 28 | 29 | #ifndef EVENT_GROUPS_H 30 | #define EVENT_GROUPS_H 31 | 32 | #ifndef INC_FREERTOS_H 33 | #error "include FreeRTOS.h" must appear in source files before "include event_groups.h" 34 | #endif 35 | 36 | /* FreeRTOS includes. */ 37 | #include "timers.h" 38 | 39 | /* The following bit fields convey control information in a task's event list 40 | * item value. It is important they don't clash with the 41 | * taskEVENT_LIST_ITEM_VALUE_IN_USE definition. */ 42 | #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) 43 | #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint16_t ) 0x0100U ) 44 | #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint16_t ) 0x0200U ) 45 | #define eventWAIT_FOR_ALL_BITS ( ( uint16_t ) 0x0400U ) 46 | #define eventEVENT_BITS_CONTROL_BYTES ( ( uint16_t ) 0xff00U ) 47 | #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) 48 | #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint32_t ) 0x01000000U ) 49 | #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint32_t ) 0x02000000U ) 50 | #define eventWAIT_FOR_ALL_BITS ( ( uint32_t ) 0x04000000U ) 51 | #define eventEVENT_BITS_CONTROL_BYTES ( ( uint32_t ) 0xff000000U ) 52 | #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_64_BITS ) 53 | #define eventCLEAR_EVENTS_ON_EXIT_BIT ( ( uint64_t ) 0x0100000000000000U ) 54 | #define eventUNBLOCKED_DUE_TO_BIT_SET ( ( uint64_t ) 0x0200000000000000U ) 55 | #define eventWAIT_FOR_ALL_BITS ( ( uint64_t ) 0x0400000000000000U ) 56 | #define eventEVENT_BITS_CONTROL_BYTES ( ( uint64_t ) 0xff00000000000000U ) 57 | #endif /* if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) */ 58 | 59 | /* *INDENT-OFF* */ 60 | #ifdef __cplusplus 61 | extern "C" { 62 | #endif 63 | /* *INDENT-ON* */ 64 | 65 | /** 66 | * An event group is a collection of bits to which an application can assign a 67 | * meaning. For example, an application may create an event group to convey 68 | * the status of various CAN bus related events in which bit 0 might mean "A CAN 69 | * message has been received and is ready for processing", bit 1 might mean "The 70 | * application has queued a message that is ready for sending onto the CAN 71 | * network", and bit 2 might mean "It is time to send a SYNC message onto the 72 | * CAN network" etc. A task can then test the bit values to see which events 73 | * are active, and optionally enter the Blocked state to wait for a specified 74 | * bit or a group of specified bits to be active. To continue the CAN bus 75 | * example, a CAN controlling task can enter the Blocked state (and therefore 76 | * not consume any processing time) until either bit 0, bit 1 or bit 2 are 77 | * active, at which time the bit that was actually active would inform the task 78 | * which action it had to take (process a received message, send a message, or 79 | * send a SYNC). 80 | * 81 | * The event groups implementation contains intelligence to avoid race 82 | * conditions that would otherwise occur were an application to use a simple 83 | * variable for the same purpose. This is particularly important with respect 84 | * to when a bit within an event group is to be cleared, and when bits have to 85 | * be set and then tested atomically - as is the case where event groups are 86 | * used to create a synchronisation point between multiple tasks (a 87 | * 'rendezvous'). 88 | */ 89 | 90 | 91 | 92 | /** 93 | * event_groups.h 94 | * 95 | * Type by which event groups are referenced. For example, a call to 96 | * xEventGroupCreate() returns an EventGroupHandle_t variable that can then 97 | * be used as a parameter to other event group functions. 98 | * 99 | * \defgroup EventGroupHandle_t EventGroupHandle_t 100 | * \ingroup EventGroup 101 | */ 102 | struct EventGroupDef_t; 103 | typedef struct EventGroupDef_t * EventGroupHandle_t; 104 | 105 | /* 106 | * The type that holds event bits always matches TickType_t - therefore the 107 | * number of bits it holds is set by configTICK_TYPE_WIDTH_IN_BITS (16 bits if set to 0, 108 | * 32 bits if set to 1, 64 bits if set to 2. 109 | * 110 | * \defgroup EventBits_t EventBits_t 111 | * \ingroup EventGroup 112 | */ 113 | typedef TickType_t EventBits_t; 114 | 115 | /** 116 | * event_groups.h 117 | * @code{c} 118 | * EventGroupHandle_t xEventGroupCreate( void ); 119 | * @endcode 120 | * 121 | * Create a new event group. 122 | * 123 | * Internally, within the FreeRTOS implementation, event groups use a [small] 124 | * block of memory, in which the event group's structure is stored. If an event 125 | * groups is created using xEventGroupCreate() then the required memory is 126 | * automatically dynamically allocated inside the xEventGroupCreate() function. 127 | * (see https://www.FreeRTOS.org/a00111.html). If an event group is created 128 | * using xEventGroupCreateStatic() then the application writer must instead 129 | * provide the memory that will get used by the event group. 130 | * xEventGroupCreateStatic() therefore allows an event group to be created 131 | * without using any dynamic memory allocation. 132 | * 133 | * Although event groups are not related to ticks, for internal implementation 134 | * reasons the number of bits available for use in an event group is dependent 135 | * on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If 136 | * configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit 137 | * 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has 138 | * 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then 139 | * each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type 140 | * is used to store event bits within an event group. 141 | * 142 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupCreate() 143 | * to be available. 144 | * 145 | * @return If the event group was created then a handle to the event group is 146 | * returned. If there was insufficient FreeRTOS heap available to create the 147 | * event group then NULL is returned. See https://www.FreeRTOS.org/a00111.html 148 | * 149 | * Example usage: 150 | * @code{c} 151 | * // Declare a variable to hold the created event group. 152 | * EventGroupHandle_t xCreatedEventGroup; 153 | * 154 | * // Attempt to create the event group. 155 | * xCreatedEventGroup = xEventGroupCreate(); 156 | * 157 | * // Was the event group created successfully? 158 | * if( xCreatedEventGroup == NULL ) 159 | * { 160 | * // The event group was not created because there was insufficient 161 | * // FreeRTOS heap available. 162 | * } 163 | * else 164 | * { 165 | * // The event group was created. 166 | * } 167 | * @endcode 168 | * \defgroup xEventGroupCreate xEventGroupCreate 169 | * \ingroup EventGroup 170 | */ 171 | #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) 172 | EventGroupHandle_t xEventGroupCreate( void ) PRIVILEGED_FUNCTION; 173 | #endif 174 | 175 | /** 176 | * event_groups.h 177 | * @code{c} 178 | * EventGroupHandle_t xEventGroupCreateStatic( EventGroupHandle_t * pxEventGroupBuffer ); 179 | * @endcode 180 | * 181 | * Create a new event group. 182 | * 183 | * Internally, within the FreeRTOS implementation, event groups use a [small] 184 | * block of memory, in which the event group's structure is stored. If an event 185 | * groups is created using xEventGroupCreate() then the required memory is 186 | * automatically dynamically allocated inside the xEventGroupCreate() function. 187 | * (see https://www.FreeRTOS.org/a00111.html). If an event group is created 188 | * using xEventGroupCreateStatic() then the application writer must instead 189 | * provide the memory that will get used by the event group. 190 | * xEventGroupCreateStatic() therefore allows an event group to be created 191 | * without using any dynamic memory allocation. 192 | * 193 | * Although event groups are not related to ticks, for internal implementation 194 | * reasons the number of bits available for use in an event group is dependent 195 | * on the configTICK_TYPE_WIDTH_IN_BITS setting in FreeRTOSConfig.h. If 196 | * configTICK_TYPE_WIDTH_IN_BITS is 0 then each event group contains 8 usable bits (bit 197 | * 0 to bit 7). If configTICK_TYPE_WIDTH_IN_BITS is set to 1 then each event group has 198 | * 24 usable bits (bit 0 to bit 23). If configTICK_TYPE_WIDTH_IN_BITS is set to 2 then 199 | * each event group has 56 usable bits (bit 0 to bit 53). The EventBits_t type 200 | * is used to store event bits within an event group. 201 | * 202 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupCreateStatic() 203 | * to be available. 204 | * 205 | * @param pxEventGroupBuffer pxEventGroupBuffer must point to a variable of type 206 | * StaticEventGroup_t, which will be then be used to hold the event group's data 207 | * structures, removing the need for the memory to be allocated dynamically. 208 | * 209 | * @return If the event group was created then a handle to the event group is 210 | * returned. If pxEventGroupBuffer was NULL then NULL is returned. 211 | * 212 | * Example usage: 213 | * @code{c} 214 | * // StaticEventGroup_t is a publicly accessible structure that has the same 215 | * // size and alignment requirements as the real event group structure. It is 216 | * // provided as a mechanism for applications to know the size of the event 217 | * // group (which is dependent on the architecture and configuration file 218 | * // settings) without breaking the strict data hiding policy by exposing the 219 | * // real event group internals. This StaticEventGroup_t variable is passed 220 | * // into the xSemaphoreCreateEventGroupStatic() function and is used to store 221 | * // the event group's data structures 222 | * StaticEventGroup_t xEventGroupBuffer; 223 | * 224 | * // Create the event group without dynamically allocating any memory. 225 | * xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer ); 226 | * @endcode 227 | */ 228 | #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 229 | EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) PRIVILEGED_FUNCTION; 230 | #endif 231 | 232 | /** 233 | * event_groups.h 234 | * @code{c} 235 | * EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, 236 | * const EventBits_t uxBitsToWaitFor, 237 | * const BaseType_t xClearOnExit, 238 | * const BaseType_t xWaitForAllBits, 239 | * const TickType_t xTicksToWait ); 240 | * @endcode 241 | * 242 | * [Potentially] block to wait for one or more bits to be set within a 243 | * previously created event group. 244 | * 245 | * This function cannot be called from an interrupt. 246 | * 247 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupWaitBits() 248 | * to be available. 249 | * 250 | * @param xEventGroup The event group in which the bits are being tested. The 251 | * event group must have previously been created using a call to 252 | * xEventGroupCreate(). 253 | * 254 | * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test 255 | * inside the event group. For example, to wait for bit 0 and/or bit 2 set 256 | * uxBitsToWaitFor to 0x05. To wait for bits 0 and/or bit 1 and/or bit 2 set 257 | * uxBitsToWaitFor to 0x07. Etc. 258 | * 259 | * @param xClearOnExit If xClearOnExit is set to pdTRUE then any bits within 260 | * uxBitsToWaitFor that are set within the event group will be cleared before 261 | * xEventGroupWaitBits() returns if the wait condition was met (if the function 262 | * returns for a reason other than a timeout). If xClearOnExit is set to 263 | * pdFALSE then the bits set in the event group are not altered when the call to 264 | * xEventGroupWaitBits() returns. 265 | * 266 | * @param xWaitForAllBits If xWaitForAllBits is set to pdTRUE then 267 | * xEventGroupWaitBits() will return when either all the bits in uxBitsToWaitFor 268 | * are set or the specified block time expires. If xWaitForAllBits is set to 269 | * pdFALSE then xEventGroupWaitBits() will return when any one of the bits set 270 | * in uxBitsToWaitFor is set or the specified block time expires. The block 271 | * time is specified by the xTicksToWait parameter. 272 | * 273 | * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait 274 | * for one/all (depending on the xWaitForAllBits value) of the bits specified by 275 | * uxBitsToWaitFor to become set. A value of portMAX_DELAY can be used to block 276 | * indefinitely (provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). 277 | * 278 | * @return The value of the event group at the time either the bits being waited 279 | * for became set, or the block time expired. Test the return value to know 280 | * which bits were set. If xEventGroupWaitBits() returned because its timeout 281 | * expired then not all the bits being waited for will be set. If 282 | * xEventGroupWaitBits() returned because the bits it was waiting for were set 283 | * then the returned value is the event group value before any bits were 284 | * automatically cleared in the case that xClearOnExit parameter was set to 285 | * pdTRUE. 286 | * 287 | * Example usage: 288 | * @code{c} 289 | * #define BIT_0 ( 1 << 0 ) 290 | * #define BIT_4 ( 1 << 4 ) 291 | * 292 | * void aFunction( EventGroupHandle_t xEventGroup ) 293 | * { 294 | * EventBits_t uxBits; 295 | * const TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; 296 | * 297 | * // Wait a maximum of 100ms for either bit 0 or bit 4 to be set within 298 | * // the event group. Clear the bits before exiting. 299 | * uxBits = xEventGroupWaitBits( 300 | * xEventGroup, // The event group being tested. 301 | * BIT_0 | BIT_4, // The bits within the event group to wait for. 302 | * pdTRUE, // BIT_0 and BIT_4 should be cleared before returning. 303 | * pdFALSE, // Don't wait for both bits, either bit will do. 304 | * xTicksToWait ); // Wait a maximum of 100ms for either bit to be set. 305 | * 306 | * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) 307 | * { 308 | * // xEventGroupWaitBits() returned because both bits were set. 309 | * } 310 | * else if( ( uxBits & BIT_0 ) != 0 ) 311 | * { 312 | * // xEventGroupWaitBits() returned because just BIT_0 was set. 313 | * } 314 | * else if( ( uxBits & BIT_4 ) != 0 ) 315 | * { 316 | * // xEventGroupWaitBits() returned because just BIT_4 was set. 317 | * } 318 | * else 319 | * { 320 | * // xEventGroupWaitBits() returned because xTicksToWait ticks passed 321 | * // without either BIT_0 or BIT_4 becoming set. 322 | * } 323 | * } 324 | * @endcode 325 | * \defgroup xEventGroupWaitBits xEventGroupWaitBits 326 | * \ingroup EventGroup 327 | */ 328 | EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, 329 | const EventBits_t uxBitsToWaitFor, 330 | const BaseType_t xClearOnExit, 331 | const BaseType_t xWaitForAllBits, 332 | TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; 333 | 334 | /** 335 | * event_groups.h 336 | * @code{c} 337 | * EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); 338 | * @endcode 339 | * 340 | * Clear bits within an event group. This function cannot be called from an 341 | * interrupt. 342 | * 343 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupClearBits() 344 | * to be available. 345 | * 346 | * @param xEventGroup The event group in which the bits are to be cleared. 347 | * 348 | * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear 349 | * in the event group. For example, to clear bit 3 only, set uxBitsToClear to 350 | * 0x08. To clear bit 3 and bit 0 set uxBitsToClear to 0x09. 351 | * 352 | * @return The value of the event group before the specified bits were cleared. 353 | * 354 | * Example usage: 355 | * @code{c} 356 | * #define BIT_0 ( 1 << 0 ) 357 | * #define BIT_4 ( 1 << 4 ) 358 | * 359 | * void aFunction( EventGroupHandle_t xEventGroup ) 360 | * { 361 | * EventBits_t uxBits; 362 | * 363 | * // Clear bit 0 and bit 4 in xEventGroup. 364 | * uxBits = xEventGroupClearBits( 365 | * xEventGroup, // The event group being updated. 366 | * BIT_0 | BIT_4 );// The bits being cleared. 367 | * 368 | * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) 369 | * { 370 | * // Both bit 0 and bit 4 were set before xEventGroupClearBits() was 371 | * // called. Both will now be clear (not set). 372 | * } 373 | * else if( ( uxBits & BIT_0 ) != 0 ) 374 | * { 375 | * // Bit 0 was set before xEventGroupClearBits() was called. It will 376 | * // now be clear. 377 | * } 378 | * else if( ( uxBits & BIT_4 ) != 0 ) 379 | * { 380 | * // Bit 4 was set before xEventGroupClearBits() was called. It will 381 | * // now be clear. 382 | * } 383 | * else 384 | * { 385 | * // Neither bit 0 nor bit 4 were set in the first place. 386 | * } 387 | * } 388 | * @endcode 389 | * \defgroup xEventGroupClearBits xEventGroupClearBits 390 | * \ingroup EventGroup 391 | */ 392 | EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, 393 | const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; 394 | 395 | /** 396 | * event_groups.h 397 | * @code{c} 398 | * BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); 399 | * @endcode 400 | * 401 | * A version of xEventGroupClearBits() that can be called from an interrupt. 402 | * 403 | * Setting bits in an event group is not a deterministic operation because there 404 | * are an unknown number of tasks that may be waiting for the bit or bits being 405 | * set. FreeRTOS does not allow nondeterministic operations to be performed 406 | * while interrupts are disabled, so protects event groups that are accessed 407 | * from tasks by suspending the scheduler rather than disabling interrupts. As 408 | * a result event groups cannot be accessed directly from an interrupt service 409 | * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the 410 | * timer task to have the clear operation performed in the context of the timer 411 | * task. 412 | * 413 | * @note If this function returns pdPASS then the timer task is ready to run 414 | * and a portYIELD_FROM_ISR(pdTRUE) should be executed to perform the needed 415 | * clear on the event group. This behavior is different from 416 | * xEventGroupSetBitsFromISR because the parameter xHigherPriorityTaskWoken is 417 | * not present. 418 | * 419 | * @param xEventGroup The event group in which the bits are to be cleared. 420 | * 421 | * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear. 422 | * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3 423 | * and bit 0 set uxBitsToClear to 0x09. 424 | * 425 | * @return If the request to execute the function was posted successfully then 426 | * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned 427 | * if the timer service queue was full. 428 | * 429 | * Example usage: 430 | * @code{c} 431 | * #define BIT_0 ( 1 << 0 ) 432 | * #define BIT_4 ( 1 << 4 ) 433 | * 434 | * // An event group which it is assumed has already been created by a call to 435 | * // xEventGroupCreate(). 436 | * EventGroupHandle_t xEventGroup; 437 | * 438 | * void anInterruptHandler( void ) 439 | * { 440 | * // Clear bit 0 and bit 4 in xEventGroup. 441 | * xResult = xEventGroupClearBitsFromISR( 442 | * xEventGroup, // The event group being updated. 443 | * BIT_0 | BIT_4 ); // The bits being set. 444 | * 445 | * if( xResult == pdPASS ) 446 | * { 447 | * // The message was posted successfully. 448 | * portYIELD_FROM_ISR(pdTRUE); 449 | * } 450 | * } 451 | * @endcode 452 | * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR 453 | * \ingroup EventGroup 454 | */ 455 | #if ( configUSE_TRACE_FACILITY == 1 ) 456 | BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, 457 | const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION; 458 | #else 459 | #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) \ 460 | xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToClear ), NULL ) 461 | #endif 462 | 463 | /** 464 | * event_groups.h 465 | * @code{c} 466 | * EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); 467 | * @endcode 468 | * 469 | * Set bits within an event group. 470 | * This function cannot be called from an interrupt. xEventGroupSetBitsFromISR() 471 | * is a version that can be called from an interrupt. 472 | * 473 | * Setting bits in an event group will automatically unblock tasks that are 474 | * blocked waiting for the bits. 475 | * 476 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupSetBits() 477 | * to be available. 478 | * 479 | * @param xEventGroup The event group in which the bits are to be set. 480 | * 481 | * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. 482 | * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 483 | * and bit 0 set uxBitsToSet to 0x09. 484 | * 485 | * @return The value of the event group at the time the call to 486 | * xEventGroupSetBits() returns. There are two reasons why the returned value 487 | * might have the bits specified by the uxBitsToSet parameter cleared. First, 488 | * if setting a bit results in a task that was waiting for the bit leaving the 489 | * blocked state then it is possible the bit will be cleared automatically 490 | * (see the xClearBitOnExit parameter of xEventGroupWaitBits()). Second, any 491 | * unblocked (or otherwise Ready state) task that has a priority above that of 492 | * the task that called xEventGroupSetBits() will execute and may change the 493 | * event group value before the call to xEventGroupSetBits() returns. 494 | * 495 | * Example usage: 496 | * @code{c} 497 | * #define BIT_0 ( 1 << 0 ) 498 | * #define BIT_4 ( 1 << 4 ) 499 | * 500 | * void aFunction( EventGroupHandle_t xEventGroup ) 501 | * { 502 | * EventBits_t uxBits; 503 | * 504 | * // Set bit 0 and bit 4 in xEventGroup. 505 | * uxBits = xEventGroupSetBits( 506 | * xEventGroup, // The event group being updated. 507 | * BIT_0 | BIT_4 );// The bits being set. 508 | * 509 | * if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) ) 510 | * { 511 | * // Both bit 0 and bit 4 remained set when the function returned. 512 | * } 513 | * else if( ( uxBits & BIT_0 ) != 0 ) 514 | * { 515 | * // Bit 0 remained set when the function returned, but bit 4 was 516 | * // cleared. It might be that bit 4 was cleared automatically as a 517 | * // task that was waiting for bit 4 was removed from the Blocked 518 | * // state. 519 | * } 520 | * else if( ( uxBits & BIT_4 ) != 0 ) 521 | * { 522 | * // Bit 4 remained set when the function returned, but bit 0 was 523 | * // cleared. It might be that bit 0 was cleared automatically as a 524 | * // task that was waiting for bit 0 was removed from the Blocked 525 | * // state. 526 | * } 527 | * else 528 | * { 529 | * // Neither bit 0 nor bit 4 remained set. It might be that a task 530 | * // was waiting for both of the bits to be set, and the bits were 531 | * // cleared as the task left the Blocked state. 532 | * } 533 | * } 534 | * @endcode 535 | * \defgroup xEventGroupSetBits xEventGroupSetBits 536 | * \ingroup EventGroup 537 | */ 538 | EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, 539 | const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION; 540 | 541 | /** 542 | * event_groups.h 543 | * @code{c} 544 | * BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ); 545 | * @endcode 546 | * 547 | * A version of xEventGroupSetBits() that can be called from an interrupt. 548 | * 549 | * Setting bits in an event group is not a deterministic operation because there 550 | * are an unknown number of tasks that may be waiting for the bit or bits being 551 | * set. FreeRTOS does not allow nondeterministic operations to be performed in 552 | * interrupts or from critical sections. Therefore xEventGroupSetBitsFromISR() 553 | * sends a message to the timer task to have the set operation performed in the 554 | * context of the timer task - where a scheduler lock is used in place of a 555 | * critical section. 556 | * 557 | * @param xEventGroup The event group in which the bits are to be set. 558 | * 559 | * @param uxBitsToSet A bitwise value that indicates the bit or bits to set. 560 | * For example, to set bit 3 only, set uxBitsToSet to 0x08. To set bit 3 561 | * and bit 0 set uxBitsToSet to 0x09. 562 | * 563 | * @param pxHigherPriorityTaskWoken As mentioned above, calling this function 564 | * will result in a message being sent to the timer daemon task. If the 565 | * priority of the timer daemon task is higher than the priority of the 566 | * currently running task (the task the interrupt interrupted) then 567 | * *pxHigherPriorityTaskWoken will be set to pdTRUE by 568 | * xEventGroupSetBitsFromISR(), indicating that a context switch should be 569 | * requested before the interrupt exits. For that reason 570 | * *pxHigherPriorityTaskWoken must be initialised to pdFALSE. See the 571 | * example code below. 572 | * 573 | * @return If the request to execute the function was posted successfully then 574 | * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned 575 | * if the timer service queue was full. 576 | * 577 | * Example usage: 578 | * @code{c} 579 | * #define BIT_0 ( 1 << 0 ) 580 | * #define BIT_4 ( 1 << 4 ) 581 | * 582 | * // An event group which it is assumed has already been created by a call to 583 | * // xEventGroupCreate(). 584 | * EventGroupHandle_t xEventGroup; 585 | * 586 | * void anInterruptHandler( void ) 587 | * { 588 | * BaseType_t xHigherPriorityTaskWoken, xResult; 589 | * 590 | * // xHigherPriorityTaskWoken must be initialised to pdFALSE. 591 | * xHigherPriorityTaskWoken = pdFALSE; 592 | * 593 | * // Set bit 0 and bit 4 in xEventGroup. 594 | * xResult = xEventGroupSetBitsFromISR( 595 | * xEventGroup, // The event group being updated. 596 | * BIT_0 | BIT_4 // The bits being set. 597 | * &xHigherPriorityTaskWoken ); 598 | * 599 | * // Was the message posted successfully? 600 | * if( xResult == pdPASS ) 601 | * { 602 | * // If xHigherPriorityTaskWoken is now set to pdTRUE then a context 603 | * // switch should be requested. The macro used is port specific and 604 | * // will be either portYIELD_FROM_ISR() or portEND_SWITCHING_ISR() - 605 | * // refer to the documentation page for the port being used. 606 | * portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); 607 | * } 608 | * } 609 | * @endcode 610 | * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR 611 | * \ingroup EventGroup 612 | */ 613 | #if ( configUSE_TRACE_FACILITY == 1 ) 614 | BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 615 | const EventBits_t uxBitsToSet, 616 | BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; 617 | #else 618 | #define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \ 619 | xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) ( xEventGroup ), ( uint32_t ) ( uxBitsToSet ), ( pxHigherPriorityTaskWoken ) ) 620 | #endif 621 | 622 | /** 623 | * event_groups.h 624 | * @code{c} 625 | * EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, 626 | * const EventBits_t uxBitsToSet, 627 | * const EventBits_t uxBitsToWaitFor, 628 | * TickType_t xTicksToWait ); 629 | * @endcode 630 | * 631 | * Atomically set bits within an event group, then wait for a combination of 632 | * bits to be set within the same event group. This functionality is typically 633 | * used to synchronise multiple tasks, where each task has to wait for the other 634 | * tasks to reach a synchronisation point before proceeding. 635 | * 636 | * This function cannot be used from an interrupt. 637 | * 638 | * The function will return before its block time expires if the bits specified 639 | * by the uxBitsToWait parameter are set, or become set within that time. In 640 | * this case all the bits specified by uxBitsToWait will be automatically 641 | * cleared before the function returns. 642 | * 643 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupSync() 644 | * to be available. 645 | * 646 | * @param xEventGroup The event group in which the bits are being tested. The 647 | * event group must have previously been created using a call to 648 | * xEventGroupCreate(). 649 | * 650 | * @param uxBitsToSet The bits to set in the event group before determining 651 | * if, and possibly waiting for, all the bits specified by the uxBitsToWait 652 | * parameter are set. 653 | * 654 | * @param uxBitsToWaitFor A bitwise value that indicates the bit or bits to test 655 | * inside the event group. For example, to wait for bit 0 and bit 2 set 656 | * uxBitsToWaitFor to 0x05. To wait for bits 0 and bit 1 and bit 2 set 657 | * uxBitsToWaitFor to 0x07. Etc. 658 | * 659 | * @param xTicksToWait The maximum amount of time (specified in 'ticks') to wait 660 | * for all of the bits specified by uxBitsToWaitFor to become set. 661 | * 662 | * @return The value of the event group at the time either the bits being waited 663 | * for became set, or the block time expired. Test the return value to know 664 | * which bits were set. If xEventGroupSync() returned because its timeout 665 | * expired then not all the bits being waited for will be set. If 666 | * xEventGroupSync() returned because all the bits it was waiting for were 667 | * set then the returned value is the event group value before any bits were 668 | * automatically cleared. 669 | * 670 | * Example usage: 671 | * @code{c} 672 | * // Bits used by the three tasks. 673 | * #define TASK_0_BIT ( 1 << 0 ) 674 | * #define TASK_1_BIT ( 1 << 1 ) 675 | * #define TASK_2_BIT ( 1 << 2 ) 676 | * 677 | * #define ALL_SYNC_BITS ( TASK_0_BIT | TASK_1_BIT | TASK_2_BIT ) 678 | * 679 | * // Use an event group to synchronise three tasks. It is assumed this event 680 | * // group has already been created elsewhere. 681 | * EventGroupHandle_t xEventBits; 682 | * 683 | * void vTask0( void *pvParameters ) 684 | * { 685 | * EventBits_t uxReturn; 686 | * TickType_t xTicksToWait = 100 / portTICK_PERIOD_MS; 687 | * 688 | * for( ;; ) 689 | * { 690 | * // Perform task functionality here. 691 | * 692 | * // Set bit 0 in the event flag to note this task has reached the 693 | * // sync point. The other two tasks will set the other two bits defined 694 | * // by ALL_SYNC_BITS. All three tasks have reached the synchronisation 695 | * // point when all the ALL_SYNC_BITS are set. Wait a maximum of 100ms 696 | * // for this to happen. 697 | * uxReturn = xEventGroupSync( xEventBits, TASK_0_BIT, ALL_SYNC_BITS, xTicksToWait ); 698 | * 699 | * if( ( uxReturn & ALL_SYNC_BITS ) == ALL_SYNC_BITS ) 700 | * { 701 | * // All three tasks reached the synchronisation point before the call 702 | * // to xEventGroupSync() timed out. 703 | * } 704 | * } 705 | * } 706 | * 707 | * void vTask1( void *pvParameters ) 708 | * { 709 | * for( ;; ) 710 | * { 711 | * // Perform task functionality here. 712 | * 713 | * // Set bit 1 in the event flag to note this task has reached the 714 | * // synchronisation point. The other two tasks will set the other two 715 | * // bits defined by ALL_SYNC_BITS. All three tasks have reached the 716 | * // synchronisation point when all the ALL_SYNC_BITS are set. Wait 717 | * // indefinitely for this to happen. 718 | * xEventGroupSync( xEventBits, TASK_1_BIT, ALL_SYNC_BITS, portMAX_DELAY ); 719 | * 720 | * // xEventGroupSync() was called with an indefinite block time, so 721 | * // this task will only reach here if the synchronisation was made by all 722 | * // three tasks, so there is no need to test the return value. 723 | * } 724 | * } 725 | * 726 | * void vTask2( void *pvParameters ) 727 | * { 728 | * for( ;; ) 729 | * { 730 | * // Perform task functionality here. 731 | * 732 | * // Set bit 2 in the event flag to note this task has reached the 733 | * // synchronisation point. The other two tasks will set the other two 734 | * // bits defined by ALL_SYNC_BITS. All three tasks have reached the 735 | * // synchronisation point when all the ALL_SYNC_BITS are set. Wait 736 | * // indefinitely for this to happen. 737 | * xEventGroupSync( xEventBits, TASK_2_BIT, ALL_SYNC_BITS, portMAX_DELAY ); 738 | * 739 | * // xEventGroupSync() was called with an indefinite block time, so 740 | * // this task will only reach here if the synchronisation was made by all 741 | * // three tasks, so there is no need to test the return value. 742 | * } 743 | * } 744 | * 745 | * @endcode 746 | * \defgroup xEventGroupSync xEventGroupSync 747 | * \ingroup EventGroup 748 | */ 749 | EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, 750 | const EventBits_t uxBitsToSet, 751 | const EventBits_t uxBitsToWaitFor, 752 | TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; 753 | 754 | 755 | /** 756 | * event_groups.h 757 | * @code{c} 758 | * EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup ); 759 | * @endcode 760 | * 761 | * Returns the current value of the bits in an event group. This function 762 | * cannot be used from an interrupt. 763 | * 764 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetBits() 765 | * to be available. 766 | * 767 | * @param xEventGroup The event group being queried. 768 | * 769 | * @return The event group bits at the time xEventGroupGetBits() was called. 770 | * 771 | * \defgroup xEventGroupGetBits xEventGroupGetBits 772 | * \ingroup EventGroup 773 | */ 774 | #define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( ( xEventGroup ), 0 ) 775 | 776 | /** 777 | * event_groups.h 778 | * @code{c} 779 | * EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ); 780 | * @endcode 781 | * 782 | * A version of xEventGroupGetBits() that can be called from an ISR. 783 | * 784 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetBitsFromISR() 785 | * to be available. 786 | * 787 | * @param xEventGroup The event group being queried. 788 | * 789 | * @return The event group bits at the time xEventGroupGetBitsFromISR() was called. 790 | * 791 | * \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR 792 | * \ingroup EventGroup 793 | */ 794 | EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; 795 | 796 | /** 797 | * event_groups.h 798 | * @code{c} 799 | * void xEventGroupDelete( EventGroupHandle_t xEventGroup ); 800 | * @endcode 801 | * 802 | * Delete an event group that was previously created by a call to 803 | * xEventGroupCreate(). Tasks that are blocked on the event group will be 804 | * unblocked and obtain 0 as the event group's value. 805 | * 806 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for vEventGroupDelete() 807 | * to be available. 808 | * 809 | * @param xEventGroup The event group being deleted. 810 | */ 811 | void vEventGroupDelete( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION; 812 | 813 | /** 814 | * event_groups.h 815 | * @code{c} 816 | * BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, 817 | * StaticEventGroup_t ** ppxEventGroupBuffer ); 818 | * @endcode 819 | * 820 | * Retrieve a pointer to a statically created event groups's data structure 821 | * buffer. It is the same buffer that is supplied at the time of creation. 822 | * 823 | * The configUSE_EVENT_GROUPS configuration constant must be set to 1 for xEventGroupGetStaticBuffer() 824 | * to be available. 825 | * 826 | * @param xEventGroup The event group for which to retrieve the buffer. 827 | * 828 | * @param ppxEventGroupBuffer Used to return a pointer to the event groups's 829 | * data structure buffer. 830 | * 831 | * @return pdTRUE if the buffer was retrieved, pdFALSE otherwise. 832 | */ 833 | #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) 834 | BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup, 835 | StaticEventGroup_t ** ppxEventGroupBuffer ) PRIVILEGED_FUNCTION; 836 | #endif /* configSUPPORT_STATIC_ALLOCATION */ 837 | 838 | /* For internal use only. */ 839 | void vEventGroupSetBitsCallback( void * pvEventGroup, 840 | uint32_t ulBitsToSet ) PRIVILEGED_FUNCTION; 841 | void vEventGroupClearBitsCallback( void * pvEventGroup, 842 | uint32_t ulBitsToClear ) PRIVILEGED_FUNCTION; 843 | 844 | 845 | #if ( configUSE_TRACE_FACILITY == 1 ) 846 | UBaseType_t uxEventGroupGetNumber( void * xEventGroup ) PRIVILEGED_FUNCTION; 847 | void vEventGroupSetNumber( void * xEventGroup, 848 | UBaseType_t uxEventGroupNumber ) PRIVILEGED_FUNCTION; 849 | #endif 850 | 851 | /* *INDENT-OFF* */ 852 | #ifdef __cplusplus 853 | } 854 | #endif 855 | /* *INDENT-ON* */ 856 | 857 | #endif /* EVENT_GROUPS_H */ 858 | --------------------------------------------------------------------------------