diff --git a/.github/workflows/HeliOS_CI_Workflow.yml b/.github/workflows/HeliOS_CI_Workflow.yml index e1c0092..77888db 100644 --- a/.github/workflows/HeliOS_CI_Workflow.yml +++ b/.github/workflows/HeliOS_CI_Workflow.yml @@ -3,14 +3,14 @@ name: HeliOS CI Workflow on: push: - branches: [ master, develop ] + branches: [ develop ] pull_request: - branches: [ master, develop ] + branches: [ develop ] workflow_dispatch: jobs: - build-test: + build-test-doc: runs-on: ubuntu-22.04 steps: @@ -19,8 +19,125 @@ jobs: - name: Build HeliOS unit tests... shell: bash - run: gcc -fdiagnostics-color=always -O0 -ggdb -std=c89 -Wall -Wextra -I ${{github.workspace}}/src -DPOSIX_ARCH_OTHER -DCONFIG_MEMORY_REGION_SIZE_IN_BLOCKS=0x1C20u -DCONFIG_ENABLE_SYSTEM_ASSERT -o ${{github.workspace}}/extras/test/bin/test ${{github.workspace}}/src/*.c ${{github.workspace}}/extras/test/src/test.c + run: gcc -fdiagnostics-color=always -O0 -ggdb -ansi -pedantic -Wall -Wextra -Wno-unused-parameter -I${{github.workspace}}/src -I${{github.workspace}}/test/src -I${{github.workspace}}/test/src/harness -I${{github.workspace}}/test/src/unit -DPOSIX_ARCH_OTHER -DCONFIG_MEMORY_REGION_SIZE_IN_BLOCKS=0x1C20u -DCONFIG_ENABLE_SYSTEM_ASSERT -o${{github.workspace}}/test/bin/test ${{github.workspace}}/src/*.c ${{github.workspace}}/test/src/*.c ${{github.workspace}}/test/src/harness/*.c ${{github.workspace}}/test/src/unit/*.c - name: Run HeliOS unit tests... shell: bash - run: ${{github.workspace}}/extras/test/bin/test \ No newline at end of file + run: ${{github.workspace}}/test/bin/test + + - name: Install Cppcheck... + shell: bash + run: | + sudo apt update + sudo apt -y install cppcheck + + - name: Run Cppcheck... + shell: bash + run: | + cppcheck --quiet --language=c --platform=unix64 --max-ctu-depth=8 --cppcheck-build-dir=${{github.workspace}}/build --template="::{severity} file={file},line={line},col={column}::{message}" --enable=all --std=c89 -DPOSIX_ARCH_OTHER ${{github.workspace}}/src/ + + - name: Install Doxygen and LaTeX... + shell: bash + run: | + sudo apt update + sudo apt -y install doxygen-latex + + - name: Create Doxygen config... + shell: bash + run: | + mkdir ${{github.workspace}}/temp + doxygen -g ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^$/d' ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^#.*/d' ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^ .*/d' ${{github.workspace}}/temp/HeliOS.conf + sed -i 's/ \+/ /g' ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^PROJECT_NAME .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'PROJECT_NAME = HeliOS' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^PROJECT_NUMBER .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'PROJECT_NUMBER = Kernel 0.3.5' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^PROJECT_LOGO .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'PROJECT_LOGO = ${{github.workspace}}/temp/HeliOS_OG_Logo.png' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^OUTPUT_DIRECTORY .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'OUTPUT_DIRECTORY = ${{github.workspace}}/temp' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^OPTIMIZE_OUTPUT_FOR_C .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'OPTIMIZE_OUTPUT_FOR_C = YES' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^GENERATE_HTML .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'GENERATE_HTML = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^GENERATE_LATEX .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'GENERATE_LATEX = YES' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^COMPACT_LATEX .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'COMPACT_LATEX = YES' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^GENERATE_RTF .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'GENERATE_RTF = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^GENERATE_MAN .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'GENERATE_MAN = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^GENERATE_XML .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'GENERATE_XML = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^REPEAT_BRIEF .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'REPEAT_BRIEF = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^FULL_PATH_NAMES .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'FULL_PATH_NAMES = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^INPUT .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'INPUT = ${{github.workspace}}/src/config.h ${{github.workspace}}/src/HeliOS.h' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^FILE_PATTERNS .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'FILE_PATTERNS = *.h' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^RECURSIVE .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'RECURSIVE = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^CLASS_DIAGRAMS .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'CLASS_DIAGRAMS = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^HAVE_DOT .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'HAVE_DOT = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^PROJECT_BRIEF .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'PROJECT_BRIEF = ' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^SHOW_HEADERFILE .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'SHOW_HEADERFILE = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^SHOW_INCLUDE_FILES .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'SHOW_INCLUDE_FILES = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^QUIET .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'QUIET = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^WARNINGS .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'WARNINGS = YES' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^WARN_LOGFILE .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'WARN_LOGFILE = ' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^INLINE_SOURCES .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'INLINE_SOURCES = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^VERBATIM_HEADERS .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'VERBATIM_HEADERS = NO' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^ENABLE_PREPROCESSING .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'ENABLE_PREPROCESSING = YES' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^DEFINED .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'DEFINED = DOXYGEN_SHOULD_SKIP_THIS' >> ${{github.workspace}}/temp/HeliOS.conf + sed -i '/^ABBREVIATE_BRIEF .*/d' ${{github.workspace}}/temp/HeliOS.conf + echo 'ABBREVIATE_BRIEF = ' >> ${{github.workspace}}/temp/HeliOS.conf + sort -o ${{github.workspace}}/temp/HeliOS.conf ${{github.workspace}}/temp/HeliOS.conf + cat ${{github.workspace}}/temp/HeliOS.conf + + - name: Resize HeliOS logo... + shell: bash + run: | + convert -resize 300 ${{github.workspace}}/extras/HeliOS_OG_Logo.png ${{github.workspace}}/temp/HeliOS_OG_Logo.png + + - name: Generate LaTeX... + shell: bash + run: | + doxygen ${{github.workspace}}/temp/HeliOS.conf + sed -i 's~^\\begin{center}\%~\\begin{center}\%\n\\includegraphics{HeliOS_OG_Logo.png}\\\\\n\\vspace*{1cm}~' ${{github.workspace}}/temp/latex/refman.tex + sed -i 's~Generated by Doxygen [0123456789]*.[0123456789]*.[0123456789]*~HeliOS Developer\x27s Guide~' ${{github.workspace}}/temp/latex/refman.tex + sed -i 's~Generated by Doxygen~(C)Copyright 2022 Manny Peterson~' ${{github.workspace}}/temp/latex/refman.tex + + - name: Generate PDF from LaTeX... + shell: bash + run: | + cd ${{github.workspace}}/temp/latex + make + cd ${{github.workspace}} + + - name: Push PDF to repository... + shell: bash + run: | + cp ${{github.workspace}}/temp/latex/refman.pdf ${{github.workspace}}/doc/HeliOS_Developers_Guide.pdf + git config --global user.name 'Manny Peterson' + git config --global user.email '12462046+MannyPeterson@users.noreply.github.com' + git add ${{github.workspace}}/doc/HeliOS_Developers_Guide.pdf + git commit -m "HeliOS CI Workflow" + git push \ No newline at end of file diff --git a/.gitignore b/.gitignore index fc5ebef..7bfc127 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ /.vscode/** -/extras/test/bin/** +/test/bin/** !.gitignore !.gitattributes !/.vscode/settings.json !/.vscode/tasks.json !/.vscode/launch.json -!/extras/test/bin/.gitkeep \ No newline at end of file +!/test/bin/.gitkeep \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 7f2a3fe..57d10af 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,9 +5,9 @@ "name": "HeliOS Unit Test (debug/gdb)", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/extras/test/bin/test", + "program": "${workspaceFolder}/test/bin/test", "args": [], - "cwd": "${workspaceFolder}/extras/test/bin", + "cwd": "${workspaceFolder}/test/bin", "environment": [], "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", diff --git a/.vscode/settings.json b/.vscode/settings.json index 3d15789..3c6f1d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,7 +13,7 @@ "doxdocgen.file.copyrightTag": [ "@copyright", "HeliOS Embedded Operating System", - "Copyright (C) 2020-2022 Manny Peterson ", + "Copyright (C) 2020-2023 Manny Peterson ", " ", "This program is free software: you can redistribute it and/or modify", "it under the terms of the GNU General Public License as published by", @@ -41,7 +41,7 @@ "custom" ], "doxdocgen.file.fileTemplate": "@file {name}", - "doxdocgen.file.versionTag": "@version 0.3.4", + "doxdocgen.file.versionTag": "@version 0.3.5", "doxdocgen.generic.authorEmail": "mannymsp@gmail.com", "doxdocgen.generic.authorName": "Manny Peterson", "doxdocgen.generic.authorTag": "@author {author} ({email})", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index afc7480..56df7f2 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,18 +8,23 @@ "-fdiagnostics-color=always", "-O0", "-ggdb", - "-std=c89", + "-ansi", + "-pedantic", "-Wall", "-Wextra", - "-I", - "${workspaceFolder}/src", + "-Wno-unused-parameter", + "-I${workspaceFolder}/src", + "-I${workspaceFolder}/test/src", + "-I${workspaceFolder}/test/src/harness", + "-I${workspaceFolder}/test/src/unit", "-DPOSIX_ARCH_OTHER", "-DCONFIG_MEMORY_REGION_SIZE_IN_BLOCKS=0x1C20u", "-DCONFIG_ENABLE_SYSTEM_ASSERT", - "-o", - "${workspaceFolder}/extras/test/bin/test", + "-o${workspaceFolder}/test/bin/test", "${workspaceFolder}/src/*.c", - "${workspaceFolder}/extras/test/src/test.c" + "${workspaceFolder}/test/src/*.c", + "${workspaceFolder}/test/src/harness/*.c", + "${workspaceFolder}/test/src/unit/*.c" ], "options": { "cwd": "${workspaceFolder}/src" @@ -31,6 +36,15 @@ "kind": "build", "isDefault": true } + }, + { + "type": "shell", + "label": "HeliOS Uncrustify", + "command": "find . \\( -name \"*.c\" -o -name \"*.h\" \\) -exec uncrustify -c extras/uncrustify/helios.cfg -lC --no-backup {} +", + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] } ], "version": "2.0.0" diff --git a/README.md b/README.md index c645199..19fc360 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://github.com/MannyPeterson/HeliOS/blob/master/LICENSE.md) ![GitHub last commit](https://img.shields.io/github/last-commit/MannyPeterson/HeliOS) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/MannyPeterson/HeliOS) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/mannypeterson/library/HeliOS.svg)](https://registry.platformio.org/libraries/mannypeterson/HeliOS) [![arduino-library-badge](https://www.ardu-badge.com/badge/HeliOS.svg?)](https://www.ardu-badge.com/HeliOS) ![GitHub stars](https://img.shields.io/github/stars/MannyPeterson/HeliOS?style=social) ![GitHub watchers](https://img.shields.io/github/watchers/MannyPeterson/HeliOS?style=social) *** # Overview -HeliOS is an embedded operating system that is free for everyone to use. While called an operating system, HeliOS is a multitasking kernel for use in embedded applications. Its rich, fully documented, API allows the user to control every aspect of the system and access kernel services for task (process) management, scheduler management, inter-process communication, memory management and more while maintaining a tiny footprint for a broad range of low-power embedded devices. HeliOS is also easily customized to fit the user’s specific needs through a single header file ([config.h](/src/config.h)). +HeliOS is an embedded operating system that is free for everyone to use. While called an operating system, HeliOS is a multitasking kernel for use in embedded applications. Its rich, fully documented, API allows the user to control every aspect of the system and access kernel services for task (process) management, scheduler management, inter-process communication, memory management, device management (i.e., device drivers) and more while maintaining a tiny footprint for a broad range of low-power embedded devices. HeliOS is also easily customized to fit the user’s specific needs through a single header file ([config.h](/src/config.h)). HeliOS supports two multitasking models that can be leveraged concurrently within the same application. The first multitasking model is event-driven. When a task is placed in the "waiting" state, the task will only respond to task events. HeliOS supports two types of task events. The first is direct-to-task notifications, which allow one task to send a notification to another task. In this scenario, the HeliOS scheduler will wake the recipient task and schedule it for execution. After the recipient task clears the direct-to-task notification, the recipient task will return to sleep until another notification is received. The second type of task event is timer based. Task timers can be configured to tell HeliOS to schedule the task to run every so many ticks (typically milliseconds), though task timers should not be confused with application timers (or simply timers) as HeliOS supports both. @@ -11,10 +11,12 @@ The second model for multitasking is a conventional cooperative model. In this m One important aspect of multitasking in HeliOS is it does not rely on context switching. This reduces the need for the user to manage access to shared resources in a “thread safe” way using mutexes and semaphores. This also eliminates the need for the “port” or portability code required to save the context during a context switch. As a result, the user can focus his or her development effort on their specific application without having to contend with concurrent access to shared resources. -HeliOS also provides services for two inter-process communication models. The first, as discussed previously, is direct-to-task notifications. Direct-to-task notifications are an efficient communication channel between tasks that prevent a task from consuming runtime when there is nothing for the task to process. The second model is message queues. Message queues can be created at runtime and can be shared among any number of tasks. Queues are highly flexible FIFO communication channels that require very little code to implement. Finally, while technically not one of HeliOS’s models for inter-process communication, HeliOS supports task parameters that can be leveraged for rudimentary inter-process communication if so desired. +HeliOS also provides services for three inter-process communication models. The first, as discussed previously, is direct-to-task notifications. Direct-to-task notifications are an efficient communication channel between tasks that prevent a task from consuming runtime when there is nothing for the task to process. The second model is message queues. Message queues can be created at runtime and can be shared among any number of tasks. Queues are highly flexible FIFO communication channels that require very little code to implement. The third model is stream buffers. Stream buffers are very much like message queues with one important difference. While queues operate on multi-byte messages, stream buffers operate similarly on single-byte streams. Finally, while technically not one of HeliOS’s models for inter-process communication, HeliOS supports task parameters that can be leveraged for rudimentary inter-process communication if so desired. The HeliOS kernel includes built-in memory management that improves the safety margin of dynamically allocated memory. While HeliOS’s dynamic memory allocation allocates “heap” memory, the heap in HeliOS is not a true heap. HeliOS uses a private heap that is implemented as static memory allocated at compile time. HeliOS does not use the standard library malloc() and free() functions and it is recommended that the user also avoid those functions in favor of HeliOS’s memory management system calls. HeliOS also maintains a separate memory region for kernel objects which reduces the risk that memory access, in the user's application, would corrupt critical kernel objects. +HeliOS also supports a kernel mode device driver model. Device drivers for virtually any feature or peripheral can be easily developed using the provided device driver template. While device drivers are not needed in most applications, when the MCU's MMU or MPU is enabled it may not be possible to access memory mapped registers and I/O from the user's code. While implementation of the ARM MMU and MPU in HeliOS is forthcoming, device driver support had to be added to HeliOS first. Information about the device driver system calls can be found in the [HeliOS Developer's Guide](/doc/HeliOS_Developers_Guide.pdf). A device driver template can be found here: [driver.c](/extras/drivers/template/driver.c) and [driver.h](/extras/drivers/template/driver.h). + HeliOS is built to be robust. HeliOS (0.3.0 and later) has undergone static analysis testing using a commercially licensed static analysis tool as well as MISRA C:2012 checks. While HeliOS is NOT certified for nor should be used (in full or in part) in any safety-critical application where a risk to life exists, user’s can be confident they are building their embedded application on a robust embedded operating system. Lastly, for PlatformIO and Arduino users, HeliOS is easily added to their embedded application. The current release of HeliOS is available directly through the [PlatformIO Registry](https://registry.platformio.org/libraries/mannypeterson/HeliOS) and the [Arduino Library Manager](https://www.arduino.cc/reference/en/libraries/helios/). For users of other embedded platforms and/or tool-chains, simply download the current [release](https://github.com/MannyPeterson/HeliOS/releases) of HeliOS from GitHub and add the sources to your project. @@ -67,7 +69,7 @@ void loop() { } ``` ## HeliOS "Blink" Example -Below is the Arduino "Blink" example code implemented using HeliOS. In this example, a HeliOS task, which alternates the microcontroller's GPIO pin state between high and low, is added in a "wait" state and a timer is set instructing HeliOS's scheduler to execute the task every 1,000,000 microseconds. +Below is the Arduino "Blink" example code implemented using HeliOS. In this example, a HeliOS task, which alternates the microcontroller's GPIO pin state between high and low, is added in a "wait" state and a timer is set instructing HeliOS's scheduler to execute the task every 1,000 ticks (milliseconds on many MCUs). ```C /* Include the HeliOS header, do not include @@ -152,7 +154,8 @@ void loop() { *** # Releases All releases, including the current release, can be found [here](https://github.com/MannyPeterson/HeliOS/releases). -* **0.3.4 - Corrected "blink" example in readme and in examples, fixed ESP8266 support, added queue locking and other improvements** +* 0.3.5 - Several new features including device drivers, stream buffers, task watchdog timer, improved memory defragmentation and many more including improvements to source code and documentation. +* 0.3.4 - Corrected "blink" example in readme and in examples, fixed ESP8266 support, added queue locking and other improvements * 0.3.3 - Multi-region memory support, memory defragmentation, CMSIS support, new portability layer and other code improvements * 0.3.2 - Some fixes to the memory management system calls and related functions * 0.3.1 - A lot of refactoring, code clean-up from the 0.3.0 release and code documentation/readability improvements @@ -169,7 +172,7 @@ All releases, including the current release, can be found [here](https://github. To contribute, create a pull request with your changes. Please fork from the **develop** branch only, as **master** is kept even with the current release. If you would like to make a recommendation or are in need of support, please open an issue. If you are seeking support, please include your source code, details about your particular platform and/or tool-chain and a detailed description of the issue you are facing. All pull requests and issues are responded to as quickly as possible. *** # Copyright & License -HeliOS Embedded Operating System Copyright (C) 2020-2022 Manny Peterson +HeliOS Embedded Operating System Copyright (C) 2020-2023 Manny Peterson HeliOS is copyrighted open source software licensed under the Free Software Foundation's GNU General Public License (GPL) Version 3. The full license text can be found [here](/LICENSE.md). *** @@ -177,5 +180,5 @@ HeliOS is copyrighted open source software licensed under the Free Software Foun HeliOS is **not** certified for use in safety-critical applications. The HeliOS source code, whether in full or in part, must **never** be used in applications where a risk to life exists. In other words, do not use HeliOS in your project if there is even a remote chance someone might get hurt. *** # Other Notice -This project is not affiliated in any way, past or present, with the Unix-like operating system HeliOS developed by Tim King of Perihelion Ltd. or Axel Muhr's work on [Helios-NG](https://github.com/axelmuhr/Helios-NG). Any resemblance is strictly coincidental. +This project is not affiliated in any way, past or present, with the discontinued Unix-like operating system Helios developed by Dr. Tim King of Perihelion Software Ltd. or Axel Muhr's work on [Helios-NG](https://github.com/axelmuhr/Helios-NG). Any resemblance is purely coincidental. *** \ No newline at end of file diff --git a/doc/HeliOS_Developers_Guide.pdf b/doc/HeliOS_Developers_Guide.pdf index 1d050b0..b63ffdb 100644 Binary files a/doc/HeliOS_Developers_Guide.pdf and b/doc/HeliOS_Developers_Guide.pdf differ diff --git a/examples/Blink/Blink.ino b/examples/Blink/Blink.ino index a494ffd..6e55c28 100644 --- a/examples/Blink/Blink.ino +++ b/examples/Blink/Blink.ino @@ -2,12 +2,12 @@ * @file Blink.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Blink example code for Arduino - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/Coop/Coop.ino b/examples/Coop/Coop.ino index afea15f..df5e29a 100644 --- a/examples/Coop/Coop.ino +++ b/examples/Coop/Coop.ino @@ -2,12 +2,12 @@ * @file Coop.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code for cooperative multitasking - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/GetInfo/GetInfo.ino b/examples/GetInfo/GetInfo.ino index 52f7c85..df887f6 100644 --- a/examples/GetInfo/GetInfo.ino +++ b/examples/GetInfo/GetInfo.ino @@ -2,12 +2,12 @@ * @file GetInfo.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code for getting task and system information - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/ListTasks/ListTasks.ino b/examples/ListTasks/ListTasks.ino index 0b0df86..6c8373a 100644 --- a/examples/ListTasks/ListTasks.ino +++ b/examples/ListTasks/ListTasks.ino @@ -2,12 +2,12 @@ * @file ListTasks.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code to print runtime statistics for all tasks - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/Mem/Mem.ino b/examples/Mem/Mem.ino index b8b9fa1..e8dc9b1 100644 --- a/examples/Mem/Mem.ino +++ b/examples/Mem/Mem.ino @@ -2,12 +2,12 @@ * @file Mem.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code to demonstrate how heap memory is managed in HeliOS - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/Timer/Timer.ino b/examples/Timer/Timer.ino index 444a7ce..fc55c8a 100644 --- a/examples/Timer/Timer.ino +++ b/examples/Timer/Timer.ino @@ -2,12 +2,12 @@ * @file Timer.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code to demonstrate event driven multitasking using a task timer - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/WaitNotify/WaitNotify.ino b/examples/WaitNotify/WaitNotify.ino index db7c41c..060164e 100644 --- a/examples/WaitNotify/WaitNotify.ino +++ b/examples/WaitNotify/WaitNotify.ino @@ -2,12 +2,12 @@ * @file WaitNotify.ino * @author Manny Peterson (mannymsp@gmail.com) * @brief Example code to demonstrate direct-to-task notifications used in event-driven multitasking - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-14 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/extras/arduino.cpp b/extras/arduino.cpp index 33ee605..580ce62 100644 --- a/extras/arduino.cpp +++ b/extras/arduino.cpp @@ -2,12 +2,12 @@ * @file arduino.cpp * @author Manny Peterson (mannymsp@gmail.com) * @brief Source code to allow the HeliOS kernel to interface with the C++ Arduino API. - * @version 0.3.4 + * @version 0.3.5 * @date 2022-02-25 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,13 +34,13 @@ #include -extern "C" void _ArduinoAssert_(const char *file_, int line_); +extern "C" void __ArduinoAssert__(const char *file_, int line_); -void _ArduinoAssert_(const char *file_, int line_) +void __ArduinoAssert__(const char *file_, int line_) { - Serial.println("assert: " + String(file_) + ":" + String(line_, DEC)); + Serial.println("kernel: assert at " + String(file_) + ":" + String(line_, DEC)); return; } diff --git a/extras/drivers/loopback/loopback.c b/extras/drivers/loopback/loopback.c new file mode 100644 index 0000000..64168da --- /dev/null +++ b/extras/drivers/loopback/loopback.c @@ -0,0 +1,115 @@ +/** + * @file loopback.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief The HeliOS loopback device driver + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "loopback.h" + +#define BUFFER_LENGTH 0xFFu +static Char_t loopback_buffer[BUFFER_LENGTH]; +static HalfWord_t loopback_buffer_size = zero; + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void) { + + /* DO NOT MODIFY THIS FUNCTION */ + + return __RegisterDevice__(DEVICE_UID, (Char_t *)TO_LITERAL(DEVICE_NAME), DEVICE_STATE, DEVICE_MODE, TO_FUNCTION(DEVICE_NAME, _init), + TO_FUNCTION(DEVICE_NAME, _config), TO_FUNCTION(DEVICE_NAME, _read), TO_FUNCTION(DEVICE_NAME, _write), + TO_FUNCTION(DEVICE_NAME, _simple_read), TO_FUNCTION(DEVICE_NAME, _simple_write)); +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_) { + Base_t ret = RETURN_SUCCESS; + + __memset__(loopback_buffer, zero, BUFFER_LENGTH); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO CONFIGURE DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_SUCCESS; + + *size_ = loopback_buffer_size; + + __memcpy__(data_, loopback_buffer, *size_); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_SUCCESS; + + loopback_buffer_size = *size_; + + __memcpy__(loopback_buffer, data_, *size_); + + device_->available = true; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_SUCCESS; + + __memcpy__(data_, loopback_buffer, sizeof(Word_t)); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_SUCCESS; + + __memcpy__(loopback_buffer, data_, sizeof(Word_t)); + + + device_->available = true; + + return ret; +} \ No newline at end of file diff --git a/extras/drivers/loopback/loopback.h b/extras/drivers/loopback/loopback.h new file mode 100644 index 0000000..610f7b6 --- /dev/null +++ b/extras/drivers/loopback/loopback.h @@ -0,0 +1,74 @@ +/** + * @file loopback.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief The HeliOS loopback device driver + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOOPBACK_H_ +#define LOOPBACK_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +/* START: DEVICE DRIVER PARAMATER BLOCK + + IMPORTANT: THE DEVICE NAME MUST BE SUPPLIED HERE AND MUST BE EXACTLY + CONFIG_DEVICE_NAME_BYTES (DEFAULT IS 8) IN LENGTH, IT MAY BE NECESSARY + TO PAD SHORTER DEVICE NAMES. */ +#define DEVICE_NAME LOOPBACK +#define DEVICE_UID 0xFFu +#define DEVICE_MODE DeviceModeReadWrite +#define DEVICE_STATE DeviceStateRunning +/* END: DEVICE DRIVER PARAMATER BLOCK */ + + + +#define CONCAT(a, b) a ## b +#define QUOTE(a) #a +#define TO_FUNCTION(a, b) CONCAT(a, b) +#define TO_LITERAL(a) QUOTE(a) + +#ifdef __cplusplus +extern "C" { +#endif + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void); +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_); +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_); +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/extras/drivers/template/driver.c b/extras/drivers/template/driver.c new file mode 100644 index 0000000..c6c07cf --- /dev/null +++ b/extras/drivers/template/driver.c @@ -0,0 +1,98 @@ +/** + * @file driver.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief A template for HeliOS device drivers + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "driver.h" + + + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void) { + + /* DO NOT MODIFY THIS FUNCTION */ + + return __RegisterDevice__(DEVICE_UID, (Char_t *)TO_LITERAL(DEVICE_NAME), DEVICE_STATE, DEVICE_MODE, TO_FUNCTION(DEVICE_NAME, _init), + TO_FUNCTION(DEVICE_NAME, _config), TO_FUNCTION(DEVICE_NAME, _read), TO_FUNCTION(DEVICE_NAME, _write), + TO_FUNCTION(DEVICE_NAME, _simple_read), TO_FUNCTION(DEVICE_NAME, _simple_write)); +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO INITIALIZE DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO CONFIGURE DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO READ FROM DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO WRITE TO DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO READ FROM DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO WRITE TO DEVICE HERE */ + + return ret; +} \ No newline at end of file diff --git a/extras/drivers/template/driver.h b/extras/drivers/template/driver.h new file mode 100644 index 0000000..6f503cd --- /dev/null +++ b/extras/drivers/template/driver.h @@ -0,0 +1,74 @@ +/** + * @file driver.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief A template for HeliOS device drivers + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef DRIVER_H_ +#define DRIVER_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +/* START: DEVICE DRIVER PARAMATER BLOCK + + IMPORTANT: THE DEVICE NAME MUST BE SUPPLIED HERE AND MUST BE EXACTLY + CONFIG_DEVICE_NAME_BYTES (DEFAULT IS 8) IN LENGTH, IT MAY BE NECESSARY + TO PAD SHORTER DEVICE NAMES. */ +#define DEVICE_NAME NAMEHERE +#define DEVICE_UID 0x1u +#define DEVICE_MODE DeviceModeReadWrite +#define DEVICE_STATE DeviceStateRunning +/* END: DEVICE DRIVER PARAMATER BLOCK */ + + + +#define CONCAT(a, b) a ## b +#define QUOTE(a) #a +#define TO_FUNCTION(a, b) CONCAT(a, b) +#define TO_LITERAL(a) QUOTE(a) + +#ifdef __cplusplus +extern "C" { +#endif + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void); +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_); +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_); +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/extras/test/src/test.c b/extras/test/src/test.c deleted file mode 100644 index e1d8a53..0000000 --- a/extras/test/src/test.c +++ /dev/null @@ -1,309 +0,0 @@ -/** - * @file test.c - * @author Manny Peterson (mannymsp@gmail.com) - * @brief Source code for unit testing - * @version 0.3.4 - * @date 2022-08-19 - * - * @copyright - * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include - -#include - -#include - -int memcmp(const void *s1_, const void *s2_, size_t n_); -void task_main(xTask task_, xTaskParm parm_); - -int main(int argc, char **argv) { - - xBase ret = zero; - - /* BEGIN: MEMORY UNIT TESTS */ - - xBase *mem01 = NULL; - - mem01 = (xBase *)xMemAlloc(0x32000u); - if (ISNULLPTR(mem01)) { - ret++; - } - - if (0x32020u != xMemGetUsed()) { - ret++; - } - - if (0x32020u != xMemGetSize(mem01)) { - ret++; - } - - xMemoryRegionStats mem02 = NULL; - xMemoryRegionStats mem03 = NULL; - - mem02 = xMemGetHeapStats(); - if (ISNULLPTR(mem02)) { - ret++; - } - - if (0x63A0u != mem02->availableSpaceInBytes) { - ret++; - } - - if (0x63A0u != mem02->largestFreeEntryInBytes) { - ret++; - } - - if (0x63A0u != mem02->minimumEverFreeBytesRemaining) { - ret++; - } - - if (0x31Du != mem02->numberOfFreeBlocks) { - ret++; - } - - if (0x63A0u != mem02->smallestFreeEntryInBytes) { - ret++; - } - - if (0x2u != mem02->successfulAllocations) { - ret++; - } - - if (0x0u != mem02->successfulFrees) { - ret++; - } - - xTask mem04 = NULL; - - mem04 = xTaskCreate("NONE", task_main, NULL); - xTaskDelete(mem04); - - mem03 = xMemGetKernelStats(); - if (ISNULLPTR(mem03)) { - ret++; - } - - if (0x383C0u != mem03->availableSpaceInBytes) { - ret++; - } - - if (0x383C0u != mem03->largestFreeEntryInBytes) { - ret++; - } - - if (0x38340u != mem03->minimumEverFreeBytesRemaining) { - ret++; - } - - if (0x1C1Eu != mem03->numberOfFreeBlocks) { - ret++; - } - - if (0x383C0u != mem03->smallestFreeEntryInBytes) { - ret++; - } - - if (0x2u != mem03->successfulAllocations) { - ret++; - } - - if (0x1u != mem03->successfulFrees) { - ret++; - } - - xMemFree(mem01); - xMemFree(mem02); - xMemFree(mem03); - - /* END: MEMORY UNIT TESTS */ - - - /* BEGIN: QUEUE UNIT TESTS */ - - xQueue queue01 = NULL; - - queue01 = xQueueCreate(7); - if (ISNULLPTR(queue01)) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE1")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE2")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE3")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE4")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE5")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE6")) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE7")) { - ret++; - } - - if (0x7u != xQueueGetLength(queue01)) { - ret++; - } - - if (true == xQueueIsQueueEmpty(queue01)) { - ret++; - } - - if (false == xQueueIsQueueFull(queue01)) { - ret++; - } - - if (false == xQueueMessagesWaiting(queue01)) { - ret++; - } - - xQueueMessage queue02 = NULL; - - queue02 = xQueuePeek(queue01); - if (ISNULLPTR(queue02)) { - ret++; - } - - if (0x8u != queue02->messageBytes) { - ret++; - } - - if (0x0u != memcmp("MESSAGE1", queue02->messageValue, 8)) { - ret++; - } - - xMemFree(queue02); - - queue02 = xQueueReceive(queue01); - if (ISNULLPTR(queue02)) { - ret++; - } - - if (0x8u != queue02->messageBytes) { - ret++; - } - - if (0x0u != memcmp("MESSAGE1", queue02->messageValue, 8)) { - ret++; - } - - xMemFree(queue02); - - xQueueDropMessage(queue01); - - if (0x5u != xQueueGetLength(queue01)) { - ret++; - } - - xQueueDelete(queue01); - - queue01 = xQueueCreate(5); - if (ISNULLPTR(queue01)) { - ret++; - } - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE1")) { - ret++; - } - - xQueueLockQueue(queue01); - - if (RETURN_SUCCESS == xQueueSend(queue01, 8, "MESSAGE2")) { - ret++; - } - - xQueueUnLockQueue(queue01); - - if (RETURN_FAILURE == xQueueSend(queue01, 8, "MESSAGE3")) { - ret++; - } - - if (0x2u != xQueueGetLength(queue01)) { - ret++; - } - - xQueueDelete(queue01); - - if (RETURN_SUCCESS == xQueueSend(queue01, 8, "MESSAGE4")) { - ret++; - } - - /* END: QUEUE UNIT TESTS */ - - /* BEGIN: TASK UNIT TESTS */ - - - /* END: TASK UNIT TESTS */ - - SYSASSERT(zero == ret); - - return ret; -} - - - -void task_main(xTask task_, xTaskParm parm_) { - - return; -} - - - -int memcmp(const void *s1_, const void *s2_, size_t n_) { - - size_t i = zero; - - int ret = zero; - - char *s1 = (char *)s1_; - - char *s2 = (char *)s2_; - - for (i = zero; i < n_; i++) { - - if (*s1 != *s2) { - - ret = *s1 - *s2; - - break; - } - - s1++; - - s2++; - } - - - return ret; -} \ No newline at end of file diff --git a/extras/uncrustify/helios.cfg b/extras/uncrustify/helios.cfg new file mode 100644 index 0000000..af65b3f --- /dev/null +++ b/extras/uncrustify/helios.cfg @@ -0,0 +1,3564 @@ +# Uncrustify-0.75.1-dev + +# +# General options +# + +# The type of line endings. +# +# Default: auto +newlines = lf # lf/crlf/cr/auto + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 8 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 8 # unsigned number + +# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). +# +# Default: 92 +string_escape_char = 92 # unsigned number + +# Alternate string escape char (usually only used for Pawn). +# Only works right before the quote char. +string_escape_char2 = 0 # unsigned number + +# Replace tab characters found in string literals with the escape sequence \t +# instead. +string_replace_tab_chars = false # true/false + +# Allow interpreting '>=' and '>>=' as part of a template in code like +# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # true/false + +# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multi-line macros). +disable_processing_nl_cont = false # true/false + +# Specify the marker used in comments to disable processing of part of the +# file. +# +# Default: *INDENT-OFF* +disable_processing_cmt = " *INDENT-OFF*" # string + +# Specify the marker used in comments to (re)enable processing in a file. +# +# Default: *INDENT-ON* +enable_processing_cmt = " *INDENT-ON*" # string + +# Enable parsing of digraphs. +enable_digraphs = false # true/false + +# Option to allow both disable_processing_cmt and enable_processing_cmt +# strings, if specified, to be interpreted as ECMAScript regular expressions. +# If true, a regex search will be performed within comments according to the +# specified patterns in order to disable/enable processing. +processing_cmt_as_regex = false # true/false + +# Add or remove the UTF-8 BOM (recommend 'remove'). +utf8_bom = ignore # ignore/add/remove/force/not_defined + +# If the file contains bytes with values between 128 and 255, but is not +# UTF-8, then output as UTF-8. +utf8_byte = false # true/false + +# Force the output encoding to UTF-8. +utf8_force = false # true/false + +# +# Spacing options +# + +# Add or remove space around non-assignment symbolic operators ('+', '/', '%', +# '<<', and so forth). +sp_arith = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around arithmetic operators '+' and '-'. +# +# Overrides sp_arith. +sp_arith_additive = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around assignment operator '=', '+=', etc. +sp_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around '=' in C++11 lambda capture specifications. +# +# Overrides sp_assign. +sp_cpp_lambda_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the capture specification of a C++11 lambda when +# an argument list is present, as in '[] (int x){ ... }'. +sp_cpp_lambda_square_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the capture specification of a C++11 lambda with +# no argument list is present, as in '[] { ... }'. +sp_cpp_lambda_square_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the opening parenthesis and before the closing +# parenthesis of a argument list of a C++11 lambda, as in +# '[]( int x ){ ... }'. +sp_cpp_lambda_argument_list = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the argument list of a C++11 lambda, as in +# '[](int x) { ... }'. +sp_cpp_lambda_paren_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a lambda body and its call operator of an +# immediately invoked lambda, as in '[]( ... ){ ... } ( ... )'. +sp_cpp_lambda_fparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around assignment operator '=' in a prototype. +# +# If set to ignore, use sp_assign. +sp_assign_default = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_before_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after assignment operator '=', '+=', etc. +# +# Overrides sp_assign. +sp_after_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space in 'enum {'. +# +# Default: add +sp_enum_brace = add # ignore/add/remove/force/not_defined + +# Add or remove space in 'NS_ENUM ('. +sp_enum_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around assignment '=' in enum. +sp_enum_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_before_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after assignment '=' in enum. +# +# Overrides sp_enum_assign. +sp_enum_after_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around assignment ':' in enum. +sp_enum_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around preprocessor '##' concatenation operator. +# +# Default: add +sp_pp_concat = add # ignore/add/remove/force/not_defined + +# Add or remove space after preprocessor '#' stringify operator. +# Also affects the '#@' charizing operator. +sp_pp_stringify = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before preprocessor '#' stringify operator +# as in '#define x(y) L#y'. +sp_before_pp_stringify = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around compare operator '<', '>', '==', etc. +sp_compare = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '(' and ')'. +sp_inside_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. +sp_cparen_oparen = ignore # ignore/add/remove/force/not_defined + +# Whether to balance spaces inside nested parentheses. +sp_balance_nested_parens = false # true/false + +# Add or remove space between ')' and '{'. +sp_paren_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between nested braces, i.e. '{{' vs. '{ {'. +sp_brace_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before pointer star '*'. +sp_before_ptr_star = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before pointer star '*' that isn't followed by a +# variable name. If set to ignore, sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between pointer stars '*', as in 'int ***a;'. +sp_between_ptr_star = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after pointer star '*', if followed by a word. +# +# Overrides sp_type_func. +sp_after_ptr_star = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after pointer caret '^', if followed by a word. +sp_after_ptr_block_caret = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after pointer star '*', if followed by a qualifier. +sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after a pointer star '*', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_ptr_star and sp_type_func. +sp_after_ptr_star_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after a pointer star '*' in the trailing return of a +# function prototype or function definition. +sp_after_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the pointer star '*' and the name of the variable +# in a function pointer definition. +sp_ptr_star_func_var = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the pointer star '*' and the name of the type +# in a function pointer type definition. +sp_ptr_star_func_type = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after a pointer star '*', if followed by an open +# parenthesis, as in 'void* (*)()'. +sp_ptr_star_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a pointer star '*', if followed by a function +# prototype or function definition. +sp_before_ptr_star_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a pointer star '*' in the trailing return of a +# function prototype or function definition. +sp_before_ptr_star_trailing = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a reference sign '&'. +sp_before_byref = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a reference sign '&' that isn't followed by a +# variable name. If set to ignore, sp_before_byref is used instead. +sp_before_unnamed_byref = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after reference sign '&', if followed by a word. +# +# Overrides sp_type_func. +sp_after_byref = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after a reference sign '&', if followed by a function +# prototype or function definition. +# +# Overrides sp_after_byref and sp_type_func. +sp_after_byref_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a reference sign '&', if followed by a function +# prototype or function definition. +sp_before_byref_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after a reference sign '&', if followed by an open +# parenthesis, as in 'char& (*)()'. +sp_byref_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between type and word. In cases where total removal of +# whitespace would be a syntax error, a value of 'remove' is treated the same +# as 'force'. +# +# This also affects some other instances of space following a type that are +# not covered by other options; for example, between the return type and +# parenthesis of a function type template argument, between the type and +# parenthesis of an array parameter, or between 'decltype(...)' and the +# following word. +# +# Default: force +sp_after_type = force # ignore/add/remove/force/not_defined + +# Add or remove space between 'decltype(...)' and word, +# brace or function call. +sp_after_decltype = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space before the parenthesis in the D constructs +# 'template Foo(' and 'class Foo('. +sp_before_template_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'template' and '<'. +# If set to ignore, sp_before_angle is used. +sp_template_angle = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before '<'. +sp_before_angle = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '<' and '>'. +sp_inside_angle = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '<>'. +sp_inside_angle_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '>' and ':'. +sp_angle_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after '>'. +sp_after_angle = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '>' and '()' as found in 'new List();'. +sp_angle_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = add # ignore/add/remove/force/not_defined + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = false # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '(' and ')' of control statements other than +# 'for'. +sp_inside_sparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after '(' of control statements other than 'for'. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_open = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before ')' of control statements other than 'for'. +# +# Overrides sp_inside_sparen. +sp_inside_sparen_close = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '(' and ')' of 'for' statements. +sp_inside_for = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after '(' of 'for' statements. +# +# Overrides sp_inside_for. +sp_inside_for_open = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before ')' of 'for' statements. +# +# Overrides sp_inside_for. +sp_inside_for_close = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '((' or '))' of control statements. +sp_sparen_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after ')' of control statements. +sp_after_sparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and '{' of control statements. +sp_sparen_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'do' and '{'. +sp_do_brace_open = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '}' and 'while'. +sp_brace_close_while = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'while' and '('. Overrides sp_before_sparen. +sp_while_paren_open = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space between 'invariant' and '('. +sp_invariant_paren = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space after the ')' in 'invariant (C) c'. +sp_after_invariant_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. +sp_special_semi = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before ';'. +# +# Default: remove +sp_before_semi = remove # ignore/add/remove/force/not_defined + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a semicolon of an empty left part of a for +# statement, as in 'for ( ; ; )'. +sp_before_semi_for_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the semicolons of an empty middle part of a for +# statement, as in 'for ( ; ; )'. +sp_between_semi_for_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after ';', except when followed by a comment. +# +# Default: add +sp_after_semi = add # ignore/add/remove/force/not_defined + +# Add or remove space after ';' in non-empty 'for' statements. +# +# Default: force +sp_after_semi_for = force # ignore/add/remove/force/not_defined + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before '[' (except '[]'). +sp_before_square = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before '[' for a variable definition. +# +# Default: remove +sp_before_vardef_square = remove # ignore/add/remove/force/not_defined + +# Add or remove space before '[' for asm block. +sp_before_square_asm_block = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before '[]'. +sp_before_squares = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '[]'. +sp_inside_square_empty = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and +# ']'. If set to ignore, sp_inside_square is used. +sp_inside_square_oc_array = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. +sp_after_comma = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before ',', i.e. 'a,b' vs. 'a ,b'. +# +# Default: remove +sp_before_comma = remove # ignore/add/remove/force/not_defined + +# (C#, Vala) Add or remove space between ',' and ']' in multidimensional array type +# like 'int[,,]'. +sp_after_mdatype_commas = ignore # ignore/add/remove/force/not_defined + +# (C#, Vala) Add or remove space between '[' and ',' in multidimensional array type +# like 'int[,,]'. +sp_before_mdatype_commas = ignore # ignore/add/remove/force/not_defined + +# (C#, Vala) Add or remove space between ',' in multidimensional array type +# like 'int[,,]'. +sp_between_mdatype_commas = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between an open parenthesis and comma, +# i.e. '(,' vs. '( ,'. +# +# Default: force +sp_paren_comma = force # ignore/add/remove/force/not_defined + +# Add or remove space between a type and ':'. +sp_type_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the variadic '...' when preceded by a +# non-punctuator. +# The value REMOVE will be overridden with FORCE +sp_after_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before the variadic '...' when preceded by a +# non-punctuator. +# The value REMOVE will be overridden with FORCE +sp_before_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a type and '...'. +sp_type_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a '*' and '...'. +sp_ptr_type_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and '...'. +sp_paren_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '&&' and '...'. +sp_byref_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and a qualifier such as 'const'. +sp_paren_qualifier = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and 'noexcept'. +sp_paren_noexcept = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after class ':'. +sp_after_class_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before class ':'. +sp_before_class_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after class constructor ':'. +# +# Default: add +sp_after_constr_colon = add # ignore/add/remove/force/not_defined + +# Add or remove space before class constructor ':'. +# +# Default: add +sp_before_constr_colon = add # ignore/add/remove/force/not_defined + +# Add or remove space before case ':'. +# +# Default: remove +sp_before_case_colon = remove # ignore/add/remove/force/not_defined + +# Add or remove space between 'operator' and operator sign. +sp_after_operator = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the operator symbol and the open parenthesis, as +# in 'operator ++('. +sp_after_operator_sym = ignore # ignore/add/remove/force/not_defined + +# Overrides sp_after_operator_sym when the operator has no arguments, as in +# 'operator *()'. +sp_after_operator_sym_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or +# '(int)a' vs. '(int) a'. +sp_after_cast = ignore # ignore/add/remove/force/not_defined + +# Add or remove spaces inside cast parentheses. +sp_inside_paren_cast = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the type and open parenthesis in a C++ cast, +# i.e. 'int(exp)' vs. 'int (exp)'. +sp_cpp_cast_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'sizeof' and '('. +sp_sizeof_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'sizeof' and '...'. +sp_sizeof_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'sizeof...' and '('. +sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '...' and a parameter pack. +sp_ellipsis_parameter_pack = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a parameter pack and '...'. +sp_parameter_pack_ellipsis = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'decltype' and '('. +sp_decltype_paren = ignore # ignore/add/remove/force/not_defined + +# (Pawn) Add or remove space after the tag keyword. +sp_after_tag = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside enum '{' and '}'. +sp_inside_braces_enum = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside struct/union '{' and '}'. +sp_inside_braces_struct = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' +sp_inside_braces_oc_dict = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after open brace in an unnamed temporary +# direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore. +sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before close brace in an unnamed temporary +# direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore. +sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside an unnamed temporary direct-list-initialization +# if statement is a brace_init_lst +# works only if sp_brace_brace is set to ignore +# works only if sp_before_type_brace_init_lst_close is set to ignore. +sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '{' and '}'. +sp_inside_braces = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside '{}'. +sp_inside_braces_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around trailing return operator '->'. +sp_trailing_return = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between return type and function name. A minimum of 1 +# is forced except for pointer return types. +sp_type_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between type and open brace of an unnamed temporary +# direct-list-initialization. +sp_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '(' on function declaration. +sp_func_proto_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '()' on function declaration +# without parameters. +sp_func_proto_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '(' with a typedef specifier. +sp_func_type_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between alias name and '(' of a non-pointer function type typedef. +sp_func_def_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '()' on function definition +# without parameters. +sp_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside empty function '()'. +# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. +sp_inside_fparens = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside function '(' and ')'. +sp_inside_fparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside the first parentheses in a function type, as in +# 'void (*x)(...)'. +sp_inside_tparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the ')' and '(' in a function type, as in +# 'void (*x)(...)'. +sp_after_tparen_close = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and '{' of function. +sp_fparen_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and '{' of a function call in object +# initialization. +# +# Overrides sp_fparen_brace. +sp_fparen_brace_initializer = ignore # ignore/add/remove/force/not_defined + +# (Java) Add or remove space between ')' and '{{' of double brace initializer. +sp_fparen_dbrace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '(' on function calls. +sp_func_call_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between function name and '()' on function calls without +# parameters. If set to ignore (the default), sp_func_call_paren is used. +sp_func_call_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between the user function name and '(' on function +# calls. You need to set a keyword to be a user function in the config file, +# like: +# set func_call_user tr _ i18n +sp_func_call_user_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside user function '(' and ')'. +sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between nested parentheses with user functions, +# i.e. '((' vs. '( ('. +sp_func_call_user_paren_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a constructor/destructor and the open +# parenthesis. +sp_func_class_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a constructor without parameters or destructor +# and '()'. +sp_func_class_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after 'return'. +# +# Default: force +sp_return = force # ignore/add/remove/force/not_defined + +# Add or remove space between 'return' and '('. +sp_return_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'return' and '{'. +sp_return_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '__attribute__' and '('. +sp_attribute_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. +sp_defined_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'throw' and '(' in 'throw (something)'. +sp_throw_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'throw' and anything other than '(' as in +# '@throw [...];'. +sp_after_throw = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'catch' and '(' in 'catch (something) { }'. +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between '@catch' and '(' +# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. +sp_oc_catch_paren = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before Objective-C protocol list +# as in '@protocol Protocol' or '@interface MyClass : NSObject'. +sp_before_oc_proto_list = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between class name and '(' +# in '@interface className(categoryName):BaseClass' +sp_oc_classname_paren = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space between 'version' and '(' +# in 'version (something) { }'. If set to ignore, sp_before_sparen is used. +sp_version_paren = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space between 'scope' and '(' +# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. +sp_scope_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'super' and '(' in 'super (something)'. +# +# Default: remove +sp_super_paren = remove # ignore/add/remove/force/not_defined + +# Add or remove space between 'this' and '(' in 'this (something)'. +# +# Default: remove +sp_this_paren = remove # ignore/add/remove/force/not_defined + +# Add or remove space between a macro name and its definition. +sp_macro = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a macro function ')' and its definition. +sp_macro_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '}' and the name of a typedef on the same line. +sp_brace_typedef = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' +# and '@catch' are on the same line, as in '@catch (decl) {'. +# If set to ignore, sp_catch_brace is used. +sp_oc_catch_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between '}' and '@catch' if on the same line. +# If set to ignore, sp_brace_catch is used. +sp_oc_brace_catch = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'finally' and '{' if on the same line. +sp_finally_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between '}' and 'finally' if on the same line. +sp_brace_finally = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'try' and '{' if on the same line. +sp_try_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between get/set and '{' if on the same line. +sp_getset_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a variable and '{' for C++ uniform +# initialization. +sp_word_brace_init_lst = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between a variable and '{' for a namespace. +# +# Default: add +sp_word_brace_ns = add # ignore/add/remove/force/not_defined + +# Add or remove space before the '::' operator. +sp_before_dc = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the '::' operator. +sp_after_dc = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove around the D named array initializer ':' operator. +sp_d_array_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the '!' (not) unary operator. +# +# Default: remove +sp_not = remove # ignore/add/remove/force/not_defined + +# Add or remove space between two '!' (not) unary operators. +# If set to ignore, sp_not will be used. +sp_not_not = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the '~' (invert) unary operator. +# +# Default: remove +sp_inv = remove # ignore/add/remove/force/not_defined + +# Add or remove space after the '&' (address-of) unary operator. This does not +# affect the spacing after a '&' that is part of a type. +# +# Default: remove +sp_addr = remove # ignore/add/remove/force/not_defined + +# Add or remove space around the '.' or '->' operators. +# +# Default: remove +sp_member = remove # ignore/add/remove/force/not_defined + +# Add or remove space after the '*' (dereference) unary operator. This does +# not affect the spacing after a '*' that is part of a type. +# +# Default: remove +sp_deref = remove # ignore/add/remove/force/not_defined + +# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. +# +# Default: remove +sp_sign = remove # ignore/add/remove/force/not_defined + +# Add or remove space between '++' and '--' the word to which it is being +# applied, as in '(--x)' or 'y++;'. +# +# Default: remove +sp_incdec = remove # ignore/add/remove/force/not_defined + +# Add or remove space before a backslash-newline at the end of a line. +# +# Default: add +sp_before_nl_cont = add # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' +# or '+(int) bar;'. +sp_after_oc_scope = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the colon in message specs, +# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. +sp_after_oc_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before the colon in message specs, +# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. +sp_before_oc_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_after_oc_dict_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before the colon in immutable dictionary expression +# 'NSDictionary *test = @{@"foo" :@"bar"};'. +sp_before_oc_dict_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue: 1];'. +sp_after_send_oc_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before the colon in message specs, +# i.e. '[object setValue:1];' vs. '[object setValue :1];'. +sp_before_send_oc_colon = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the (type) in message specs, +# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. +sp_after_oc_type = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after the first (type) in message specs, +# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. +sp_after_oc_return_type = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between '@selector' and '(', +# i.e. '@selector(msgName)' vs. '@selector (msgName)'. +# Also applies to '@protocol()' constructs. +sp_after_oc_at_sel = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between '@selector(x)' and the following word, +# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. +sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space inside '@selector' parentheses, +# i.e. '@selector(foo)' vs. '@selector( foo )'. +# Also applies to '@protocol()' constructs. +sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space before a block pointer caret, +# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. +sp_before_oc_block_caret = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after a block pointer caret, +# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. +sp_after_oc_block_caret = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between the receiver and selector in a message, +# as in '[receiver selector ...]'. +sp_after_oc_msg_receiver = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space after '@property'. +sp_after_oc_property = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove space between '@synchronized' and the open parenthesis, +# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. +sp_after_oc_synchronized = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around the ':' in 'b ? t : f'. +sp_cond_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_before = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the ':' in 'b ? t : f'. +# +# Overrides sp_cond_colon. +sp_cond_colon_after = ignore # ignore/add/remove/force/not_defined + +# Add or remove space around the '?' in 'b ? t : f'. +sp_cond_question = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_before = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the '?' in 'b ? t : f'. +# +# Overrides sp_cond_question. +sp_cond_question_after = ignore # ignore/add/remove/force/not_defined + +# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' +# and ':'. +# +# Overrides all other sp_cond_* options. +sp_cond_ternary_short = ignore # ignore/add/remove/force/not_defined + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make +# sense here. +sp_case_label = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space around the D '..' operator. +sp_range = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_after_for_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_before_for_colon = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. +sp_extern_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the opening of a C++ comment, as in '// A'. +sp_cmt_cpp_start = ignore # ignore/add/remove/force/not_defined + +# Add or remove space in a C++ region marker comment, as in '// BEGIN'. +# A region marker is defined as a comment which is not preceded by other text +# (i.e. the comment is the first non-whitespace on the line), and which starts +# with either 'BEGIN' or 'END'. +# +# Overrides sp_cmt_cpp_start. +sp_cmt_cpp_region = ignore # ignore/add/remove/force/not_defined + +# If true, space added with sp_cmt_cpp_start will be added after Doxygen +# sequences like '///', '///<', '//!' and '//!<'. +sp_cmt_cpp_doxygen = false # true/false + +# If true, space added with sp_cmt_cpp_start will be added after Qt translator +# or meta-data comments like '//:', '//=', and '//~'. +sp_cmt_cpp_qttr = false # true/false + +# Add or remove space between #else or #endif and a trailing comment. +sp_endif_cmt = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after 'new', 'delete' and 'delete[]'. +sp_after_new = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between 'new' and '(' in 'new()'. +sp_between_new_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space between ')' and type in 'new(foo) BAR'. +sp_after_newop_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space inside parentheses of the new operator +# as in 'new(foo) BAR'. +sp_inside_newop_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after the open parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_open = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before the close parenthesis of the new operator, +# as in 'new(foo) BAR'. +# +# Overrides sp_inside_newop_paren. +sp_inside_newop_paren_close = ignore # ignore/add/remove/force/not_defined + +# Add or remove space before a trailing comment. +sp_before_tr_cmt = ignore # ignore/add/remove/force/not_defined + +# Number of spaces before a trailing comment. +sp_num_before_tr_cmt = 0 # unsigned number + +# Add or remove space before an embedded comment. +# +# Default: force +sp_before_emb_cmt = force # ignore/add/remove/force/not_defined + +# Number of spaces before an embedded comment. +# +# Default: 1 +sp_num_before_emb_cmt = 1 # unsigned number + +# Add or remove space after an embedded comment. +# +# Default: force +sp_after_emb_cmt = force # ignore/add/remove/force/not_defined + +# Number of spaces after an embedded comment. +# +# Default: 1 +sp_num_after_emb_cmt = 1 # unsigned number + +# (Java) Add or remove space between an annotation and the open parenthesis. +sp_annotation_paren = ignore # ignore/add/remove/force/not_defined + +# If true, vbrace tokens are dropped to the previous token and skipped. +sp_skip_vbrace_tokens = false # true/false + +# Add or remove space after 'noexcept'. +sp_after_noexcept = ignore # ignore/add/remove/force/not_defined + +# Add or remove space after '_'. +sp_vala_after_translation = ignore # ignore/add/remove/force/not_defined + +# If true, a is inserted after #define. +force_tab_after_define = false # true/false + +# +# Indenting options +# + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 2 # unsigned number + +# Whether to ignore indent for the first continuation line. Subsequent +# continuation lines will still be indented to match the first. +indent_ignore_first_continue = false # true/false + +# The continuation indent. If non-zero, this overrides the indent of '(', '[' +# and '=' continuation indents. Negative values are OK; negative value is +# absolute and not increased for each '(' or '[' level. +# +# For FreeBSD, this is set to 4. +# Requires indent_ignore_first_continue=false. +indent_continue = 0 # number + +# The continuation indent, only for class header line(s). If non-zero, this +# overrides the indent of 'class' continuation indents. +# Requires indent_ignore_first_continue=false. +indent_continue_class_head = 0 # unsigned number + +# Whether to indent empty lines (i.e. lines which contain only spaces before +# the newline character). +indent_single_newlines = false # true/false + +# The continuation indent for func_*_param if they are true. If non-zero, this +# overrides the indent. +indent_param = 0 # unsigned number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent comments that are not at a brace level with tabs on a +# tabstop. Requires indent_with_tabs=2. If false, will use spaces. +indent_cmt_with_tabs = false # true/false + +# Whether to indent strings broken by '\' so that they line up. +indent_align_string = false # true/false + +# The number of spaces to indent multi-line XML strings. +# Requires indent_align_string=true. +indent_xml_string = 0 # unsigned number + +# Spaces to indent '{' from level. +indent_brace = 0 # unsigned number + +# Whether braces are indented to the body level. +indent_braces = false # true/false + +# Whether to disable indenting function braces if indent_braces=true. +indent_braces_no_func = false # true/false + +# Whether to disable indenting class braces if indent_braces=true. +indent_braces_no_class = false # true/false + +# Whether to disable indenting struct braces if indent_braces=true. +indent_braces_no_struct = false # true/false + +# Whether to indent based on the size of the brace parent, +# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. +indent_brace_parent = false # true/false + +# Whether to indent based on the open parenthesis instead of the open brace +# in '({\n'. +indent_paren_open_brace = false # true/false + +# (C#) Whether to indent the brace of a C# delegate by another level. +indent_cs_delegate_brace = false # true/false + +# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by +# another level. +indent_cs_delegate_body = false # true/false + +# Whether to indent the body of a 'namespace'. +indent_namespace = false # true/false + +# Whether to indent only the first namespace, and not any nested namespaces. +# Requires indent_namespace=true. +indent_namespace_single_indent = false # true/false + +# The number of spaces to indent a namespace block. +# If set to zero, use the value indent_columns +indent_namespace_level = 0 # unsigned number + +# If the body of the namespace is longer than this number, it won't be +# indented. Requires indent_namespace=true. 0 means no limit. +indent_namespace_limit = 0 # unsigned number + +# Whether to indent only in inner namespaces (nested in other namespaces). +# Requires indent_namespace=true. +indent_namespace_inner_only = false # true/false + +# Whether the 'extern "C"' body is indented. +indent_extern = false # true/false + +# Whether the 'class' body is indented. +indent_class = false # true/false + +# Whether to ignore indent for the leading base class colon. +indent_ignore_before_class_colon = false # true/false + +# Additional indent before the leading base class colon. +# Negative values decrease indent down to the first column. +# Requires indent_ignore_before_class_colon=false and a newline break before +# the colon (see pos_class_colon and nl_class_colon) +indent_before_class_colon = 0 # number + +# Whether to indent the stuff after a leading base class colon. +indent_class_colon = false # true/false + +# Whether to indent based on a class colon instead of the stuff after the +# colon. Requires indent_class_colon=true. +indent_class_on_colon = false # true/false + +# Whether to ignore indent for a leading class initializer colon. +indent_ignore_before_constr_colon = false # true/false + +# Whether to indent the stuff after a leading class initializer colon. +indent_constr_colon = false # true/false + +# Virtual indent from the ':' for leading member initializers. +# +# Default: 2 +indent_ctor_init_leading = 2 # unsigned number + +# Virtual indent from the ':' for following member initializers. +# +# Default: 2 +indent_ctor_init_following = 2 # unsigned number + +# Additional indent for constructor initializer list. +# Negative values decrease indent down to the first column. +indent_ctor_init = 0 # number + +# Whether to indent 'if' following 'else' as a new block under the 'else'. +# If false, 'else\nif' is treated as 'else if' for indenting purposes. +indent_else_if = false # true/false + +# Amount to indent variable declarations after a open brace. +# +# <0: Relative +# >=0: Absolute +indent_var_def_blk = 0 # number + +# Whether to indent continued variable declarations instead of aligning. +indent_var_def_cont = false # true/false + +# How to indent continued shift expressions ('<<' and '>>'). +# Set align_left_shift=false when using this. +# 0: Align shift operators instead of indenting them (default) +# 1: Indent by one level +# -1: Preserve original indentation +indent_shift = 0 # number + +# Whether to force indentation of function definitions to start in column 1. +indent_func_def_force_col1 = false # true/false + +# Whether to indent continued function call parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_call_param = false # true/false + +# Whether to indent continued function definition parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_def_param = false # true/false + +# for function definitions, only if indent_func_def_param is false +# Allows to align params when appropriate and indent them when not +# behave as if it was true if paren position is more than this value +# if paren position is more than the option value +indent_func_def_param_paren_pos_threshold = 0 # unsigned number + +# Whether to indent continued function call prototype one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_proto_param = false # true/false + +# Whether to indent continued function call declaration one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_class_param = false # true/false + +# Whether to indent continued class variable constructors one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_ctor_var_param = false # true/false + +# Whether to indent continued template parameter list one indent level, +# rather than aligning parameters under the open parenthesis. +indent_template_param = false # true/false + +# Double the indent for indent_func_xxx_param options. +# Use both values of the options indent_columns and indent_param. +indent_func_param_double = false # true/false + +# Indentation column for standalone 'const' qualifier on a function +# prototype. +indent_func_const = 0 # unsigned number + +# Indentation column for standalone 'throw' qualifier on a function +# prototype. +indent_func_throw = 0 # unsigned number + +# How to indent within a macro followed by a brace on the same line +# This allows reducing the indent in macros that have (for example) +# `do { ... } while (0)` blocks bracketing them. +# +# true: add an indent for the brace on the same line as the macro +# false: do not add an indent for the brace on the same line as the macro +# +# Default: true +indent_macro_brace = true # true/false + +# The number of spaces to indent a continued '->' or '.'. +# Usually set to 0, 1, or indent_columns. +indent_member = 0 # unsigned number + +# Whether lines broken at '.' or '->' should be indented by a single indent. +# The indent_member option will not be effective if this is set to true. +indent_member_single = false # true/false + +# Spaces to indent single line ('//') comments on lines before code. +indent_single_line_comments_before = 0 # unsigned number + +# Spaces to indent single line ('//') comments on lines after code. +indent_single_line_comments_after = 0 # unsigned number + +# When opening a paren for a control statement (if, for, while, etc), increase +# the indent level by this value. Negative values decrease the indent level. +indent_sparen_extra = 0 # number + +# Whether to indent trailing single line ('//') comments relative to the code +# instead of trying to keep the same absolute column. +indent_relative_single_line_comments = false # true/false + +# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. +# It might be wise to choose the same value for the option indent_case_brace. +indent_switch_case = 0 # unsigned number + +# Spaces to indent the body of a 'switch' before any 'case'. +# Usually the same as indent_columns or indent_switch_case. +indent_switch_body = 0 # unsigned number + +# Whether to ignore indent for '{' following 'case'. +indent_ignore_case_brace = false # true/false + +# Spaces to indent '{' from 'case'. By default, the brace will appear under +# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. +# It might be wise to choose the same value for the option indent_switch_case. +indent_case_brace = 0 # number + +# indent 'break' with 'case' from 'switch'. +indent_switch_break_with_case = false # true/false + +# Whether to indent preprocessor statements inside of switch statements. +# +# Default: true +indent_switch_pp = true # true/false + +# Spaces to shift the 'case' line, without affecting any other lines. +# Usually 0. +indent_case_shift = 0 # unsigned number + +# Whether to align comments before 'case' with the 'case'. +# +# Default: true +indent_case_comment = true # true/false + +# Whether to indent comments not found in first column. +# +# Default: true +indent_comment = true # true/false + +# Whether to indent comments found in first column. +indent_col1_comment = false # true/false + +# Whether to indent multi string literal in first column. +indent_col1_multi_string_literal = false # true/false + +# Align comments on adjacent lines that are this many columns apart or less. +# +# Default: 3 +indent_comment_align_thresh = 3 # unsigned number + +# Whether to ignore indent for goto labels. +indent_ignore_label = false # true/false + +# How to indent goto labels. Requires indent_ignore_label=false. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_label = 1 # number + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = 1 # number + +# Whether to indent the code after an access specifier by one level. +# If true, this option forces 'indent_access_spec=0'. +indent_access_spec_body = false # true/false + +# If an open parenthesis is followed by a newline, whether to indent the next +# line so that it lines up after the open parenthesis (not recommended). +indent_paren_nl = false # true/false + +# How to indent a close parenthesis after a newline. +# +# 0: Indent to body level (default) +# 1: Align under the open parenthesis +# 2: Indent to the brace level +# -1: Preserve original indentation +indent_paren_close = 0 # number + +# Whether to indent the open parenthesis of a function definition, +# if the parenthesis is on its own line. +indent_paren_after_func_def = false # true/false + +# Whether to indent the open parenthesis of a function declaration, +# if the parenthesis is on its own line. +indent_paren_after_func_decl = false # true/false + +# Whether to indent the open parenthesis of a function call, +# if the parenthesis is on its own line. +indent_paren_after_func_call = false # true/false + +# How to indent a comma when inside braces. +# 0: Indent by one level (default) +# 1: Align under the open brace +# -1: Preserve original indentation +indent_comma_brace = 0 # number + +# How to indent a comma when inside parentheses. +# 0: Indent by one level (default) +# 1: Align under the open parenthesis +# -1: Preserve original indentation +indent_comma_paren = 0 # number + +# How to indent a Boolean operator when inside parentheses. +# 0: Indent by one level (default) +# 1: Align under the open parenthesis +# -1: Preserve original indentation +indent_bool_paren = 0 # number + +# Whether to ignore the indentation of a Boolean operator when outside +# parentheses. +indent_ignore_bool = false # true/false + +# Whether to ignore the indentation of an arithmetic operator. +indent_ignore_arith = false # true/false + +# Whether to indent a semicolon when inside a for parenthesis. +# If true, aligns under the open for parenthesis. +indent_semicolon_for_paren = false # true/false + +# Whether to ignore the indentation of a semicolon outside of a 'for' +# statement. +indent_ignore_semicolon = false # true/false + +# Whether to align the first expression to following ones +# if indent_bool_paren=1. +indent_first_bool_expr = false # true/false + +# Whether to align the first expression to following ones +# if indent_semicolon_for_paren=true. +indent_first_for_expr = false # true/false + +# If an open square is followed by a newline, whether to indent the next line +# so that it lines up after the open square (not recommended). +indent_square_nl = false # true/false + +# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. +indent_preserve_sql = false # true/false + +# Whether to ignore the indentation of an assignment operator. +indent_ignore_assign = false # true/false + +# Whether to align continued statements at the '='. If false or if the '=' is +# followed by a newline, the next line is indent one tab. +# +# Default: true +indent_align_assign = true # true/false + +# If true, the indentation of the chunks after a '=' sequence will be set at +# LHS token indentation column before '='. +indent_off_after_assign = false # true/false + +# Whether to align continued statements at the '('. If false or the '(' is +# followed by a newline, the next line indent is one tab. +# +# Default: true +indent_align_paren = true # true/false + +# (OC) Whether to indent Objective-C code inside message selectors. +indent_oc_inside_msg_sel = false # true/false + +# (OC) Whether to indent Objective-C blocks at brace level instead of usual +# rules. +indent_oc_block = false # true/false + +# (OC) Indent for Objective-C blocks in a message relative to the parameter +# name. +# +# =0: Use indent_oc_block rules +# >0: Use specified number of spaces to indent +indent_oc_block_msg = 0 # unsigned number + +# (OC) Minimum indent for subsequent parameters +indent_oc_msg_colon = 0 # unsigned number + +# (OC) Whether to prioritize aligning with initial colon (and stripping spaces +# from lines, if necessary). +# +# Default: true +indent_oc_msg_prioritize_first_colon = true # true/false + +# (OC) Whether to indent blocks the way that Xcode does by default +# (from the keyword if the parameter is on its own line; otherwise, from the +# previous indentation level). Requires indent_oc_block_msg=true. +indent_oc_block_msg_xcode_style = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a +# message keyword. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_keyword = false # true/false + +# (OC) Whether to indent blocks from where the brace is, relative to a message +# colon. Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_colon = false # true/false + +# (OC) Whether to indent blocks from where the block caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_caret = false # true/false + +# (OC) Whether to indent blocks from where the brace caret is. +# Requires indent_oc_block_msg=true. +indent_oc_block_msg_from_brace = false # true/false + +# When indenting after virtual brace open and newline add further spaces to +# reach this minimum indent. +indent_min_vbrace_open = 0 # unsigned number + +# Whether to add further spaces after regular indent to reach next tabstop +# when indenting after virtual brace open and newline. +indent_vbrace_open_on_tabstop = false # true/false + +# How to indent after a brace followed by another token (not a newline). +# true: indent all contained lines to match the token +# false: indent all contained lines to match the brace +# +# Default: true +indent_token_after_brace = true # true/false + +# Whether to indent the body of a C++11 lambda. +indent_cpp_lambda_body = false # true/false + +# How to indent compound literals that are being returned. +# true: add both the indent from return & the compound literal open brace +# (i.e. 2 indent levels) +# false: only indent 1 level, don't add the indent for the open brace, only +# add the indent for the return. +# +# Default: true +indent_compound_literal_return = true # true/false + +# (C#) Whether to indent a 'using' block if no braces are used. +# +# Default: true +indent_using_block = true # true/false + +# How to indent the continuation of ternary operator. +# +# 0: Off (default) +# 1: When the `if_false` is a continuation, indent it under the `if_true` branch +# 2: When the `:` is a continuation, indent it under `?` +indent_ternary_operator = 0 # unsigned number + +# Whether to indent the statements inside ternary operator. +indent_inside_ternary_operator = false # true/false + +# If true, the indentation of the chunks after a `return` sequence will be set at return indentation column. +indent_off_after_return = false # true/false + +# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. +indent_off_after_return_new = false # true/false + +# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. +indent_single_after_return = false # true/false + +# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they +# have their own indentation). +indent_ignore_asm_block = false # true/false + +# Don't indent the close parenthesis of a function definition, +# if the parenthesis is on its own line. +donot_indent_func_def_close_paren = false # true/false + +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}' except for functions. +# Use nl_collapse_empty_body_functions to specify how empty function braces +# should be formatted. +nl_collapse_empty_body = false # true/false + +# Whether to collapse empty blocks between '{' and '}' for functions only. +# If true, overrides nl_inside_empty_func. +nl_collapse_empty_body_functions = false # true/false + +# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. +nl_assign_leave_one_liners = false # true/false + +# Don't split one-line braced statements inside a 'class xx { }' body. +nl_class_leave_one_liners = false # true/false + +# Don't split one-line enums, as in 'enum foo { BAR = 15 };' +nl_enum_leave_one_liners = false # true/false + +# Don't split one-line get or set functions. +nl_getset_leave_one_liners = false # true/false + +# (C#) Don't split one-line property get or set functions. +nl_cs_property_leave_one_liners = false # true/false + +# Don't split one-line function definitions, as in 'int foo() { return 0; }'. +# might modify nl_func_type_name +nl_func_leave_one_liners = false # true/false + +# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. +nl_cpp_lambda_leave_one_liners = false # true/false + +# Don't split one-line if/else statements, as in 'if(...) b++;'. +nl_if_leave_one_liners = false # true/false + +# Don't split one-line while statements, as in 'while(...) b++;'. +nl_while_leave_one_liners = false # true/false + +# Don't split one-line do statements, as in 'do { b++; } while(...);'. +nl_do_leave_one_liners = false # true/false + +# Don't split one-line for statements, as in 'for(...) b++;'. +nl_for_leave_one_liners = false # true/false + +# (OC) Don't split one-line Objective-C messages. +nl_oc_msg_leave_one_liner = false # true/false + +# (OC) Add or remove newline between method declaration and '{'. +nl_oc_mdef_brace = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove newline between Objective-C block signature and '{'. +nl_oc_block_brace = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove blank line before '@interface' statement. +nl_oc_before_interface = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove blank line before '@implementation' statement. +nl_oc_before_implementation = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove blank line before '@end' statement. +nl_oc_before_end = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove newline between '@interface' and '{'. +nl_oc_interface_brace = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove newline between '@implementation' and '{'. +nl_oc_implementation_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newlines at the start of the file. +nl_start_of_file = ignore # ignore/add/remove/force/not_defined + +# The minimum number of newlines at the start of the file (only used if +# nl_start_of_file is 'add' or 'force'). +nl_start_of_file_min = 0 # unsigned number + +# Add or remove newline at the end of the file. +nl_end_of_file = ignore # ignore/add/remove/force/not_defined + +# The minimum number of newlines at the end of the file (only used if +# nl_end_of_file is 'add' or 'force'). +nl_end_of_file_min = 0 # unsigned number + +# Add or remove newline between '=' and '{'. +nl_assign_brace = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove newline between '=' and '['. +nl_assign_square = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '[]' and '{'. +nl_tsquare_brace = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove newline after '= ['. Will also affect the newline before +# the ']'. +nl_after_square_assign = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between a function call's ')' and '{', as in +# 'list_for_each(item, &list) { }'. +nl_fcall_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'enum' and '{'. +nl_enum_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'enum' and 'class'. +nl_enum_class = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'enum class' and the identifier. +nl_enum_class_identifier = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'enum class' type and ':'. +nl_enum_identifier_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'enum class identifier :' and type. +nl_enum_colon_type = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'struct and '{'. +nl_struct_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'union' and '{'. +nl_union_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'if' and '{'. +nl_if_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and 'else'. +nl_brace_else = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'else if' and '{'. If set to ignore, +# nl_if_brace is used instead. +nl_elseif_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'else' and '{'. +nl_else_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'else' and 'if'. +nl_else_if = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before '{' opening brace +nl_before_opening_brace_func_class_def = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before 'if'/'else if' closing parenthesis. +nl_before_if_closing_paren = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and 'finally'. +nl_brace_finally = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'finally' and '{'. +nl_finally_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'try' and '{'. +nl_try_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between get/set and '{'. +nl_getset_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'for' and '{'. +nl_for_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before the '{' of a 'catch' statement, as in +# 'catch (decl) {'. +nl_catch_brace = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove newline before the '{' of a '@catch' statement, as in +# '@catch (decl) {'. If set to ignore, nl_catch_brace is used. +nl_oc_catch_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and 'catch'. +nl_brace_catch = ignore # ignore/add/remove/force/not_defined + +# (OC) Add or remove newline between '}' and '@catch'. If set to ignore, +# nl_brace_catch is used. +nl_oc_brace_catch = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and ']'. +nl_brace_square = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and ')' in a function invocation. +nl_brace_fparen = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'while' and '{'. +nl_while_brace = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove newline between 'scope (x)' and '{'. +nl_scope_brace = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove newline between 'unittest' and '{'. +nl_unittest_brace = ignore # ignore/add/remove/force/not_defined + +# (D) Add or remove newline between 'version (x)' and '{'. +nl_version_brace = ignore # ignore/add/remove/force/not_defined + +# (C#) Add or remove newline between 'using' and '{'. +nl_using_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between two open or close braces. Due to general +# newline/brace handling, REMOVE may not work. +nl_brace_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'do' and '{'. +nl_do_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '}' and 'while' of 'do' statement. +nl_brace_while = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'switch' and '{'. +nl_switch_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'synchronized' and '{'. +nl_synchronized_brace = ignore # ignore/add/remove/force/not_defined + +# Add a newline between ')' and '{' if the ')' is on a different line than the +# if/for/etc. +# +# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and +# nl_catch_brace. +nl_multi_line_cond = false # true/false + +# Add a newline after '(' if an if/for/while/switch condition spans multiple +# lines +nl_multi_line_sparen_open = ignore # ignore/add/remove/force/not_defined + +# Add a newline before ')' if an if/for/while/switch condition spans multiple +# lines. Overrides nl_before_if_closing_paren if both are specified. +nl_multi_line_sparen_close = ignore # ignore/add/remove/force/not_defined + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = false # true/false + +# Whether to add a newline before 'case', and a blank line before a 'case' +# statement that follows a ';' or '}'. +nl_before_case = false # true/false + +# Whether to add a newline after a 'case' statement. +nl_after_case = false # true/false + +# Add or remove newline between a case ':' and '{'. +# +# Overrides nl_after_case. +nl_case_colon_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between ')' and 'throw'. +nl_before_throw = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'namespace' and '{'. +nl_namespace_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template class. +nl_template_class = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template class declaration. +# +# Overrides nl_template_class. +nl_template_class_decl = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<>' of a specialized class declaration. +# +# Overrides nl_template_class_decl. +nl_template_class_decl_special = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template class definition. +# +# Overrides nl_template_class. +nl_template_class_def = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<>' of a specialized class definition. +# +# Overrides nl_template_class_def. +nl_template_class_def_special = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template function. +nl_template_func = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template function +# declaration. +# +# Overrides nl_template_func. +nl_template_func_decl = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<>' of a specialized function +# declaration. +# +# Overrides nl_template_func_decl. +nl_template_func_decl_special = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template function +# definition. +# +# Overrides nl_template_func. +nl_template_func_def = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<>' of a specialized function +# definition. +# +# Overrides nl_template_func_def. +nl_template_func_def_special = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after 'template<...>' of a template variable. +nl_template_var = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'template<...>' and 'using' of a templated +# type alias. +nl_template_using = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'class' and '{'. +nl_class_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before or after (depending on pos_class_comma, +# may not be IGNORE) each',' in the base class list. +nl_class_init_args = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after each ',' in the constructor member +# initialization. Related to nl_constr_colon, pos_constr_colon and +# pos_constr_comma. +nl_constr_init_args = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before first element, after comma, and after last +# element, in 'enum'. +nl_enum_own_lines = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between return type and function name in a function +# definition. +# might be modified by nl_func_leave_one_liners +nl_func_type_name = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between return type and function name inside a class +# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name +# is used instead. +nl_func_type_name_class = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between class specification and '::' +# in 'void A::f() { }'. Only appears in separate member implementation (does +# not appear with in-line implementation). +nl_func_class_scope = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between function scope and name, as in +# 'void A :: f() { }'. +nl_func_scope_name = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between return type and function name in a prototype. +nl_func_proto_type_name = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between a function name and the opening '(' in the +# declaration. +nl_func_paren = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_paren for functions with no parameters. +nl_func_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between a function name and the opening '(' in the +# definition. +nl_func_def_paren = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_def_paren for functions with no parameters. +nl_func_def_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between a function name and the opening '(' in the +# call. +nl_func_call_paren = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_call_paren for functions with no parameters. +nl_func_call_paren_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after '(' in a function declaration. +nl_func_decl_start = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after '(' in a function definition. +nl_func_def_start = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_decl_start when there is only one parameter. +nl_func_decl_start_single = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_def_start when there is only one parameter. +nl_func_def_start_single = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after '(' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_start is used instead. +nl_func_decl_start_multi_line = false # true/false + +# Whether to add a newline after '(' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_start is used instead. +nl_func_def_start_multi_line = false # true/false + +# Add or remove newline after each ',' in a function declaration. +nl_func_decl_args = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after each ',' in a function definition. +nl_func_def_args = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline after each ',' in a function call. +nl_func_call_args = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after each ',' in a function declaration if '(' +# and ')' are in different lines. If false, nl_func_decl_args is used instead. +nl_func_decl_args_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function definition if '(' +# and ')' are in different lines. If false, nl_func_def_args is used instead. +nl_func_def_args_multi_line = false # true/false + +# Add or remove newline before the ')' in a function declaration. +nl_func_decl_end = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline before the ')' in a function definition. +nl_func_def_end = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_decl_end when there is only one parameter. +nl_func_decl_end_single = ignore # ignore/add/remove/force/not_defined + +# Overrides nl_func_def_end when there is only one parameter. +nl_func_def_end_single = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline before ')' in a function declaration if '(' and ')' +# are in different lines. If false, nl_func_decl_end is used instead. +nl_func_decl_end_multi_line = false # true/false + +# Whether to add a newline before ')' in a function definition if '(' and ')' +# are in different lines. If false, nl_func_def_end is used instead. +nl_func_def_end_multi_line = false # true/false + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between '()' in a function call. +nl_func_call_empty = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after '(' in a function call, +# has preference over nl_func_call_start_multi_line. +nl_func_call_start = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline before ')' in a function call. +nl_func_call_end = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after '(' in a function call if '(' and ')' are in +# different lines. +nl_func_call_start_multi_line = false # true/false + +# Whether to add a newline after each ',' in a function call if '(' and ')' +# are in different lines. +nl_func_call_args_multi_line = false # true/false + +# Whether to add a newline before ')' in a function call if '(' and ')' are in +# different lines. +nl_func_call_end_multi_line = false # true/false + +# Whether to respect nl_func_call_XXX option in case of closure args. +nl_func_call_args_multi_line_ignore_closures = false # true/false + +# Whether to add a newline after '<' of a template parameter list. +nl_template_start = false # true/false + +# Whether to add a newline after each ',' in a template parameter list. +nl_template_args = false # true/false + +# Whether to add a newline before '>' of a template parameter list. +nl_template_end = false # true/false + +# (OC) Whether to put each Objective-C message parameter on a separate line. +# See nl_oc_msg_leave_one_liner. +nl_oc_msg_args = false # true/false + +# (OC) Minimum number of Objective-C message parameters before applying nl_oc_msg_args. +nl_oc_msg_args_min_params = 0 # unsigned number + +# Add or remove newline between function signature and '{'. +nl_fdef_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between function signature and '{', +# if signature ends with ')'. Overrides nl_fdef_brace. +nl_fdef_brace_cond = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between C++11 lambda signature and '{'. +nl_cpp_ldef_brace = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'return' and the return expression. +nl_return_expr = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline between 'throw' and the throw expression. +nl_throw_expr = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after semicolons, except in 'for' statements. +nl_after_semicolon = false # true/false + +# (Java) Add or remove newline between the ')' and '{{' of the double brace +# initializer. +nl_paren_dbrace_open = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after the type in an unnamed temporary +# direct-list-initialization, better: +# before a direct-list-initialization. +nl_type_brace_init_lst = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline after the open brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_open = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline before the close brace in an unnamed temporary +# direct-list-initialization. +nl_type_brace_init_lst_close = ignore # ignore/add/remove/force/not_defined + +# Whether to add a newline before '{'. +nl_before_brace_open = false # true/false + +# Whether to add a newline after '{'. +nl_after_brace_open = false # true/false + +# Whether to add a newline between the open brace and a trailing single-line +# comment. Requires nl_after_brace_open=true. +nl_after_brace_open_cmt = false # true/false + +# Whether to add a newline after a virtual brace open with a non-empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open = false # true/false + +# Whether to add a newline after a virtual brace open with an empty body. +# These occur in un-braced if/while/do/for statement bodies. +nl_after_vbrace_open_empty = false # true/false + +# Whether to add a newline after '}'. Does not apply if followed by a +# necessary ';'. +nl_after_brace_close = false # true/false + +# Whether to add a newline after a virtual brace close, +# as in 'if (foo) a++; return;'. +nl_after_vbrace_close = false # true/false + +# Add or remove newline between the close brace and identifier, +# as in 'struct { int a; } b;'. Affects enumerations, unions and +# structures. If set to ignore, uses nl_after_brace_close. +nl_brace_struct_var = ignore # ignore/add/remove/force/not_defined + +# Whether to alter newlines in '#define' macros. +nl_define_macro = false # true/false + +# Whether to alter newlines between consecutive parenthesis closes. The number +# of closing parentheses in a line will depend on respective open parenthesis +# lines. +nl_squeeze_paren_close = false # true/false + +# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and +# '#endif'. Does not affect top-level #ifdefs. +nl_squeeze_ifdef = false # true/false + +# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. +nl_squeeze_ifdef_top_level = false # true/false + +# Add or remove blank line before 'if'. +nl_before_if = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'if' statement. Add/Force work only if the +# next token is not a closing brace. +nl_after_if = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line before 'for'. +nl_before_for = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'for' statement. +nl_after_for = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line before 'while'. +nl_before_while = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'while' statement. +nl_after_while = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line before 'switch'. +nl_before_switch = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'switch' statement. +nl_after_switch = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line before 'synchronized'. +nl_before_synchronized = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'synchronized' statement. +nl_after_synchronized = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line before 'do'. +nl_before_do = ignore # ignore/add/remove/force/not_defined + +# Add or remove blank line after 'do/while' statement. +nl_after_do = ignore # ignore/add/remove/force/not_defined + +# Ignore nl_before_{if,for,switch,do,synchronized} if the control +# statement is immediately after a case statement. +# if nl_before_{if,for,switch,do} is set to remove, this option +# does nothing. +nl_before_ignore_after_case = false # true/false + +# Whether to put a blank line before 'return' statements, unless after an open +# brace. +nl_before_return = false # true/false + +# Whether to put a blank line after 'return' statements, unless followed by a +# close brace. +nl_after_return = false # true/false + +# Whether to put a blank line before a member '.' or '->' operators. +nl_before_member = ignore # ignore/add/remove/force/not_defined + +# (Java) Whether to put a blank line after a member '.' or '->' operators. +nl_after_member = ignore # ignore/add/remove/force/not_defined + +# Whether to double-space commented-entries in 'struct'/'union'/'enum'. +nl_ds_struct_enum_cmt = false # true/false + +# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. +# (Lower priority than eat_blanks_before_close_brace.) +nl_ds_struct_enum_close_brace = false # true/false + +# Add or remove newline before or after (depending on pos_class_colon) a class +# colon, as in 'class Foo : public Bar'. +nl_class_colon = ignore # ignore/add/remove/force/not_defined + +# Add or remove newline around a class constructor colon. The exact position +# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. +nl_constr_colon = ignore # ignore/add/remove/force/not_defined + +# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' +# into a single line. If true, prevents other brace newline rules from turning +# such code into four lines. If true, it also preserves one-liner namespaces. +nl_namespace_two_to_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced if statements, turning them +# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. +nl_create_if_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced for statements, turning them +# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. +nl_create_for_one_liner = false # true/false + +# Whether to remove a newline in simple unbraced while statements, turning +# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. +nl_create_while_one_liner = false # true/false + +# Whether to collapse a function definition whose body (not counting braces) +# is only one line so that the entire definition (prototype, braces, body) is +# a single line. +nl_create_func_def_one_liner = false # true/false + +# Whether to split one-line simple list definitions into three lines by +# adding newlines, as in 'int a[12] = { 0 };'. +nl_create_list_one_liner = false # true/false + +# Whether to split one-line simple unbraced if statements into two lines by +# adding a newline, as in 'if(b) i++;'. +nl_split_if_one_liner = false # true/false + +# Whether to split one-line simple unbraced for statements into two lines by +# adding a newline, as in 'for (...) stmt;'. +nl_split_for_one_liner = false # true/false + +# Whether to split one-line simple unbraced while statements into two lines by +# adding a newline, as in 'while (expr) stmt;'. +nl_split_while_one_liner = false # true/false + +# Don't add a newline before a cpp-comment in a parameter list of a function +# call. +donot_add_nl_before_cpp_comment = false # true/false + +# +# Blank line options +# + +# The maximum number of consecutive newlines (3 = 2 blank lines). +nl_max = 0 # unsigned number + +# The maximum number of consecutive newlines in a function. +nl_max_blank_in_func = 0 # unsigned number + +# The number of newlines inside an empty function body. +# This option overrides eat_blanks_after_open_brace and +# eat_blanks_before_close_brace, but is ignored when +# nl_collapse_empty_body_functions=true +nl_inside_empty_func = 0 # unsigned number + +# The number of newlines before a function prototype. +nl_before_func_body_proto = 0 # unsigned number + +# The number of newlines before a multi-line function definition. Where +# applicable, this option is overridden with eat_blanks_after_open_brace=true +nl_before_func_body_def = 0 # unsigned number + +# The number of newlines before a class constructor/destructor prototype. +nl_before_func_class_proto = 0 # unsigned number + +# The number of newlines before a class constructor/destructor definition. +nl_before_func_class_def = 0 # unsigned number + +# The number of newlines after a function prototype. +nl_after_func_proto = 0 # unsigned number + +# The number of newlines after a function prototype, if not followed by +# another function prototype. +nl_after_func_proto_group = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype. +nl_after_func_class_proto = 0 # unsigned number + +# The number of newlines after a class constructor/destructor prototype, +# if not followed by another constructor/destructor prototype. +nl_after_func_class_proto_group = 0 # unsigned number + +# Whether one-line method definitions inside a class body should be treated +# as if they were prototypes for the purposes of adding newlines. +# +# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def +# and nl_before_func_class_def for one-liners. +nl_class_leave_one_liner_groups = false # true/false + +# The number of newlines after '}' of a multi-line function body. +nl_after_func_body = 0 # unsigned number + +# The number of newlines after '}' of a multi-line function body in a class +# declaration. Also affects class constructors/destructors. +# +# Overrides nl_after_func_body. +nl_after_func_body_class = 0 # unsigned number + +# The number of newlines after '}' of a single line function body. Also +# affects class constructors/destructors. +# +# Overrides nl_after_func_body and nl_after_func_body_class. +nl_after_func_body_one_liner = 0 # unsigned number + +# The number of newlines before a block of typedefs. If nl_after_access_spec +# is non-zero, that option takes precedence. +# +# 0: No change (default). +nl_typedef_blk_start = 0 # unsigned number + +# The number of newlines after a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of typedefs. +# +# 0: No change (default). +nl_typedef_blk_in = 0 # unsigned number + +# The minimum number of blank lines after a block of variable definitions +# at the top of a function body. If any preprocessor directives appear +# between the opening brace of the function and the variable block, then +# it is considered as not at the top of the function.Newlines are added +# before trailing preprocessor directives, if any exist. +# +# 0: No change (default). +nl_var_def_blk_end_func_top = 0 # unsigned number + +# The minimum number of empty newlines before a block of variable definitions +# not at the top of a function body. If nl_after_access_spec is non-zero, +# that option takes precedence. Newlines are not added at the top of the +# file or just after an opening brace. Newlines are added above any +# preprocessor directives before the block. +# +# 0: No change (default). +nl_var_def_blk_start = 0 # unsigned number + +# The minimum number of empty newlines after a block of variable definitions +# not at the top of a function body. Newlines are not added if the block +# is at the bottom of the file or just before a preprocessor directive. +# +# 0: No change (default). +nl_var_def_blk_end = 0 # unsigned number + +# The maximum number of consecutive newlines within a block of variable +# definitions. +# +# 0: No change (default). +nl_var_def_blk_in = 0 # unsigned number + +# The minimum number of newlines before a multi-line comment. +# Doesn't apply if after a brace open or another multi-line comment. +nl_before_block_comment = 0 # unsigned number + +# The minimum number of newlines before a single-line C comment. +# Doesn't apply if after a brace open or other single-line C comments. +nl_before_c_comment = 0 # unsigned number + +# The minimum number of newlines before a CPP comment. +# Doesn't apply if after a brace open or other CPP comments. +nl_before_cpp_comment = 0 # unsigned number + +# Whether to force a newline after a multi-line comment. +nl_after_multiline_comment = false # true/false + +# Whether to force a newline after a label's colon. +nl_after_label_colon = false # true/false + +# The number of newlines before a struct definition. +nl_before_struct = 0 # unsigned number + +# The number of newlines after '}' or ';' of a struct/enum/union definition. +nl_after_struct = 0 # unsigned number + +# The number of newlines before a class definition. +nl_before_class = 0 # unsigned number + +# The number of newlines after '}' or ';' of a class definition. +nl_after_class = 0 # unsigned number + +# The number of newlines before a namespace. +nl_before_namespace = 0 # unsigned number + +# The number of newlines after '{' of a namespace. This also adds newlines +# before the matching '}'. +# +# 0: Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if +# applicable, otherwise no change. +# +# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. +nl_inside_namespace = 0 # unsigned number + +# The number of newlines after '}' of a namespace. +nl_after_namespace = 0 # unsigned number + +# The number of newlines before an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +nl_before_access_spec = 0 # unsigned number + +# The number of newlines after an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +# +# Overrides nl_typedef_blk_start and nl_var_def_blk_start. +nl_after_access_spec = 0 # unsigned number + +# The number of newlines between a function definition and the function +# comment, as in '// comment\n void foo() {...}'. +# +# 0: No change (default). +nl_comment_func_def = 0 # unsigned number + +# The number of newlines after a try-catch-finally block that isn't followed +# by a brace close. +# +# 0: No change (default). +nl_after_try_catch_finally = 0 # unsigned number + +# (C#) The number of newlines before and after a property, indexer or event +# declaration. +# +# 0: No change (default). +nl_around_cs_property = 0 # unsigned number + +# (C#) The number of newlines between the get/set/add/remove handlers. +# +# 0: No change (default). +nl_between_get_set = 0 # unsigned number + +# (C#) Add or remove newline between property and the '{'. +nl_property_brace = ignore # ignore/add/remove/force/not_defined + +# Whether to remove blank lines after '{'. +eat_blanks_after_open_brace = false # true/false + +# Whether to remove blank lines before '}'. +eat_blanks_before_close_brace = false # true/false + +# How aggressively to remove extra newlines not in preprocessor. +# +# 0: No change (default) +# 1: Remove most newlines not handled by other config +# 2: Remove all newlines and reformat completely by config +nl_remove_extra_newlines = 0 # unsigned number + +# (Java) Add or remove newline after an annotation statement. Only affects +# annotations that are after a newline. +nl_after_annotation = ignore # ignore/add/remove/force/not_defined + +# (Java) Add or remove newline between two annotations. +nl_between_annotation = ignore # ignore/add/remove/force/not_defined + +# The number of newlines before a whole-file #ifdef. +# +# 0: No change (default). +nl_before_whole_file_ifdef = 0 # unsigned number + +# The number of newlines after a whole-file #ifdef. +# +# 0: No change (default). +nl_after_whole_file_ifdef = 0 # unsigned number + +# The number of newlines before a whole-file #endif. +# +# 0: No change (default). +nl_before_whole_file_endif = 0 # unsigned number + +# The number of newlines after a whole-file #endif. +# +# 0: No change (default). +nl_after_whole_file_endif = 0 # unsigned number + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions. +pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of assignment in wrapped expressions. Do not affect '=' +# followed by '{'. +pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of Boolean operators in wrapped expressions. +pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of comparison operators in wrapped expressions. +pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of conditional operators, as in the '?' and ':' of +# 'expr ? stmt : stmt', in wrapped expressions. +pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in wrapped expressions. +pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in enum entries. +pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the base class list if there is more than one +# line. Affects nl_class_init_args. +pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the constructor initialization list. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. +pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of trailing/leading class colon, between class and base class +# list. Affects nl_class_colon. +pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of colons between constructor and member initialization. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. +pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of shift operators in wrapped expressions. +pos_shift = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# +# Line splitting options +# + +# Try to limit code width to N columns. +code_width = 0 # unsigned number + +# Whether to fully split long 'for' statements at semi-colons. +ls_for_split_full = false # true/false + +# Whether to fully split long function prototypes/calls at commas. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_func_split_full = false # true/false + +# Whether to split lines as close to code_width as possible and ignore some +# groupings. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_code_width = false # true/false + +# +# Code alignment options (not left column spaces/tabs) +# + +# Whether to keep non-indenting tabs. +align_keep_tabs = false # true/false + +# Whether to use tabs for aligning. +align_with_tabs = false # true/false + +# Whether to bump out to the next tab when aligning. +align_on_tabstop = false # true/false + +# Whether to right-align numbers. +align_number_right = false # true/false + +# Whether to keep whitespace not required for alignment. +align_keep_extra_space = false # true/false + +# Whether to align variable definitions in prototypes and functions. +align_func_params = false # true/false + +# The span for aligning parameter definitions in function on parameter name. +# +# 0: Don't align (default). +align_func_params_span = 0 # unsigned number + +# The threshold for aligning function parameter definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_params_thresh = 0 # number + +# The gap for aligning function parameter definitions. +align_func_params_gap = 0 # unsigned number + +# The span for aligning constructor value. +# +# 0: Don't align (default). +align_constr_value_span = 0 # unsigned number + +# The threshold for aligning constructor value. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_constr_value_thresh = 0 # number + +# The gap for aligning constructor value. +align_constr_value_gap = 0 # unsigned number + +# Whether to align parameters in single-line functions that have the same +# name. The function names must already be aligned with each other. +align_same_func_call_params = false # true/false + +# The span for aligning function-call parameters for single line functions. +# +# 0: Don't align (default). +align_same_func_call_params_span = 0 # unsigned number + +# The threshold for aligning function-call parameters for single line +# functions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_same_func_call_params_thresh = 0 # number + +# The span for aligning variable definitions. +# +# 0: Don't align (default). +align_var_def_span = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of variable definitions. +# +# 0: Part of the type 'void * foo;' (default) +# 1: Part of the variable 'void *foo;' +# 2: Dangling 'void *foo;' +# Dangling: the '*' will not be taken into account when aligning. +align_var_def_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of variable definitions. +# +# 0: Part of the type 'long & foo;' (default) +# 1: Part of the variable 'long &foo;' +# 2: Dangling 'long &foo;' +# Dangling: the '&' will not be taken into account when aligning. +align_var_def_amp_style = 0 # unsigned number + +# The threshold for aligning variable definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_def_thresh = 0 # number + +# The gap for aligning variable definitions. +align_var_def_gap = 0 # unsigned number + +# Whether to align the colon in struct bit fields. +align_var_def_colon = false # true/false + +# The gap for aligning the colon in struct bit fields. +align_var_def_colon_gap = 0 # unsigned number + +# Whether to align any attribute after the variable name. +align_var_def_attribute = false # true/false + +# Whether to align inline struct/enum/union variable definitions. +align_var_def_inline = false # true/false + +# The span for aligning on '=' in assignments. +# +# 0: Don't align (default). +align_assign_span = 0 # unsigned number + +# The span for aligning on '=' in function prototype modifier. +# +# 0: Don't align (default). +align_assign_func_proto_span = 0 # unsigned number + +# The threshold for aligning on '=' in assignments. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_assign_thresh = 0 # number + +# Whether to align on the left most assignment when multiple +# definitions are found on the same line. +# Depends on 'align_assign_span' and 'align_assign_thresh' settings. +align_assign_on_multi_var_defs = false # true/false + +# The span for aligning on '{' in braced init list. +# +# 0: Don't align (default). +align_braced_init_list_span = 0 # unsigned number + +# The threshold for aligning on '{' in braced init list. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_braced_init_list_thresh = 0 # number + +# How to apply align_assign_span to function declaration "assignments", i.e. +# 'virtual void foo() = 0' or '~foo() = {default|delete}'. +# +# 0: Align with other assignments (default) +# 1: Align with each other, ignoring regular assignments +# 2: Don't align +align_assign_decl_func = 0 # unsigned number + +# The span for aligning on '=' in enums. +# +# 0: Don't align (default). +align_enum_equ_span = 0 # unsigned number + +# The threshold for aligning on '=' in enums. +# Use a negative number for absolute thresholds. +# +# 0: no limit (default). +align_enum_equ_thresh = 0 # number + +# The span for aligning class member definitions. +# +# 0: Don't align (default). +align_var_class_span = 0 # unsigned number + +# The threshold for aligning class member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_class_thresh = 0 # number + +# The gap for aligning class member definitions. +align_var_class_gap = 0 # unsigned number + +# The span for aligning struct/union member definitions. +# +# 0: Don't align (default). +align_var_struct_span = 0 # unsigned number + +# The threshold for aligning struct/union member definitions. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_var_struct_thresh = 0 # number + +# The gap for aligning struct/union member definitions. +align_var_struct_gap = 0 # unsigned number + +# The span for aligning struct initializer values. +# +# 0: Don't align (default). +align_struct_init_span = 0 # unsigned number + +# The span for aligning single-line typedefs. +# +# 0: Don't align (default). +align_typedef_span = 0 # unsigned number + +# The minimum space between the type and the synonym of a typedef. +align_typedef_gap = 0 # unsigned number + +# How to align typedef'd functions with other typedefs. +# +# 0: Don't mix them at all (default) +# 1: Align the open parenthesis with the types +# 2: Align the function type name with the other type names +align_typedef_func = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int * pint;' (default) +# 1: Part of type name: 'typedef int *pint;' +# 2: Dangling: 'typedef int *pint;' +# Dangling: the '*' will not be taken into account when aligning. +align_typedef_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of typedefs. +# +# 0: Part of the typedef type, 'typedef int & intref;' (default) +# 1: Part of type name: 'typedef int &intref;' +# 2: Dangling: 'typedef int &intref;' +# Dangling: the '&' will not be taken into account when aligning. +align_typedef_amp_style = 0 # unsigned number + +# The span for aligning comments that end lines. +# +# 0: Don't align (default). +align_right_cmt_span = 0 # unsigned number + +# Minimum number of columns between preceding text and a trailing comment in +# order for the comment to qualify for being aligned. Must be non-zero to have +# an effect. +align_right_cmt_gap = 0 # unsigned number + +# If aligning comments, whether to mix with comments after '}' and #endif with +# less than three spaces before the comment. +align_right_cmt_mix = false # true/false + +# Whether to only align trailing comments that are at the same brace level. +align_right_cmt_same_level = false # true/false + +# Minimum column at which to align trailing comments. Comments which are +# aligned beyond this column, but which can be aligned in a lesser column, +# may be "pulled in". +# +# 0: Ignore (default). +align_right_cmt_at_col = 0 # unsigned number + +# The span for aligning function prototypes. +# +# 0: Don't align (default). +align_func_proto_span = 0 # unsigned number + +# How to consider (or treat) the '*' in the alignment of function prototypes. +# +# 0: Part of the type 'void * foo();' (default) +# 1: Part of the function 'void *foo();' +# 2: Dangling 'void *foo();' +# Dangling: the '*' will not be taken into account when aligning. +align_func_proto_star_style = 0 # unsigned number + +# How to consider (or treat) the '&' in the alignment of function prototypes. +# +# 0: Part of the type 'long & foo();' (default) +# 1: Part of the function 'long &foo();' +# 2: Dangling 'long &foo();' +# Dangling: the '&' will not be taken into account when aligning. +align_func_proto_amp_style = 0 # unsigned number + +# The threshold for aligning function prototypes. +# Use a negative number for absolute thresholds. +# +# 0: No limit (default). +align_func_proto_thresh = 0 # number + +# Minimum gap between the return type and the function name. +align_func_proto_gap = 0 # unsigned number + +# Whether to align function prototypes on the 'operator' keyword instead of +# what follows. +align_on_operator = false # true/false + +# Whether to mix aligning prototype and variable declarations. If true, +# align_var_def_XXX options are used instead of align_func_proto_XXX options. +align_mix_var_proto = false # true/false + +# Whether to align single-line functions with function prototypes. +# Uses align_func_proto_span. +align_single_line_func = false # true/false + +# Whether to align the open brace of single-line functions. +# Requires align_single_line_func=true. Uses align_func_proto_span. +align_single_line_brace = false # true/false + +# Gap for align_single_line_brace. +align_single_line_brace_gap = 0 # unsigned number + +# (OC) The span for aligning Objective-C message specifications. +# +# 0: Don't align (default). +align_oc_msg_spec_span = 0 # unsigned number + +# Whether to align macros wrapped with a backslash and a newline. This will +# not work right if the macro contains a multi-line comment. +align_nl_cont = false # true/false + +# Whether to align macro functions and variables together. +align_pp_define_together = false # true/false + +# The span for aligning on '#define' bodies. +# +# =0: Don't align (default) +# >0: Number of lines (including comments) between blocks +align_pp_define_span = 0 # unsigned number + +# The minimum space between label and value of a preprocessor define. +align_pp_define_gap = 0 # unsigned number + +# Whether to align lines that start with '<<' with previous '<<'. +# +# Default: true +align_left_shift = true # true/false + +# Whether to align comma-separated statements following '<<' (as used to +# initialize Eigen matrices). +align_eigen_comma_init = false # true/false + +# Whether to align text after 'asm volatile ()' colons. +align_asm_colon = false # true/false + +# (OC) Span for aligning parameters in an Objective-C message call +# on the ':'. +# +# 0: Don't align. +align_oc_msg_colon_span = 0 # unsigned number + +# (OC) Whether to always align with the first parameter, even if it is too +# short. +align_oc_msg_colon_first = false # true/false + +# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration +# on the ':'. +align_oc_decl_colon = false # true/false + +# (OC) Whether to not align parameters in an Objectve-C message call if first +# colon is not on next line of the message call (the same way Xcode does +# alignment) +align_oc_msg_colon_xcode_like = false # true/false + +# +# Comment modification options +# + +# Try to wrap comments at N columns. +cmt_width = 0 # unsigned number + +# How to reflow comments. +# +# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) +# 1: No touching at all +# 2: Full reflow (enable cmt_indent_multi for indent with line wrapping due to cmt_width) +cmt_reflow_mode = 0 # unsigned number + +# Path to a file that contains regular expressions describing patterns for +# which the end of one line and the beginning of the next will be folded into +# the same sentence or paragraph during full comment reflow. The regular +# expressions are described using ECMAScript syntax. The syntax for this +# specification is as follows, where "..." indicates the custom regular +# expression and "n" indicates the nth end_of_prev_line_regex and +# beg_of_next_line_regex regular expression pair: +# +# end_of_prev_line_regex[1] = "...$" +# beg_of_next_line_regex[1] = "^..." +# end_of_prev_line_regex[2] = "...$" +# beg_of_next_line_regex[2] = "^..." +# . +# . +# . +# end_of_prev_line_regex[n] = "...$" +# beg_of_next_line_regex[n] = "^..." +# +# Note that use of this option overrides the default reflow fold regular +# expressions, which are internally defined as follows: +# +# end_of_prev_line_regex[1] = "[\w,\]\)]$" +# beg_of_next_line_regex[1] = "^[\w,\[\(]" +# end_of_prev_line_regex[2] = "\.$" +# beg_of_next_line_regex[2] = "^[A-Z]" +cmt_reflow_fold_regex_file = "" # string + +# Whether to indent wrapped lines to the start of the encompassing paragraph +# during full comment reflow (cmt_reflow_mode = 2). Overrides the value +# specified by cmt_sp_after_star_cont. +# +# Note that cmt_align_doxygen_javadoc_tags overrides this option for +# paragraphs associated with javadoc tags +cmt_reflow_indent_to_paragraph_start = false # true/false + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = false # true/false + +# Whether to apply changes to multi-line comments, including cmt_width, +# keyword substitution and leading chars. +# +# Default: true +cmt_indent_multi = true # true/false + +# Whether to align doxygen javadoc-style tags ('@param', '@return', etc.) +# and corresponding fields such that groups of consecutive block tags, +# parameter names, and descriptions align with one another. Overrides that +# which is specified by the cmt_sp_after_star_cont. If cmt_width > 0, it may +# be necessary to enable cmt_indent_multi and set cmt_reflow_mode = 2 +# in order to achieve the desired alignment for line-wrapping. +cmt_align_doxygen_javadoc_tags = false # true/false + +# The number of spaces to insert after the star and before doxygen +# javadoc-style tags (@param, @return, etc). Requires enabling +# cmt_align_doxygen_javadoc_tags. Overrides that which is specified by the +# cmt_sp_after_star_cont. +# +# Default: 1 +cmt_sp_before_doxygen_javadoc_tags = 1 # unsigned number + +# Whether to change trailing, single-line c-comments into cpp-comments. +cmt_trailing_single_line_c_to_cpp = false # true/false + +# Whether to group c-comments that look like they are in a block. +cmt_c_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined c-comment. +cmt_c_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined c-comment. +cmt_c_nl_end = false # true/false + +# Whether to change cpp-comments into c-comments. +cmt_cpp_to_c = false # true/false + +# Whether to group cpp-comments that look like they are in a block. Only +# meaningful if cmt_cpp_to_c=true. +cmt_cpp_group = false # true/false + +# Whether to put an empty '/*' on the first line of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_start = false # true/false + +# Whether to add a newline before the closing '*/' of the combined cpp-comment +# when converting to a c-comment. +# +# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. +cmt_cpp_nl_end = false # true/false + +# Whether to put a star on subsequent comment lines. +cmt_star_cont = false # true/false + +# The number of spaces to insert at the start of subsequent comment lines. +cmt_sp_before_star_cont = 0 # unsigned number + +# The number of spaces to insert after the star on subsequent comment lines. +cmt_sp_after_star_cont = 0 # unsigned number + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length. +# +# Default: true +cmt_multi_check_last = true # true/false + +# For multi-line comments with a '*' lead, remove leading spaces if the first +# and last lines of the comment are the same length AND if the length is +# bigger as the first_len minimum. +# +# Default: 4 +cmt_multi_first_len_minimum = 4 # unsigned number + +# Path to a file that contains text to insert at the beginning of a file if +# the file doesn't start with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_header = "" # string + +# Path to a file that contains text to insert at the end of a file if the +# file doesn't end with a C/C++ comment. If the inserted text contains +# '$(filename)', that will be replaced with the current file's name. +cmt_insert_file_footer = "" # string + +# Path to a file that contains text to insert before a function definition if +# the function isn't preceded by a C/C++ comment. If the inserted text +# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be +# replaced with, respectively, the name of the function, the javadoc '@param' +# and '@return' stuff, or the name of the class to which the member function +# belongs. +cmt_insert_func_header = "" # string + +# Path to a file that contains text to insert before a class if the class +# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', +# that will be replaced with the class name. +cmt_insert_class_header = "" # string + +# Path to a file that contains text to insert before an Objective-C message +# specification, if the method isn't preceded by a C/C++ comment. If the +# inserted text contains '$(message)' or '$(javaparam)', these will be +# replaced with, respectively, the name of the function, or the javadoc +# '@param' and '@return' stuff. +cmt_insert_oc_msg_header = "" # string + +# Whether a comment should be inserted if a preprocessor is encountered when +# stepping backwards from a function name. +# +# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and +# cmt_insert_class_header. +cmt_insert_before_preproc = false # true/false + +# Whether a comment should be inserted if a function is declared inline to a +# class definition. +# +# Applies to cmt_insert_func_header. +# +# Default: true +cmt_insert_before_inlines = true # true/false + +# Whether a comment should be inserted if the function is a class constructor +# or destructor. +# +# Applies to cmt_insert_func_header. +cmt_insert_before_ctor_dtor = false # true/false + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on a single-line 'do' statement. +mod_full_brace_do = ignore # ignore/add/remove/force/not_defined + +# Add or remove braces on a single-line 'for' statement. +mod_full_brace_for = ignore # ignore/add/remove/force/not_defined + +# (Pawn) Add or remove braces on a single-line function definition. +mod_full_brace_function = ignore # ignore/add/remove/force/not_defined + +# Add or remove braces on a single-line 'if' statement. Braces will not be +# removed if the braced statement contains an 'else'. +mod_full_brace_if = ignore # ignore/add/remove/force/not_defined + +# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either +# have, or do not have, braces. Overrides mod_full_brace_if. +# +# 0: Don't override mod_full_brace_if +# 1: Add braces to all blocks if any block needs braces and remove braces if +# they can be removed from all blocks +# 2: Add braces to all blocks if any block already has braces, regardless of +# whether it needs them +# 3: Add braces to all blocks if any block needs braces and remove braces if +# they can be removed from all blocks, except if all blocks have braces +# despite none needing them +mod_full_brace_if_chain = 0 # unsigned number + +# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. +# If true, mod_full_brace_if_chain will only remove braces from an 'if' that +# does not have an 'else if' or 'else'. +mod_full_brace_if_chain_only = false # true/false + +# Add or remove braces on single-line 'while' statement. +mod_full_brace_while = ignore # ignore/add/remove/force/not_defined + +# Add or remove braces on single-line 'using ()' statement. +mod_full_brace_using = ignore # ignore/add/remove/force/not_defined + +# Don't remove braces around statements that span N newlines +mod_full_brace_nl = 0 # unsigned number + +# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks +# which span multiple lines. +# +# Affects: +# mod_full_brace_for +# mod_full_brace_if +# mod_full_brace_if_chain +# mod_full_brace_if_chain_only +# mod_full_brace_while +# mod_full_brace_using +# +# Does not affect: +# mod_full_brace_do +# mod_full_brace_function +mod_full_brace_nl_block_rem_mlcond = false # true/false + +# Add or remove unnecessary parentheses on 'return' statement. +mod_paren_on_return = ignore # ignore/add/remove/force/not_defined + +# Add or remove unnecessary parentheses on 'throw' statement. +mod_paren_on_throw = ignore # ignore/add/remove/force/not_defined + +# (Pawn) Whether to change optional semicolons to real semicolons. +mod_pawn_semicolon = false # true/false + +# Whether to fully parenthesize Boolean expressions in 'while' and 'if' +# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. +mod_full_paren_if_bool = false # true/false + +# Whether to fully parenthesize Boolean expressions after '=' +# statement, as in 'x = a && b > c;' => 'x = (a && (b > c));'. +mod_full_paren_assign_bool = false # true/false + +# Whether to fully parenthesize Boolean expressions after '=' +# statement, as in 'return a && b > c;' => 'return (a && (b > c));'. +mod_full_paren_return_bool = false # true/false + +# Whether to remove superfluous semicolons. +mod_remove_extra_semicolon = false # true/false + +# Whether to remove duplicate include. +mod_remove_duplicate_include = false # true/false + +# If a function body exceeds the specified number of newlines and doesn't have +# a comment after the close brace, a comment will be added. +mod_add_long_function_closebrace_comment = 0 # unsigned number + +# If a namespace body exceeds the specified number of newlines and doesn't +# have a comment after the close brace, a comment will be added. +mod_add_long_namespace_closebrace_comment = 0 # unsigned number + +# If a class body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_class_closebrace_comment = 0 # unsigned number + +# If a switch body exceeds the specified number of newlines and doesn't have a +# comment after the close brace, a comment will be added. +mod_add_long_switch_closebrace_comment = 0 # unsigned number + +# If an #ifdef body exceeds the specified number of newlines and doesn't have +# a comment after the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # unsigned number + +# If an #ifdef or #else body exceeds the specified number of newlines and +# doesn't have a comment after the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # unsigned number + +# Whether to take care of the case by the mod_sort_xx options. +mod_sort_case_sensitive = false # true/false + +# Whether to sort consecutive single-line 'import' statements. +mod_sort_import = false # true/false + +# (C#) Whether to sort consecutive single-line 'using' statements. +mod_sort_using = false # true/false + +# Whether to sort consecutive single-line '#include' statements (C/C++) and +# '#import' statements (Objective-C). Be aware that this has the potential to +# break your code if your includes/imports have ordering dependencies. +mod_sort_include = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# filename without extension when sorting is enabled. +mod_sort_incl_import_prioritize_filename = false # true/false + +# Whether to prioritize '#include' and '#import' statements that does not +# contain extensions when sorting is enabled. +mod_sort_incl_import_prioritize_extensionless = false # true/false + +# Whether to prioritize '#include' and '#import' statements that contain +# angle over quotes when sorting is enabled. +mod_sort_incl_import_prioritize_angle_over_quotes = false # true/false + +# Whether to ignore file extension in '#include' and '#import' statements +# for sorting comparison. +mod_sort_incl_import_ignore_extension = false # true/false + +# Whether to group '#include' and '#import' statements when sorting is enabled. +mod_sort_incl_import_grouping_enabled = false # true/false + +# Whether to move a 'break' that appears after a fully braced 'case' before +# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. +mod_move_case_break = false # true/false + +# Whether to move a 'return' that appears after a fully braced 'case' before +# the close brace, as in 'case X: { ... } return;' => 'case X: { ... return; }'. +mod_move_case_return = false # true/false + +# Add or remove braces around a fully braced case statement. Will only remove +# braces if there are no variable declarations in the block. +mod_case_brace = ignore # ignore/add/remove/force/not_defined + +# Whether to remove a void 'return;' that appears as the last statement in a +# function. +mod_remove_empty_return = false # true/false + +# Add or remove the comma after the last value of an enumeration. +mod_enum_last_comma = ignore # ignore/add/remove/force/not_defined + +# Syntax to use for infinite loops. +# +# 0: Leave syntax alone (default) +# 1: Rewrite as `for(;;)` +# 2: Rewrite as `while(true)` +# 3: Rewrite as `do`...`while(true);` +# 4: Rewrite as `while(1)` +# 5: Rewrite as `do`...`while(1);` +# +# Infinite loops that do not already match one of these syntaxes are ignored. +# Other options that affect loop formatting will be applied after transforming +# the syntax. +mod_infinite_loop = 0 # unsigned number + +# Add or remove the 'int' keyword in 'int short'. +mod_int_short = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'short int'. +mod_short_int = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'int long'. +mod_int_long = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'long int'. +mod_long_int = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'int signed'. +mod_int_signed = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'signed int'. +mod_signed_int = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'int unsigned'. +mod_int_unsigned = ignore # ignore/add/remove/force/not_defined + +# Add or remove the 'int' keyword in 'unsigned int'. +mod_unsigned_int = ignore # ignore/add/remove/force/not_defined + +# If there is a situation where mod_int_* and mod_*_int would result in +# multiple int keywords, whether to keep the rightmost int (the default) or the +# leftmost int. +mod_int_prefer_int_on_left = false # true/false + +# (OC) Whether to organize the properties. If true, properties will be +# rearranged according to the mod_sort_oc_property_*_weight factors. +mod_sort_oc_properties = false # true/false + +# (OC) Weight of a class property modifier. +mod_sort_oc_property_class_weight = 0 # number + +# (OC) Weight of 'atomic' and 'nonatomic'. +mod_sort_oc_property_thread_safe_weight = 0 # number + +# (OC) Weight of 'readwrite' when organizing properties. +mod_sort_oc_property_readwrite_weight = 0 # number + +# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', +# 'weak', 'strong') when organizing properties. +mod_sort_oc_property_reference_weight = 0 # number + +# (OC) Weight of getter type ('getter=') when organizing properties. +mod_sort_oc_property_getter_weight = 0 # number + +# (OC) Weight of setter type ('setter=') when organizing properties. +mod_sort_oc_property_setter_weight = 0 # number + +# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', +# 'null_resettable') when organizing properties. +mod_sort_oc_property_nullability_weight = 0 # number + +# +# Preprocessor options +# + +# Add or remove indentation of preprocessor directives inside #if blocks +# at brace level 0 (file-level). +pp_indent = ignore # ignore/add/remove/force/not_defined + +# Whether to indent #if/#else/#endif at the brace level. If false, these are +# indented from column 1. +pp_indent_at_level = false # true/false + +# Whether to indent #if/#else/#endif at the parenthesis level if the brace +# level is 0. If false, these are indented from column 1. +pp_indent_at_level0 = false # true/false + +# Specifies the number of columns to indent preprocessors per level +# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies +# the number of columns to indent preprocessors per level +# at brace level > 0 (function-level). +# +# Default: 1 +pp_indent_count = 1 # unsigned number + +# Add or remove space after # based on pp_level of #if blocks. +pp_space_after = ignore # ignore/add/remove/force/not_defined + +# Sets the number of spaces per level added with pp_space_after. +pp_space_count = 0 # unsigned number + +# The indent for '#region' and '#endregion' in C# and '#pragma region' in +# C/C++. Negative values decrease indent down to the first column. +pp_indent_region = 0 # number + +# Whether to indent the code between #region and #endregion. +pp_region_indent_code = false # true/false + +# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when +# not at file-level. Negative values decrease indent down to the first column. +# +# =0: Indent preprocessors using output_tab_size +# >0: Column at which all preprocessors will be indented +pp_indent_if = 0 # number + +# Whether to indent the code between #if, #else and #endif. +pp_if_indent_code = false # true/false + +# Whether to indent the body of an #if that encompasses all the code in the file. +pp_indent_in_guard = false # true/false + +# Whether to indent '#define' at the brace level. If false, these are +# indented from column 1. +pp_define_at_level = false # true/false + +# Whether to indent '#include' at the brace level. +pp_include_at_level = false # true/false + +# Whether to ignore the '#define' body while formatting. +pp_ignore_define_body = false # true/false + +# Whether to indent case statements between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the case statements +# directly inside of. +# +# Default: true +pp_indent_case = true # true/false + +# Whether to indent whole function definitions between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the function definition +# is directly inside of. +# +# Default: true +pp_indent_func_def = true # true/false + +# Whether to indent extern C blocks between #if, #else, and #endif. +# Only applies to the indent of the preprocesser that the extern block is +# directly inside of. +# +# Default: true +pp_indent_extern = true # true/false + +# How to indent braces directly inside #if, #else, and #endif. +# Requires pp_if_indent_code=true and only applies to the indent of the +# preprocesser that the braces are directly inside of. +# 0: No extra indent +# 1: Indent by one level +# -1: Preserve original indentation +# +# Default: 1 +pp_indent_brace = 1 # number + +# Whether to print warning messages for unbalanced #if and #else blocks. +# This will print a message in the following cases: +# - if an #ifdef block ends on a different indent level than +# where it started from. Example: +# +# #ifdef TEST +# int i; +# { +# int j; +# #endif +# +# - an #elif/#else block ends on a different indent level than +# the corresponding #ifdef block. Example: +# +# #ifdef TEST +# int i; +# #else +# } +# int j; +# #endif +pp_warn_unbalanced_if = false # true/false + +# +# Sort includes options +# + +# The regex for include category with priority 0. +include_category_0 = "" # string + +# The regex for include category with priority 1. +include_category_1 = "" # string + +# The regex for include category with priority 2. +include_category_2 = "" # string + +# +# Use or Do not Use options +# + +# true: indent_func_call_param will be used (default) +# false: indent_func_call_param will NOT be used +# +# Default: true +use_indent_func_call_param = true # true/false + +# The value of the indentation for a continuation line is calculated +# differently if the statement is: +# - a declaration: your case with QString fileName ... +# - an assignment: your case with pSettings = new QSettings( ... +# +# At the second case the indentation value might be used twice: +# - at the assignment +# - at the function call (if present) +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indent_continue will be used only once +# false: indent_continue will be used every time (default) +# +# Requires indent_ignore_first_continue=false. +use_indent_continue_only_once = false # true/false + +# The indentation can be: +# - after the assignment, at the '[' character +# - at the beginning of the lambda body +# +# true: indentation will be at the beginning of the lambda body +# false: indentation will be after the assignment (default) +indent_cpp_lambda_only_once = false # true/false + +# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the +# historic behavior, but is probably not the desired behavior, so this is off +# by default. +use_sp_after_angle_always = false # true/false + +# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, +# this tries to format these so that they match Qt's normalized form (i.e. the +# result of QMetaObject::normalizedSignature), which can slightly improve the +# performance of the QObject::connect call, rather than how they would +# otherwise be formatted. +# +# See options_for_QT.cpp for details. +# +# Default: true +use_options_overriding_for_qt_macros = true # true/false + +# If true: the form feed character is removed from the list of whitespace +# characters. See https://en.cppreference.com/w/cpp/string/byte/isspace. +use_form_feed_no_more_as_whitespace_character = false # true/false + +# +# Warn levels - 1: error, 2: warning (default), 3: note +# + +# (C#) Warning is given if doing tab-to-\t replacement and we have found one +# in a C# verbatim string literal. +# +# Default: 2 +warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number + +# Limit the number of loops. +# Used by uncrustify.cpp to exit from infinite loop. +# 0: no limit. +debug_max_number_of_loops = 0 # number + +# Set the number of the line to protocol; +# Used in the function prot_the_line if the 2. parameter is zero. +# 0: nothing protocol. +debug_line_number_to_protocol = 0 # number + +# Set the number of second(s) before terminating formatting the current file, +# 0: no timeout. +# only for linux +debug_timeout = 0 # number + +# Set the number of characters to be printed if the text is too long, +# 0: do not truncate. +debug_truncate = 0 # unsigned number + +# sort (or not) the tracking info. +# +# Default: true +debug_sort_the_tracks = true # true/false + +# insert the number of the line at the beginning of each line +set_numbering_for_html_output = false # true/false + +# Meaning of the settings: +# Ignore - do not do any changes +# Add - makes sure there is 1 or more space/brace/newline/etc +# Force - makes sure there is exactly 1 space/brace/newline/etc, +# behaves like Add in some contexts +# Remove - removes space/brace/newline/etc +# +# +# - Token(s) can be treated as specific type(s) with the 'set' option: +# `set tokenType tokenString [tokenString...]` +# +# Example: +# `set BOOL __AND__ __OR__` +# +# tokenTypes are defined in src/token_enum.h, use them without the +# 'CT_' prefix: 'CT_BOOL' => 'BOOL' +# +# +# - Token(s) can be treated as type(s) with the 'type' option. +# `type tokenString [tokenString...]` +# +# Example: +# `type int c_uint_8 Rectangle` +# +# This can also be achieved with `set TYPE int c_uint_8 Rectangle` +# +# +# To embed whitespace in tokenStrings use the '\' escape character, or quote +# the tokenStrings. These quotes are supported: "'` +# +# +# - Support for the auto detection of languages through the file ending can be +# added using the 'file_ext' command. +# `file_ext langType langString [langString..]` +# +# Example: +# `file_ext CPP .ch .cxx .cpp.in` +# +# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use +# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' +# +# +# - Custom macro-based indentation can be set up using 'macro-open', +# 'macro-else' and 'macro-close'. +# `(macro-open | macro-else | macro-close) tokenString` +# +# Example: +# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` +# `macro-open BEGIN_MESSAGE_MAP` +# `macro-close END_MESSAGE_MAP` +# +# +# option(s) with 'not default' value: 0 +# diff --git a/library.properties b/library.properties index 67cb2c0..c10db46 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=HeliOS -version=0.3.4 +version=0.3.5 author=Manny Peterson maintainer=Manny Peterson sentence=The free embedded operating system. diff --git a/src/HeliOS.h b/src/HeliOS.h index deb52ff..fcd0c0b 100644 --- a/src/HeliOS.h +++ b/src/HeliOS.h @@ -2,12 +2,12 @@ * @file HeliOS.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Header file for end-user application code - * @version 0.3.4 - * @date 2022-01-31 + * @version 0.3.5 + * @date 2022-09-06 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,603 +33,724 @@ #include "config.h" #include "defines.h" +/* START OF ENUM TYPES */ + /** - * @brief Enumerated type for task states. + * @brief Enumerated data type for task states. * - * A task can be in one of the four possible states defined in the TaskState_t - * enumerated type. The state of a task is changed by calling xTaskResume(), - * xTaskSuspend() or xTaskWait(). The TaskState_t enumerated type should be declared - * as xTaskState. + * A task can be in one of four possible states as defined by the TaskState_t + * enumerated data type. The state a task is in is changed by calling xTaskResume(), + * xTaskSuspend() or xTaskWait(). The HeliOS scheduler will only schedule, for execution, + * tasks in either the TaskStateRunning or TaskStateWaiting state. TaskState_t should + * be declared (i.e., used) as xTaskState. * * @sa xTaskState * @sa xTaskResume() * @sa xTaskSuspend() * @sa xTaskWait() + * @sa xTaskGetTaskState() * */ typedef enum { - TaskStateError, /**< Returned by xTaskGetTaskState() when task cannot be found. */ - TaskStateSuspended, /**< State a task is in when it is first created by xTaskCreate() or suspended by xTaskSuspend(). */ - TaskStateRunning, /**< State a task is in after xTaskResume() is called. */ - TaskStateWaiting /**< State a task is in after xTaskWait() is called. */ + TaskStateError, /**< Returned by xTaskGetTaskState() when the task cannot be found. */ + TaskStateSuspended, /**< State a task is in when it is first created OR after calling xTaskSuspend() - tasks in the TaskStateSuspended state will not be scheduled for execution. */ + TaskStateRunning, /**< State a task is in after calling xTaskResume() - tasks in the TaskStateRunning state will be scheduled co-operatively. */ + TaskStateWaiting /**< State a task is in after calling xTaskWait() - tasks in the TaskStateWaiting state will be scheduled as event driven. */ } TaskState_t; /** - * @brief Enumerated type for scheduler states. + * @brief Enumerated data type for task states. + * + * @sa TaskState_t * - * The scheduler can be in one of four possible states defined in the SchedulerState_t - * enumerated type. The state of the scheduler is changed by calling xTaskSuspendAll() - * and xTaskResumeAll(). The state can be obtained by calling xTaskGetSchedulerState(). + */ +typedef TaskState_t xTaskState; + +/** + * @brief Enumerated data type for scheduler state. + * + * The scheduler can be in one of three possible states as defined by the SchedulerState_t + * enumerated data type. The state the scheduler is in is changed by calling xTaskSuspendAll() + * and xTaskResumeAll(). The state the scheduler is in can be obtained by calling xTaskGetSchedulerState(). + * SchedulerState_t should be declared (i.e., used) as xSchedulerState. * * @sa xSchedulerState * @sa xTaskSuspendAll() * @sa xTaskResumeAll() + * @sa xTaskGetSchedulerState() + * @sa xTaskStartScheduler() * */ typedef enum { - SchedulerStateError, /**< Not used. */ - SchedulerStateSuspended, /**< State the scheduler is in after xTaskSuspendAll() is called. */ - SchedulerStateRunning /**< State the scheduler is in after xTaskResumeAll() is called. */ + SchedulerStateError, /**< Not used - reserved for future use. */ + SchedulerStateSuspended, /**< State the scheduler is in after calling xTaskSuspendAll() - xTaskStartScheduler() will stop scheduling tasks for execution and relinquish control when xTaskSuspendAll() is called. */ + SchedulerStateRunning /**< State the scheduler is in after calling xTaskResumeAll() - xTaskStartScheduler() will continue to schedule tasks for execution until xTaskSuspendAll() is called. */ } SchedulerState_t; /** - * @brief Type definition for the base data type. - * - * A simple data type is often needed as an argument for a system call or a return type. - * The Base_t type is used in such a case where there are no other structural data - * requirements and is typically an unsigned 8-bit integer. The Base_t type should - * be declared as xBase. + * @brief Enumerated data type for the scheduler state. * - * @sa xBase + * @sa SchedulerState_t * */ -typedef uint8_t Base_t; +typedef SchedulerState_t xSchedulerState; + +/* START OF BASIC TYPES */ /** - * @brief Type defintion for the word data type + * @brief Data type for the task paramater. * - * A word is a 32-bit data type in HeliOS. + * The TaskParm_t type is used to pass a paramater to a task at the time of task + * creation using xTaskCreate(). A task paramater is a pointer of type void and + * can point to any number of types, arrays and/or data structures that will be + * passed to the task. It is up to the end-user to manage, allocate and free the + * memory related to these objects using xMemAlloc() and xMemFree(). TaskParm_t + * should be declared as xTaskParm. + * + * @sa xTaskParm + * @sa xTaskCreate() + * @sa xMemAlloc() + * @sa xMemFree() * - * @sa xWord */ -typedef uint32_t Word_t; +typedef VOID_TYPE TaskParm_t; /** - * @brief The type definition for time expressed in ticks. + * @brief Data type for the task paramater. * - * The xTicks type is used by several of the task and timer related system calls to express time. - * The unit of measure for time is always ticks. - * - * @sa xTicks + * @sa TaskParm_t * */ -typedef uint32_t Ticks_t; +typedef TaskParm_t *xTaskParm; /** - * @brief The type defintion for storing the size of some object in memory. + * @brief Data type for the base type. * - * The Size_t type is used to store the size of an object in memory and is - * always represented in bytes. Size_t should always be declared as xSize. + * The Base_t type is a simple data type often used as an argument or return type + * for system calls when the value is known not to exceed its 8-bit width and no + * data structure requirements exist. There are no guarantees the Base_t will + * always be 8-bits wide. If an 8-bit data type is needed that is guaranteed + * to remain 8-bits wide, the Byte_t data type should be used. Base_t should be + * declared as xBase. * - * @sa xSize + * @sa xBase + * @sa Byte_t * */ -typedef size_t Size_t; +typedef UINT8_TYPE Base_t; /** - * @brief The type defintion for storing the size of some object in memory. + * @brief Data type for the base type. * - * The xSize type is used to store the size of an object in memory and is - * always represented in bytes. + * @sa Base_t * */ -typedef Size_t xSize; +typedef Base_t xBase; /** - * @brief Data structure for task runtime statistics. + * @brief Data type for an 8-bit wide byte. * - * The TaskRunTimeStats_t structure contains task runtime statistics and is returned by - * xTaskGetAllRunTimeStats() and xTaskGetTaskRunTimeStats(). The TaskRunTimeStats_t type - * should be declared as xTaskRunTimeStats. + * The Byte_t type is an 8-bit wide data type and is guaranteed to always be + * 8-bits wide. Byte_t should be declared as xByte. * - * @sa xTaskRunTimeStats - * @sa xTaskGetTaskRunTimeStats() - * @sa xTaskGetAllRunTimeStats() - * @sa xMemFree() - * - * @warning The memory allocated for an instance of xTaskRunTimeStats must be freed - * using xMemFree(). + * @sa xByte * */ -typedef struct TaskRunTimeStats_s { - Base_t id; /**< The task identifier which is used by xTaskGetHandleById() to return the task handle. */ - Ticks_t lastRunTime; /**< The runtime duration in ticks the last time the task was executed by the scheduler. */ - Ticks_t totalRunTime; /**< The total runtime duration in ticks the task has been executed by the scheduler. */ -} TaskRunTimeStats_t; +typedef UINT8_TYPE Byte_t; /** - * @brief Data structure for information about a task. + * @brief Data type for an 8-bit wide byte. * - * The TaskInfo_t structure is similar to xTaskRuntimeStats_t in that it contains runtime statistics for - * a task. However, TaskInfo_t also contains additional details about a task such as its identifier, ASCII name - * and state. The TaskInfo_t structure is returned by xTaskGetTaskInfo(). If only runtime statistics are needed, - * TaskRunTimeStats_t should be used because of its lower memory footprint. The TaskInfo_t type should be - * declared as xTaskInfo. - * - * @sa xTaskInfo - * @sa xTaskGetTaskInfo() - * @sa xMemFree() - * @sa CONFIG_TASK_NAME_BYTES - * - * @warning The memory allocated for an instance of xTaskInfo must be freed using - * xMemFree(). + * @sa Byte_t * */ -typedef struct TaskInfo_s { - Base_t id; /**< The task identifier which is used by xTaskGetHandleById() to return the task handle. */ - char name[CONFIG_TASK_NAME_BYTES]; /**< The name of the task which is used by xTaskGetHandleByName() to return the task handle. This is NOT a null terminated string. */ - TaskState_t state; /**< The state the task is in which is one of four states specified in the TaskState_t enumerated data type. */ - Ticks_t lastRunTime; /**< The runtime duration in ticks the last time the task was executed by the scheduler. */ - Ticks_t totalRunTime; /**< The total runtime duration in ticks the task has been executed by the scheduler. */ -} TaskInfo_t; +typedef Byte_t xByte; /** - * @brief Data structure for direct to task notifications. - * - * The TaskNotification_t data structure contains the direct to task notification returned by xTaskNotifyTake(). - * The TaskNotification_t type should be declared as xTaskNotification. + * @brief Data type for a pointer to an address. * - * @sa xTaskNotification - * @sa xTaskNotifyTake() - * @sa xMemFree() - * @sa CONFIG_NOTIFICATION_VALUE_BYTES + * The Addr_t type is a pointer of type void and is used to pass + * addresses between the end-user application and system calls. It is not + * necessary to use the Addr_t ype within the end-user application as long as + * the type is not used to interact with the kernel through system calls. Addr_t + * should be declared as xAddr. * - * @warning The memory allocated for an instance of xTaskNotification must be freed using - * xMemFree(). + * @sa xAddr * */ -typedef struct TaskNotification_s { - Base_t notificationBytes; /**< The number of bytes in the notificationValue member that makes up the notification value. This cannot exceed CONFIG_NOTIFICATION_VALUE_BYTES. */ - char notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; /**< The char array that contains the actual notification value. This is NOT a null terminated string. */ -} TaskNotification_t; +typedef VOID_TYPE Addr_t; /** - * @brief Data structure for a message queue message. + * @brief Data type for a pointer to an address. * - * The QueueMessage_t data structure contains the message queue message returned by xQueuePeek() and - * xQueueReceive(). The QueueMessage_t type should be declared as xQueueMessage. + * @sa Addr_t * - * @sa xQueueMessage - * @sa xQueuePeek() - * @sa xQueueReceive() - * @sa xMemFree() - * @sa CONFIG_MESSAGE_VALUE_BYTES + */ +typedef Addr_t *xAddr; + +/** + * @brief Data type for the storage requirements of an object in memory. * - * @warning The memory allocated for an instance of xQueueMessage must be freed using xMemFree(). + * The Size_t type is used for the storage requirements of an object in + * memory and is always represented in bytes. Size_t should be declared as + * xSize. + * + * @sa xSize * */ -typedef struct QueueMessage_s { - Base_t messageBytes; /**< The number of bytes in the messageValue member that makes up the message value. This cannot exceed CONFIG_MESSAGE_VALUE_BYTES. */ - char messageValue[CONFIG_MESSAGE_VALUE_BYTES]; /**< the char array that contains the actual message value. This is NOT a null terminated string. */ -} QueueMessage_t; +typedef SIZE_TYPE Size_t; /** - * @brief Data structure for system informaiton. + * @brief Data type for the storage requirements of an object in memory. * - * The SystemInfo_t data structure contains information about the HeliOS system and is returned - * by xSystemGetSystemInfo(). The SystemInfo_t type should be declared as xSystemInfo. + * @sa Size_t * - * @sa xSystemInfo - * @sa xSystemGetSystemInfo() - * @sa xMemFree() + */ +typedef Size_t xSize; + +/** + * @brief Data type for a 16-bit half word. + * + * The HalfWord_t type is a 16-bit wide data type and is guaranteed to always be + * 16-bits wide. HalfWord_t should be declared as xHalfWord. * - * @warning The memory allocated for an instance of xSystemInfo must be freed using xMemFree(). + * @sa xHalfWord * */ -typedef struct SystemInfo_s { - char productName[OS_PRODUCT_NAME_SIZE]; /**< The name of the operating system or product. Its length is defined by OS_PRODUCT_NAME_SIZE. This is NOT a null terminated string. */ - Base_t majorVersion; /**< The major version number of HeliOS and is Symantec Versioning Specification (SemVer) compliant. */ - Base_t minorVersion; /**< The minor version number of HeliOS and is Symantec Versioning Specification (SemVer) compliant. */ - Base_t patchVersion; /**< The patch version number of HeliOS and is Symantec Versioning Specification (SemVer) compliant. */ - Base_t numberOfTasks; /**< The number of tasks presently in a suspended, running or waiting state. */ -} SystemInfo_t; +typedef UINT16_TYPE HalfWord_t; /** - * @brief Data structure for statistics on a memory region. + * @brief Data type for a 16-bit half word. * - * The MemoryRegionStats_t data structure is used to store statistics about a HeliOS - * memory region. Statistics can be obtained for the heap and kernel memory regions. - * - * @sa xMemGetHeapStats() - * @sa xMemGetKernelStats() - * @sa xMemoryRegionStats + * @sa HalfWord_t * */ -typedef struct MemoryRegionStats_s { - Word_t largestFreeEntryInBytes; - Word_t smallestFreeEntryInBytes; - Word_t numberOfFreeBlocks; - Word_t availableSpaceInBytes; - Word_t successfulAllocations; - Word_t successfulFrees; - Word_t minimumEverFreeBytesRemaining; -} MemoryRegionStats_t; +typedef HalfWord_t xHalfWord; /** - * @brief Stub type definition for the task type. + * @brief Data type for a 32-bit word. * - * The Task_t type is a stub type definition for the internal task data structure and is treated - * as a task handle by most of the task related system calls. The members of the data structure - * are not accessible. The Task_t type should be declared as xTask. + * The Word_t type is a 32-bit wide data type and is guaranteed to always be + * 32-bits wide. Word_t should be declared as xWord. * - * @sa xTask - * @sa xTaskDelete() + * @sa xWord * - * @warning The memory allocated for an instance of xTask must be freed by xTaskDelete() + */ +typedef UINT32_TYPE Word_t; + +/** + * @brief Data type for a 32-bit word. + * + * @sa Word_t * */ -typedef void Task_t; +typedef Word_t xWord; /** - * @brief Type definition for the task parameter. + * @brief Data type for system ticks. * - * The TaskParm_t type is used to pass a parameter to a task at the time of creation using - * xTaskCreate(). A task parameter is a pointer of type void and can point to any number - * of intrinsic types, arrays and/or user defined structures which can be passed to a - * task. It is up the the end-user to manage, allocate and free the memory related to - * these objects using xMemAlloc() and xMemFree(). The TaskParm_t should be declared - * as xTaskParm. + * The Ticks_t type is used to store ticks from the system clock. Ticks + * is not bound to any one unit of measure for time though most systems + * are configured for millisecond resolution, milliseconds is not guaranteed + * and is dependent on the system clock frequency and prescaler. Ticks_t should + * be declared as xTicks. * - * @sa xTaskParm - * @sa xMemAlloc() - * @sa xMemFree() + * @sa xTicks + * + */ +typedef UINT32_TYPE Ticks_t; + +/** + * @brief Data type for system ticks. * - * @warning The memory allocated for an instance of xTaskParm must be freed using xMemFree(). + * @sa Ticks_t * */ -typedef void TaskParm_t; +typedef Ticks_t xTicks; /** - * @brief Stub type definition for the message queue type. + * @brief Data type for a character. * - * The Queue_t type is a stub type definition for the internal message queue structure and is treated - * as a message queue handle by most of the message queue related system calls. The members of the data structure - * are not accessible. The Queue_t type should be declared as xQueue. + * The Char_t data type is used to store an 8-bit char and is + * typically used for char arrays for ASCII names (e.g., task name). + * Char_t should be declared as xChar. * - * @sa xQueue - * @sa xQueueDelete() + * @sa xChar + * + */ +typedef UCHAR_TYPE Char_t; + +/** + * @brief Data type for a character. * - * @warning The memory allocated for an instance of xQueue must be freed using xQueueDelete(). + * @sa Data_t * */ -typedef void Queue_t; +typedef Char_t xChar; + +/* START OF HANDLE TYPES */ /** - * @brief Stub type definition for the timer type. + * @brief Data type for a device handle. * - * The Timer_t type is a stub type definition for the internal timer data structure and is treated - * as a timer handle by most of the timer related system calls. The members of the data structure - * are not accessible. The Timer_t type should be declared as xTimer. + * The Device_t data type is used as a device handle. The device handle + * is created when xDeviceRegisterDevice() is called. For more information + * about devices and device drivers, see xDeviceRegisterDevice() for more + * information. Device_t should be declared as xDevice. * - * @sa xTimer - * @sa xTimerDelete() + * @sa xDevice + * @sa xDeviceRegisterDevice() * - * @warning The memory allocated for an instance of xTimer must be freed using xTimerDelete(). + */ +typedef VOID_TYPE Device_t; + +/** + * @brief Data type for a device handle. + * + * @sa Device_t * */ -typedef void Timer_t; +typedef Device_t *xDevice; /** - * @brief Type defintion for the memory address data type. + * @brief Data type for a task handle * - * The xAddr type is used to store a memory address and is used to pass memory - * addresses back and forth between system calls and the end-user application. It - * is not necessary to use the xAddr type within the end-user application as long - * as the type is not used to interact with the HeliOS kernel through system calls. + * The Task_t data type is used as a task handle. The task handle is created + * when xTaskCreate() is called. For more information about tasks, see xTaskCreate(). + * Task_t should be declared as xTask. * + * @sa xTask + * @sa xTaskCreate() + * @attention The memory referenced by the task handle must be freed by calling xTaskDelete(). + * @sa xTaskDelete() * */ -typedef void Addr_t; +typedef VOID_TYPE Task_t; /** - * @brief Type defintion for the memory address data type. - * - * The xAddr type is used to store a memory address and is used to pass memory - * addresses back and forth between system calls and the end-user application. It - * is not necessary to use the xAddr type within the end-user application as long - * as the type is not used to interact with the HeliOS kernel through system calls. + * @brief Data type for a task handle. * + * @sa Task_t + * @attention The memory referenced by the task handle must be freed by calling xTaskDelete(). + * @sa xTaskDelete() * */ -typedef Addr_t *xAddr; +typedef Task_t *xTask; /** - * @brief Type definition for the base data type. + * @brief Data type for a stream buffer handle. * - * A simple data type is often needed as an argument for a system call or a return type. - * The xBase type is used in such a case where there are no other structural data - * requirements is typically an unsigned 8-bit integer. + * The StreamBuffer_t data type is used as a stream buffer handle. The stream buffer + * handle is created when xStreamCreate() is called. For more information about + * stream buffers, see xStreamCreate(). Stream_t should be declared as xStream. * - * @sa Base_t + * @sa xStream + * @sa xStreamCreate() + * @attention The memory referenced by the stream buffer handle must be freed by calling xStreamDelete(). + * @sa xStreamDelete() * */ -typedef Base_t xBase; +typedef VOID_TYPE StreamBuffer_t; /** - * @brief Type defintion for the word data type + * @brief Data type for a stream buffer handle. * - * A word is a 32-bit data type in HeliOS. + * @sa StreamBuffer_t + * @attention The memory referenced by the stream buffer handle must be freed by calling xStreamDelete(). + * @sa xStreamDelete() * - * @sa Word_t */ -typedef Word_t xWord; +typedef StreamBuffer_t *xStreamBuffer; /** - * @brief Stub type definition for the timer type. - * - * The xTimer type is a stub type definition for the internal timer data structure and is treated - * as a timer handle by most of the timer related system calls. The members of the data structure - * are not accessible. + * @brief Data type for a queue handle. * - * @sa Timer_t - * @sa xTimerDelete() + * The Queue_t data type is used as a queue handle. The queue handle is created + * when xQueueCreate() is called. For more information about queues, see xQueueCreate(). + * Queue_t should be declared as xQueue. * - * @warning The memory allocated for an instance of xTimer must be freed using xTimerDelete(). + * @sa xQueue + * @sa xQueueCreate() + * @attention The memory referenced by the queue handle must be freed by calling xQueueDelete(). + * @sa xQueueDelete() * */ -typedef Timer_t *xTimer; +typedef VOID_TYPE Queue_t; /** - * @brief Stub type definition for the message queue type. - * - * The xQueue type is a stub type definition for the internal message queue structure and is treated - * as a message queue handle by most of the message queue related system calls. The members of the data structure - * are not accessible. + * @brief Data type for a queue handle. * * @sa Queue_t + * @attention The memory referenced by the queue handle must be freed by calling xQueueDelete(). * @sa xQueueDelete() * - * @warning The memory allocated for an instance of xQueue must be freed using xQueueDelete(). - * */ typedef Queue_t *xQueue; /** - * @brief Data structure for a message queue message. + * @brief Data type for a timer handle. * - * The xQueueMessage data structure contains the message queue message returned by xQueuePeek() and - * xQueueReceive(). See QueueMessage_t for information about the data structure's members. + * The Timer_t data type is used as a timer handle. The timer handle is created when xTimerCreate() + * is called. For more information about timers, see xTimerCreate(). Timer_t should be declared + * as xTimer. * - * @sa QueueMessage_t - * @sa xQueuePeek() - * @sa xQueueReceive() - * @sa xMemFree() - * @sa CONFIG_MESSAGE_VALUE_BYTES + * @sa xTimer + * @sa xTimerCreate() + * @attention The memory referenced by the timer handle must be freed by calling xTimerDelete(). + * @sa xTimerDelete() + * + */ +typedef VOID_TYPE Timer_t; + +/** + * @brief Data type for a timer handle. * - * @warning The memory allocated for an instance of xQueueMessage must be freed using xMemFree(). + * @sa Timer_t + * @attention The memory referenced by the timer handle must be freed by calling xTimerDelete(). + * @sa xTimerDelete() * */ -typedef QueueMessage_t *xQueueMessage; +typedef Timer_t *xTimer; + +/* START OF STRUCT TYPES */ /** - * @brief Data structure for direct to task notifications. + * @brief Data structure for a direct to task notification. * - * The xTaskNotification data structure contains the direct to task notification returned by xTaskNotifyTake(). - * See TaskNotification_t for information about the data structure's members. + * The TaskNotification_t data structure is used by xTaskNotifyGive() and xTaskNotifyTake() + * to send and receive direct to task notifications. Direct to task notifications are part of + * the event-driven multitasking model. A direct to task notifcation may be received by event-driven + * and co-operative tasks alike. However, the benefit of direct to task notifications may only be + * realized by tasks scheduled as event-driven. In order to wait for a direct to task notification, + * the task must be in a "waiting" state which is set by xTaskWait(). The TaskNotification_t type + * should be declared as xTaskNotification. * - * @sa TaskNotification_t - * @sa xTaskNotifyTake() + * @sa xTaskNotification + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). * @sa xMemFree() - * @sa CONFIG_NOTIFICATION_VALUE_BYTES + * @sa xTaskNotifyGive() + * @sa xTaskNotifyTake() + * @sa xTaskWait() * - * @warning The memory allocated for an instance of xTaskNotification must be freed using - * xMemFree(). + * @attention The notification value is *NOT* null terminated and thus Standard C Library string functions + * such as strcmp(), strcpy() and strlen(), which expect a null terminated char array, must not be used to + * manipulate the notification value. * */ -typedef TaskNotification_t *xTaskNotification; +typedef struct TaskNotification_s { + Base_t notificationBytes; /**< The length in bytes of the notification value which cannot exceed CONFIG_NOTIFICATION_VALUE_BYTES. */ + Char_t notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; /**< The notification value whose length is specified by the notification bytes member. */ +} TaskNotification_t; /** - * @brief Data structure for information about a task. + * @brief Data structure for a direct to task notification. * - * The xTaskInfo structure is similar to xTaskRunTimeStats in that it contains runtime statistics for - * a task. However, xTaskInfo also contains additional details about a task such as its identifier, ASCII name - * and state. The xTaskInfo structure is returned by xTaskGetTaskInfo(). If only runtime statistics are needed, - * xTaskRunTimeStats should be used because of its lower memory footprint. See TaskInfo_t for information about - * the data structure's members. - * - * @sa TaskInfo_t - * @sa xTaskGetTaskInfo() + * @sa TaskNotification_t + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). * @sa xMemFree() - * @sa CONFIG_TASK_NAME_BYTES - * - * @warning The memory allocated for an instance of xTaskInfo must be freed using - * xMemFree(). * */ -typedef TaskInfo_t *xTaskInfo; +typedef TaskNotification_t *xTaskNotification; /** * @brief Data structure for task runtime statistics. * - * The xTaskRunTimeStats structure contains task runtime statistics and is returned by - * xTaskGetAllRunTimeStats() and xTaskGetTaskRunTimeStats(). See TaskRunTimeStats_t for information - * about the data structure's members. + * The TaskRunTimeStats_t data structure is used by xTaskGetTaskRunTimeStats() and xTaskGetAllRuntimeStats() to obtain + * runtime statistics about a task. The TaskRunTimeStats_t type should be declared as xTaskRunTimeStats. * - * @sa TaskRunTimeStats_t + * @sa xTaskRunTimeStats * @sa xTaskGetTaskRunTimeStats() * @sa xTaskGetAllRunTimeStats() + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). * @sa xMemFree() * - * @warning The memory allocated for an instance of xTaskRunTimeStats must be freed - * using xMemFree(). + */ +typedef struct TaskRunTimeStats_s { + Base_t id; /**< The ID of the task referenced by the task handle. */ + Ticks_t lastRunTime; /**< The duration in ticks of the task's last runtime. */ + Ticks_t totalRunTime; /**< The duration in ticks of the task's total runtime. */ +} TaskRunTimeStats_t; + +/** + * @brief Data structure for task runtime statistics. + * + * @sa TaskRunTimeStats_t + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). + * @sa xMemFree() * */ typedef TaskRunTimeStats_t *xTaskRunTimeStats; /** - * @brief Data structure for statistics on a memory region. + * @brief Data structure for memory region statistics. * - * The xMemoryRegionStats data structure is used to store statistics about a HeliOS - * memory region. Statistics can be obtained for the heap and kernel memory regions. + * The MemoryRegionStats_t data structure is used by xMemGetHeapStats() and xMemGetKernelStats() + * to obtain statistics about either memory region. The MemoryRegionStats_t type should be declared + * as xMemoryRegionStats. * + * @sa xMemoryRegionStats * @sa xMemGetHeapStats() * @sa xMemGetKernelStats() + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). + * @sa xMemFree() + * + */ +typedef struct MemoryRegionStats_s { + Word_t largestFreeEntryInBytes; /**< The largest free entry in bytes. */ + Word_t smallestFreeEntryInBytes; /**< The smallest free entry in bytes. */ + Word_t numberOfFreeBlocks; /**< The number of free blocks - see CONFIG_MEMORY_REGION_BLOCK_SIZE for block size in bytes. */ + Word_t availableSpaceInBytes; /**< The amount of free memory in bytes (i.e., numberOfFreeBlocks * CONFIG_MEMORY_REGION_BLOCK_SIZE). */ + Word_t successfulAllocations; /**< Number of successful memory allocations. */ + Word_t successfulFrees; /**< Number of successful memory "frees". */ + Word_t minimumEverFreeBytesRemaining; /**< Lowest water lever since system initialization of free bytes of memory. */ +} MemoryRegionStats_t; + +/** + * @brief Data structure for memory region statistics. + * * @sa MemoryRegionStats_t + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). + * @sa xMemFree() * */ typedef MemoryRegionStats_t *xMemoryRegionStats; /** - * @brief Stub type definition for the task type. + * @brief Data structure for information about a task * - * The xTask type is a stub type definition for the internal task data structure and is treated - * as a task handle by most of the task related system calls. The members of the data structure - * are not accessible. + * The TaskInfo_t structure is similar to xTaskRuntimeStats_t in that it contains runtime statistics for + * a task. However, TaskInfo_t also contains additional details about a task such as its ASCII name + * and state. The TaskInfo_t structure is returned by xTaskGetTaskInfo() and xTaskGetAllTaskInfo(). + * If only runtime statistics are needed, then TaskRunTimeStats_t should be used because of its smaller + * memory footprint. The TaskInfo_t should be declared as xTaskInfo * - * @sa Task_t - * @sa xTaskCreate() - * @sa xTaskDelete() + * @sa xTaskInfo + * @sa xTaskGetTaskInfo() + * @sa xTaskGetAllTaskInfo() + * @sa CONFIG_TASK_NAME_BYTES + * @sa xMemFree() + * + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). * - * @warning The memory allocated for an instance of xTask must be freed by xTaskDelete() + * @attention The task name is *NOT* null terminated and thus Standard C Library string functions + * such as strcmp(), strcpy() and strlen(), which expect a null terminated char array, must not be used to + * manipulate the task name. * */ -typedef Task_t *xTask; +typedef struct TaskInfo_s { + Base_t id; /**< The task identifier which is used by xTaskGetHandleById() to return the task handle. */ + Char_t name[CONFIG_TASK_NAME_BYTES]; /**< The ASCII name of the task which is used by xTaskGetHandleByName() to return the task handle - this is *NOT* a null terminated char array. */ + TaskState_t state; /**< The state the task is in which is one of four states specified in the TaskState_t enumerated data type. */ + Ticks_t lastRunTime; /**< The duration in ticks of the task's last runtime. */ + Ticks_t totalRunTime; /**< The duration in ticks of the task's total runtime. */ +} TaskInfo_t; /** - * @brief Type definition for the task parameter. - * - * The xTaskParm type is used to pass a parameter to a task at the time of creation using - * xTaskCreate(). A task parameter is a pointer of type void and can point to any number - * of intrinsic types, arrays and/or user defined structures which can be passed to a - * task. It is up the the end-user to manage allocate and free the memory related to - * these objects using xMemAlloc() and xMemFree(). + * @brief Data structure for information about a task. * - * @sa TaskParm_t - * @sa xMemAlloc() + * @sa TaskInfo_t + * @attention The memory allocated for the data struture must be freed by calling xMemFree(). * @sa xMemFree() * - * @warning The memory allocated for an instance of xTaskParm must be freed using xMemFree(). - * */ -typedef TaskParm_t *xTaskParm; +typedef TaskInfo_t *xTaskInfo; /** - * @brief The type definition for time expressed in ticks. + * @brief Data structure for a queue message. * - * The xTicks type is used by several of the task and timer related system calls to express time. - * The unit of measure for time is always ticks. + * The QueueMessage_t stucture is used to store a queue message and is returned by xQueueReceive() and xQueuePeek(). + * The QueueMessage_t stucture should be declared as xQueueMessage. + * + * @sa xQueueMessage + * @sa xQueueReceive() + * @sa xQueuePeek() + * @sa CONFIG_MESSAGE_VALUE_BYTES + * @sa xMemFree() + * + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). + * + * @attention The message value is *NOT* null terminated and thus Standard C Library string functions + * such as strcmp(), strcpy() and strlen(), which expect a null terminated char array, must not be used to + * manipulate the message value. * - * @sa Ticks_t * */ -typedef Ticks_t xTicks; +typedef struct QueueMessage_s { + Base_t messageBytes; /**< The number of bytes contained in the message value which cannot exceed CONFIG_MESSAGE_VALUE_BYTES. */ + Char_t messageValue[CONFIG_MESSAGE_VALUE_BYTES]; /**< The ASCII queue message value - this is *NOT* a null terminated character array. */ +} QueueMessage_t; /** - * @brief Enumerated type for task states. + * @brief Data structure for a queue message. * - * A task can be in one of the four possible states defined in the TaskState_t - * enumerated type. The state of a task is changed by calling xTaskResume(), - * xTaskSuspend() or xTaskWait(). - * - * @sa TaskState_t - * @sa xTaskResume() - * @sa xTaskSuspend() - * @sa xTaskWait() + * @sa QueueMessage_t + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). + * @sa xMemFree() * */ -typedef TaskState_t xTaskState; +typedef QueueMessage_t *xQueueMessage; /** - * @brief Enumerated type for scheduler states. + * @brief Data structure for information about the HeliOS system. * - * The scheduler can be in one of four possible states defined in the SchedulerState_t - * enumerated type. The state of the scheduler is changed by calling xTaskSuspendAll() - * and xTaskResumeAll(). The state can be obtained by calling xTaskGetSchedulerState(). + * The SystemInfo_t data structure is used to store information about the HeliOS system and + * is returned by xSystemGetSystemInfo(). The SystemInfo_t structure should be declared as + * xSystemInfo. * - * @sa xSchedulerState - * @sa xTaskSuspendAll() - * @sa xTaskResumeAll() - * @sa xTaskGetSchedulerState() + * @sa xSystemInfo + * @sa xSystemGetSystemInfo() + * @sa OS_PRODUCT_NAME_SIZE + * @sa xMemFree() + * + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). + * + * @attention The product name is *NOT* null terminated and thus Standard C Library string functions + * such as strcmp(), strcpy() and strlen(), which expect a null terminated char array, must not be used to + * manipulate the product name. * */ -typedef SchedulerState_t xSchedulerState; +typedef struct SystemInfo_s { + Char_t productName[OS_PRODUCT_NAME_SIZE]; /**< The ASCII product name of the operating system (always "HeliOS"). */ + Base_t majorVersion; /**< The SemVer major version number of HeliOS. */ + Base_t minorVersion; /**< The SemVer minor version number of HeliOS. */ + Base_t patchVersion; /**< The SemVer patch version number of HeliOS. */ + Base_t numberOfTasks; /**< The number of tasks regardless of their state. */ +} SystemInfo_t; /** - * @brief Data structure for system informaiton. - * - * The xSystemInfo data structure contains information about the HeliOS system and is returned - * by xSystemGetSystemInfo(). See xSystemInfo_t for information about the data structure's members. + * @brief Data structure for information about the HeliOS system. * * @sa SystemInfo_t - * @sa xSystemGetSystemInfo() + * @attention The memory allocated for the data structure must be freed by calling xMemFree(). * @sa xMemFree() * - * @warning The memory allocated for an instance of xSystemInfo must be freed using xMemFree(). - * */ typedef SystemInfo_t *xSystemInfo; +#ifdef __cplusplus +extern "C" { +#endif + /** - * @brief A C macro to simplify casting and dereferencing a task paramater. - * - * When a task paramater is passed to a task, it is passed as a pointer of - * type void. To use the paramater, it must first be cast to the correct type - * and dereferenced. The following is an example of how the DEREF_TASKPARM() C - * macro simplifies that process. + * @brief System call to register a device driver. * - * @code {.c} - * void myTask_main(xTask task_, xTaskParm parm_) { - * int i; + * The xDeviceRegisterDevice() system call, as part of the HeliOS device driver model, registers a + * device driver with the HeliOS kernel. This system call must be made before a device driver can + * be called by xDeviceRead(), xDeviceWrite(), etc. If the device driver is successfully registered + * with the kernel, xDeviceRegisterDevice() will return RETURN_SUCCESS. Once a device is registered + * it cannot be un-registered - it can only be placed in a suspended state which is done by calling + * xDeviceConfigDevice(). However, as with most aspects of the device driver model in HeliOS, it is + * important to note that the implementation of the device state and mode is up to the device driver + * author. A quick word about device driver unique identifiers (uid). A device driver uid *MUST* be + * a globally unique identifier. No two device drivers in the same application can share the same uid. + * This is best achieved by ensuring the device driver author selects a uid for his device driver + * that is not in use by another device driver. A device driver template and pre-packaged device drivers + * can be found in /drivers. * - * i = DEREF_TASKPARM(int, parm_); + * @param device_self_register_ A pointer to the self registration function for the device driver. + * @return xBase If the device driver is successfully registered with the kernel, xDeviceRegisterDevice() + * returns RETURN_SUCCESS. Otherwise RETURN_FAILURE is returned.. + */ +xBase xDeviceRegisterDevice(xBase (*device_self_register_)()); + +/** + * @brief System call to check if a device is available * - * i++; + * The xDeviceIsAvailable() system call checks to see if a device driver is "available", generally + * for a read, write or read/write operation. What "available" means is up to the device driver author and + * may change based on what mode the device driver is in. For example, if the device driver is in read-only + * mode, then xDeviceIsAvailable() may return "true" if data is ready to be read from the device. A device + * driver template and pre-packaged device drivers can be found in /drivers. * - * DEREF_TASKPARM(int, parm_) = i; + * @param uid_ The unique identifier of the device driver. + * @return xBase If the device driver is "available", then "true" is returned. Otherwise "false" is returned. + */ +xBase xDeviceIsAvailable(const xHalfWord uid_); + +/** + * @brief System call to write fixed length data to a device. * - * return; - * } - * @endcode + * The xDeviceSimpleWrite() system call will write fixed length (one word) data to a device driver. Whether the + * data is written is dependent on the device driver mode, state and implementation of these features by the + * device driver author. A device driver template and pre-packaged device drives can be found in /drivers. * - * @param t The data type to cast the task paramater to (e.g., int). - * @param p The task pointer, typically named parm_. + * @param uid_ The unique identifier of the device driver + * @param data_ A pointer to the data to be written to the device - because xDeviceSimpleWrite() uses fixed length data, + * the pointer must reference a word of memory and the memory *MUST* be located in the heap memory region. + * @return xBase If the write operation was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. */ -#if !defined(DEREF_TASKPARM) -#define DEREF_TASKPARM(t, p) *(( t *) p ) -#endif +xBase xDeviceSimpleWrite(const xHalfWord uid_, xWord *data_); -/* In the event HeliOS is compiled with a C++ compiler, make the system calls (written in C) -visible to C++. */ -#ifdef __cplusplus -extern "C" { -#endif +/** + * @brief System call to write variable length data to a device. + * + * The xDeviceWrite() system call will write variable length data to a device driver. Whether the data is written + * is dependent on the device driver mode, state and implementation of these features by the device driver author. A + * device driver template and pre-packaged drivers an be found in /drivers. + * + * @param uid_ The unique identifier of the device driver. + * @param size_ The length (i.e., size) of the data to be written to the device. + * @param data_ A pointer to the data to be written to the device - because xDeviceWrite uses variable length data, + * the pointer must reference size_ bytes of memory and the memory *MUST* be located in the heap memory region. + * @return xBase If the write operation was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. + */ +xBase xDeviceWrite(const xHalfWord uid_, xSize *size_, xAddr data_); /** - * @brief System call to initialize the system. + * @brief System call to read fixed length data from a device. * - * The xSystemInit() system call initializes the required interrupt handlers and - * memory and must be called prior to calling any other system call. + * The xDeviceSimpleRead() system call will read fixed length (one word) data from a device driver. Whether the data + * is read is dependent on the device driver mode, state and implementation of these features by the device driver + * author. A device driver template and pre-packaged device drivers can be found in /drivers. + * + * @param uid_ The unique identifier of the device driver. + * @param data_ A pointer to the data buffer to read the data into from the device - because xDeviceSimpleRead() uses fixed + * length data, the pointer must reference a word of memory and the memory *MUST* be located in the heap memory region. + * @return xBase If the read operation was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. + */ +xBase xDeviceSimpleRead(const xHalfWord uid_, xWord *data_); + +/** + * @brief System call to read variable length data from a device. * + * The xDeviceRead() system call will read variable length data from a device driver. Whether the data is read + * is dependent on the device driver mode, state and implementation of these features by the device driver author. A + * device driver template and pre-packaged drivers can be found in /drivers. * + * @param uid_ The unique identifier of the device driver. + * @param size_ The number of bytes read from the device. + * @param data_ A pointer to the data buffer to read the data into from the device - because xDeviceRead() uses variable length data, + * the pointer must reference size_ bytes of memory and the memory *MUST* be located in the heap memory region. + * @return xBase If the read operation was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. */ -void xSystemInit(void); +xBase xDeviceRead(const xHalfWord uid_, xSize *size_, xAddr data_); /** - * @brief System call to handle assertions. + * @brief System call to initialize a device driver and its device. * - * The _SystemAssert_() system call handles assertions. The _SystemAssert_() system - * call should not be called directly. Instead, the SYSASSERT() macro should be used. - * The system assertion functionality will only work when the CONFIG_ENABLE_SYSTEM_ASSERT - * and CONFIG_SYSTEM_ASSERT_BEHAVIOR settings are defined. + * The xDeviceInitDevice() system call will initialize the device driver and its device. Like most aspects of the HeliOS device driver model, + * the implementation of this feature is dependent on the author of the device driver. Some device drivers may not implement this + * feature of the device driver model at all. A device driver template and pre-packaged drivers can be found in /drivers. * - * @sa SYSASSERT - * @sa CONFIG_ENABLE_SYSTEM_ASSERT - * @sa CONFIG_SYSTEM_ASSERT_BEHAVIOR + * @param uid_ The unique identifier of the device driver. + * @return xBase If the initialization of the device driver was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. + */ +xBase xDeviceInitDevice(const xHalfWord uid_); + +/** + * @brief System call to configure a device driver and its device. * - * @param file_ This is automatically defined by the compiler's definition of _FILE_ - * @param line_ This is automatically defined by the compiler's definition of _LINE_ + * The xDeviceConfigDevice() system call will configure the device driver and its device. Like most aspects of the HeliOS device driver model, + * the implementation of this feature is dependent on the author of the device driver. Some device drivers may not implement this + * feature of the device driver model at all. A device driver template and pre-packaged drivers can be found in /drivers. + * + * @param uid_ The unique identifier of the device driver. + * @param size_ The number of bytes (i.e., size) of the device configuration data structure. + * @param config_ A pointer to the size_ bytes of memory occupied by the configuration data structure - the memory *MUST* be located + * in the heap memory region. + * @return xBase If configuration of the device driver was successful, RETURN_SUCCESS is returned. Otherwise RETURN_FAILURE is returned. */ -void _SystemAssert_(const char *file_, int line_); +xBase xDeviceConfigDevice(const xHalfWord uid_, xSize *size_, xAddr config_); /** * @brief System call to allocate memory from the heap. @@ -651,6 +772,7 @@ void _SystemAssert_(const char *file_, int line_); * HeliOS uses a private "heap" which is actually static memory allocated at compile time. This * is done to maintain MISRA C:2012 compliance since standard library functions like malloc(), * calloc() and free() are not permitted. + * */ xAddr xMemAlloc(const xSize size_); @@ -666,9 +788,9 @@ xAddr xMemAlloc(const xSize size_); * * @warning xMemFree() cannot be used to free memory allocated for kernel objects. * Memory allocated by xTaskCreate(), xTimerCreate() or xQueueCreate() must - * be freed by their respective delete system calls (i.e., xTaskDelete()). + * be freed by their respective delete system calls (e.g., xTaskDelete()). */ -void xMemFree(const xAddr addr_); +void xMemFree(const volatile xAddr addr_); /** * @brief System call to return the amount of allocated heap memory. @@ -677,7 +799,7 @@ void xMemFree(const xAddr addr_); * that is currently allocated. Calls to xMemAlloc() increases and xMemFree() * decreases the amount of memory in use. * - * @return Size_t The amount of memory currently allocated in bytes. If no heap + * @return xSize The amount of memory currently allocated in bytes. If no heap * memory is currently allocated, xMemGetUsed() will return zero. * * @note xMemGetUsed() returns the amount of heap memory that is currently @@ -696,7 +818,7 @@ xSize xMemGetUsed(void); * * @param addr_ The address of the allocated heap memory to obtain the size of the * memory, in bytes, that is allocated. - * @return Size_t The amount of memory currently allocated to the specific address in bytes. If + * @return xSize The amount of memory currently allocated to the specific address in bytes. If * the address is invalid or null, xMemGetSize() will return zero. * * @note If the address addr_ points to a structure that, for example, is 48 bytes in size @@ -706,7 +828,7 @@ xSize xMemGetUsed(void); * heap and will return zero if it detects a consistency issue with the heap. Thus, xMemGetSize() * can be used to validate addresses before the objects they reference are accessed. */ -xSize xMemGetSize(const xAddr addr_); +xSize xMemGetSize(const volatile xAddr addr_); /** * @brief System call to obtain statistics on the heap. @@ -717,7 +839,7 @@ xSize xMemGetSize(const xAddr addr_); * @sa xMemoryRegionStats * * @return xMemoryRegionStats Returns the xMemoryRegionStats structure or null - * if unsuccesful. + * if unsuccessful. * * @warning The memory allocated by xMemGetHeapStats() must be freed by xMemFree(). */ @@ -733,7 +855,7 @@ xMemoryRegionStats xMemGetHeapStats(void); * @sa xMemoryRegionStats * * @return xMemoryRegionStats Returns the xMemoryRegionStats structure or null - * if unsuccesful. + * if unsuccessful. * * @warning The memory allocated by xMemGetKernelStats() must be freed by xMemFree(). */ @@ -756,7 +878,7 @@ xMemoryRegionStats xMemGetKernelStats(void); * * @warning The message queue memory can only be freed by xQueueDelete(). */ -xQueue xQueueCreate(xBase limit_); +xQueue xQueueCreate(const xBase limit_); /** * @brief System call to delete a message queue. @@ -782,7 +904,7 @@ void xQueueDelete(xQueue queue_); * @return xBase The number of messages in the queue. If unsuccessful or if the queue is empty, * xQueueGetLength() returns zero. */ -xBase xQueueGetLength(xQueue queue_); +xBase xQueueGetLength(const xQueue queue_); /** * @brief System call to check if the message queue is empty. @@ -794,7 +916,7 @@ xBase xQueueGetLength(xQueue queue_); * @return xBase True if the queue is empty. False if the queue has one or more messages. xQueueIsQueueEmpty() * will also return false if the queue parameter is invalid. */ -xBase xQueueIsQueueEmpty(xQueue queue_); +xBase xQueueIsQueueEmpty(const xQueue queue_); /** * @brief System call to check if the message queue is full. @@ -807,7 +929,7 @@ xBase xQueueIsQueueEmpty(xQueue queue_); * @return xBase True if the queue is full. False if the queue has zero. xQueueIsQueueFull() * will also return false if the queue parameter is invalid. */ -xBase xQueueIsQueueFull(xQueue queue_); +xBase xQueueIsQueueFull(const xQueue queue_); /** * @brief System call to check if there are message queue messages waiting. @@ -819,7 +941,7 @@ xBase xQueueIsQueueFull(xQueue queue_); * @return xBase True if one or more messages are waiting. False if there are no * messages waiting of the queue parameter is invalid. */ -xBase xQueueMessagesWaiting(xQueue queue_); +xBase xQueueMessagesWaiting(const xQueue queue_); /** * @brief System call to send a message using a message queue. @@ -841,7 +963,7 @@ xBase xQueueMessagesWaiting(xQueue queue_); * @return xBase xQueueSend() returns RETURN_SUCCESS if the message was sent to the queue successfully. Otherwise * RETURN_FAILURE if unsuccessful. */ -xBase xQueueSend(xQueue queue_, xBase messageBytes_, const char *messageValue_); +xBase xQueueSend(xQueue queue_, const xBase messageBytes_, const xChar *messageValue_); /** * @brief System call to peek at the next message in a message queue. @@ -858,7 +980,7 @@ xBase xQueueSend(xQueue queue_, xBase messageBytes_, const char *messageValue_); * * @warning The memory allocated by xQueuePeek() must be freed by xMemFree(). */ -xQueueMessage xQueuePeek(xQueue queue_); +xQueueMessage xQueuePeek(const xQueue queue_); /** * @brief System call to drop the next message in a message queue. @@ -908,39 +1030,130 @@ void xQueueLockQueue(xQueue queue_); void xQueueUnLockQueue(xQueue queue_); /** - * @brief System call to pass control to the HeliOS scheduler. + * @brief The xStreamCreate() system call will create a new stream buffer. * - * The xTaskStartScheduler() system call passes control to the HeliOS scheduler. This system - * call will not return until xTaskSuspendAll() is called. If xTaskSuspendAll() is called, xTaskResumeAll() - * must be called before xTaskStartScheduler() can be called again to continue executing tasks. + * The xStreamCreate() system call will create a new stream buffer. The + * memory for a stream buffer is allocated from kernel memory and therefor + * cannot be freed by calling xMemFree(). * + * @return xStreamBuffer The newly created stream buffer. + * + * @warning The stream buffer created by xStreamCreate() must + * be freed by calling xStreamDelete(). */ -void xTaskStartScheduler(void); +xStreamBuffer xStreamCreate(void); /** - * @brief System call to set scheduler state to running. + * @brief The xStreamDelete() system call will delete a stream buffer * - * The xTaskResumeAll() system call will set the scheduler state to running so the next - * call to xTaskStartScheduler() will resume execute of all tasks. The state of each task - * is not altered by xTaskSuspendAll() or xTaskResumeAll(). + * The xStreamDelete() system call will delete a stream buffer and + * free its memory. Once a stream buffer is deleted, it can not + * be written to or read from. * - * @sa xTaskSuspendAll() + * @param stream_ The stream buffer to operate on. */ -void xTaskResumeAll(void); +void xStreamDelete(const xStreamBuffer stream_); /** - * @brief System call to set the scheduler state to suspended. + * @brief The xStreamSend() system call will write one byte to the stream buffer * - * The xTaskSuspendAll() system call will set the scheduler state to suspended - * so the scheduler will stop and return. The state of each task is not altered by - * xTaskSuspendAll() or xTaskResumeAll(). + * The xStreamSend() system call will write one byte to the stream buffer. If the + * stream buffer's length is equal to CONFIG_STREAM_BUFFER_BYTES (i.e., full) then + * the byte will not be written to the stream buffer and xStreamSend() will return + * RETURN_FAILURE. * - * @sa xTaskResumeAll() + * @param stream_ The stream buffer to operate on. + * @param byte_ The byte to be sent to the stream buffer. + * @return xBase Returns RETURN_SUCCESS if the byte was successfully written to the + * stream buffer. Otherwise, returns RETURN_FAILURE. */ -void xTaskSuspendAll(void); +xBase xStreamSend(xStreamBuffer stream_, const xByte byte_); /** - * @brief The xSystemGetSystemInfo() system call will return the type xSystemInfo containing + * @brief The xStreamReceive() system call will return the contents of the stream buffer. + * + * The xStreamReceive() system call will return the contents of the stream buffer. The + * contents are returned as a byte array whose length is known by the bytes_ paramater. + * Because the byte array is stored in the heap, it must be freed by calling xMemFree(). + * + * @param stream_ The stream to operate on. + * @param bytes_ The number of bytes returned (i.e., length of the byte array) by xStreamReceive(). + * @return xByte* The byte array containing the contents of the stream buffer. + * + * @warning The byte array returned by xStreamReceive() must be freed by calling xMemFree(). + */ +xByte *xStreamReceive(const xStreamBuffer stream_, xHalfWord *bytes_); + +/** + * @brief The xStreamBytesAvailable() system call returns the length of the stream buffer. + * + * The xStreamBytesAvailable() system call will return the length of the stream buffer + * in bytes (i.e., bytes available to be received by xStreamReceive()). + * + * @param stream_ The stream to operate on. + * @return xHalfWord The length of the stream buffer in bytes. + */ +xHalfWord xStreamBytesAvailable(const xStreamBuffer stream_); + +/** + * @brief The xStreamReset() system call will reset a stream buffer. + * + * The xStreamRest() system call will clear the contents of the stream buffer + * and reset its length to zero. + * + * @param stream_ The stream buffer to operate on. + */ +void xStreamReset(const xStreamBuffer stream_); + +/** + * @brief The xStreamIsEmpty() system call returns true if the stream buffer is empty. + * + * The xStreamIsEmpty() system call is used to determine if the stream buffer is empty. + * A stream buffer is considered empty when it's length is equal to zero. If the buffer + * is greater than zero in length, xStreamIsEmpty() will return false. + * + * @param stream_ The stream buffer to operate on. + * @return xBase Returns true if the stream buffer length is equal to zero + * in length, otherwise xStreamIsEmpty() will return false. + */ +xBase xStreamIsEmpty(const xStreamBuffer stream_); + +/** + * @brief The xStreamIsFull() system call returns true if the stream buffer is full + * + * The xStreamIsFull() system call is used to determine if the stream buffer is full. + * A stream buffer is considered full when it's length is equal to CONFIG_STREAM_BUFFER_BYTES. + * If the buffer is less than CONFIG_STREAM_BUFFER_BYTES in length, xStreamIsFull() + * will return false. + * + * @param stream_ The stream buffer to operate on. + * @return xBase Returns true if the stream buffer is equal to CONFIG_STREAM_BUFFER_BYTES + * in length, otherwise xStreamIsFull() will return false. + */ +xBase xStreamIsFull(const xStreamBuffer stream_); + +/** + * @brief System call to initialize the system. + * + * The xSystemInit() system call initializes the required interrupt handlers and + * memory and must be called prior to calling any other system call. + * + */ +void xSystemInit(void); + +/** + * @brief The xSystemHalt() system call will halt HeliOS. + * + * The xSystemHalt() system call will halt HeliOS. Once xSystemHalt() is called, + * the system must be reset. + * + */ +void xSystemHalt(void); + +/** + * @brief The xSystemGetSystemInfo() system call will return information about the running system. + * + * The xSystemGetSystemInfo() system call will return the type xSystemInfo containing * information about the system including the OS (product) name, its version and how many tasks * are currently in the running, suspended or waiting states. * @@ -950,7 +1163,7 @@ void xTaskSuspendAll(void); * @sa xSystemInfo * @sa xMemFree() * - * @warning The memory allocated by the xSystemGetSystemInfo() must be freed with xMemFree() + * @warning The memory allocated by the xSystemGetSystemInfo() must be freed with xMemFree(). */ xSystemInfo xSystemGetSystemInfo(void); @@ -978,7 +1191,7 @@ xSystemInfo xSystemGetSystemInfo(void); * @warning xTaskCreate() MUST be called outside the scope of the HeliOS scheduler (i.e., not from a task's main). * The task memory can only be freed by xTaskDelete(). */ -xTask xTaskCreate(const char *name_, void (*callback_)(xTask, xTaskParm), xTaskParm taskParameter_); +xTask xTaskCreate(const xChar *name_, void (*callback_)(xTask task_, xTaskParm parm_), xTaskParm taskParameter_); /** * @brief System call to delete a task. @@ -990,7 +1203,7 @@ xTask xTaskCreate(const char *name_, void (*callback_)(xTask, xTaskParm), xTaskP * * @warning xTaskDelete() MUST be called outside the scope of the HeliOS scheduler (i.e., not from a task's main). */ -void xTaskDelete(xTask task_); +void xTaskDelete(const xTask task_); /** * @brief System call to get a task's handle by its ASCII name. @@ -1005,7 +1218,7 @@ void xTaskDelete(xTask task_); * @param name_ The ASCII name of the task to return the handle of. The task name is NOT a null terminated string. * @return xTask The task handle. xTaskGetHandleByName() returns null if the name cannot be found. */ -xTask xTaskGetHandleByName(const char *name_); +xTask xTaskGetHandleByName(const xChar *name_); /** * @brief System call to get a task's handle by its task identifier. @@ -1019,7 +1232,7 @@ xTask xTaskGetHandleByName(const char *name_); * @return xTask The task handle. xTaskGetHandleById() returns null if the the task identifier * cannot be found. */ -xTask xTaskGetHandleById(xBase id_); +xTask xTaskGetHandleById(const xBase id_); /** * @brief System call to return task runtime statistics for all tasks. @@ -1059,7 +1272,7 @@ xTaskRunTimeStats xTaskGetAllRunTimeStats(xBase *tasks_); * * @warning The memory allocated by xTaskGetTaskRunTimeStats() must be freed by xMemFree(). */ -xTaskRunTimeStats xTaskGetTaskRunTimeStats(xTask task_); +xTaskRunTimeStats xTaskGetTaskRunTimeStats(const xTask task_); /** * @brief System call to return the number of tasks regardless of their state. @@ -1085,7 +1298,7 @@ xBase xTaskGetNumberOfTasks(void); * * @warning The memory allocated by xTaskGetTaskInfo() must be freed by xMemFree(). */ -xTaskInfo xTaskGetTaskInfo(xTask task_); +xTaskInfo xTaskGetTaskInfo(const xTask task_); /** * @brief System call to return the details of all tasks. @@ -1102,7 +1315,7 @@ xTaskInfo xTaskGetTaskInfo(xTask task_); * * @warning The memory allocated by xTaskGetAllTaskInfo() must be freed by xMemFree(). */ -xTaskInfo *xTaskGetAllTaskInfo(xBase *tasks_); +xTaskInfo xTaskGetAllTaskInfo(xBase *tasks_); /** * @brief System call to return the state of a task. @@ -1115,7 +1328,7 @@ xTaskInfo *xTaskGetAllTaskInfo(xBase *tasks_); * @return xTaskState The xTaskState of the task. If the task cannot be found, xTaskGetTaskState() * will return null. */ -xTaskState xTaskGetTaskState(xTask task_); +xTaskState xTaskGetTaskState(const xTask task_); /** * @brief System call to return the ASCII name of a task. @@ -1129,12 +1342,12 @@ xTaskState xTaskGetTaskState(xTask task_); * @sa xMemFree() * * @param task_ The task to return the name of. - * @return char* A pointer to the char array containing the ASCII name of the task. The task name + * @return xChar* A pointer to the char array containing the ASCII name of the task. The task name * is NOT a null terminated char string. xTaskGetName() will return null if the task cannot be found. * * @warning The memory allocated by xTaskGetName() must be free by xMemFree(). */ -char *xTaskGetName(xTask task_); +xChar *xTaskGetName(const xTask task_); /** * @brief System call to return the task identifier for a task. @@ -1145,7 +1358,7 @@ char *xTaskGetName(xTask task_); * @return xBase The identifier of the task. If the task cannot be found, xTaskGetId() * returns zero (all tasks identifiers are 1 or greater). */ -xBase xTaskGetId(xTask task_); +xBase xTaskGetId(const xTask task_); /** * @brief System call to clear a waiting direct to task notification. @@ -1167,7 +1380,7 @@ void xTaskNotifyStateClear(xTask task_); * @return xBase Returns true if there is a task notification. False if there is no notification * or if the task could not be found. */ -xBase xTaskNotificationIsWaiting(xTask task_); +xBase xTaskNotificationIsWaiting(const xTask task_); /** * @brief System call to give another task a direct to task notification. @@ -1188,7 +1401,7 @@ xBase xTaskNotificationIsWaiting(xTask task_); * @param notificationValue_ A char array containing the notification value. The notification value is NOT a null terminated string. * @return xBase RETURN_SUCCESS if the direct to task notification was successfully given, RETURN_FAILURE if not. */ -Base_t xTaskNotifyGive(xTask task_, xBase notificationBytes_, const char *notificationValue_); +xBase xTaskNotifyGive(xTask task_, const xBase notificationBytes_, const xChar *notificationValue_); /** * @brief System call to take a direct to task notification from another task. @@ -1274,7 +1487,7 @@ void xTaskWait(xTask task_); * @param task_ The task to change the timer period for. * @param timerPeriod_ The timer period in ticks. */ -void xTaskChangePeriod(xTask task_, xTicks timerPeriod_); +void xTaskChangePeriod(xTask task_, const xTicks timerPeriod_); /** * @brief System call to get the task timer period. @@ -1290,7 +1503,7 @@ void xTaskChangePeriod(xTask task_, xTicks timerPeriod_); * @return xTicks The timer period in ticks. xTaskGetPeriod() will return zero * if the timer period is zero or if the task could not be found. */ -xTicks xTaskGetPeriod(xTask task_); +xTicks xTaskGetPeriod(const xTask task_); /** * @brief System call to reset the task timer. @@ -1306,6 +1519,40 @@ xTicks xTaskGetPeriod(xTask task_); */ void xTaskResetTimer(xTask task_); +/** + * @brief System call to pass control to the HeliOS scheduler. + * + * The xTaskStartScheduler() system call passes control to the HeliOS scheduler. This system + * call will not return until xTaskSuspendAll() is called. If xTaskSuspendAll() is called, xTaskResumeAll() + * must be called before xTaskStartScheduler() can be called again to continue executing tasks. + * + */ +void xTaskStartScheduler(void); + +/** + * @brief System call to set scheduler state to running. + * + * The xTaskResumeAll() system call will set the scheduler state to running so the next + * call to xTaskStartScheduler() will resume execute of all tasks. The state of each task + * is not altered by xTaskSuspendAll() or xTaskResumeAll(). + * + * @sa xTaskSuspendAll() + * + */ +void xTaskResumeAll(void); + +/** + * @brief System call to set the scheduler state to suspended. + * + * The xTaskSuspendAll() system call will set the scheduler state to suspended + * so the scheduler will stop and return. The state of each task is not altered by + * xTaskSuspendAll() or xTaskResumeAll(). + * + * @sa xTaskResumeAll() + * + */ +void xTaskSuspendAll(void); + /** * @brief System call to get the state of the scheduler. * @@ -1320,6 +1567,31 @@ void xTaskResetTimer(xTask task_); */ xSchedulerState xTaskGetSchedulerState(void); +/** + * @brief The xTaskChangeWDPeriod() will change the period on the task watchdog timer. + * + * The xTaskChangeWDPeriod() system call will change the task watchdog timer period. The period, + * measured in ticks, must be greater than zero to have any effect. If the tasks last runtime + * exceeds the task watchdog timer period, the task will automatically be placed in a suspended + * state. + * + * @sa xTaskGetWDPeriod() + * @param task_ The task to change the task watchdog timer for. + * @param wdTimerPeriod_ The task watchdog timer period which is measured in ticks. If zero, the task watchdog timer will not have any effect. + */ +void xTaskChangeWDPeriod(xTask task_, const xTicks wdTimerPeriod_); + +/** + * @brief The xTaskGetWDPeriod() return the current task watchdog timer. + * + * The xTaskGetWDPeriod() will return the current task watchdog timer for the task. + * + * @sa xTaskChangeWDPeriod() + * @param task_ The task to get the task watchdog timer period for. + * @return xTicks The task watchdog timer period which is measured in ticks. + */ +xTicks xTaskGetWDPeriod(const xTask task_); + /** * @brief System call to create a new timer. * @@ -1339,7 +1611,7 @@ xSchedulerState xTaskGetSchedulerState(void); * * @warning The timer memory can only be freed by xTimerDelete(). */ -xTimer xTimerCreate(xTicks timerPeriod_); +xTimer xTimerCreate(const xTicks timerPeriod_); /** * @brief System call will delete a timer. @@ -1351,7 +1623,7 @@ xTimer xTimerCreate(xTicks timerPeriod_); * * @param timer_ The timer to be deleted. */ -void xTimerDelete(xTimer timer_); +void xTimerDelete(const xTimer timer_); /** * @brief System call to change the period of a timer. @@ -1365,7 +1637,7 @@ void xTimerDelete(xTimer timer_); * @param timer_ The timer to change the period for. * @param timerPeriod_ The timer period in is ticks. Timer period must be zero or greater. */ -void xTimerChangePeriod(xTimer timer_, xTicks timerPeriod_); +void xTimerChangePeriod(xTimer timer_, const xTicks timerPeriod_); /** * @brief System call to get the period of a timer. @@ -1377,7 +1649,7 @@ void xTimerChangePeriod(xTimer timer_, xTicks timerPeriod_); * @return xTicks The timer period. If the timer cannot be found, xTimerGetPeriod() * will return zero. */ -xTicks xTimerGetPeriod(xTimer timer_); +xTicks xTimerGetPeriod(const xTimer timer_); /** * @brief System call to check if a timer is active. @@ -1390,7 +1662,7 @@ xTicks xTimerGetPeriod(xTimer timer_); * @param timer_ The timer to check if active. * @return xBase True if active, false if not active or if the timer could not be found. */ -xBase xTimerIsTimerActive(xTimer timer_); +xBase xTimerIsTimerActive(const xTimer timer_); /** * @brief System call to check if a timer has expired. @@ -1404,7 +1676,7 @@ xBase xTimerIsTimerActive(xTimer timer_); * @param timer_ The timer to determine if the period has expired. * @return xBase True if the timer has expired, false if the timer has not expired or could not be found. */ -xBase xTimerHasTimerExpired(xTimer timer_); +xBase xTimerHasTimerExpired(const xTimer timer_); /** * @brief System call to reset a timer. @@ -1429,7 +1701,9 @@ void xTimerReset(xTimer timer_); void xTimerStart(xTimer timer_); /** - * @brief The xTimerStop() system call will place the timer in the stopped state. Neither xTimerStart() nor + * @brief System call to stop a timer. + * + * The xTimerStop() system call will place the timer in the stopped state. Neither xTimerStart() nor * xTimerStop() will reset the timer. Timers can only be reset with xTimerReset(). * * @sa xTimerStart() @@ -1439,24 +1713,25 @@ void xTimerStart(xTimer timer_); */ void xTimerStop(xTimer timer_); -/** - * @brief The xSystemHalt() system call will halt HeliOS. - * - * The xSystemHalt() system call will halt HeliOS. Once xSystemHalt() is called, - * the system must be reset. - * - */ -void xSystemHalt(void); +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/* DO NOT USE - USE THE SYSASSERT() C MACRO INSTEAD! */ +void __SystemAssert__(const char *file_, int line_); +/* DO NOT USE - THESE ARE FOR UNIT TESTING! */ +#if defined(POSIX_ARCH_OTHER) +void __MemoryClear__(void); +void __SysStateClear__(void); +void __TimerStateClear__(void); +void __TaskStateClear__(void); +void __MemoryRegionDumpKernel__(void); +void __MemoryRegionDumpHeap__(void); +void __DeviceStateClear__(void); +#endif -#if defined(DEBUG_ON) -void _MemoryRegionDumpKernel_(void); -void _MemoryRegionDumpHeap_(void); #endif -/* In the event HeliOS is compiled with a C++ compiler, make the system calls (written in C) -visible to C++. */ #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/config.h b/src/config.h index bbaaef9..aa072b4 100644 --- a/src/config.h +++ b/src/config.h @@ -2,12 +2,12 @@ * @file config.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel header file for user definable settings - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +29,9 @@ /* The following configurable settings may be changed by the end-user -to customize the HeliOS kernel for their specific application. */ + to customize the HeliOS kernel for their specific application. */ + + /** * @brief Define to enable the Arduino API C++ interface. @@ -39,7 +41,7 @@ to customize the HeliOS kernel for their specific application. */ * unable to be written to the serial bus in applications using the * Arduino platform/tool-chain. The CONFIG_ENABLE_ARDUINO_CPP_INTERFACE * builds the included arduino.cpp file to allow the kernel to call the - * Arduino API through wrapper functions such as _ArduinoAssert_(). The + * Arduino API through wrapper functions such as __ArduinoAssert__(). The * arduino.cpp file can be found in the /extras directory. It must * be copied into the /src directory to be built. * @@ -50,10 +52,10 @@ to customize the HeliOS kernel for their specific application. */ * */ /* -#if !defined(CONFIG_ENABLE_ARDUINO_CPP_INTERFACE) -#define CONFIG_ENABLE_ARDUINO_CPP_INTERFACE -#endif -*/ + #if !defined(CONFIG_ENABLE_ARDUINO_CPP_INTERFACE) + #define CONFIG_ENABLE_ARDUINO_CPP_INTERFACE + #endif + */ @@ -70,10 +72,10 @@ to customize the HeliOS kernel for their specific application. */ * */ /* -#if !defined(CONFIG_ENABLE_SYSTEM_ASSERT) -#define CONFIG_ENABLE_SYSTEM_ASSERT -#endif -*/ + #if !defined(CONFIG_ENABLE_SYSTEM_ASSERT) + #define CONFIG_ENABLE_SYSTEM_ASSERT + #endif + */ @@ -86,22 +88,23 @@ to customize the HeliOS kernel for their specific application. */ * of output is generated over a serial or other interface. By default * the CONFIG_SYSTEM_ASSERT_BEHAVIOR is not defined. * - * @note In order to use the _ArduinoAssert_() functionality, the + * @note In order to use the __ArduinoAssert__() functionality, the * CONFIG_ENABLE_ARDUINO_CPP_INTERFACE setting must be enabled. * * @sa CONFIG_ENABLE_SYSTEM_ASSERT * @sa CONFIG_ENABLE_ARDUINO_CPP_INTERFACE * * @code {.c} - * #define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) _ArduinoAssert_( f , l ) + * #define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) __ArduinoAssert__( f , l ) * @endcode * */ /* -#if !defined(CONFIG_SYSTEM_ASSERT_BEHAVIOR) -#define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) _ArduinoAssert_( f , l ) -#endif -*/ + #if !defined(CONFIG_SYSTEM_ASSERT_BEHAVIOR) + #define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) __ArduinoAssert__( f , l ) + #endif + */ + /** @@ -122,7 +125,6 @@ to customize the HeliOS kernel for their specific application. */ - /** * @brief Define the size in bytes of the direct to task notification value. * @@ -140,7 +142,6 @@ to customize the HeliOS kernel for their specific application. */ - /** * @brief Define the size in bytes of the ASCII task name. * @@ -159,7 +160,6 @@ to customize the HeliOS kernel for their specific application. */ - /** * @brief Define the number of memory blocks available in all memory regions. * @@ -223,4 +223,50 @@ to customize the HeliOS kernel for their specific application. */ #define CONFIG_QUEUE_MINIMUM_LIMIT 0x5u /* 5 */ #endif + + +/** + * @brief Define the length of the stream buffer. + * + * Setting CONFIG_STREAM_BUFFER_BYTES will define the length + * of stream buffers created by xStreamCreate(). When the length + * of the stream buffer reaches this value, it is considered + * full and can no longer be written to by calling xStreamSend(). + * The default value is 32. The literal must be appended with "u" to maintain + * MISRA C:2012 compliance. + * + */ +#if !defined(CONFIG_STREAM_BUFFER_BYTES) +#define CONFIG_STREAM_BUFFER_BYTES 0x20u /* 32 */ +#endif + + + +/** + * @brief Enable task watchdog timers. + * + * Defining CONFIG_TASK_WD_TIMER_ENABLE will enable the + * task watchdog timer feature. The default is enabled. + * + */ +#if !defined(CONFIG_TASK_WD_TIMER_ENABLE) +#define CONFIG_TASK_WD_TIMER_ENABLE +#endif + + + +/** + * @brief Define the length of a device driver name. + * + * Setting CONFIG_DEVICE_NAME_BYTES will define the length + * of a device driver name. The name of device drivers + * should be exactly this length. There really isn't + * a reason to change this and doing so may break + * existing device drivers. The default length + * is 8 bytes. + * + */ +#if !defined(CONFIG_DEVICE_NAME_BYTES) +#define CONFIG_DEVICE_NAME_BYTES 0x8u /* 8 */ +#endif #endif \ No newline at end of file diff --git a/src/defines.h b/src/defines.h index 6275f10..84db627 100644 --- a/src/defines.h +++ b/src/defines.h @@ -2,12 +2,12 @@ * @file defines.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel header for macros and definitions - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,8 +33,9 @@ #include + /* Check that the system HeliOS is being targeted for has an -8-bit wide byte. */ + 8-bit wide byte. */ #if !defined(CHAR_BIT) #pragma message("WARNING: Unable to determine if system has an 8-bit wide byte. CHAR_BIT not defined?") #else @@ -45,7 +46,6 @@ - /* Define "true" if not defined. */ #if !defined(true) #define true 0x1u /* 1 */ @@ -53,7 +53,6 @@ - /* Define "false" if not defined. */ #if !defined(false) #define false 0x0u /* 0 */ @@ -61,7 +60,6 @@ - /* Define "NULL" if not defined. */ #if !defined(NULL) #if !defined(__cplusplus) @@ -73,7 +71,6 @@ - /* Define "zero" if not defined. */ #if !defined(zero) #define zero 0x0u /* 0 */ @@ -81,34 +78,30 @@ - /* Define a general return failure for -return values. */ + return values. */ #if !defined(RETURN_FAILURE) #define RETURN_FAILURE 0x0u /* 0 */ #endif - /* Define a general return success -for return values. */ + for return values. */ #if !defined(RETURN_SUCCESS) #define RETURN_SUCCESS 0x1u /* 1 */ #endif - /* Define the size in bytes of the OS product name which is accessible through -xSystemGetSystemInfo(). */ + xSystemGetSystemInfo(). */ #if !defined(OS_PRODUCT_NAME_SIZE) #define OS_PRODUCT_NAME_SIZE 0x6u /* 6 */ #endif - /* Define the OS product name which is accessible through xSystemGetSystemInfo(). */ #if !defined(OS_PRODUCT_NAME) #define OS_PRODUCT_NAME "HeliOS" @@ -116,123 +109,176 @@ xSystemGetSystemInfo(). */ - /* Define the OS product major version number which is accessible through -xSystemGetSystemInfo(). */ + xSystemGetSystemInfo(). */ #if !defined(OS_MAJOR_VERSION_NO) #define OS_MAJOR_VERSION_NO 0x0u /* 0 */ #endif - /* Define the OS product minor version number which is accessible through -xSystemGetSystemInfo(). */ + xSystemGetSystemInfo(). */ #if !defined(OS_MINOR_VERSION_NO) #define OS_MINOR_VERSION_NO 0x3u /* 3 */ #endif - /* Define the OS product patch version number which is accessible through -xSystemGetSystemInfo(). */ + xSystemGetSystemInfo(). */ #if !defined(OS_PATCH_VERSION_NO) -#define OS_PATCH_VERSION_NO 0x4u /* 4 */ +#define OS_PATCH_VERSION_NO 0x5u /* 5 */ #endif /* Define the raw size of the heap in bytes based on the number of blocks -the heap contains and the size of each block in bytes. */ + the heap contains and the size of each block in bytes. */ #if !defined(MEMORY_REGION_SIZE_IN_BYTES) -#define MEMORY_REGION_SIZE_IN_BYTES CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE +#define MEMORY_REGION_SIZE_IN_BYTES CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS *CONFIG_MEMORY_REGION_BLOCK_SIZE #endif /* Define a macro to access the running system flag which is used -by xTaskStartScheduler() to indicate whether the scheduler is -running. */ + by xTaskStartScheduler() to indicate whether the scheduler is + running. */ #if !defined(SYSFLAG_RUNNING) #define SYSFLAG_RUNNING() sysFlags.running #endif - /* Define a macro to access the overflow system flag which is used -by the scheduler to determine when a task's runtime has overflowed -and all runtimes need to be reset. */ + by the scheduler to determine when a task's runtime has overflowed + and all runtimes need to be reset. */ #if !defined(SYSFLAG_OVERFLOW) #define SYSFLAG_OVERFLOW() sysFlags.overflow #endif - /* Define a macro to access the corrupt system flag which is used -by the memory management system calls to flag if corruption -of the heap has been detected. */ -#if !defined(SYSFLAG_CORRUPT) -#define SYSFLAG_CORRUPT() sysFlags.corrupt + by the memory management system calls to flag if corruption + of the heap has been detected. */ +#if !defined(SYSFLAG_FAULT) +#define SYSFLAG_FAULT() sysFlags.fault #endif /* Define a marco which makes null pointer checks more readable and -concise */ + concise */ #if !defined(ISNOTNULLPTR) -#define ISNOTNULLPTR(addr_) ((NULL) != ( addr_ )) +#define ISNOTNULLPTR(addr_) ((NULL) != (addr_)) #endif - /* Define a marco which makes null pointer checks more readable and -concise */ + concise */ #if !defined(ISNULLPTR) -#define ISNULLPTR(addr_) ((NULL) == ( addr_ )) +#define ISNULLPTR(addr_) ((NULL) == (addr_)) #endif - /* Define a macro to assert if assertions are enabled through -the CONFIG_ENABLE_SYSTEM_ASSERT setting. */ + the CONFIG_ENABLE_SYSTEM_ASSERT setting. */ #if !defined(SYSASSERT) #if !defined(CONFIG_ENABLE_SYSTEM_ASSERT) #define SYSASSERT(expr_) #else -#define SYSASSERT(expr_) if (false == ( expr_ )) _SystemAssert_( __FILE__ , __LINE__ ) +#define SYSASSERT(expr_) \ + if (false == (expr_)) \ + __SystemAssert__(__FILE__, __LINE__) #endif #endif + #if !defined(MEMORY_REGION_CHECK_OPTION_WO_ADDR) #define MEMORY_REGION_CHECK_OPTION_WO_ADDR 0x1u /* 1 */ #endif + #if !defined(MEMORY_REGION_CHECK_OPTION_W_ADDR) #define MEMORY_REGION_CHECK_OPTION_W_ADDR 0x2u /* 2 */ #endif - /* Define a macro to convert a heap memory address to it's corresponding -heap entry. */ + heap entry. */ #if !defined(ADDR2ENTRY) -#define ADDR2ENTRY(addr_, region_) (MemoryEntry_t *)((Byte_t *)( addr_ ) - (( region_ )->entrySize * CONFIG_MEMORY_REGION_BLOCK_SIZE)) +#define ADDR2ENTRY(addr_, region_) (MemoryEntry_t *)((Byte_t *)(addr_) - ((region_)->entrySize * CONFIG_MEMORY_REGION_BLOCK_SIZE)) #endif /* Define a macro to convert a heap entry to it's corresponding heap memory -address. */ + address. */ #if !defined(ENTRY2ADDR) -#define ENTRY2ADDR(addr_, region_) (Addr_t *)((Byte_t *)( addr_ ) + (( region_ )->entrySize * CONFIG_MEMORY_REGION_BLOCK_SIZE)) +#define ENTRY2ADDR(addr_, region_) (Addr_t *)((Byte_t *)(addr_) + ((region_)->entrySize * CONFIG_MEMORY_REGION_BLOCK_SIZE)) +#endif + + + +#if defined(UCHAR_TYPE) +#undef UCHAR_TYPE +#define UCHAR_TYPE unsigned char +#else +#define UCHAR_TYPE unsigned char +#endif + + + +#if defined(UINT8_TYPE) +#undef UINT8_TYPE +#define UINT8_TYPE uint8_t +#else +#define UINT8_TYPE uint8_t +#endif + + + +#if defined(UINT16_TYPE) +#undef UINT16_TYPE +#define UINT16_TYPE uint16_t +#else +#define UINT16_TYPE uint16_t +#endif + + + +#if defined(UINT32_TYPE) +#undef UINT32_TYPE +#define UINT32_TYPE uint32_t +#else +#define UINT32_TYPE uint32_t +#endif + + +#if defined(SIZE_TYPE) +#undef SIZE_TYPE +#define SIZE_TYPE size_t +#else +#define SIZE_TYPE size_t +#endif + + +#if defined(VOID_TYPE) +#undef VOID_TYPE +#define VOID_TYPE void +#else +#define VOID_TYPE void +#endif + + +#if !defined(DEREF_TASKPARM) +#define DEREF_TASKPARM(t, p) *((t *)p) #endif #endif \ No newline at end of file diff --git a/src/device.c b/src/device.c new file mode 100644 index 0000000..2893538 --- /dev/null +++ b/src/device.c @@ -0,0 +1,545 @@ +/** + * @file device.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief Kernel source code for device drivers + * @version 0.3.5 + * @date 2022-09-01 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "device.h" + +static DeviceList_t *deviceList = NULL; + + +static Device_t *__DeviceListFind__(const HalfWord_t uid_); + + + + +Base_t xDeviceRegisterDevice(Base_t (*device_self_register_)()) { + + Base_t ret = RETURN_FAILURE; + + SYSASSERT(ISNOTNULLPTR(device_self_register_)); + + if (ISNOTNULLPTR(device_self_register_)) { + + ret = (*device_self_register_)(); + + SYSASSERT(RETURN_SUCCESS == ret); + } + + + return ret; +} + + + +Base_t __RegisterDevice__(const HalfWord_t uid_, + const Char_t *name_, + const DeviceState_t state_, + const DeviceMode_t mode_, + Base_t (*init_)(Device_t *device_), + Base_t (*config_)(Device_t *device_, Size_t *size_, Addr_t *config_), + Base_t (*read_)(Device_t *device_, Size_t *size_, Addr_t *data_), + Base_t (*write_)(Device_t *device_, Size_t *size_, Addr_t *data_), + Base_t (*simple_read_)(Device_t *device_, Word_t *data_), + Base_t (*simple_write_)(Device_t *device_, Word_t *data_)) { + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Device_t *cursor = NULL; + + + SYSASSERT((zero < uid_) && (ISNOTNULLPTR(name_)) && (ISNOTNULLPTR(init_)) && (ISNOTNULLPTR(config_)) && + (ISNOTNULLPTR(read_)) && (ISNOTNULLPTR(write_))); + + if (((zero < uid_) && (ISNOTNULLPTR(name_)) && (ISNOTNULLPTR(init_)) && (ISNOTNULLPTR(config_)) && + (ISNOTNULLPTR(read_)) && (ISNOTNULLPTR(write_)))) { + + + if (ISNULLPTR(deviceList)) { + + deviceList = (DeviceList_t *)__KernelAllocateMemory__(sizeof(DeviceList_t)); + } + + + SYSASSERT(ISNOTNULLPTR(deviceList)); + + if (ISNOTNULLPTR(deviceList)) { + + device = __DeviceListFind__(uid_); + + SYSASSERT(ISNULLPTR(device)); + + if (ISNULLPTR(device)) { + + device = (Device_t *)__KernelAllocateMemory__(sizeof(Device_t)); + + + + SYSASSERT(ISNOTNULLPTR(device)); + + + + if (ISNOTNULLPTR(device)) { + + device->uid = uid_; + __memcpy__(device->name, name_, CONFIG_DEVICE_NAME_BYTES); + device->state = state_; + device->mode = mode_; + device->bytesWritten = zero; + device->bytesRead = zero; + device->available = false; + device->init = init_; + device->config = config_; + device->read = read_; + device->write = write_; + device->simple_read = simple_read_; + device->simple_write = simple_write_; + + + + cursor = deviceList->head; + + + if (ISNOTNULLPTR(deviceList->head)) { + + + while (ISNOTNULLPTR(cursor->next)) { + + + cursor = cursor->next; + } + + cursor->next = device; + + } else { + + deviceList->head = device; + } + + deviceList->length++; + + ret = RETURN_SUCCESS; + } + } + } + } + + return ret; +} + + + +Base_t xDeviceIsAvailable(const HalfWord_t uid_) { + + + Base_t ret = false; + + Device_t *device = NULL; + + SYSASSERT(zero < uid_); + + + + if (zero < uid_) { + + device = __DeviceListFind__(uid_); + + + SYSASSERT(ISNOTNULLPTR(device)); + + if (ISNOTNULLPTR(device)) { + + ret = device->available; + } + } + + return ret; +} + + + +Base_t xDeviceSimpleWrite(const HalfWord_t uid_, Word_t *data_) { + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Word_t *data = NULL; + + SYSASSERT(zero < uid_); + + SYSASSERT(ISNOTNULLPTR(data_)); + + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + if ((zero < uid_) && (ISNOTNULLPTR(data_)) && (RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR))) { + + + device = __DeviceListFind__(uid_); + + + SYSASSERT(ISNOTNULLPTR(device)); + + if (ISNOTNULLPTR(device)) { + + SYSASSERT(((DeviceModeReadWrite == device->mode) || (DeviceModeWriteOnly == device->mode)) && (DeviceStateRunning == device->state)); + + if (((DeviceModeReadWrite == device->mode) || (DeviceModeWriteOnly == device->mode)) && (DeviceStateRunning == device->state)) { + + data = (Word_t *)__KernelAllocateMemory__(sizeof(Word_t)); + + SYSASSERT(ISNOTNULLPTR(data)); + + if (ISNOTNULLPTR(data)) { + + __memcpy__(data, data_, sizeof(Word_t)); + + ret = (*device->simple_write)(device, data); + + device->bytesWritten += sizeof(Word_t); + + SYSASSERT(RETURN_SUCCESS == ret); + + __KernelFreeMemory__(data); + } + } + } + } + + + + return ret; +} + + + +Base_t xDeviceWrite(const HalfWord_t uid_, Size_t *size_, Addr_t *data_) { + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Byte_t *data = NULL; + + SYSASSERT(zero < uid_); + + SYSASSERT(ISNOTNULLPTR(size_)); + + SYSASSERT(zero < *size_); + + SYSASSERT(ISNOTNULLPTR(data_)); + + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + if ((zero < uid_) && (ISNOTNULLPTR(size_)) && (zero < *size_) && (ISNOTNULLPTR(data_)) && (RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR))) { + + + device = __DeviceListFind__(uid_); + + + SYSASSERT(ISNOTNULLPTR(device)); + + if (ISNOTNULLPTR(device)) { + + SYSASSERT(((DeviceModeReadWrite == device->mode) || (DeviceModeWriteOnly == device->mode)) && (DeviceStateRunning == device->state)); + + if (((DeviceModeReadWrite == device->mode) || (DeviceModeWriteOnly == device->mode)) && (DeviceStateRunning == device->state)) { + + data = (Byte_t *)__KernelAllocateMemory__(*size_); + + SYSASSERT(ISNOTNULLPTR(data)); + + if (ISNOTNULLPTR(data)) { + + __memcpy__(data, data_, *size_); + + ret = (*device->write)(device, size_, data); + + device->bytesWritten += *size_; + + SYSASSERT(RETURN_SUCCESS == ret); + + __KernelFreeMemory__(data); + } + } + } + } + + + + return ret; +} + + + +Base_t xDeviceSimpleRead(const HalfWord_t uid_, Word_t *data_) { + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Word_t *data = NULL; + + SYSASSERT(zero < uid_); + + + SYSASSERT(ISNOTNULLPTR(data_)); + + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + if ((zero < uid_) && (ISNOTNULLPTR(data_)) && (RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR))) { + + + device = __DeviceListFind__(uid_); + + + SYSASSERT(ISNOTNULLPTR(device)); + + if (ISNOTNULLPTR(device)) { + + SYSASSERT(((DeviceModeReadWrite == device->mode) || (DeviceModeReadOnly == device->mode)) && (DeviceStateRunning == device->state)); + + if (((DeviceModeReadWrite == device->mode) || (DeviceModeReadOnly == device->mode)) && (DeviceStateRunning == device->state)) { + + data = (Word_t *)__KernelAllocateMemory__(sizeof(Word_t)); + + SYSASSERT(ISNOTNULLPTR(data)); + + if (ISNOTNULLPTR(data)) { + + ret = (*device->simple_read)(device, data); + + __memcpy__(data_, data, sizeof(Word_t)); + + device->bytesRead += sizeof(Word_t); + + SYSASSERT(RETURN_SUCCESS == ret); + + __KernelFreeMemory__(data); + } + } + } + } + + + + return ret; +} + + + +Base_t xDeviceRead(const HalfWord_t uid_, Size_t *size_, Addr_t *data_) { + + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Addr_t *data = NULL; + + SYSASSERT(zero < uid_); + + SYSASSERT(ISNOTNULLPTR(size_)); + + SYSASSERT(zero < *size_); + + SYSASSERT(ISNOTNULLPTR(data_)); + + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + if ((zero < uid_) && (ISNOTNULLPTR(size_)) && (zero < *size_) && (ISNOTNULLPTR(data_)) && (RETURN_SUCCESS == __MemoryRegionCheckHeap__(data_, MEMORY_REGION_CHECK_OPTION_W_ADDR))) { + + + device = __DeviceListFind__(uid_); + + + SYSASSERT(ISNOTNULLPTR(device)); + + if (ISNOTNULLPTR(device)) { + + SYSASSERT(((DeviceModeReadWrite == device->mode) || (DeviceModeReadOnly == device->mode)) && (DeviceStateRunning == device->state)); + + if (((DeviceModeReadWrite == device->mode) || (DeviceModeReadOnly == device->mode)) && (DeviceStateRunning == device->state)) { + + data = (Byte_t *)__KernelAllocateMemory__(*size_); + + SYSASSERT(ISNOTNULLPTR(data)); + + if (ISNOTNULLPTR(data)) { + + ret = (*device->read)(device, size_, data); + + __memcpy__(data_, data, *size_); + + device->bytesRead += *size_; + + SYSASSERT(RETURN_SUCCESS == ret); + + __KernelFreeMemory__(data); + } + } + } + } + + + + return ret; +} + + + +static Device_t *__DeviceListFind__(const HalfWord_t uid_) { + + + Device_t *ret = NULL; + + Device_t *cursor = NULL; + + + SYSASSERT(ISNOTNULLPTR(deviceList)); + + + SYSASSERT(zero < uid_); + + + if ((ISNOTNULLPTR(deviceList)) && (zero < uid_)) { + + + + cursor = deviceList->head; + + + while ((ISNOTNULLPTR(cursor)) && (cursor->uid != uid_)) { + + cursor = cursor->next; + } + + + SYSASSERT(ISNOTNULLPTR(cursor)); + + + if (ISNOTNULLPTR(cursor)) { + + + ret = cursor; + } + } + + return ret; +} + + + +Base_t xDeviceInitDevice(const HalfWord_t uid_) { + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + SYSASSERT(zero < uid_); + + if (zero < uid_) { + + device = __DeviceListFind__(uid_); + + SYSASSERT(ISNOTNULLPTR(device)); + + + if (ISNOTNULLPTR(device)) { + + ret = (*device->init)(device); + + SYSASSERT(RETURN_SUCCESS == ret); + } + } + + + return ret; +} + + + +Base_t xDeviceConfigDevice(const HalfWord_t uid_, Size_t *size_, Addr_t *config_) { + + + Base_t ret = RETURN_FAILURE; + + Device_t *device = NULL; + + Addr_t *config = NULL; + + SYSASSERT(zero < uid_); + + SYSASSERT(zero < *size_); + + SYSASSERT(ISNOTNULLPTR(config_)); + + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckHeap__(config_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + if ((zero < uid_) && (zero < *size_) && (ISNOTNULLPTR(config_)) && (RETURN_SUCCESS == __MemoryRegionCheckHeap__(config_, MEMORY_REGION_CHECK_OPTION_W_ADDR))) { + + device = __DeviceListFind__(uid_); + + SYSASSERT(ISNOTNULLPTR(device)); + + + if (ISNOTNULLPTR(device)) { + + config = (Addr_t *)__KernelAllocateMemory__(*size_); + + SYSASSERT(ISNOTNULLPTR(config)); + + if (ISNOTNULLPTR(config)) { + + __memcpy__(config, config_, *size_); + + + ret = (*device->config)(device, size_, config); + + + __memcpy__(config_, config, *size_); + + + SYSASSERT(RETURN_SUCCESS == ret); + + __KernelFreeMemory__(config); + } + } + } + + + return ret; +} + + + +#if defined(POSIX_ARCH_OTHER) +void __DeviceStateClear__(void) { + + deviceList = NULL; + + return; +} +#endif \ No newline at end of file diff --git a/src/device.h b/src/device.h new file mode 100644 index 0000000..5677767 --- /dev/null +++ b/src/device.h @@ -0,0 +1,70 @@ +/** + * @file device.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief Kernel source code for device drivers + * @version 0.3.5 + * @date 2022-09-01 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef DEVICE_H_ +#define DEVICE_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +Base_t xDeviceRegisterDevice(Base_t (*device_self_register_)()); +Base_t __RegisterDevice__(const HalfWord_t uid_, + const Char_t *name_, + const DeviceState_t state_, + const DeviceMode_t mode_, + Base_t (*init_)(Device_t *device_), + Base_t (*config_)(Device_t *device_, Size_t *size_, Addr_t *config_), + Base_t (*read_)(Device_t *device_, Size_t *size_, Addr_t *data_), + Base_t (*write_)(Device_t *device_, Size_t *size_, Addr_t *data_), + Base_t (*simple_read_)(Device_t *device_, Word_t *data_), + Base_t (*simple_write_)(Device_t *device_, Word_t *data_)); +Base_t xDeviceIsAvailable(const HalfWord_t uid_); +Base_t xDeviceSimpleWrite(const HalfWord_t uid_, Word_t *data_); +Base_t xDeviceWrite(const HalfWord_t uid_, Size_t *size_, Addr_t *data_); +Base_t xDeviceSimpleRead(const HalfWord_t uid_, Word_t *data_); +Base_t xDeviceRead(const HalfWord_t uid_, Size_t *size_, Addr_t *data_); +Base_t xDeviceInitDevice(const HalfWord_t uid_); +Base_t xDeviceConfigDevice(const HalfWord_t uid_, Size_t *size_, Addr_t *config_); + +#if defined(POSIX_ARCH_OTHER) +void __DeviceStateClear__(void); +#endif + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/mem.c b/src/mem.c index bbf3d4a..b8b08ec 100644 --- a/src/mem.c +++ b/src/mem.c @@ -2,12 +2,12 @@ * @file mem.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for memory management - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,49 +23,52 @@ * along with this program. If not, see . * */ - #include "mem.h" +static volatile MemoryRegion_t heap; + +static volatile MemoryRegion_t kernel; +static Base_t __MemoryRegionCheck__(const volatile MemoryRegion_t *region_, const volatile Addr_t *addr_, const Base_t option_); +static Base_t __MemoryRegionCheckAddr__(const volatile MemoryRegion_t *region_, const volatile Addr_t *addr_); +static Addr_t *__calloc__(volatile MemoryRegion_t *region_, const Size_t size_); +static void __free__(volatile MemoryRegion_t *region_, const volatile Addr_t *addr_); +static MemoryRegionStats_t *__MemGetRegionStats__(const volatile MemoryRegion_t *region_); +static void __DefragMemoryRegion__(const volatile MemoryRegion_t *region_); -static volatile MemoryRegion_t heap = { - .entrySize = zero, - .start = NULL, - .allocations = zero, - .frees = zero, - .minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE}; +void __MemoryInit__(void) { + __memset__(&heap, 0x0, sizeof(MemoryRegion_t)); + heap.minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE; -static volatile MemoryRegion_t kernel = { - .entrySize = zero, - .start = NULL, - .allocations = zero, - .frees = zero, - .minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE}; + __memset__(&kernel, 0x0, sizeof(MemoryRegion_t)); + kernel.minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE; + return; +} /* System call used by end-user tasks to allocate memory -from the heap memory region. */ + from the heap memory region. */ Addr_t *xMemAlloc(const Size_t size_) { - /* Just call _calloc_() with the heap memory region - to allocate memory from the heap. */ - return _calloc_(&heap, size_); + /* Just call __calloc__() with the heap memory region + to allocate memory from the heap. */ + return __calloc__(&heap, size_); } /* System call used by end-user tasks to free memory from -the heap memory region. */ -void xMemFree(const Addr_t *addr_) { + the heap memory region. */ +void xMemFree(const volatile Addr_t *addr_) { - /* Just call _free_() with the heap memory region to free - from the heap. */ - _free_(&heap, addr_); + /* Just call __free__() with the heap memory region to free + from the heap. */ + __free__(&heap, addr_); return; } @@ -73,7 +76,7 @@ void xMemFree(const Addr_t *addr_) { /* System call to find out how much memory is allocated -in the heap memory region. */ + in the heap memory region. */ Size_t xMemGetUsed(void) { @@ -83,39 +86,39 @@ Size_t xMemGetUsed(void) { MemoryEntry_t *cursor = NULL; - HWord_t used = zero; + HalfWord_t used = zero; /* Assert if any memory region is corrupt. */ - SYSASSERT(false == SYSFLAG_CORRUPT()); + SYSASSERT(false == SYSFLAG_FAULT()); /* Check to make sure no memory regions are - corrupt before we do anything. */ - if (false == SYSFLAG_CORRUPT()) { + corrupt before we do anything. */ + if (false == SYSFLAG_FAULT()) { /* Assert if the check of the heap memory region fails. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheck_(&heap, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(&heap, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); /* Check if the heap memory region is consistent. */ - if (RETURN_SUCCESS == _MemoryRegionCheck_(&heap, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { + if (RETURN_SUCCESS == __MemoryRegionCheck__(&heap, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { cursor = heap.start; /* Traverse the memory region as long as there is - something to traverse. */ + something to traverse. */ while (ISNOTNULLPTR(cursor)) { /* If the entry pointed to by the cursor is not - free, then add its blocks to the used block count. */ + free, then add its blocks to the used block count. */ if (false == cursor->free) { @@ -131,7 +134,7 @@ Size_t xMemGetUsed(void) { /* The end-user is expecting bytes, not blocks so multiply - the block size by the number of used blocks. */ + the block size by the number of used blocks. */ ret = used * CONFIG_MEMORY_REGION_BLOCK_SIZE; } } @@ -141,11 +144,10 @@ Size_t xMemGetUsed(void) { - /* A system call used by end-user tasks to return the amount -of memory in bytes assigned to an address in the heap memory -region. */ -Size_t xMemGetSize(const Addr_t *addr_) { + of memory in bytes assigned to an address in the heap memory + region. */ +Size_t xMemGetSize(const volatile Addr_t *addr_) { Size_t ret = zero; @@ -156,25 +158,25 @@ Size_t xMemGetSize(const Addr_t *addr_) { /* Assert if any memory region is corrupt. */ - SYSASSERT(false == SYSFLAG_CORRUPT()); + SYSASSERT(false == SYSFLAG_FAULT()); /* Check to make sure no memory regions are - corrupt before we do anything. */ - if (false == SYSFLAG_CORRUPT()) { + corrupt before we do anything. */ + if (false == SYSFLAG_FAULT()) { /* Assert if the heap memory region fails its consistency check OR if the memory address is not - valid for the heap memory region. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheck_(&heap, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + valid for the heap memory region. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(&heap, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap memory region is consistent AND if the memory address is valid for the heap - memory region. */ - if (RETURN_SUCCESS == _MemoryRegionCheck_(&heap, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + memory region. */ + if (RETURN_SUCCESS == __MemoryRegionCheck__(&heap, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { @@ -194,7 +196,7 @@ Size_t xMemGetSize(const Addr_t *addr_) { /* The end-user is expecting the size in bytes so multiple the block - size by the number of blocks the entry contains. */ + size by the number of blocks the entry contains. */ ret = tosize->blocks * CONFIG_MEMORY_REGION_BLOCK_SIZE; } } @@ -207,10 +209,10 @@ Size_t xMemGetSize(const Addr_t *addr_) { -/* The _MemoryRegionCheck_() function checks the consistency of a memory region. If specified, it will also check -that an address points to valid memory that was previously allocated by _calloc_() for the respective memory -region. */ -Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t *addr_, const Base_t option_) { +/* The __MemoryRegionCheck__() function checks the consistency of a memory region. If specified, it will also check + that an address points to valid memory that was previously allocated by __calloc__() for the respective memory + region. */ +static Base_t __MemoryRegionCheck__(const volatile MemoryRegion_t *region_, const volatile Addr_t *addr_, const Base_t option_) { MemoryEntry_t *cursor = NULL; @@ -219,7 +221,7 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t Base_t found = false; - HWord_t blocks = zero; + HalfWord_t blocks = zero; Base_t ret = RETURN_FAILURE; @@ -238,14 +240,14 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t /* Check if the starting entry of the memory region has been set. if it hasn't then - the memory region hasn't been initialized. */ + the memory region hasn't been initialized. */ if (ISNOTNULLPTR(region_->start)) { cursor = region_->start; /* Check if we will also be checking if an address is a valid - address that points to allocated memory in the memory region. */ + address that points to allocated memory in the memory region. */ if (MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) { find = ADDR2ENTRY(addr_, region_); @@ -253,29 +255,29 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t /* Traverse the memory region's entries if there is - an entry. */ + an entry. */ while (ISNOTNULLPTR(cursor)) { /* Assert if the memory address of the cursor is outside of the scope - of the memory region. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckAddr_(region_, cursor)); + of the memory region. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckAddr__(region_, cursor)); /* Check if the memory address of the cursor is inside the scope of the - memory region, this is important in case an entry is corrupt we don't - want to inadvertently access some other area of memory. */ - if (RETURN_SUCCESS == _MemoryRegionCheckAddr_(region_, cursor)) { + memory region, this is important in case an entry is corrupt we don't + want to inadvertently access some other area of memory. */ + if (RETURN_SUCCESS == __MemoryRegionCheckAddr__(region_, cursor)) { blocks += cursor->blocks; /* If we are also checking if an address is valid, let's see if the entry for the address matches - the entry we are currently on and that entry is NOT free. If that is the case, let's flag that - we found what we are looking for. */ + the entry we are currently on and that entry is NOT free. If that is the case, let's flag that + we found what we are looking for. */ if ((MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) && (cursor == find) && (false == cursor->free)) { found = true; @@ -290,35 +292,35 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t /* The address of the memory entry was outside of the scope of the memory region - so the memory region is corrupt, so mark the corrupt system flag. */ - SYSFLAG_CORRUPT() = true; + so the memory region is corrupt, so mark the corrupt system flag. */ + SYSFLAG_FAULT() = true; /* No point in continuing to traverse the memory entries in the memory region - so break out of the loop. */ + so break out of the loop. */ break; } } /* Assert if the memory region blocks does not match the setting because this would - indicate a serious issued. */ + indicate a serious issued. */ SYSASSERT(CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS == blocks); /* Check if the number of blocks in the memory region matches the setting before - we give the memory region a clean bill of health. */ + we give the memory region a clean bill of health. */ if (CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS == blocks) { /* Assert if the memory region is flagged corrupt or if the address we were looking - for was not found. */ - SYSASSERT(((MEMORY_REGION_CHECK_OPTION_WO_ADDR == option_) && (false == SYSFLAG_CORRUPT())) || ((MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) && (false == SYSFLAG_CORRUPT()) && (true == found))); + for was not found. */ + SYSASSERT(((MEMORY_REGION_CHECK_OPTION_WO_ADDR == option_) && (false == SYSFLAG_FAULT())) || ((MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) && (false == SYSFLAG_FAULT()) && (true == found))); /* Check that the memory region is not flagged corrupt and we found the memory address - we were looking before. */ - if (((MEMORY_REGION_CHECK_OPTION_WO_ADDR == option_) && (false == SYSFLAG_CORRUPT())) || ((MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) && (false == SYSFLAG_CORRUPT()) && (true == found))) { + we were looking before. */ + if (((MEMORY_REGION_CHECK_OPTION_WO_ADDR == option_) && (false == SYSFLAG_FAULT())) || ((MEMORY_REGION_CHECK_OPTION_W_ADDR == option_) && (false == SYSFLAG_FAULT()) && (true == found))) { /* Things look good so set the return value to success. */ @@ -326,8 +328,8 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t - } /* Never use an else statement here to mark SYSFLAG_CORRUPT() = true. Just because an address wasn't - found does not mean the memory region is corrupt. */ + } /* Never use an else statement here to mark SYSFLAG_FAULT() = true. Just because an address wasn't + found does not mean the memory region is corrupt. */ @@ -335,8 +337,8 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t /* The number of blocks counted in the memory region does not match the setting - so something is seriously wrong, so set the corrupt system flag. */ - SYSFLAG_CORRUPT() = true; + so something is seriously wrong, so set the corrupt system flag. */ + SYSFLAG_FAULT() = true; } } } @@ -347,8 +349,8 @@ Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t /* Function to check if an address falls within the scope of a memory region. This -function is used exclusively by _MemoryRegionCheck_(). */ -Base_t _MemoryRegionCheckAddr_(const volatile MemoryRegion_t *region_, const Addr_t *addr_) { + function is used exclusively by __MemoryRegionCheck__(). */ +static Base_t __MemoryRegionCheckAddr__(const volatile MemoryRegion_t *region_, const volatile Addr_t *addr_) { @@ -362,7 +364,7 @@ Base_t _MemoryRegionCheckAddr_(const volatile MemoryRegion_t *region_, const Add /* Check if the address is inside the scope of the memory region, if it is - then return success. */ + then return success. */ if ((addr_ >= (Addr_t *)(region_->mem)) && (addr_ < (Addr_t *)(region_->mem + MEMORY_REGION_SIZE_IN_BYTES))) { @@ -374,25 +376,19 @@ Base_t _MemoryRegionCheckAddr_(const volatile MemoryRegion_t *region_, const Add } -/* A function to allocate memory and is similar to the standard libc calloc() but supports multiple memory regions. */ -Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { - - - /* Need to disable interrupts while modifying entries in - a memory region. */ - DISABLE_INTERRUPTS(); +/* A function to allocate memory and is similar to the standard libc calloc() but supports multiple memory regions. */ +static Addr_t *__calloc__(volatile MemoryRegion_t *region_, const Size_t size_) { Addr_t *ret = NULL; - HWord_t requested = zero; - - HWord_t free = zero; + HalfWord_t requested = zero; + HalfWord_t free = zero; /* Intentionally underflow an unsigned data type - to get its maximum value. */ - HWord_t fewest = -1; + to get its maximum value. */ + HalfWord_t fewest = -1; MemoryEntry_t *cursor = NULL; @@ -403,9 +399,13 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { MemoryEntry_t *candidateNext = NULL; + /* Need to disable interrupts while modifying entries in + a memory region. */ + DISABLE_INTERRUPTS(); + /* Assert if zero bytes are requested because, well... we can't - allocate zero bytes of memory. */ + allocate zero bytes of memory. */ SYSASSERT(zero < size_); @@ -414,27 +414,27 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Assert if the memory corruption flag is true. */ - SYSASSERT(false == SYSFLAG_CORRUPT()); + SYSASSERT(false == SYSFLAG_FAULT()); /* Check to make sure the memory corruption flag is not true because - we can't allocate memory if a memory region is corrupt. */ - if (false == SYSFLAG_CORRUPT()) { + we can't allocate memory if a memory region is corrupt. */ + if (false == SYSFLAG_FAULT()) { /* Check if we have calculated how many blocks are needed to story - a memory entry, if we haven't then we must calculate it now and save - it for later. */ + a memory entry, if we haven't then we must calculate it now and save + it for later. */ if (zero == region_->entrySize) { /* Calculate the quotient part of the blocks. */ - region_->entrySize = ((HWord_t)(sizeof(MemoryEntry_t) / CONFIG_MEMORY_REGION_BLOCK_SIZE)); + region_->entrySize = ((HalfWord_t)(sizeof(MemoryEntry_t) / CONFIG_MEMORY_REGION_BLOCK_SIZE)); /* Check if there is a remainder, if so we need to add one block. */ - if (zero < ((HWord_t)(sizeof(MemoryEntry_t) % CONFIG_MEMORY_REGION_BLOCK_SIZE))) { + if (zero < ((HalfWord_t)(sizeof(MemoryEntry_t) % CONFIG_MEMORY_REGION_BLOCK_SIZE))) { @@ -444,18 +444,18 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Check to see if the region has been initialized, if it hasn't then - we must initialize it. */ + we must initialize it. */ if (ISNULLPTR(region_->start)) { /* Start by setting the start entry to the start address of the memory - region. We do this so we don't have to cast the type every time we wan't - to address the first entry in the memory region. */ + region. We do this so we don't have to cast the type every time we wan't + to address the first entry in the memory region. */ region_->start = (MemoryEntry_t *)region_->mem; /* Zero out all of the memory in the memory region. */ - _memset_(region_->mem, zero, MEMORY_REGION_SIZE_IN_BYTES); + __memset__(region_->mem, zero, MEMORY_REGION_SIZE_IN_BYTES); /* Mark the first entry in the memory region free. */ region_->start->free = true; @@ -474,19 +474,19 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Assert if the memory region fails its consistency check. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheck_(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); /* Check if the memory region passes its consistency check. */ - if (RETURN_SUCCESS == _MemoryRegionCheck_(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { + if (RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { /* Calculate the number of blocks requested. */ - requested = ((HWord_t)(size_ / CONFIG_MEMORY_REGION_BLOCK_SIZE)); + requested = ((HalfWord_t)(size_ / CONFIG_MEMORY_REGION_BLOCK_SIZE)); /* Check if there is a remainder, if so add one more block. */ - if (zero < ((HWord_t)(size_ % CONFIG_MEMORY_REGION_BLOCK_SIZE))) { + if (zero < ((HalfWord_t)(size_ % CONFIG_MEMORY_REGION_BLOCK_SIZE))) { @@ -500,7 +500,7 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* To traverse the entries in the memory region we need to start off with - the cursor set to the starting entry. */ + the cursor set to the starting entry. */ cursor = region_->start; @@ -524,8 +524,8 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { } - /* Count how many blocks are free so we can update the mininum bytes free ever - for the memory region. */ + /* Count how many blocks are free so we can update the minimum bytes free ever + for the memory region. */ if (true == cursor->free) { free += cursor->blocks; @@ -547,7 +547,7 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Check if we can split the blocks in the entry. If we can then proceed with - splitting the blocks by putting the remainder in a new entry. */ + splitting the blocks by putting the remainder in a new entry. */ if ((region_->entrySize + 1) <= (candidate->blocks - requested)) { @@ -563,7 +563,7 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Now used the "candidate->next" saved earlier. We are basically inserting - a new node in a linked list. */ + a new node in a linked list. */ candidate->next->next = candidateNext; @@ -589,12 +589,12 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Clear the memory allocated. */ - _memset_(ENTRY2ADDR(candidate, region_), zero, (requested - region_->entrySize) * CONFIG_MEMORY_REGION_BLOCK_SIZE); + __memset__(ENTRY2ADDR(candidate, region_), zero, (requested - region_->entrySize) * CONFIG_MEMORY_REGION_BLOCK_SIZE); /* Convert the candidate memory entry address to the starting address of the - newly allocated memory. */ + newly allocated memory. */ ret = ENTRY2ADDR(candidate, region_); @@ -608,12 +608,12 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* Clear the memory allocated. */ - _memset_(ENTRY2ADDR(candidate, region_), zero, (requested - region_->entrySize) * CONFIG_MEMORY_REGION_BLOCK_SIZE); + __memset__(ENTRY2ADDR(candidate, region_), zero, (requested - region_->entrySize) * CONFIG_MEMORY_REGION_BLOCK_SIZE); /* Convert the candidate memory entry address to the starting address of the - newly allocated memory. */ + newly allocated memory. */ ret = ENTRY2ADDR(candidate, region_); } @@ -624,7 +624,7 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { /* We just allocated memory, so subtract back out the requested blocks - before we set the mininum bytes available ever. */ + before we set the minimum bytes available ever. */ free -= requested; @@ -647,66 +647,54 @@ Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_) { } -/* Function to free memory allocated by _calloc_(). */ -void _free_(volatile MemoryRegion_t *region_, const Addr_t *addr_) { - - /* Need to disable interrupts while modifying entries in - a memory region. */ - DISABLE_INTERRUPTS(); +/* Function to free memory allocated by __calloc__(). */ +static void __free__(volatile MemoryRegion_t *region_, const volatile Addr_t *addr_) { MemoryEntry_t *free = NULL; + /* Need to disable interrupts while modifying entries in + a memory region. */ + DISABLE_INTERRUPTS(); /* Assert if a memory region is corrupt. */ - SYSASSERT(false == SYSFLAG_CORRUPT()); + SYSASSERT(false == SYSFLAG_FAULT()); /* Check if a memory region is corrupt. If it is, we might as well head toward - the exit because we can't reliably modify the memory region. */ - if (false == SYSFLAG_CORRUPT()) { + the exit because we can't reliably modify the memory region. */ + if (false == SYSFLAG_FAULT()) { /* Assert if the memory region fails a consistency check. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheck_(region_, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(region_, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check the consistency of the memory region before we modify it. We are also checking - that the memory address is valid. */ - if (RETURN_SUCCESS == _MemoryRegionCheck_(region_, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + that the memory address is valid. */ + if (RETURN_SUCCESS == __MemoryRegionCheck__(region_, addr_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { /* Convert the address of the allocated memory to its - respective memory entry address. */ + respective memory entry address. */ free = ADDR2ENTRY(addr_, region_); - /* Mark the memory entry as free. */ free->free = true; region_->frees++; - /* Is there a next entry and is it free? If so, let's merge the - two entries to reduce fragmentation. */ - if ((ISNOTNULLPTR(free->next)) && (true == free->next->free)) { - - - /* Add the blocks from the subsequent entry to the - current entry. */ - free->blocks += free->next->blocks; - - - /* Just drop the entry just as you would in a linked list. */ - free->next = free->next->next; - } + /* After freeing blocks we should defrag the memory + region. */ + __DefragMemoryRegion__(region_); } } @@ -720,74 +708,78 @@ void _free_(volatile MemoryRegion_t *region_, const Addr_t *addr_) { -/* A wrapper function for _calloc_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -Addr_t *_KernelAllocateMemory_(const Size_t size_) { +/* A wrapper function for __calloc__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +Addr_t *__KernelAllocateMemory__(const Size_t size_) { - - return _calloc_(&kernel, size_); + return __calloc__(&kernel, size_); } -/* A wrapper function for _free_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -void _KernelFreeMemory_(const Addr_t *addr_) { +/* A wrapper function for __free__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +void __KernelFreeMemory__(const volatile Addr_t *addr_) { - _free_(&kernel, addr_); + __free__(&kernel, addr_); return; } -/* A wrapper function for _MemoryRegionCheck_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -Base_t _MemoryRegionCheckKernel_(const Addr_t *addr_, const Base_t option_) { - return _MemoryRegionCheck_(&kernel, addr_, option_); + +/* A wrapper function for __MemoryRegionCheck__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +Base_t __MemoryRegionCheckKernel__(const volatile Addr_t *addr_, const Base_t option_) { + + return __MemoryRegionCheck__(&kernel, addr_, option_); } -/* A wrapper function for _calloc_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -Addr_t *_HeapAllocateMemory_(const Size_t size_) { + +/* A wrapper function for __calloc__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +Addr_t *__HeapAllocateMemory__(const Size_t size_) { - return _calloc_(&heap, size_); + return __calloc__(&heap, size_); } -/* A wrapper function for _free_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -void _HeapFreeMemory_(const Addr_t *addr_) { +/* A wrapper function for __free__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +void __HeapFreeMemory__(const volatile Addr_t *addr_) { - _free_(&heap, addr_); + __free__(&heap, addr_); return; } -/* A wrapper function for _MemoryRegionCheck_() because the memory -regions cannot be accessed outside the scope of mem.c. */ -Base_t _MemoryRegionCheckHeap_(const Addr_t *addr_, const Base_t option_) { - return _MemoryRegionCheck_(&heap, addr_, option_); +/* A wrapper function for __MemoryRegionCheck__() because the memory + regions cannot be accessed outside the scope of mem.c. */ +Base_t __MemoryRegionCheckHeap__(const volatile Addr_t *addr_, const Base_t option_) { + + return __MemoryRegionCheck__(&heap, addr_, option_); } -/* Like the standard libc function, _memcpy_() copies memory from one -address to another. */ -void _memcpy_(Addr_t *dest_, const Addr_t *src_, Size_t n_) { + +/* Like the standard libc function, __memcpy__() copies memory from one + address to another. */ +void __memcpy__(const volatile Addr_t *dest_, const volatile Addr_t *src_, const Size_t size_) { Size_t i = zero; - char *src = (char *)src_; + const volatile Char_t *src = (Char_t *)src_; - char *dest = (char *)dest_; + volatile Char_t *dest = (Char_t *)dest_; - for (i = zero; i < n_; i++) { + for (i = zero; i < size_; i++) { dest[i] = src[i]; } @@ -797,17 +789,17 @@ void _memcpy_(Addr_t *dest_, const Addr_t *src_, Size_t n_) { -/* Like the standard libc function, _memset_() sets the memory -at the location specified as the address to the defined value. */ -void _memset_(volatile Addr_t *dest_, uint16_t val_, Size_t n_) { +/* Like the standard libc function, __memset__() sets the memory + at the location specified as the address to the defined value. */ +void __memset__(const volatile Addr_t *dest_, const Byte_t val_, const Size_t size_) { Size_t i = zero; - char *dest = (char *)dest_; + volatile Char_t *dest = (Char_t *)dest_; - for (i = zero; i < n_; i++) { + for (i = zero; i < size_; i++) { - dest[i] = (char)val_; + dest[i] = (Char_t)val_; } return; @@ -815,26 +807,26 @@ void _memset_(volatile Addr_t *dest_, uint16_t val_, Size_t n_) { -/* Similar to the standard libc function, _memcmp_() compares the contents -of two memory locations pointed. */ -uint16_t _memcmp_(const Addr_t *s1_, const Addr_t *s2_, Size_t n_) { - +/* Similar to the standard libc function, __memcmp__() compares the contents + of two memory locations pointed. */ +Base_t __memcmp__(const volatile Addr_t *s1_, const volatile Addr_t *s2_, const Size_t size_) { + Size_t i = zero; - uint16_t ret = zero; + Base_t ret = zero; - char *s1 = (char *)s1_; + volatile Char_t *s1 = (Char_t *)s1_; - char *s2 = (char *)s2_; + volatile Char_t *s2 = (Char_t *)s2_; - for (i = zero; i < n_; i++) { + for (i = zero; i < size_; i++) { if (*s1 != *s2) { ret = *s1 - *s2; break; /* Typically memcmp() just returns here but we can't do that for MISRA C:2012 - compliance. */ + compliance. */ } s1++; @@ -847,24 +839,26 @@ uint16_t _memcmp_(const Addr_t *s1_, const Addr_t *s2_, Size_t n_) { } + /* Return the memory region statistics for the heap. */ MemoryRegionStats_t *xMemGetHeapStats(void) { - return _MemGetRegionStats_(&heap); + return __MemGetRegionStats__(&heap); } -/* Return the memory region stastics for the kernel */ + +/* Return the memory region statistics for the kernel */ MemoryRegionStats_t *xMemGetKernelStats(void) { - return _MemGetRegionStats_(&kernel); + return __MemGetRegionStats__(&kernel); } /* Return the memory region statistics for the specified memory region. */ -MemoryRegionStats_t *_MemGetRegionStats_(const volatile MemoryRegion_t *region_) { +static MemoryRegionStats_t *__MemGetRegionStats__(const volatile MemoryRegion_t *region_) { MemoryEntry_t *cursor = NULL; @@ -880,52 +874,52 @@ MemoryRegionStats_t *_MemGetRegionStats_(const volatile MemoryRegion_t *region_) /* Assert if any memory region is corrupt. */ - SYSASSERT(false == SYSFLAG_CORRUPT()); + SYSASSERT(false == SYSFLAG_FAULT()); /* Check to make sure no memory regions are - corrupt before we do anything. */ - if (false == SYSFLAG_CORRUPT()) { + corrupt before we do anything. */ + if (false == SYSFLAG_FAULT()) { /* Assert if the check if the memory region fails. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheck_(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); /* Check if the memory region is consistent. */ - if (RETURN_SUCCESS == _MemoryRegionCheck_(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { + if (RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { /* Allocate heap memory for the MemoryRegionStats_t structure. */ - ret = (MemoryRegionStats_t *)_HeapAllocateMemory_(sizeof(MemoryRegionStats_t)); + ret = (MemoryRegionStats_t *)__HeapAllocateMemory__(sizeof(MemoryRegionStats_t)); - /* Assert if _HeapAllocateMemory_() failed to allocate the memory. */ + /* Assert if __HeapAllocateMemory__() failed to allocate the memory. */ SYSASSERT(ISNOTNULLPTR(ret)); - /* Check to make sure _HeapAllocateMemory_() did its job. */ + /* Check to make sure __HeapAllocateMemory__() did its job. */ if (ISNOTNULLPTR(ret)) { cursor = region_->start; /* - MemoryRegionStats_t contains these elements which - we need to fill-in before returning. + MemoryRegionStats_t contains these elements which + we need to fill-in before returning. - largestFreeEntryInBytes; - smallestFreeEntryInBytes; - numberOfFreeBlocks; - availableSpaceInBytes; - successfulAllocations; - successfulFrees; - minimumEverFreeBytesRemaining; - */ + largestFreeEntryInBytes; + smallestFreeEntryInBytes; + numberOfFreeBlocks; + availableSpaceInBytes; + successfulAllocations; + successfulFrees; + minimumEverFreeBytesRemaining; + */ /* Clear the structure to make sure everything is zero. */ - _memset_(ret, zero, sizeof(MemoryRegionStats_t)); + __memset__(ret, zero, sizeof(MemoryRegionStats_t)); @@ -946,7 +940,7 @@ MemoryRegionStats_t *_MemGetRegionStats_(const volatile MemoryRegion_t *region_) /* Traverse the memory region as long as there is - something to traverse. */ + something to traverse. */ while (ISNOTNULLPTR(cursor)) { if (true == cursor->free) { @@ -981,22 +975,109 @@ MemoryRegionStats_t *_MemGetRegionStats_(const volatile MemoryRegion_t *region_) +/* Defrag an entire memory region to reduce memory fragmentation. */ +static void __DefragMemoryRegion__(const volatile MemoryRegion_t *region_) { + + + MemoryEntry_t *cursor = NULL; + + + + /* We can't do anything if the region_ pointer is null so assert if it is. */ + SYSASSERT(ISNOTNULLPTR(region_)); + + + /* We can't do anything if the region pointer is null so check before we proceed. */ + if (ISNOTNULLPTR(region_)) { + + + /* Assert if any memory region is corrupt. */ + SYSASSERT(false == SYSFLAG_FAULT()); + + + + /* Check to make sure no memory regions are + corrupt before we do anything. */ + if (false == SYSFLAG_FAULT()) { + + + /* Assert if the check if the memory region fails. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)); + + + + /* Check if the memory region is consistent. */ + if (RETURN_SUCCESS == __MemoryRegionCheck__(region_, NULL, MEMORY_REGION_CHECK_OPTION_WO_ADDR)) { + + cursor = region_->start; + + /* Traverse the memory region as long as there is + something to traverse. */ + while (ISNOTNULLPTR(cursor)) { + + + /* If the current entry is free AND the subsequent entry is free, + we can merge the two. */ + if ((ISNOTNULLPTR(cursor)) && (ISNOTNULLPTR(cursor->next)) && (true == cursor->free) && (true == cursor->next->free)) { + + + /* Add the blocks from the subsequent entry to the + current entry. */ + cursor->blocks += cursor->next->blocks; + + /* Just drop the "next" entry just as you would in a linked list. */ + cursor->next = cursor->next->next; + + + } else { + + + /* Move on to the next entry. */ + cursor = cursor->next; + } + } + } + } + } + + return; +} + + + #if defined(POSIX_ARCH_OTHER) +void __MemoryClear__(void) { + + + __memset__(&heap, 0x0, sizeof(MemoryRegion_t)); + + heap.minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE; + + __memset__(&kernel, 0x0, sizeof(MemoryRegion_t)); + + kernel.minAvailableEver = CONFIG_MEMORY_REGION_SIZE_IN_BLOCKS * CONFIG_MEMORY_REGION_BLOCK_SIZE; + + return; +} + + + /* Just a debugging function to dump the contents of kernel memory. */ -void _MemoryRegionDumpKernel_(void) { +void __MemoryRegionDumpKernel__(void) { - _memdump_(&kernel); + __memdump__(&kernel); return; } -/* Just a debugging function to dump the onents of heap memory. */ -void _MemoryRegionDumpHeap_(void) { - _memdump_(&heap); +/* Just a debugging function to dump the contents of heap memory. */ +void __MemoryRegionDumpHeap__(void) { + + __memdump__(&heap); @@ -1006,13 +1087,13 @@ void _MemoryRegionDumpHeap_(void) { /* Function to dump the memory of the specified memory region. */ -void _memdump_(const volatile MemoryRegion_t *region_) { +void __memdump__(const volatile MemoryRegion_t *region_) { Size_t i = zero; Size_t j = zero; - + Size_t k = zero; diff --git a/src/mem.h b/src/mem.h index 96ddcc4..4a13ed6 100644 --- a/src/mem.h +++ b/src/mem.h @@ -2,12 +2,12 @@ * @file mem.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for memory management - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,9 @@ #include "defines.h" #include "types.h" #include "port.h" +#include "device.h" #include "queue.h" +#include "stream.h" #include "sys.h" #include "task.h" #include "timer.h" @@ -39,37 +41,31 @@ extern "C" { #endif - - Addr_t *xMemAlloc(const Size_t size_); -void xMemFree(const Addr_t *addr_); +void xMemFree(const volatile Addr_t *addr_); Size_t xMemGetUsed(void); -Size_t xMemGetSize(const Addr_t *addr_); -Base_t _MemoryRegionCheck_(const volatile MemoryRegion_t *region_, const Addr_t *addr_, const Base_t option_); -Base_t _MemoryRegionCheckAddr_(const volatile MemoryRegion_t *region_, const Addr_t *addr_); -Addr_t *_calloc_(volatile MemoryRegion_t *region_, const Size_t size_); -void _free_(volatile MemoryRegion_t *region_, const Addr_t *addr_); -Addr_t *_KernelAllocateMemory_(const Size_t size_); -void _KernelFreeMemory_(const Addr_t *addr_); -Base_t _MemoryRegionCheckKernel_(const Addr_t *addr_, const Base_t option_); -Addr_t *_HeapAllocateMemory_(const Size_t size_); -void _HeapFreeMemory_(const Addr_t *addr_); -Base_t _MemoryRegionCheckHeap_(const Addr_t *addr_, const Base_t option_); -void _memcpy_(Addr_t *dest_, const Addr_t *src_, Size_t n_); -void _memset_(volatile Addr_t *dest_, uint16_t val_, Size_t n_); -uint16_t _memcmp_(const Addr_t *s1_, const Addr_t *s2_, Size_t n_); +Size_t xMemGetSize(const volatile Addr_t *addr_); +Addr_t *__KernelAllocateMemory__(const Size_t size_); +void __KernelFreeMemory__(const volatile Addr_t *addr_); +Base_t __MemoryRegionCheckKernel__(const volatile Addr_t *addr_, const Base_t option_); +Addr_t *__HeapAllocateMemory__(const Size_t size_); +void __HeapFreeMemory__(const volatile Addr_t *addr_); +Base_t __MemoryRegionCheckHeap__(const volatile Addr_t *addr_, const Base_t option_); +void __memcpy__(const volatile Addr_t *dest_, const volatile Addr_t *src_, const Size_t size_); +void __memset__(const volatile Addr_t *dest_, const Byte_t val_, const Size_t size_); +Base_t __memcmp__(const volatile Addr_t *s1_, const volatile Addr_t *s2_, const Size_t size_); +void __MemoryInit__(void); MemoryRegionStats_t *xMemGetHeapStats(void); MemoryRegionStats_t *xMemGetKernelStats(void); -MemoryRegionStats_t *_MemGetRegionStats_(const volatile MemoryRegion_t *region_); - #if defined(POSIX_ARCH_OTHER) -void _MemoryRegionDumpKernel_(void); -void _MemoryRegionDumpHeap_(void); -void _memdump_(const volatile MemoryRegion_t *region_); +void __MemoryClear__(void); +void __MemoryRegionDumpKernel__(void); +void __MemoryRegionDumpHeap__(void); +void __memdump__(const volatile MemoryRegion_t *region_); #endif #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/port.c b/src/port.c index f79d2c3..bd5068d 100644 --- a/src/port.c +++ b/src/port.c @@ -2,12 +2,12 @@ * @file port.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for portability layer - * @version 0.3.4 + * @version 0.3.5 * @date 2022-03-24 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,114 +27,79 @@ #include "port.h" -#if defined(ARDUINO_ARCH_AVR) - -Ticks_t _SysGetSysTicks_(void) { - - return timer0_overflow_count; -} - -void _SysInit_(void) { - return; -} +#if defined(CMSIS_ARCH_CORTEXM) +static volatile Ticks_t sysTicks = zero; -#elif defined(ARDUINO_ARCH_SAM) +void SysTick_Handler(void) { -Ticks_t _SysGetSysTicks_(void) { + DISABLE_INTERRUPTS(); - return GetTickCount(); -} + sysTicks++; -void _SysInit_(void) { + ENABLE_INTERRUPTS(); return; } +#endif -#elif defined(ARDUINO_ARCH_SAMD) -Ticks_t _SysGetSysTicks_(void) { +Ticks_t __SysGetSysTicks__(void) { +#if defined(ARDUINO_ARCH_AVR) + return timer0_overflow_count; +#elif defined(ARDUINO_ARCH_SAM) + return GetTickCount(); +#elif defined(ARDUINO_ARCH_SAMD) return millis(); -} - -void _SysInit_(void) { - - return; -} - #elif defined(ARDUINO_ARCH_ESP8266) - -Ticks_t _SysGetSysTicks_(void) { - yield(); return (Ticks_t)(system_get_time() / 1000ULL); -} - -void _SysInit_(void) { - - return; -} - #elif defined(ARDUINO_TEENSY_MICROMOD) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY30) || defined(ARDUINO_TEENSYLC) - -Ticks_t _SysGetSysTicks_(void) { - return systick_millis_count; -} - -void _SysInit_(void) { - - return; -} - #elif defined(ESP32) /* Not supported. */ - #elif defined(CMSIS_ARCH_CORTEXM) + return sysTicks; -static volatile Ticks_t sysTicks = zero; - -void SysTick_Handler(void) { +#elif defined(POSIX_ARCH_OTHER) - DISABLE_INTERRUPTS(); - sysTicks++; + struct timeval t; - ENABLE_INTERRUPTS(); + gettimeofday(&t, NULL); - return; -} -Ticks_t _SysGetSysTicks_(void) { + return (t.tv_sec) * 1000 + (t.tv_usec) / 1000; - return sysTicks; +#endif } -void _SysInit_(void) { +void __SysInit__(void) { +#if defined(ARDUINO_ARCH_AVR) + return; +#elif defined(ARDUINO_ARCH_SAM) + return; +#elif defined(ARDUINO_ARCH_SAMD) + return; +#elif defined(ARDUINO_ARCH_ESP8266) + return; +#elif defined(ARDUINO_TEENSY_MICROMOD) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY36) || defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY30) || defined(ARDUINO_TEENSYLC) + return; +#elif defined(ESP32) +/* Not supported. */ +#elif defined(CMSIS_ARCH_CORTEXM) SysTick_Config(SYSTEM_CORE_CLOCK_FREQUENCY / SYSTEM_CORE_CLOCK_PRESCALER); return; -} - #elif defined(POSIX_ARCH_OTHER) - -Ticks_t _SysGetSysTicks_(void) { - - struct timeval t; - - gettimeofday(&t, NULL); - - - return (t.tv_sec) * 1000 + (t.tv_usec) / 1000; + return; +#endif } -void _SysInit_(void) { - return; -} -#endif + diff --git a/src/port.h b/src/port.h index 709d1ff..2a705db 100644 --- a/src/port.h +++ b/src/port.h @@ -2,12 +2,12 @@ * @file port.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for portability layer - * @version 0.3.4 + * @version 0.3.5 * @date 2022-03-24 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,8 +29,10 @@ #include "config.h" #include "defines.h" #include "types.h" +#include "device.h" #include "mem.h" #include "queue.h" +#include "stream.h" #include "sys.h" #include "task.h" #include "timer.h" @@ -41,20 +43,20 @@ /* - https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring.c + https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring.c - Copyright (c) 2005-2006 David A. Mellis + Copyright (c) 2005-2006 David A. Mellis - volatile unsigned long timer0_overflow_count = 0; - volatile unsigned long timer0_millis = 0; - static unsigned char timer0_fract = 0; + volatile unsigned long timer0_overflow_count = 0; + volatile unsigned long timer0_millis = 0; + static unsigned char timer0_fract = 0; - #if defined(TIM0_OVF_vect) - ISR(TIM0_OVF_vect) - #else - ISR(TIMER0_OVF_vect) - #endif - { + #if defined(TIM0_OVF_vect) + ISR(TIM0_OVF_vect) + #else + ISR(TIMER0_OVF_vect) + #endif + { // copy these to local variables so they can be stored in registers // (volatile variables must be read from memory on every access) unsigned long m = timer0_millis; @@ -70,26 +72,26 @@ timer0_fract = f; timer0_millis = m; timer0_overflow_count++; - } + } -*/ + */ extern unsigned long timer0_overflow_count; -#define DISABLE_INTERRUPTS() __asm__ __volatile__("cli") +#define DISABLE_INTERRUPTS() __asm__ __volatile__ ("cli") -#define ENABLE_INTERRUPTS() __asm__ __volatile__("sei") +#define ENABLE_INTERRUPTS() __asm__ __volatile__ ("sei") #elif defined(ARDUINO_ARCH_SAM) /* - https://github.com/arduino/ArduinoCore-sam/blob/master/cores/arduino/cortex_handlers.c + https://github.com/arduino/ArduinoCore-sam/blob/master/cores/arduino/cortex_handlers.c - Copyright (c) 2012 Arduino. All right reserved. + Copyright (c) 2012 Arduino. All right reserved. - void SysTick_Handler(void) - { + void SysTick_Handler(void) + { if (sysTickHook()) return; @@ -97,76 +99,76 @@ extern unsigned long timer0_overflow_count; // Increment tick count each ms TimeTick_Increment(); - } + } - https://github.com/arduino/ArduinoCore-sam/blob/master/system/libsam/source/timetick.c + https://github.com/arduino/ArduinoCore-sam/blob/master/system/libsam/source/timetick.c - Copyright (c) 2011-2012, Atmel Corporation + Copyright (c) 2011-2012, Atmel Corporation - static volatile uint32_t _dwTickCount=0 ; + static volatile uint32_t _dwTickCount=0 ; - extern void TimeTick_Increment( void ) - { + extern void TimeTick_Increment( void ) + { _dwTickCount++ ; - } + } - extern uint32_t GetTickCount( void ) - { + extern uint32_t GetTickCount( void ) + { return _dwTickCount ; - } + } -*/ + */ extern uint32_t GetTickCount(void); -#define DISABLE_INTERRUPTS() __asm volatile("cpsid i") +#define DISABLE_INTERRUPTS() __asm volatile ("cpsid i") -#define ENABLE_INTERRUPTS() __asm volatile("cpsie i") +#define ENABLE_INTERRUPTS() __asm volatile ("cpsie i") #elif defined(ARDUINO_ARCH_SAMD) /* TESTED 2022-03-24 */ /* - https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/delay.c + https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/delay.c - Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2015 Arduino LLC. All right reserved. - static volatile uint32_t _ulTickCount=0 ; + static volatile uint32_t _ulTickCount=0 ; - unsigned long millis( void ) - { - // todo: ensure no interrupts + unsigned long millis( void ) + { + // todo: ensure no interrupts return _ulTickCount ; - } + } - void SysTick_DefaultHandler(void) - { + void SysTick_DefaultHandler(void) + { // Increment tick count each ms _ulTickCount++; tickReset(); - } + } -*/ + */ extern unsigned long millis(void); -#define DISABLE_INTERRUPTS() __asm volatile("cpsid i") +#define DISABLE_INTERRUPTS() __asm volatile ("cpsid i") -#define ENABLE_INTERRUPTS() __asm volatile("cpsie i") +#define ENABLE_INTERRUPTS() __asm volatile ("cpsie i") #elif defined(ARDUINO_ARCH_ESP8266) /* TESTED 2022-08-22 */ /* -https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_wiring.cpp + https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_wiring.cpp -Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. + Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. -unsigned long IRAM_ATTR micros() { + unsigned long IRAM_ATTR micros() { return system_get_time(); -} + } -*/ + */ #include "core_esp8266_features.h" typedef uint32_t uint32; @@ -181,37 +183,37 @@ extern void yield(void); /* - https://github.com/PaulStoffregen/cores/blob/master/teensy4/EventResponder.cpp + https://github.com/PaulStoffregen/cores/blob/master/teensy4/EventResponder.cpp - Copyright 2017 Paul Stoffregen + Copyright 2017 Paul Stoffregen - extern "C" volatile uint32_t systick_millis_count; - extern "C" volatile uint32_t systick_cycle_count; - extern "C" uint32_t systick_safe_read; // micros() synchronization - extern "C" void systick_isr(void) - { + extern "C" volatile uint32_t systick_millis_count; + extern "C" volatile uint32_t systick_cycle_count; + extern "C" uint32_t systick_safe_read; // micros() synchronization + extern "C" void systick_isr(void) + { systick_cycle_count = ARM_DWT_CYCCNT; systick_millis_count++; - } + } - https://github.com/PaulStoffregen/cores/blob/master/teensy3/EventResponder.cpp + https://github.com/PaulStoffregen/cores/blob/master/teensy3/EventResponder.cpp - Copyright 2017 Paul Stoffregen + Copyright 2017 Paul Stoffregen - extern "C" volatile uint32_t systick_millis_count; + extern "C" volatile uint32_t systick_millis_count; - void systick_isr(void) - { + void systick_isr(void) + { systick_millis_count++; - } + } -*/ + */ extern uint32_t systick_millis_count; -#define DISABLE_INTERRUPTS() __asm volatile("cpsid i") +#define DISABLE_INTERRUPTS() __asm volatile ("cpsid i") -#define ENABLE_INTERRUPTS() __asm volatile("cpsie i") +#define ENABLE_INTERRUPTS() __asm volatile ("cpsie i") #elif defined(ESP32) @@ -225,26 +227,26 @@ extern uint32_t systick_millis_count; /* ld linker script section - .kernel_mem_region (NOLOAD): - { + .kernel_mem_region (NOLOAD): + { . = ALIGN(0x8000); _start_kernel_mem_region = .; - *(.kernel_mem_region*); + *(.kernel_mem_region*); . = ALIGN(0x8000); _end_kernel_mem_region = .; _size_kernel_mem_region = _end_kernel_mem_region - _start_kernel_mem_region; - } > RAM + } > RAM -*/ + */ /* - *** START SECTION: ADD VENDOR HEADER HERE *** + *** START SECTION: ADD VENDOR HEADER HERE *** - Example: For the STM32 F4292ZI MCU, the following - include line would have to be added. + Example: For the STM32 F4292ZI MCU, the following + include line would have to be added. - #include "stm32f429xx.h" -*/ + #include "stm32f429xx.h" + */ #include "stm32f429xx.h" /* *** END SECTION: ADD VENDOR HEADER HERE *** @@ -271,7 +273,7 @@ extern uint32_t systick_millis_count; #define ENABLE_INTERRUPTS() -#define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) printf("assert: %s:%d\n", f , l ) +#define CONFIG_SYSTEM_ASSERT_BEHAVIOR(f, l) printf("kernel: assert at %s:%d\n", f, l ) #endif @@ -281,11 +283,11 @@ extern uint32_t systick_millis_count; extern "C" { #endif -Ticks_t _SysGetSysTicks_(void); -void _SysInit_(void); +Ticks_t __SysGetSysTicks__(void); +void __SysInit__(void); #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/posix.h b/src/posix.h index 031cbaa..08a6f67 100644 --- a/src/posix.h +++ b/src/posix.h @@ -2,12 +2,12 @@ * @file posix.h * @author Manny Peterson (mannymsp@gmail.com) * @brief POSIX header file to use POSIX definitions in header files - * @version 0.3.4 + * @version 0.3.5 * @date 2022-08-20 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,4 @@ #endif #define _POSIX_C_SOURCE 200809L #endif - - #endif \ No newline at end of file diff --git a/src/queue.c b/src/queue.c index 715961e..6c23689 100644 --- a/src/queue.c +++ b/src/queue.c @@ -2,12 +2,12 @@ * @file queue.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for message queues - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,14 +23,13 @@ * along with this program. If not, see . * */ - #include "queue.h" - - +static void __QueueDropmessage__(Queue_t *queue_); +static QueueMessage_t *__QueuePeek__(const Queue_t *queue_); /* The xQueueCreate() system call creates a message queue for inter-task -communication. */ + communication. */ Queue_t *xQueueCreate(Base_t limit_) { @@ -38,28 +37,28 @@ Queue_t *xQueueCreate(Base_t limit_) { /* Assert if the end-user attempted to create a queue with a limit - that is less than the configured minimum limit. */ + that is less than the configured minimum limit. */ SYSASSERT(CONFIG_QUEUE_MINIMUM_LIMIT <= limit_); /* Check if the end-user attempted to create a queue with a limit - that is less than the configured minimum limit, if they did then - just head toward the exit. */ + that is less than the configured minimum limit, if they did then + just head toward the exit. */ if (CONFIG_QUEUE_MINIMUM_LIMIT <= limit_) { - ret = (Queue_t *)_KernelAllocateMemory_(sizeof(Queue_t)); + ret = (Queue_t *)__KernelAllocateMemory__(sizeof(Queue_t)); /* Assert if xMemAlloc() didn't return our requested - heap memory. */ + kernel memory. */ SYSASSERT(ISNOTNULLPTR(ret)); /* Check if xMemAlloc() returned our requested - heap memory. */ + kernel memory. */ if (ISNOTNULLPTR(ret)) { @@ -79,23 +78,23 @@ Queue_t *xQueueCreate(Base_t limit_) { } /* The xQueueDelete() system call will delete a queue created by xQueueCreate(). xQueueDelete() -will delete a queue regardless of how many messages the queue contains at the time xQueueDelete() is called. */ + will delete a queue regardless of how many messages the queue contains at the time xQueueDelete() is called. */ void xQueueDelete(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { /* If the queue contains messages, traverse the queue and drop the - messages as we go. */ + messages as we go. */ while (ISNOTNULLPTR(queue_->head)) { @@ -106,7 +105,7 @@ void xQueueDelete(Queue_t *queue_) { - _KernelFreeMemory_(queue_); + __KernelFreeMemory__(queue_); } @@ -117,8 +116,8 @@ void xQueueDelete(Queue_t *queue_) { /* The xQueueGetLength() system call returns the length of the queue (the number of messages -the queue currently contains). */ -Base_t xQueueGetLength(Queue_t *queue_) { + the queue currently contains). */ +Base_t xQueueGetLength(const Queue_t *queue_) { Base_t ret = zero; @@ -128,13 +127,13 @@ Base_t xQueueGetLength(Queue_t *queue_) { Message_t *cursor = NULL; /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { cursor = queue_->head; @@ -149,12 +148,12 @@ Base_t xQueueGetLength(Queue_t *queue_) { /* Assert if the number of messages we counted disagrees with the queue's - length. This could indicate a problem. */ + length. This could indicate a problem. */ SYSASSERT(messages == queue_->length); /* Check if the number of messages we counted agrees with the queue's - length. */ + length. */ if (messages == queue_->length) { ret = messages; @@ -169,8 +168,8 @@ Base_t xQueueGetLength(Queue_t *queue_) { /* The xQueueIsEmpty() system call will return a true or false dependent on whether the queue is -empty or contains one or more messages. */ -Base_t xQueueIsQueueEmpty(Queue_t *queue_) { + empty or contains one or more messages. */ +Base_t xQueueIsQueueEmpty(const Queue_t *queue_) { @@ -182,13 +181,13 @@ Base_t xQueueIsQueueEmpty(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { cursor = queue_->head; @@ -205,12 +204,12 @@ Base_t xQueueIsQueueEmpty(Queue_t *queue_) { /* Assert if the number of messages we counted disagrees with the queue's - length. This could indicate a problem. */ + length. This could indicate a problem. */ SYSASSERT(messages = queue_->length); /* Check if the number of messages we counted agrees with the queue's - length. Also, for the queue to be empty there must be zero messages. */ + length. Also, for the queue to be empty there must be zero messages. */ if ((zero == messages) && (messages == queue_->length)) { ret = true; @@ -224,9 +223,9 @@ Base_t xQueueIsQueueEmpty(Queue_t *queue_) { /* The xQueueIsFull() system call will return a true or false dependent on whether the queue is -full or contains zero messages. A queue is considered full if the number of messages in the queue -is equal to the queue's length limit. */ -Base_t xQueueIsQueueFull(Queue_t *queue_) { + full or contains zero messages. A queue is considered full if the number of messages in the queue + is equal to the queue's length limit. */ +Base_t xQueueIsQueueFull(const Queue_t *queue_) { Base_t ret = false; @@ -237,13 +236,13 @@ Base_t xQueueIsQueueFull(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { cursor = queue_->head; @@ -259,12 +258,12 @@ Base_t xQueueIsQueueFull(Queue_t *queue_) { /* Assert if the number of messages we counted disagrees with the queue's - length. This could indicate a problem. */ + length. This could indicate a problem. */ SYSASSERT(messages == queue_->length); /* Check if the number of messages we counted agrees with the queue's - length. Also, for the queue to be full the number of messages must be - equal to the queue limit. */ + length. Also, for the queue to be full the number of messages must be + equal to the queue limit. */ if ((messages >= queue_->limit) && (messages == queue_->length)) { @@ -279,8 +278,8 @@ Base_t xQueueIsQueueFull(Queue_t *queue_) { /* The xQueueMessageWaiting() system call returns true or false dependent on whether -there is at least one message waiting. The queue does not have to be full to return true. */ -Base_t xQueueMessagesWaiting(Queue_t *queue_) { + there is at least one message waiting. The queue does not have to be full to return true. */ +Base_t xQueueMessagesWaiting(const Queue_t *queue_) { @@ -292,14 +291,14 @@ Base_t xQueueMessagesWaiting(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { cursor = queue_->head; @@ -313,13 +312,13 @@ Base_t xQueueMessagesWaiting(Queue_t *queue_) { /* Assert if the number of messages we counted disagrees with the queue's - length. This could indicate a problem. */ + length. This could indicate a problem. */ SYSASSERT(messages == queue_->length); /* Check if the number of messages we counted agrees with the queue's - length. Also, for there to be waiting messages look to make sure the - count is greater than zero. */ + length. Also, for there to be waiting messages look to make sure the + count is greater than zero. */ if ((zero < messages) && (messages == queue_->length)) { @@ -335,8 +334,8 @@ Base_t xQueueMessagesWaiting(Queue_t *queue_) { /* The xQueueSend() system call will send a message to the queue. The size of the message -value is passed in the message bytes parameter. */ -Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValue_) { + value is passed in the message bytes parameter. */ +Base_t xQueueSend(Queue_t *queue_, const Base_t messageBytes_, const Char_t *messageValue_) { @@ -350,21 +349,25 @@ Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValu /* Assert if the end-user passed zero message bytes. A message - must have at least one byte in it. */ + must have at least one byte in it. */ SYSASSERT(zero < messageBytes_); /* Assert if the end-user passed a number of message bytes that - exceeds the size of the message value. */ + exceeds the size of the message value. */ SYSASSERT(CONFIG_MESSAGE_VALUE_BYTES >= messageBytes_); /* Assert if the end-user passed a null pointer for the message - value. */ + value. */ SYSASSERT(ISNOTNULLPTR(messageValue_)); + /* Assert if the user passed an invalid queue. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + /* Check if the message bytes is within parameters and the message value is not null. */ - if ((zero < messageBytes_) && (CONFIG_MESSAGE_VALUE_BYTES >= messageBytes_) && (ISNOTNULLPTR(messageValue_))) { + if ((RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) && (zero < messageBytes_) && (CONFIG_MESSAGE_VALUE_BYTES >= messageBytes_) && (ISNOTNULLPTR(messageValue_))) { /* Assert if the queue is locked (locked queues can not SEND messages). */ @@ -375,12 +378,12 @@ Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValu if (false == queue_->locked) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { cursor = queue_->head; @@ -398,18 +401,18 @@ Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValu /* Assert if the messages counted disagrees with the queue length. If - so there is a problem. */ + so there is a problem. */ SYSASSERT(messages == queue_->length); /* Check if the queue is not full and that the messages counted agrees with the - queue length. */ + queue length. */ if ((queue_->limit > queue_->length) && (messages == queue_->length)) { - message = (Message_t *)_KernelAllocateMemory_(sizeof(Message_t)); + message = (Message_t *)__KernelAllocateMemory__(sizeof(Message_t)); /* Assert if xMemAlloc() did not allocate our requested memory. */ @@ -420,12 +423,12 @@ Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValu message->messageBytes = messageBytes_; - _memcpy_(message->messageValue, messageValue_, CONFIG_MESSAGE_VALUE_BYTES); + __memcpy__(message->messageValue, messageValue_, CONFIG_MESSAGE_VALUE_BYTES); message->next = NULL; /* If the queue tail is not null then it already contains messages and append the new message, otherwise - set the head and tail to the new message. */ + set the head and tail to the new message. */ if (ISNOTNULLPTR(queue_->tail)) { queue_->tail->next = message; @@ -453,45 +456,45 @@ Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValu /* The xQueuePeek() system call will return the next message in the queue without -dropping the message. */ -QueueMessage_t *xQueuePeek(Queue_t *queue_) { + dropping the message. */ +QueueMessage_t *xQueuePeek(const Queue_t *queue_) { - return _QueuePeek_(queue_); + return __QueuePeek__(queue_); } -QueueMessage_t *_QueuePeek_(Queue_t *queue_) { +static QueueMessage_t *__QueuePeek__(const Queue_t *queue_) { QueueMessage_t *ret = NULL; /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { /* If the head is not null, then there is a message waiting for us to - peek at. */ + peek at. */ if (ISNOTNULLPTR(queue_->head)) { - ret = (QueueMessage_t *)_HeapAllocateMemory_(sizeof(QueueMessage_t)); + ret = (QueueMessage_t *)__HeapAllocateMemory__(sizeof(QueueMessage_t)); /* Assert if xMemAlloc() didn't do its job. */ SYSASSERT(ISNOTNULLPTR(ret)); /* If xMemAlloc() allocated the heap memory then copy the message into the - queue message we will return. Otherwise, head toward the exit. */ + queue message we will return. Otherwise, head toward the exit. */ if (ISNOTNULLPTR(ret)) { ret->messageBytes = queue_->head->messageBytes; - _memcpy_(ret->messageValue, queue_->head->messageValue, CONFIG_MESSAGE_VALUE_BYTES); + __memcpy__(ret->messageValue, queue_->head->messageValue, CONFIG_MESSAGE_VALUE_BYTES); } } } @@ -501,15 +504,15 @@ QueueMessage_t *_QueuePeek_(Queue_t *queue_) { } /* The xQueueDropMessage() system call will drop the next message from the queue without -returning the message. */ + returning the message. */ void xQueueDropMessage(Queue_t *queue_) { - _QueueDropmessage_(queue_); + __QueueDropmessage__(queue_); return; } -void _QueueDropmessage_(Queue_t *queue_) { +static void __QueueDropmessage__(Queue_t *queue_) { Message_t *message = NULL; @@ -517,19 +520,19 @@ void _QueueDropmessage_(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { /* Check if there is a message in the queue, if there isn't then - we have nothing to drop so head toward the exit. */ + we have nothing to drop so head toward the exit. */ if (ISNOTNULLPTR(queue_->head)) { @@ -539,7 +542,7 @@ void _QueueDropmessage_(Queue_t *queue_) { /* If the head is now null, then let's set the tail to null - too because the queue is now empty. */ + too because the queue is now empty. */ if (ISNULLPTR(queue_->head)) { queue_->tail = NULL; @@ -548,7 +551,7 @@ void _QueueDropmessage_(Queue_t *queue_) { queue_->length--; - _KernelFreeMemory_(message); + __KernelFreeMemory__(message); } } @@ -557,7 +560,7 @@ void _QueueDropmessage_(Queue_t *queue_) { } /* The xQueueReceive() system call will return the next message in the queue and drop -it from the queue. */ + it from the queue. */ QueueMessage_t *xQueueReceive(Queue_t *queue_) { @@ -566,32 +569,32 @@ QueueMessage_t *xQueueReceive(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { /* Re-use some code and peek to see if there is a message - waiting in the queue. + waiting in the queue. - NOTE: We don't need to allocate any heap memory since xQueuePeek() - has already done that for us. */ - ret = _QueuePeek_(queue_); + NOTE: We don't need to allocate any heap memory since xQueuePeek() + has already done that for us. */ + ret = __QueuePeek__(queue_); /* See if xQueuePeek() returned a message, if so we need to drop it - before we return the message. */ + before we return the message. */ if (ISNOTNULLPTR(ret)) { /* Re-use some code and just call xQueueDropMessage() to drop - the message we just received. */ - _QueueDropmessage_(queue_); + the message we just received. */ + __QueueDropmessage__(queue_); } } @@ -600,24 +603,23 @@ QueueMessage_t *xQueueReceive(Queue_t *queue_) { /* The xQueueLockQueue() system call will LOCK the queue and prevent xQueueSend() from -sending a message to the queue. */ + sending a message to the queue. */ void xQueueLockQueue(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { SYSASSERT(false == queue_->locked); queue_->locked = true; - } @@ -626,26 +628,25 @@ void xQueueLockQueue(Queue_t *queue_) { /* The xQueueUnLockQueue() system call will UNLOCK the queue and allow xQueueSend() to -sendi a message to the queue. */ + send a message to the queue. */ void xQueueUnLockQueue(Queue_t *queue_) { /* Assert if the heap fails its health check or if the queue pointer the end-user - passed is invalid. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); /* Check if the heap is health and the queue pointer the end-user passed is valid. - If so, continue. Otherwise, head toward the exit. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(queue_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { SYSASSERT(true == queue_->locked); queue_->locked = false; - } return; -} \ No newline at end of file +} diff --git a/src/queue.h b/src/queue.h index bd1d7ff..a7d47df 100644 --- a/src/queue.h +++ b/src/queue.h @@ -2,26 +2,26 @@ * @file queue.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for message queues - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 - * + * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson - * + * Copyright (C) 2020-2023 Manny Peterson + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #ifndef QUEUE_H_ #define QUEUE_H_ @@ -30,7 +30,9 @@ #include "defines.h" #include "types.h" #include "port.h" +#include "device.h" #include "mem.h" +#include "stream.h" #include "sys.h" #include "task.h" #include "timer.h" @@ -39,22 +41,20 @@ extern "C" { #endif -Queue_t *xQueueCreate(Base_t limit_); +Queue_t *xQueueCreate(const Base_t limit_); void xQueueDelete(Queue_t *queue_); -Base_t xQueueGetLength(Queue_t *queue_); -Base_t xQueueIsQueueEmpty(Queue_t *queue_); -Base_t xQueueIsQueueFull(Queue_t *queue_); -Base_t xQueueMessagesWaiting(Queue_t *queue_); -Base_t xQueueSend(Queue_t *queue_, Base_t messageBytes_, const char *messageValue_); -QueueMessage_t *xQueuePeek(Queue_t *queue_); +Base_t xQueueGetLength(const Queue_t *queue_); +Base_t xQueueIsQueueEmpty(const Queue_t *queue_); +Base_t xQueueIsQueueFull(const Queue_t *queue_); +Base_t xQueueMessagesWaiting(const Queue_t *queue_); +Base_t xQueueSend(Queue_t *queue_, const Base_t messageBytes_, const Char_t *messageValue_); +QueueMessage_t *xQueuePeek(const Queue_t *queue_); void xQueueDropMessage(Queue_t *queue_); QueueMessage_t *xQueueReceive(Queue_t *queue_); -void _QueueDropmessage_(Queue_t *queue_); -QueueMessage_t *_QueuePeek_(Queue_t *queue_); void xQueueLockQueue(Queue_t *queue_); void xQueueUnLockQueue(Queue_t *queue_); #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/stream.c b/src/stream.c new file mode 100644 index 0000000..a26752f --- /dev/null +++ b/src/stream.c @@ -0,0 +1,311 @@ +/** + * @file stream.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief Kernel sources for stream buffers + * @version 0.3.5 + * @date 2022-08-30 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "stream.h" + + + +/* The xStreamCreate() system call will create a new stream. Streams + are fast for sending streams of bytes between tasks. */ +StreamBuffer_t *xStreamCreate() { + + + + StreamBuffer_t *ret = NULL; + + + + + ret = (StreamBuffer_t *)__KernelAllocateMemory__(sizeof(StreamBuffer_t)); + + + /* Assert if xMemAlloc() didn't return our requested + kernel memory. */ + SYSASSERT(ISNOTNULLPTR(ret)); + + + /* Check if xMemAlloc() returned our requested + kernel memory. */ + if (ISNOTNULLPTR(ret)) { + + + ret->length = zero; + } + + + return ret; +} + + + +/* The xStreamDelete() system call will delete a stream. Streams + are fast for sending streams of bytes between tasks. */ +void xStreamDelete(const StreamBuffer_t *stream_) { + + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + + __KernelFreeMemory__(stream_); + } + + + return; +} + + + +/* The xStreamSend() system call will send one byte to + the designated stream. Sending to a stream must be done + one byte at a time. However, receiving from a stream + will return all available bytes in a stream. */ +Base_t xStreamSend(StreamBuffer_t *stream_, const Byte_t byte_) { + + Base_t ret = RETURN_FAILURE; + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + /* Check to make sure our stream buffer is less than + CONFIG_STREAM_BUFFER_BYTES in length before we attempt + to write a byte to it. */ + if (CONFIG_STREAM_BUFFER_BYTES > stream_->length) { + + stream_->length++; + + /* Offset the stream buffer length by -1 because array + is base zero. */ + stream_->buffer[stream_->length - 1] = byte_; + + ret = RETURN_SUCCESS; + } + } + + + return ret; +} + + + +/* The xStreamReceive() system call will receive all waiting bytes + in the stream. */ +Byte_t *xStreamReceive(const StreamBuffer_t *stream_, HalfWord_t *bytes_) { + + + Byte_t *ret = NULL; + + + /* Assert if the bytes paramater is null. It can't be + null because we need to return the number of bytes + received. */ + SYSASSERT(ISNOTNULLPTR(bytes_)); + + + /* Check if the bytes parameter is null. It can't be null + because we need to return the number of bytes received. */ + if (ISNOTNULLPTR(bytes_)) { + + + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + /* If there is nothing to receive then just head toward the exit. */ + if (zero < stream_->length) { + + + + + ret = (Byte_t *)__HeapAllocateMemory__(stream_->length * sizeof(Byte_t)); + + + /* Assert if we didn't get the memory we requested. */ + SYSASSERT(ISNOTNULLPTR(ret)); + + /* Check to make sure we got the memory we requested. */ + if (ISNOTNULLPTR(ret)) { + + *bytes_ = stream_->length; + + __memcpy__(ret, stream_->buffer, stream_->length * sizeof(Byte_t)); + + __memset__(stream_, zero, sizeof(StreamBuffer_t)); + } + } + } + } + + return ret; +} + + + +/* The xStreamBytesAvailable() system call will return the number + of waiting bytes in the stream. */ +HalfWord_t xStreamBytesAvailable(const StreamBuffer_t *stream_) { + + + HalfWord_t ret = zero; + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + + if (zero < stream_->length) { + + ret = stream_->length; + } + } + + + return ret; +} + + + +/* The xStreamReset() system call will reset the stream and clear + its buffer of all waiting bytes. */ +void xStreamReset(const StreamBuffer_t *stream_) { + + + + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + /* If there is nothing to receive then just head toward the exit. */ + if (zero < stream_->length) { + + + __memset__(stream_, zero, sizeof(StreamBuffer_t)); + } + } + + + return; +} + + + +/* The xStreamIsEmpty() system call will return true if the stream + buffer is empty (i.e., zero in size). */ +Base_t xStreamIsEmpty(const StreamBuffer_t *stream_) { + + Base_t ret = true; + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + /* If there is nothing to receive then just head toward the exit. */ + if (zero < stream_->length) { + + + ret = false; + } + } + + + return ret; +} + + + +/* The xStreamIsFull() system call will return true if the stream + buffer is full (i.e., size is equal to CONFIG_STREAM_BUFFER_BYTES) */ +Base_t xStreamIsFull(const StreamBuffer_t *stream_) { + + Base_t ret = false; + + /* Assert if the heap fails its health check or if the stream pointer the end-user + passed is invalid. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + + + + /* Check if the heap is health and the stream pointer the end-user passed is valid. + If so, continue. Otherwise, head toward the exit. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(stream_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + + + /* If there is nothing to receive then just head toward the exit. */ + if (CONFIG_STREAM_BUFFER_BYTES == stream_->length) { + + + ret = true; + } + } + + + return ret; +} diff --git a/src/stream.h b/src/stream.h new file mode 100644 index 0000000..00b60c3 --- /dev/null +++ b/src/stream.h @@ -0,0 +1,56 @@ +/** + * @file stream.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief Kernel sources for stream buffers + * @version 0.3.5 + * @date 2022-08-30 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef STREAM_H_ +#define STREAM_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +StreamBuffer_t *xStreamCreate(void); +void xStreamDelete(const StreamBuffer_t *stream_); +Base_t xStreamSend(StreamBuffer_t *stream_, const Byte_t byte_); +Byte_t *xStreamReceive(const StreamBuffer_t *stream_, HalfWord_t *bytes_); +HalfWord_t xStreamBytesAvailable(const StreamBuffer_t *stream_); +void xStreamReset(const StreamBuffer_t *stream_); +Base_t xStreamIsEmpty(const StreamBuffer_t *stream_); +Base_t xStreamIsFull(const StreamBuffer_t *stream_); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/sys.c b/src/sys.c index 5f0fc9c..4725f8e 100644 --- a/src/sys.c +++ b/src/sys.c @@ -2,12 +2,12 @@ * @file sys.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources system related calls - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,30 +27,27 @@ #include "sys.h" /* "You are not expected to understand this." -Thank you for the best OS on Earth, Dennis. */ + Thank you for the best OS on Earth, Dennis. */ /* Declare and set the system flags to their default values. */ -SysFlags_t sysFlags = { - .running = false, - .overflow = false, - .corrupt = false}; +SysFlags_t sysFlags; -/* The _SystemAssert_() system call will be called when -the SYSASSERT() macro evaluates false. In order for there -to be any effect, CONFIG_ENABLE_SYSTEM_ASSERT and -CONFIG_SYSTEM_ASSERT_BEHAVIOR must be defined. +/* The __SystemAssert__() system call will be called when + the SYSASSERT() macro evaluates false. In order for there + to be any effect, CONFIG_ENABLE_SYSTEM_ASSERT and + CONFIG_SYSTEM_ASSERT_BEHAVIOR must be defined. -_SystemAssert_() should NOT be called directly because it is an INTERNAL -function name and may change in future releases. Instead use the SYSASSERT() C macro. */ -void _SystemAssert_(const char *file_, int line_) { + __SystemAssert__() should NOT be called directly because it is an INTERNAL + function name and may change in future releases. Instead use the SYSASSERT() C macro. */ +void __SystemAssert__(const char *file_, const int line_) { /* Do not modify this system call directly. Define - the behavior (code) through the CONFIG_SYSTEM_ASSERT_BEHAVIOR - setting in the config.h header file. */ + the behavior (code) through the CONFIG_SYSTEM_ASSERT_BEHAVIOR + setting in the config.h header file. */ #if defined(CONFIG_SYSTEM_ASSERT_BEHAVIOR) CONFIG_SYSTEM_ASSERT_BEHAVIOR(file_, line_); @@ -65,7 +62,13 @@ void _SystemAssert_(const char *file_, int line_) { /* The xSystemInit() system call initializes the system. */ void xSystemInit(void) { - _SysInit_(); + __MemoryInit__(); + + sysFlags.fault = false; + sysFlags.overflow = false; + sysFlags.running = false; + + __SysInit__(); return; } @@ -91,15 +94,15 @@ void xSystemHalt(void) { /* The xSystemGetSystemInfo() system call will return the type xSystemInfo containing -information about the system including the OS (product) name, its version and how many tasks -are currently in the running, suspended or waiting states. */ + information about the system including the OS (product) name, its version and how many tasks + are currently in the running, suspended or waiting states. */ SystemInfo_t *xSystemGetSystemInfo(void) { SystemInfo_t *ret = NULL; - ret = (SystemInfo_t *)_HeapAllocateMemory_(sizeof(SystemInfo_t)); + ret = (SystemInfo_t *)__HeapAllocateMemory__(sizeof(SystemInfo_t)); @@ -109,11 +112,11 @@ SystemInfo_t *xSystemGetSystemInfo(void) { /* Check if system info is not null to make sure xMemAlloc() successfully allocated - the memory. */ + the memory. */ if (ISNOTNULLPTR(ret)) { - _memcpy_(ret->productName, OS_PRODUCT_NAME, OS_PRODUCT_NAME_SIZE); + __memcpy__(ret->productName, OS_PRODUCT_NAME, OS_PRODUCT_NAME_SIZE); ret->majorVersion = OS_MAJOR_VERSION_NO; @@ -125,4 +128,15 @@ SystemInfo_t *xSystemGetSystemInfo(void) { } return ret; -} \ No newline at end of file +} + + + +#if defined(POSIX_ARCH_OTHER) +void __SysStateClear__(void) { + + __memset__(&sysFlags, 0x0, sizeof(SysFlags_t)); + + return; +} +#endif \ No newline at end of file diff --git a/src/sys.h b/src/sys.h index 95befbe..41e8c80 100644 --- a/src/sys.h +++ b/src/sys.h @@ -2,12 +2,12 @@ * @file sys.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources system related calls - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,8 +30,10 @@ #include "defines.h" #include "types.h" #include "port.h" +#include "device.h" #include "mem.h" #include "queue.h" +#include "stream.h" #include "task.h" #include "timer.h" @@ -41,16 +43,20 @@ extern SysFlags_t sysFlags; extern "C" { #endif -void _SystemAssert_(const char *file_, int line_); +void __SystemAssert__(const char *file_, const int line_); void xSystemInit(void); void xSystemHalt(void); SystemInfo_t *xSystemGetSystemInfo(void); #if defined(CONFIG_ENABLE_ARDUINO_CPP_INTERFACE) -void _ArduinoAssert_(const char *file_, int line_); +void __ArduinoAssert__(const char *file_, int line_); +#endif + +#if defined(POSIX_ARCH_OTHER) +void __SysStateClear__(void); #endif #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/task.c b/src/task.c index b8fee45..36c60ea 100644 --- a/src/task.c +++ b/src/task.c @@ -2,12 +2,12 @@ * @file task.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for task management - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,29 +26,27 @@ #include "task.h" - - - /* Declare and initialize the task list to null. */ static TaskList_t *taskList = NULL; +static void __RunTimeReset__(void); +static void __TaskRun__(Task_t *task_); +static Base_t __TaskListFindTask__(const Task_t *task_); /* Declare and initialize the scheduler state to -running. This is controlled with xTaskResumeAll() -and xTaskSuspendAll(). */ + running. This is controlled with xTaskResumeAll() + and xTaskSuspendAll(). */ static SchedulerState_t schedulerState = SchedulerStateRunning; - - /* The xTaskCreate() system call will create a new task. The task will be created with its -state set to suspended. The xTaskCreate() and xTaskDelete() system calls cannot be called within -a task. They MUST be called outside of the scope of the HeliOS scheduler. */ -Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *), TaskParm_t *taskParameter_) { + state set to suspended. The xTaskCreate() and xTaskDelete() system calls cannot be called within + a task. They MUST be called outside of the scope of the HeliOS scheduler. */ +Task_t *xTaskCreate(const Char_t *name_, void (*callback_)(Task_t *task_, TaskParm_t *parm_), TaskParm_t *taskParameter_) { Task_t *ret = NULL; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; SYSASSERT(false == SYSFLAG_RUNNING()); @@ -60,9 +58,9 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) /* Make sure we aren't inside the scope of the scheduler and that the end-user didn't - pass any null pointers. + pass any null pointers. - NOTE: It is okay for the task paramater to be null. */ + NOTE: It is okay for the task paramater to be null. */ if ((false == SYSFLAG_RUNNING()) && (ISNOTNULLPTR(name_)) && (ISNOTNULLPTR(callback_))) { @@ -72,8 +70,7 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) - - taskList = (TaskList_t *)_KernelAllocateMemory_(sizeof(TaskList_t)); + taskList = (TaskList_t *)__KernelAllocateMemory__(sizeof(TaskList_t)); } @@ -86,7 +83,7 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) - ret = (Task_t *)_KernelAllocateMemory_(sizeof(Task_t)); + ret = (Task_t *)__KernelAllocateMemory__(sizeof(Task_t)); /* Again, assert if xMemAlloc() didn't do its job. */ @@ -94,14 +91,14 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) /* Check if xMemAlloc() did its job. If so, populate the task with all the - pertinent details. */ + pertinent details. */ if (ISNOTNULLPTR(ret)) { taskList->nextId++; ret->id = taskList->nextId; - _memcpy_(ret->name, name_, CONFIG_TASK_NAME_BYTES); + __memcpy__(ret->name, name_, CONFIG_TASK_NAME_BYTES); ret->state = TaskStateSuspended; @@ -111,22 +108,22 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) ret->next = NULL; - taskCursor = taskList->head; + cursor = taskList->head; /* Check if this is the first task in the task list. If it is just set - the head to it. Otherwise we are going to have to traverse the list - to find the end. */ + the head to it. Otherwise we are going to have to traverse the list + to find the end. */ if (ISNOTNULLPTR(taskList->head)) { /* If the task cursor is not null, continue to traverse the list to find the end. */ - while (ISNOTNULLPTR(taskCursor->next)) { + while (ISNOTNULLPTR(cursor->next)) { - taskCursor = taskCursor->next; + cursor = cursor->next; } - taskCursor->next = ret; + cursor->next = ret; } else { @@ -144,11 +141,11 @@ Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *) /* The xTaskDelete() system call will delete a task. The xTaskCreate() and xTaskDelete() system calls -cannot be called within a task. They MUST be called outside of the scope of the HeliOS scheduler. */ -void xTaskDelete(Task_t *task_) { + cannot be called within a task. They MUST be called outside of the scope of the HeliOS scheduler. */ +void xTaskDelete(const Task_t *task_) { - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; Task_t *taskPrevious = NULL; @@ -162,58 +159,58 @@ void xTaskDelete(Task_t *task_) { /* Assert if we can't find the task in the task list. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task is in the task list, if not then head toward - the exit. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + the exit. */ + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { - taskCursor = taskList->head; + cursor = taskList->head; /* If the task is at the head of the task list then just remove - it and free its heap memory. */ - if ((ISNOTNULLPTR(taskCursor)) && (taskCursor == task_)) { + it and free its heap memory. */ + if ((ISNOTNULLPTR(cursor)) && (cursor == task_)) { - taskList->head = taskCursor->next; + taskList->head = cursor->next; - _KernelFreeMemory_(taskCursor); + __KernelFreeMemory__(cursor); taskList->length--; } else { /* Well, it wasn't at the head of the task list so now we have to - go hunt it down. */ - while ((ISNOTNULLPTR(taskCursor)) && (taskCursor != task_)) { + go hunt it down. */ + while ((ISNOTNULLPTR(cursor)) && (cursor != task_)) { - taskPrevious = taskCursor; + taskPrevious = cursor; - taskCursor = taskCursor->next; + cursor = cursor->next; } /* Assert if we didn't find it which should be impossible given - _TaskListFindTask_() found it. Maybe some cosmic rays bit flipped - the DRAM!? */ - SYSASSERT(ISNOTNULLPTR(taskCursor)); + __TaskListFindTask__() found it. Maybe some cosmic rays bit flipped + the DRAM!? */ + SYSASSERT(ISNOTNULLPTR(cursor)); /* Check if the task cursor points to something. That something should - be the task we want to free. */ - if (ISNOTNULLPTR(taskCursor)) { + be the task we want to free. */ + if (ISNOTNULLPTR(cursor)) { - taskPrevious->next = taskCursor->next; + taskPrevious->next = cursor->next; - _KernelFreeMemory_(taskCursor); + __KernelFreeMemory__(cursor); taskList->length--; @@ -229,19 +226,19 @@ void xTaskDelete(Task_t *task_) { /* The xTaskGetHandleByName() system call will return the task handle pointer to the -task specified by its ASCII name. The length of the task name is dependent on the -CONFIG_TASK_NAME_BYTES setting. The name is compared byte-for-byte so the name is -case sensitive. */ -Task_t *xTaskGetHandleByName(const char *name_) { + task specified by its ASCII name. The length of the task name is dependent on the + CONFIG_TASK_NAME_BYTES setting. The name is compared byte-for-byte so the name is + case sensitive. */ +Task_t *xTaskGetHandleByName(const Char_t *name_) { Task_t *ret = NULL; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; /* Assert if the task list has not been initialized. We wouldn't have to do this - if we called _TaskListFindTask_() but that isn't needed here. */ + if we called __TaskListFindTask__() but that isn't needed here. */ SYSASSERT(ISNOTNULLPTR(taskList)); /* Assert if the end-user passed a null pointer for the task name. */ @@ -250,22 +247,22 @@ Task_t *xTaskGetHandleByName(const char *name_) { /* Check if the task list is not null and the name parameter is also not null. */ if ((ISNOTNULLPTR(taskList)) && (ISNOTNULLPTR(name_))) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, scan the task list for the task name. */ - while (ISNOTNULLPTR(taskCursor)) { + while (ISNOTNULLPTR(cursor)) { /* Compare the task name of the task pointed to by the task cursor against the - name parameter. */ - if (zero == _memcmp_(taskCursor->name, name_, CONFIG_TASK_NAME_BYTES)) { + name parameter. */ + if (zero == __memcmp__(cursor->name, name_, CONFIG_TASK_NAME_BYTES)) { - ret = taskCursor; + ret = cursor; break; } - taskCursor = taskCursor->next; + cursor = cursor->next; } } @@ -276,16 +273,16 @@ Task_t *xTaskGetHandleByName(const char *name_) { /* The xTaskGetHandleById() system call will return a pointer to the task handle -specified by its identifier. */ -Task_t *xTaskGetHandleById(Base_t id_) { + specified by its identifier. */ +Task_t *xTaskGetHandleById(const Base_t id_) { Task_t *ret = NULL; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; /* Assert if the task list has not been initialized. We wouldn't have to do this - if we called _TaskListFindTask_() but that isn't needed here. */ + if we called __TaskListFindTask__() but that isn't needed here. */ SYSASSERT(ISNOTNULLPTR(taskList)); @@ -293,24 +290,24 @@ Task_t *xTaskGetHandleById(Base_t id_) { SYSASSERT(zero < id_); /* Check if the task list is not null and the identifier parameter is greater than - zero. */ + zero. */ if ((ISNOTNULLPTR(taskList)) && (zero < id_)) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, check the task pointed to by the task cursor - and compare its identifier against the identifier parameter being searched for. */ - while (ISNOTNULLPTR(taskCursor)) { + and compare its identifier against the identifier parameter being searched for. */ + while (ISNOTNULLPTR(cursor)) { - if (id_ == taskCursor->id) { + if (id_ == cursor->id) { - ret = taskCursor; + ret = cursor; break; } - taskCursor = taskCursor->next; + cursor = cursor->next; } } @@ -321,23 +318,23 @@ Task_t *xTaskGetHandleById(Base_t id_) { /* The xTaskGetAllRunTimeStats() system call will return the runtime statistics for all - of the tasks regardless of their state. The xTaskGetAllRunTimeStats() system call returns - the xTaskRunTimeStats type. An xBase variable must be passed by reference to xTaskGetAllRunTimeStats() - which will contain the number of tasks so the end-user can iterate through the tasks. */ + of the tasks regardless of their state. The xTaskGetAllRunTimeStats() system call returns + the xTaskRunTimeStats type. An xBase variable must be passed by reference to xTaskGetAllRunTimeStats() + which will contain the number of tasks so the end-user can iterate through the tasks. */ TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_) { - Base_t i = zero; + Base_t task = zero; Base_t tasks = zero; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; TaskRunTimeStats_t *ret = NULL; /* Assert if the task list has not been initialized. We wouldn't have to do this - if we called _TaskListFindTask_() but that isn't needed here. */ + if we called __TaskListFindTask__() but that isn't needed here. */ SYSASSERT(ISNOTNULLPTR(taskList)); @@ -348,15 +345,15 @@ TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_) { /* Check if the task list is not null and the tasks parameter is not null. */ if ((ISNOTNULLPTR(taskList)) && (ISNOTNULLPTR(tasks_))) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, continue to traverse the task list counting - the number of tasks in the list. */ - while (ISNOTNULLPTR(taskCursor)) { + the number of tasks in the list. */ + while (ISNOTNULLPTR(cursor)) { tasks++; - taskCursor = taskCursor->next; + cursor = cursor->next; } @@ -364,7 +361,7 @@ TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_) { SYSASSERT(tasks == taskList->length); /* Check if the number of tasks is greater than zero and the length of the task list equals - the number of tasks just counted (this is done as an integrity check). */ + the number of tasks just counted (this is done as an integrity check). */ if ((zero < tasks) && (tasks == taskList->length)) { @@ -377,21 +374,21 @@ TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_) { /* Check if xMemAlloc() successfully allocated the memory. */ if (ISNOTNULLPTR(ret)) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, continue to traverse the task list adding the - runtime statistics of each task to the runtime stats array to be returned. */ - while (ISNOTNULLPTR(taskCursor)) { + runtime statistics of each task to the runtime stats array to be returned. */ + while (ISNOTNULLPTR(cursor)) { - ret[i].id = taskCursor->id; + ret[task].id = cursor->id; - ret[i].lastRunTime = taskCursor->lastRunTime; + ret[task].lastRunTime = cursor->lastRunTime; - ret[i].totalRunTime = taskCursor->totalRunTime; + ret[task].totalRunTime = cursor->totalRunTime; - taskCursor = taskCursor->next; + cursor = cursor->next; - i++; + task++; } *tasks_ = tasks; @@ -410,22 +407,22 @@ TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_) { /* The xTaskGetTaskRunTimeStats() system call returns the task runtime statistics for -one task. The xTaskGetTaskRunTimeStats() system call returns the xTaskRunTimeStats type. -The memory must be freed by calling xMemFree() after it is no longer needed. */ -TaskRunTimeStats_t *xTaskGetTaskRunTimeStats(Task_t *task_) { + one task. The xTaskGetTaskRunTimeStats() system call returns the xTaskRunTimeStats type. + The memory must be freed by calling xMemFree() after it is no longer needed. */ +TaskRunTimeStats_t *xTaskGetTaskRunTimeStats(const Task_t *task_) { TaskRunTimeStats_t *ret = NULL; /* Assert if the task cannot be found in the task list. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task cannot be found in the task list. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { - ret = (TaskRunTimeStats_t *)_HeapAllocateMemory_(sizeof(TaskRunTimeStats_t)); + ret = (TaskRunTimeStats_t *)__HeapAllocateMemory__(sizeof(TaskRunTimeStats_t)); /* Assert if xMemAlloc() didn't do its job. */ @@ -449,7 +446,7 @@ TaskRunTimeStats_t *xTaskGetTaskRunTimeStats(Task_t *task_) { /* The xTaskGetNumberOfTasks() system call returns the current number of tasks -regardless of their state. */ + regardless of their state. */ Base_t xTaskGetNumberOfTasks(void) { @@ -457,7 +454,7 @@ Base_t xTaskGetNumberOfTasks(void) { Base_t tasks = zero; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; /* Assert if the task list is not initialized. */ SYSASSERT(ISNOTNULLPTR(taskList)); @@ -466,23 +463,23 @@ Base_t xTaskGetNumberOfTasks(void) { /* Check if the task list is not initialized. */ if (ISNOTNULLPTR(taskList)) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, continue to count the number of - tasks. */ - while (ISNOTNULLPTR(taskCursor)) { + tasks. */ + while (ISNOTNULLPTR(cursor)) { tasks++; - taskCursor = taskCursor->next; + cursor = cursor->next; } /* Assert if the number of tasks counted does not agree with the task list - length. */ + length. */ SYSASSERT(tasks == taskList->length); /* Check if the length of the task list equals the number of tasks counted - (this is an integrity check). */ + (this is an integrity check). */ if (tasks == taskList->length) { ret = tasks; @@ -496,28 +493,28 @@ Base_t xTaskGetNumberOfTasks(void) { /* The xTaskGetTaskInfo() system call returns the xTaskInfo structure containing -the details of the task including its identifier, name, state and runtime statistics. */ -TaskInfo_t *xTaskGetTaskInfo(Task_t *task_) { + the details of the task including its identifier, name, state and runtime statistics. */ +TaskInfo_t *xTaskGetTaskInfo(const Task_t *task_) { TaskInfo_t *ret = NULL; /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task cannot be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { - ret = (TaskInfo_t *)_HeapAllocateMemory_(sizeof(TaskInfo_t)); + ret = (TaskInfo_t *)__HeapAllocateMemory__(sizeof(TaskInfo_t)); /* Assert if xMemAlloc() failed to do its one job in life. */ SYSASSERT(ISNOTNULLPTR(ret)); /* Check if the task info memory has been allocated by xMemAlloc(). if it - has then populate the task info and return. */ + has then populate the task info and return. */ if (ISNOTNULLPTR(ret)) { @@ -525,7 +522,7 @@ TaskInfo_t *xTaskGetTaskInfo(Task_t *task_) { ret->state = task_->state; - _memcpy_(ret->name, task_->name, CONFIG_TASK_NAME_BYTES); + __memcpy__(ret->name, task_->name, CONFIG_TASK_NAME_BYTES); ret->lastRunTime = task_->lastRunTime; @@ -540,15 +537,15 @@ TaskInfo_t *xTaskGetTaskInfo(Task_t *task_) { /* The xTaskGetAllTaskInfo() system call returns the xTaskInfo structure containing -the details of ALL tasks including its identifier, name, state and runtime statistics. */ + the details of ALL tasks including its identifier, name, state and runtime statistics. */ TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_) { - Base_t i = zero; + Base_t task = zero; Base_t tasks = zero; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; TaskInfo_t *ret = NULL; @@ -564,17 +561,17 @@ TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_) { /* Check if the task list is not null and the tasks parameter is not null. */ if ((ISNOTNULLPTR(taskList)) && (ISNOTNULLPTR(tasks_))) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, continue to traverse the task list counting - the number of tasks in the list. */ - while (ISNOTNULLPTR(taskCursor)) { + the number of tasks in the list. */ + while (ISNOTNULLPTR(cursor)) { tasks++; - taskCursor = taskCursor->next; + cursor = cursor->next; } @@ -582,7 +579,7 @@ TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_) { SYSASSERT(tasks == taskList->length); /* Check if the number of tasks is greater than zero and the length of the task list equals - the number of tasks just counted (this is done as an integrity check). */ + the number of tasks just counted (this is done as an integrity check). */ if ((zero < tasks) && (tasks == taskList->length)) { @@ -597,27 +594,27 @@ TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_) { if (ISNOTNULLPTR(ret)) { - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null, continue to traverse the task list adding the - runtime statistics of each task to the runtime stats array to be returned. */ - while (ISNOTNULLPTR(taskCursor)) { + runtime statistics of each task to the runtime stats array to be returned. */ + while (ISNOTNULLPTR(cursor)) { - ret[i].id = taskCursor->id; + ret[task].id = cursor->id; - ret[i].state = taskCursor->state; + ret[task].state = cursor->state; - _memcpy_(ret[i].name, taskCursor->name, CONFIG_TASK_NAME_BYTES); + __memcpy__(ret[task].name, cursor->name, CONFIG_TASK_NAME_BYTES); - ret[i].lastRunTime = taskCursor->lastRunTime; + ret[task].lastRunTime = cursor->lastRunTime; - ret[i].totalRunTime = taskCursor->totalRunTime; + ret[task].totalRunTime = cursor->totalRunTime; - taskCursor = taskCursor->next; + cursor = cursor->next; - i++; + task++; } *tasks_ = tasks; @@ -635,7 +632,7 @@ TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_) { /* The xTaskGetTaskState() system call will return the state of the task. */ -TaskState_t xTaskGetTaskState(Task_t *task_) { +TaskState_t xTaskGetTaskState(const Task_t *task_) { TaskState_t ret = TaskStateError; @@ -643,11 +640,11 @@ TaskState_t xTaskGetTaskState(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check to make sure the task was found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { ret = task_->state; } @@ -659,24 +656,24 @@ TaskState_t xTaskGetTaskState(Task_t *task_) { /* The xTaskGetName() system call returns the ASCII name of the task. The size of the -task is dependent on the setting CONFIG_TASK_NAME_BYTES. The task name is NOT a null -terminated char array. */ -char *xTaskGetName(Task_t *task_) { + task is dependent on the setting CONFIG_TASK_NAME_BYTES. The task name is NOT a null + terminated char array. */ +Char_t *xTaskGetName(const Task_t *task_) { - char *ret = NULL; + Char_t *ret = NULL; /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { - ret = (char *)xMemAlloc(CONFIG_TASK_NAME_BYTES); + ret = (Char_t *)xMemAlloc(CONFIG_TASK_NAME_BYTES); /* Assert if xMemAlloc() didn't do its job. */ @@ -688,7 +685,7 @@ char *xTaskGetName(Task_t *task_) { - _memcpy_(ret, task_->name, CONFIG_TASK_NAME_BYTES); + __memcpy__(ret, task_->name, CONFIG_TASK_NAME_BYTES); } } @@ -699,18 +696,18 @@ char *xTaskGetName(Task_t *task_) { /* The xTaskGetId() system call returns the task identifier for the task. */ -Base_t xTaskGetId(Task_t *task_) { +Base_t xTaskGetId(const Task_t *task_) { Base_t ret = zero; /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check that the task was found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { ret = task_->id; } @@ -723,25 +720,25 @@ Base_t xTaskGetId(Task_t *task_) { /* The xTaskNotifyStateClear() system call will clear a waiting task notification if one -exists without returning the notification. */ + exists without returning the notification. */ void xTaskNotifyStateClear(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task was found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { /* If the notification bytes are greater than zero then there - is a notification to be cleared. */ + is a notification to be cleared. */ if (zero < task_->notificationBytes) { task_->notificationBytes = zero; - _memset_(task_->notificationValue, zero, CONFIG_NOTIFICATION_VALUE_BYTES); + __memset__(task_->notificationValue, zero, CONFIG_NOTIFICATION_VALUE_BYTES); } } @@ -752,22 +749,22 @@ void xTaskNotifyStateClear(Task_t *task_) { /* The xTaskNotificationIsWaiting() system call will return true or false depending -on whether there is a task notification waiting for the task. */ -Base_t xTaskNotificationIsWaiting(Task_t *task_) { + on whether there is a task notification waiting for the task. */ +Base_t xTaskNotificationIsWaiting(const Task_t *task_) { Base_t ret = zero; /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task was found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { /* If there are notification bytes, there is a notification - waiting. */ + waiting. */ if (zero < task_->notificationBytes) { @@ -783,11 +780,11 @@ Base_t xTaskNotificationIsWaiting(Task_t *task_) { /* The xTaskNotifyGive() system call will send a task notification to the specified task. The -task notification bytes is the number of bytes contained in the notification value. The number of -notification bytes must be between one and the CONFIG_NOTIFICATION_VALUE_BYTES setting. The notification -value must contain a pointer to a char array containing the notification value. If the task already -has a waiting task notification, xTaskNotifyGive() will NOT overwrite the waiting task notification. */ -Base_t xTaskNotifyGive(Task_t *task_, Base_t notificationBytes_, const char *notificationValue_) { + task notification bytes is the number of bytes contained in the notification value. The number of + notification bytes must be between one and the CONFIG_NOTIFICATION_VALUE_BYTES setting. The notification + value must contain a pointer to a char array containing the notification value. If the task already + has a waiting task notification, xTaskNotifyGive() will NOT overwrite the waiting task notification. */ +Base_t xTaskNotifyGive(Task_t *task_, const Base_t notificationBytes_, const Char_t *notificationValue_) { @@ -797,34 +794,34 @@ Base_t xTaskNotifyGive(Task_t *task_, Base_t notificationBytes_, const char *not SYSASSERT(zero < notificationBytes_); /* Assert if the notification bytes exceeds the setting - CONFIG_NOTIFICATION_VALUE_BYTES. */ + CONFIG_NOTIFICATION_VALUE_BYTES. */ SYSASSERT(CONFIG_NOTIFICATION_VALUE_BYTES >= notificationBytes_); /* Assert if the end-user passed us a null pointer for the - notification value. */ + notification value. */ SYSASSERT(ISNOTNULLPTR(notificationValue_)); /* Check if the task list is not null and the task parameter is not null, the notification bytes are between - one and CONFIG_NOTIFICATION_VALUE_BYTES and that the notification value char array pointer is not null. */ + one and CONFIG_NOTIFICATION_VALUE_BYTES and that the notification value char array pointer is not null. */ if ((zero < notificationBytes_) && (CONFIG_NOTIFICATION_VALUE_BYTES >= notificationBytes_) && (ISNOTNULLPTR(notificationValue_))) { /* Assert if we can't find the task to receive the notification. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { /* Make sure there isn't a waiting notification. xTaskNotifyGive will NOT - overwrite a waiting notification. */ + overwrite a waiting notification. */ if (zero == task_->notificationBytes) { task_->notificationBytes = notificationBytes_; - _memcpy_(task_->notificationValue, notificationValue_, CONFIG_NOTIFICATION_VALUE_BYTES); + __memcpy__(task_->notificationValue, notificationValue_, CONFIG_NOTIFICATION_VALUE_BYTES); ret = RETURN_SUCCESS; } @@ -837,8 +834,8 @@ Base_t xTaskNotifyGive(Task_t *task_, Base_t notificationBytes_, const char *not /* The xTaskNotifyTake() system call will return the waiting task notification if there -is one. The xTaskNotifyTake() system call will return an xTaskNotification structure containing -the notification bytes and its value. */ + is one. The xTaskNotifyTake() system call will return an xTaskNotification structure containing + the notification bytes and its value. */ TaskNotification_t *xTaskNotifyTake(Task_t *task_) { TaskNotification_t *ret = NULL; @@ -846,35 +843,35 @@ TaskNotification_t *xTaskNotifyTake(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task cannot be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { /* If there are notification bytes, there is a notification - waiting. */ + waiting. */ if (zero < task_->notificationBytes) { - ret = (TaskNotification_t *)_HeapAllocateMemory_(sizeof(TaskNotification_t)); + ret = (TaskNotification_t *)__HeapAllocateMemory__(sizeof(TaskNotification_t)); /* Assert if xMemAlloc() didn't do its job. */ SYSASSERT(ISNOTNULLPTR(ret)); /* Check if xMemAlloc() successfully allocated the memory for the task notification - structure. */ + structure. */ if (ISNOTNULLPTR(ret)) { ret->notificationBytes = task_->notificationBytes; - _memcpy_(ret->notificationValue, task_->notificationValue, CONFIG_NOTIFICATION_VALUE_BYTES); + __memcpy__(ret->notificationValue, task_->notificationValue, CONFIG_NOTIFICATION_VALUE_BYTES); task_->notificationBytes = zero; - _memset_(task_->notificationValue, zero, CONFIG_NOTIFICATION_VALUE_BYTES); + __memset__(task_->notificationValue, zero, CONFIG_NOTIFICATION_VALUE_BYTES); } } } @@ -886,17 +883,17 @@ TaskNotification_t *xTaskNotifyTake(Task_t *task_) { /* The xTaskResume() system call will resume a suspended task. Tasks are suspended on creation -so either xTaskResume() or xTaskWait() must be called to place the task in a state that the scheduler -will execute. */ + so either xTaskResume() or xTaskWait() must be called to place the task in a state that the scheduler + will execute. */ void xTaskResume(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { task_->state = TaskStateRunning; } @@ -909,17 +906,17 @@ void xTaskResume(Task_t *task_) { /* The xTaskSuspend() system call will suspend a task. A task that has been suspended -will not be executed by the scheduler until xTaskResume() or xTaskWait() is called. */ + will not be executed by the scheduler until xTaskResume() or xTaskWait() is called. */ void xTaskSuspend(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { task_->state = TaskStateSuspended; } @@ -932,18 +929,18 @@ void xTaskSuspend(Task_t *task_) { /* The xTaskWait() system call will place a task in the waiting state. A task must -be in the waiting state for event driven multitasking with either direct to task -notifications OR setting the period on the task timer with xTaskChangePeriod(). A task -in the waiting state will not be executed by the scheduler until an event has occurred. */ + be in the waiting state for event driven multitasking with either direct to task + notifications OR setting the period on the task timer with xTaskChangePeriod(). A task + in the waiting state will not be executed by the scheduler until an event has occurred. */ void xTaskWait(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { task_->state = TaskStateWaiting; } @@ -956,19 +953,19 @@ void xTaskWait(Task_t *task_) { /* The xTaskChangePeriod() system call will change the period (ticks) on the task timer -for the specified task. The timer period must be greater than zero. To have any effect, the task -must be in the waiting state set by calling xTaskWait() on the task. Once the timer period is set -and the task is in the waiting state, the task will be executed every N ticks based on the period. -Changing the period to zero will prevent the task from being executed even if it is in the waiting state. */ -void xTaskChangePeriod(Task_t *task_, Ticks_t timerPeriod_) { + for the specified task. The timer period must be greater than zero. To have any effect, the task + must be in the waiting state set by calling xTaskWait() on the task. Once the timer period is set + and the task is in the waiting state, the task will be executed every N ticks based on the period. + Changing the period to zero will prevent the task from being executed even if it is in the waiting state. */ +void xTaskChangePeriod(Task_t *task_, const Ticks_t timerPeriod_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { task_->timerPeriod = timerPeriod_; } @@ -980,20 +977,42 @@ void xTaskChangePeriod(Task_t *task_, Ticks_t timerPeriod_) { +/* The xTaskChangeWDPeriod() system call will change the task watchdog timer period. The period, + measured in ticks, must be greater than zero to have any effect. If the tasks last runtime + exceeds the task watchdog timer period, the task will automatically be placed in a suspended + state. */ +void xTaskChangeWDPeriod(Task_t *task_, const Ticks_t wdTimerPeriod_) { + + /* Assert if the task cannot be found. */ + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); + + + /* Check if the task can be found. */ + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { + + task_->wdTimerPeriod = wdTimerPeriod_; + } + + + return; +} + + + /* The xTaskGetPeriod() will return the period for the timer for the specified task. See -xTaskChangePeriod() for more information on how the task timer works. */ -Ticks_t xTaskGetPeriod(Task_t *task_) { + xTaskChangePeriod() for more information on how the task timer works. */ +Ticks_t xTaskGetPeriod(const Task_t *task_) { Ticks_t ret = zero; /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task can be found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { ret = task_->timerPeriod; } @@ -1004,15 +1023,15 @@ Ticks_t xTaskGetPeriod(Task_t *task_) { -/* _TaskListFindTask_() is used to search the task list for a -task and returns RETURN_SUCCESS if the task is found. It also -always checks the health of the heap by calling _MemoryRegionCheckKernel_(). */ -Base_t _TaskListFindTask_(const Task_t *task_) { +/* __TaskListFindTask__() is used to search the task list for a + task and returns RETURN_SUCCESS if the task is found. It also + always checks the health of the heap by calling __MemoryRegionCheckKernel__(). */ +static Base_t __TaskListFindTask__(const Task_t *task_) { Base_t ret = RETURN_FAILURE; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; /* Assert if the task list is not initialized. */ @@ -1027,32 +1046,32 @@ Base_t _TaskListFindTask_(const Task_t *task_) { if ((ISNOTNULLPTR(taskList)) && (ISNOTNULLPTR(task_))) { - /* Assert if _MemoryRegionCheckKernel_() fails on the health check of the heap OR if - the task pointer's entry cannot be found in the heap. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(task_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + /* Assert if __MemoryRegionCheckKernel__() fails on the health check of the heap OR if + the task pointer's entry cannot be found in the heap. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(task_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); - /* Check if _MemoryRegionCheckKernel_() passes on the health check and - the task pointer's entry can be found in the heap. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(task_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + /* Check if __MemoryRegionCheckKernel__() passes on the health check and + the task pointer's entry can be found in the heap. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(task_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { - taskCursor = taskList->head; + cursor = taskList->head; /* Traverse the heap to find the task in the task list. */ - while ((ISNOTNULLPTR(taskCursor)) && (taskCursor != task_)) { + while ((ISNOTNULLPTR(cursor)) && (cursor != task_)) { - taskCursor = taskCursor->next; + cursor = cursor->next; } /* Assert if the task cannot be found. */ - SYSASSERT(ISNOTNULLPTR(taskCursor)); + SYSASSERT(ISNOTNULLPTR(cursor)); /* Check if the task was found, if so then - return success! */ - if (ISNOTNULLPTR(taskCursor)) { + return success! */ + if (ISNOTNULLPTR(cursor)) { ret = RETURN_SUCCESS; @@ -1067,19 +1086,19 @@ Base_t _TaskListFindTask_(const Task_t *task_) { /* The xTaskResetTimer() system call will reset the task timer. xTaskResetTimer() does not change -the timer period or the task state when called. See xTaskChangePeriod() for more details on task timers. */ + the timer period or the task state when called. See xTaskChangePeriod() for more details on task timers. */ void xTaskResetTimer(Task_t *task_) { /* Assert if the task cannot be found. */ - SYSASSERT(RETURN_SUCCESS == _TaskListFindTask_(task_)); + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); /* Check if the task was found. */ - if (RETURN_SUCCESS == _TaskListFindTask_(task_)) { + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { - task_->timerStartTime = _SysGetSysTicks_(); + task_->timerStartTime = __SysGetSysTicks__(); } return; @@ -1095,7 +1114,7 @@ void xTaskStartScheduler(void) { Task_t *runTask = NULL; - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; /* Underflow unsigned least runtime to get maximum value */ Ticks_t leastRunTime = -1; @@ -1110,13 +1129,13 @@ void xTaskStartScheduler(void) { /* Check that the scheduler is not already running and - that the task list is initialized. */ + that the task list is initialized. */ if ((false == SYSFLAG_RUNNING()) && (ISNOTNULLPTR(taskList))) { /* Now set the scheduler system flag to running because - the scheduler IS running. */ + the scheduler IS running. */ SYSFLAG_RUNNING() = true; @@ -1128,51 +1147,51 @@ void xTaskStartScheduler(void) { /* If the runtime overflow flag is true. Reset the runtimes on all of the tasks. */ if (SYSFLAG_OVERFLOW()) { - _RunTimeReset_(); + __RunTimeReset__(); } - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null (i.e., there are further tasks in the task list). */ - while (ISNOTNULLPTR(taskCursor)) { + while (ISNOTNULLPTR(cursor)) { /* If the task pointed to by the task cursor is waiting and it has a notification waiting, then execute it. */ - if ((TaskStateWaiting == taskCursor->state) && (zero < taskCursor->notificationBytes)) { + if ((TaskStateWaiting == cursor->state) && (zero < cursor->notificationBytes)) { - _TaskRun_(taskCursor); + __TaskRun__(cursor); /* If the task pointed to by the task cursor is waiting and its timer has expired, then execute it. */ - } else if ((TaskStateWaiting == taskCursor->state) && (zero < taskCursor->timerPeriod) && ((_SysGetSysTicks_() - taskCursor->timerStartTime) > taskCursor->timerPeriod)) { + } else if ((TaskStateWaiting == cursor->state) && (zero < cursor->timerPeriod) && ((__SysGetSysTicks__() - cursor->timerStartTime) > cursor->timerPeriod)) { - _TaskRun_(taskCursor); + __TaskRun__(cursor); - taskCursor->timerStartTime = _SysGetSysTicks_(); + cursor->timerStartTime = __SysGetSysTicks__(); /* If the task pointed to by the task cursor is running and it's total runtime is less than the - least runtime from previous tasks, then set the run task pointer to the task cursor. This logic - is used to achieve the runtime balancing. */ - } else if ((TaskStateRunning == taskCursor->state) && (leastRunTime > taskCursor->totalRunTime)) { + least runtime from previous tasks, then set the run task pointer to the task cursor. This logic + is used to achieve the runtime balancing. */ + } else if ((TaskStateRunning == cursor->state) && (leastRunTime > cursor->totalRunTime)) { - leastRunTime = taskCursor->totalRunTime; + leastRunTime = cursor->totalRunTime; - runTask = taskCursor; + runTask = cursor; } else { /* Nothing to do here.. Just for MISRA C:2012 compliance. */ } - taskCursor = taskCursor->next; + cursor = cursor->next; } /* If the run task pointer is not null, then there is a running tasks to execute. */ if (ISNOTNULLPTR(runTask)) { - _TaskRun_(runTask); + __TaskRun__(runTask); runTask = NULL; } @@ -1183,8 +1202,6 @@ void xTaskStartScheduler(void) { SYSFLAG_RUNNING() = false; - - } return; @@ -1193,24 +1210,24 @@ void xTaskStartScheduler(void) { -/* If the runtime overflow flag is set, then _RunTimeReset_() is called to reset all of the -total runtimes on tasks to their last runtime. */ -void _RunTimeReset_(void) { +/* If the runtime overflow flag is set, then __RunTimeReset__() is called to reset all of the + total runtimes on tasks to their last runtime. */ +static void __RunTimeReset__(void) { - Task_t *taskCursor = NULL; + Task_t *cursor = NULL; - taskCursor = taskList->head; + cursor = taskList->head; /* While the task cursor is not null (i.e., there are further tasks in the task list). */ - while (ISNOTNULLPTR(taskCursor)) { + while (ISNOTNULLPTR(cursor)) { - taskCursor->totalRunTime = taskCursor->lastRunTime; + cursor->totalRunTime = cursor->lastRunTime; - taskCursor = taskCursor->next; + cursor = cursor->next; } SYSFLAG_OVERFLOW() = false; @@ -1221,20 +1238,24 @@ void _RunTimeReset_(void) { -/* Called by the xTaskStartScheduler() system call, _TaskRun_() executes a task and updates all of its -runtime statistics. */ -void _TaskRun_(Task_t *task_) { +/* Called by the xTaskStartScheduler() system call, __TaskRun__() executes a task and updates all of its + runtime statistics. */ +static void __TaskRun__(Task_t *task_) { Ticks_t taskStartTime = zero; Ticks_t prevTotalRunTime = zero; + + /* Record the total runtime before executing the task. */ prevTotalRunTime = task_->totalRunTime; + + /* Record the start time of the task. */ - taskStartTime = _SysGetSysTicks_(); + taskStartTime = __SysGetSysTicks__(); @@ -1243,18 +1264,30 @@ void _TaskRun_(Task_t *task_) { /* Calculate the runtime and store it in last runtime. */ - task_->lastRunTime = _SysGetSysTicks_() - taskStartTime; + task_->lastRunTime = __SysGetSysTicks__() - taskStartTime; /* Add last runtime to the total runtime. */ task_->totalRunTime += task_->lastRunTime; +#if defined(CONFIG_TASK_WD_TIMER_ENABLE) + /* Check if the task watchdog timer is set and see if the task's last runtime + exceeded it. If it did, set the task state to suspended. */ + if ((zero != task_->wdTimerPeriod) && (task_->lastRunTime > task_->wdTimerPeriod)) { + + + task_->state = TaskStateSuspended; + } +#endif + /* Check if the new total runtime is less than the previous total runtime, - if so an overflow has occurred so set the runtime over flow system flag. */ + if so an overflow has occurred so set the runtime over flow system flag. */ if (task_->totalRunTime < prevTotalRunTime) { SYSFLAG_OVERFLOW() = true; } + + return; } @@ -1262,7 +1295,7 @@ void _TaskRun_(Task_t *task_) { /* The xTaskResumeAll() system call will set the scheduler system flag so the next -call to xTaskStartScheduler() will resume execute of all tasks. */ + call to xTaskStartScheduler() will resume execute of all tasks. */ void xTaskResumeAll(void) { @@ -1275,7 +1308,7 @@ void xTaskResumeAll(void) { /* The xTaskSuspendAll() system call will set the scheduler system flag so the scheduler -will stop and return. */ + will stop and return. */ void xTaskSuspendAll(void) { schedulerState = SchedulerStateSuspended; @@ -1289,4 +1322,36 @@ SchedulerState_t xTaskGetSchedulerState(void) { return schedulerState; -} \ No newline at end of file +} + +/* The xTaskGetWDPeriod() system call will return the current task watchdog + timer period. */ +Ticks_t xTaskGetWDPeriod(const Task_t *task_) { + + + Ticks_t ret = zero; + + + /* Assert if the task cannot be found. */ + SYSASSERT(RETURN_SUCCESS == __TaskListFindTask__(task_)); + + + /* Check if the task can be found. */ + if (RETURN_SUCCESS == __TaskListFindTask__(task_)) { + + ret = task_->wdTimerPeriod; + } + + + return ret; +} + + +#if defined(POSIX_ARCH_OTHER) +void __TaskStateClear__(void) { + + taskList = NULL; + + return; +} +#endif \ No newline at end of file diff --git a/src/task.h b/src/task.h index 5a66d18..4fe1082 100644 --- a/src/task.h +++ b/src/task.h @@ -2,26 +2,26 @@ * @file task.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for task management - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 - * + * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson - * + * Copyright (C) 2020-2023 Manny Peterson + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ #ifndef TASK_H_ #define TASK_H_ @@ -30,8 +30,10 @@ #include "defines.h" #include "types.h" #include "port.h" +#include "device.h" #include "mem.h" #include "queue.h" +#include "stream.h" #include "sys.h" #include "timer.h" @@ -39,37 +41,40 @@ extern "C" { #endif -Task_t *xTaskCreate(const char *name_, void (*callback_)(Task_t *, TaskParm_t *), TaskParm_t *taskParameter_); -void xTaskDelete(Task_t *task_); -Task_t *xTaskGetHandleByName(const char *name_); -Task_t *xTaskGetHandleById(Base_t id_); +Task_t *xTaskCreate(const Char_t *name_, void (*callback_)(Task_t *task_, TaskParm_t *parm_), TaskParm_t *taskParameter_); +void xTaskDelete(const Task_t *task_); +Task_t *xTaskGetHandleByName(const Char_t *name_); +Task_t *xTaskGetHandleById(const Base_t id_); TaskRunTimeStats_t *xTaskGetAllRunTimeStats(Base_t *tasks_); -TaskRunTimeStats_t *xTaskGetTaskRunTimeStats(Task_t *task_); +TaskRunTimeStats_t *xTaskGetTaskRunTimeStats(const Task_t *task_); Base_t xTaskGetNumberOfTasks(void); -TaskInfo_t *xTaskGetTaskInfo(Task_t *task_); +TaskInfo_t *xTaskGetTaskInfo(const Task_t *task_); TaskInfo_t *xTaskGetAllTaskInfo(Base_t *tasks_); -TaskState_t xTaskGetTaskState(Task_t *task_); -char *xTaskGetName(Task_t *task_); -Base_t xTaskGetId(Task_t *task_); +TaskState_t xTaskGetTaskState(const Task_t *task_); +Char_t *xTaskGetName(const Task_t *task_); +Base_t xTaskGetId(const Task_t *task_); void xTaskNotifyStateClear(Task_t *task_); -Base_t xTaskNotificationIsWaiting(Task_t *task_); -Base_t xTaskNotifyGive(Task_t *task_, Base_t notificationBytes_, const char *notificationValue_); +Base_t xTaskNotificationIsWaiting(const Task_t *task_); +Base_t xTaskNotifyGive(Task_t *task_, const Base_t notificationBytes_, const Char_t *notificationValue_); TaskNotification_t *xTaskNotifyTake(Task_t *task_); void xTaskResume(Task_t *task_); void xTaskSuspend(Task_t *task_); void xTaskWait(Task_t *task_); -void xTaskChangePeriod(Task_t *task_, Ticks_t timerPeriod_); -Ticks_t xTaskGetPeriod(Task_t *task_); +void xTaskChangePeriod(Task_t *task_, const Ticks_t timerPeriod_); +Ticks_t xTaskGetPeriod(const Task_t *task_); void xTaskResetTimer(Task_t *task_); void xTaskStartScheduler(void); -void _RunTimeReset_(void); -void _TaskRun_(Task_t *task_); void xTaskResumeAll(void); void xTaskSuspendAll(void); SchedulerState_t xTaskGetSchedulerState(void); -Base_t _TaskListFindTask_(const Task_t *task_); +void xTaskChangeWDPeriod(Task_t *task_, const Ticks_t wdTimerPeriod_); +Ticks_t xTaskGetWDPeriod(const Task_t *task_); + +#if defined(POSIX_ARCH_OTHER) +void __TaskStateClear__(void); +#endif #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/timer.c b/src/timer.c index ac982b1..9e77024 100644 --- a/src/timer.c +++ b/src/timer.c @@ -2,12 +2,12 @@ * @file timer.c * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for timers - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,33 +29,31 @@ - - /* Declare and initialize the task list to null. */ static TimerList_t *timerList = NULL; - +static Base_t __TimerListFindTimer__(const Timer_t *timer_); /* The xTimerCreate() system call will create a new timer. Timers differ from - task timers in that they do not create events that effect the scheduling of a task. - Timers can be used by tasks to initiate various task activities based on a specified - time period represented in ticks. The memory allocated by xTimerCreate() must - be freed by xTimerDelete(). Unlike tasks, timers may be created and deleted within - tasks. */ -Timer_t *xTimerCreate(Ticks_t timerPeriod_) { + task timers in that they do not create events that effect the scheduling of a task. + Timers can be used by tasks to initiate various task activities based on a specified + time period represented in ticks. The memory allocated by xTimerCreate() must + be freed by xTimerDelete(). Unlike tasks, timers may be created and deleted within + tasks. */ +Timer_t *xTimerCreate(const Ticks_t timerPeriod_) { Timer_t *ret = NULL; - Timer_t *timerCursor = NULL; + Timer_t *cursor = NULL; /* Check if the timer list has been initialized. */ if (ISNULLPTR(timerList)) { - timerList = (TimerList_t *)_KernelAllocateMemory_(sizeof(TimerList_t)); + timerList = (TimerList_t *)__KernelAllocateMemory__(sizeof(TimerList_t)); } @@ -69,8 +67,7 @@ Timer_t *xTimerCreate(Ticks_t timerPeriod_) { - - ret = (Timer_t *)_KernelAllocateMemory_(sizeof(Task_t)); + ret = (Timer_t *)__KernelAllocateMemory__(sizeof(Task_t)); /* Assert if xMemAlloc() didn't do its job. */ @@ -85,24 +82,24 @@ Timer_t *xTimerCreate(Ticks_t timerPeriod_) { ret->timerPeriod = timerPeriod_; - ret->timerStartTime = _SysGetSysTicks_(); + ret->timerStartTime = __SysGetSysTicks__(); ret->next = NULL; - timerCursor = timerList->head; + cursor = timerList->head; /* Check if the head of the timer list is null. If so, iterate through the - timer list to find the end otherwise just append the timer to the timer list. */ + timer list to find the end otherwise just append the timer to the timer list. */ if (ISNOTNULLPTR(timerList->head)) { /* While the next timer is not null. */ - while (ISNOTNULLPTR(timerCursor->next)) { + while (ISNOTNULLPTR(cursor->next)) { - timerCursor = timerCursor->next; + cursor = cursor->next; } - timerCursor->next = ret; + cursor->next = ret; } else { @@ -120,9 +117,9 @@ Timer_t *xTimerCreate(Ticks_t timerPeriod_) { /* The xTimerDelete() system call will delete a timer. For more information on timers see the -xTaskTimerCreate() system call. */ -void xTimerDelete(Timer_t *timer_) { - Timer_t *timerCursor = NULL; + xTaskTimerCreate() system call. */ +void xTimerDelete(const Timer_t *timer_) { + Timer_t *cursor = NULL; @@ -130,30 +127,30 @@ void xTimerDelete(Timer_t *timer_) { /* Assert if the timer cannot be found in the timer - list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + list. */ + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { - timerCursor = timerList->head; + cursor = timerList->head; timerPrevious = NULL; /* Check if the timer cursor is not null a if the timer cursor equals - the timer parameter. */ - if ((ISNOTNULLPTR(timerCursor)) && (timerCursor == timer_)) { + the timer parameter. */ + if ((ISNOTNULLPTR(cursor)) && (cursor == timer_)) { - timerList->head = timerCursor->next; + timerList->head = cursor->next; - _KernelFreeMemory_(timerCursor); + __KernelFreeMemory__(cursor); timerList->length--; @@ -161,32 +158,32 @@ void xTimerDelete(Timer_t *timer_) { /* While the timer cursor is not null and the timer cursor is not - equal to the timer parameter, continue to scan the timer list. */ - while ((ISNOTNULLPTR(timerCursor)) && (timerCursor != timer_)) { + equal to the timer parameter, continue to scan the timer list. */ + while ((ISNOTNULLPTR(cursor)) && (cursor != timer_)) { - timerPrevious = timerCursor; + timerPrevious = cursor; - timerCursor = timerCursor->next; + cursor = cursor->next; } /* Assert if the timer is not found though this - shouldn't ever happen. */ - SYSASSERT(ISNOTNULLPTR(timerCursor)); + shouldn't ever happen. */ + SYSASSERT(ISNOTNULLPTR(cursor)); /* Check if the timer was found, if so drop it from - the timer list and free its memory. */ - if (ISNOTNULLPTR(timerCursor)) { + the timer list and free its memory. */ + if (ISNOTNULLPTR(cursor)) { - timerPrevious->next = timerCursor->next; + timerPrevious->next = cursor->next; - _KernelFreeMemory_(timerCursor); + __KernelFreeMemory__(cursor); timerList->length--; } @@ -201,18 +198,18 @@ void xTimerDelete(Timer_t *timer_) { /* The xTimerChangePeriod() system call will change the period of the specified timer. -The timer period is measured in ticks. If the timer period is zero, the xTimerHasTimerExpired() -system call will always return false. */ -void xTimerChangePeriod(Timer_t *timer_, Ticks_t timerPeriod_) { + The timer period is measured in ticks. If the timer period is zero, the xTimerHasTimerExpired() + system call will always return false. */ +void xTimerChangePeriod(Timer_t *timer_, const Ticks_t timerPeriod_) { /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { timer_->timerPeriod = timerPeriod_; } @@ -225,17 +222,17 @@ void xTimerChangePeriod(Timer_t *timer_, Ticks_t timerPeriod_) { /* The xTimerGetPeriod() system call will return the current timer period -for the specified timer. */ -Ticks_t xTimerGetPeriod(Timer_t *timer_) { + for the specified timer. */ +Ticks_t xTimerGetPeriod(const Timer_t *timer_) { Ticks_t ret = zero; /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { ret = timer_->timerPeriod; } @@ -248,21 +245,21 @@ Ticks_t xTimerGetPeriod(Timer_t *timer_) { /* The xTimerIsTimerActive() system call will return true of the timer has been -started with xTimerStart(). */ -Base_t xTimerIsTimerActive(Timer_t *timer_) { + started with xTimerStart(). */ +Base_t xTimerIsTimerActive(const Timer_t *timer_) { Base_t ret = false; /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { /* Check if the timer state is running, if so - return true. */ + return true. */ if (TimerStateRunning == timer_->state) { ret = true; @@ -277,37 +274,37 @@ Base_t xTimerIsTimerActive(Timer_t *timer_) { /* The xTimerHasTimerExpired() system call will return true or false dependent on whether -the timer period for the specified timer has elapsed. xTimerHasTimerExpired() will NOT -reset the timer. Timers must be reset with xTimerReset(). */ -Base_t xTimerHasTimerExpired(Timer_t *timer_) { + the timer period for the specified timer has elapsed. xTimerHasTimerExpired() will NOT + reset the timer. Timers must be reset with xTimerReset(). */ +Base_t xTimerHasTimerExpired(const Timer_t *timer_) { Base_t ret = false; /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { /* Assert if the timer isn't running, it must be for the - timer to expire. */ + timer to expire. */ SYSASSERT(TimerStateRunning == timer_->state); /* Assert if the timer period is zero, it must be greater - than zero for the timer to expire. */ + than zero for the timer to expire. */ SYSASSERT(zero < timer_->timerPeriod); /* The timer should be running, the timer period should be - greater than zero and the elapsed time is greater than - the timer period. If so, then return true. */ - if ((TimerStateRunning == timer_->state) && (zero < timer_->timerPeriod) && ((_SysGetSysTicks_() - timer_->timerStartTime) > timer_->timerPeriod)) { + greater than zero and the elapsed time is greater than + the timer period. If so, then return true. */ + if ((TimerStateRunning == timer_->state) && (zero < timer_->timerPeriod) && ((__SysGetSysTicks__() - timer_->timerStartTime) > timer_->timerPeriod)) { ret = true; } @@ -326,14 +323,14 @@ void xTimerReset(Timer_t *timer_) { /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { - timer_->timerStartTime = _SysGetSysTicks_(); + timer_->timerStartTime = __SysGetSysTicks__(); } return; @@ -343,18 +340,18 @@ void xTimerReset(Timer_t *timer_) { /* The xTimerStart() system call will place the timer in the running state. Neither xTaskStart() nor -xTaskStop() will reset the timer. Timers can only be reset with xTimerReset(). */ + xTaskStop() will reset the timer. Timers can only be reset with xTimerReset(). */ void xTimerStart(Timer_t *timer_) { /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { timer_->state = TimerStateRunning; } @@ -367,17 +364,17 @@ void xTimerStart(Timer_t *timer_) { /* The xTimerStop() system call will place the timer in the stopped state. Neither xTaskStart() nor -xTaskStop() will reset the timer. Timers can only be reset with xTimerReset(). */ + xTaskStop() will reset the timer. Timers can only be reset with xTimerReset(). */ void xTimerStop(Timer_t *timer_) { /* Assert if the timer cannot be found in the timer list. */ - SYSASSERT(RETURN_SUCCESS == _TimerListFindTimer_(timer_)); + SYSASSERT(RETURN_SUCCESS == __TimerListFindTimer__(timer_)); /* Check if the timer was found in the timer list. */ - if (RETURN_SUCCESS == _TimerListFindTimer_(timer_)) { + if (RETURN_SUCCESS == __TimerListFindTimer__(timer_)) { timer_->state = TimerStateSuspended; } @@ -389,16 +386,16 @@ void xTimerStop(Timer_t *timer_) { -/* _TimerListFindTimer_() is used to search the timer list for a -timer and returns RETURN_SUCCESS if the timer is found. It also -always checks the health of the heap by calling _MemoryRegionCheckKernel_(). */ -Base_t _TimerListFindTimer_(const Timer_t *timer_) { +/* __TimerListFindTimer__() is used to search the timer list for a + timer and returns RETURN_SUCCESS if the timer is found. It also + always checks the health of the heap by calling __MemoryRegionCheckKernel__(). */ +static Base_t __TimerListFindTimer__(const Timer_t *timer_) { Base_t ret = RETURN_FAILURE; - Timer_t *timerCursor = NULL; + Timer_t *cursor = NULL; /* Assert if the timer list is not initialized. */ @@ -410,34 +407,34 @@ Base_t _TimerListFindTimer_(const Timer_t *timer_) { /* Check if the timer list is initialized and the timer pointer - is not null. */ + is not null. */ if ((ISNOTNULLPTR(timerList)) && (ISNOTNULLPTR(timer_))) { - /* Assert if the _MemoryRegionCheckKernel_() fails on the health check or is unable - to find the entry for the heap pointer. */ - SYSASSERT(RETURN_SUCCESS == _MemoryRegionCheckKernel_(timer_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); + /* Assert if the __MemoryRegionCheckKernel__() fails on the health check or is unable + to find the entry for the heap pointer. */ + SYSASSERT(RETURN_SUCCESS == __MemoryRegionCheckKernel__(timer_, MEMORY_REGION_CHECK_OPTION_W_ADDR)); - /* Check if _MemoryRegionCheckKernel_() was successful. */ - if (RETURN_SUCCESS == _MemoryRegionCheckKernel_(timer_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { + /* Check if __MemoryRegionCheckKernel__() was successful. */ + if (RETURN_SUCCESS == __MemoryRegionCheckKernel__(timer_, MEMORY_REGION_CHECK_OPTION_W_ADDR)) { - timerCursor = timerList->head; + cursor = timerList->head; /* Traverse the timer list while there is a timer - and the timer is not the timer we are looking for. */ - while ((ISNOTNULLPTR(timerCursor)) && (timerCursor != timer_)) { + and the timer is not the timer we are looking for. */ + while ((ISNOTNULLPTR(cursor)) && (cursor != timer_)) { - timerCursor = timerCursor->next; + cursor = cursor->next; } /* Assert if the timer was never found. */ - SYSASSERT(ISNOTNULLPTR(timerCursor)); + SYSASSERT(ISNOTNULLPTR(cursor)); /* Check if the timer was found. */ - if (ISNOTNULLPTR(timerCursor)) { + if (ISNOTNULLPTR(cursor)) { ret = RETURN_SUCCESS; } @@ -445,4 +442,15 @@ Base_t _TimerListFindTimer_(const Timer_t *timer_) { } return ret; -} \ No newline at end of file +} + + + +#if defined(POSIX_ARCH_OTHER) +void __TimerStateClear__(void) { + + timerList = NULL; + + return; +} +#endif \ No newline at end of file diff --git a/src/timer.h b/src/timer.h index 01b2b98..067d510 100644 --- a/src/timer.h +++ b/src/timer.h @@ -2,12 +2,12 @@ * @file timer.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel sources for timers - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,8 +30,10 @@ #include "defines.h" #include "types.h" #include "port.h" +#include "device.h" #include "mem.h" #include "queue.h" +#include "stream.h" #include "sys.h" #include "task.h" @@ -39,18 +41,22 @@ extern "C" { #endif -Timer_t *xTimerCreate(Ticks_t timerPeriod_); -void xTimerDelete(Timer_t *timer_); -void xTimerChangePeriod(Timer_t *timer_, Ticks_t timerPeriod_); -Ticks_t xTimerGetPeriod(Timer_t *timer_); -Base_t xTimerIsTimerActive(Timer_t *timer_); -Base_t xTimerHasTimerExpired(Timer_t *timer_); +Timer_t *xTimerCreate(const Ticks_t timerPeriod_); +void xTimerDelete(const Timer_t *timer_); +void xTimerChangePeriod(Timer_t *timer_, const Ticks_t timerPeriod_); +Ticks_t xTimerGetPeriod(const Timer_t *timer_); +Base_t xTimerIsTimerActive(const Timer_t *timer_); +Base_t xTimerHasTimerExpired(const Timer_t *timer_); void xTimerReset(Timer_t *timer_); void xTimerStart(Timer_t *timer_); void xTimerStop(Timer_t *timer_); -Base_t _TimerListFindTimer_(const Timer_t *timer_); + + +#if defined(POSIX_ARCH_OTHER) +void __TimerStateClear__(void); +#endif #ifdef __cplusplus -} // extern "C" { +} #endif #endif \ No newline at end of file diff --git a/src/types.h b/src/types.h index 9124860..6b3f5c3 100644 --- a/src/types.h +++ b/src/types.h @@ -2,12 +2,12 @@ * @file types.h * @author Manny Peterson (mannymsp@gmail.com) * @brief Kernel header for kernel type definitions - * @version 0.3.4 + * @version 0.3.5 * @date 2022-01-31 * * @copyright * HeliOS Embedded Operating System - * Copyright (C) 2020-2022 Manny Peterson + * Copyright (C) 2020-2023 Manny Peterson * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +31,9 @@ #include - +/* + * WARNING: MODIFYING THIS FILE MAY HAVE DISASTROUS CONSEQUENCES. YOU'VE BEEN WARNED. + */ typedef enum { @@ -60,23 +62,52 @@ typedef enum { } TimerState_t; +typedef enum { + DeviceStateError, + DeviceStateSuspended, + DeviceStateRunning +} DeviceState_t; - -/* WARNING: Modifying these type defintions may cause serious headaches. You've been warned! */ -typedef void TaskParm_t; -typedef uint8_t Base_t; -typedef uint8_t Byte_t; -typedef void Addr_t; -typedef size_t Size_t; -typedef uint16_t HWord_t; -typedef uint32_t Word_t; -typedef uint32_t Ticks_t; +typedef enum { + DeviceModeReadOnly, + DeviceModeWriteOnly, + DeviceModeReadWrite +} DeviceMode_t; + + +typedef VOID_TYPE TaskParm_t; +typedef UINT8_TYPE Base_t; +typedef UINT8_TYPE Byte_t; +typedef VOID_TYPE Addr_t; +typedef SIZE_TYPE Size_t; +typedef UINT16_TYPE HalfWord_t; +typedef UINT32_TYPE Word_t; +typedef UINT32_TYPE Ticks_t; +typedef UCHAR_TYPE Char_t; + + +typedef struct Device_s { + HalfWord_t uid; + Char_t name[CONFIG_DEVICE_NAME_BYTES]; + DeviceState_t state; + DeviceMode_t mode; + Word_t bytesWritten; + Word_t bytesRead; + Base_t available; + Base_t (*init)(struct Device_s *device_); + Base_t (*config)(struct Device_s *device_, Size_t *size_, Addr_t *config_); + Base_t (*read)(struct Device_s *device_, Size_t *size_, Addr_t *data_); + Base_t (*write)(struct Device_s *device_, Size_t *size_, Addr_t *data_); + Base_t (*simple_read)(struct Device_s *device_, Word_t *data_); + Base_t (*simple_write)(struct Device_s *device_, Word_t *data_); + struct Device_s *next; +} Device_t; typedef struct MemoryEntry_s { - Byte_t free : 1; - Byte_t reserved : 7; - HWord_t blocks; + Byte_t free; + Byte_t reserved; + HalfWord_t blocks; struct MemoryEntry_s *next; } MemoryEntry_t; @@ -85,9 +116,9 @@ typedef struct MemoryEntry_s { typedef struct MemoryRegion_s { volatile Byte_t mem[MEMORY_REGION_SIZE_IN_BYTES]; MemoryEntry_t *start; - HWord_t entrySize; - HWord_t allocations; - HWord_t frees; + HalfWord_t entrySize; + HalfWord_t allocations; + HalfWord_t frees; Word_t minAvailableEver; } MemoryRegion_t; @@ -96,7 +127,7 @@ typedef struct MemoryRegion_s { typedef struct TaskNotification_s { Base_t notificationBytes; - char notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; + Char_t notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; } TaskNotification_t; @@ -104,16 +135,17 @@ typedef struct TaskNotification_s { typedef struct Task_s { Base_t id; - char name[CONFIG_TASK_NAME_BYTES]; + Char_t name[CONFIG_TASK_NAME_BYTES]; TaskState_t state; TaskParm_t *taskParameter; - void (*callback)(struct Task_s *, TaskParm_t *); + void (*callback)(struct Task_s *task_, TaskParm_t *parm_); Base_t notificationBytes; - char notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; + Char_t notificationValue[CONFIG_NOTIFICATION_VALUE_BYTES]; Ticks_t lastRunTime; Ticks_t totalRunTime; Ticks_t timerPeriod; Ticks_t timerStartTime; + Ticks_t wdTimerPeriod; struct Task_s *next; } Task_t; @@ -142,7 +174,7 @@ typedef struct MemoryRegionStats_s { typedef struct TaskInfo_s { Base_t id; - char name[CONFIG_TASK_NAME_BYTES]; + Char_t name[CONFIG_TASK_NAME_BYTES]; TaskState_t state; Ticks_t lastRunTime; Ticks_t totalRunTime; @@ -159,6 +191,12 @@ typedef struct TaskList_s { +typedef struct DeviceList_s { + Base_t length; + Device_t *head; +} DeviceList_t; + + typedef struct Timer_s { TimerState_t state; @@ -179,10 +217,10 @@ typedef struct TimerList_s { typedef struct SysFlags_s { - Byte_t running : 1; - Byte_t overflow : 1; - Byte_t corrupt : 1; - Byte_t reserved : 5; + Base_t running; + Base_t overflow; + Base_t fault; + Base_t reserved; } SysFlags_t; @@ -190,7 +228,7 @@ typedef struct SysFlags_s { typedef struct QueueMessage_s { Base_t messageBytes; - char messageValue[CONFIG_MESSAGE_VALUE_BYTES]; + Char_t messageValue[CONFIG_MESSAGE_VALUE_BYTES]; } QueueMessage_t; @@ -198,7 +236,7 @@ typedef struct QueueMessage_s { typedef struct Message_s { Base_t messageBytes; - char messageValue[CONFIG_MESSAGE_VALUE_BYTES]; + Char_t messageValue[CONFIG_MESSAGE_VALUE_BYTES]; struct Message_s *next; } Message_t; @@ -217,10 +255,19 @@ typedef struct Queue_s { typedef struct SystemInfo_s { - char productName[OS_PRODUCT_NAME_SIZE]; + Char_t productName[OS_PRODUCT_NAME_SIZE]; Base_t majorVersion; Base_t minorVersion; Base_t patchVersion; Base_t numberOfTasks; } SystemInfo_t; + + + +typedef struct StreamBuffer_s { + Byte_t buffer[CONFIG_STREAM_BUFFER_BYTES]; + HalfWord_t length; +} StreamBuffer_t; + + #endif \ No newline at end of file diff --git a/extras/test/bin/.gitkeep b/test/bin/.gitkeep similarity index 100% rename from extras/test/bin/.gitkeep rename to test/bin/.gitkeep diff --git a/test/src/harness/device_harness.c b/test/src/harness/device_harness.c new file mode 100644 index 0000000..d787caa --- /dev/null +++ b/test/src/harness/device_harness.c @@ -0,0 +1,129 @@ +/** + * @file device_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "device_harness.h" + + +void device_harness(void) { + + + Size_t bytes1; + + Addr_t *data1; + + Size_t bytes2; + + Addr_t *data2; + + Word_t *data3; + + Word_t *data4; + + unit_begin("xDeviceRegisterDevice()"); + + + unit_try(RETURN_SUCCESS == xDeviceRegisterDevice(LOOPBACK_self_register)); + + unit_end(); + + + + unit_begin("xDeviceWrite()"); + + bytes1 = 0x26u; + + data1 = NULL; + + data1 = (Byte_t *)xMemAlloc(bytes1); + + memcpy(data1, "THIS IS A TEST OF THE LOOPBACK DEVICE\0", bytes1); + + unit_try(RETURN_SUCCESS == xDeviceWrite(0xFFu, &bytes1, data1)); + + xMemFree(data1); + + unit_end(); + + + + unit_begin("xDeviceIsAvailable()"); + + unit_try(true == xDeviceIsAvailable(0xFFu)); + + unit_end(); + + + + unit_begin("xDeviceRead()"); + + bytes2 = 0x26u; + + data2 = NULL; + + data2 = (Byte_t *)xMemAlloc(bytes2); + + unit_try(RETURN_SUCCESS == xDeviceRead(0xFFu, &bytes2, data2)); + + unit_try(0x26u == bytes2); + + unit_try(zero == strncmp((char *)data2, "THIS IS A TEST OF THE LOOPBACK DEVICE\0", bytes2)); + + xMemFree(data2); + + unit_end(); + + + + unit_begin("xDeviceSimpleWrite()"); + + data3 = (Word_t *)xMemAlloc(sizeof(Word_t)); + + *data3 = 0xFAFAu; + + unit_try(RETURN_SUCCESS == xDeviceSimpleWrite(0xFFu, data3)); + + xMemFree(data3); + + unit_end(); + + + + unit_begin("xDeviceSimpleRead()"); + + data4 = (Word_t *)xMemAlloc(sizeof(Word_t)); + + *data4 = zero; + + unit_try(RETURN_SUCCESS == xDeviceSimpleRead(0xFFu, data4)); + + unit_try(0xFAFAu == *data4); + + unit_end(); + + + + return; +} diff --git a/test/src/harness/device_harness.h b/test/src/harness/device_harness.h new file mode 100644 index 0000000..759e12f --- /dev/null +++ b/test/src/harness/device_harness.h @@ -0,0 +1,53 @@ +/** + * @file device_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef DEVICE_HARNESS_H_ +#define DEVICE_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" +#include "loopback.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void device_harness(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/harness/loopback.c b/test/src/harness/loopback.c new file mode 100644 index 0000000..64168da --- /dev/null +++ b/test/src/harness/loopback.c @@ -0,0 +1,115 @@ +/** + * @file loopback.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief The HeliOS loopback device driver + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "loopback.h" + +#define BUFFER_LENGTH 0xFFu +static Char_t loopback_buffer[BUFFER_LENGTH]; +static HalfWord_t loopback_buffer_size = zero; + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void) { + + /* DO NOT MODIFY THIS FUNCTION */ + + return __RegisterDevice__(DEVICE_UID, (Char_t *)TO_LITERAL(DEVICE_NAME), DEVICE_STATE, DEVICE_MODE, TO_FUNCTION(DEVICE_NAME, _init), + TO_FUNCTION(DEVICE_NAME, _config), TO_FUNCTION(DEVICE_NAME, _read), TO_FUNCTION(DEVICE_NAME, _write), + TO_FUNCTION(DEVICE_NAME, _simple_read), TO_FUNCTION(DEVICE_NAME, _simple_write)); +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_) { + Base_t ret = RETURN_SUCCESS; + + __memset__(loopback_buffer, zero, BUFFER_LENGTH); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_) { + Base_t ret = RETURN_FAILURE; + + /* INSERT CODE TO CONFIGURE DEVICE HERE */ + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_SUCCESS; + + *size_ = loopback_buffer_size; + + __memcpy__(data_, loopback_buffer, *size_); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_) { + Base_t ret = RETURN_SUCCESS; + + loopback_buffer_size = *size_; + + __memcpy__(loopback_buffer, data_, *size_); + + device_->available = true; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_SUCCESS; + + __memcpy__(data_, loopback_buffer, sizeof(Word_t)); + + device_->available = false; + + return ret; +} + + + +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_) { + Base_t ret = RETURN_SUCCESS; + + __memcpy__(loopback_buffer, data_, sizeof(Word_t)); + + + device_->available = true; + + return ret; +} \ No newline at end of file diff --git a/test/src/harness/loopback.h b/test/src/harness/loopback.h new file mode 100644 index 0000000..610f7b6 --- /dev/null +++ b/test/src/harness/loopback.h @@ -0,0 +1,74 @@ +/** + * @file loopback.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief The HeliOS loopback device driver + * @version 0.3.5 + * @date 2022-09-02 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOOPBACK_H_ +#define LOOPBACK_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +/* START: DEVICE DRIVER PARAMATER BLOCK + + IMPORTANT: THE DEVICE NAME MUST BE SUPPLIED HERE AND MUST BE EXACTLY + CONFIG_DEVICE_NAME_BYTES (DEFAULT IS 8) IN LENGTH, IT MAY BE NECESSARY + TO PAD SHORTER DEVICE NAMES. */ +#define DEVICE_NAME LOOPBACK +#define DEVICE_UID 0xFFu +#define DEVICE_MODE DeviceModeReadWrite +#define DEVICE_STATE DeviceStateRunning +/* END: DEVICE DRIVER PARAMATER BLOCK */ + + + +#define CONCAT(a, b) a ## b +#define QUOTE(a) #a +#define TO_FUNCTION(a, b) CONCAT(a, b) +#define TO_LITERAL(a) QUOTE(a) + +#ifdef __cplusplus +extern "C" { +#endif + +Base_t TO_FUNCTION(DEVICE_NAME, _self_register)(void); +Base_t TO_FUNCTION(DEVICE_NAME, _init)(Device_t *device_); +Base_t TO_FUNCTION(DEVICE_NAME, _config)(Device_t *device_, Size_t *size_, Addr_t *config_); +Base_t TO_FUNCTION(DEVICE_NAME, _read)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _write)(Device_t *device_, Size_t *size_, Addr_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_read)(Device_t *device_, Word_t *data_); +Base_t TO_FUNCTION(DEVICE_NAME, _simple_write)(Device_t *device_, Word_t *data_); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/harness/memory_harness.c b/test/src/harness/memory_harness.c new file mode 100644 index 0000000..6445a8d --- /dev/null +++ b/test/src/harness/memory_harness.c @@ -0,0 +1,183 @@ +/** + * @file memory_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "memory_harness.h" + +static Size_t sizes[0x20u] = {0x2532u, 0x1832u, 0x132u, 0x2932u, 0x332u, 0x1432u, 0x1332u, 0x532u, 0x1732u, 0x932u, 0x1432u, 0x2232u, 0x1432u, 0x3132u, 0x032u, 0x1132u, 0x632u, 0x932u, 0x1532u, 0x632u, 0x1832u, 0x132u, 0x1332u, 0x3132u, 0x2732u, 0x1532u, 0x2432u, 0x2932u, 0x2432u, 0x2932u, 0x3032u, 0x2332u}; +static Size_t order[0x20u] = {0x02u, 0x16u, 0x07u, 0x0Cu, 0x06u, 0x00u, 0x0Du, 0x18u, 0x10u, 0x08u, 0x0Au, 0x1Eu, 0x0Bu, 0x0Eu, 0x03u, 0x09u, 0x19u, 0x05u, 0x1Cu, 0x1Du, 0x0Fu, 0x01u, 0x1Au, 0x04u, 0x13u, 0x11u, 0x1Fu, 0x12u, 0x17u, 0x15u, 0x14u, 0x1Bu}; +static MemoryTest_t tests[0x20u]; + + +void memory_harness(void) { + + Size_t i; + Size_t used; + Base_t *mem01; + MemoryRegionStats_t *mem02; + MemoryRegionStats_t *mem03; + + Task_t *mem04 = NULL; + + unit_begin("Unit test for memory region defragmentation routine"); + + i = zero; + used = zero; + + for (i = 0; i < 0x20u; i++) { + tests[i].size = sizes[i]; + + tests[i].blocks = (sizes[i] / CONFIG_MEMORY_REGION_BLOCK_SIZE) + 1; /* ... + 1; Assuming a memory region entry only takes one (1) block - that may not always be true. */ + + if (zero < ((Size_t)(sizes[i] % CONFIG_MEMORY_REGION_BLOCK_SIZE))) { + tests[i].blocks += 1; + } + + tests[i].ptr = (void *)xMemAlloc(sizes[i]); + + unit_try(NULL != tests[i].ptr); + + used += tests[i].blocks * CONFIG_MEMORY_REGION_BLOCK_SIZE; + + unit_try(used == xMemGetUsed()); + + unit_try((tests[i].blocks * CONFIG_MEMORY_REGION_BLOCK_SIZE) == xMemGetSize(tests[i].ptr)); + } + + unit_try(NULL == (void *)xMemAlloc(0x99999u)); + + + for (i = 0; i < 0x20u; i++) { + xMemFree(tests[order[i]].ptr); + } + + unit_try(0x0u == xMemGetUsed()); + + unit_end(); + + + + + unit_begin("xMemAlloc()"); + + mem01 = NULL; + + mem01 = (Base_t *)xMemAlloc(0x32000u); + + unit_try(NULL != mem01); + + unit_end(); + + + + unit_begin("xMemGetUsed()"); + + unit_try(0x32020u == xMemGetUsed()); + + unit_end(); + + + + unit_begin("xMemGetSize()"); + + unit_try(0x32020u == xMemGetSize(mem01)); + + unit_end(); + + + + unit_begin("xMemGetHeapStats()"); + + mem02 = NULL; + + mem02 = xMemGetHeapStats(); + + unit_try(NULL != mem02); + + unit_try(0x63A0u == mem02->availableSpaceInBytes); + + unit_try(0x63A0u == mem02->largestFreeEntryInBytes); + + unit_try(0x63A0u == mem02->minimumEverFreeBytesRemaining); + + unit_try(0x31Du == mem02->numberOfFreeBlocks); + + unit_try(0x63A0u == mem02->smallestFreeEntryInBytes); + + unit_try(0x22u == mem02->successfulAllocations); + + unit_try(0x20u == mem02->successfulFrees); + + unit_end(); + + + + unit_begin("xMemGetKernelStats()"); + + mem03 = NULL; + + mem04 = NULL; + + mem04 = xTaskCreate((Char_t *)"NONE", memory_harness_task, NULL); + + unit_try(NULL != mem04); + + xTaskDelete(mem04); + + mem03 = xMemGetKernelStats(); + + unit_try(NULL != mem03); + + unit_try(0x383C0u == mem03->availableSpaceInBytes); + + unit_try(0x383C0u == mem03->largestFreeEntryInBytes); + + unit_try(0x38340u == mem03->minimumEverFreeBytesRemaining); + + unit_try(0x1C1Eu == mem03->numberOfFreeBlocks); + + unit_try(0x383C0u == mem03->smallestFreeEntryInBytes); + + unit_try(0x2u == mem03->successfulAllocations); + + unit_try(0x1u == mem03->successfulFrees); + + xMemFree(mem01); + + xMemFree(mem02); + + xMemFree(mem03); + + unit_end(); + + return; +} + +void memory_harness_task(Task_t *task_, TaskParm_t *parm_) { + + xTaskSuspendAll(); + + return; +} diff --git a/test/src/harness/memory_harness.h b/test/src/harness/memory_harness.h new file mode 100644 index 0000000..47f2b30 --- /dev/null +++ b/test/src/harness/memory_harness.h @@ -0,0 +1,59 @@ +/** + * @file memory_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef MEMORY_HARNESS_H_ +#define MEMORY_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" + +typedef struct MemoryTest_s { + Size_t size; + Size_t blocks; + void* ptr; +} MemoryTest_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void memory_harness(void); +void memory_harness_task(Task_t *task_, TaskParm_t *parm_); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/test/src/harness/queue_harness.c b/test/src/harness/queue_harness.c new file mode 100644 index 0000000..274957d --- /dev/null +++ b/test/src/harness/queue_harness.c @@ -0,0 +1,190 @@ +/** + * @file queue_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "queue_harness.h" + + +void queue_harness(void) { + + Queue_t *queue01; + + QueueMessage_t *queue02; + + unit_begin("xQueueCreate()"); + + queue01 = NULL; + + queue01 = xQueueCreate(0x4); + + unit_try(NULL == queue01); + + queue01 = xQueueCreate(0x7); + + unit_try(NULL != queue01); + + unit_end(); + + + + unit_begin("xQueueSend()"); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE1")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE2")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE3")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE4")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE5")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE6")); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE7")); + + unit_try(RETURN_FAILURE == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE8")); + + unit_end(); + + + + unit_begin("xQueueGetLength()"); + + unit_try(0x7u == xQueueGetLength(queue01)); + + unit_end(); + + + + unit_begin("xQueueIsQueueEmpty()"); + + unit_try(false == xQueueIsQueueEmpty(queue01)); + + unit_end(); + + + + unit_begin("xQueueIsQueueFull()"); + + unit_try(true == xQueueIsQueueFull(queue01)); + + unit_end(); + + + + unit_begin("xQueueMessagesWaiting()"); + + unit_try(true == xQueueMessagesWaiting(queue01)); + + unit_end(); + + + + unit_begin("xQueuePeek()"); + + queue02 = NULL; + + queue02 = xQueuePeek(queue01); + + unit_try(NULL != queue02); + + unit_try(0x8u == queue02->messageBytes); + + unit_try(0x0u == strncmp("MESSAGE1", (char *)queue02->messageValue, 0x8)); + + xMemFree(queue02); + + unit_end(); + + + + unit_begin("xQueueReceive()"); + + queue02 = xQueueReceive(queue01); + + unit_try(NULL != queue02); + + unit_try(0x8u == queue02->messageBytes); + + unit_try(0x0u == strncmp("MESSAGE1", (char *)queue02->messageValue, 0x8)); + + xMemFree(queue02); + + unit_end(); + + + + unit_begin("xQueueDropMessage()"); + + xQueueDropMessage(queue01); + + unit_try(0x6u != xQueueGetLength(queue01)); + + xQueueDelete(queue01); + + unit_end(); + + + + unit_begin("xQueueLockQueue()"); + + queue01 = xQueueCreate(5); + + unit_try(NULL != queue01); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE1")); + + xQueueLockQueue(queue01); + + unit_try(RETURN_FAILURE == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE2")); + + unit_end(); + + + + unit_begin("xQueueUnlockQueue()"); + + xQueueUnLockQueue(queue01); + + unit_try(RETURN_SUCCESS == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE3")); + + unit_try(0x2u == xQueueGetLength(queue01)); + + unit_end(); + + + + unit_begin("xQueueDelete()"); + + xQueueDelete(queue01); + + unit_try(RETURN_FAILURE == xQueueSend(queue01, 0x8, (Char_t *)"MESSAGE4")); + + unit_end(); + + + return; +} diff --git a/test/src/harness/queue_harness.h b/test/src/harness/queue_harness.h new file mode 100644 index 0000000..f180dbb --- /dev/null +++ b/test/src/harness/queue_harness.h @@ -0,0 +1,52 @@ +/** + * @file queue_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef QUEUE_HARNESS_H_ +#define QUEUE_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void queue_harness(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/harness/stream_harness.c b/test/src/harness/stream_harness.c new file mode 100644 index 0000000..5c5a73d --- /dev/null +++ b/test/src/harness/stream_harness.c @@ -0,0 +1,135 @@ +/** + * @file stream_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-30 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "stream_harness.h" + +void stream_harness(void) { + + StreamBuffer_t *stream01 = NULL; + + HalfWord_t i = zero; + + HalfWord_t stream02 = zero; + + Byte_t *stream03 = NULL; + + + + unit_begin("xStreamCreate()"); + + stream01 = xStreamCreate(); + + unit_try(NULL != stream01); + + unit_end(); + + + + unit_begin("xStreamSend()"); + + for (i = 0; i < CONFIG_STREAM_BUFFER_BYTES; i++) { + + unit_try(RETURN_SUCCESS == xStreamSend(stream01, i)); + } + + unit_try(RETURN_FAILURE == xStreamSend(stream01, zero)); + + unit_end(); + + + + unit_begin("xStreamIsFull()"); + + unit_try(true == xStreamIsFull(stream01)); + + unit_end(); + + + + + unit_begin("xStreamIsEmpty()"); + + unit_try(false == xStreamIsEmpty(stream01)); + + unit_end(); + + + + unit_begin("xStreamBytesAvailable()"); + + unit_try(0x20u == xStreamBytesAvailable(stream01)); + + unit_end(); + + + + unit_begin("xStreamReceive()"); + + stream03 = xStreamReceive(stream01, &stream02); + + unit_try(NULL != stream03); + + unit_try(0x20u == stream02); + + unit_try(0x1Fu == stream03[0x1Fu]); + + unit_end(); + + + + unit_begin("xStreamReset()"); + + for (i = 0; i < CONFIG_STREAM_BUFFER_BYTES; i++) { + + unit_try(RETURN_SUCCESS == xStreamSend(stream01, i)); + } + + unit_try(RETURN_FAILURE == xStreamSend(stream01, zero)); + + unit_try(true == xStreamIsFull(stream01)); + + xStreamReset(stream01); + + unit_try(true == xStreamIsEmpty(stream01)); + + unit_end(); + + + + unit_begin("xStreamDelete()"); + + xStreamReset(stream01); + + xStreamDelete(stream01); + + unit_try(RETURN_FAILURE == xStreamSend(stream01, zero)); + + unit_end(); + + + + return; +} diff --git a/test/src/harness/stream_harness.h b/test/src/harness/stream_harness.h new file mode 100644 index 0000000..e8853a2 --- /dev/null +++ b/test/src/harness/stream_harness.h @@ -0,0 +1,52 @@ +/** + * @file queue_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef STREAM_HARNESS_H_ +#define STREAM_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void stream_harness(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/harness/task_harness.c b/test/src/harness/task_harness.c new file mode 100644 index 0000000..010db21 --- /dev/null +++ b/test/src/harness/task_harness.c @@ -0,0 +1,431 @@ +/** + * @file task_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "task_harness.h" + + +void task_harness(void) { + + Task_t *task01; + Task_t *task02; + Base_t task03; + TaskRunTimeStats_t *task04; + Base_t task05; + Base_t task06; + TaskInfo_t *task07; + Char_t *task08; + TaskNotification_t *task09; + + Task_t *task10 = NULL; + Task_t *task11 = NULL; + Task_t *task12 = NULL; + + + unit_begin("xTaskCreate()"); + + task01 = NULL; + + task01 = xTaskCreate((Char_t *)"TASK01", task_harness_task, NULL); + + unit_try(NULL != task01); + + unit_end(); + + + + unit_begin("xTaskGetHandleByName()"); + + task02 = NULL; + + task02 = xTaskGetHandleByName((Char_t *)"TASK01"); + + unit_try(task02 == task01); + + unit_end(); + + + + unit_begin("xTaskGetHandleById()"); + + task02 = NULL; + + task03 = 0x0; + + task03 = xTaskGetId(task01); + + task02 = xTaskGetHandleById(task03); + + unit_try(task02 == task01); + + unit_end(); + + + + unit_begin("xTaskGetAllRunTimeStats()"); + + task04 = NULL; + task05 = 0; + + task04 = xTaskGetAllRunTimeStats(&task05); + + unit_try(NULL != task04); + + unit_try(0x1 == task05); + + unit_try(0x1 == task04[0].id); + + xMemFree(task04); + + unit_end(); + + + + unit_begin("xTaskGetTaskRunTimeStats()"); + + task04 = NULL; + + task04 = xTaskGetTaskRunTimeStats(task01); + + unit_try(NULL != task04); + + unit_try(0x1 == task04->id); + + xMemFree(task04); + + unit_end(); + + + + unit_begin("xTaskGetNumberOfTasks()"); + + task06 = 0; + + task06 = xTaskGetNumberOfTasks(); + + unit_try(0x1 == task06); + + unit_end(); + + + + unit_begin("xTaskGetTaskInfo()"); + + task07 = NULL; + + task07 = xTaskGetTaskInfo(task01); + + unit_try(NULL != task07); + + unit_try(0x1 == task07->id); + + unit_try(0x0 == strncmp("TASK01", (char *)task07->name, 0x6)); + + unit_try(TaskStateSuspended == task07->state); + + xMemFree(task07); + + unit_end(); + + + + unit_begin("xTaskGetAllTaskInfo()"); + + task07 = NULL; + + task07 = xTaskGetAllTaskInfo(&task06); + + unit_try(NULL != task07); + + unit_try(0x1 == task06); + + unit_try(0x1 == task07->id); + + unit_try(0x0 == strncmp("TASK01", (char *)task07->name, 0x6)); + + unit_try(TaskStateSuspended == task07->state); + + xMemFree(task07); + + unit_end(); + + + + unit_begin("xTaskGetTaskState()"); + + unit_try(TaskStateSuspended == xTaskGetTaskState(task01)); + + unit_end(); + + + + unit_begin("xTaskGetName()"); + + task08 = xTaskGetName(task01); + + unit_try(NULL != task08); + + unit_try(0x0 == strncmp("TASK01", (char *)task08, 0x6)); + + unit_end(); + + + + unit_begin("xTaskGetId()"); + + unit_try(0x1 == xTaskGetId(task01)); + + unit_end(); + + + + unit_begin("xTaskNotifyGive()"); + + unit_try(RETURN_SUCCESS == xTaskNotifyGive(task01, 0x7, (Char_t *)"MESSAGE")); + + unit_end(); + + + + unit_begin("xTaskNotificationIsWaiting()"); + + unit_try(true == xTaskNotificationIsWaiting(task01)); + + unit_end(); + + + + unit_begin("xTaskNotifyStateClear()"); + + xTaskNotifyStateClear(task01); + + unit_try(false == xTaskNotificationIsWaiting(task01)); + + unit_end(); + + + + unit_begin("xTaskNotifyTake()"); + + task09 = NULL; + + unit_try(RETURN_SUCCESS == xTaskNotifyGive(task01, 0x7, (Char_t *)"MESSAGE")); + + task09 = xTaskNotifyTake(task01); + + unit_try(NULL != task09); + + unit_try(0x7 == task09->notificationBytes); + + unit_try(0x0 == strncmp("MESSAGE", (char *)task09->notificationValue, 0x7)); + + xMemFree(task09); + + unit_end(); + + + + unit_begin("xTaskResume()"); + + xTaskResume(task01); + + unit_try(TaskStateRunning == xTaskGetTaskState(task01)); + + unit_end(); + + + + unit_begin("xTaskSuspend()"); + + xTaskSuspend(task01); + + unit_try(TaskStateSuspended == xTaskGetTaskState(task01)); + + unit_end(); + + + + unit_begin("xTaskWait()"); + + xTaskWait(task01); + + unit_try(TaskStateWaiting == xTaskGetTaskState(task01)); + + unit_end(); + + + + unit_begin("xTaskChangePeriod()"); + + xTaskChangePeriod(task01, 0xD05); + + unit_try(0xD05 == xTaskGetPeriod(task01)); + + unit_end(); + + + + unit_begin("xTaskGetPeriod()"); + + xTaskChangePeriod(task01, 0x1E61); + + unit_try(0x1E61 == xTaskGetPeriod(task01)); + + unit_end(); + + + + unit_begin("xTaskResetTimer()"); + + xTaskResetTimer(task01); + + unit_end(); + + + + unit_begin("xTaskGetSchedulerState()"); + + xTaskSuspendAll(); + + unit_try(SchedulerStateSuspended == xTaskGetSchedulerState()); + + xTaskResumeAll(); + + unit_try(SchedulerStateRunning == xTaskGetSchedulerState()); + + unit_end(); + + + + unit_begin("Unit test for task timer event"); + + xTaskResumeAll(); + + xTaskDelete(task01); + + task10 = NULL; + + task10 = xTaskCreate((Char_t *)"TASK10", task_harness_task, NULL); + + unit_try(NULL != task10); + + xTaskChangePeriod(task10, 0xBB8); + + xTaskWait(task10); + + xTaskResetTimer(task10); + + xTaskStartScheduler(); + + xTaskDelete(task10); + + unit_end(); + + + + unit_begin("Unit test for direct to task notification event"); + + xTaskResumeAll(); + + task11 = NULL; + + task11 = xTaskCreate((Char_t *)"TASK11", task_harness_task, NULL); + + unit_try(NULL != task11); + + xTaskWait(task11); + + xTaskNotifyGive(task11, 0x7, (Char_t *)"MESSAGE"); + + unit_try(true == xTaskNotificationIsWaiting(task11)); + + xTaskResumeAll(); + + xTaskStartScheduler(); + + unit_try(false == xTaskNotificationIsWaiting(task11)); + + xTaskDelete(task11); + + unit_end(); + + + + + unit_begin("Unit test for task watchdog timer"); + + xTaskResumeAll(); + + task12 = NULL; + + task12 = xTaskCreate((Char_t *)"TASK12", task_harness_task2, NULL); + + unit_try(NULL != task12); + + xTaskChangeWDPeriod(task12, 0x7D0u); + + xTaskResume(task12); + + unit_try(TaskStateRunning == xTaskGetTaskState(task12)); + + xTaskStartScheduler(); + + unit_try(TaskStateSuspended == xTaskGetTaskState(task12)); + + unit_end(); + + + + + unit_begin("xTaskGetWDPeriod()"); + + unit_try(0x7D0u == xTaskGetWDPeriod(task12)); + + unit_end(); + + + + + return; +} + +void task_harness_task(Task_t *task_, TaskParm_t *parm_) { + + xTaskNotifyStateClear(task_); + + xTaskSuspendAll(); + + return; +} + +void task_harness_task2(Task_t *task_, TaskParm_t *parm_) { + + sleep(3); + + xTaskSuspendAll(); + + return; +} diff --git a/test/src/harness/task_harness.h b/test/src/harness/task_harness.h new file mode 100644 index 0000000..20996a3 --- /dev/null +++ b/test/src/harness/task_harness.h @@ -0,0 +1,54 @@ +/** + * @file task_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef TASK_HARNESS_H_ +#define TASK_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void task_harness(void); +void task_harness_task(Task_t* task_, TaskParm_t* parm_); +void task_harness_task2(Task_t* task_, TaskParm_t* parm_); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/harness/timer_harness.c b/test/src/harness/timer_harness.c new file mode 100644 index 0000000..ca944b1 --- /dev/null +++ b/test/src/harness/timer_harness.c @@ -0,0 +1,128 @@ +/** + * @file timer_harness.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "timer_harness.h" + + +void timer_harness(void) { + + Timer_t* timer01 = NULL; + + unit_begin("xTimerCreate()"); + + timer01 = NULL; + + timer01 = xTimerCreate(0x3E8); + + unit_try(NULL != timer01); + + unit_end(); + + + + unit_begin("xTimerGetPeriod()"); + + unit_try(0x3E8 == xTimerGetPeriod(timer01)); + + unit_end(); + + + + unit_begin("xTimerChangePeriod()"); + + xTimerChangePeriod(timer01, 0x7D0); + + unit_try(0x7D0 == xTimerGetPeriod(timer01)); + + unit_end(); + + + + unit_begin("xTimerIsTimerActive()"); + + unit_try(false == xTimerIsTimerActive(timer01)); + + unit_end(); + + + + unit_begin("xTimerHasTimerExpired()"); + + unit_try(false == xTimerHasTimerExpired(timer01)); + + xTimerStart(timer01); + + sleep(3); + + unit_try(true == xTimerHasTimerExpired(timer01)); + + unit_end(); + + + + unit_begin("xTimerStop()"); + + xTimerStop(timer01); + + unit_try(false == xTimerIsTimerActive(timer01)); + + unit_end(); + + + + unit_begin("xTimerStart()"); + + xTimerStart(timer01); + + unit_try(true == xTimerIsTimerActive(timer01)); + + unit_end(); + + + + unit_begin("xTimerReset()"); + + unit_try(true == xTimerHasTimerExpired(timer01)); + + xTimerReset(timer01); + + unit_try(false == xTimerHasTimerExpired(timer01)); + + unit_end(); + + + + unit_begin("xTimerDelete()"); + + xTimerDelete(timer01); + + unit_try(0x0u == xTimerGetPeriod(timer01)); + + unit_end(); + + return; +} diff --git a/test/src/harness/timer_harness.h b/test/src/harness/timer_harness.h new file mode 100644 index 0000000..0eb80a5 --- /dev/null +++ b/test/src/harness/timer_harness.h @@ -0,0 +1,52 @@ +/** + * @file timer_harness.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef TIMER_HARNESS_H_ +#define TIMER_HARNESS_H_ + +#include "config.h" +#include "defines.h" +#include "types.h" +#include "port.h" +#include "device.h" +#include "mem.h" +#include "queue.h" +#include "stream.h" +#include "sys.h" +#include "task.h" +#include "timer.h" + +#include "unit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void timer_harness(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/test.c b/test/src/test.c new file mode 100644 index 0000000..3963290 --- /dev/null +++ b/test/src/test.c @@ -0,0 +1,81 @@ +/** + * @file test.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief Source code for HeliOS unit testing + * @version 0.3.5 + * @date 2022-08-23 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "test.h" + +int main(int argc, char **argv) { + + unit_init(); + + + + reset(); + + memory_harness(); + + + + reset(); + + queue_harness(); + + + + reset(); + + timer_harness(); + + + + reset(); + + task_harness(); + + + reset(); + + stream_harness(); + + + reset(); + + device_harness(); + + + unit_exit(); + + return 0; +} + +void reset(void) { + + __MemoryClear__(); + __SysStateClear__(); + __TaskStateClear__(); + __TimerStateClear__(); + __DeviceStateClear__(); + + return; +} diff --git a/test/src/test.h b/test/src/test.h new file mode 100644 index 0000000..fd482ed --- /dev/null +++ b/test/src/test.h @@ -0,0 +1,47 @@ +/** + * @file test.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief + * @version 0.3.5 + * @date 2022-08-27 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef TEST_H_ +#define TEST_H_ + +#include "unit.h" +#include "memory_harness.h" +#include "queue_harness.h" +#include "task_harness.h" +#include "timer_harness.h" +#include "stream_harness.h" +#include "device_harness.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int main(int argc, char **argv); +void reset(void); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/test/src/unit/unit.c b/test/src/unit/unit.c new file mode 100644 index 0000000..5011b07 --- /dev/null +++ b/test/src/unit/unit.c @@ -0,0 +1,151 @@ +/** + * @file unit.c + * @author Manny Peterson (mannymsp@gmail.com) + * @brief A simple unit testing framework for HeliOS + * @version 0.3.5 + * @date 2022-08-23 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "unit.h" + +static unit_t *unit = NULL; + +void unit_init(void) { + + + + + if (NULL == unit) { + + + unit = (unit_t *)calloc(1, sizeof(unit_t)); + + printf("unit: intializing...\n"); + } + + + + return; +} + +void unit_begin(const char *name_) { + + + if ((NULL != unit) & (NULL != name_) & (false == unit->begun)) { + + + strncpy(unit->name, name_, UNIT_NAME_LENGTH); + + + unit->begun = true; + + + unit->failed = false; + + printf("unit: begin: %s\n", unit->name); + } + + return; +} + +void unit_try(int expr_) { + + + if ((NULL != unit) & (true == unit->begun) & (false == expr_)) { + + unit->failed = true; + } + + + return; +} + +void unit_end(void) { + + + if ((NULL != unit) & (true == unit->begun)) { + + + if (true == unit->failed) { + + + printf("unit: end: %s failed\n", unit->name); + + + + unit->fail++; + + + } else { + + printf("unit: end: %s\n", unit->name); + + unit->pass++; + } + + + memset(unit->name, 0x0, UNIT_NAME_LENGTH); + + + unit->begun = false; + + + unit->failed = false; + } + + + + return; +} + + +void unit_exit(void) { + + + if (NULL != unit) { + + printf("unit: failed = %" PRId32 "\n", unit->fail); + + + printf("unit: passed = %" PRId32 "\n", unit->pass); + + + printf("unit: total = %" PRId32 "\n", unit->fail + unit->pass); + + + printf("unit: exiting...\n"); + + free(unit); + + if (0x0 < unit->fail) { + + + exit(0x1); + + + } else { + + + exit(0x0); + } + } + + return; +} diff --git a/test/src/unit/unit.h b/test/src/unit/unit.h new file mode 100644 index 0000000..9fe669e --- /dev/null +++ b/test/src/unit/unit.h @@ -0,0 +1,81 @@ +/** + * @file unit.h + * @author Manny Peterson (mannymsp@gmail.com) + * @brief A simple unit testing framework for HeliOS + * @version 0.3.5 + * @date 2022-08-23 + * + * @copyright + * HeliOS Embedded Operating System + * Copyright (C) 2020-2023 Manny Peterson + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef UNIT_H_ +#define UNIT_H_ + +#include "posix.h" + +#include +#include +#include +#include +#include +#include + +#if !defined(UNIT_NAME_LENGTH) +#define UNIT_NAME_LENGTH 0x40 /* 64 */ +#endif + +#if !defined(true) +#define true 0x1 /* 1 */ +#endif + +#if !defined(false) +#define false 0x0 /* 0 */ +#endif + +#if !defined(NULL) +#if !defined(__cplusplus) +#define NULL ((void *)0x0) /* 0 */ +#else +#define NULL 0x0 /* 0 */ +#endif +#endif + +typedef struct unit_s { + char name[UNIT_NAME_LENGTH]; + int32_t begun; + int32_t failed; + int32_t pass; + int32_t fail; +} unit_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void unit_init(void); +void unit_begin(const char *name_); +void unit_try(int expr_); +void unit_end(void); +void unit_exit(void); + +#ifdef __cplusplus +} +#endif + + +#endif \ No newline at end of file