├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── platformio.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── doc ├── tick_sources.md └── tick_sources_timer0.cpp ├── examples ├── AnalogRead_DigitalRead │ └── AnalogRead_DigitalRead.ino ├── ArrayQueue │ └── ArrayQueue.ino ├── Assert │ └── Assert.ino ├── Blink_AnalogRead │ └── Blink_AnalogRead.ino ├── GoldilocksAnalogueTestSuite │ ├── GA_Header.h │ └── GoldilocksAnalogueTestSuite.ino ├── IntegerQueue │ └── IntegerQueue.ino ├── Interrupts │ └── Interrupts.ino ├── Mutex │ └── Mutex.ino ├── Notifications │ └── Notifications.ino ├── StructArray │ └── StructArray.ino ├── StructQueue │ └── StructQueue.ino ├── TaskStatus │ └── TaskStatus.ino └── TaskUtilities │ └── TaskUtilities.ino ├── keywords.txt ├── library.properties ├── readme.md └── src ├── .gitignore ├── Arduino_FreeRTOS.h ├── FreeRTOSConfig.h ├── FreeRTOSVariant.h ├── History.txt ├── LICENSE.md ├── event_groups.c ├── event_groups.h ├── heap_3.c ├── list.c ├── list.h ├── message_buffer.h ├── mpu_wrappers.h ├── port.c ├── portable.h ├── portmacro.h ├── projdefs.h ├── queue.c ├── queue.h ├── semphr.h ├── stack_macros.h ├── stream_buffer.c ├── stream_buffer.h ├── task.h ├── tasks.c ├── timers.c ├── timers.h └── variantHooks.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Line ending normalization 2 | * text=auto 3 | 4 | # Documents 5 | *.doc diff=astextplain 6 | *.DOC diff=astextplain 7 | *.docx diff=astextplain 8 | *.DOCX diff=astextplain 9 | *.dot diff=astextplain 10 | *.DOT diff=astextplain 11 | *.pdf diff=astextplain 12 | *.PDF diff=astextplain 13 | *.rtf diff=astextplain 14 | *.RTF diff=astextplain 15 | *.md text 16 | *.adoc text 17 | *.textile text 18 | *.mustache text 19 | *.csv text 20 | *.tab text 21 | *.tsv text 22 | *.sql text 23 | *.html text 24 | *.css text 25 | 26 | # Graphics 27 | *.png binary 28 | *.jpg binary 29 | *.jpeg binary 30 | *.gif binary 31 | *.tif binary 32 | *.tiff binary 33 | *.ico binary 34 | *.svg binary 35 | *.eps binary 36 | 37 | #sources 38 | *.c text 39 | *.cc text 40 | *.cxx text 41 | *.cpp text 42 | *.c++ text 43 | *.hpp text 44 | *.h text 45 | *.h++ text 46 | *.hh text 47 | *.s text 48 | *.S text 49 | *.inc text 50 | *.asm text 51 | 52 | # Compiled Object files 53 | *.slo binary 54 | *.lo binary 55 | *.o binary 56 | *.obj binary 57 | 58 | # Compiled Dynamic libraries 59 | *.so binary 60 | *.dylib binary 61 | *.dll binary 62 | 63 | # Compiled Static libraries 64 | *.lai binary 65 | *.la binary 66 | *.a binary 67 | *.lib binary 68 | 69 | # Executables 70 | *.exe binary 71 | *.out binary 72 | *.app binary 73 | *.bin binary 74 | 75 | *.sh text 76 | make text 77 | makefile text 78 | *.mk text 79 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the issue** 11 | A clear and concise description of the issue. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Screenshots** 17 | If applicable, add screenshots to help explain your problem. 18 | 19 | **Desktop (please complete the following information):** 20 | - OS: [e.g. iOS] 21 | - Browser [e.g. chrome, safari] 22 | - Version [e.g. 22] 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /.github/workflows/platformio.yml: -------------------------------------------------------------------------------- 1 | name: Test PlatformIO support 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | example: 17 | - examples/AnalogRead_DigitalRead/AnalogRead_DigitalRead.ino 18 | - examples/ArrayQueue/ArrayQueue.ino 19 | - examples/Assert/Assert.ino 20 | - examples/Blink_AnalogRead/Blink_AnalogRead.ino 21 | - examples/IntegerQueue/IntegerQueue.ino 22 | - examples/Interrupts/Interrupts.ino 23 | - examples/Mutex/Mutex.ino 24 | - examples/Notifications/Notifications.ino 25 | - examples/StructArray/StructArray.ino 26 | - examples/StructQueue/StructQueue.ino 27 | - examples/TaskStatus/TaskStatus.ino 28 | - examples/TaskUtilities/TaskUtilities.ino 29 | 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v3 33 | 34 | - name: Cache 35 | uses: actions/cache@v3 36 | with: 37 | path: | 38 | ~/.cache/pip 39 | ~/.platformio/.cache 40 | key: ${{ runner.os }}-pio 41 | 42 | - name: Install python 43 | uses: actions/setup-python@v4 44 | with: 45 | python-version: '3.10' 46 | 47 | - name: Install PlatformIO Core 48 | run: pip install --upgrade platformio 49 | 50 | - name: Build PlatformIO examples 51 | run: pio ci --lib="." --board=uno --board=leonardo --board=sanguino_atmega1284p --board=megaatmega2560 ${{ matrix.example }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore .development file, https://arduino.github.io/arduino-cli/library-specification/#development-flag-file 2 | .development 3 | 4 | # Ignore CLion IDE folder 5 | .idea 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at phillip.stevens@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, 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, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /doc/tick_sources.md: -------------------------------------------------------------------------------- 1 | # Scheduler tick sources 2 | 3 | ## Configuration 4 | Tick source is selected by (un)defining values `portUSE_WDTO` and `portUSE_TIMER0` in file `FreeRTOSVariant.h`. Default in Arduino_FreeRTOS is Watchdog timer (WDT), it contains all code needed for this and works out-of-the-box. 5 | 6 | For alternative tick source, pieces of code must be provided by the application. Arduino_FreeRTOS expects you to provide function `void prvSetupTimerInterrupt(void)` responsible for the initialisation of your tick source. This function is called after the Arduino's initialisation and before the FreeRTOS scheduler is launched. 7 | 8 | NOTE: Reconfiguring Timer0 for FreeRTOS will break Arduino `millis()` and `micros()`, as these functions rely on Timer0. Functions relying on these Arduino features need to be overridden. 9 | 10 | ## WDT (default) 11 | 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. 12 | 13 | Watchdog period options: 14 | * `WDTO_15MS` (default) 15 | * `WDTO_30MS` 16 | * `WDTO_60MS` 17 | * `WDTO_120MS` 18 | * `WDTO_250MS` 19 | * `WDTO_500MS` 20 | * `WDTO_1S` 21 | * `WDTO_2S` 22 | 23 | ### WDT precision limitations 24 | The frequency of the Watchdog Oscillator is voltage and temperature dependent as shown in “Typical Characteristics” on corresponding figures: 25 | 26 | ![WDT limitations](https://user-images.githubusercontent.com/35344069/224619444-3c0b634c-f460-40d2-8a73-256bad0d5ba1.png) 27 | 28 | Timing consistency may vary as much as 20% between two devices in same setup due to individual device differences, or between a prototype and production device due to setup differences. 29 | 30 | ## Alternative tick sources 31 | For applications requiring high precision timing, the Ticks can be sourced from one of the hardware timers or an external clock input. 32 | 33 | First, you switch it in `FreeRTOSVariant.h` header by removing or undefining `portUSE_WDTO` and defining, here for example, the 8-bit Timer0 `portUSE_TIMER0`. 34 | 35 | ```cpp 36 | #undef portUSE_WDTO 37 | #define portUSE_TIMER0 38 | ``` 39 | 40 | Next, in your app you provide two pieces of code: the initialisation functions and the ISR hook. Their implementation depends on your tick source. 41 | 42 | ## Timer specific initialisation and ISR functions 43 | 44 | For implementation examples for many different timers, including the RTC Timer2 available on some devices, please refer to `port.c` in the [AVRfreeRTOS Repository](https://github.com/feilipu/avrfreertos/tree/master/freeRTOS10xx/portable). 45 | 46 | ### Hardware timer Timer0 47 | _NOTE: This code snippet is verified to work on Atmega2560. Full code available [here](./tick_sources_timer0.cpp)._ 48 | 49 | ```cpp 50 | // Formula for the frequency is: 51 | // f = F_CPU / (PRESCALER * (1 + COUNTER_TOP) 52 | // 53 | // Assuming the MCU clock of 16MHz, prescaler 1024 and counter top 249, the resulting tick period is 16 ms (62.5 Hz). 54 | // 55 | #define TICK_PERIOD_16MS 249 56 | #define PRESCALER 1024 57 | #if (portTICK_PERIOD_MS != (PRESCALER * (1 + TICK_PERIOD_16MS) * 1000 / F_CPU)) 58 | #warning portTICK_PERIOD_MS defined in FreeRTOSVariant.h differs from your timer configuration 59 | #endif 60 | 61 | // For register TCCR0A: 62 | #define NO_PWM (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) 63 | #define MODE_CTC_TCCR0A (1 << WGM01) | (0 << WGM00) 64 | 65 | // For register TCCR0B: 66 | #define MODE_CTC_TCCR0B (0 << WGM02) 67 | #define PRESCALER_1024 (1 << CS02) | (0 << CS01) | (1 << CS00) 68 | 69 | // For register TIMSK0: 70 | #define INTERRUPT_AT_TOP (1 << OCIE0A) 71 | 72 | extern "C" 73 | void prvSetupTimerInterrupt( void ) 74 | { 75 | // In case Arduino platform has pre-configured the timer, 76 | // disable it before re-configuring here to avoid unpredicted results: 77 | TIMSK0 = 0; 78 | 79 | // Now configure the timer: 80 | TCCR0A = NO_PWM | MODE_CTC_TCCR0A; 81 | TCCR0B = MODE_CTC_TCCR0B | PRESCALER_1024; 82 | OCR0A = TICK_PERIOD_16MS; 83 | 84 | // Prevent missing the top and going into a possibly long wait until wrapping around: 85 | TCNT0 = 0; 86 | 87 | // At this point the global interrupt flag is NOT YET enabled, 88 | // so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler. 89 | TIMSK0 = INTERRUPT_AT_TOP; 90 | } 91 | ``` 92 | 93 | To switch to an alternative tick source, here for example Timer0, insert this block in `FreeRTOSVariant.h`: 94 | 95 | ```cpp 96 | #undef portUSE_WDTO 97 | #define portUSE_TIMER0 98 | #define portTICK_PERIOD_MS 16 99 | 100 | /* 101 | * When a tick source other than WDT is used, configuring the tick source becomes the user's responsibility. 102 | * E.g., when using Timer0 for the tick source, you can use the following snippet: 103 | */ 104 | 105 | // Formula for the frequency is: 106 | // f = F_CPU / (PRESCALER * (1 + COUNTER_TOP) 107 | // 108 | // Assuming the MCU clock of 16MHz, prescaler 1024 and counter top 249, the resulting tick period is 16 ms (62.5 Hz). 109 | // 110 | 111 | #define TICK_PERIOD_16MS 249 112 | #define PRESCALER 1024 113 | 114 | #if (portTICK_PERIOD_MS != (PRESCALER * (1 + TICK_PERIOD_16MS) * 1000 / F_CPU)) 115 | #warning portTICK_PERIOD_MS defined in FreeRTOSVariant.h differs from your timer configuration 116 | #endif 117 | * 118 | // For register TCCR0A: 119 | #define NO_PWM (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) 120 | #define MODE_CTC_TCCR0A (1 << WGM01) | (0 << WGM00) 121 | 122 | // For register TCCR0B: 123 | #define MODE_CTC_TCCR0B (0 << WGM02) 124 | #define PRESCALER_1024 (1 << CS02) | (0 << CS01) | (1 << CS00) 125 | 126 | // For register TIMSK0: 127 | #define INTERRUPT_AT_TOP (1 << OCIE0A) 128 | 129 | extern "C" 130 | void prvSetupTimerInterrupt( void ) 131 | { 132 | // In case Arduino platform has pre-configured the timer, 133 | // disable it before re-configuring here to avoid unpredicted results: 134 | TIMSK0 = 0; 135 | 136 | // Now configure the timer: 137 | TCCR0A = NO_PWM | MODE_CTC_TCCR0A; 138 | TCCR0B = MODE_CTC_TCCR0B | PRESCALER_1024; 139 | OCR0A = TICK_PERIOD_16MS; 140 | 141 | // Prevent missing the top and going into a possibly long wait until wrapping around: 142 | TCNT0 = 0; 143 | 144 | // At this point the global interrupt flag is NOT YET enabled, 145 | // so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler. 146 | TIMSK0 = INTERRUPT_AT_TOP; 147 | } 148 | ``` 149 | 150 | Though Timer0 is given as example here, any timer can be used. A 16-bit timer (e.g., Timer1) is needed for time slices longer than ~20 milliseconds. 151 | 152 | ### Hardware timer ISR hook 153 | For **preemptive** scheduler use `ISR_NAKED` attribute to reduce the call overhead: 154 | 155 | ```cpp 156 | ISR(TIMER0_COMPA_vect, ISR_NAKED) __attribute__ ((hot, flatten)); 157 | ISR(TIMER0_COMPA_vect) { 158 | vPortYieldFromTick(); 159 | __asm__ __volatile__ ( "reti" ); 160 | } 161 | ``` 162 | 163 | The register context is saved at the start of `vPortYieldFromTick()`, then the tick count is incremented, finally the new context is loaded - so no dirtying occurs. 164 | 165 | 166 | For **cooperative** scheduler, the register context is not saved because no switching is intended; therefore `naked` attribute cannot be applied because cooperative `xTaskIncrementTick()` dirties the context. 167 | 168 | ```cpp 169 | ISR(TIMER0_COMPA_vect) __attribute__ ((hot, flatten)); 170 | ISR(TIMER0_COMPA_vect) { 171 | xTaskIncrementTick(); 172 | } 173 | ``` 174 | 175 | Use `ISR_NOBLOCK` where there is an important timer running, that should preempt the scheduler: 176 | ```cpp 177 | ISR(portSCHEDULER_ISR, ISR_NAKED ISR_NOBLOCK) __attribute__ ((hot, flatten)); 178 | ``` 179 | 180 | The attributes `hot` and `flatten` help inlining all the code found inside your ISR thus reducing the call overhead. 181 | Note: NO comma before `ISR_NOBLOCK`. 182 | 183 | 184 | ### External clock 185 | _NOTE: This code snippet example has not been verified to work._ 186 | 187 | Assuming the external clock is connected to data pin 21 (external interrupt `INT0`): 188 | 189 | ```cpp 190 | // For register EICRA: 191 | #define TICK_ON_RISING_EDGE_D21 (1 << ISC01) | (1 << ISC00) 192 | 193 | // For register EIMSK: 194 | #define TICK_INPUT_PIN_D21 (1 << INT0) 195 | 196 | extern "C" 197 | void prvSetupTimerInterrupt( void ) 198 | { 199 | EICRA = TICK_ON_RISING_EDGE_D21; 200 | 201 | // At this point the global interrupt flag is NOT YET enabled, 202 | // so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler. 203 | EIMSK = TICK_INPUT_PIN_D21; 204 | 205 | // Configure the pin 206 | pinMode(21, INPUT); 207 | } 208 | ``` 209 | 210 | 211 | ### External clock ISR hook 212 | Similar to Timer0 ISR, for **preemptive** scheduler: 213 | 214 | ```cpp 215 | ISR(INT0_vect, ISR_NAKED) __attribute__ ((hot, flatten)); 216 | ISR(INT0_vect) { 217 | vPortYieldFromTick(); 218 | __asm__ __volatile__ ( "reti" ); 219 | } 220 | ``` 221 | 222 | For **cooperative** scheduler: 223 | ```cpp 224 | ISR(INT0_vect) __attribute__ ((hot, flatten)); 225 | ISR(INT0_vect) { 226 | xTaskIncrementTick(); 227 | } 228 | ``` 229 | 230 | ## Performance considerations 231 | When selecting the duration for the time slice, the following should be kept in mind. 232 | 233 | ### Granularity 234 | Note that Timer resolution (or granularity) is affected by integer maths division and the time slice selected. For example, trying to measure 50ms using a 120ms time slice won't work. 235 | 236 | ### Context switching 237 | In preemptive mode, tasks which are actively executing (i.e., those not waiting for a semaphore or queue) might be switched every time tick, depending on their priority. Switching the context involves pushing all CPU's registers of old task and popping all registers of new task. The shorter your time slice is, the bigger of overhead this becomes. 238 | 239 | In cooperative mode, context overhead is not a factor. 240 | 241 | ### Calculations 242 | On MCUs lacking the hardware division operation like AVR, a special care should be taken to avoid division operations. Where unavoidable, operations with divisor of power of 2 work best because they are performed with bitwise shifting, whereas an arbitrary value results in a software division operation taking ~200 clock cycles (for a `uint16_t` operand). 243 | 244 | You might encounter a division when calculating delays, e.g. converting milliseconds to ticks: 245 | 246 | ```cpp 247 | TickType_t ticks = delay_millis / portTICK_PERIOD_MS 248 | ``` 249 | 250 | If your application needs to do this sort of conversion a lot, consider making your time slice a power-of-2 value (16 ms, 32 ms, 64 ms etc.). 251 | 252 | -------------------------------------------------------------------------------- /doc/tick_sources_timer0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * Formula for the frequency is: 5 | * f = F_CPU / (PRESCALER * (1 + COUNTER_TOP) 6 | * 7 | * Assuming the MCU clock of 16MHz, prescaler 1024 and counter top 249, the resulting tick period is 16 ms (62.5 Hz). 8 | */ 9 | #define TICK_PERIOD_16MS 249 10 | #define PRESCALER 1024 11 | #if (portTICK_PERIOD_MS != (PRESCALER * (1 + TICK_PERIOD_16MS) * 1000 / F_CPU)) 12 | #warning portTICK_PERIOD_MS defined in FreeRTOSVariant.h differs from your timer configuration 13 | #endif 14 | 15 | // For register TCCR0A: 16 | #define NO_PWM (0 << COM0A1) | (0 << COM0A0) | (0 << COM0B1) | (0 << COM0B0) 17 | #define MODE_CTC_TCCR0A (1 << WGM01) | (0 << WGM00) 18 | 19 | // For register TCCR0B: 20 | #define MODE_CTC_TCCR0B (0 << WGM02) 21 | #define PRESCALER_1024 (1 << CS02) | (0 << CS01) | (1 << CS00) 22 | 23 | // For register TIMSK0: 24 | #define INTERRUPT_AT_TOP (1 << OCIE0A) 25 | 26 | extern "C" 27 | void prvSetupTimerInterrupt( void ) 28 | { 29 | // In case Arduino platform has pre-configured the timer, 30 | // disable it before re-configuring here to avoid unpredicted results: 31 | TIMSK0 = 0; 32 | 33 | // Now configure the timer: 34 | TCCR0A = NO_PWM | MODE_CTC_TCCR0A; 35 | TCCR0B = MODE_CTC_TCCR0B | PRESCALER_1024; 36 | OCR0A = TICK_PERIOD_16MS; 37 | 38 | // Prevent missing the top and going into a possibly long wait until wrapping around: 39 | TCNT0 = 0; 40 | 41 | // At this point the global interrupt flag is NOT YET enabled, 42 | // so you're NOT starting to get the ISR calls until FreeRTOS enables it just before launching the scheduler. 43 | TIMSK0 = INTERRUPT_AT_TOP; 44 | } 45 | 46 | 47 | ISR(TIMER0_COMPA_vect, ISR_NAKED) __attribute__ ((hot, flatten)); 48 | ISR(TIMER0_COMPA_vect) 49 | { 50 | vPortYieldFromTick(); 51 | __asm__ __volatile__ ( "reti" ); 52 | } 53 | -------------------------------------------------------------------------------- /examples/AnalogRead_DigitalRead/AnalogRead_DigitalRead.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include // add the FreeRTOS functions for Semaphores (or Flags). 3 | 4 | // Declare a mutex Semaphore Handle which we will use to manage the Serial Port. 5 | // It will be used to ensure only one Task is accessing this resource at any time. 6 | SemaphoreHandle_t xSerialSemaphore; 7 | 8 | // define two Tasks for DigitalRead & AnalogRead 9 | void TaskDigitalRead( void *pvParameters ); 10 | void TaskAnalogRead( void *pvParameters ); 11 | 12 | // the setup function runs once when you press reset or power the board 13 | void setup() { 14 | 15 | // initialize serial communication at 9600 bits per second: 16 | Serial.begin(9600); 17 | 18 | while (!Serial) { 19 | ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 20 | } 21 | 22 | // Semaphores are useful to stop a Task proceeding, where it should be paused to wait, 23 | // because it is sharing a resource, such as the Serial port. 24 | // Semaphores should only be used whilst the scheduler is running, but we can set it up here. 25 | if ( xSerialSemaphore == NULL ) // Check to confirm that the Serial Semaphore has not already been created. 26 | { 27 | xSerialSemaphore = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use to manage the Serial Port 28 | if ( ( xSerialSemaphore ) != NULL ) 29 | xSemaphoreGive( ( xSerialSemaphore ) ); // Make the Serial Port available for use, by "Giving" the Semaphore. 30 | } 31 | 32 | // Now set up two Tasks to run independently. 33 | xTaskCreate( 34 | TaskDigitalRead 35 | , "DigitalRead" // A name just for humans 36 | , 128 // This stack size can be checked & adjusted by reading the Stack Highwater 37 | , NULL //Parameters for the task 38 | , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 39 | , NULL ); //Task Handle 40 | 41 | xTaskCreate( 42 | TaskAnalogRead 43 | , "AnalogRead" // A name just for humans 44 | , 128 // Stack size 45 | , NULL //Parameters for the task 46 | , 1 // Priority 47 | , NULL ); //Task Handle 48 | 49 | // Now the Task scheduler, which takes over control of scheduling individual Tasks, is automatically started. 50 | } 51 | 52 | void loop() 53 | { 54 | // Empty. Things are done in Tasks. 55 | } 56 | 57 | /*--------------------------------------------------*/ 58 | /*---------------------- Tasks ---------------------*/ 59 | /*--------------------------------------------------*/ 60 | 61 | void TaskDigitalRead( void *pvParameters __attribute__((unused)) ) // This is a Task. 62 | { 63 | /* 64 | DigitalReadSerial 65 | Reads a digital input on pin 2, prints the result to the serial monitor 66 | 67 | This example code is in the public domain. 68 | */ 69 | 70 | // digital pin 2 has a pushbutton attached to it. Give it a name: 71 | uint8_t pushButton = 2; 72 | 73 | // make the pushbutton's pin an input: 74 | pinMode(pushButton, INPUT); 75 | 76 | for (;;) // A Task shall never return or exit. 77 | { 78 | // read the input pin: 79 | int buttonState = digitalRead(pushButton); 80 | 81 | // See if we can obtain or "Take" the Serial Semaphore. 82 | // If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free. 83 | if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE ) 84 | { 85 | // We were able to obtain or "Take" the semaphore and can now access the shared resource. 86 | // We want to have the Serial Port for us alone, as it takes some time to print, 87 | // so we don't want it getting stolen during the middle of a conversion. 88 | // print out the state of the button: 89 | Serial.println(buttonState); 90 | 91 | xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others. 92 | } 93 | 94 | vTaskDelay(1); // one tick delay (15ms) in between reads for stability 95 | } 96 | } 97 | 98 | void TaskAnalogRead( void *pvParameters __attribute__((unused)) ) // This is a Task. 99 | { 100 | 101 | for (;;) 102 | { 103 | // read the input on analog pin 0: 104 | int sensorValue = analogRead(A0); 105 | 106 | // See if we can obtain or "Take" the Serial Semaphore. 107 | // If the semaphore is not available, wait 5 ticks of the Scheduler to see if it becomes free. 108 | if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE ) 109 | { 110 | // We were able to obtain or "Take" the semaphore and can now access the shared resource. 111 | // We want to have the Serial Port for us alone, as it takes some time to print, 112 | // so we don't want it getting stolen during the middle of a conversion. 113 | // print out the value you read: 114 | Serial.println(sensorValue); 115 | 116 | xSemaphoreGive( xSerialSemaphore ); // Now free or "Give" the Serial Port for others. 117 | } 118 | 119 | vTaskDelay(1); // one tick delay (15ms) in between reads for stability 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /examples/ArrayQueue/ArrayQueue.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a basic FreeRTOS queue 3 | * https://www.freertos.org/Embedded-RTOS-Queues.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | // Include queue support 10 | #include 11 | 12 | // Define a Array 13 | int pinReadArray[4]={0,0,0,0}; 14 | 15 | //Function Declaration 16 | void TaskBlink(void *pvParameters); 17 | void TaskAnalogReadPin0(void *pvParameters); 18 | void TaskAnalogReadPin1(void *pvParameters); 19 | void TaskSerial(void *pvParameters); 20 | 21 | /* 22 | * Declaring a global variable of type QueueHandle_t 23 | * 24 | */ 25 | QueueHandle_t arrayQueue; 26 | 27 | void setup() { 28 | 29 | /** 30 | * Create a queue. 31 | * https://www.freertos.org/a00116.html 32 | */ 33 | arrayQueue=xQueueCreate(10, //Queue length 34 | sizeof(pinReadArray)); //Queue item size 35 | if(arrayQueue!=NULL){ 36 | 37 | // Create task that consumes the queue if it was created. 38 | xTaskCreate(TaskSerial,// Task function 39 | "PrintSerial",// Task name 40 | 128,// Stack size 41 | NULL, 42 | 2,// Priority 43 | NULL); 44 | 45 | // Create task that publish data in the queue if it was created. 46 | xTaskCreate(TaskAnalogReadPin0, // Task function 47 | "AnalogRead1",// Task name 48 | 128,// Stack size 49 | NULL, 50 | 1,// Priority 51 | NULL); 52 | 53 | // Create other task that publish data in the queue if it was created. 54 | xTaskCreate(TaskAnalogReadPin1,// Task function 55 | "AnalogRead2",// Task name 56 | 128,// Stack size 57 | NULL, 58 | 1,// Priority 59 | NULL); 60 | 61 | 62 | xTaskCreate(TaskBlink,// Task function 63 | "Blink", // Task name 64 | 128,// Stack size 65 | NULL, 66 | 0,// Priority 67 | NULL); 68 | 69 | } 70 | } 71 | 72 | void loop() {} 73 | 74 | /** 75 | * Analog read task for Pin A0 76 | * Reads an analog input on pin 0 and send the readed value through the queue. 77 | * See Blink_AnalogRead example. 78 | */ 79 | void TaskAnalogReadPin0(void *pvParameters){ 80 | (void) pvParameters; 81 | for (;;){ 82 | pinReadArray[0]=0; 83 | pinReadArray[1]=analogRead(A0); 84 | /** 85 | * Post an item on a queue. 86 | * https://www.freertos.org/a00117.html 87 | */ 88 | xQueueSend(arrayQueue,&pinReadArray,portMAX_DELAY); 89 | // One tick delay (15ms) in between reads for stability 90 | vTaskDelay(1); 91 | } 92 | } 93 | 94 | /** 95 | * Analog read task for Pin A1 96 | * Reads an analog input on pin 1 and send the readed value through the queue. 97 | * See Blink_AnalogRead example. 98 | */ 99 | void TaskAnalogReadPin1(void *pvParameters){ 100 | (void) pvParameters; 101 | for (;;){ 102 | pinReadArray[2]=1; 103 | pinReadArray[3]=analogRead(A1); 104 | /** 105 | * Post an item on a queue. 106 | * https://www.freertos.org/a00117.html 107 | */ 108 | xQueueSend(arrayQueue,&pinReadArray,portMAX_DELAY); 109 | // One tick delay (15ms) in between reads for stability 110 | vTaskDelay(1); 111 | } 112 | } 113 | 114 | 115 | 116 | /** 117 | * Serial task. 118 | * Prints the received items from the queue to the serial monitor. 119 | */ 120 | void TaskSerial(void *pvParameters){ 121 | (void) pvParameters; 122 | 123 | // Init Arduino serial 124 | Serial.begin(9600); 125 | 126 | // Wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 127 | while (!Serial) { 128 | vTaskDelay(1); 129 | } 130 | 131 | for (;;){ 132 | if(xQueueReceive(arrayQueue,&pinReadArray,portMAX_DELAY) == pdPASS ){ 133 | Serial.print("PIN:"); 134 | Serial.println(pinReadArray[0]); 135 | Serial.print("value:"); 136 | Serial.println(pinReadArray[1]); 137 | Serial.print("PIN:"); 138 | Serial.println(pinReadArray[2]); 139 | Serial.print("value:"); 140 | Serial.println(pinReadArray[3]); 141 | vTaskDelay(500/portTICK_PERIOD_MS); 142 | } 143 | } 144 | } 145 | 146 | /* 147 | * Blink task. 148 | * See Blink_AnalogRead example. 149 | */ 150 | void TaskBlink(void *pvParameters){ 151 | (void) pvParameters; 152 | pinMode(LED_BUILTIN,OUTPUT); 153 | digitalWrite(LED_BUILTIN,LOW); 154 | for (;;){ 155 | digitalWrite(LED_BUILTIN,HIGH); 156 | vTaskDelay(250/portTICK_PERIOD_MS); 157 | digitalWrite(LED_BUILTIN,LOW); 158 | vTaskDelay(250/portTICK_PERIOD_MS); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /examples/Assert/Assert.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of FreeRTOS configASSERT macro 3 | * https://www.freertos.org/a00110.html#configASSERT 4 | */ 5 | 6 | #include 7 | 8 | const boolean valueToAssert = true; 9 | 10 | // The setup function runs once when you press reset or power the board 11 | void setup() { 12 | 13 | // Assert value is true, execution doesn't stop. 14 | configASSERT(valueToAssert == true); 15 | 16 | // Assert value is false, FreeRTOS execution stops and start to blink main led two times with 4 second cycle. 17 | configASSERT(valueToAssert == false); 18 | } 19 | 20 | 21 | void loop() 22 | { 23 | // Empty. Things are done in Tasks. 24 | } 25 | -------------------------------------------------------------------------------- /examples/Blink_AnalogRead/Blink_AnalogRead.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // define two tasks for Blink & AnalogRead 4 | void TaskBlink( void *pvParameters ); 5 | void TaskAnalogRead( void *pvParameters ); 6 | 7 | // the setup function runs once when you press reset or power the board 8 | void setup() { 9 | 10 | // initialize serial communication at 9600 bits per second: 11 | Serial.begin(9600); 12 | 13 | while (!Serial) { 14 | ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 15 | } 16 | 17 | // Now set up two tasks to run independently. 18 | xTaskCreate( 19 | TaskBlink 20 | , "Blink" // A name just for humans 21 | , 128 // This stack size can be checked & adjusted by reading the Stack Highwater 22 | , NULL 23 | , 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 24 | , NULL ); 25 | 26 | xTaskCreate( 27 | TaskAnalogRead 28 | , "AnalogRead" 29 | , 128 // Stack size 30 | , NULL 31 | , 1 // Priority 32 | , NULL ); 33 | 34 | // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. 35 | } 36 | 37 | void loop() 38 | { 39 | // Empty. Things are done in Tasks. 40 | } 41 | 42 | /*--------------------------------------------------*/ 43 | /*---------------------- Tasks ---------------------*/ 44 | /*--------------------------------------------------*/ 45 | 46 | void TaskBlink(void *pvParameters) // This is a task. 47 | { 48 | (void) pvParameters; 49 | 50 | /* 51 | Blink 52 | Turns on an LED on for one second, then off for one second, repeatedly. 53 | 54 | Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO 55 | it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care 56 | of use the correct LED pin whatever is the board used. 57 | 58 | The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute 59 | the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX. 60 | e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc. 61 | 62 | If you want to know what pin the on-board LED is connected to on your Arduino model, check 63 | the Technical Specs of your board at https://www.arduino.cc/en/Main/Products 64 | 65 | This example code is in the public domain. 66 | 67 | modified 8 May 2014 68 | by Scott Fitzgerald 69 | 70 | modified 2 Sep 2016 71 | by Arturo Guadalupi 72 | */ 73 | 74 | // initialize digital LED_BUILTIN on pin 13 as an output. 75 | pinMode(LED_BUILTIN, OUTPUT); 76 | 77 | for (;;) // A Task shall never return or exit. 78 | { 79 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 80 | vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second 81 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW 82 | vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second 83 | } 84 | } 85 | 86 | void TaskAnalogRead(void *pvParameters) // This is a task. 87 | { 88 | (void) pvParameters; 89 | 90 | /* 91 | AnalogReadSerial 92 | Reads an analog input on pin 0, prints the result to the serial monitor. 93 | Graphical representation is available using serial plotter (Tools > Serial Plotter menu) 94 | Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground. 95 | 96 | This example code is in the public domain. 97 | */ 98 | 99 | for (;;) 100 | { 101 | // read the input on analog pin 0: 102 | int sensorValue = analogRead(A0); 103 | // print out the value you read: 104 | Serial.println(sensorValue); 105 | vTaskDelay(1); // one tick delay (15ms) in between reads for stability 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/GoldilocksAnalogueTestSuite/GA_Header.h: -------------------------------------------------------------------------------- 1 | #ifndef GA_HEADER_h // include guard 2 | #define GA_HEADER_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | /*--------------------------------------------------*/ 11 | /*------------Often Configured Parameters-----------*/ 12 | /*--------------------------------------------------*/ 13 | 14 | #define SAMPLE_RATE 16000 // samples per second 15 | #define DELAY 128000 // bytes of delay 16 | 17 | /* Working buffer */ 18 | #define CMD_BUFFER_SIZE 8192 // size of working buffer (on heap) 19 | 20 | /*--------------------------------------------------*/ 21 | /*---------------Public Functions-------------------*/ 22 | /*--------------------------------------------------*/ 23 | 24 | void AudioCodec_ADC_init(void) __attribute__((flatten)); 25 | void AudioCodec_ADC(uint16_t* _modvalue) __attribute__((hot, flatten)); 26 | 27 | void alaw_compress1(int16_t* linval, uint8_t* logval) __attribute__ ((hot, flatten)); 28 | void alaw_expand1(uint8_t* logval, int16_t* linval) __attribute__ ((hot, flatten)); 29 | 30 | void audioCodec_dsp( uint16_t* ch_A, uint16_t* ch_B) __attribute__ ((hot, flatten)); 31 | // prototype for the DSP function to be implemented. 32 | // needs to at least provide *ch_A and *ch_B 33 | // within Timer1 interrupt routine - time critical I/O. Keep it short and punchy! 34 | 35 | /*--------------------------------------------------*/ 36 | 37 | void AudioCodec_ADC_init(void) 38 | { 39 | // setup ADCs 40 | ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(ADLAR) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0); // 2.56V reference with external capacitor at AREF pin - left justify - start sampling MIC input ADC7 41 | ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // ADC enable, auto trigger, ck/128 = 192kHz 42 | ADCSRB = 0x00; // free running mode 43 | DIDR0 = _BV(ADC7D) | _BV(ADC6D) | _BV(ADC2D) | _BV(ADC1D) | _BV(ADC0D); // turn off digital input for pin ADC6 Line and ADC7 Mic input (and ADC2, ADC1, & ADC0) 44 | 45 | // Analogue Comparator Disable 46 | // When the ACD bit is written logic one, the power to the Analogue Comparator is switched off. 47 | // This bit can be set at any time to turn off the Analogue Comparator. 48 | // This will reduce power consumption in Active and Idle mode. 49 | // When changing the ACD bit, the Analogue Comparator Interrupt must be disabled by clearing the ACIE bit in ACSR. 50 | // Otherwise an interrupt can occur when the ACD bit is changed. 51 | ACSR &= ~_BV(ACIE); 52 | ACSR |= _BV(ACD); 53 | 54 | } 55 | 56 | // adc sampling routine 57 | void AudioCodec_ADC(uint16_t* _modvalue) 58 | { 59 | if (ADCSRA & _BV(ADIF)) // check if sample ready 60 | { 61 | *_modvalue = ADCW; // fetch ADCL first to freeze sample, then ADCH. It is done by the compiler. 62 | ADCSRA |= _BV(ADIF); // reset the interrupt flag 63 | } 64 | } 65 | 66 | /* 67 | ========================================================================== 68 | 69 | FUNCTION NAME: alaw_compress11 70 | 71 | DESCRIPTION: ALaw encoding rule according ITU-T Rec. G.711. 72 | 73 | PROTOTYPE: int8_t alaw_compress1( int16_t linval ) 74 | PARAMETERS: 75 | linval: (In) linear samples (only 12 MSBits are taken into account) 76 | logval: (Out) compressed sample (8 bit right justified without sign extension) 77 | 78 | RETURN VALUE: none. 79 | 80 | ========================================================================== 81 | */ 82 | void alaw_compress1 (int16_t* linval, uint8_t* logval) 83 | { 84 | uint16_t ix, iexp; 85 | 86 | ix = *linval < 0 /* 0 <= ix < 2048 */ 87 | ? ~*linval >> 4 /* 1's complement for negative values */ 88 | : *linval >> 4; 89 | 90 | /* Do more, if exponent > 0 */ 91 | if (ix > 15) /* exponent=0 for ix <= 15 */ 92 | { 93 | iexp = 1; /* first step: */ 94 | while (ix > 16 + 15) /* find mantissa and exponent */ 95 | { 96 | ix >>= 1; 97 | iexp++; 98 | } 99 | ix -= 16; /* second step: remove leading '1' */ 100 | 101 | ix += iexp << 4; /* now compute encoded value */ 102 | } 103 | 104 | if (*linval >= 0) ix |= (0x0080); /* add sign bit */ 105 | 106 | *logval = (uint8_t)(ix ^ (0x0055)); /* toggle even bits */ 107 | } 108 | /* ................... End of alaw_compress1() ..................... */ 109 | 110 | 111 | /* 112 | ========================================================================== 113 | 114 | FUNCTION NAME: alaw_expand1 115 | 116 | DESCRIPTION: ALaw decoding rule according ITU-T Rec. G.711. 117 | 118 | PROTOTYPE: int16_t alaw_expand1( uint8_t logval ) 119 | 120 | PARAMETERS: 121 | logval: (In) buffer with compressed samples (8 bit right justified, 122 | without sign extension) 123 | linval: (Out) buffer with linear samples (13 bits left justified) 124 | 125 | RETURN VALUE: none. 126 | ============================================================================ 127 | */ 128 | void alaw_expand1(uint8_t* logval, int16_t* linval) 129 | { 130 | uint8_t ix, iexp; 131 | int16_t mant; 132 | 133 | ix = (*logval ^ (0x55)); /* re-toggle toggled even bits */ 134 | 135 | ix &= 0x7F; /* remove sign bit */ 136 | iexp = ix >> 4; /* extract exponent */ 137 | mant = ix & 0x0f; /* now get mantissa */ 138 | if (iexp > 0) 139 | mant = mant + 16; /* add leading '1', if exponent > 0 */ 140 | 141 | mant = (mant << 4) + (0x0008); /* now mantissa left justified and */ 142 | /* 1/2 quantization step added */ 143 | if (iexp > 1) /* now left shift according exponent */ 144 | mant = mant << (iexp - 1); 145 | 146 | *linval = *logval > 127 /* invert, if negative sample */ 147 | ? mant 148 | : -mant; 149 | } 150 | /* ................... End of alaw_expand1() ..................... */ 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif 155 | 156 | #endif // GA_HEADER_h end include guard 157 | -------------------------------------------------------------------------------- /examples/GoldilocksAnalogueTestSuite/GoldilocksAnalogueTestSuite.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | // This example only works with Goldilocks Analogue, as DAC and SPI SRAM is required. 15 | 16 | // INSTALLATION OF THE 4 FOLLOWING LIBRARIES REQUIRED! 17 | 18 | // From Library: FreeRTOS 19 | #include 20 | #include 21 | 22 | // From Library: AVR Real Time Clock Library 23 | #include 24 | 25 | // From Library: Goldilocks Analogue DAC Library 26 | #include 27 | 28 | // From Library: Goldilocks Analogue SPI RAM Library 29 | #include 30 | #include 31 | 32 | #include "GA_Header.h" 33 | 34 | /*--------------------------------------------------*/ 35 | /*------------------- Globals ----------------------*/ 36 | /*--------------------------------------------------*/ 37 | 38 | DAC_value_t mod7_value; // location to store the ADC value before it is processed. 39 | 40 | uint16_t ch_A_out; // storage for the values to be written to MCP4822 41 | uint16_t ch_B_out; 42 | 43 | SPIRAM_ringBuffer_t SRAM_delayBuffer; // structure to hold the SRAM ringbuffer info. 44 | 45 | filter_t tx_filter; // instantiate a filter, which can be initialised to be a LPF (or BPF or HPF) later. 46 | 47 | // set up variables using the SD utility library functions: 48 | Sd2Card card; 49 | SdVolume volume; 50 | SdFile root; 51 | 52 | static uint8_t * Buff = NULL; /* Put a working buffer on heap later (with pvPortMalloc). */ 53 | 54 | // change this to match your SD shield or module; 55 | // GoldilocksAnalogue SD shield: pin 14 56 | uint8_t const chipSelect = 14; 57 | 58 | // Create a Semaphore binary flag for the Serial Port. To ensure only single access. 59 | SemaphoreHandle_t xSerialSemaphore; 60 | 61 | // define two tasks to operate this test suite. 62 | static void TaskReport( void *pvParameters ); // Report on the status reguarly using USART. 63 | static void TaskAnalogue( void *pvParameters ); // Manage Analogue set-up, then sleep. 64 | 65 | // Test the SPI EEPROM device, prior to building the SPI SRAM Delay loop. 66 | static int8_t testSPIEEPROM( uint_farptr_t p1, uint16_t p2 ); 67 | // p1 = address of the SPI memory to be tested 68 | // p2 = number of bytes to be tested (allocates a RAM buffer of this size too) 69 | 70 | /*--------------------------------------------------*/ 71 | /*-------------------- Set Up ----------------------*/ 72 | /*--------------------------------------------------*/ 73 | 74 | void setup() { 75 | // put your setup code here, to run once: 76 | // Open serial communications and wait for port to open: 77 | Serial.begin(38400); 78 | 79 | Serial.println(F("Hello World!\n")); 80 | 81 | setup_RTC_interrupt(); 82 | 83 | { 84 | tm CurrTimeDate; // set up an array for the RTC info. 85 | // 86 | 87 | CurrTimeDate.tm_year = (uint8_t) ( 2016 - 1900 ); 88 | CurrTimeDate.tm_mon = (uint8_t) 1; // January is month 0, February is month 1, etc 89 | CurrTimeDate.tm_mday = (uint8_t) 18; 90 | CurrTimeDate.tm_hour = (uint8_t) 17; 91 | CurrTimeDate.tm_min = (uint8_t) 16; 92 | CurrTimeDate.tm_sec = (uint8_t) 0; 93 | 94 | set_system_time( mktime( (tm*)&CurrTimeDate ) ); 95 | } 96 | 97 | // Semaphores are useful to stop a task proceeding, where it should be stopped because it is using a resource, such as the Serial port. 98 | // But they should only be used whilst the scheduler is running. 99 | if ( xSerialSemaphore == NULL ) // Check to see if the Serial Semaphore has not been created. 100 | { 101 | xSerialSemaphore = xSemaphoreCreateMutex(); // mutex semaphore for Serial Port 102 | if ( ( xSerialSemaphore ) != NULL ) 103 | xSemaphoreGive( ( xSerialSemaphore ) ); // make the Serial Port available 104 | } 105 | 106 | SPI.begin(); // warm up the SPI interface, so it can be used for the SPI RAM testing. 107 | 108 | Serial.print(F("SPI SRAM Memory Testing: ")); 109 | if (testSPIEEPROM(RAM0_ADDR + 17, CMD_BUFFER_SIZE)) 110 | Serial.println(F("*** FAILED ***")); 111 | else 112 | Serial.println(F("PASSED")); 113 | 114 | Serial.print(F("SPI EEPROM Memory Testing: ")); 115 | if (testSPIEEPROM(RAM1_ADDR + 17, CMD_BUFFER_SIZE)) 116 | Serial.println(F("*** FAILED ***\n")); 117 | else 118 | Serial.println(F("PASSED\n")); 119 | 120 | // we'll use the SD Card initialization code from the utility libraries 121 | // since we're just testing if the card is working! 122 | Serial.print(F("\nInitializing SD card... ")); 123 | if (!card.init(SPI_HALF_SPEED, chipSelect)) { 124 | Serial.println(F("initialization failed.")); 125 | Serial.println(F("Is a card inserted? You must insert a formatted SD Card to proceed.")); 126 | } else { 127 | Serial.println(F("wiring is correct and a SD card is present.")); 128 | } 129 | 130 | // print the type of card 131 | Serial.print(F("\nCard type: ")); 132 | switch (card.type()) { 133 | case SD_CARD_TYPE_SD1: 134 | Serial.println(F("SD1")); 135 | break; 136 | case SD_CARD_TYPE_SD2: 137 | Serial.println(F("SD2")); 138 | break; 139 | case SD_CARD_TYPE_SDHC: 140 | Serial.println(F("SDHC")); 141 | break; 142 | default: 143 | Serial.println(F("Unknown SD Card Type")); 144 | break; 145 | } 146 | 147 | // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 148 | if (!volume.init(card)) { 149 | Serial.println(F("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card")); 150 | } else { 151 | 152 | // print the type and size of the first FAT-type volume 153 | uint32_t volumesize; 154 | Serial.print(F("\nVolume type is FAT")); 155 | Serial.println(volume.fatType(), DEC); 156 | Serial.println(); 157 | 158 | volumesize = volume.blocksPerCluster(); // clusters are collections of blocks 159 | volumesize *= volume.clusterCount(); // we'll have a lot of clusters 160 | volumesize *= 512; // SD card blocks are always 512 bytes 161 | Serial.print(F("Volume size (bytes): ")); 162 | Serial.println(volumesize); 163 | Serial.print(F("Volume size (Kbytes): ")); 164 | volumesize /= 1024; 165 | Serial.println(volumesize); 166 | Serial.print(F("Volume size (Mbytes): ")); 167 | volumesize /= 1024; 168 | Serial.println(volumesize); 169 | 170 | Serial.println(F("\nFiles found on the card (name, date and size in bytes): ")); 171 | root.openRoot(volume); 172 | 173 | // list all files in the card with date and size 174 | root.ls(LS_R | LS_DATE | LS_SIZE); 175 | } 176 | 177 | // Now set up two tasks to help us with testing. 178 | xTaskCreate( 179 | TaskReport 180 | , "RedLED" // report reguarly on the status of its stack and the tick values. 181 | , 256 // Stack size 182 | , NULL 183 | , 2 // priority 184 | , NULL ); // */ 185 | 186 | xTaskCreate( 187 | TaskAnalogue 188 | , "Analogue" 189 | , 256 // This stack size can be checked & adjusted by reading Highwater 190 | , NULL 191 | , 1 // priority 192 | , NULL ); // */ 193 | 194 | // Start the task scheduler, which takes over control of scheduling individual tasks. 195 | // The scheduler is started in initVariant() found in variantHooks.c 196 | } 197 | 198 | /*--------------------------------------------------*/ 199 | /*---------------------- Tasks ---------------------*/ 200 | /*--------------------------------------------------*/ 201 | 202 | static void TaskAnalogue(void *pvParameters) // Prepare the DAC 203 | { 204 | (void) pvParameters; 205 | TickType_t xLastWakeTime; 206 | /* The xLastWakeTime variable needs to be initialised with the current tick 207 | count. Note that this is the only time we access this variable. From this 208 | point on xLastWakeTime is managed automatically by the xTaskDelayUntil() 209 | API function. */ 210 | xLastWakeTime = xTaskGetTickCount(); 211 | 212 | // Create the SPI SRAM ring-buffer used by audio delay loop. 213 | SPIRAM_ringBuffer_InitBuffer( &SRAM_delayBuffer, (uint_farptr_t)(RAM0_ADDR), sizeof(uint8_t) * DELAY); 214 | 215 | // See if we can obtain the Serial Semaphore. 216 | // If the semaphore is not available, wait 5 ticks to see if it becomes free. 217 | if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE ) 218 | { 219 | // We were able to obtain the semaphore and can now access the shared resource. 220 | // We want to have the Serial Port for us alone, as it takes some time to print, 221 | // so we don't want it getting stolen during the middle of a conversion. 222 | 223 | Serial.print(F("DAC_Codec_init ")); 224 | // initialise the USART 1 MSPIM bus specifically for DAC use, with the post-latch configuration. 225 | // pre-latch for audio or AC signals (FALSE), or post-latch for single value setting or DC values (TRUE). 226 | DAC_init(FALSE); 227 | 228 | Serial.print(F("will ")); 229 | // Initialise the sample interrupt timer. 230 | // set up the sampling Timer3 to 48000Hz (or lower), runs at audio sampling rate in Hz. 231 | DAC_Timer3_init(SAMPLE_RATE); 232 | 233 | Serial.print(F("very ")); 234 | // Initialise the filter to be a Low Pass Filter. 235 | tx_filter.cutoff = 0xc000; // set filter to 3/8 of sample frequency. 236 | setIIRFilterLPF( &tx_filter ); // initialise transmit sample filter 237 | 238 | Serial.print(F("soon ")); 239 | // set up ADC sampling on the ADC7 (Microphone). 240 | AudioCodec_ADC_init(); 241 | 242 | Serial.print (F("be ")); 243 | // Set the call back function to do the audio processing. 244 | // Done this way so that we can change the audio handling depending on what we want to achieve. 245 | DAC_setHandler(audioCodec_dsp, &ch_A_out, &ch_B_out); 246 | 247 | Serial.println(F("done.")); 248 | 249 | xSemaphoreGive( xSerialSemaphore ); // Now free the Serial Port for others. 250 | } 251 | 252 | // vTaskSuspend(NULL); // Well, we're pretty much done here. Let's suspend the Task. 253 | // vTaskEndScheduler(); // Or just kill the FreeRTOS scheduler. Rely on Timer3 Interrupt for regular output. 254 | 255 | for (;;) 256 | { 257 | // See if we can obtain the Serial Semaphore. 258 | // If the semaphore is not available, wait 5 ticks to see if it becomes free. 259 | if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE ) 260 | { 261 | // We were able to obtain the semaphore and can now access the shared resource. 262 | // We want to have the Serial Port for us alone, as it takes some time to print, 263 | // so we don't want it getting stolen during the middle of a conversion. 264 | 265 | Serial.print(F("Audio Stack HighWater @ ")); 266 | Serial.println(uxTaskGetStackHighWaterMark(NULL)); 267 | 268 | xSemaphoreGive( xSerialSemaphore ); // Now free the Serial Port for others. 269 | } 270 | xTaskDelayUntil( &xLastWakeTime, ( 8192 / portTICK_PERIOD_MS ) ); 271 | } 272 | } 273 | 274 | static void TaskReport(void *pvParameters) // report on the status of the device 275 | { 276 | (void) pvParameters;; 277 | TickType_t xLastWakeTime; 278 | /* The xLastWakeTime variable needs to be initialised with the current tick 279 | count. Note that this is the only time we access this variable. From this 280 | point on xLastWakeTime is managed automatically by the xTaskDelayUntil() 281 | API function. */ 282 | xLastWakeTime = xTaskGetTickCount(); 283 | 284 | time_t currentTick; // set up a location for the current time stamp 285 | 286 | for (;;) 287 | { 288 | // See if we can obtain the Serial Semaphore. 289 | // If the semaphore is not available, wait 5 ticks to see if it becomes free. 290 | if ( xSemaphoreTake( xSerialSemaphore, ( TickType_t ) 5 ) == pdTRUE ) 291 | { 292 | // We were able to obtain the semaphore and can now access the shared resource. 293 | // We want to have the Serial Port for us alone, as it takes some time to print, 294 | // so we don't want it getting stolen during the middle of a conversion. 295 | 296 | Serial.print(F("Report Stack HighWater @ ")); 297 | Serial.print(uxTaskGetStackHighWaterMark(NULL)); 298 | 299 | Serial.print(F(" Current Time: ")); 300 | time((time_t *)¤tTick); 301 | Serial.println(ctime( (time_t *)¤tTick)); 302 | 303 | xSemaphoreGive( xSerialSemaphore ); // Now free the Serial Port for others. 304 | } 305 | xTaskDelayUntil( &xLastWakeTime, ( 2048 / portTICK_PERIOD_MS ) ); 306 | } 307 | } 308 | 309 | /*--------------------------------------------------*/ 310 | /*-------------------- Functions -------------------*/ 311 | /*--------------------------------------------------*/ 312 | 313 | 314 | static int8_t testSPIEEPROM( uint_farptr_t p1, uint16_t p2 ) 315 | { 316 | int8_t ReturnCode; 317 | 318 | if (Buff == NULL) // if there is no Buff buffer allocated (pointer is NULL), then allocate buffer. 319 | if ( !(Buff = (uint8_t *) pvPortMalloc( sizeof(uint8_t) * CMD_BUFFER_SIZE ))) 320 | { 321 | Serial.println(F("pvPortMalloc for *Buff fail..!")); 322 | return SPIRAM_ERROR; 323 | } 324 | 325 | if (p2 >= CMD_BUFFER_SIZE) p2 = CMD_BUFFER_SIZE; 326 | 327 | srand( p1 % 42 ); // create a random seed, based on 42. 328 | 329 | for ( uint16_t i = 0; i < p2; ++i) 330 | { 331 | Buff[i] = (uint8_t) rand(); // fill the Buff with some pseudo random numbers. 332 | } 333 | 334 | Serial.print(F("Testing at 0x")); 335 | Serial.print( (uint32_t)p1, HEX); 336 | Serial.print(F(" for ")); 337 | Serial.print( p2, DEC); 338 | Serial.println(F(" bytes.")); 339 | 340 | ReturnCode = SPIRAM_begin(); 341 | if (ReturnCode) return ReturnCode; // problem with opening the EEPROM / SRAM 342 | 343 | uint_farptr_t FarAddress = p1; 344 | 345 | ReturnCode = SPIRAM_write( FarAddress, Buff, (size_t)p2); 346 | if (ReturnCode) return ReturnCode; /* error or disk full */ 347 | 348 | for (uint16_t i = 0; i < p2; ++i) 349 | { 350 | uint8_t read_result; 351 | 352 | ReturnCode = SPIRAM_read( &read_result, (uint_farptr_t)(FarAddress + i), (size_t)1); 353 | if (ReturnCode) return ReturnCode; /* error or disk full */ 354 | 355 | // Serial.print(F("Written 0x")); 356 | // Serial.print( Buff[i], HEX); 357 | // Serial.print(F(" Read 0x")); 358 | // Serial.println( read_result, HEX); 359 | 360 | if ( Buff[i] != read_result) 361 | { 362 | Serial.print(F("Error at Address 0x")); 363 | Serial.print( (uint_farptr_t)(FarAddress + i), HEX); 364 | Serial.print(F(" with 0x")); 365 | Serial.println( read_result, HEX); 366 | return SPIRAM_ERROR; 367 | } 368 | } 369 | return SPIRAM_SUCCESS; 370 | } 371 | 372 | void audioCodec_dsp( uint16_t * ch_A, uint16_t * ch_B) 373 | { 374 | int16_t xn; 375 | uint8_t cn; 376 | 377 | if ( SPIRAM_ringBuffer_GetCount(&SRAM_delayBuffer) >= DELAY ) 378 | { 379 | cn = SPIRAM_ringBuffer_Pop(&SRAM_delayBuffer); 380 | } 381 | else 382 | { 383 | cn = 0x80 ^ 0x55; // put A-Law nulled signal on the output. 384 | } 385 | 386 | alaw_expand1(&cn, &xn); // expand the A-Law compression 387 | 388 | *ch_A = *ch_B = (uint16_t)(xn + 0x7fff); // put signal out on A & B channel. 389 | 390 | AudioCodec_ADC(&mod7_value.u16); 391 | 392 | xn = mod7_value.u16 - 0x7fe0; // centre the sample to 0 by subtracting 1/2 10bit range. 393 | 394 | IIRFilter( &tx_filter, &xn); // filter sample train 395 | 396 | alaw_compress1(&xn, &cn); // compress using A-Law 397 | 398 | if ( SPIRAM_ringBuffer_GetCount(&SRAM_delayBuffer) <= DELAY ) 399 | { 400 | SPIRAM_ringBuffer_Poke(&SRAM_delayBuffer, cn); 401 | } 402 | } 403 | 404 | 405 | /*--------------------------------------------------*/ 406 | /*---------------------- Loop ----------------------*/ 407 | /*--------------------------------------------------*/ 408 | 409 | void loop() { 410 | // Remember that loop() is simply the freeRTOS idle task. 411 | // It is only something to do, when there's nothing else to do. 412 | 413 | // There are several macros provided in the header file to put 414 | // the device into sleep mode. 415 | // SLEEP_MODE_IDLE (0) 416 | // SLEEP_MODE_ADC _BV(SM0) 417 | // SLEEP_MODE_PWR_DOWN _BV(SM1) 418 | // SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1)) 419 | // SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2)) 420 | // SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2)) 421 | 422 | set_sleep_mode( SLEEP_MODE_IDLE ); 423 | 424 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 425 | { 426 | sleep_enable(); 427 | 428 | #if defined(BODS) && defined(BODSE) // Only if there is support to disable the brown-out detection. 429 | sleep_bod_disable(); 430 | #endif 431 | } 432 | sleep_cpu(); // good night. 433 | 434 | // Ugh. I've been woken up. Better disable sleep mode. 435 | sleep_disable(); 436 | } 437 | -------------------------------------------------------------------------------- /examples/IntegerQueue/IntegerQueue.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a basic FreeRTOS queue 3 | * https://www.freertos.org/Embedded-RTOS-Queues.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | // Include queue support 10 | #include 11 | 12 | /* 13 | * Declaring a global variable of type QueueHandle_t 14 | * 15 | */ 16 | QueueHandle_t integerQueue; 17 | 18 | void setup() { 19 | 20 | /** 21 | * Create a queue. 22 | * https://www.freertos.org/a00116.html 23 | */ 24 | integerQueue = xQueueCreate(10, // Queue length 25 | sizeof(int) // Queue item size 26 | ); 27 | 28 | if (integerQueue != NULL) { 29 | 30 | // Create task that consumes the queue if it was created. 31 | xTaskCreate(TaskSerial, // Task function 32 | "Serial", // A name just for humans 33 | 128, // This stack size can be checked & adjusted by reading the Stack Highwater 34 | NULL, 35 | 2, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 36 | NULL); 37 | 38 | 39 | // Create task that publish data in the queue if it was created. 40 | xTaskCreate(TaskAnalogRead, // Task function 41 | "AnalogRead", // Task name 42 | 128, // Stack size 43 | NULL, 44 | 1, // Priority 45 | NULL); 46 | 47 | } 48 | 49 | 50 | xTaskCreate(TaskBlink, // Task function 51 | "Blink", // Task name 52 | 128, // Stack size 53 | NULL, 54 | 0, // Priority 55 | NULL ); 56 | 57 | } 58 | 59 | void loop() {} 60 | 61 | 62 | /** 63 | * Analog read task 64 | * Reads an analog input on pin 0 and send the readed value through the queue. 65 | * See Blink_AnalogRead example. 66 | */ 67 | void TaskAnalogRead(void *pvParameters) 68 | { 69 | (void) pvParameters; 70 | 71 | for (;;) 72 | { 73 | // Read the input on analog pin 0: 74 | int sensorValue = analogRead(A0); 75 | 76 | /** 77 | * Post an item on a queue. 78 | * https://www.freertos.org/a00117.html 79 | */ 80 | xQueueSend(integerQueue, &sensorValue, portMAX_DELAY); 81 | 82 | // One tick delay (15ms) in between reads for stability 83 | vTaskDelay(1); 84 | } 85 | } 86 | 87 | /** 88 | * Serial task. 89 | * Prints the received items from the queue to the serial monitor. 90 | */ 91 | void TaskSerial(void * pvParameters) { 92 | (void) pvParameters; 93 | 94 | // Init Arduino serial 95 | Serial.begin(9600); 96 | 97 | // Wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 98 | while (!Serial) { 99 | vTaskDelay(1); 100 | } 101 | 102 | int valueFromQueue = 0; 103 | 104 | for (;;) 105 | { 106 | 107 | /** 108 | * Read an item from a queue. 109 | * https://www.freertos.org/a00118.html 110 | */ 111 | if (xQueueReceive(integerQueue, &valueFromQueue, portMAX_DELAY) == pdPASS) { 112 | Serial.println(valueFromQueue); 113 | } 114 | } 115 | } 116 | 117 | /* 118 | * Blink task. 119 | * See Blink_AnalogRead example. 120 | */ 121 | void TaskBlink(void *pvParameters) 122 | { 123 | (void) pvParameters; 124 | 125 | pinMode(LED_BUILTIN, OUTPUT); 126 | 127 | for (;;) 128 | { 129 | digitalWrite(LED_BUILTIN, HIGH); 130 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 131 | digitalWrite(LED_BUILTIN, LOW); 132 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /examples/Interrupts/Interrupts.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a Arduino interruption and RTOS Binary Semaphore 3 | * https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html 4 | */ 5 | 6 | 7 | // Include Arduino FreeRTOS library 8 | #include 9 | 10 | // Include semaphore supoport 11 | #include 12 | 13 | /* 14 | * Declaring a global variable of type SemaphoreHandle_t 15 | * 16 | */ 17 | SemaphoreHandle_t interruptSemaphore; 18 | 19 | void setup() { 20 | 21 | // Configure pin 2 as an input and enable the internal pull-up resistor 22 | pinMode(2, INPUT_PULLUP); 23 | 24 | // Create task for Arduino led 25 | xTaskCreate(TaskLed, // Task function 26 | "Led", // Task name 27 | 128, // Stack size 28 | NULL, 29 | 0, // Priority 30 | NULL ); 31 | 32 | /** 33 | * Create a binary semaphore. 34 | * https://www.freertos.org/xSemaphoreCreateBinary.html 35 | */ 36 | interruptSemaphore = xSemaphoreCreateBinary(); 37 | if (interruptSemaphore != NULL) { 38 | // Attach interrupt for Arduino digital pin 39 | attachInterrupt(digitalPinToInterrupt(2), interruptHandler, LOW); 40 | } 41 | 42 | 43 | } 44 | 45 | void loop() {} 46 | 47 | 48 | void interruptHandler() { 49 | /** 50 | * Give semaphore in the interrupt handler 51 | * https://www.freertos.org/a00124.html 52 | */ 53 | 54 | xSemaphoreGiveFromISR(interruptSemaphore, NULL); 55 | } 56 | 57 | 58 | /* 59 | * Led task. 60 | */ 61 | void TaskLed(void *pvParameters) 62 | { 63 | (void) pvParameters; 64 | 65 | pinMode(LED_BUILTIN, OUTPUT); 66 | 67 | for (;;) { 68 | 69 | /** 70 | * Take the semaphore. 71 | * https://www.freertos.org/a00122.html 72 | */ 73 | if (xSemaphoreTake(interruptSemaphore, portMAX_DELAY) == pdPASS) { 74 | digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); 75 | } 76 | vTaskDelay(10); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /examples/Mutex/Mutex.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Example of a FreeRTOS mutex 3 | https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | 10 | // Include mutex support 11 | #include 12 | 13 | /* 14 | Declaring a global variable of type SemaphoreHandle_t 15 | 16 | */ 17 | SemaphoreHandle_t mutex; 18 | 19 | int globalCount = 0; 20 | 21 | void setup() { 22 | 23 | Serial.begin(9600); 24 | 25 | /** 26 | Create a mutex. 27 | https://www.freertos.org/CreateMutex.html 28 | */ 29 | mutex = xSemaphoreCreateMutex(); 30 | if (mutex != NULL) { 31 | Serial.println("Mutex created"); 32 | } 33 | 34 | /** 35 | Create tasks 36 | */ 37 | xTaskCreate(TaskMutex, // Task function 38 | "Task1", // Task name for humans 39 | 128, 40 | 1000, // Task parameter 41 | 1, // Task priority 42 | NULL); 43 | 44 | xTaskCreate(TaskMutex, "Task2", 128, 1000, 1, NULL); 45 | 46 | } 47 | 48 | void loop() {} 49 | 50 | void TaskMutex(void *pvParameters) 51 | { 52 | TickType_t delayTime = *((TickType_t*)pvParameters); // Use task parameters to define delay 53 | 54 | for (;;) 55 | { 56 | /** 57 | Take mutex 58 | https://www.freertos.org/a00122.html 59 | */ 60 | if (xSemaphoreTake(mutex, 10) == pdTRUE) 61 | { 62 | Serial.print(pcTaskGetName(NULL)); // Get task name 63 | Serial.print(", Count read value: "); 64 | Serial.print(globalCount); 65 | 66 | globalCount++; 67 | 68 | Serial.print(", Updated value: "); 69 | Serial.print(globalCount); 70 | 71 | Serial.println(); 72 | /** 73 | Give mutex 74 | https://www.freertos.org/a00123.html 75 | */ 76 | xSemaphoreGive(mutex); 77 | } 78 | 79 | vTaskDelay(delayTime / portTICK_PERIOD_MS); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /examples/Notifications/Notifications.ino: -------------------------------------------------------------------------------- 1 | /** 2 | Example of a Arduino interruption and RTOS Task Notification. 3 | https://www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | /** 10 | Declaring a global TaskHandle for the led task. 11 | */ 12 | TaskHandle_t taskNotificationHandler; 13 | 14 | void setup() { 15 | 16 | // Configure pin 2 as an input and enable the internal pull-up resistor. 17 | pinMode(2, INPUT_PULLUP); 18 | 19 | // Create task for FreeRTOS notification 20 | xTaskCreate(TaskNotification, // Task function 21 | "Notification", // Task name 22 | 128, // Stack size 23 | NULL, 24 | 3, // Priority 25 | &taskNotificationHandler ); // TaskHandle 26 | } 27 | 28 | void loop() { 29 | 30 | } 31 | 32 | /* 33 | Notification task. 34 | */ 35 | void TaskNotification(void *pvParameters) 36 | { 37 | (void) pvParameters; 38 | 39 | int digitalPin = 2; 40 | 41 | Serial.begin(9600); 42 | 43 | attachInterrupt(digitalPinToInterrupt(digitalPin), digitalPinInterruptHandler, LOW); 44 | 45 | for (;;) { 46 | 47 | if (ulTaskNotifyTake(pdTRUE, portMAX_DELAY)) { 48 | Serial.println("Notification received"); 49 | } 50 | 51 | } 52 | } 53 | 54 | 55 | void digitalPinInterruptHandler() { 56 | BaseType_t xHigherPriorityTaskWoken = pdFALSE; 57 | vTaskNotifyGiveFromISR(taskNotificationHandler, &xHigherPriorityTaskWoken); 58 | if (xHigherPriorityTaskWoken) { 59 | taskYIELD(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/StructArray/StructArray.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a basic FreeRTOS queue 3 | * https://www.freertos.org/Embedded-RTOS-Queues.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | // Include queue support 10 | #include 11 | 12 | // Define a Structure Array 13 | struct Arduino{ 14 | int pin[2]; 15 | int ReadValue[2]; 16 | }; 17 | 18 | //Function Declaration 19 | void Blink(void *pvParameters); 20 | void POT(void *pvParameters); 21 | void TaskSerial(void *pvParameters); 22 | 23 | /* 24 | * Declaring a global variable of type QueueHandle_t 25 | * 26 | */ 27 | QueueHandle_t structArrayQueue; 28 | 29 | void setup() { 30 | 31 | /** 32 | * Create a queue. 33 | * https://www.freertos.org/a00116.html 34 | */ 35 | structArrayQueue=xQueueCreate(10, //Queue length 36 | sizeof(struct Arduino)); //Queue item size 37 | 38 | if(structArrayQueue!=NULL){ 39 | 40 | 41 | xTaskCreate(TaskBlink, // Task function 42 | "Blink",// Task name 43 | 128,// Stack size 44 | NULL, 45 | 0,// Priority 46 | NULL); 47 | 48 | // Create other task that publish data in the queue if it was created. 49 | xTaskCreate(POT,// Task function 50 | "AnalogRead",// Task name 51 | 128, // Stack size 52 | NULL, 53 | 2,// Priority 54 | NULL); 55 | 56 | // Create task that consumes the queue if it was created. 57 | xTaskCreate(TaskSerial,// Task function 58 | "PrintSerial",// A name just for humans 59 | 128,// This stack size can be checked & adjusted by reading the Stack Highwater 60 | NULL, 61 | 1, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 62 | NULL); 63 | } 64 | } 65 | 66 | void loop() {} 67 | 68 | /* 69 | * Blink task. 70 | * See Blink_AnalogRead example. 71 | */ 72 | void TaskBlink(void *pvParameters){ 73 | (void) pvParameters; 74 | 75 | pinMode(13,OUTPUT); 76 | 77 | digitalWrite(13,LOW); 78 | 79 | for(;;) 80 | { 81 | digitalWrite(13,HIGH); 82 | vTaskDelay(250/portTICK_PERIOD_MS); 83 | digitalWrite(13,LOW); 84 | vTaskDelay(250/portTICK_PERIOD_MS); 85 | } 86 | } 87 | 88 | /** 89 | * Analog read task for Pin A0 and A1 90 | * Reads an analog input on pin 0 and pin 1 91 | * Send the readed value through the queue. 92 | * See Blink_AnalogRead example. 93 | */ 94 | void POT(void *pvParameters){ 95 | (void) pvParameters; 96 | pinMode(A0,INPUT); 97 | pinMode(A1,INPUT); 98 | for (;;){ 99 | // Read the input on analog pin 0: 100 | struct Arduino currentVariable; 101 | currentVariable.pin[0]=0; 102 | currentVariable.pin[1]=1; 103 | currentVariable.ReadValue[0]=analogRead(A0); 104 | currentVariable.ReadValue[1]=analogRead(A1); 105 | 106 | /** 107 | * Post an item on a queue. 108 | * https://www.freertos.org/a00117.html 109 | */ 110 | xQueueSend(structArrayQueue,¤tVariable,portMAX_DELAY); 111 | 112 | // One tick delay (15ms) in between reads for stability 113 | vTaskDelay(1); 114 | } 115 | } 116 | 117 | /** 118 | * Serial task. 119 | * Prints the received items from the queue to the serial monitor. 120 | */ 121 | void TaskSerial(void *pvParameters){ 122 | (void) pvParameters; 123 | 124 | // Init Arduino serial 125 | Serial.begin(9600); 126 | 127 | // Wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 128 | while (!Serial) { 129 | vTaskDelay(1); 130 | } 131 | 132 | for (;;){ 133 | 134 | struct Arduino currentVariable; 135 | 136 | /** 137 | * Read an item from a queue. 138 | * https://www.freertos.org/a00118.html 139 | */ 140 | if(xQueueReceive(structArrayQueue,¤tVariable,portMAX_DELAY) == pdPASS ){ 141 | for(int i=0;i<2;i++){ 142 | Serial.print("PIN:"); 143 | Serial.println(currentVariable.pin[i]); 144 | Serial.print("value:"); 145 | Serial.println(currentVariable.ReadValue[i]); 146 | } 147 | } 148 | vTaskDelay(500/portTICK_PERIOD_MS); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /examples/StructQueue/StructQueue.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a basic FreeRTOS queue 3 | * https://www.freertos.org/Embedded-RTOS-Queues.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | // Include queue support 10 | #include 11 | 12 | // Define a struct 13 | struct pinRead { 14 | int pin; 15 | int value; 16 | }; 17 | 18 | /* 19 | * Declaring a global variable of type QueueHandle_t 20 | * 21 | */ 22 | QueueHandle_t structQueue; 23 | 24 | void setup() { 25 | 26 | /** 27 | * Create a queue. 28 | * https://www.freertos.org/a00116.html 29 | */ 30 | structQueue = xQueueCreate(10, // Queue length 31 | sizeof(struct pinRead) // Queue item size 32 | ); 33 | 34 | if (structQueue != NULL) { 35 | 36 | // Create task that consumes the queue if it was created. 37 | xTaskCreate(TaskSerial, // Task function 38 | "Serial", // A name just for humans 39 | 128, // This stack size can be checked & adjusted by reading the Stack Highwater 40 | NULL, 41 | 2, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 42 | NULL); 43 | 44 | 45 | // Create task that publish data in the queue if it was created. 46 | xTaskCreate(TaskAnalogReadPin0, // Task function 47 | "AnalogReadPin0", // Task name 48 | 128, // Stack size 49 | NULL, 50 | 1, // Priority 51 | NULL); 52 | 53 | // Create other task that publish data in the queue if it was created. 54 | xTaskCreate(TaskAnalogReadPin1, // Task function 55 | "AnalogReadPin1", // Task name 56 | 128, // Stack size 57 | NULL, 58 | 1, // Priority 59 | NULL); 60 | 61 | } 62 | 63 | 64 | xTaskCreate(TaskBlink, // Task function 65 | "Blink", // Task name 66 | 128, // Stack size 67 | NULL, 68 | 0, // Priority 69 | NULL ); 70 | 71 | } 72 | 73 | void loop() {} 74 | 75 | 76 | /** 77 | * Analog read task for Pin A0 78 | * Reads an analog input on pin 0 and send the readed value through the queue. 79 | * See Blink_AnalogRead example. 80 | */ 81 | void TaskAnalogReadPin0(void *pvParameters) 82 | { 83 | (void) pvParameters; 84 | 85 | for (;;) 86 | { 87 | // Read the input on analog pin 0: 88 | struct pinRead currentPinRead; 89 | currentPinRead.pin = 0; 90 | currentPinRead.value = analogRead(A0); 91 | 92 | /** 93 | * Post an item on a queue. 94 | * https://www.freertos.org/a00117.html 95 | */ 96 | xQueueSend(structQueue, ¤tPinRead, portMAX_DELAY); 97 | 98 | // One tick delay (15ms) in between reads for stability 99 | vTaskDelay(1); 100 | } 101 | } 102 | 103 | 104 | /** 105 | * Analog read task for Pin A1 106 | * Reads an analog input on pin 1 and send the readed value through the queue. 107 | * See Blink_AnalogRead example. 108 | */ 109 | void TaskAnalogReadPin1(void *pvParameters) 110 | { 111 | (void) pvParameters; 112 | 113 | for (;;) 114 | { 115 | // Read the input on analog pin 1: 116 | struct pinRead currentPinRead; 117 | currentPinRead.pin = 1; 118 | currentPinRead.value = analogRead(A1); 119 | 120 | /** 121 | * Post an item on a queue. 122 | * https://www.freertos.org/a00117.html 123 | */ 124 | xQueueSend(structQueue, ¤tPinRead, portMAX_DELAY); 125 | 126 | // One tick delay (15ms) in between reads for stability 127 | vTaskDelay(1); 128 | } 129 | } 130 | 131 | /** 132 | * Serial task. 133 | * Prints the received items from the queue to the serial monitor. 134 | */ 135 | void TaskSerial(void * pvParameters) { 136 | (void) pvParameters; 137 | 138 | // Init Arduino serial 139 | Serial.begin(9600); 140 | 141 | // Wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 142 | while (!Serial) { 143 | vTaskDelay(1); 144 | } 145 | 146 | for (;;) 147 | { 148 | 149 | struct pinRead currentPinRead; 150 | 151 | /** 152 | * Read an item from a queue. 153 | * https://www.freertos.org/a00118.html 154 | */ 155 | if (xQueueReceive(structQueue, ¤tPinRead, portMAX_DELAY) == pdPASS) { 156 | Serial.print("Pin: "); 157 | Serial.print(currentPinRead.pin); 158 | Serial.print(" Value: "); 159 | Serial.println(currentPinRead.value); 160 | } 161 | } 162 | } 163 | 164 | /* 165 | * Blink task. 166 | * See Blink_AnalogRead example. 167 | */ 168 | void TaskBlink(void *pvParameters) 169 | { 170 | (void) pvParameters; 171 | 172 | pinMode(LED_BUILTIN, OUTPUT); 173 | 174 | for (;;) 175 | { 176 | digitalWrite(LED_BUILTIN, HIGH); 177 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 178 | digitalWrite(LED_BUILTIN, LOW); 179 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /examples/TaskStatus/TaskStatus.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //define task handles 4 | TaskHandle_t TaskBlink_Handler; 5 | TaskHandle_t TaskSerial_Handler; 6 | 7 | // define two tasks for Blink & Serial 8 | void TaskBlink( void *pvParameters ); 9 | void TaskSerial(void* pvParameters); 10 | 11 | // the setup function runs once when you press reset or power the board 12 | void setup() { 13 | // initialize serial communication at 9600 bits per second: 14 | Serial.begin(9600); 15 | 16 | while (!Serial) { 17 | ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. 18 | } 19 | 20 | // Now set up two tasks to run independently. 21 | xTaskCreate( 22 | TaskBlink 23 | , "Blink" // A name just for humans 24 | , 128 // This stack size can be checked & adjusted by reading the Stack Highwater 25 | , NULL //Parameters passed to the task function 26 | , 2 // Priority, with 2 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. 27 | , &TaskBlink_Handler );//Task handle 28 | 29 | xTaskCreate( 30 | TaskSerial 31 | , "Serial" 32 | , 128 // Stack size 33 | , NULL //Parameters passed to the task function 34 | , 1 // Priority 35 | , &TaskSerial_Handler ); //Task handle 36 | } 37 | 38 | 39 | void loop() 40 | { 41 | // Empty. Things are done in Tasks. 42 | } 43 | 44 | /*--------------------------------------------------*/ 45 | /*---------------------- Tasks ---------------------*/ 46 | /*--------------------------------------------------*/ 47 | 48 | void TaskSerial(void* pvParameters){ 49 | /* 50 | Serial 51 | Send "s" or "r" through the serial port to control the suspend and resume of the LED light task. 52 | This example code is in the public domain. 53 | */ 54 | (void) pvParameters; 55 | for (;;) // A Task shall never return or exit. 56 | { 57 | while(Serial.available()>0){ 58 | switch(Serial.read()){ 59 | case 's': 60 | vTaskSuspend(TaskBlink_Handler); 61 | Serial.println("Suspend!"); 62 | break; 63 | case 'r': 64 | vTaskResume(TaskBlink_Handler); 65 | Serial.println("Resume!"); 66 | break; 67 | } 68 | vTaskDelay(1); 69 | } 70 | } 71 | } 72 | 73 | void TaskBlink(void *pvParameters) // This is a task. 74 | { 75 | (void) pvParameters; 76 | pinMode(LED_BUILTIN, OUTPUT); 77 | for (;;) // A Task shall never return or exit. 78 | { 79 | //Serial.println(11); 80 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 81 | vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second 82 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW 83 | vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /examples/TaskUtilities/TaskUtilities.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of FreeRTOS task utilities 3 | * https://www.freertos.org/a00021.html 4 | */ 5 | 6 | // Include Arduino FreeRTOS library 7 | #include 8 | 9 | /** 10 | * Task handlers 11 | * https://www.freertos.org/a00019.html#xTaskHandle 12 | */ 13 | TaskHandle_t taskBlinkHandle; 14 | 15 | TaskHandle_t taskDeletedHandle; 16 | 17 | TaskHandle_t taskBlockedHandle; 18 | 19 | void setup() { 20 | 21 | /** 22 | * Task creation 23 | */ 24 | xTaskCreate(TaskBlink, // Task function 25 | "Blink", // Task name 26 | 128, // Stack size 27 | NULL, 28 | 0, // Priority 29 | &taskBlinkHandle); // Task handler 30 | 31 | xTaskCreate(TaskSerial, 32 | "Serial", 33 | 128, 34 | NULL, 35 | 2, 36 | NULL); 37 | 38 | xTaskCreate(TaskDeleted, 39 | "Deleted", 40 | 64, 41 | NULL, 42 | 1, 43 | &taskDeletedHandle); 44 | 45 | xTaskCreate(TaskBlocked, 46 | "Blocked", 47 | 64, 48 | NULL, 49 | 1, 50 | &taskBlockedHandle); 51 | 52 | } 53 | 54 | void loop() {} 55 | 56 | /** 57 | * Example of utilities usage 58 | */ 59 | void TaskSerial(void *pvParameters) 60 | { 61 | (void) pvParameters; 62 | 63 | Serial.begin(9600); 64 | 65 | for (;;) 66 | { 67 | Serial.println("======== Tasks status ========"); 68 | Serial.print("Tick count: "); 69 | Serial.print(xTaskGetTickCount()); 70 | Serial.print(", Task count: "); 71 | Serial.print(uxTaskGetNumberOfTasks()); 72 | 73 | Serial.println(); 74 | Serial.println(); 75 | 76 | // Serial task status 77 | Serial.print("- TASK "); 78 | Serial.print(pcTaskGetName(NULL)); // Get task name without handler https://www.freertos.org/a00021.html#pcTaskGetName 79 | Serial.print(", High Watermark: "); 80 | Serial.print(uxTaskGetStackHighWaterMark(NULL)); // https://www.freertos.org/uxTaskGetStackHighWaterMark.html 81 | 82 | 83 | TaskHandle_t taskSerialHandle = xTaskGetCurrentTaskHandle(); // Get current task handle. https://www.freertos.org/a00021.html#xTaskGetCurrentTaskHandle 84 | 85 | Serial.println(); 86 | 87 | Serial.print("- TASK "); 88 | Serial.print(pcTaskGetName(taskBlinkHandle)); // Get task name with handler 89 | Serial.print(", High Watermark: "); 90 | Serial.print(uxTaskGetStackHighWaterMark(taskBlinkHandle)); 91 | Serial.println(); 92 | 93 | Serial.print("- TASK "); 94 | Serial.print(pcTaskGetName(taskDeletedHandle)); 95 | Serial.print(", High Watermark: "); 96 | Serial.print(uxTaskGetStackHighWaterMark(taskDeletedHandle)); 97 | Serial.println(); 98 | 99 | Serial.print("- TASK "); 100 | Serial.print(pcTaskGetName(taskBlockedHandle)); 101 | Serial.print(", High Watermark: "); 102 | Serial.print(uxTaskGetStackHighWaterMark(taskBlockedHandle)); 103 | Serial.println(); 104 | 105 | Serial.println(); 106 | 107 | vTaskDelay( 5000 / portTICK_PERIOD_MS ); 108 | } 109 | } 110 | 111 | /** 112 | * Blocked tasks when run 113 | */ 114 | void TaskBlocked(void *pvParameters) { 115 | (void) pvParameters; 116 | for (;;) 117 | { 118 | vTaskDelay( 900000 / portTICK_PERIOD_MS ); 119 | } 120 | } 121 | 122 | /** 123 | * Deleted tasks when run 124 | */ 125 | void TaskDeleted(void *pvParameters) { 126 | (void) pvParameters; 127 | 128 | vTaskDelete(NULL); 129 | } 130 | 131 | /* 132 | * Blink task. 133 | * See Blink_AnalogRead example. 134 | */ 135 | void TaskBlink(void *pvParameters) 136 | { 137 | (void) pvParameters; 138 | 139 | pinMode(LED_BUILTIN, OUTPUT); 140 | 141 | for (;;) 142 | { 143 | digitalWrite(LED_BUILTIN, HIGH); 144 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 145 | digitalWrite(LED_BUILTIN, LOW); 146 | vTaskDelay( 250 / portTICK_PERIOD_MS ); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax Coloring Map For FreeRTOS 2 | # https://arduino.github.io/arduino-cli/library-specification/#keywords 3 | # Formatted by a single true tab (not spaces) 4 | 5 | # Datatypes (KEYWORD1) 6 | StackType_t KEYWORD1 7 | BaseType_t KEYWORD1 8 | UBaseType_t KEYWORD1 9 | TickType_t KEYWORD1 10 | 11 | TaskHandle_t KEYWORD1 12 | QueueHandle_t KEYWORD1 13 | TimerHandle_t KEYWORD1 14 | SemaphoreHandle_t KEYWORD1 15 | StreamBufferHandle_t KEYWORD1 16 | MessageBufferHandle_t KEYWORD1 17 | EventGroupHandle_t KEYWORD1 18 | 19 | # Methods and Functions (KEYWORD2) 20 | xSemaphoreCreateMutex KEYWORD2 21 | xSemaphoreCreateBinary KEYWORD2 22 | xSemaphoreTake KEYWORD2 23 | xSemaphoreTakeFromISR KEYWORD2 24 | xSemaphoreGive KEYWORD2 25 | xSemaphoreGiveFromISR KEYWORD2 26 | xTaskCreate KEYWORD2 27 | vTaskDelete KEYWORD2 28 | vTaskDelay KEYWORD2 29 | xTaskDelayUntil KEYWORD2 30 | xQueueCreate KEYWORD2 31 | xQueueSend KEYWORD2 32 | xQueueReceive KEYWORD2 33 | pcTaskGetName KEYWORD2 34 | ulTaskNotifyTake KEYWORD2 35 | vTaskNotifyGiveFromISR KEYWORD2 36 | taskYIELD KEYWORD2 37 | vTaskSuspend KEYWORD2 38 | vTaskResume KEYWORD2 39 | xTaskResumeFromISR KEYWORD2 40 | xTaskGetTickCount KEYWORD2 41 | xTaskGetTickCountFromISR KEYWORD2 42 | uxTaskGetNumberOfTasks KEYWORD2 43 | uxTaskGetStackHighWaterMark KEYWORD2 44 | 45 | # Instances (KEYWORD2) 46 | 47 | # Structures (KEYWORD3) 48 | TaskParameters_t KEYWORD3 49 | TaskStatus_t KEYWORD3 50 | ListItem_t KEYWORD3 51 | MiniListItem_t KEYWORD3 52 | HeapStats_t KEYWORD3 53 | 54 | # Constants (LITERAL1) 55 | portUSE_WDTO LITERAL1 56 | portTICK_PERIOD_MS LITERAL1 57 | configTICK_RATE_HZ LITERAL1 58 | configCPU_CLOCK_HZ LITERAL1 59 | configMAX_PRIORITIES LITERAL1 60 | configMINIMAL_STACK_SIZE LITERAL1 61 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=FreeRTOS 2 | version=11.1.0-3 3 | author=Richard Barry 4 | maintainer=Phillip Stevens 5 | sentence=FreeRTOS Real Time Operating System implemented for Arduino Uno R3, Nano, Leonardo, Mega, and related Microchip ATmega devices. 6 | paragraph=The primary design goals are: Easy to use, Small footprint, Robust. Uses Watchdog Timer for 15ms resolution. Slow blink = stack overflow. Fast blink = heap malloc() failure. 7 | category=Timing 8 | url=https://github.com/feilipu/Arduino_FreeRTOS_Library 9 | architectures=avr 10 | license=MIT 11 | includes=Arduino_FreeRTOS.h 12 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | This is a fork of Richard Barry's FreeRTOS, optimised for the Arduino Microchip ATmega devices. 2 | 3 | It has been created to provide access to FreeRTOS capabilities, with full compatibility to the Arduino IDE environment. 4 | It does this by keeping hands off almost everything, and only touching the minimum of hardware to be successful. 5 | 6 | If you want to use FreeRTOS on the Renesas family of Arduino like the Arduino UNO R4, it is [already included](https://github.com/arduino/ArduinoCore-renesas/tree/main/libraries/Arduino_FreeRTOS) in the default Arduino IDE. All that is required is to include the header file `Arduino_FreeRTOS.h` provided by the Arduino IDE, and follow the information noted below. 7 | 8 | ## Usage & Further Reading 9 | 10 | Read the short blog post on [Arduino FreeRTOS](https://feilipu.me/2015/11/24/arduino_freertos/) to get started. And there is another much older post on using [FreeRTOS with AVR](https://feilipu.me/2011/09/22/freertos-and-libraries-for-avr-atmega/), which may be useful to read too. There are some further posts I've written on [Hackster.IO](https://www.hackster.io/feilipu), but they're essentially the same content. 11 | 12 | The canonical source for information is the [FreeRTOS Web Site](https://www.freertos.org/). Within this site, the [Beginner's Guide](https://www.freertos.org/Documentation/01-FreeRTOS-quick-start/01-Beginners-guide/00-Overview) is very useful. This is the source for FreeRTOS usage (as distinct from installing and using this Arduino Library). 13 | 14 | My other [AVRfreeRTOS Sourceforge Repository](https://sourceforge.net/projects/avrfreertos/) or [AVRfreeRTOS Github](https://github.com/feilipu/avrfreertos) has plenty of examples, ranging from [blink](https://sourceforge.net/projects/avrfreertos/files/MegaBlink/) through to a [synthesiser](https://sourceforge.net/projects/avrfreertos/files/GA_Synth/). 15 | 16 | This library was the genesis of [generalised support for the ATmega platform within FreeRTOS](https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/48), and improvement of the [stack depth type management](https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/942). 17 | 18 | Over the past few years FreeRTOS development has become increasingly 32-bit orientated, now including symmetric multiprocessing, with little change or improvement for the 8-bit world. As such I'm treating this FreeRTOS V11.1.0 (updated April 22 2024) as my LTS release. 19 | 20 | ## General 21 | 22 | FreeRTOS has a multitude of configuration options, which can be specified from within the FreeRTOSConfig.h file. 23 | To keep commonality with all of the Arduino hardware options, some sensible defaults have been selected. Feel free to change these defaults as you gain experience with FreeRTOS. 24 | 25 | Normally, the ATmega Watchdog Timer is used to generate 15ms time slices (Ticks). For applications requiring high precision timing, the Ticks can be sourced from a hardware timer or external clock. See chapter [Scheduler Tick Sources](./doc/tick_sources.md) for the configuration details. 26 | 27 | Tasks that suspend or delay before their allocated time slice completes will revert execution back to the Scheduler. 28 | 29 | The Arduino `delay()` function has been redefined to automatically use the FreeRTOS `vTaskDelay()` function when the delay required is one Tick or longer, by setting `configUSE_PORT_DELAY` to `1`, so that simple Arduino example sketches and tutorials work as expected. If you would like to measure a short millisecond delay of less than one Tick, then preferably use [`millis()`](https://www.arduino.cc/reference/en/language/functions/time/millis/) (or with greater granularity use [`micros()`](https://www.arduino.cc/reference/en/language/functions/time/micros/)) to achieve this outcome (for example see [BlinkWithoutDelay](https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay)). However, when the delay requested is less than one Tick then the original Arduino `delay()` function will be automatically selected. 30 | 31 | The 8-bit ATmega Timer0 has been added as an option for the experienced user. Please examine the Timer0 source code example to figure out how to use it. Reconfiguring Timer0 for the FreeRTOS Tick will break Arduino `millis()` and `micros()` though, as these functions rely on the Arduino IDE configuring Timer0. Example support for the Logic Green hardware using Timer 3 is provided via an open PR. 32 | 33 | Stack for the `loop()` function has been set at 192 Bytes. This can be configured by adjusting the `configMINIMAL_STACK_SIZE` parameter. If you have stack overflow issues just increase it (within the SRAM limitations of your hardware). Users should prefer to allocate larger structures, arrays, or buffers on the heap using `pvPortMalloc()`, rather than defining them locally on the stack. Ideally you should __not__ use `loop()` for your sketches, and then the Idle Task stack size can be reduced down to 92 Bytes which will save some valuable memory. 34 | 35 | Memory for the heap is allocated by the normal C `malloc()` function, wrapped by the FreeRTOS `pvPortMalloc()` function. This option has been selected because it is automatically adjusted to use the capabilities of each device. Other heap allocation schemes are supported by FreeRTOS, and they can used with some additional configuration. 36 | 37 | If you do not need to use FreeRTOS Timer API functions, then they can be disabled. This will remove the need for the Timer Task Stack, saving 92 Bytes of RAM. 38 | 39 | ## Upgrading 40 | 41 | * [Upgrading to FreeRTOS-9](https://www.freertos.org/FreeRTOS-V9.html) 42 | * [Upgrading to FreeRTOS-10](https://www.freertos.org/FreeRTOS-V10.html) 43 | * [Symmetric Multiprocessing with FreeRTOS-11](https://www.freertos.org/2023/12/introducing-freertos-kernel-version-11-0-0-a-major-release-with-symmetric-multiprocessing-smp-support.html) 44 | 45 | ## Errors 46 | 47 | * Stack Overflow: If any stack (for the `loop()` or) for any Task overflows, there will be a slow LED blink, with 4 second cycle. 48 | * Heap Overflow: If any Task tries to allocate memory and that allocation fails, there will be a fast LED blink, with 100 millisecond cycle. 49 | 50 | ## Errata 51 | 52 | Testing with the Software Serial library shows some incompatibilities at low baud rates (9600), due to the extended time this library disables the global interrupt. Use the hardware USARTs. 53 | 54 | ## Compatibility 55 | 56 | * ATmega328 @ 16MHz : Arduino UNO R3, 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 @ 16MHz: Sanguino, WickedDevice WildFire 64 | * ATmega1284p @ 24.576MHz : Seeed Studio Goldilocks Analogue 65 | * ATmega2560 @ 16MHz : Arduino Mega, Arduino ADK 66 | * ATmega2560 @ 16MHz : Seeed Studio ADK 67 | 68 | The new megaAVR 0-Series devices (eg. ATmega4809) are not fully compatible with this library. Their Timer configuration is substantially different from previous devices, and forms part of a new __avr8x__ architecture. It may be a while until avr-libc is updated to include support for megaAVR devices, but when that happens further work will be added here. 69 | 70 | The Arduino IDE supporting the Arduino UNO R4 already includes FreeRTOS as standard. 71 | 72 | ## Files & Configuration 73 | 74 | * `Arduino_FreeRTOS.h` : Must always be `#include` first. It references other configuration files, and sets defaults where necessary. 75 | * `FreeRTOSConfig.h` : Contains a multitude of API and environment configurations. 76 | * `FreeRTOSVariant.h` : Contains the ATmega specific configurations for this port of FreeRTOS. 77 | * `heap_3.c` : Contains the heap allocation scheme based on `malloc()`. Other schemes are available, but depend on user configuration for specific MCU choice. 78 | 79 | ### PlatformIO 80 | 81 | [Arduino FreeRTOS](https://platformio.org/lib/show/507/FreeRTOS) is available in the [PlatformIO library manager](https://docs.platformio.org/en/latest/librarymanager/index.html) for use in a [PlatformIO project](https://docs.platformio.org/en/latest/projectconf/index.html). 82 | 83 | Watchdog period is configurable using build-flags: 84 | 85 | ```python 86 | build_flags = 87 | -DportUSE_WDTO=WDTO_15MS 88 | ``` 89 | 90 | ### Code of conduct 91 | 92 | See the [Code of conduct](https://github.com/feilipu/Arduino_FreeRTOS_Library/blob/master/CODE_OF_CONDUCT.md). 93 | 94 | ## Contributors ✨ 95 | 96 | 97 | [![All Contributors](https://img.shields.io/badge/all_contributors-10-green.svg?style=flat-square)](#contributors-) 98 | 99 | 100 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |

Phillip Stevens

🚧💻👀📖

Hector Espert

💻

Floessie

💻

Derekduke

💻

Balaji.V

💻📖

John Y. Pazekha

💻📖

Guglielmo Braguglia

💻📖

ShortArrow

📖

Altuğ Bakan

💻

Ian Katz

💻
121 | 122 | 123 | 124 | 125 | 126 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 127 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | /Debug/ 2 | /Release/ 3 | -------------------------------------------------------------------------------- /src/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 | /* Delay definition - here, the user can choose which delay implementation is required. 48 | * The default is to change nothing. */ 49 | #define configUSE_PORT_DELAY 1 50 | 51 | /* And on to the things the same no matter the AVR type... */ 52 | #define configUSE_PREEMPTION 1 53 | 54 | #define configCPU_CLOCK_HZ ( ( uint32_t ) F_CPU ) // This F_CPU variable set by the environment 55 | #define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_16_BITS 56 | 57 | #define configMAX_PRIORITIES 4 58 | #define configMAX_TASK_NAME_LEN 16 59 | 60 | /* Set the stack depth type to be uint16_t, otherwise it defaults to StackType_t */ 61 | #define configSTACK_DEPTH_TYPE uint16_t 62 | 63 | #define configMINIMAL_STACK_SIZE 192 64 | #define configCHECK_FOR_STACK_OVERFLOW 1 65 | #define configUSE_TRACE_FACILITY 0 66 | 67 | #define configUSE_MUTEXES 1 68 | #define configUSE_RECURSIVE_MUTEXES 1 69 | #define configUSE_COUNTING_SEMAPHORES 1 70 | #define configUSE_TIME_SLICING 1 71 | 72 | #define configUSE_QUEUE_SETS 0 73 | #define configUSE_APPLICATION_TASK_TAG 0 74 | #define configUSE_MALLOC_FAILED_HOOK 1 75 | #define configQUEUE_REGISTRY_SIZE 0 76 | #define configSUPPORT_DYNAMIC_ALLOCATION 1 77 | #define configSUPPORT_STATIC_ALLOCATION 0 78 | 79 | #define configUSE_IDLE_HOOK 1 80 | #define configIDLE_SHOULD_YIELD 1 81 | #define configUSE_TICK_HOOK 0 82 | 83 | /* Timer definitions. */ 84 | #define configUSE_TIMERS 1 85 | #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES-1 ) 86 | #define configTIMER_TASK_STACK_DEPTH 92 87 | #define configTIMER_QUEUE_LENGTH 10 88 | 89 | /* Set the following definitions to 1 to include the API function, or zero 90 | to exclude the API function. */ 91 | 92 | /* Set the following INCLUDE_* constants to 1 to incldue the named API function, 93 | * or 0 to exclude the named API function. Most linkers will remove unused 94 | * functions even when the constant is 1. */ 95 | #define INCLUDE_vTaskPrioritySet 1 96 | #define INCLUDE_uxTaskPriorityGet 1 97 | #define INCLUDE_vTaskDelete 1 98 | #define INCLUDE_vTaskSuspend 1 99 | #define INCLUDE_xTaskResumeFromISR 1 100 | #define INCLUDE_xTaskDelayUntil 1 101 | #define INCLUDE_vTaskDelay 1 102 | #define INCLUDE_xTaskGetSchedulerState 0 103 | #define INCLUDE_xTaskGetCurrentTaskHandle 1 104 | #define INCLUDE_uxTaskGetStackHighWaterMark 1 105 | #define INCLUDE_xTaskGetIdleTaskHandle 0 106 | #define INCLUDE_eTaskGetState 0 107 | #define INCLUDE_xEventGroupSetBitFromISR 1 108 | #define INCLUDE_xTimerPendFunctionCall 0 109 | #define INCLUDE_xTaskAbortDelay 0 110 | #define INCLUDE_xTaskGetHandle 0 111 | 112 | #define configMAX(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; }) 113 | #define configMIN(a,b) ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; }) 114 | 115 | /** 116 | * configASSERT macro: https://www.freertos.org/a00110.html#configASSERT 117 | */ 118 | #ifndef configASSERT 119 | #define configDEFAULT_ASSERT 0 120 | #else 121 | /** 122 | * Enable configASSERT macro if it is defined. 123 | */ 124 | #ifndef configDEFAULT_ASSERT 125 | #define configDEFAULT_ASSERT 1 126 | #endif 127 | 128 | /** 129 | * Define a hook method for configASSERT macro if configASSERT is enabled. 130 | */ 131 | #if configDEFAULT_ASSERT == 1 132 | extern void vApplicationAssertHook(); 133 | #define configASSERT( x ) if (( x ) == 0) { vApplicationAssertHook(); } 134 | #endif 135 | #endif 136 | 137 | 138 | #endif /* FREERTOS_CONFIG_H */ 139 | -------------------------------------------------------------------------------- /src/FreeRTOSVariant.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 | #ifndef freeRTOSVariant_h 27 | #define freeRTOSVariant_h 28 | 29 | #include 30 | #include 31 | 32 | #ifndef INC_TASK_H 33 | #include "Arduino_FreeRTOS.h" 34 | #include "task.h" 35 | #endif 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | // System Tick - Scheduler timer 42 | // Use the Watchdog timer, and choose the rate at which scheduler interrupts will occur. 43 | 44 | /* Watchdog Timer is 128kHz nominal, but 120 kHz at 5V DC and 25 degrees is actually more accurate, from data sheet. */ 45 | 46 | #ifndef portUSE_WDTO 47 | #define portUSE_WDTO WDTO_15MS // portUSE_WDTO to use the Watchdog Timer for xTaskIncrementTick 48 | #endif 49 | 50 | /* Watchdog period options: WDTO_15MS 51 | WDTO_30MS 52 | WDTO_60MS 53 | WDTO_120MS 54 | WDTO_250MS 55 | WDTO_500MS 56 | WDTO_1S 57 | WDTO_2S 58 | */ 59 | 60 | #if defined( portUSE_WDTO ) 61 | 62 | #define configTICK_RATE_HZ ( (TickType_t)( (uint32_t)128000 >> (portUSE_WDTO + 11) ) ) // 2^11 = 2048 WDT scaler for 128kHz Timer 63 | #define portTICK_PERIOD_MS ( (TickType_t) _BV( portUSE_WDTO + 4 ) ) 64 | #else 65 | #warning "Variant configuration must define `configTICK_RATE_HZ` and `portTICK_PERIOD_MS` as either a macro or a constant" 66 | #define configTICK_RATE_HZ 1 67 | #define portTICK_PERIOD_MS ( (TickType_t) ( 1000 / configTICK_RATE_HZ ) ) 68 | #endif 69 | 70 | /*-----------------------------------------------------------*/ 71 | 72 | void initVariant(void); 73 | 74 | void vApplicationIdleHook( void ); 75 | 76 | void vApplicationMallocFailedHook( void ); 77 | void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName ); 78 | 79 | void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 80 | StackType_t ** ppxIdleTaskStackBuffer, 81 | configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ); 82 | void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, 83 | StackType_t ** ppxTimerTaskStackBuffer, 84 | configSTACK_DEPTH_TYPE * puxTimerTaskStackSize ); 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #endif // freeRTOSVariant_h 91 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 "Arduino_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 | /* 96 | * Reset the state in this file. This state is normally initialized at start up. 97 | * This function must be called by the application before restarting the 98 | * scheduler. 99 | */ 100 | void vPortHeapResetState( void ) 101 | { 102 | /* No state needs to be re-initialised in heap_3. */ 103 | } 104 | /*-----------------------------------------------------------*/ 105 | #endif /* ( configSUPPORT_DYNAMIC_ALLOCATION > 0 ) */ 106 | -------------------------------------------------------------------------------- /src/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 "Arduino_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 | -------------------------------------------------------------------------------- /src/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_ARDUINO_FREERTOS_H 62 | #error "Arduino_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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | #if configUSE_PORT_DELAY == 1 93 | /* 94 | * If configUSE_PORT_DELAY is defined, 95 | * delay() is implemented as either the Arduino delay() 96 | * if the delay is less than one Tick, or 97 | * otherwise as FreeRTOS vTaskDelay() for longer delays. 98 | */ 99 | 100 | #ifndef delay 101 | #define delay vPortDelay 102 | #endif 103 | 104 | #endif 105 | 106 | #ifndef configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 107 | /* Defaults to 0 for backward compatibility. */ 108 | #define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 109 | #endif 110 | 111 | #include "mpu_wrappers.h" 112 | 113 | /* *INDENT-OFF* */ 114 | #ifdef __cplusplus 115 | extern "C" { 116 | #endif 117 | /* *INDENT-ON* */ 118 | 119 | /* 120 | * Setup the stack of a new task so it is ready to be placed under the 121 | * scheduler control. The registers have to be placed on the stack in 122 | * the order that the port expects to find them. 123 | * 124 | */ 125 | #if ( portUSING_MPU_WRAPPERS == 1 ) 126 | #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) 127 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 128 | StackType_t * pxEndOfStack, 129 | TaskFunction_t pxCode, 130 | void * pvParameters, 131 | BaseType_t xRunPrivileged, 132 | xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; 133 | #else 134 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 135 | TaskFunction_t pxCode, 136 | void * pvParameters, 137 | BaseType_t xRunPrivileged, 138 | xMPU_SETTINGS * xMPUSettings ) PRIVILEGED_FUNCTION; 139 | #endif /* if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) */ 140 | #else /* if ( portUSING_MPU_WRAPPERS == 1 ) */ 141 | #if ( portHAS_STACK_OVERFLOW_CHECKING == 1 ) 142 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 143 | StackType_t * pxEndOfStack, 144 | TaskFunction_t pxCode, 145 | void * pvParameters ) PRIVILEGED_FUNCTION; 146 | #else 147 | StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, 148 | TaskFunction_t pxCode, 149 | void * pvParameters ) PRIVILEGED_FUNCTION; 150 | #endif 151 | #endif /* if ( portUSING_MPU_WRAPPERS == 1 ) */ 152 | 153 | /* Used by heap_5.c to define the start address and size of each memory region 154 | * that together comprise the total FreeRTOS heap space. */ 155 | typedef struct HeapRegion 156 | { 157 | uint8_t * pucStartAddress; 158 | size_t xSizeInBytes; 159 | } HeapRegion_t; 160 | 161 | /* Used to pass information about the heap out of vPortGetHeapStats(). */ 162 | typedef struct xHeapStats 163 | { 164 | 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. */ 165 | size_t xSizeOfLargestFreeBlockInBytes; /* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ 166 | size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */ 167 | size_t xNumberOfFreeBlocks; /* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */ 168 | 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. */ 169 | size_t xNumberOfSuccessfulAllocations; /* The number of calls to pvPortMalloc() that have returned a valid memory block. */ 170 | size_t xNumberOfSuccessfulFrees; /* The number of calls to vPortFree() that has successfully freed a block of memory. */ 171 | } HeapStats_t; 172 | 173 | /* 174 | * Used to define multiple heap regions for use by heap_5.c. This function 175 | * must be called before any calls to pvPortMalloc() - not creating a task, 176 | * queue, semaphore, mutex, software timer, event group, etc. will result in 177 | * pvPortMalloc being called. 178 | * 179 | * pxHeapRegions passes in an array of HeapRegion_t structures - each of which 180 | * defines a region of memory that can be used as the heap. The array is 181 | * terminated by a HeapRegions_t structure that has a size of 0. The region 182 | * with the lowest start address must appear first in the array. 183 | */ 184 | void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION; 185 | 186 | /* 187 | * Returns a HeapStats_t structure filled with information about the current 188 | * heap state. 189 | */ 190 | void vPortGetHeapStats( HeapStats_t * pxHeapStats ); 191 | 192 | /* 193 | * Map to the memory management routines required for the port. 194 | */ 195 | void * pvPortMalloc( size_t xWantedSize ) PRIVILEGED_FUNCTION; 196 | void * pvPortCalloc( size_t xNum, 197 | size_t xSize ) PRIVILEGED_FUNCTION; 198 | void vPortFree( void * pv ) PRIVILEGED_FUNCTION; 199 | void vPortInitialiseBlocks( void ) PRIVILEGED_FUNCTION; 200 | size_t xPortGetFreeHeapSize( void ) PRIVILEGED_FUNCTION; 201 | size_t xPortGetMinimumEverFreeHeapSize( void ) PRIVILEGED_FUNCTION; 202 | 203 | #if ( configSTACK_ALLOCATION_FROM_SEPARATE_HEAP == 1 ) 204 | void * pvPortMallocStack( size_t xSize ) PRIVILEGED_FUNCTION; 205 | void vPortFreeStack( void * pv ) PRIVILEGED_FUNCTION; 206 | #else 207 | #define pvPortMallocStack pvPortMalloc 208 | #define vPortFreeStack vPortFree 209 | #endif 210 | 211 | /* 212 | * This function resets the internal state of the heap module. It must be called 213 | * by the application before restarting the scheduler. 214 | */ 215 | void vPortHeapResetState( void ) PRIVILEGED_FUNCTION; 216 | 217 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 218 | 219 | /** 220 | * task.h 221 | * @code{c} 222 | * void vApplicationMallocFailedHook( void ) 223 | * @endcode 224 | * 225 | * This hook function is called when allocation failed. 226 | */ 227 | void vApplicationMallocFailedHook( void ); 228 | #endif 229 | 230 | /* 231 | * Setup the hardware ready for the scheduler to take control. This generally 232 | * sets up a tick interrupt and sets timers for the correct tick frequency. 233 | */ 234 | BaseType_t xPortStartScheduler( void ) PRIVILEGED_FUNCTION; 235 | 236 | /* 237 | * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so 238 | * the hardware is left in its original condition after the scheduler stops 239 | * executing. 240 | */ 241 | void vPortEndScheduler( void ) PRIVILEGED_FUNCTION; 242 | 243 | /* 244 | * The structures and methods of manipulating the MPU are contained within the 245 | * port layer. 246 | * 247 | * Fills the xMPUSettings structure with the memory region information 248 | * contained in xRegions. 249 | */ 250 | #if ( portUSING_MPU_WRAPPERS == 1 ) 251 | struct xMEMORY_REGION; 252 | void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, 253 | const struct xMEMORY_REGION * const xRegions, 254 | StackType_t * pxBottomOfStack, 255 | configSTACK_DEPTH_TYPE uxStackDepth ) PRIVILEGED_FUNCTION; 256 | #endif 257 | 258 | /** 259 | * @brief Checks if the calling task is authorized to access the given buffer. 260 | * 261 | * @param pvBuffer The buffer which the calling task wants to access. 262 | * @param ulBufferLength The length of the pvBuffer. 263 | * @param ulAccessRequested The permissions that the calling task wants. 264 | * 265 | * @return pdTRUE if the calling task is authorized to access the buffer, 266 | * pdFALSE otherwise. 267 | */ 268 | #if ( portUSING_MPU_WRAPPERS == 1 ) 269 | BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer, 270 | uint32_t ulBufferLength, 271 | uint32_t ulAccessRequested ) PRIVILEGED_FUNCTION; 272 | #endif 273 | 274 | /** 275 | * @brief Checks if the calling task is authorized to access the given kernel object. 276 | * 277 | * @param lInternalIndexOfKernelObject The index of the kernel object in the kernel 278 | * object handle pool. 279 | * 280 | * @return pdTRUE if the calling task is authorized to access the kernel object, 281 | * pdFALSE otherwise. 282 | */ 283 | #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) 284 | 285 | BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) PRIVILEGED_FUNCTION; 286 | 287 | #endif 288 | 289 | /* *INDENT-OFF* */ 290 | #ifdef __cplusplus 291 | } 292 | #endif 293 | /* *INDENT-ON* */ 294 | 295 | #endif /* PORTABLE_H */ 296 | -------------------------------------------------------------------------------- /src/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 | #define sleep_reset() do { _SLEEP_CONTROL_REG = 0; } while(0) /* reset all sleep_mode() configurations. */ 95 | 96 | #define portSTACK_GROWTH ( -1 ) 97 | #define portBYTE_ALIGNMENT 1 98 | #define portNOP() __asm__ __volatile__ ( "nop" ); 99 | /*-----------------------------------------------------------*/ 100 | 101 | /* Kernel utilities. */ 102 | 103 | extern void vPortDelay( const uint32_t ms ); 104 | #define portDELAY( ms ) vPortDelay( ms ) 105 | 106 | extern void vPortYield( void ) __attribute__( ( naked ) ); 107 | #define portYIELD() vPortYield() 108 | 109 | extern void vPortYieldFromISR( void ) __attribute__( ( naked ) ); 110 | #define portYIELD_FROM_ISR() vPortYieldFromISR() 111 | /*-----------------------------------------------------------*/ 112 | 113 | #if defined( __AVR_3_BYTE_PC__ ) 114 | /* Task function macros as described on the FreeRTOS.org WEB site. */ 115 | 116 | /* Add .lowtext tag from the avr linker script avr6.x for ATmega2560 and ATmega2561 117 | * to make sure functions are loaded in low memory. 118 | */ 119 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( section( ".lowtext" ) ) ) 120 | #else 121 | #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) 122 | #endif 123 | 124 | #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) 125 | 126 | /* *INDENT-OFF* */ 127 | #ifdef __cplusplus 128 | } 129 | #endif 130 | /* *INDENT-ON* */ 131 | 132 | #endif /* PORTMACRO_H */ 133 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/variantHooks.cpp: -------------------------------------------------------------------------------- 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 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | 35 | /* FreeRTOS includes. */ 36 | #include "Arduino_FreeRTOS.h" 37 | #include "task.h" 38 | #include "timers.h" 39 | 40 | extern void setup(void); 41 | extern void loop(void); 42 | 43 | /*-----------------------------------------------------------*/ 44 | 45 | void initVariant(void) __attribute__ ((OS_main)); 46 | 47 | void initVariant(void) 48 | { 49 | // As the Task stacks are on heap before Task allocated heap variables, 50 | // the library default __malloc_heap_end = 0 doesn't work. 51 | __malloc_heap_end = (char *)(RAMEND - __malloc_margin); 52 | 53 | #if defined(USBCON) 54 | USBDevice.attach(); 55 | #endif 56 | 57 | setup(); // the normal Arduino setup() function is run here. 58 | vTaskStartScheduler(); // initialise and run the freeRTOS scheduler. Execution should never return here. 59 | } 60 | 61 | 62 | /*-----------------------------------------------------------*/ 63 | #if ( configUSE_IDLE_HOOK == 1 ) 64 | /* 65 | * Call the user defined loop() function from within the idle task. 66 | * This allows the application designer to add background functionality 67 | * without the overhead of a separate task. 68 | * 69 | * NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES, CALL A FUNCTION THAT MIGHT BLOCK. 70 | * 71 | */ 72 | void vApplicationIdleHook( void ) __attribute__ ((weak)); 73 | 74 | void vApplicationIdleHook( void ) 75 | { 76 | loop(); // the normal Arduino loop() function is run here. 77 | if (serialEventRun) serialEventRun(); 78 | } 79 | 80 | #else 81 | void loop() {} //Empty loop function 82 | #endif /* configUSE_IDLE_HOOK == 1 */ 83 | /*-----------------------------------------------------------*/ 84 | 85 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 || configCHECK_FOR_STACK_OVERFLOW >= 1 || configDEFAULT_ASSERT == 1 ) 86 | 87 | /** 88 | * Private function to enable board led to use it in application hooks 89 | */ 90 | void prvSetMainLedOn( void ) 91 | { 92 | 93 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Arduino Mega with 2560 94 | DDRB |= _BV(DDB7); 95 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 96 | 97 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 98 | DDRB |= _BV(DDB7); 99 | PORTB |= _BV(PORTB7); // Main (red PB7) LED on. Main LED on. 100 | 101 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 102 | DDRB |= _BV(DDB5); 103 | PORTB |= _BV(PORTB5); // Main (red PB5) LED on. Main LED on. 104 | 105 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 106 | DDRC |= _BV(DDC7); 107 | PORTC |= _BV(PORTC7); // Main (red PC7) LED on. Main LED on. 108 | 109 | #endif 110 | 111 | } 112 | 113 | /** 114 | * Private function to blink board led to use it in application hooks 115 | */ 116 | void prvBlinkMainLed( void ) 117 | { 118 | 119 | #if defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) // Mega with 2560 120 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. 121 | 122 | #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284PA__) // Seeed Goldilocks with 1284p 123 | PINB |= _BV(PINB7); // Main (red PB7) LED toggle. 124 | 125 | #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) // assume we're using an Arduino Uno with 328p 126 | PINB |= _BV(PINB5); // Main (red PB5) LED toggle. 127 | 128 | #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) // assume we're using an Arduino Leonardo with 32u4 129 | PINC |= _BV(PINC7); // Main (red PC7) LED toggle. 130 | 131 | #endif 132 | 133 | } 134 | 135 | #endif 136 | 137 | #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 138 | /*---------------------------------------------------------------------------*\ 139 | Usage: 140 | called by task system when a malloc failure is noticed 141 | Description: 142 | Malloc failure handler -- Shut down all interrupts, send serious complaint 143 | to command port. FAST Blink on main LED. 144 | Arguments: 145 | pxTask - pointer to task handle 146 | pcTaskName - pointer to task name 147 | Results: 148 | 149 | Notes: 150 | This routine will never return. 151 | This routine is referenced in the task.c file of FreeRTOS as an extern. 152 | \*---------------------------------------------------------------------------*/ 153 | void vApplicationMallocFailedHook( void ) __attribute__ ((weak)); 154 | 155 | void vApplicationMallocFailedHook( void ) 156 | { 157 | prvSetMainLedOn(); // Main LED on. 158 | 159 | for(;;) 160 | { 161 | _delay_ms(50); 162 | prvBlinkMainLed(); // Main LED fast blink. 163 | } 164 | } 165 | 166 | #endif /* configUSE_MALLOC_FAILED_HOOK == 1 */ 167 | /*-----------------------------------------------------------*/ 168 | 169 | 170 | #if ( configCHECK_FOR_STACK_OVERFLOW >= 1 ) 171 | 172 | void vApplicationStackOverflowHook( TaskHandle_t xTask, 173 | char * pcTaskName ) __attribute__ ((weak)); 174 | 175 | void vApplicationStackOverflowHook( TaskHandle_t xTask __attribute__ ((unused)), 176 | char * pcTaskName __attribute__ ((unused)) ) 177 | { 178 | 179 | prvSetMainLedOn(); // Main LED on. 180 | 181 | for(;;) 182 | { 183 | _delay_ms(2000); 184 | prvBlinkMainLed(); // Main LED slow blink. 185 | } 186 | } 187 | 188 | #endif /* configCHECK_FOR_STACK_OVERFLOW >= 1 */ 189 | /*-----------------------------------------------------------*/ 190 | 191 | #if ( configSUPPORT_STATIC_ALLOCATION >= 1 ) 192 | 193 | void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 194 | StackType_t ** ppxIdleTaskStackBuffer, 195 | configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ) __attribute__ ((weak)); 196 | 197 | void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, 198 | StackType_t ** ppxIdleTaskStackBuffer, 199 | configSTACK_DEPTH_TYPE * puxIdleTaskStackSize ) 200 | { 201 | static StaticTask_t xIdleTaskTCB; 202 | static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; 203 | 204 | *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; 205 | *ppxIdleTaskStackBuffer = uxIdleTaskStack; 206 | *puxIdleTaskStackSize = configMINIMAL_STACK_SIZE; 207 | } 208 | 209 | #if ( configUSE_TIMERS >= 1 ) 210 | 211 | void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, 212 | StackType_t ** ppxTimerTaskStackBuffer, 213 | configSTACK_DEPTH_TYPE * puxTimerTaskStackSize ) __attribute__ ((weak)); 214 | 215 | void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, 216 | StackType_t ** ppxTimerTaskStackBuffer, 217 | configSTACK_DEPTH_TYPE * puxTimerTaskStackSize ) 218 | { 219 | static StaticTask_t xTimerTaskTCB; 220 | static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; 221 | 222 | *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; 223 | *ppxTimerTaskStackBuffer = uxTimerTaskStack; 224 | *puxTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; 225 | } 226 | 227 | #endif /* configUSE_TIMERS >= 1 */ 228 | 229 | #endif /* configSUPPORT_STATIC_ALLOCATION >= 1 */ 230 | 231 | /** 232 | * configASSERT default implementation 233 | */ 234 | #if configDEFAULT_ASSERT == 1 235 | 236 | void vApplicationAssertHook() { 237 | 238 | taskDISABLE_INTERRUPTS(); // Disable task interrupts 239 | 240 | prvSetMainLedOn(); // Main LED on. 241 | for(;;) 242 | { 243 | _delay_ms(100); 244 | prvBlinkMainLed(); // Led off. 245 | 246 | _delay_ms(2000); 247 | prvBlinkMainLed(); // Led on. 248 | 249 | _delay_ms(100); 250 | prvBlinkMainLed(); // Led off 251 | 252 | _delay_ms(100); 253 | prvBlinkMainLed(); // Led on. 254 | } 255 | } 256 | #endif 257 | --------------------------------------------------------------------------------