From 5e1dab36c685f81969b6d482bf36c0c34295762c Mon Sep 17 00:00:00 2001 From: Matias N Date: Mon, 20 Jul 2020 19:18:26 -0300 Subject: [PATCH] sphinx doc --- .github/workflows/build.yml | 4 + .github/workflows/check.yml | 2 + .github/workflows/doc.yml | 2 + .github/workflows/sphinx-docs.yml | 56 + Documentation/NuttXCCodingStandard.html | 3127 --------------- Documentation/NuttXGettingStarted.html | 25 - Documentation/README.html | 649 --- Documentation/backgd.gif | Bin 1097 -> 0 bytes Documentation/redirect.html | 20 - doc/.gitignore | 1 + doc/Makefile | 22 + doc/Pipfile | 14 + doc/Pipfile.lock | 244 ++ doc/_static/custom.css | 25 + doc/_static/favicon.ico | Bin 0 -> 4286 bytes doc/applications/index.rst | 6 + doc/boards/index.rst | 8 + doc/components/binfmt.rst | 372 ++ doc/components/drivers/index.rst | 941 +++++ doc/components/filesystem.rst | 43 + doc/components/index.rst | 20 + doc/components/nsh/builtin.rst | 204 + doc/components/nsh/commands.rst | 1692 ++++++++ doc/components/nsh/config.rst | 486 +++ doc/components/nsh/customizing.rst | 213 + doc/components/nsh/index.rst | 18 + doc/components/nsh/installation.rst | 187 + doc/components/nsh/login.rst | 261 ++ doc/components/nsh/nsh.rst | 361 ++ doc/components/nxflat.rst | 469 +++ .../components/nxgraphics}/NXOrganization.gif | Bin .../nxgraphics}/NuttXScreenShot.jpg | Bin doc/components/nxgraphics/appendix.rst | 657 +++ doc/components/nxgraphics/index.rst | 174 + doc/components/nxgraphics/nx.rst | 742 ++++ doc/components/nxgraphics/nxcursor.rst | 50 + doc/components/nxgraphics/nxfonts.rst | 127 + doc/components/nxgraphics/nxgl.rst | 259 ++ doc/components/nxgraphics/nxtk.rst | 732 ++++ doc/components/nxgraphics/sample.rst | 30 + doc/components/nxwidgets.rst | 59 + doc/components/paging.rst | 423 ++ {Documentation => doc/components}/pm.png | Bin doc/components/power.rst | 241 ++ doc/components/syslog.rst | 511 +++ doc/conf.py | 85 + doc/contributing/coding_style.rst | 2656 +++++++++++++ doc/contributing/documentation.rst | 170 + doc/contributing/index.rst | 15 + doc/contributing/workflow.rst | 7 + doc/guides/index.rst | 8 + doc/guides/nfs.rst | 285 ++ doc/guides/usbtrace.rst | 214 + doc/index.rst | 30 + doc/introduction/about.rst | 277 ++ doc/introduction/detailed_support.rst | 3536 +++++++++++++++++ doc/introduction/development_environments.rst | 153 + doc/introduction/index.rst | 17 + doc/introduction/licensing.rst | 9 + doc/introduction/resources.rst | 23 + doc/introduction/supported_platforms.rst | 430 ++ doc/introduction/trademarks.rst | 30 + doc/make.bat | 35 + doc/quickstart/config_build.rst | 131 + doc/quickstart/index.rst | 15 + doc/quickstart/organization.rst | 501 +++ doc/reference/index.rst | 14 + doc/reference/os/addrenv.rst | 305 ++ doc/reference/os/app_vs_os.rst | 103 + doc/reference/os/arch.rst | 329 ++ doc/reference/os/board.rst | 74 + doc/reference/os/boardctl.rst | 40 + doc/reference/os/conventions.rst | 101 + doc/reference/os/index.rst | 25 + doc/reference/os/iob.rst | 310 ++ doc/reference/os/led.rst | 122 + doc/reference/os/nuttx.rst | 50 + doc/reference/os/paging.rst | 13 + doc/reference/os/shm.rst | 38 + doc/reference/os/smp.rst | 99 + doc/reference/os/time_clock.rst | 660 +++ doc/reference/os/wqueue.rst | 307 ++ doc/reference/user/01_task_control.rst | 887 +++++ doc/reference/user/02_task_scheduling.rst | 180 + doc/reference/user/03_task_control.rst | 458 +++ doc/reference/user/04_message_queue.rst | 375 ++ doc/reference/user/05_counting_semaphore.rst | 455 +++ doc/reference/user/06_clocks_timers.rst | 360 ++ doc/reference/user/07_signals.rst | 514 +++ doc/reference/user/08_pthread.rst | 1710 ++++++++ doc/reference/user/09_env_vars.rst | 95 + doc/reference/user/10_filesystem.rst | 573 +++ doc/reference/user/11_network.rst | 417 ++ doc/reference/user/12_shared_memory.rst | 202 + doc/reference/user/index.rst | 28 + doc/reference/user/structures.rst | 169 + doc/releases/index.rst | 6 + doc/requirements.txt | 3 + doc/substitutions.rst | 5 + 99 files changed, 27310 insertions(+), 3821 deletions(-) create mode 100644 .github/workflows/sphinx-docs.yml delete mode 100644 Documentation/NuttXCCodingStandard.html delete mode 100644 Documentation/NuttXGettingStarted.html delete mode 100644 Documentation/README.html delete mode 100644 Documentation/backgd.gif delete mode 100644 Documentation/redirect.html create mode 100644 doc/.gitignore create mode 100644 doc/Makefile create mode 100644 doc/Pipfile create mode 100644 doc/Pipfile.lock create mode 100644 doc/_static/custom.css create mode 100644 doc/_static/favicon.ico create mode 100644 doc/applications/index.rst create mode 100644 doc/boards/index.rst create mode 100644 doc/components/binfmt.rst create mode 100644 doc/components/drivers/index.rst create mode 100644 doc/components/filesystem.rst create mode 100644 doc/components/index.rst create mode 100644 doc/components/nsh/builtin.rst create mode 100644 doc/components/nsh/commands.rst create mode 100644 doc/components/nsh/config.rst create mode 100644 doc/components/nsh/customizing.rst create mode 100644 doc/components/nsh/index.rst create mode 100644 doc/components/nsh/installation.rst create mode 100644 doc/components/nsh/login.rst create mode 100644 doc/components/nsh/nsh.rst create mode 100644 doc/components/nxflat.rst rename {Documentation => doc/components/nxgraphics}/NXOrganization.gif (100%) rename {Documentation => doc/components/nxgraphics}/NuttXScreenShot.jpg (100%) create mode 100644 doc/components/nxgraphics/appendix.rst create mode 100644 doc/components/nxgraphics/index.rst create mode 100644 doc/components/nxgraphics/nx.rst create mode 100644 doc/components/nxgraphics/nxcursor.rst create mode 100644 doc/components/nxgraphics/nxfonts.rst create mode 100644 doc/components/nxgraphics/nxgl.rst create mode 100644 doc/components/nxgraphics/nxtk.rst create mode 100644 doc/components/nxgraphics/sample.rst create mode 100644 doc/components/nxwidgets.rst create mode 100644 doc/components/paging.rst rename {Documentation => doc/components}/pm.png (100%) create mode 100644 doc/components/power.rst create mode 100644 doc/components/syslog.rst create mode 100644 doc/conf.py create mode 100644 doc/contributing/coding_style.rst create mode 100644 doc/contributing/documentation.rst create mode 100644 doc/contributing/index.rst create mode 100644 doc/contributing/workflow.rst create mode 100644 doc/guides/index.rst create mode 100644 doc/guides/nfs.rst create mode 100644 doc/guides/usbtrace.rst create mode 100644 doc/index.rst create mode 100644 doc/introduction/about.rst create mode 100644 doc/introduction/detailed_support.rst create mode 100644 doc/introduction/development_environments.rst create mode 100644 doc/introduction/index.rst create mode 100644 doc/introduction/licensing.rst create mode 100644 doc/introduction/resources.rst create mode 100644 doc/introduction/supported_platforms.rst create mode 100644 doc/introduction/trademarks.rst create mode 100644 doc/make.bat create mode 100644 doc/quickstart/config_build.rst create mode 100644 doc/quickstart/index.rst create mode 100644 doc/quickstart/organization.rst create mode 100644 doc/reference/index.rst create mode 100644 doc/reference/os/addrenv.rst create mode 100644 doc/reference/os/app_vs_os.rst create mode 100644 doc/reference/os/arch.rst create mode 100644 doc/reference/os/board.rst create mode 100644 doc/reference/os/boardctl.rst create mode 100644 doc/reference/os/conventions.rst create mode 100644 doc/reference/os/index.rst create mode 100644 doc/reference/os/iob.rst create mode 100644 doc/reference/os/led.rst create mode 100644 doc/reference/os/nuttx.rst create mode 100644 doc/reference/os/paging.rst create mode 100644 doc/reference/os/shm.rst create mode 100644 doc/reference/os/smp.rst create mode 100644 doc/reference/os/time_clock.rst create mode 100644 doc/reference/os/wqueue.rst create mode 100644 doc/reference/user/01_task_control.rst create mode 100644 doc/reference/user/02_task_scheduling.rst create mode 100644 doc/reference/user/03_task_control.rst create mode 100644 doc/reference/user/04_message_queue.rst create mode 100644 doc/reference/user/05_counting_semaphore.rst create mode 100644 doc/reference/user/06_clocks_timers.rst create mode 100644 doc/reference/user/07_signals.rst create mode 100644 doc/reference/user/08_pthread.rst create mode 100644 doc/reference/user/09_env_vars.rst create mode 100644 doc/reference/user/10_filesystem.rst create mode 100644 doc/reference/user/11_network.rst create mode 100644 doc/reference/user/12_shared_memory.rst create mode 100644 doc/reference/user/index.rst create mode 100644 doc/reference/user/structures.rst create mode 100644 doc/releases/index.rst create mode 100644 doc/requirements.txt create mode 100644 doc/substitutions.rst diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a20e7db5403..cf000659397 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,11 @@ name: Build on: pull_request: + paths-ignore: + - 'doc/**' push: + paths-ignore: + - 'doc/**' branches: - master - 'releases/*' diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 9f031bfff67..924113596c0 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -14,6 +14,8 @@ name: Check on: pull_request: + paths-ignore: + - 'doc/**' jobs: check: diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index ead2d42ff88..c32f707ddef 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -14,6 +14,8 @@ name: Doc on: pull_request: + paths: + - 'docs/**' jobs: docs: diff --git a/.github/workflows/sphinx-docs.yml b/.github/workflows/sphinx-docs.yml new file mode 100644 index 00000000000..b324527dee0 --- /dev/null +++ b/.github/workflows/sphinx-docs.yml @@ -0,0 +1,56 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +name: "Build Sphinx Docs" +on: + pull_request: + push: + branches: + - master + - docs + - 'releases/*' + tags: + +jobs: + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: ammaraskar/sphinx-action@master + with: + docs-folder: "doc/" + - uses: actions/upload-artifact@v2 + with: + name: sphinx-docs + path: doc/_build/html/ + - name: Commit documentation changes + if: github.event_name != 'pull_request' + run: | + git clone https://github.com/v01d/incubator-nuttx.git --branch gh-pages --single-branch gh-pages + cd gh-pages + rm -rf ${GITHUB_REF##*/} + mkdir -p ${GITHUB_REF##*/} + cd ${GITHUB_REF##*/} + cp -r ../../doc/_build/html/* . + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add . + git commit -m "Update documentation" -a || true + # The above command will fail if no changes were present, so we ignore + # the return code. + - name: Push changes + if: github.event_name != 'pull_request' + uses: ad-m/github-push-action@master + with: + branch: gh-pages + directory: gh-pages + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Documentation/NuttXCCodingStandard.html b/Documentation/NuttXCCodingStandard.html deleted file mode 100644 index 02c835bcc9c..00000000000 --- a/Documentation/NuttXCCodingStandard.html +++ /dev/null @@ -1,3127 +0,0 @@ - - -NuttX C Coding Standard - - - - - -
- - -
-

- - - - -
-

- NuttX C Coding Standard -

-

Last Updated: May 19, 2020

-
-

- - - - - -
-

1.0 General Conventions

-
- -

1.1 File Organization

- -

- File Extensions - Use the .h extension for C header files and .c for C source files. -

-

- File header. - Every C, C++, make file, or script begins with a file header. - That file header is enclosed with a block comment (see below). - Within the block comment, the following must appear: -

-
    -
  • - The relative path to the file from the top-level directory. -
  • -
  • - An optional, one-line description of the file contents. -
  • -
  • - A blank line -
  • -
  • - A copyright notice indented two additional spaces -
  • -
  • - A line identifying the author and contact information with the same indentation as the copyright notice. -
  • -
  • - A blank line
  • -
  • - NuttX standard Apache 2.0 licensing information as provided in the appendix. -
  • -
-

- Sample File Headers. - Sample file headers are provided in an Appendix to this document. - No new software may be included in the NuttX source tree that does not have licensing information included in the file. - No new software may be included in the NuttX source tree that does not have a Apache 2.0 license or license (or, in the case of 3rd party file, a compatible license such as the BSD or MIT licenses). - If the file does not follow Apache 2.0 licensing, then the appropriate license information should be provided in the header rather than the Apache 2.0 licensing information and a NOTE should be included in the top-level COPYING file to indicate any variations from Apache 2.0 licensing. -

-

- Grouping. - All like components in a C source or header file are grouped together. - Definitions do not appear arbitrarily through the file, rather, like definitions are grouped together and preceded by a block comment identifying the grouping. -

-

- Block Comments. - Each grouping in the file is separated with a block comment. - The block comment consists of: -

-
    -
  • - A line that consists of the opening C comment (/*) followed by a series of asterisks extending to the length of the line (usually to column 78). -
  • -
  • - The name of the grouping, starting at column 4. - An asterisk preceives the name of the grouping in column 1. -
  • -
  • - A line that consists of the closing C comment (*/) at the end of the line (usually column 78) preceded by a series of asterisks extending to column 1. -
  • -
-

- Examples of Block Comments. - See Appendix A for examples of block comments. -

-

- Order of Groupings. - The following groupings should appear in all C source files in the following order: -

-
    -
  1. - Included Files -
  2. -
  3. - Pre-processor Definitions -
  4. -
  5. - Private Types (definitions) -
  6. -
  7. - Private Function Prototypes (declarations) -
  8. -
  9. - Private Data (definitions) -
  10. -
  11. - Public Data (definitions) -
  12. -
  13. - Private Functions (definitions) -
  14. -
  15. - Public Functions (definitions) -
  16. -
-

- The following groupings should appear in all C header files in the following order: -

-
    -
  1. - Included Files -
  2. -
  3. - Pre-processor Definitions -
  4. -
  5. - Public Types (definitions) -
  6. -
  7. - Public Data (declarations) -
  8. -
  9. - Inline Functions (definitions) -
  10. -
  11. - Public Function Prototypes (declarations) -
  12. -
-

- Large vs. Small Files. - In larger files, block comments should be included for all groupings, even if they are empty; - the empty grouping provides important information in itself. - Smaller files may omit some of the block comments; - it is awkard if the block comments are larger than the file content! -

-

- Header File Idempotence. - C header file must protect against multiple inclusion through the use of macros that "guard" against multiple definitions if the header file is included multiple times. -

-
    -
  • -

    - Each header file must contain the following pre-processor conditional logic near the beginning of the header file: Between the file header and the "Included Files" block comment. - For example, -

    -
      -#ifndef __INCLUDE_NUTTX_ARCH_H
      -#define __INCLUDE_NUTTX_ARCH_H
      -
    -

    - Notice that the definitions within of the header do not follow the usually rules: - The presence of the conditional test at the top of the file does not cause the - remaining definitions within the file to be indented. -

    -
  • -
  • -

    - Then conditional compilation is closed at the fine line of the header file with: -

    -
      -#endif /* __INCLUDE_NUTTX_ARCH_H */
      -
    -
  • -
-

- Forming Guard Names. - Then pre-processor macro name used in the guard is formed from the full, relative path to the header for from the top-level, controlled directory. - That path is preceded by __ and _ replaces each character that would otherwise be invalid in a macro name. - So, for example, __INCLUDE_NUTTX_ARCH_H corresponds to the header file include/nuttx/arch.h -

- -

- Deoxygen Information. - NuttX does not use Deoxygen for documentation and no file should contain Doxygen tags or Doxygen style comments. -

- -

- Sample File Formats. - C source and header file templates are provided in an Appendix to this document. -

- -

1.2 Lines

-

- Line Endings. - Files should be formatted with the newline character (\n) as the line ending (Unix-style line endings) and specifically not the carriage return, newline sequence (\r\n) used with Windows-style line endings. - There should be no extra whitespace at the end of the line. - In addition, all text files should end in a single newline (\n). This avoids the "No newline at end of file" warning generated by certain tools. -

- -

- Line Width. - Text should not extend past column 78 in the typical C source or header file. - Sometimes the nature of the content of a file may require that the lines exceed this limit. - This often occurs in header files with naturally long definitions. - If the line width must extend 78 lines, then some wider line width may be used in the file provided that it is used consistently. -

- -

- Line Wrapping. -

-
- - -
-

Incorrect

-
    -  struct some_long_struct_name_s
    -  {
    -    struct some_long_struct_name_s *flink;  /* The forward link to the next instance of struct some_long_struct_name_s in a singly linked list */
    -    int short_name1;   /* Short comment 1 */
    -    int short_name2;   /* This is a very long comment describing subtle aspects of the short_name2 field */
    -  };
    -
    -  struct some_medium_name_s *ptr = (struct some_medium_name_s *)malloc(sizeof(some_medium_name_s);
    -
    -  struct some_long_struct_name_s *ptr = (struct some_long_struct_name_s *)malloc(sizeof(some_long_struct_name_s);
    -
    -  ret = some_function_with_many parameters(long_parameter_name_1, long_parameter_name_2, long_parameter_name_3, long_parameter_name_4, long_parameter_name_5, long_parameter_name_6, long_parameter_name_7, long_parameter_name_8);
    -
    -  ret = some_function_with_many parameters(long_parameter_name_1,
    -    long_parameter_name_2,
    -    long_parameter_name_3
    -    long_parameter_name_4,
    -    long_parameter_name_5,
    -    long_parameter_name_6,
    -    long_parameter_name_7,
    -    long_parameter_name_8);
    -
-
-

Correct

-
    -  struct some_long_struct_name_s
    -  {
    -    /* The forward link to the next instance of struct
    -     * some_long_struct_name_s in a singly linked list.
    -     */
    -
    -    struct some_long_struct_name_s *flink;
    -    int short_name1;   /* Short comment 1. */
    -    int short_name2;   /* This is a very long comment describing subtle
    -                        * aspects of the short_name2 field. */
    -  };
    -
    -  FAR struct some_medium_name_s *ptr = (FAR struct some_medium_name_s *)
    -    malloc(sizeof(some_medium_name_s);
    -
    -  FAR struct some_medium_name_s *ptr =
    -    (FAR struct some_medium_name_s *)malloc(sizeof(some_medium_name_s);
    -
    -  FAR struct some_long_struct_name_s *ptr =
    -    (FAR struct some_long_struct_name_s *)
    -      malloc(sizeof(some_long_struct_name_s);
    -
    -  ret = some_function_with_many parameters(long_parameter_name_1,
    -                                           long_parameter_name_2,
    -                                           long_parameter_name_3,
    -                                           long_parameter_name_4,
    -                                           long_parameter_name_5,
    -                                           long_parameter_name_6,
    -                                           long_parameter_name_7,
    -                                           long_parameter_name_8);
    -
-
- -

- NOTE: - See the discussion of pointers for information about the FAR qualifier used above. -

- -

- Double Spacing. - A single blank line may be use to separate logical groupings as the designer feels fit. - Single blank lines are also required in certain contexts as defined in this standard. - Additional blanks lines (two or more) are prohibited. -

- -

- Columnar Organization. - Similar things should be aligned on the same column unless doing so would cause the line width to be exceeded. -

-
- - -
-

Acceptable

-
    -  dog = cat;
    -  monkey = oxen;
    -  aardvark = macaque;
    -
-
-

Preferred

-
    -  dog      = cat;
    -  monkey   = oxen;
    -  aardvark = macaque;
    -
-
- -

- Block Comments - The final asterisk (*) should occur at column 78 (or the line width of files with longer lines). - Note that the final comment delimiter of the block comment is an exception an lies at column 79. -

- -

1.3 Comments

- -

- General. - Within a comment, the text must be standard English conforming to standard English rules of grammar and spelling (US English spelling). - Of course, this is not the place to summarize all English grammar, but as examples of common grammatic issues in comments: -

-
    -
  • - All sentences should begin with an upper-case character and end with either '.', '?', or '!'. -
  • -
  • - Sentence fragments and phrases are generally treated the same as sentences. -
  • -
  • - The punctuation '.' and ':' is followed by two spaces; the punctuation ',' and ';' is followed by a single space. -
  • -
  • - Text following '.' or ':' begins with an upper-case character; - text following ',' or ';' begins with a lower-case character. -
  • -
-

- Line Spacing - A single blank line should precede and follow each comment. - The only exceptions are: -

-
    -
  1. - For the file header block comment that begins on line one; - there is no preceding blank line in that case. -
  2. - For conditional compilation. - Conditional compilation should include the conditional logic and all comments associated with the conditional logic. - In this case, the blank line appears before the conditional, not after it. - No blank lines precede any comments following the conditional. -
  3. -
  4. - With braces. - No blank line separates the line containing the opening left brace from a comment. - No blank line follows a comment that may be the final line preceding a closing right brace. -
  5. -
  6. - With Labels. - No blank line separates the line containing the label from a comment. -
  7. -

    -
    - - -
    -

    Incorrect

    -
      -  /* set a equal to b */
      -  a = b;
      -  /* set b equal to c */
      -  b = c;
      -
      -  /* Do the impossible */
      -
      -#ifdef CONFIG_THE_IMPOSSIBLE
      -  the_impossible();
      -#endif
      -
      -  if (a == b)
      -    {
      -
      -      /* Only a comment */
      -
      -    }
      -
      -  here:
      -
      -    /* This is the place */
      -
      -
    -
    -

    Correct

    -
      -
      -  /* Set a equal to b. */
      -
      -  a = b;
      -
      -  /* Set b equal to c. */
      -
      -  b = c;
      -
      -#ifdef CONFIG_THE_IMPOSSIBLE
      -  /* Do the impossible */
      -
      -  the_impossible();
      -#endif
      -
      -  if (a == b)
      -    {
      -      /* Only a comment */
      -    }
      -
      -  here:
      -    /* This is the place */
      -
      -
    -
    - -

    - Indentation - Comments should, typically, be placed before the code section to which they apply. - The comment indentation should be the same as the follow indentation rules as the following code (if applicable). -

    - -

    - Short, Single line comments. - Short comments must lie on a single line. - The comment delimiters must lie on the same line. -

    -
    - - -
    -

    Incorrect

    -
      -  /*
      -   * This is a single line comment
      -   */
      -
    -
    -

    Correct

    -
      -  /* This is a single line comment. */
      -
    -
    - -

    - Multi-line comments. - If the comment is too long to fit on a single, it must be broken into a multi-line comment. - The comment must be begin on the first line of the multi-line comment with the opening comment delimiter (/*). - The following lines of the multi-line comment must be with an asterisk (*) aligned in the same column as the asterisk in the preceding line. - The closing comment delimiter must lie on a separate line with the asterisk (*) aligned in the same column as the asterisk in the preceding line. -

    -
    - - -
    -

    Incorrect

    -
      -  /*
      -     This is the first line of a multi-line comment.
      -     This is the second line of a multi-line comment.
      -     This is the third line of a multi-line comment. */
      -
      -  /* This is the first line of another multi-line comment.  */
      -  /* This is the second line of another multi-line comment. */
      -  /* This is the third line of another multi-line comment.  */
      -
      -
    -
    -

    Correct

    -
      -  /* This is the first line of a multi-line comment.
      -   * This is the second line of a multi-line comment.
      -   * This is the third line of a multi-line comment.
      -   */
      -
      -
    -
    - -

    - Comments to the Right of Statements. - Comments to the right of statements in C source files are discouraged. - If such comments are used, they should be (1) very short so that they do not exceed the line width (typically 78 characters), (2) aligned so that the comment begins in the same column on each line. -

    -
    - - - -
    -

    Incorrect

    -
      -  dog = cat; /* Make the dog be a cat */
      -  monkey = oxen; /* Make the monkey be an oxen */
      -  aardvark = macaque; /* Make the aardvark be a macaque */
      -
    -
    -

    Acceptable

    -
      -  dog      = cat;     /* Make the dog be a cat. */
      -  monkey   = oxen;    /* Make the monkey be an oxen. */
      -  aardvark = macaque; /* Make the aardvark be a macaque. */
      -
    -
    -

    Preferred

    -
      -  /* Make the dog be a cat. */
      -
      -  dog      = cat;
      -
      -  /* Make the monkey be an oxen. */
      -
      -  monkey   = oxen;
      -
      -  /* Make the aardvark be a macaque. */
      -
      -  aardvark = macaque;
      -
    -
    - -

    - Comments to the Right of Data Definitions. - Comments to the right of a declaration with an enumeration or structure, on the other hand, are encouraged, provided that the comments are short and do not exceed the maximum line width (usually 78 characters). - Columnar alignment of comments is very desirable (but often cannot be achieved without violating the line width). -

    -
    - - - -
    -

    Incorrect

    -
      -struct animals_s
      -{
      -  int dog; /* This is a dog */
      -  int cat; /* This is a cat */
      -  double monkey; /* This is a monkey */
      -  double oxen; /* This is an oxen */
      -  bool aardvark; /* This is an aardvark */
      -  bool macaque; /* This is a macaque */
      -};
      -
    -
    -

    Acceptable

    -
      -struct animals_s
      -{
      -  int dog;       /* This is a dog. */
      -  int cat;       /* This is a cat. */
      -  double monkey; /* This is a monkey. */
      -  double oxen;   /* This is an oxen. */
      -  bool aardvark; /* This is an aardvark. */
      -  bool macaque;  /* This is a macaque. */
      -};
      -
    -
    -

    Preferred

    -
      -struct animals_s
      -{
      -  int    dog;      /* This is a dog. */
      -  int    cat;      /* This is a cat. */
      -  double monkey;   /* This is a monkey. */
      -  double oxen;     /* This is an oxen. */
      -  bool   aardvark; /* This is an aardvark. */
      -  bool   macaque;  /* This is a macaque. */
      -};
      -
    -
    - -

    - Long Comments on the Right. - Comments on the right of statements or data definitions must be short and fit on the same line without exceeding the maximum line length. - If a longer comment is needed, then it should appear above the statement of definition rather than to the right of the definition. -

    -

    - Breaking Long Comments to the Right of Statements - Breaking long comments to the right of statements is acceptable as well, but not encouraged. - In this case the comment must be begin on the first line of the multi-line, right-hand comment with the opening comment delimiter (/*). - The following lines of the multi-line, right hand comment must be with an asterisk (*) aligned in the same column as the asterisk in the preceding line. - The closing comment delimiter must lie on the same line with the asterisk. -

    -
    - - - -
    -

    Incorrect

    -
      -  dog = cat; /* This assignment will convert what was at one time a lowly dog into a ferocious feline. */
      -
    -
    -

    Acceptable

    -
      -  dog = cat;       /* This assignment will convert what was at one time a
      -                    * lowly dog into a ferocious feline. */
      -
    -
    -

    Preferred

    -
      -  /* This assignment will convert what was at one time a lowly dog into a
      -   * ferocious feline.
      -   */
      -
      -  dog = cat;
      -
    -
    -

    - Note that if the comment is continued on multiple lines, the comment alignment and multi-line comment rules still apply with one exception: The closing */ appears on the same line as the final text of the comment. This exception to the rule is enforced to keep the statements and definitions from becoming to spread out. -

    - -

    - Block comments. - Block comments are only used to delimit groupings with the overall file organization and should not be used unless the usage is consistent with delimiting logical groupings in the program. -

    - -

    - C Style Comments. - C99/C11/C++ style comments (beginning with //) should not be used with NuttX. - NuttX generally follows C89 and all code outside of architecture specific directories must be compatible with C89. -

    -
    - - -
    -

    Incorrect

    -
      -// This is a structure of animals
      -struct animals_s
      -{
      -  int    dog;      // This is a dog
      -  int    cat;      // This is a cat
      -  double monkey;   // This is a monkey
      -  double oxen;     // This is an oxen
      -  bool   aardvark; // This is an aardvark
      -  bool   macaque;  // This is a macaque
      -};
      -
    -
    -

    Correct

    -
      -/* This is a structure of animals. */
      -
      -struct animals_s
      -{
      -  int    dog;      /* This is a dog. */
      -  int    cat;      /* This is a cat. */
      -  double monkey;   /* This is a monkey. */
      -  double oxen;     /* This is an oxen. */
      -  bool   aardvark; /* This is an aardvark. */
      -  bool   macaque;  /* This is a macaque. */
      -};
      -
    -
    - -

    - "Commenting Out" Large Code Blocks. - Do not use C or C++ comments to disable compilation of large blocks of code. - Instead, use #if 0 to do that. - Make sure there is a comment before the #if 0 to explain why the code is not compiled. -

    -
    - - -
    -

    Incorrect

    -
      -void some_function(void)
      -{
      -  ... compiled code ...
      -
      -  /*
      -  ... disabled code ..
      -   */
      -
      -  ... compiled code ...
      -}
      -
      -void some_function(void)
      -{
      -  ... compiled code ...
      -
      -  //
      -  // ... disabled code ..
      -  //
      -
      -  ... compiled code ...
      -}
      -
    -
    -

    Correct

    -
      -void some_function(void)
      -{
      -  ... compiled code ...
      -
      -  /* The following code is disabled because it is no longer needed. */
      -
      -#if 0
      -  ... disabled code ..
      -#endif
      -
      -  ... compiled code ...
      -}
      -
    -
    - -

    1.4 Braces

    - -

    - In general, the use of braces in the NuttX coding standard is similar to the use of braces in the GNU Coding standards with a few subtle differences. -

    - -

    Coding Standard:

    -
      -
    • - Always on Separate Lines. - Braces always appear on a separate line containing nothing else other than white space. -
    • -
    • - Never Comments on Braces. - Do not put comments on the same line as braces. -
    • -
    • - Compound Statements. - Within this document, an opening left brace followed by a sequence of statements, and ending with a closing right brace is referred to as a compound statement. -
    • -
    • - Nested Compound Statements. - In the case where there are nested compound statements that end with several consecutive right braces, each closing right brace must lie on a separate line and must be indented to match the corresponding opening brace. -
    • -
    • - Final brace followed by a single blank line. - The final right brace must be followed by a blank line as per standard rules. - There are two exceptions to this rule: -
        -
      1. - In the case where there are nested several consecutive right braces, no blank lines should be inserted except for after the final right brace. -
      2. -
      3. - No blank should be used to separate the final, closing right brace when it is followed by a break; statement. -
      4. -
      -
    • -
    • - Special Indentation Rules. - Special indentation rules apply to braces. -
    • -
    - -
    - - -
    -

    Incorrect

    -
      -while (true)
      -  {
      -    if (valid)
      -      {
      -      ...
      -      } /* if valid */
      -    else
      -      {
      -      ...
      -      } /* not valid */
      -  } /* end forever */
      -if (a < b) {
      -  if (a < 0) {
      -      c = -a;
      -  } else {
      -      c = a;
      -  }
      -} else {
      -  if (b < 0) {
      -      c = -b;
      -  } else {
      -      c = b;
      -  }
      -}
      -
    -
    -

    Correct

    -
      -while (true)
      -  {
      -    if (valid)
      -      {
      -      ...
      -      }
      -    else
      -      {
      -      ...
      -      }
      -  }
      -
      -if (a < b)
      -  {
      -    if (a < 0)
      -      {
      -        c = -a;
      -      }
      -    else
      -      {
      -        c = a;
      -      }
      -  }
      -else
      -  {
      -    if (b < 0)
      -      {
      -        c = -b;
      -      }
      -    else
      -      {
      -        c = b;
      -      }
      -  }
      -
      -
    -
    - -

    - Exception to Indentation Rule for Braces. - The exception is braces that following structure, enumeration, union, and function declarations. - There is no additional indentation for those braces; - those braces align with the beginning of the definition -

    -
    - - -
    -

    Incorrect

    -
      -enum kinds_of_dogs_e
      -  {
      -  ...
      -  };
      -
      -struct dogs_s {
      -  ...
      -  union {
      -  ...
      -  } u;
      -  ...
      -};
      -
      -struct cats_s
      -  {
      -  ...
      -    union
      -     {
      -     ...
      -     } u;
      -  ...
      -  };
      -
      -int animals(int animal)
      -  {
      -  ...
      -  }
      -
    -
    -

    Correct

    -
      -enum kinds_of_dogs_e
      -{
      -  ...
      -};
      -
      -struct dogs_s
      -{
      -  ...
      -  union
      -  {
      -  ...
      -  } u;
      -  ...
      -};
      -
      -struct cats_s
      -{
      -  ...
      -  union
      -  {
      -  ...
      -  } u;
      -  ...
      -};
      -
      -int animals(int animal)
      -{
      -  ...
      -}
      -
      -
    -
    - -

    1.5 Indentation

    - -

    - In general, the indentation in the NuttX coding standard is similar to the indentation requirements of the GNU Coding standards with a few subtle differences. -

    - -

    - Indentation Unit. - Indentation is in units of two spaces; Each indentation level is twos spaces further to the right than the preceding indentation levels. - TAB characters may not be used for indentation. -

    -
    - - -
    -

    Incorrect

    -
      -	if (x == y) {
      -		dosomething(x);
      -	}
      -
      -    if (x == y) {
      -        dosomething(x);
      -    }
      -
    -
    -

    Correct

    -
      -  if (x == y)
      -    {
      -      dosomething(x);
      -    }
      -
    -
    - -

    - Use of TAB Characters. - The use of TAB characters for indentation is prohibited in C source and header files. - TAB characters are, however, used in make files, assembly language source files, Kconfig files and some script files. - When TAB characters are used in these files, spaces may not be used for indentation. - The correct TAB setting is 4 spaces (not 8) in these cases. -

    -

    - Alignment of Braces. - Note that since braces must be on a separate line (see above), this indentation by two spaces has an interesting property: -

    -
      -
    • - All C statements (and case selectors) lie on lines that are multiples of 4 spaces (beginning with an indentation of two): 2, 6, 10, ... (4*n + 2) (for indentation level n = 0, 1, ...) -

    • -
    • - Braces lie on a separate line also indented by multiple of 4 spaces: 4, 8, 12, ... 4*n (for indentation level n = 1, 2, ...) -

    • -
    -

    - Thus, all code at the indentation level should align on the same column. - Similarly, opening and closing braces at the same indentation level should also align on the same (but different) column. -

    - -

    - Indentation of Pre-Processor Lines. - C Pre-processor commands following any conditional computation are also indented following basically the indentation same rules, differing in that the # always remains in column 1. -

    -

    - When C pre-processor statements are indented, they should be should be indented by 2 spaces per level-of-indentation following the #. - C pre-processor statements should be indented when they are enclosed within C pre-processor conditional logic (#if..#endif). The level of indentation increases with each level of such nested conditional logic. -

    -

    - C pre-processor statements should always be indented in this way in the Pre-processor Definitions section of each file. - C pre-processor statements may be indented in the Public/Private Data and Public/Private Functions sections of the file. - However, often the indentation of C pre-processor statements conflicts with the indentation of the C code and makes the code more difficult to read. - In such cases, indentation of C pre-processor statements should be omitted in those sections (only). -

    - -
    - - -
    -

    Incorrect

    -
      -#ifdef CONFIG_ABC
      -#define ABC_THING1 1
      -#define ABC_THING2 2
      -#define ABC_THING3 3
      -#endif
      -
      -#ifdef CONFIG_ABC
      -  #define ABC_THING1 1
      -  #define ABC_THING2 2
      -  #define ABC_THING3 3
      -#endif
      -
    -
    -

    Correct

    -
      -#ifdef CONFIG_ABC
      -#  define ABC_THING1 1
      -#  define ABC_THING2 2
      -#  define ABC_THING3 3
      -#endif
      -
      -#ifdef CONFIG_ABC
      -#  define ABC_THING1 1
      -#  define ABC_THING2 2
      -#  define ABC_THING3 3
      -#endif
      -
    -
    - -

    - Exception. - Each header file includes idempotence definitions at the beginning of the header file. - This conditional compilation does not cause any change to the indentation. -

    -
    - - -
    -

    Incorrect

    -
      -#ifndef __INCLUDE_SOMEHEADER_H
      -#  define __INCLUDE_SOMEHEADER_H
      -...
      -#  define THING1 1
      -#  define THING2 2
      -#  define THING3 3
      -...
      -#endif /* __INCLUDE_SOMEHEADER_H */
      -
    -
    -

    Correct

    -
      -#ifndef __INCLUDE_SOMEHEADER_H
      -#define __INCLUDE_SOMEHEADER_H
      -...
      -#define THING1 1
      -#define THING2 2
      -#define THING3 3
      -...
      -#endif /* __INCLUDE_SOMEHEADER_H */
      -
    -
    - -

    1.6 Parentheses

    - -

    Coding Standard:

    -
      -
    • - Space after key words. - Do not put a left parenthesis (() immediately after any C keywords (for, switch, while, do, return, etc.). - Put a space before the left parenthesis in these cases. -
    • -
    • - Otherwise, no space before left parentheses. - Otherwise, there should be no space before the left parentheses -
    • -
    • - No space between function name and argument list. - There should be no space between a function name and an argument list. -
    • -
    • - Never space before the right parentheses. - There should never be space before a right parenthesis ()). -
    • -
    • - No parentheses around returned values. - Returned values should never be enclosed in parentheses unless the parentheses are required to force the correct order of operations in a computed return value. -
    • -
    -
    - - -
    -

    Incorrect

    -
      -int do_foobar ( void )
      -{
      -  int ret = 0;
      -  int i;
      -
      -  for( i = 0; ( ( i < 5 ) || ( ret < 10 ) ); i++ )
      -    {
      -      ret = foobar ( i );
      -    }
      -
      -  return ( ret );
      -}
      -
    -
    -

    Correct

    -
      -int do_foobar(void)
      -{
      -  int ret = 0;
      -  int i;
      -
      -  for (i = 0; i < 5 || ret < 10; i++)
      -    {
      -      ret = foobar(i);
      -    }
      -
      -  return ret;
      -}
      -
    -
    - -

    - NOTE: - Many people do not trust their understanding of the precedence of operators and so use lots of parentheses in expressions to force the order of evaluation even though the parentheses may have no effect. - This will certainly avoid errors due to an unexpected order of evaluation, but can also make the code ugly and overly complex (as in the above example). - In general, NuttX does not use unnecessary parentheses to force order of operations. - There is no particular policy in this regard. - However, you are are advised to check your C Programming Language book if necessary and avoid unnecessary parenthesis when possible. -

    - - - - - -
    -

    2.0 Data and Type Definitions

    -
    - -

    2.1 One Definition/Declaration Per Line

    - -
    - - -
    -

    Incorrect

    -
      -  extern long time, money;
      -  char **ach, *bch;
      -  int i, j, k;
      -
    -
    -

    Correct

    -
      -  extern long time;
      -  extern long money;
      -  FAR char **ach;
      -  FAR char *bch;
      -  int i;
      -  int j;
      -  int k;
      -
    -
    - -

    - NOTE: - See the discussion of pointers for information about the FAR qualifier used above. -

    - -

    2.2 Global Variables

    - -Global vs. Local vs. Public vs. Private -By a global variable it is meant any variable defined outside of a function. -The distinction is between this kind of global and function local definition and refers to the scope a symbol within a file. -A related concept for all global names defined within a file is the scope of the name across different files. -If the global symbol is pre-pended with the static storage class then the scope of the global symbol is within the file only. -This is a somewhat different concept and within NuttX you will find these distinguished as private vs. public global symbols. -However, within this standard, the term global variable will refer to any variable that has more than local scope. - - -

    Coding Standard:

    -
      -
    • - Short global variable names. - Names should be terse, but generally descriptive of what the variable is for. - Try to say something with the variable name, but don't try to say too much. - For example, the variable name of g_filelen is preferable to something like g_lengthoffile. -
    • -
    • - Global variable prefix. - All global variables begin with the prefix g_ to indicate the scope of variable. -
    • -
    • - Module name prefix - If a global variable belongs in a module with a name of, say xyz, then that module should be included as part of the prefix like: g_xyz_. -
    • -
    • - Lowercase, - Use all lower case letters. -
    • -
    • - Minimal use of '_'. - Preferably there are no '_' separators within the name. - Long variable names might require some delimitation using '_'. - Long variable names, however, are discouraged. -
    • -
    • - Use structures. - If possible, wrap all global variables within a structure to minimize the liklihood of name collisions. -
    • -
    • - Avoid global variables when possible. - Use of global variables, in general, is discourage unless there is no other reasonable solution. -
    • -
    -
    - - - -
    -

    Incorrect

    -
      -extern int someint;
      -static int anotherint;
      -uint32_t dwA32BitInt;
      -uint32_t gAGlobalVariable;
      -
    -
    -

    Acceptable

    -
      -extern int g_someint;
      -static int g_anotherint;
      -uint32_t g_a32bitint;
      -uint32_t g_aglobal;
      -
    -
    -

    Preferred

    -
      -struct my_variables_s
      -{
      -  uint32_t a32bitint;
      -  uint32_t aglobal;
      -};
      -
      -extern int g_someint;
      -static int g_anotherint;
      -struct my_variables_s g_myvariables;
      -
    -
    - -

    2.3 Parameters and Local Variables

    - -

    Coding Standard:

    -
      -
    • - Common naming standard. - Naming for function parameters and local variables is the same. -
    • -
    • - Short variable names. - Names should be terse, but generally descriptive of what the variable is for. - Try to say something with the variable name, but don't try to say too much. - For example, the variable name of len is preferable to something like lengthofiobuffer. -
    • -
    • - No special ornamentation. - There is no special ornamentation of the name to indication that the variable is a local variable. - The prefix p or pp may be used on names of pointers (or pointer to pointers) if it helps to distinguish the variable from some other local variable with a similar name. - Even this convention is discouraged when not necessary. -
    • -
    • - Lowercase - Use all lower case letters. -
    • -
    • - Minimal use of single character variable names. - Short variable names are preferred. - However, single character variable names should be avoided. - Exceptions to this include i, j, and k which are reserved only for use as loop indices - (part of our Fortran legacy). -
    • -
    • - Minimal use of '_'. - Preferably there are no '_' separators within the name. - Long variable names might require some delimitation using '_'. - Long variable names, however, are discouraged. -
    • -
    -
    - - -
    -

    Incorrect

    -
      -uint32_t somefunction(int a, uint32_t dwBValue)
      -{
      -  uint32_t this_is_a_long_variable_name = 1;
      -  int i;
      -
      -  for (i = 0; i < a; i++)
      -    {
      -      this_is_a_long_variable_name *= dwBValue--;
      -    }
      -
      -  return this_is_a_long_variable_name;
      -}
      -
    -
    -

    Correct

    -
      -uint32_t somefunction(int limit, uint32_t value)
      -{
      -  uint32_t ret = 1;
      -  int i;
      -
      -  for (i = 0; i < limit; i++)
      -    {
      -      ret *= value--;
      -    }
      -
      -  return ret;
      -}
      -
    -
    - -

    - NOTE: - You will see the local variable named ret is frequently used in the code base for the name of a local variable whose value will be returned or to received the returned value from a called function. -

    - -

    2.4 Type Definitions

    - -

    Coding Standard:

    -
      -
    • - Short type names. - Type names should be terse, but generally descriptive of what the type is for. - Try to say something with the type name, but don't try to say too much. - For example, the type name of fhandle_t is preferable to something like openfilehandle_t. -
    • -
    • - Type name suffix. - All typedef'ed names end with the suffix _t. -
    • -
    • - Module name prefix - If a type belongs in a module with a name of, say xyz, then that module should be included as a prefix to the type name like: xyz_. -
    • -
    • - Lowercase. - Use all lower case letters. -
    • -
    • - Minimal use of '_'. - Preferably there are few '_' separators within the type name. - Long type names might require some delimitation using '_'. - Long type names, however, are discouraged. -
    • -
    -
    - - -
    -

    Incorrect

    -
      -typedef void *myhandle;
      -typedef int myInteger;
      -
    -
    -

    Correct

    -
      -typedef FAR void *myhandle_t;
      -typedef int myinteger_t;
      -
    -
    - -

    - NOTE: - See the discussion of pointers for information about the FAR qualifier used above. -

    - -

    2.5 Structures

    - -

    Structure Naming

    -
      -
    • - No un-named structures. - All structures must be named, even if they are part of a type definition. - That is, a structure name must follow the reserved word struct in all structure definitions. - There are two exceptions to this rule: -
        -
      1. - First for structures that are defined within another union or structure (discouraged). In those cases, the structure name should always be omitted. -
      2. -
      3. - Second for structures as the type of a local variable. In this case, again, the structure name should always be omitted. -
      4. -
      -
    • -
    • - Structured defined with structures discouraged. - Fields within a structure may be another structure that is defined only with the scope of the containing structure. - This practice is acceptable, but discouraged. -
    • -
    • - No un-named structure fields. - Structure may contain other structures as fields. - This this case, the structure field must be named. - C11 permits such un-named structure fields within a structure. - NuttX generally follows C89 and all code outside of architecture specific directories must be compatible with C89. -
    • - No structure definitions within Type Definition. - The practice of defining a structure within a type definition is discouraged. - It is preferred that the structure definition and the type definition be separate definitions. - In general, the NuttX coding style discourages any typdef-ing of structures; - normally the full structure name is used as types throughout the code. - The reason for this is that is structure pointers may be forward referenced in header files without having to include the file the provides the type definition. - This greatly reduces header file coupling. -
    • -
    • - Short structure names. - Structure names should be terse, but generally descriptive of what the structure contains. - Try to say something with the structure name, but don't try to say too much. - For example, the structure name of xyz_info_s is preferable to something like xyz_datainputstatusinformation_s. -
    • -
    • - Structure name suffix. - All structure names end with the suffix _s. -
    • -
    • - Module name prefix - If a structure belongs to a module with a name of, say xyz, then that module should be included as a prefix to the structure name like: xyz_. -
    • -
    • - Lowercase. - Use all lower case letters. -
    • -
    • - Minimal use of '_'. - Preferably there are few '_' separators within the structure name. - Long variable names might require some delimitation using '_'. - Long variable names, however, are discouraged. -
    • -
    - -

    Structure Field Naming

    -
      -
    • - Common variable naming. - Structure field naming is generally the same as for local variables. -
    • -
    • - One definition per line. - The one definition per line rule applies to structure fields, - including bit field definitions. -
    • -
    • - Each field should be commented. - Each structure field should be commented. - Commenting should follow the standard conventions. -
    • -
    • - Optional structure field prefix. - It make be helpful to add a two-letter prefix to each field name so that is is clear which structure the field belongs to. - Although a good practice, that convention has not been used consistently in NuttX. -
    • -
    • - Lowercase. - Use all lower case letters. -
    • -
    • - Minimal use of '_'. - Preferably there are few '_' separators within the field name. - Long variable names might require some delimitation using '_'. - Long variable names, however, are discouraged. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to line formatting, use of braces, indentation, and comments. -

    -

    - Size Optimizations. - When declaring fields in structures, order the declarations in such a way as to minimize memory waste due of data alignment. - This essentially means that that fields should be organized by data size, not by functionality: - Put all pointers togeter, all uint8_t's together, all uint32_t's together. - Data types withi well known like uint8_t and uint32_t should also be place in either ascending or descending size order. -

    -
    - - -
    -

    Incorrect

    -
      -typedef struct       /* Un-named structure */
      -{
      -  ...
      -  int val1, val2, val3; /* Values 1-3 */
      -  ...
      -} xzy_info_t;
      -
      -struct xyz_information
      -{
      -  ...
      -  uint8_t bita : 1,  /* Bit A */
      -          bitb : 1,  /* Bit B */
      -          bitc : 1;  /* Bit C */
      -  ...
      -};
      -
      -struct abc_s
      -{
      -  ...
      -  struct
      -  {
      -    int a;           /* Value A */
      -    int b;           /* Value B */
      -    int c;           /* Value C */
      -  };                 /* Un-named structure field */
      -  ...
      -};
      -
      -
    -
    -
      - -

      - Correct -

      -
      -struct xyz_info_s
      -{
      -  ...
      -  int val1;          /* Value 1 */
      -  int val2;          /* Value 2 */
      -  int val3;          /* Value 3 */
      -  ...
      -};
      -
      - -

      - Discouraged -

      -
      -typedef struct xyz_info_s xzy_info_t;
      -
      -

      - The use of typedef'ed structures is acceptable but discouraged. -

      -
      -

      - Correct -

      -
      -struct xyz_info_s
      -{
      -  ...
      -  uint8_t bita : 1,  /* Bit A */
      -  uint8_t bitb : 1,  /* Bit B */
      -  uint8_t bitc : 1,  /* Bit C */
      -  ...
      -};
      -
      - -

      - Discouraged -

      -
      -struct abc_s
      -{
      -  ...
      -  struct
      -  {
      -    int a;           /* Value A */
      -    int b;           /* Value B */
      -    int c;           /* Value C */
      -  } abc;
      -  ...
      -};
      -
      -

      - The use of structures defined within other structures is acceptable provided that they define named fields. - The general practice of defining a structure within the scope of another structure, however, is still but discouraged in any case. - The following is preferred: -

      -
      -

      - Preferred -

      -
      -struct abc_s
      -{
      -  ...
      -  int a;             /* Value A */
      -  int b;             /* Value B */
      -  int c;             /* Value C */
      -  ...
      -};
      -
      -
    -
    - -

    2.6 Unions

    -

    - Union and Field Names. - Naming of unions and fields within unions follow the same naming rules as for structures and structure fields. - The only difference is that the suffix _u is used to identify unions. -

    -

    - Other Applicable Coding Standards. - See sections related to line formatting, use of braces, indentation, and comments. -

    -
    - -
    -

    Example

    -
      -union xyz_union_u  /* All unions must be named */
      -{
      -  uint8_t  b[4];   /* Byte values. */
      -  uint16_t h[2];   /* Half word values. */
      -  uint32_t w;      /* Word Value. */
      -};
      -
      -
      -typedef union xyz_union_u xzy_union_t;
      -
      -

      The use of typedef'ed unions is acceptable but discouraged.

      -
      -struct xyz_info_s
      -{
      -  ...
      -  union
      -  {
      -    uint8_t  b[4]; /* Byte values. */
      -    uint16_t h[2]; /* Half word values. */
      -    uint32_t w;    /* Word Value. */
      -  } u;             /* All union fields must be named */
      -  ...
      -};
      -
      -
    -
    -

    - NOTE: - Note that the union fields within structures are often named u. - This is another exception to the prohibition against using single character variable and field names. - The short field name u clearly identifies a union field and prevents the full name of the union value from being excessively long. -

    - -

    2.7 Enumerations

    -

    - Enumeration Naming. - Naming of enumerations follow the same naming rules as for structure and union naming. - The only difference is that the suffix _e is used to identify an enumeration. -

    -

    - Enumeration Value Naming. - Enumeration values, however, following a naming convention more similar to macros. -

    -
      -
    • - Uppercase. - Enumeration values are always in upper case. -
    • -
    • - Use of '_' encouraged. - Unlike other naming, use of the underscore character _ to break up enumeration names is encouraged. -
    • -
    • - Prefix. - Each value in the enumeration should begin with an upper-case prefix that identifies the value as a member of the enumeration. - This prefix should, ideally, derive from the name of the enumeration. -
    • -
    • - No dangling commas. - There should be no dangling comma on the final value of the enumeration. - The most commonly used tool chain are tolerant of such dangling commas, but others will not. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to line formatting, use of braces, indentation, and comments. -

    -
    - -
    -

    Example

    -
      -enum xyz_state_e
      -{
      -  XYZ_STATE_UNINITIALIZED = 0, /* Uninitialized state. */
      -  XYZ_STATE_WAITING,           /* Waiting for input state. */
      -  XYZ_STATE_BUSY,              /* Busy processing input state. */
      -  XYZ_STATE_ERROR,             /* Halted due to an error. */
      -  XYZ_STATE_TERMINATING,       /* Terminating stated. */
      -  XYZ_STATE_TERMINATED         /* Terminating stated. */
      -};
      -
    -
    - -

    2.8 C Pre-processor Macros

    - -

    Coding Standard:

    - -

    - Macro Naming. - Macro naming following a naming convention similar to the naming of enumeration values. -

    -
      -
    • - Uppercase. - Macro names are always in upper case. -
    • -
    • - Lowercase Exceptions. - There are a few lower case values in NuttX macro names. Such as a lower-case p for a period or decimal point (such as VOLTAGE_3p3V). - I have also used lower-case v for a version number (such as CONFIG_NET_IPv6). - However, these are exceptions to the rule rather than illustrating a rule. -
    • -
    • - Macros that could be functions. - Lower-case macro names are also acceptable if the macro is a substitute for a function name that might be used in some other context. - In that case, normal function naming applies. -
    • -
    • - Use of '_' encouraged. - Unlike other naming, use of the underscore character _ to break up macro names is encouraged. -
    • -
    • - Prefix. - Each related macro value should begin with an upper-case prefix that identifies the value as part of a set of values (and also to minimize the likelihood of naming collisions). -
    • -
    • - Single space after #define. - A single space character should separate the #define from the macro name. - Tabs are never used. -
    • -
    • - Normal commenting rules. - Normal commenting rules apply. -
    • -
    • - Line continuations. - Macro definitions may be continued on the next line by terminating the line with the \ character just before the newline character. - There should be a single space before the \ character. - Aligned \ characters on multiple line continuations are discouraged because they are a maintenance problem. -
    • -
    • - Parentheses around macro argument expansions. - Macros may have argument lists. - In the macros expansion, each argument should be enclosed in parentheses. -
    • -
    • - Real statements. - If a macro functions as a statement, then the macro expansion should be wrapped in do { ... } while (0) to assume that the macros is, indeed, a statement. -
    • -
    • - Magic numbers are prohibited in code. - Any numeric value is not intuitively obvious, must be properly named and provided as either a pre-processor macro or an enumeration value. -
    • -
    • - Side effects. - Be careful of side effects. -
    • -
    • - Indentation. - See the Indentation of Pre-Processor Lines requirements above. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to line formatting, indentation, and comments. -

    -
    - - -
    -

    Incorrect

    -
      -#define max(a,b) a > b ? a : b
      -
      -#define ADD(x,y) x + y
      -
      -#ifdef HAVE_SOMEFUNCTION
      -int somefunction(struct somestruct_s* psomething);
      -#else
      -#define SOMEFUNCTION() (0)
      -#endif
      -
      -#	define	IS_A_CAT(c)		((c) == A_CAT)
      -
      -#define LONG_MACRO(a,b)                                  \
      -  {                                                      \
      -    int value;                                           \
      -    value = b-1;                                         \
      -    a = b*value;                                         \
      -  }
      -
      -#define DO_ASSIGN(a,b) a = b
      -
    -
    -

    Correct

    -
      -#define MAX(a,b) (((a) > (b)) ? (a) : (b))
      -
      -#define ADD(x,y) ((x) + (y))
      -
      -#ifdef HAVE_SOMEFUNCTION
      -int somefunction(struct somestruct_s* psomething);
      -#else
      -#  define somefunction(p) (0)
      -#endif
      -
      -# define IS_A_CAT(c)  ((c) == A_CAT)
      -
      -#define LONG_MACRO(a,b) \
      -  { \
      -    int value; \
      -    value = (b)-1; \
      -    (a) = (b)*value; \
      -  }
      -
      -#define DO_ASSIGN(a,b) do { (a) = (b); } while (0)
      -
    -
    - -

    2.9 Pointer Variables

    -

    - Pointer Naming. - Pointers following same naming conventions as for other variable types. - A pointer (or pointer-to-a-pointer) variable may be prefaced with p (or pp) with no intervening underscore character _ in order to identify that variable is a pointer. - That convention is not encouraged, however, and is only appropriate if there is some reason to be concerned that there might otherwise be confusion with another variable that differs only in not being a pointer. -

    - White Space. - The asterisk used in the declaration of a pointer variable or to dereference a pointer variable should be placed immediately before the variable name with no intervening spaces. - A space should precede the asterisk in a cast to a pointer type. -

    -
    - - -
    -

    Incorrect

    -
      -int somefunction(struct somestruct_s* psomething);
      -
      -ptr = (struct somestruct_s*)value;
      -
    -
    -

    Correct

    -
      -int somefunction(FAR struct somestruct_s *something);
      -
      -ptr = (FAR struct somestruct_s *)value;
      -
    -
    - -

    - FAR, NEAR, DSEG and CODE pointers. - Some architectures require a qualifier on pointers to identify the address space into which the pointer refers. - The macros FAR, NEAR, DSEG and CODE are defined in include/nuttx/compiler.h to provide meaning for this qualifiers when needed. - For portability, the general rule is that pointers to data that may lie in the stack, heap, .bss, or .data should be prefaced by the qualifier FAR; pointers to functions probably lie in a code address space and should have the qualifier CODE. - The typical effect of these macros on architectures where they have meaning to determine the size of the pointer (size in the sense of the width of the pointer value in bits). -

    - -

    2.10 Initializers

    -

    - Applicable Coding Standards. - See the section related to parentheses. -

    -

    - C89 Compatibility. - All common NuttX code must conform to ANSII C89 requirements. - Newer C standards permit more flexible initialization with named initializers and array initializers. - However, these are not backward compatible with C89 and cannot be used in common code. - Newer C99 features may be included in architecture-specific sub-directories where there is no possibility of the use of such older toolchains. - C11 is included in NuttX, but has not been verified and, hence, it not encourage anywhere. -

    - - - - - -
    -

    3.0 Functions

    -
    - -

    3.1 Function Headers

    - -

    Coding Standard:

    -
      -
    • - Function headers. - Each function is preceded by a function header. The function header is a block comment that provides information about the function. - The block comment consists of the following: -

        -
      • - The block comment begins with a line that consists of the opening C comment in column 1 (/*) followed by a series of asterisks extending to the length of the line (usually to column 78). -
      • -
      • - The block comment ends with a line that consists of series of asterisks beginning at column 2 and extending to the near the end line (usually to column 77) followed by the closing C comment in (usually at column 78 for a total length of 79 characters). -
      • -
      • - Information about the function is included in lines between the first and final lines. - Each of these begin with a space in column 1, an sterisk (*) in column 2, and a space in column 3. -
      • -

      -
    • -
    • - Function header preceded by one blank line. - Exactly one blank line precedes each function header. -
    • -
    • - Function header followed by one blank line. - Exactly one blank line is placed after function header and before the function definition. -
    • -
    • - Function header sections. - Within the function header, the following data sections must be provided: -

        -
      • - * Name: followed by the name of the function on the same line. -
      • -
      • - * Description: followed by a description of the function beginning on the second line. - Each line of the function description is indented by two additional spaces. -
      • -
      • - * Input Parameters: followed by a description of the of each input parameter beginning on the second line. - Each input parameter begins on a separator line indented by two additional spaces. - The description needs to include (1) the name of the input parameters, and (2) a short description of the input parameter. -
      • -
      • - * Returned Value: followed by a description of the of returned value(s) beginning on the second line. - The description of the returned value should identify all error values returned by the function. -
      • -
      • - * Assumptions/Limitations: followed by a any additional information that is needed to use the function correctly. - This section is optional and may be omitted with there is no such special information required for use of the function. -
      • -

      - Each of these data sections is separated by a single line like " * ". -
    • -
    -

    - Function header template. - Refer to Appendix A for the template for a function header. -

    - -

    3.2 Function Naming

    - -

    Coding Standard:

    -
      -
    • - Short function names. - Function names should be terse, but generally descriptive of what the function is for. - Try to say something with the function name, but don't try to say too much. - For example, the variable name of xyz_putvalue is preferable to something like xyz_savethenewvalueinthebuffer. -
    • -
    • - Lowercase. - Use all lower case letters. -
    • -
    • - Module prefix. - All functions in the same module, or sub-system, or within the same file should have a name beginning with a common prefix separated from the remainder of the function name with the underscore, '_', character. - For example, for a module called xyz, all of the functions should begin with xyz_. -
    • -
    • - Extended prefix. - Other larger functional grouping should have another level in the naming convention. - For example, if module xyz contains a set of functions that manage a set of I/O buffers (IOB), then those functions all should get naming beginning with a common prefix like xyz_iob_. -
    • -
    • - Use of '_' discouraged. - Further use of the '_' separators is discouraged in function naming. - Long function names might require some additional elimitation using '_'. - Long function names, however, are also discouraged. -
    • -
    • - Verbs and Objects. - The remainder of the function name should be either in the form of verb-object or object-verb. - It does not matter which as long as the usage is consistent within the module. - Common verbs include get and set (or put) for operations that retrieve or store data, respectively. - The verb is is reserved for functions that perform some test and return a boolean value to indicate the result of the test. - In this case, the object should indicate what is testing and the return value of true should be consistent with result of the test being true. -
    • -
    - -

    3.3 Parameter Lists

    - -

    - Coding Standards. - See general rules for parameter naming. - See also the sections related to the use of parentheses. -

    -

    - Use of const Parameters. - Use of the const storage class is encouraged. - This is appropriate to indicate that the function will not modify the object. -

    - -

    3.4 Function Body

    - -

    Coding Standard:

    -
      -
    • - Single compound statement. - The function body consists of a single compound statement. -
    • -
    • - Braces in column 1 - The opening and close braces of the compound statement must be placed in column one. -
    • -
    • - First definition or statement in column 3. - The first data definitions or statements in the function body are idented by two spaces. - Standards for statements are covered in the following paragraph -
    • -
    • - Local variables first. - Because NuttX conforms to the older C89 standard, all variables that have scope over the compound statement must be defined at the beginning of the compound statement prior to any executable statements. - Local variable definitions intermixed within the following sequence of executable statements are forbidden. - A single blank line must follow the local variable definitions separating the local variable definitions from the following executable statements. - NOTE that a function body consists of a compound statement, but typically so does the statement following if, else, for, while, do. - Local variable definitions are also acceptable at the beginning of these compound statements as with any other. -
    • -
    • - Long functions are discouraged. - As a rule of thumb, the length of a function should be limited so that it would fit on a single page (if you were to print the source code). -
    • -
    • - Return Statement. - The argument of the return statement should not be enclosed in parentheses. - A reasonable exception is the case where the returned value argument is a complex expression and where the parentheses improve the readability of the code. - Such complex expressions might be Boolean expressions or expressions containing conditions. - Simple arithmetic computations would not be considered complex expressions. -
    • -
    • - Space after the function body. - A one (and only one) blank line must follow the closing right brace of the function body. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to General Conventions, Parameters and Local Variables, and Statements. -

    - -
    - - -
    -

    Incorrect

    -
      -  int myfunction(int a, int b)
      -    {
      -      int c, d;
      -      c = a
      -      d = b;
      -
      -      int e = c + d;
      -
      -      for (int i = 0; i < a; i++)
      -        {
      -          for (int j = 0; j < b; j++)
      -            {
      -              e += j * d;
      -            }
      -        }
      -
      -      return (e / a);
      -    }
      -
    -
    -

    Correct

    -
      -  int myfunction(int a, int b)
      -  {
      -    int c;
      -    int d;
      -    int e;
      -    int i;
      -
      -    c = a
      -    d = b;
      -    e = c + d;
      -
      -    for (i = 0; i < a; i++)
      -      {
      -        int j;
      -
      -        for (j = 0; j < b; j++)
      -          {
      -            e += j * d;
      -          }
      -      }
      -
      -    return e / a;
      -  }
      -
    -
    - -

    Returned Values

    - -

    - OS Internal Functions. - In general, OS internal functions return a type int to indicate success or failure conditions. - Non-negative values indicate success. - The return value of zero is the typical success return value, but other successful return can be represented with other positive values. - Errors are always reported with negative values. - These negative values must be a well-defined errno as defined in the file nuttx/include/errno.h. -

    - -

    - Application/OS Interface. - All but a few OS interfaces conform to documented standards that have precedence over the coding standards of this document. -

    - -

    - Checking Return Values. - Callers of internal OS functions should always check return values for an error. - At a minimum, a debug statement should indicate that an error has occurred. - Ignored return values are always suspicious. - All calls to malloc or realloc, in particular, must be checked for failures to allocate memory to avoid use of NULL pointers. -

    - - - - - -
    -

    4.0 Statements

    -
    - -

    4.1 One Statement Per Line

    - -

    Coding Standard:

    -
      -
    • - One statement per line. - There should never be more than one statement on a line. -
    • -
    • - No more than one assignment per statement. - Related to this, there should never be multiple assignments in the same statement. -
    • -
    • - Statements should never be on the same line as any keyword. - Statements should never be on the same line as case selectors or any C keyword. -
    • -
    -

    - Other Applicable Coding Standards. - See the section related to the use of braces. -

    - -
    - - -
    -

    Incorrect

    -
      -  if (var1 < var2) var1 = var2;
      -
      -  case 5: var1 = var2; break;
      -
      -  var1 = 5; var2 = 6; var3 = 7;
      -
      -  var1 = var2 = var3 = 0;
      -
    -
    -

    Correct

    -
      -  if (var1 < var2)
      -    {
      -      var1 = var2;
      -    }
      -
      -  case 5:
      -    {
      -      var1 = var2;
      -    }
      -    break;
      -
      -  var1 = 5;
      -  var2 = 6;
      -  var3 = 7;
      -
      -  var1 = 0;
      -  var2 = 0;
      -  var3 = 0;
      -
    -
    - -

    4.2 Casts

    - -

    Coding Standard:

    -
      -
    • - No space in cast. - There should be no space between a cast and the value being cast. -
    • -
    -
    - - -
    -

    Incorrect

    -
      -struct something_s *x = (struct something_s*) y;
      -
    -
    -

    Correct

    -
      -struct something_s *x = (struct something_s *)y;
      -
    -
    - -

    4.3 Operators

    -

    - Spaces before and after binary operators. - All binary operators (operators that come between two values), such as +, -, =, !=, ==, >, etc. should have a space before and after the operator, for readability. As examples: -

    -
    - - -
    -

    Incorrect

    -
      -for=bar;
      -if(a==b)
      -for(i=0;i>5;i++)
      -
    -
    -

    Correct

    -
      -for = bar;
      -if (a == b)
      -for (i = 0; i > 5; i++)
      -
    -
    - -

    - No space separating unary operators. - Unary operators (operators that operate on only one value), such as ++, should not have a space between the operator and the variable or number they are operating on. -

    -
    - - -
    -

    Incorrect

    -
      -x ++;
      -
    -
    -

    Correct

    -
      -x++;
      -
    -
    - -

    - Forbidden Multicharacter Forms. - Many operators are expressed as a character in combination with = such as +=, >=, >>=, etc. - Some compilers will accept the = at the beginning or the end of the sequence. - This standard, however, requires that the = always appear last in order to avoid amiguities that may arise if the = were to appear first. For example, a =++ b; could also be interpreted as a =+ +b; or a = ++b all of which are very different. -

    - -

    -

    4.4 if then else Statement

    - -

    Coding Standard:

    -
      -
    • - if separated from <condition>. - The if keyword and the <condition> must appear on the same line. - The if keyword and the <condition> must be separated by a single space. -
    • - - Keywords on separate lines. - if <condition> and else must lie on separate lines with nothing else present on the line. - -
    • - Indentation and parentheses. - if <condition> follows the standard indentation and parentheses rules. -
    • -
    • - Alignment. - The if in the if <condition> line and the else must be aligned at the same column. -
    • -
    • - Statement(s) always enclosed in braces. - Statement(s) following the if <condition> and else keywords must always be enclosed in braces. - Braces must follow the if <condition> and else lines even in the cases where (a) there is no contained statement or (b) there is only a single statement! -
    • -
    • - Braces and indentation. - The placement of braces and statements must follow the standard rules for braces and indentation. -
    • -
    • - Final brace followed by a single blank line. - The final right brace of the if-else must be followed by a blank line in most cases (the exception given below). - This may be the final brace of the if compound statement if the else keyword is not present. - Or it may be the the final brace of the else compound statement if present. - A blank line never follows the right brace closing the if compound statement if the else keyword is present. - Use of braces must follow all other standard rules for braces and spacing. -
    • -
    • - Exception. - That blank line must also be omitted for certain cases where the if <condition>-else statement is nested within another compound statement; there should be no blank lines between consecutive right braces as discussed in the standard rules for use of braces. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to use of braces and indentation. -

    - -
    - - -
    -

    Incorrect

    -
      -  if(var1 < var2) var1 = var2;
      -
      -  if(var > 0)
      -    var--;
      -  else
      -    var = 0;
      -
      -  if (var1 > 0) {
      -    var1--;
      -  } else {
      -    var1 = 0;
      -  }
      -  var2 = var1;
      -
    -
    -

    Correct

    -
      -  if (var1 < var2
      -    {
      -      var1 = var2;
      -    }
      -
      -  if (var > 0)
      -    {
      -      var--;
      -    }
      -  else
      -    {
      -      var = 0;
      -    }
      -
      -  if (var1 > 0)
      -    {
      -      var1--;
      -    }
      -  else
      -    {
      -      var1 = 0;
      -    }
      -
      -  var2 = var1;
      -
    -
    - -

    - <condition> ? <then> : <else> -

    -
      -
    • - Only if the expression is short. - Use of this form is only appropriate if the entire sequence is short and fits neatly on the line. -
    • -
    • - Multiple lines forbidden. - This form is forbidden if it extends to more than one line. -
    • -
    • - Use of parentheses. - The condition and the entire sequence are often enclosed in parentheses. - These are, however, not required if the expressions evaluate properly without them. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to parentheses. -

    -
    - -
    -

    Example

    -
      -  int arg1 = arg2 > arg3 ? arg2 : arg3;
      -  int arg1 = ((arg2 > arg3) ? arg2 : arg3);
      -
    -
    - -

    4.5 switch Statement

    - -

    Definitions:

    -
      -
    • - Case logic. - By case logic it is mean the case or default and all of the lines of code following the case or default up to the next case, default, or the right brace indicating the end of the switch statement. -
    • -
    - -

    Coding Standard:

    -
      -
    • - switch separated from <value>. - The switch keyword and the switch <value> must appear on the same line. - The if keyword and the <value> must be separated by a single space. -
    • -
    • - Falling through. - Falling through a case statement into the next case statement is be permitted as long as a comment is included. -
    • -
    • - default case. - The default case should always be present and trigger an error if it is reached when it should not be. -
    • -
    • - Case logic in braces. - It is preferable that all case logic (except for the break) be enclosed in braces. - If you need to instantiate local variables in case logic, then that logic must be surrounded with braces. -
    • -
    • - break outside of braces. - break statements are normally indented by two spaces. - When used conditionally with case logic, the placement of the break statement follows normal indentation rules. -
    • -
    • - Case logic followed by a single blank line. - A single blank line must separate the case logic and any following case or default. - The should, however, be no blank lines between the case logic and the closing right brace. -
    • -
    • - Switch followed by a single blank line. - The final right brace that closes the switch <value> statement must be followed by a single blank line. -
    • -
    • - Exception. - That blank line must be omitted for certain cases where the switch <value> statement is nested within another compound statement; there should be no blank lines between consecutive right braces as discussed in the standard rules for use of braces. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to use of braces, indentation, and comments. -

    -
    - -
    -

    Example

    -
      -  switch (...)
      -    {
      -      case 1:  /* Example of a comment following a case selector. */
      -      ...
      -
      -      /* Example of a comment preceding a case selector. */
      -
      -      case 2:
      -        {
      -          /* Example of comment following the case selector. */
      -
      -          int value;
      -          ...
      -        }
      -        break;
      -
      -      default:
      -        break;
      -    }
      -
    -
    - -

    4.6 while Statement

    -

    Coding Standard:

    -
      -
    • - while separated from <condition>. - The while keyword and the <condition> must appear on the same line. - The while keyword and the <condition> must be separated by a single space. -
    • -
    • - Keywords on separate lines. - while <condition> must lie on a separate line with nothing else present on the line. -
    • -
    • - Indentation and parentheses. - while <condition> follows the standard indentation and parentheses rules. -
    • -
    • - Statements enclosed in braces - Statement(s) following the while <condition> must always be enclosed in braces, even if only a single statement follows. -
    • -
    • - No braces on null statements. - No braces are required if no statements follow the while <condition>. - The single semicolon (null statement) is sufficient; -
    • -
    • - Braces and indentation. - The placement of braces and statements must follow the standard rules for braces and indentation. -
    • -
    • - Followed by a single blank line. - The final right brace that closes the while <condition> statement must be followed by a single blank line. -
    • -
    • - Exception. - That blank line must be omitted for certain cases where the while <condition> statement is nested within another compound statement; there should be no blank lines between consecutive right braces as discussed in the standard rules for use of braces. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to use of braces, indentation, and comments. -

    -
    - - -
    -

    Incorrect

    -
      -  while( notready() )
      -    {
      -    }
      -  ready = true;
      -
      -  while (*ptr != '\0') ptr++;
      -
    -
    -

    Correct

    -
      -  while (notready());
      -
      -  ready = true;
      -
      -  while (*ptr != '\0')
      -    {
      -      ptr++;
      -    }
      -
      -
    -
    - -

    4.7 do while Statement

    -

    Coding Standard:

    -
      -
    • - Keywords on separate lines. - do and while <condition> must lie on separate lines with nothing else present on the line. -
    • -
    • - Indentation and parentheses. - do .. while <condition> follows the standard indentation and parentheses rules. -
    • -
    • - Statements enclosed in braces - Statement(s) following the do must always be enclosed in braces, even if only a single statement (or no statement) follows. -
    • -
    • - Braces and indentation. - The placement of braces and statements must follow the standard rules for braces and indentation. -
    • -
    • - while separated from <condition>. - The while keyword and the <condition> must appear on the same line. - The while keyword and the <condition> must be separated by a single space. -
    • -
    • - Followed by a single blank line. - The concluding while <condition> must be followed by a single blank line. -
    • -
    -

    - Other Applicable Coding Standards. - See sections related to use of braces, indentation, and comments. -

    -
    - - -
    -

    Incorrect

    -
      -  do {
      -    ready = !notready();
      -  } while (!ready);
      -  senddata();
      -
      -  do ptr++; while (*ptr != '\0');
      -
    -
    -

    Correct

    -
      -  do
      -    {
      -      ready = !notready();
      -    }
      -  while (!ready);
      -
      -  senddata();
      -
      -  do
      -    {
      -      ptr++;
      -    }
      -  while (*ptr != '\0');
      -
      -
    -
    - -

    4.8 Use of goto

    -

    Coding Standard:

    -
      -
    • - Limited Usage of goto. - All use of the goto statement is prohibited except for one usage: - for handling error conditions in complex, nested logic. - A simple goto in those conditions can greatly improve the readability and complexity of the code. -
    • -
    • - Label Naming. - Labels must all lower case. - The underscore character _ is permitted to break up long labels. -
    • -
    • - Error Exit Labels. - The error exit label is normally called errout. - Multiple error labels are often to required to unwind to recover resources committed in logic prior to the error to otherwise undo preceding operations. - Naming for these other labels would be some like errout_with_allocation, errout_with_openfile, etc. -
    • -
    • - Label Positioning. - Labels are never indented. - Labels must always begin in column 1. -
    • -
    -
    - -
    -

    Example

    -
      -   FAR struct some_struct_s *ptr;
      -   int fd;
      -   int ret;
      -   ...
      -
      -   if (arg == NULL)
      -     {
      -       ret = -EINVAL;
      -       goto errout;
      -     }
      -   ...
      -   ptr = (FAR struct some_struct_s *)malloc(sizeof(struct some_struct_s));
      -   if (!ptr)
      -     {
      -       ret = -ENOMEM;
      -       goto errout;
      -     }
      -   ...
      -   fd = open(filename, O_RDONLY);
      -   if (fd < 0)
      -     {
      -       errcode = -errno;
      -       DEBUGASSERT(errcode > 0);
      -       goto errotout_with_alloc;
      -     }
      -   ...
      -   ret = readfile(fd);
      -   if (ret < 0)
      -     {
      -       goto errout_with_openfile;
      -     }
      -   ...
      -errout_with_openfile:
      -  close(fd);
      -
      -errout_with_alloc:
      -  free(ptr);
      -
      -error:
      -  return ret;
      -
    -
    -

    - NOTE: - See the discussion of pointers for information about the FAR qualifier used above. -

    - - - - - -
    -

    5.0 C++

    -
    - -

    - There is no existing document that provides a complete coding standard for NuttX C++ files. - This section is included here to provide some minimal guidance in C++ code development. - In most details like indentation, spacing, and file organization, it is identical to the C coding standard. - But there are significant differences in the acceptable standard beyond that. - The primary differences are as follows: -

    -
      -
    1. -

      - C++ style comments are not only permissible but are required (other than for the following exception). - This includes the block comments of in the Source File Structure described in an Appendix to this standard. -

      -
    2. -
    3. -

      - Deoxygen tags are acceptable. As are C style comments when needed to provide DOxygen tags. -

      -
    4. -
    5. -

      - There is currently no requirement to conform any specific C++ version. - However, for portability reasons, conformance to older, pre-C++11 standards is encouraged where reasonable. -

      -
    6. -

      - C++ file name extensions: The extension .cxx is used for C++ source files; the extension .hxx is used for C++ header files. -

      -
    7. -

      - All naming must use CamelCase. - Use of the underbar character, '_' is discouraged. - This includes variables, classes, structures, ..., etc.: All user-nameable C++ elements. - Pre-processor definitions are still required to be all upper case. -

      -
    8. -
    9. -

      - Local variable, method names, and function names must all begin with a lower case letter. - As examples, myLocalVariable would be a compliant name for a local variable; - myMethod would be a compliant name for a method; -

      -
    10. -

      - Namespaces, global variable, class, structure, template, and enumeration names begin with a capital letter identifying what is being named: -

      -
    11. -

        -
        -
        - Namespace Names -
        -
        - Namespaces begin with an upper case character but no particular character is specified. - As an example, MyNamespace is fully compliant. -
        -
        - Global Variable Names -
        -
        - Global variables and singletons begin with an upper case 'G'. - For example, GMyGlobalVariable. - The prefix g_ is never used. -
        -
        - Implementation Class Names -
        -
        - Classes that implement methods begin with an upper case 'C'. - For example, CMyClass. - A fully qualified method of CMyClass could be MyNamespace::CMyClass::myMethod -
        -
        - Pure Virtual Base Class Names -
        -
        - Such base classes begin with an upper case 'I'. - For example, IMyInterface. -
        -
        - Template Class Names -
        -
        - Template classes begin with an upper case 'T'. - For example, TMyTemplate. -
        -
        - typedef'd Type Names -
        -
        - Currently all such types also begin with an upper case 'T'. - That probably needs some resolution to distinguish for template names. - The suffix _t is never used. -
        -
        - Structure Names -
        -
        - Structures begin with an upper case 'S'. - For example, SMyStructure. - The suffix _s is never used. -
        -
        - Enumerations Names -
        -
        - Enumerations begin with an upper case 'E'. - For example, EMyEnumeration. - The suffix _e is never used. -

      - -
    - - - - - -
    -

    Appendix A

    -
    - -

    A.1 C Source File Structure

    -
    -/****************************************************************************
    - * <Relative path to the file>
    - * <Optional one line file description>
    - *
    - * Licensed to the Apache Software Foundation (ASF) under one or more
    - * contributor license agreements.  See the NOTICE file distributed with
    - * this work for additional information regarding copyright ownership.  The
    - * ASF licenses this file to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance with the
    - * License.  You may obtain a copy of the License at
    - *
    - *   http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    - * License for the specific language governing permissions and limitations
    - * under the License.
    - *
    - ****************************************************************************/
    -
    -/****************************************************************************
    - * Included Files
    - ****************************************************************************/
    -
    -

    All header files are included here.

    -
    -/****************************************************************************
    - * Pre-processor Definitions
    - ****************************************************************************/
    -
    -

    All C pre-processor macros are defined here.

    -
    -/****************************************************************************
    - * Private Types
    - ****************************************************************************/
    -
    -

    Any types, enumerations, structures or unions used by the file are defined here.

    -
    -/****************************************************************************
    - * Private Function Prototypes
    - ****************************************************************************/
    -
    -

    Prototypes of all static functions in the file are provided here.

    -
    -/****************************************************************************
    - * Private Data
    - ****************************************************************************/
    -
    -

    All static data definitions appear here.

    -
    -/****************************************************************************
    - * Public Data
    - ****************************************************************************/
    -
    -

    All data definitions with global scope appear here.

    -
    -/****************************************************************************
    - * Private Functions
    - ****************************************************************************/
    -
    -/****************************************************************************
    - * Name: <Static function name>
    - *
    - * Description:
    - *   Description of the operation of the static function.
    - *
    - * Input Parameters:
    - *   A list of input parameters, one-per-line, appears here along with a
    - *   description of each input parameter.
    - *
    - * Returned Value:
    - *   Description of the value returned by this function (if any),
    - *   including an enumeration of all possible error values.
    - *
    - * Assumptions/Limitations:
    - *   Anything else that one might need to know to use this function.
    - *
    - ****************************************************************************/
    -
    -

    All static functions in the file are defined in this grouping. -Each is preceded by a function header similar to the above.

    -
    -/****************************************************************************
    - * Public Functions
    - ****************************************************************************/
    -
    -/****************************************************************************
    - * Name: <Global function name>
    - *
    - * Description:
    - *   Description of the operation of the function.
    - *
    - * Input Parameters:
    - *   A list of input parameters, one-per-line, appears here along with a
    - *   description of each input parameter.
    - *
    - * Returned Value:
    - *   Description of the value returned by this function (if any),
    - *   including an enumeration of all possible error values.
    - *
    - * Assumptions/Limitations:
    - *   Anything else that one might need to know to use this function.
    - *
    - ****************************************************************************/
    -
    -

    All global functions in the file are defined here.

    - -

    A.2 C Header File Structure

    - -
    -/****************************************************************************
    - * <Relative path to the file>
    - * <Optional one line file description>
    - *
    - * Licensed to the Apache Software Foundation (ASF) under one or more
    - * contributor license agreements.  See the NOTICE file distributed with
    - * this work for additional information regarding copyright ownership.  The
    - * ASF licenses this file to you under the Apache License, Version 2.0 (the
    - * "License"); you may not use this file except in compliance with the
    - * License.  You may obtain a copy of the License at
    - *
    - *   http://www.apache.org/licenses/LICENSE-2.0
    - *
    - * Unless required by applicable law or agreed to in writing, software
    - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
    - * License for the specific language governing permissions and limitations
    - * under the License.
    - *
    - ****************************************************************************/
    -
    -

    Header file idempotence definitions go here

    -
    -/****************************************************************************
    - * Included Files
    - ****************************************************************************/
    -
    -

    All header files are included here.

    -
    -/****************************************************************************
    - * Pre-processor Definitions
    - ****************************************************************************/
    -
    -

    All C pre-processor macros are defined here.

    -
    -/****************************************************************************
    - * Public Types
    - ****************************************************************************/
    -
    -#ifndef __ASSEMBLY__
    -
    -

    Any types, enumerations, structures or unions are defined here.

    -
    -/****************************************************************************
    - * Public Data
    - ****************************************************************************/
    -
    -#ifdef __cplusplus
    -#define EXTERN extern "C"
    -extern "C"
    -{
    -#else
    -#define EXTERN extern
    -#endif
    -
    -
    -

    All data declarations with global scope appear here, preceded by the definition EXTERN.

    -
    -/****************************************************************************
    - * Inline Functions
    - ****************************************************************************/
    -
    -/****************************************************************************
    - * Name: <Inline function name>
    - *
    - * Description:
    - *   Description of the operation of the inline function.
    - *
    - * Input Parameters:
    - *   A list of input parameters, one-per-line, appears here along with a
    - *   description of each input parameter.
    - *
    - * Returned Value:
    - *   Description of the value returned by this function (if any),
    - *   including an enumeration of all possible error values.
    - *
    - * Assumptions/Limitations:
    - *   Anything else that one might need to know to use this function.
    - *
    - ****************************************************************************/
    -
    -

    Any static inline functions may be defined in this grouping. -Each is preceded by a function header similar to the above.

    -
    -/****************************************************************************
    - * Public Function Prototypes
    - ****************************************************************************/
    -
    -/****************************************************************************
    - * Name: <Global function name>
    - *
    - * Description:
    - *   Description of the operation of the function.
    - *
    - * Input Parameters:
    - *   A list of input parameters, one-per-line, appears here along with a
    - *   description of each input parameter.
    - *
    - * Returned Value:
    - *   Description of the value returned by this function (if any),
    - *   including an enumeration of all possible error values.
    - *
    - * Assumptions/Limitations:
    - *   Anything else that one might need to know to use this function.
    - *
    - ****************************************************************************/
    -
    -

    All global functions in the file are prototyped here. The keyword extern or the definition EXTERN are never used with function prototypes.

    -
    -#undef EXTERN
    -#ifdef __cplusplus
    -}
    -#endif
    -
    -#endif /* __INCLUDE_ASSERT_H */
    -
    -

    Ending with the header file idempotence #endif.

    - -
-
- - - diff --git a/Documentation/NuttXGettingStarted.html b/Documentation/NuttXGettingStarted.html deleted file mode 100644 index 6793c2988fe..00000000000 --- a/Documentation/NuttXGettingStarted.html +++ /dev/null @@ -1,25 +0,0 @@ - - -NuttX Getting Started - - - -

- - - - -
-

Getting Started with NuttX

-

Last Updated: December 31, 2011

-
-

-

Getting Started. - There is no official "Getting Started" Guide for NuttX yet. - However, most everything that you need to get started with NuttX can be found in the - NuttX README.txt. -

-

There is an unofficial introductory guide to NuttX available called the - NuttX Companion.

- - diff --git a/Documentation/README.html b/Documentation/README.html deleted file mode 100644 index 3024cf5b653..00000000000 --- a/Documentation/README.html +++ /dev/null @@ -1,649 +0,0 @@ - - -README Files - - -

- - - - -
-

NuttX README Files

-

Last Updated: February 17, 2019

-
-

- Additional information can be found in the Documentation/ directory and - also in README files that are scattered throughout the source tree. - Below is a guide to the available README files. - Some README files contain more important information than others. - The key README files are shown in BOLDFACE/ITALIC below. -

-

- Below is a guide to the available README files in the NuttX source tree: -

- - - -

- Below is a guide to the available README files in the semi-optional apps/ source tree: -

- - - -

- Additional README.txt files in the other, related repositories: -

- - - - diff --git a/Documentation/backgd.gif b/Documentation/backgd.gif deleted file mode 100644 index e81f153aa2b42c18c627621aba029e7db952e154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1097 zcmV-P1h)G}Nk%v~VI%+~0QUd@00030004jh009300Du4h0RI30fdBshfPeu10RMmh zfB^sh0Dyo20RaL60s{jB1qB5L1_lQQ2M7oV2?+@b3JMDg3k(bl4Gj$r4h|0w4-gO# z5fKp*5)u;=6BQK|78Vv47Z(^97#SHE8X6iK8yg%P9334U9v&VaA0HqfAR!?kA|fIq zBO@gxB_<{&CnqN;C@3i@DJm)|D=RB3EG#W8EiNuDFE1}JFfcJOF)}hTGcz+aH8nOi zHa9mnI5;>tIXOByIy*Z%JUl!-Jv}}?K0iM{KtMo2K|w-7LPJACMMXtMMn*?RM@UFW zNl8gcN=i#hOH52mO-)TsPEJoxPf$=$QBhG+Qc_b>Q&m+}R#sM5S65hASXo(FT3T9L zTU%UQTwPsVUS3{bUteHgU}0flVq#)rV`F7yWoBk(XJ=<Cc=sHmx_sj8}~tE;Q5tgNlAt*)-FudlDLu&}YQv9hwVv$M0cwY9dkwzs#p zxVX5vxw*Q!y1To(yu7@dCU$jHda z$;ryf%FD~k%*@Qq&CSlv&d<-!(9qD)(b3Y<($mw^)YR0~)z#M4*4Nk9*x1lt)=I7_<=;-L_>FMg~>g((4 z?Ck9A?d|UF?(gsK@bK{Q@$vHV^7Hfa^z`)g_4W4l_V@Sq`1ttw`T6?#`uqF){QUg= z{r&#_{{R2~EC2ui03-k;000R70OO^LM=;&Lf(HdAG>EXF!h!|UNt7s%;=qU(Cr+$5 zP$R>CAmbebIg(&Vkt0Kr9H{ajLz4tWI=uL>=1ZD47wVk3($a&-!);f_U3^z=%!PFC>eYKQ@?N-LOWLqo zoK;ghq|BJBYP=l7cGPTCcI=OjMLQ+!w)aw(2`Sfgoi(`enXQHY{5*8|(dQd00#%sU zsZ`z7)t-E#Lq9%WNbV0(ZGM3n>N0C{Z#Ok8|Q5e-!jhm(#wC&zgc!)?ma12 P(|pH;C*WiR1q1*)rw| - - -The NuttX RTOS - - - - - - -
-

The NuttX RTOS

-
-

-
- The NuttX RTOS web site has moved to nuttx.org. - Please update your bookmarks and wait while you are redirected there. -
- - diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000000..a485625d427 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +/_build diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000000..36feb34a6dd --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,22 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +html: clean + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/Pipfile b/doc/Pipfile new file mode 100644 index 00000000000..5a000c6a25e --- /dev/null +++ b/doc/Pipfile @@ -0,0 +1,14 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +sphinx = "*" +recommonmark = "*" +sphinx_rtd_theme = "*" + +[requires] +python_version = "3.7" diff --git a/doc/Pipfile.lock b/doc/Pipfile.lock new file mode 100644 index 00000000000..73e1881287c --- /dev/null +++ b/doc/Pipfile.lock @@ -0,0 +1,244 @@ +{ + "_meta": { + "hash": { + "sha256": "d3d0367e13851216b99ed5af8e34abf7e35fecdae5484dc2b61400b733f1536f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, + "babel": { + "hashes": [ + "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", + "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" + ], + "version": "==2.8.0" + }, + "certifi": { + "hashes": [ + "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3", + "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41" + ], + "version": "==2020.6.20" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "commonmark": { + "hashes": [ + "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60", + "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9" + ], + "version": "==0.9.1" + }, + "docutils": { + "hashes": [ + "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", + "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" + ], + "version": "==0.16" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "version": "==2.10" + }, + "imagesize": { + "hashes": [ + "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", + "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" + ], + "version": "==1.2.0" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "version": "==2.11.2" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "version": "==1.1.1" + }, + "packaging": { + "hashes": [ + "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8", + "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181" + ], + "version": "==20.4" + }, + "pygments": { + "hashes": [ + "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44", + "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324" + ], + "version": "==2.6.1" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "version": "==2.4.7" + }, + "pytz": { + "hashes": [ + "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed", + "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048" + ], + "version": "==2020.1" + }, + "recommonmark": { + "hashes": [ + "sha256:29cd4faeb6c5268c633634f2d69aef9431e0f4d347f90659fd0aab20e541efeb", + "sha256:2ec4207a574289355d5b6ae4ae4abb29043346ca12cdd5f07d374dc5987d2852" + ], + "index": "pypi", + "version": "==0.6.0" + }, + "requests": { + "hashes": [ + "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b", + "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898" + ], + "version": "==2.24.0" + }, + "six": { + "hashes": [ + "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", + "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" + ], + "version": "==1.15.0" + }, + "snowballstemmer": { + "hashes": [ + "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", + "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52" + ], + "version": "==2.0.0" + }, + "sphinx": { + "hashes": [ + "sha256:97dbf2e31fc5684bb805104b8ad34434ed70e6c588f6896991b2fdfd2bef8c00", + "sha256:b9daeb9b39aa1ffefc2809b43604109825300300b987a24f45976c001ba1a8fd" + ], + "index": "pypi", + "version": "==3.1.2" + }, + "sphinx-rtd-theme": { + "hashes": [ + "sha256:22c795ba2832a169ca301cd0a083f7a434e09c538c70beb42782c073651b707d", + "sha256:373413d0f82425aaa28fb288009bf0d0964711d347763af2f1b65cafcb028c82" + ], + "index": "pypi", + "version": "==0.5.0" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", + "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", + "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" + ], + "version": "==1.1.4" + }, + "urllib3": { + "hashes": [ + "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", + "sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115" + ], + "version": "==1.25.9" + } + }, + "develop": {} +} diff --git a/doc/_static/custom.css b/doc/_static/custom.css new file mode 100644 index 00000000000..058bf376f06 --- /dev/null +++ b/doc/_static/custom.css @@ -0,0 +1,25 @@ +/* Make content wider */ + +.wy-nav-content { + max-width: 1200px !important; +} + +/* Make links inside C definitions more visible */ + +.c a:link { + color: black; +} + +/* override table width restrictions */ +@media screen and (min-width: 767px) { + + .wy-table-responsive table td { + /* !important prevents the common CSS stylesheets from overriding + this as on RTD they are loaded after this stylesheet */ + white-space: normal !important; + } + + .wy-table-responsive { + overflow: visible !important; + } +} diff --git a/doc/_static/favicon.ico b/doc/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..40668652bc65ac23fac27c4be1a1d9b006035485 GIT binary patch literal 4286 zcmb_gTTEO<7(SJUjq!pH#y0~Gt56|OcBxXZ7C~uD8c1ufRZ6TeA?lOyv8id%U=`Ys z+EfZPYBd5)sJAp$f#NohwoqA6ce$(r%kJVXm%=Vkx?F$%fA-AjoY}LK7^WF!_U!Ec zUH*S&PO2zd@Lyu0LVuOUM-=5TMNyKm<0B;(J3Zg*=FNQ8Jh&sr=i2}LS2(|Kv*WK9 zkFZ^qY~MfDY#1om37g3w>G6k@E1$hqCiF)|E+RJ0f%--`P+V$!6l3!F_KZ|EZ9Q`U zTF<-+$bq_*e=lPD3X8y9cM_UPUV)3L7I3~8+lP?X{($Y=o0rsh)v-9>y0XRjDWDeU z|4oN4VtcJQFx}k(bN@PE^6%?#V)qNsoR(?m1IA349sA>U&|`<2P31gh3fCl#I{dyi zzSgS4M!)?ZABFkx0mgG-+5;U8XQ3)N6-JPkoC}OuyL=}EOA9kF+Wn&zQ^e(SBYgYe zqW!$qDA!DTPb*MNYO5=YaBH|r^MKZH4#DBhMC7?d>uygDfup&G@PFTs|ET}xs$#G| zm$N{1&ak=mKtwymr6zm8IgGb|H$^;G78fv29ne-&O89%YUU?MtkNtH8DtB6-HzP~K z7PYS~FEVTzjXW58y%gsB{cO!fv=bK*f3&w1K1@mhr)7tR&+@KnC(YEvQLKZ>Um97C zNPA$Q9a>J8tgHQ=_*C<1-pNy5e>Bo((Sz252Xxw->rTMe`?43kmK?L}x%fHc>3)mv zKUu%1oiIgwKIe5{zg(|r_xH6!MS2GGTC%`-FwYl@1J;b$|Ls|yA-<%2YUl>y4@Po3 z;R3h4Me|^4s1s)WeUb05=1F@)$~Kn6k<1)J4unm6%=5)5Fv6F$x7XL;esZZ8E@-Ma z4D&)=@S5k^9YPJs95^=Zv2i1OtbZ}@w}v~Rsvuv7Uv5r@QMESKR#yzQ)1KsAwnEoON3?aT%VC&sU1NE-i~CpN;3&@ZIZN|=BL%w{ zwpgW7#_&jeE$;%@AtLZ{+n^%)bgp*PB|3u)%{239P#x0*~ac8 zI*()zVqtR*;`tNucC&a<+9iDArfJ7LNIC1q8kIe`n3@3tm~ZYm#}r5L{GSU%?v5z! zGCpE*?Ub*|q*QPh7D5p3WYL3DMOkp8d|%`RO9U0>BL31skm=Xuo$nvP|8U69N}kRi z(oXL|ROb_obvh5O)gPhzr&fTAnu_=o)KI&mpUxY~5!X)dK!i{4hoT4Go=b$kggqe& zSbZSkQ_LB67o0AB33~D)F)1$Vf_}zR(oSor*2XTJTe({Y4(PnFz6T;cX&=0L9$HQo zcl6`EHM}QsM#=a_+6kM^Re$9%YslLZ%sj-9w7ei`EeJ7Ljjl`=>ps5W#pNa z_NI;ldK~if0C_*BYHv&1&b;B+$dldm81pFiVAj_Q?O(oQi}n6ToN#?5_O3vG+slY; z=4)jR6Ag6`8ta7#e9!4jf7%dRjTevcf>fV4+J3Fx`=F8bjXaY%&^g5Nq2`-B=eoss zh`SB@8`%FhHjfv@;U3uhcbhqi9OQg&CeC`X7>ANP-(aS(=j;7e{0>%j0fZAE{BAsi z51Ed;bK~ON$`1&+; literal 0 HcmV?d00001 diff --git a/doc/applications/index.rst b/doc/applications/index.rst new file mode 100644 index 00000000000..489d45d4687 --- /dev/null +++ b/doc/applications/index.rst @@ -0,0 +1,6 @@ +Applications +============ + +.. note:: This is to be used to describe how applications work in NuttX as well as to ducment + existing ones. + diff --git a/doc/boards/index.rst b/doc/boards/index.rst new file mode 100644 index 00000000000..6e96a41510f --- /dev/null +++ b/doc/boards/index.rst @@ -0,0 +1,8 @@ +Supported Boards +================ + +.. note:: + Include a full list of supported boards, organized by architecture / family / vendor. + Each board should have its own entry, a photo, brief hardware specifications, features + supported (currently working in NuttX), how to flash, special toolchains required, etc. + diff --git a/doc/components/binfmt.rst b/doc/components/binfmt.rst new file mode 100644 index 00000000000..1267153d379 --- /dev/null +++ b/doc/components/binfmt.rst @@ -0,0 +1,372 @@ +============= +Binary Loader +============= + +The purpose of a *binary loader* is to load and +execute modules in various *binary formats* that reside in a file +system. Loading refers instantiating the binary module in some fashion, +usually copy all or some of the binary module into memory and then +linking the module with other components. In most architectures, it is +the base FLASH code that is the primary component that the binary module +must link with because that is where the RTOS and primary tasks reside. +Program modules can then be executed after they have been loaded. + +**Binary Formats**. The binary loader provides generic support for +different binary formats. It supports a *registration interface* that +allows the number of support binary formats to be loaded at run time. +Each binary format provides a common, interface for use by the binary +loader. When asked to load a binary, the binary loader will query each +registered binary format, providing it with the path of the binary +object to be loaded. The binary loader will stop when first binary +format the recognizes the binary object and successfully loads it or +when all registered binary formats have attempt loading the binary +object and failed. + +At present, the following binary formats are support by NuttX: + + - **ELF**. Standard ELF formatted files. + - **NXFLAT**. NuttX NXFLAT formatted files. More information about the + NXFLAT binary format can be found in the `NXFLAT + documentation `__. + +**Executables and Libraries** The generic binary loader logic does not +care what it is that it being loaded. It could load an executable +program or a library. There are no strict rules, but a library will tend +to export symbols and a program will tend to import symbols: The program +will use the symbols exported by the library. However, at this point in +time, none of the supported binary formats support exporting of symbols. + +**binfmt**. In the NuttX source code, the short name ``binfmt`` is used +to refer to the NuttX binary loader. This is the name of the directory +containing the binary loader and the name of the header files and +variables used by the binary loader. + +The name ``binfmt`` is the same name used by the Linux binary loader. +However, the NuttX binary loader is an independent development and +shares nothing with the Linux binary loader other the same name and the +same basic functionality. + +Binary Loader Interface +======================= + +Header Files +------------ + +The interface to the binary loader is described in the header file +``include/nuttx/binfmt/binfmt.h``. +A brief summary of the data structurs and interfaces prototyped in that +header file are listed below. + +Data Structures +--------------- + +When a binary format registers with the binary loader, it provides a +pointer to a write-able instance of :c:struct:`binfmt_s`. + +.. c:struct:: binfmt_s + + .. code-block:: c + + struct binfmt_s + { + FAR struct binfmt_s *next; /* Supports a singly-linked list */ + int (*load)(FAR struct binary_s *bin); /* Verify and load binary into memory */ + }; + + + The ``load`` method is used to load the binary format into memory. It + returns either ``OK`` (0) meaning that the binary object was loaded + successfully, or a negated ``errno`` indicating why the object was not + loaded. + +.. c:struct:: binary_s + + The type ``struct binary_s`` is use both to (1) describe the binary + object to be loaded, and if successfully loaded, (2) to provide + information about where and how the binary object was loaded. That + structure is shown below: + + .. code-block:: c + + struct symtab_s; + struct binary_s + { + /* Information provided to the loader to load and bind a module */ + + FAR const char *filename; /* Full path to the binary to be loaded */ + FAR const char **argv; /* Argument list */ + FAR const struct symtab_s *exports; /* Table of exported symbols */ + int nexports; /* The number of symbols in exports[] */ + + /* Information provided from the loader (if successful) describing the + * resources used by the loaded module. + */ + + main_t entrypt; /* Entry point into a program module */ + FAR void *mapped; /* Memory-mapped, address space */ + FAR void *alloc[BINFMT_NALLOC]; /* Allocated address spaces */ + + /* Constructors/destructors */ + + #ifdef CONFIG_BINFMT_CONSTRUCTORS + FAR binfmt_ctor_t *ctors; /* Pointer to a list of constructors */ + FAR binfmt_dtor_t *dtors; /* Pointer to a list of destructors */ + uint16_t nctors; /* Number of constructors in the list */ + uint16_t ndtors; /* Number of destructors in the list */ + #endif + + /* Address environment. + * + * addrenv - This is the handle created by up_addrenv_create() that can be + * used to manage the tasks address space. + */ + + #ifdef CONFIG_ARCH_ADDRENV + group_addrenv_t addrenv; /* Task group address environment */ + #endif + + size_t mapsize; /* Size of the mapped address region (needed for munmap) */ + + /* Start-up information that is provided by the loader, but may be modified + * by the caller between load_module() and exec_module() calls. + */ + + uint8_t priority; /* Task execution priority */ + size_t stacksize; /* Size of the stack in bytes (unallocated) */ + }; + + Where the types ``binfmt_ctor_t`` and ``binfmt_dtor_t`` define the type + of one C++ constructor or destructor: + + .. code-block:: c + + typedef FAR void (*binfmt_ctor_t)(void); + typedef FAR void (*binfmt_dtor_t)(void); + +Function Interfaces +------------------- + +Binary format management +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: int register_binfmt(FAR struct binfmt_s *binfmt) + + Register a loader for a binary format. + + :return: This is a NuttX internal function so it follows the convention + that 0 (OK) is returned on success and a negated errno is returned on + failure. + +.. c:function:: int unregister_binfmt(FAR struct binfmt_s *binfmt) + + Register a loader for a binary format. + + :return: + This is a NuttX internal function so it follows the convention + that 0 (OK) is returned on success and a negated errno is returned on + failure. + +Basic module management +~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: int load_module(FAR struct binary_s *bin) + + Load a module into memory, bind it to an exported symbol take, + and prep the module for execution. + + :param bin: + The ``filename`` field will be used + in order to locate the module to be loaded from the file system. + The filename must be the full, absolute path to the file to be executed + unless ``CONFIG_LIB_ENVPATH`` is defined. In that case, filename may be + a relative path; a set of candidate absolute paths will be generated using + the ``PATH`` environment variable and ``load_module()`` will attempt to load each + file that is found at those absolute paths. + + :return: + This is a NuttX internal function so it follows the convention that 0 (``OK``) + is returned on success and a negated ``errno`` is returned on failure. + +.. c:function:: int unload_module(FAR struct binary_s *bin) + + Unload a (non-executing) module from memory. If the module has been started + (via :c:func:`exec_module`) and has not exited, calling this will be fatal. + + However, this function must be called after the module exist. How this is + done is up to your logic. Perhaps you register it to be called by :c:func:`on_exit`? + + :return: + This is a NuttX internal function so it follows the convention that 0 (``OK``) + is returned on success and a negated ``errno`` is returned on failure. + +.. c:function:: int exec_module(FAR const struct binary_s *bin); + + Execute a module that has been loaded into memory by :c:func:`load_module`. + + :return: + This is a NuttX internal function so it follows the convention that 0 (``OK``) + is returned on success and a negated ``errno`` is returned on failure. + +.. c:function:: int exec(FAR const char *filename, FAR const char **argv, FAR const struct symtab_s *exports, int nexports) + + This is a convenience function that wraps :c:func:`load_module` and + :c:func:`exec_module` into one call. + + :param filename: Full path to the binary to be loaded. + :param argv: Argument list. + :param exports: Table of exported symbols. + :param exports: The number of symbols in exports. + + :return: + This is an end-user function, so it follows the normal convention: + Returns 0 (``OK``) on success. On failure, it returns -1 (ERROR) + with ``errno`` set appropriately. + +``PATH`` traversal logic +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. c:function:: ENVPATH_HANDLE envpath_init(void); + + Initialize for the traversal of each value in the ``PATH`` variable. The + usage is sequence is as follows: + + #. Call :c:func:`envpath_init` to initialize for the traversal. + ``envpath_init()`` will return an opaque handle that can then be + provided to :c:func:`envpath_next` and :c:func:`envpath_release`. + #. Call :c:func:`envpath_next` repeatedly to examine every file that lies in + the directories of the ``PATH`` variable. + #. Call :c:func:`envpath_release` to free resources set aside by + :c:func:`envpath_init`. + + :return: + On success, :c:func:`envpath_init` return a non-``NULL``, opaque handle + that may subsequently be used in calls to :c:func:`envpath_next` and + :c:func:`envpath_release`. On error, a ``NULL`` handle value will be returned. + The most likely cause of an error would be that there is no value + associated with the ``PATH`` variable. + +.. c:function:: FAR char *envpath_next(ENVPATH_HANDLE handle, FAR const char *relpath) + + Traverse all possible values in the PATH variable in attempt to find the + full path to an executable file when only a relative path is provided. + + :param handle: The handle value returned by :c:func:`envpath_init`. + :param relpath: The relative path to the file to be found. + + :return: + On success, a non-``NULL`` pointer to a null-terminated string is provided. + This is the full path to a file that exists in the file system. + This function will verify that the file exists (but will not verify that it is marked executable). + + .. note:: + The string pointer return in the success case points to allocated memory. + This memory must be freed by the called by calling :c:func:`kmm_free`. + + ``NULL`` relpath from any absolute path in the ``PATH`` variable. + In this case, there is no point in calling :c:func:`envpath_next` further; + :c:func:`envpath_release` must be called to release resources set aside by + :c:func:`envpath_init`. + +.. c:function:: void envpath_release(ENVPATH_HANDLE handle) + +Release all resources set aside by envpath_init when the +handle value was created. The handle value is invalid on +return from this function. Attempts to all :c:func:`envpath_next` +or :c:func:`envpath_release` with such a stale handle will result +in undefined (i.e., not good) behavior. + + :param handle: The handle value returned by :c:func:`envpath_init`. + +Symbol Tables +============= + +**Symbol Tables**. Symbol tables are lists of name value mappings: The +name is a string that identifies a symbol, and the value is an address +in memory where the symbol of that name has been positioned. In most +NuttX architectures symbol tables are required, as a minimum, in order +to dynamically link the loaded binary object with the base code on +FLASH. Since the binary object was separately built and separately +linked, these symbols will appear as *undefined* symbols in the binary +object. The binary loader will use the symbol table to look up the +symbol by its name and to provide the address associated with the symbol +as needed to perform the dynamic linking of the binary object to the +base FLASH code. + +Symbol Table Header Files +------------------------- + +The interface to the symbol table logic is described in the header file +``include/nuttx/binfmt/symtab.h``. +A brief summary of the data structurs and interfaces prototyped in that +header file are listed below. + +Symbol Table Data Structures +---------------------------- + +.. c:struct:: symbtab_s + + Describes one entry in the symbol table. + + .. code-block:: c + + struct symtab_s + { + FAR const char *sym_name; /* A pointer to the symbol name string */ + FAR const void *sym_value; /* The value associated with the string */ + }; + + A symbol table is a fixed size array of ``struct symtab_s``. The + information is intentionally minimal and supports only: + + #. Function pointers as ``sym_values``. Of other kinds of values need to + be supported, then typing information would also need to be included + in the structure. + #. Fixed size arrays. There is no explicit provisional for dynamically + adding or removing entries from the symbol table (realloc might be + used for that purpose if needed). The intention is to support only + fixed size arrays completely defined at compilation or link time. + +Symbol Table Function Interfaces +-------------------------------- + +.. c:function:: FAR const struct symtab_s *symtab_findbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms); + + Find the symbol in the symbol table with the matching name. + This version assumes that table is not ordered with respect to + symbol name and, hence, access time will be linear with respect + to ``nsyms``. + + :return: + A reference to the symbol table entry if an entry with the matching name is found; NULL is returned if the entry is not found. + +.. c:function:: FAR const struct symtab_s *symtab_findorderedbyname(FAR const struct symtab_s *symtab, FAR const char *name, int nsyms); + + Find the symbol in the symbol table with the matching name. + This version assumes that table ordered with respect to symbol name. + + :return: + A reference to the symbol table entry if an entry with + the matching name is found; NULL is returned if the entry is not found. + + +.. c:function:: FAR const struct symtab_s *symtab_findbyvalue(FAR const struct symtab_s *symtab, FAR void *value, int nsyms); + + Find the symbol in the symbol table whose value closest + (but not greater than), the provided value. This version assumes + that table is not ordered with respect to symbol name and, hence, + access time will be linear with respect to ``nsyms``. + + :return: + A reference to the symbol table entry if an entry with the matching + name is found; ``NULL`` is returned if the entry is not found. + +Configuration Variables +======================= + + - ``CONFIG_BINFMT_DISABLE``: By default, support for loadable binary formats is built. + This logic may be suppressed be defining this setting. + - ``CONFIG_BINFMT_CONSTRUCTORS``: Build in support for C++ constructors in loaded modules. + - ``CONFIG_SYMTAB_ORDEREDBYNAME``: Symbol tables are order by name (rather than value). + +Additional configuration options may be required for the each enabled +binary format. diff --git a/doc/components/drivers/index.rst b/doc/components/drivers/index.rst new file mode 100644 index 00000000000..28af15da75c --- /dev/null +++ b/doc/components/drivers/index.rst @@ -0,0 +1,941 @@ +============== +Device Drivers +============== + +NuttX supports a variety of device drivers including: + + - *Character* Device Drivers, + - *Block* Device Drivers, and + - Other *Specialized* Drivers. + +These different device driver types are discussed in the following +paragraphs. Note: device driver support depends on the +*in-memory*, *pseudo* file system that is enabled by default. + +Character Device Drivers +************************ + +Character device drivers have these properties: + +- ``include/nuttx/fs/fs.h``. All structures and APIs needed + to work with character drivers are provided in this header + file. + +- ``struct file_operations``. Each character device driver + must implement an instance of ``struct file_operations``. That + structure defines a call table with the following methods: + +- ``int register_driver(const char *path, const struct file_operations *fops, mode_t mode, void *priv);``. + Each character driver registers itself by calling + ``register_driver()``, passing it the ``path`` where it will + appear in the `pseudo-file-system <#NxFileSystem>`__ and it's + initialized instance of ``struct file_operations``. + +- **User Access**. After it has been registered, the character + driver can be accessed by user code using the standard `driver + operations `__ including + ``open()``, ``close()``, ``read()``, ``write()``, etc. + +- **Specialized Character Drivers**. Within the common character + driver framework, there are different specific varieties of + *specialized* character drivers. The unique requirements of the + underlying device hardware often mandates some customization of + the character driver. These customizations tend to take the + form of: + + - Device-specific ``ioctl()`` commands used to performed + specialized operations on the device. These ``ioctl()`` will + be documented in header files under ``include/nuttx`` that + detail the specific device interface. + - Specialized I/O formats. Some devices will require that + ``read()`` and/or ``write()`` operations use data conforming + to a specific format, rather than a plain stream of bytes. + These specialized I/O formats will be documented in header + files under ``include/nuttx`` that detail the specific + device interface. The typical representation of the I/O + format will be a C structure definition. + + The specialized character drivers support by NuttX are + documented in the following paragraphs. + +- **Examples**: ``drivers/dev_null.c``, ``drivers/fifo.c``, + ``drivers/serial.c``, etc. + +Serial Device Drivers +===================== + +- ``include/nuttx/serial/serial.h``. All structures and APIs + needed to work with serial drivers are provided in this header + file. + +- ``struct uart_ops_s``. Each serial device driver must + implement an instance of ``struct uart_ops_s``. That structure + defines a call table with the following methods: + +- ``int uart_register(FAR const char *path, FAR uart_dev_t *dev);``. + A serial driver may register itself by calling + ``uart_register()``, passing it the ``path`` where it will + appear in the `pseudo-file-system <#NxFileSystem>`__ and it's + initialized instance of ``struct uart_ops_s``. By convention, + serial device drivers are registered at paths like + ``/dev/ttyS0``, ``/dev/ttyS1``, etc. See the + ``uart_register()`` implementation in ``drivers/serial.c``. + +- **User Access**. Serial drivers are, ultimately, normal + `character drivers <#chardrivers>`__ and are accessed as other + character drivers. + +- **Examples**: ``arch/arm/src/stm32/stm32_serial.c``, + ``arch/arm/src/lpc214x/lpc214x_serial.c``, + ``arch/z16/src/z16f/z16f_serial.c``, etc. + +Touchscreen Device Drivers +========================== + +NuttX supports a two-part touchscreen driver architecture. + +#. An "upper half", generic driver that provides the common + touchscreen interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level touchscreen controls to implement the touchscreen + functionality. + +Files supporting the touchscreen controller (TSC) driver can be +found in the following locations: + +- **Interface Definition**. The header files for NuttX + touchscreen drivers reside in the + ``include/nuttx/include/input`` directory. The interface + between the touchscreen controller "upper half" and "lower + half" drivers are *not* common, but vary from + controller-to-controller. Because of this, each touchscreen + driver has its own unique header file that describes the "upper + half"/"lower half" interface in that directory. The application + level interface to each touchscreen driver, on the other hand, + *is* the same for each touchscreen driver and is described + ``include/nuttx/include/input/touchscreen.h``. The touchscreen + driver uses a standard character driver framework but read + operations return specially formatted data. +- **"Upper Half" Driver**. The controller-specific, "upper half" + touchscreen drivers reside in the directory ``drivers/input``. +- **"Lower Half" Drivers**. Platform-specific touchscreen drivers + reside in either: (1) The + ``arch/``\ **\ ``/src/``\ ** directory + for the processor architectures that have build in touchscreen + controllers or (2) the + ``boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/src/`` + directory for boards that use an external touchscreen + controller chip. + +Analog (ADC/DAC) Drivers +======================== + +The NuttX analog drivers are split into two parts: + +#. An "upper half", generic driver that provides the common analog + interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level controls to implement the analog functionality. + +- General header files for the NuttX analog drivers reside in + ``include/nuttx/analog/``. These header files includes both the + application level interface to the analog driver as well as the + interface between the "upper half" and "lower half" drivers. +- Common analog logic and share-able analog drivers reside in the + ``drivers/analog/``. +- Platform-specific drivers reside in + ``arch/``\ **\ ``/src/``\ ** directory + for the specific processor ** and for the + specific ** analog peripheral devices. + +ADC Drivers +----------- + +- ``include/nuttx/analog/adc.h``. All structures and APIs needed + to work with ADC drivers are provided in this header file. This + header file includes: + + #. Structures and interface descriptions needed to develop a + low-level, architecture-specific, ADC driver. + #. To register the ADC driver with a common ADC character + driver. + #. Interfaces needed for interfacing user programs with the + common ADC character driver. + +- ``drivers/analog/adc.c``. The implementation of the common ADC + character driver. + +DAC Drivers +----------- + +- ``include/nuttx/analog/dac.h``. All structures and APIs needed + to work with DAC drivers are provided in this header file. This + header file includes: + + #. Structures and interface descriptions needed to develop a + low-level, architecture-specific, DAC driver. + #. To register the DAC driver with a common DAC character + driver. + #. Interfaces needed for interfacing user programs with the + common DAC character driver. + +- ``drivers/analog/dac.c``. The implementation of the common DAC + character driver. + +PWM Drivers +=========== + +For the purposes of this driver, a PWM device is any device that +generates periodic output pulses of controlled frequency and pulse +width. Such a device might be used, for example, to perform +pulse-width modulated output or frequency/pulse-count modulated +output (such as might be needed to control a stepper motor). + +The NuttX PWM driver is split into two parts: + +#. An "upper half", generic driver that provides the common PWM + interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the PWM functionality. + +Files supporting PWM can be found in the following locations: + +- **Interface Definition**. The header file for the NuttX PWM + driver reside at ``include/nuttx/timers/pwm.h``. This header + file includes both the application level interface to the PWM + driver as well as the interface between the "upper half" and + "lower half" drivers. The PWM module uses a standard character + driver framework. However, since the PWM driver is a devices + control interface and not a data transfer interface, the + majority of the functionality available to the application is + implemented in driver ioctl calls. +- **"Upper Half" Driver**. The generic, "upper half" PWM driver + resides at ``drivers/pwm.c``. +- **"Lower Half" Drivers**. Platform-specific PWM drivers reside + in ``arch/``\ **\ ``/src/``\ ** + directory for the specific processor ** and for + the specific ** PWM peripheral devices. + +CAN Drivers +=========== + +NuttX supports only a very low-level CAN driver. This driver +supports only the data exchange and does not include any +high-level CAN protocol. The NuttX CAN driver is split into two +parts: + +#. An "upper half", generic driver that provides the common CAN + interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the CAN functionality. + +Files supporting CAN can be found in the following locations: + +- **Interface Definition**. The header file for the NuttX CAN + driver resides at ``include/nuttx/can/can.h``. This header file + includes both the application level interface to the CAN driver + as well as the interface between the "upper half" and "lower + half" drivers. The CAN module uses a standard character driver + framework. +- **"Upper Half" Driver**. The generic, "upper half" CAN driver + resides at ``drivers/can.c``. +- **"Lower Half" Drivers**. Platform-specific CAN drivers reside + in ``arch/``\ **\ ``/src/``\ ** + directory for the specific processor ** and for + the specific ** CAN peripheral devices. + +**Usage Note**: When reading from the CAN driver multiple messages +may be returned, depending on (1) the size the returned can +messages, and (2) the size of the buffer provided to receive CAN +messages. *Never assume that a single message will be returned*... +if you do this, *you will lose CAN data* under conditions where +your read buffer can hold more than one small message. Below is an +example about how you should think of the CAN read operation: + +Quadrature Encoder Drivers +========================== + +NuttX supports a low-level, two-part Quadrature Encoder driver. + +#. An "upper half", generic driver that provides the common + Quadrature Encoder interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the Quadrature Encoder + functionality. + +Files supporting the Quadrature Encoder can be found in the +following locations: + +- **Interface Definition**. The header file for the NuttX + Quadrature Encoder driver reside at + ``include/nuttx/sensors/qencoder.h``. This header file includes + both the application level interface to the Quadrature Encoder + driver as well as the interface between the "upper half" and + "lower half" drivers. The Quadrature Encoder module uses a + standard character driver framework. +- **"Upper Half" Driver**. The generic, "upper half" Quadrature + Encoder driver resides at ``drivers/sensors/qencoder.c``. +- **"Lower Half" Drivers**. Platform-specific Quadrature Encoder + drivers reside in + ``arch/``\ **\ ``/src/``\ ** directory + for the specific processor ** and for the + specific ** Quadrature Encoder peripheral devices. + +Timer Drivers +============= + +NuttX supports a low-level, two-part timer driver. + +#. An "upper half", generic driver that provides the common timer + interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the timer functionality. + +Files supporting the timer driver can be found in the following +locations: + +- **Interface Definition**. The header file for the NuttX timer + driver reside at ``include/nuttx/timers/timer.h``. This header + file includes both the application level interface to the timer + driver as well as the interface between the "upper half" and + "lower half" drivers. The timer driver uses a standard + character driver framework. +- **"Upper Half" Driver**. The generic, "upper half" timer driver + resides at ``drivers/timers/timer.c``. +- **"Lower Half" Drivers**. Platform-specific timer drivers + reside in ``arch/``\ **\ ``/src/``\ ** + directory for the specific processor ** and for + the specific ** timer peripheral devices. + +RTC Drivers +=========== + +NuttX supports a low-level, two-part RealTime Clock (RTC) driver. + +#. An "upper half", generic driver that provides the common RTC + interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the RTC functionality. + +Files supporting the RTC driver can be found in the following +locations: + +- **Interface Definition**. The header file for the NuttX RTC + driver reside at ``include/nuttx/timers/rtc.h``. This header + file includes both the application level interface to the RTC + driver as well as the interface between the "upper half" and + "lower half" drivers. The RTC driver uses a standard character + driver framework. +- **"Upper Half" Driver**. The generic, "upper half" RTC driver + resides at ``drivers/timers/rtc.c``. +- **"Lower Half" Drivers**. Platform-specific RTC drivers reside + in ``arch/``\ **\ ``/src/``\ ** + directory for the specific processor ** and for + the specific ** RTC peripheral devices. + +Watchdog Timer Drivers +====================== + +NuttX supports a low-level, two-part watchdog timer driver. + +#. An "upper half", generic driver that provides the common + watchdog timer interface to application level code, and +#. A "lower half", platform-specific driver that implements the + low-level timer controls to implement the watchdog timer + functionality. + +Files supporting the watchdog timer driver can be found in the +following locations: + +- **Interface Definition**. The header file for the NuttX + watchdog timer driver reside at + ``include/nuttx/timers/watchdog.h``. This header file includes + both the application level interface to the watchdog timer + driver as well as the interface between the "upper half" and + "lower half" drivers. The watchdog timer driver uses a standard + character driver framework. +- **"Upper Half" Driver**. The generic, "upper half" watchdog + timer driver resides at ``drivers/timers/watchdog.c``. +- **"Lower Half" Drivers**. Platform-specific watchdog timer + drivers reside in + ``arch/``\ **\ ``/src/``\ ** directory + for the specific processor ** and for the + specific ** watchdog timer peripheral devices. + +Keyboard/Keypad Drivers +======================= + +**Keypads vs. Keyboards** Keyboards and keypads are really the +same devices for NuttX. A keypad is thought of as simply a +keyboard with fewer keys. + +**Special Commands**. In NuttX, a keyboard/keypad driver is simply +a character driver that may have an (optional) encoding/decoding +layer on the data returned by the character driver. A keyboard may +return simple text data (alphabetic, numeric, and punctuation) or +control characters (enter, control-C, etc.) when a key is pressed. +We can think about this the "normal" keyboard data stream. +However, in addition, most keyboards support actions that cannot +be represented as text or control data. Such actions include +things like cursor controls (home, up arrow, page down, etc.), +editing functions (insert, delete, etc.), volume controls, (mute, +volume up, etc.) and other special functions. In this case, some +special encoding may be required to multiplex the normal text data +and special command key press data streams. + +**Key Press and Release Events** Sometimes the time that a key is +released is needed by applications as well. Thus, in addition to +normal and special key press events, it may also be necessary to +encode normal and special key release events. + +**Encoding/Decoding** Layer. An optional encoding/decoding layer +can be used with the basic character driver to encode the keyboard +events into the text data stream. The function interfaces that +comprise that encoding/decoding layer are defined in the header +file ``include/nuttx/input/kbd_code.h``. These functions provide +an matched set of (a) driver encoding interfaces, and (b) +application decoding interfaces. + +#. **Driver Encoding Interfaces**. These are interfaces used by + the keyboard/keypad driver to encode keyboard events and data. + + - ``kbd_press()`` + + **Function Prototype:** + + **Description:** + + **Input Parameters:** + + - ``ch``: The character to be added to the output stream. + - ``stream``: An instance of ``lib_outstream_s`` to perform + the actual low-level put operation. + + **Returned Value:** + + - ``kbd_release()`` + + **Function Prototype:** + + **Description:** + + **Input Parameters:** + + - ``ch``: The character associated with the key that was + released. + - ``stream``: An instance of ``lib_outstream_s`` to perform + the actual low-level put operation. + + **Returned Value:** + + - ``kbd_specpress()`` + + **Function Prototype:** + + **Description:** + + **Input Parameters:** + + - ``keycode``: The command to be added to the output + stream. The enumeration ``enum kbd_keycode_e keycode`` + identifies all commands known to the system. + - ``stream``: An instance of ``lib_outstream_s`` to perform + the actual low-level put operation. + + **Returned Value:** + + - ``kbd_specrel()`` + + **Function Prototype:** + + **Description:** + + **Input Parameters:** + + - ``keycode``: The command to be added to the output + stream. The enumeration ``enum kbd_keycode_e keycode`` + identifies all commands known to the system. + - ``stream``: An instance of ``lib_outstream_s`` to perform + the actual low-level put operation. + + **Returned Value:** + +#. **Application Decoding Interfaces**. These are user interfaces + to decode the values returned by the keyboard/keypad driver. + + - ``kbd_decode()`` + + **Function Prototype:** + + **Description:** + + **Input Parameters:** + + - ``stream``: An instance of ``lib_instream_s`` to perform + the actual low-level get operation. + - ``pch``: The location to save the returned value. This + may be either a normal, character code or a special + command (i.e., a value from ``enum kbd_getstate_s``. + - ``state``: A user provided buffer to support parsing. + This structure should be cleared the first time that + ``kbd_decode()`` is called. + + **Returned Value:** + + - ``KBD_PRESS`` (0)**: Indicates the successful receipt + of normal, keyboard data. This corresponds to a keypress + event. The returned value in ``pch`` is a simple byte of + text or control data. + - ``KBD_RELEASE`` (1)**: Indicates a key release event. + The returned value in ``pch`` is the byte of text or + control data corresponding to the released key. + - ``KBD_SPECPRESS`` (2)**: Indicates the successful + receipt of a special keyboard command. The returned value + in ``pch`` is a value from ``enum kbd_getstate_s``. + - ``KBD_SPECREL`` (3)**: Indicates a special command key + release event. The returned value in ``pch`` is a value + from ``enum kbd_getstate_s``. + - ``KBD_ERROR`` (``EOF``)**: An error has getting the + next character (reported by the ``stream``). Normally + indicates the end of file. + +**I/O Streams**. Notice the use of the abstract I/O streams in +these interfaces. These stream interfaces are defined in +``include/nuttx/streams.h``. + +Block Device Drivers +******************** + +Block device drivers have these properties: + +- ``include/nuttx/fs/fs.h``. All structures and APIs needed + to work with block drivers are provided in this header file. + +- ``struct block_operations``. Each block device driver must + implement an instance of ``struct block_operations``. That + structure defines a call table with the following methods: + +- ``int register_blockdriver(const char *path, const struct block_operations *bops, mode_t mode, void *priv);``. + Each block driver registers itself by calling + ``register_blockdriver()``, passing it the ``path`` where it + will appear in the `pseudo-file-system <#NxFileSystem>`__ and + it's initialized instance of ``struct block_operations``. + +- **User Access**. Users do not normally access block drivers + directly, rather, they access block drivers indirectly through + the ``mount()`` API. The ``mount()`` API binds a block driver + instance with a file system and with a mountpoint. Then the + user may use the block driver to access the file system on the + underlying media. *Example*: See the ``cmd_mount()`` + implementation in ``apps/nshlib/nsh_fscmds.c``. + +- **Accessing a Character Driver as a Block Device**. See the + loop device at ``drivers/loop.c``. *Example*: See the + ``cmd_losetup()`` implementation in + ``apps/nshlib/nsh_fscmds.c``. + +- **Accessing a Block Driver as Character Device**. See the + Block-to-Character (BCH) conversion logic in ``drivers/bch/``. + *Example*: See the ``cmd_dd()`` implementation in + ``apps/nshlib/nsh_ddcmd.c``. + +- **Examples**. ``drivers/loop.c``, + ``drivers/mmcsd/mmcsd_spi.c``, ``drivers/ramdisk.c``, etc. + +Specialized Device Drivers +************************** + +All device drivers that are accessible to application logic are +either: (1) Character device drivers that can be accessed via the +standard driver operations (``open()``, ``close()``, ``read()``, +``write()``, etc.), or (2) block drivers that can be accessing +only as part of mounting a file system or other special use cases +as described in the preceding paragraph. + +In addition to this, there are also specialized "drivers" that can +be used only within the OS logic itself and are not accessible to +application logic. These specialized drivers are discussed in the +following paragraphs. + +Ethernet Device Drivers +======================= + +- ``include/nuttx/net/netdev.h``. All structures and APIs + needed to work with Ethernet drivers are provided in this + header file. The structure ``struct net_driver_s`` defines the + interface and is passed to the network via + ``netdev_register()``. + +- ``int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype);``. + Each Ethernet driver registers itself by calling + ``netdev_register()``. + +- **Examples**: ``drivers/net/dm90x0.c``, + ``arch/drivers/arm/src/c5471/c5471_ethernet.c``, + ``arch/z80/src/ez80/ez80_emac.c``, etc. + +SPI Device Drivers +================== + +- ``include/nuttx/spi/spi.h``. All structures and APIs needed + to work with SPI drivers are provided in this header file. + +- ``struct spi_ops_s``. Each SPI device driver must implement + an instance of ``struct spi_ops_s``. That structure defines a + call table with the following methods: + +- **Binding SPI Drivers**. SPI drivers are not normally directly + accessed by user code, but are usually bound to another, higher + level device driver. See for example, + ``int mmcsd_spislotinitialize(int minor, int slotno, FAR struct spi_dev_s *spi)`` + in ``drivers/mmcsd/mmcsd_spi.c``. In general, the binding + sequence is: + + #. Get an instance of ``struct spi_dev_s`` from the + hardware-specific SPI device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``drivers/loop.c``, + ``drivers/mmcsd/mmcsd_spi.c``, ``drivers/ramdisk.c``, etc. + +I2C Device Drivers +================== + +- ``include/nuttx/i2c/i2c.h``. All structures and APIs needed + to work with I2C drivers are provided in this header file. + +- ``struct i2c_ops_s``. Each I2C device driver must implement + an instance of ``struct i2c_ops_s``. That structure defines a + call table with the following methods: + +- **Binding I2C Drivers**. I2C drivers are not normally directly + accessed by user code, but are usually bound to another, higher + level device driver. In general, the binding sequence is: + + #. Get an instance of ``struct i2c_master_s`` from the + hardware-specific I2C device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``arch/z80/src/ez80/ez80_i2c.c``, + ``arch/z80/src/z8/z8_i2c.c``, etc. + +Frame Buffer Drivers +==================== + +- ``include/nuttx/video/fb.h``. All structures and APIs + needed to work with frame buffer drivers are provided in this + header file. + +- ``struct fb_vtable_s``. Each frame buffer device driver + must implement an instance of ``struct fb_vtable_s``. That + structure defines a call table with the following methods: + + Get information about the video controller configuration and + the configuration of each color plane. + + The following are provided only if the video hardware supports + RGB color mapping: + + The following are provided only if the video hardware supports + a hardware cursor: + +- **Binding Frame Buffer Drivers**. Frame buffer drivers are not + normally directly accessed by user code, but are usually bound + to another, higher level device driver. In general, the binding + sequence is: + + #. Get an instance of ``struct fb_vtable_s`` from the + hardware-specific frame buffer device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``arch/sim/src/up_framebuffer.c``. See also the + usage of the frame buffer driver in the ``graphics/`` + directory. + +LCD Drivers +=========== + +- ``include/nuttx/lcd/lcd.h``. Structures and APIs needed to + work with LCD drivers are provided in this header file. This + header file also depends on some of the same definitions used + for the frame buffer driver as provided in + ``include/nuttx/video/fb.h``. + +- ``struct lcd_dev_s``. Each LCD device driver must implement + an instance of ``struct lcd_dev_s``. That structure defines a + call table with the following methods: + + Get information about the LCD video controller configuration + and the configuration of each LCD color plane. + + The following are provided only if the video hardware supports + RGB color mapping: + + The following are provided only if the video hardware supports + a hardware cursor: + + Get the LCD panel power status (0: full off - + ``CONFIG_LCD_MAXPOWER``: full on). On backlit LCDs, this + setting may correspond to the backlight setting. + + Enable/disable LCD panel power (0: full off - + ``CONFIG_LCD_MAXPOWER``: full on). On backlit LCDs, this + setting may correspond to the backlight setting. + + Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST) \*/ + + Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST) + +- **Binding LCD Drivers**. LCD drivers are not normally directly + accessed by user code, but are usually bound to another, higher + level device driver. In general, the binding sequence is: + + #. Get an instance of ``struct lcd_dev_s`` from the + hardware-specific LCD device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``drivers/lcd/p14201.c``, + ``boards/arm/sam34/sam3u-ek/src/up_lcd.c.`` See also the usage + of the LCD driver in the ``graphics/`` directory. + +Memory Technology Device Drivers +================================ + +- ``include/nuttx/mtd/mtd.h``. All structures and APIs needed + to work with MTD drivers are provided in this header file. + +- ``struct mtd_dev_s``. Each MTD device driver must implement + an instance of ``struct mtd_dev_s``. That structure defines a + call table with the following methods: + + Erase the specified erase blocks (units are erase blocks): + + Read/write from the specified read/write blocks: + + Some devices may support byte oriented reads (optional). Most + MTD devices are inherently block oriented so byte-oriented + accesses are not supported. It is recommended that low-level + drivers not support read() if it requires buffering. + + Some devices may also support byte oriented writes (optional). + Most MTD devices are inherently block oriented so byte-oriented + accesses are not supported. It is recommended that low-level + drivers not support read() if it requires buffering. This + interface is only available if ``CONFIG_MTD_BYTE_WRITE`` is + defined. + + Support other, less frequently used commands: + + - ``MTDIOC_GEOMETRY``: Get MTD geometry + - ``MTDIOC_XIPBASE:``: Convert block to physical address for + eXecute-In-Place + - ``MTDIOC_BULKERASE``: Erase the entire device + + is provided via a single ``ioctl`` method (see + ``include/nuttx/fs/ioctl.h``): + +- **Binding MTD Drivers**. MTD drivers are not normally directly + accessed by user code, but are usually bound to another, higher + level device driver. In general, the binding sequence is: + + #. Get an instance of ``struct mtd_dev_s`` from the + hardware-specific MTD device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``drivers/mtd/m25px.c`` and ``drivers/mtd/ftl.c`` + +SDIO Device Drivers +=================== + +- ``include/nuttx/sdio.h``. All structures and APIs needed to + work with SDIO drivers are provided in this header file. + +- ``struct sdio_dev_s``. Each SDIO device driver must + implement an instance of ``struct sdio_dev_s``. That structure + defines a call table with the following methods: + + Mutual exclusion: + + Initialization/setup: + + Command/Status/Data Transfer: + + Event/Callback support: + + DMA support: + +- **Binding SDIO Drivers**. SDIO drivers are not normally + directly accessed by user code, but are usually bound to + another, higher level device driver. In general, the binding + sequence is: + + #. Get an instance of ``struct sdio_dev_s`` from the + hardware-specific SDIO device driver, and + #. Provide that instance to the initialization method of the + higher level device driver. + +- **Examples**: ``arch/arm/src/stm32/stm32_sdio.c`` and + ``drivers/mmcsd/mmcsd_sdio.c`` + +USB Host-Side Drivers +===================== + +- ``include/nuttx/usb/usbhost.h``. All structures and APIs + needed to work with USB host-side drivers are provided in this + header file. + +- ``struct usbhost_driver_s`` and + ``struct usbhost_connection_s``. Each USB host controller + driver must implement an instance of + ``struct usbhost_driver_s`` and + ``struct usbhost_connection_s``: ``struct usbhost_driver_s`` + provides the interface between the USB host driver and the USB + class driver; ``struct usbhost_connection_s`` provides the + interface between the USB host driver and platform-specific + connection management and device enumeration logic. These + structures are defined in ``include/nuttx/usb/usbhost.h``. + + **Examples**: ``arch/arm/src/lpc17xx_40xx/lpc17_40_usbhost.c``, + ``arch/arm/src/stm32/stm32_otgfshost.c``, + ``arch/arm/src/sama5/sam_ohci.c``, and + ``arch/arm/src/sama5/sam_ehci.c``. + +- ``struct usbhost_class_s``. Each USB host class driver must + implement an instance of ``struct usbhost_class_s``. This + structure is also defined in ``include/nuttx/usb/usbhost.h``. + + **Examples**: ``drivers/usbhost/usbhost_storage.c`` + +- **USB Host Class Driver Registry**. The NuttX USB host + infrastructure includes a *registry*. During its + initialization, each USB host class driver must call the + interface, ``usbhost_registerclass()`` in order add its + interface to the registry. Later, when a USB device is + connected, the USB host controller will look up the USB host + class driver that is needed to support the connected device in + this registry. + + **Examples**: ``drivers/usbhost/usbhost_registry.c``, + ``drivers/usbhost/usbhost_registerclass.c``, and + ``drivers/usbhost/usbhost_findclass.c``, + +- **Detection and Enumeration of Connected Devices**. Each USB + host device controller supports two methods that are used to + detect and enumeration newly connected devices (and also detect + disconnected devices): + + - ``int (*wait)(FAR struct usbhost_connection_s *drvr, FAR const bool *connected);`` + + Wait for a device to be connected or disconnected. + + - ``int (*enumerate)(FAR struct usbhost_connection_s *drvr, int rhpndx);`` + + Enumerate the device connected to a root hub port. As part + of this enumeration process, the driver will (1) get the + device's configuration descriptor, (2) extract the class ID + info from the configuration descriptor, (3) call + ``usbhost_findclass(``) to find the class that supports this + device, (4) call the ``create()`` method on the + ``struct usbhost_registry_s interface`` to get a class + instance, and finally (5) call the ``connect()`` method of + the ``struct usbhost_class_s`` interface. After that, the + class is in charge of the sequence of operations. + +- **Binding USB Host-Side Drivers**. USB host-side controller + drivers are not normally directly accessed by user code, but + are usually bound to another, higher level USB host class + driver. The class driver exports the standard NuttX device + interface so that the connected USB device can be accessed just + as with other, similar, on-board devices. For example, the USB + host mass storage class driver + (``drivers/usbhost/usbhost_storage.c``) will register a + standard, NuttX block driver interface (like ``/dev/sda``) that + can be used to mount a file system just as with any other other + block driver instance. In general, the binding sequence is: + + #. Each USB host class driver includes an initialization entry + point that is called from the application at initialization + time. This driver calls ``usbhost_registerclass()`` during + this initialization in order to makes itself available in + the event the device that it supports is connected. + + **Examples**: The function ``usbhost_msc_initialize()`` in + the file ``drivers/usbhost/usbhost_storage.c`` + + #. Each application must include a *waiter* thread thread that + (1) calls the USB host controller driver's ``wait()`` to + detect the connection of a device, and then (2) call the USB + host controller driver's ``enumerate`` method to bind the + registered USB host class driver to the USB host controller + driver. + + **Examples**: The function ``nsh_waiter()`` in the file + ``boards/arm/lpc17xx_40xx/olimex-lpc1766stk/src/lpc17_40_appinit.c``. + + #. As part of its operation during the binding operation, the + USB host class driver will register an instances of a + standard NuttX driver under the ``/dev`` directory. To + repeat the above example, the USB host mass storage class + driver (``drivers/usbhost/usbhost_storage.c``) will register + a standard, NuttX block driver interface (like ``/dev/sda``) + that can be used to mount a file system just as with any + other other block driver instance. + + **Examples**: See the call to ``register_blockdriver()`` in + the function ``usbhost_initvolume()`` in the file + ``drivers/usbhost/usbhost_storage.c``. + +USB Device-Side Drivers +======================= + +- ``include/nuttx/usb/usbdev.h``. All structures and APIs + needed to work with USB device-side drivers are provided in + this header file. + +- ``include/nuttx/usb/usbdev_trace.h``. Declarations needed + to work with the NuttX USB device driver trace capability. That + USB trace capability is detailed in `separate + document `__. + +- ``struct usbdev_s``. Each USB device controller driver must + implement an instance of ``struct usbdev_s``. This structure is + defined in ``include/nuttx/usb/usbdev.h``. + + **Examples**: ``arch/arm/src/dm320/dm320_usbdev.c``, + ``arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c``, + ``arch/arm/src/lpc214x/lpc214x_usbdev.c``, + ``arch/arm/src/lpc313x/lpc313x_usbdev.c``, and + ``arch/arm/src/stm32/stm32_usbdev.c``. + +- ``struct usbdevclass_driver_s``. Each USB device class + driver must implement an instance of + ``struct usbdevclass_driver_s``. This structure is also defined + in ``include/nuttx/usb/usbdev.h``. + + **Examples**: ``drivers/usbdev/pl2303.c`` and + ``drivers/usbdev/usbmsc.c`` + +- **Binding USB Device-Side Drivers**. USB device-side controller + drivers are not normally directly accessed by user code, but + are usually bound to another, higher level USB device class + driver. The class driver is then configured to export the USB + device functionality. In general, the binding sequence is: + + #. Each USB device class driver includes an initialization + entry point that is called from the application at + initialization time. + + **Examples**: The function ``usbdev_serialinitialize()`` in + the file ``drivers/usbdev/pl2303.c`` and the function + in the file ``drivers/usbdev/usbmsc.c`` + + #. These initialization functions called the driver API, + ``usbdev_register()``. This driver function will *bind* the + USB class driver to the USB device controller driver, + completing the initialization. + diff --git a/doc/components/filesystem.rst b/doc/components/filesystem.rst new file mode 100644 index 00000000000..5794dc31697 --- /dev/null +++ b/doc/components/filesystem.rst @@ -0,0 +1,43 @@ +================= +NuttX File System +================= + +**Overview**. NuttX includes an optional, scalable file system. +This file-system may be omitted altogether; NuttX does not depend +on the presence of any file system. + +**Pseudo Root File System**. A simple *in-memory*, *pseudo* file +system can be enabled by default. This is an *in-memory* file +system because it does not require any storage medium or block +driver support. Rather, file system contents are generated +on-the-fly as referenced via standard file system operations +(open, close, read, write, etc.). In this sense, the file system +is *pseudo* file system (in the same sense that the Linux +``/proc`` file system is also referred to as a pseudo file +system). + +Any user supplied data or logic can be accessed via the +pseudo-file system. Built in support is provided for character and +block `drivers <#DeviceDrivers>`__ in the ``/dev`` pseudo file +system directory. + +**Mounted File Systems** The simple in-memory file system can be +extended my mounting block devices that provide access to true +file systems backed up via some mass storage device. NuttX +supports the standard ``mount()`` command that allows a block +driver to be bound to a mountpoint within the pseudo file system +and to a file system. At present, NuttX supports the standard VFAT +and ROMFS file systems, a special, wear-leveling NuttX FLASH File +System (NXFFS), as well as a Network File System client (NFS +version 3, UDP). + +**Comparison to Linux** From a programming perspective, the NuttX +file system appears very similar to a Linux file system. However, +there is a fundamental difference: The NuttX root file system is a +pseudo file system and true file systems may be mounted in the +pseudo file system. In the typical Linux installation by +comparison, the Linux root file system is a true file system and +pseudo file systems may be mounted in the true, root file system. +The approach selected by NuttX is intended to support greater +scalability from the very tiny platform to the moderate platform. + diff --git a/doc/components/index.rst b/doc/components/index.rst new file mode 100644 index 00000000000..aa3463480ee --- /dev/null +++ b/doc/components/index.rst @@ -0,0 +1,20 @@ +OS Components +============= + +.. note:: + TODO: add brief intro + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + nsh/index.rst + power.rst + syslog.rst + binfmt.rst + drivers/index.rst + filesystem.rst + nxflat.rst + nxgraphics/index.rst + nxwidgets.rst + paging.rst diff --git a/doc/components/nsh/builtin.rst b/doc/components/nsh/builtin.rst new file mode 100644 index 00000000000..338a539548b --- /dev/null +++ b/doc/components/nsh/builtin.rst @@ -0,0 +1,204 @@ +*************************** +NSH "Built-In" Applications +*************************** + +**Overview.** In addition to these commands that are a part of NSH, +external programs can also be executed as NSH commands. These external +programs are called "Built-In" Applications for historic reasons. That +terminology is somewhat confusing because the actual NSH commands as +described above are truly "built-into" NSH whereas these applications +are really external to NuttX. + +These applications are built-into NSH in the sense that they can be +executed by simply typing the name of the application at the NSH prompt. +Built-in application support is enabled with these configuration option: + + - ``CONFIG_BUILTIN``: Enable NuttX support for builtin applications. + - ``CONFIG_NSH_BUILTIN_APPS``: Enable NSH support for builtin + applications. + +When these configuration options are set, you will also be able to see +the built-in applications if you enter "nsh> help". They will appear at +the bottom of the list of NSH commands under:: + + Builtin Apps: + +Note that no detailed help information beyond the name of the built-in +application is provided. + +Built-In Applications +~~~~~~~~~~~~~~~~~~~~~ + +**Overview.** The underlying logic that supports the NSH built-in +applications is called "Built-In Applications". The builtin application +logic can be found at ``apps/builtin``. This logic simply does the +following: + + #. It supports registration mechanism so that builtin applications can + dynamically register themselves at build time, and + + #. Utility functions to look up, list, and execute the builtin + applications. + +**Built-In Application Utility Functions**. The utility functions +exported by the builtin application logic are prototyped in +``nuttx/include/nuttx/lib/builtin.h`` and ``apps/include/builtin.h``. +These utility functions include: + + - ``int builtin_isavail(FAR const char *appname);`` Checks for + availability of application registered as ``appname`` during build + time. + + - ``const char *builtin_getname(int index);`` Returns a pointer to a + name of built-in application pointed by the ``index``. This is the + utility function that is used by NSH in order to list the available + built-in applications when "``nsh> help``" is entered. + + - ``int exec_builtin(FAR const char *appname, FAR const char **argv);`` + Executes built-in builtin application registered during compile time. + This is the utility function used by NSH to execute the built-in + application. + +**Autogenerated Header Files**. Application entry points with their +requirements are gathered together in two files when NuttX is first +built: + + #. ``apps/builtin/builtin_proto.h``: Prototypes of application task + entry points. + + #. ``apps/builtin/builtin_list.h``: Application specific information and + start-up requirements + +**Registration of Built-In Applications**. The NuttX build occurs in +several phases as different build targets are executed: (1) *context* +when the configuration is established, (2) *depend* when target +dependencies are generated, and (3) *default* (``all``) when the normal +compilation and link operations are performed. Built-in application +information is collected during the make *context* build phase. + +An example application that can be "built-in" is be found in the +``apps/examples/hello directory``. Let's walk through this specific +cause to illustrate the general way that built-in applications are +created and how they register themselves so that they can be used from +NSH. + +``apps/examples/hello``. The main routine for apps/examples/hello can be +found in ``apps/examples/hello/main.c``. The main routine is: + +.. code-block:: c + + int hello_main(int argc, char *argv[]) + { + printf("Hello, World!!\n"); + return 0; + } + +This is the built in function that will be registered during the +*context* build phase of the NuttX build. That registration is performed +by logic in ``apps/examples/hello/Makefile``. But the build system gets +to that logic through a rather tortuous path: + + #. The top-level context make target is in ``nuttx/Makefile``. All build + targets depend upon the *context* build target. For the ``apps/`` + directory, this build target will execute the *context* target in the + ``apps/Makefile``. + + #. The ``apps/Makefile`` will, in turn, execute the *context* targets in + all of the configured sub-directories. In our case will include the + ``Makefile`` in ``apps/examples``. + + #. And finally, the ``apps/examples/Makefile`` will execute the + *context* target in all configured ``example``\ sub-directories, + getting us finally to ``apps/examples/Makefile`` which is covered + below. + +**NOTE**: Since this context build phase can only be executed one time, +any subsequent configuration changes that you make will, then, not be +reflected in the build sequence. That is a common area of confusion. +Before you can instantiate the new configuration, you have to first get +rid of the old configuration. The most drastic way to this is:: + + make distclean + +But then you will have to re-configuration NuttX from scratch. But if +you only want to re-build the configuration in the ``apps/`` +sub-directory, then there is a less labor-intensive way to do that. The +following NuttX make command will remove the configuration only from the +``apps/`` directory and will let you continue without re-configuring +everything:: + + make apps_distclean + +Logic for the ``context`` target in ``apps/examples/hello/Makefile`` +registers the ``hello_main()`` application in the ``builtin``'s +``builtin_proto.h``\ and ``builtin_list.h`` files. That logic that does +that in ``apps/examples/hello/Makefile`` is abstracted below: + + #. First, the ``Makefile`` includes ``apps/Make.defs``:: + + include $(APPDIR)/Make.defs + + This defines a macro called ``REGISTER`` that adds data to the + *builtin* header files:: + + define REGISTER + @echo "Register: $1" + @echo "{ \"$1\", $2, $3, $4 }," >> "$(APPDIR)/builtin/builtin_list.h" + @echo "EXTERN int $4(int argc, char *argv[]);" >> "$(APPDIR)/builtin/builtin_proto.h" + endef + + When this macro runs, you will see the output in the build + "``Register: hello``", that is a sure sign that the registration was + successful. + + #. The make file then defines the application name (``hello``), the task + priority (default), and the stack size that will be allocated in the + task runs (2K):: + + APPNAME = hello + PRIORITY = SCHED_PRIORITY_DEFAULT + STACKSIZE = 2048 + + #. And finally, the ``Makefile`` invokes the ``REGISTER`` macro to added + the ``hello_main()`` builtin application. Then, when the system build + completes, the ``hello`` command can be executed from the NSH command + line. When the ``hello`` command is executed, it will start the task + with entry point ``hello_main()`` with the default priority and with + a stack size of 2K:: + + context: + $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + + +**Other Uses of Built-In Application.** The primary purpose of builtin +applications is to support command line execution of applications from +NSH. However, there is one other use of builtin applications that should +be mentioned. + + #. **binfs**. *binfs* is a tiny file system located at + ``apps/builtin/binfs.c``. This provides an alternative what of + visualizing installed builtin applications. Without *binfs*, you can + see the installed builtin applications using the NSH help command. + *binfs* will create a tiny pseudo-file system mounted at ``/bin``. + Using *binfs*, you can see the available builtin applications by + listing the contents of ``/bin`` directory. This gives some + superficial Unix-like compatibility, but does not really add any new + functionality. + +Synchronous Built-In Applications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, built-in commands started from the NSH command line will run +asynchronously with NSH. If you want to force NSH to execute commands +then wait for the command to execute, you can enable that feature by +adding the following to the NuttX configuration file:: + + CONFIG_SCHED_WAITPID=y + +This configuration option enables support for the standard ``waitpid()`` +RTOS interface. When that interface is enabled, NSH will use it to wait, +sleeping until the built-in application executes to completion. + +Of course, even with ``CONFIG_SCHED_WAITPID=y`` defined, specific +applications can still be forced to run asynchronously by adding the +ampersand (&) after the NSH command. diff --git a/doc/components/nsh/commands.rst b/doc/components/nsh/commands.rst new file mode 100644 index 00000000000..3e125eee8d4 --- /dev/null +++ b/doc/components/nsh/commands.rst @@ -0,0 +1,1692 @@ +******** +Commands +******** + +Evaluate Expression (test) +-------------------------- + +**Command Syntax:** + +.. code-block:: fish + + [ ] + test + +**Synopsis**. These are two alternative forms of the same command. +They support evaluation of a boolean expression which sets +``$?``. This command is used most frequently as +the conditional command following the ``if`` in the +``if-then[-else]-fi``. + +**Expression Syntax:** + +:: + + expression = simple-expression | !expression | expression -o expression | expression -a expression + + simple-expression = unary-expression | binary-expression + + unary-expression = string-unary | file-unary + + string-unary = -n string | -z string + + file-unary = -b file | -c file | -d file | -e file | -f file | -r file | -s file | -w file + + binary-expression = string-binary | numeric-binary + + string-binary = string = string | string == string | string != string + + numeric-binary = integer -eq integer | integer -ge integer | integer -gt integer | integer -le integer | integer -lt integer | integer -ne integer + +Add a Routing Table Entry (addroute) +------------------------------------ + +**Command Syntax:** + +:: + + addroute [] + addroute default + +**Synopsis**. This command adds an entry in the routing table. The +new entry will map the IP address of a router on a local network +() to an external network characterized by the IP +address and a network mask + +The netmask may also be expressed using IPv4 CIDR or IPv6 slash +notation. In that case, the netmask need not be provided. + +**Example:** + +:: + + nsh> addroute addroute 11.0.0.0 255.255.255.0 10.0.0.2 + +which is equivalent to + +:: + + nsh> addroute 11.0.0.0/24 10.0.0.2 + +The second form of the addroute command can be used to set the +default gateway. + +Access the ARP table (arp) +************************** + +**Command syntax**:: + + arp [-t|-a |-d |-s ] + +**Synopsis**: Access the OS ARP table. + + -a Will show the hardware address that the IP address is + mapped to. + -d Will delete the mapping for the IP address from the + ARP table. + -s Will set (or replace) the mapping of the IP address to + the hardware address . + -t Will dump the entire content of the ARP table. This option is + only available if ``CONFIG_NETLINK_ROUTE`` is enabled. + +**Example**:: + + nsh> arp -a 10.0.0.1 + nsh: arp: no such ARP entry: 10.0.0.1 + + nsh> arp -s 10.0.0.1 00:13:3b:12:73:e6 + nsh> arp -a 10.0.0.1 + HWAddr: 00:13:3b:12:73:e6 + + nsh> arp -d 10.0.0.1 + nsh> arp -a 10.0.0.1 + nsh: arp: no such ARP entry: 10.0.0.1 + +Base64 Decode (base64dec) +************************* + +**Command Syntax**:: + + base64dec [-w] [-f] + +**Synopsis**. *To be provided.* + +Base64 Encode (base64enc) +************************* + +**Command Syntax**:: + + base64enc [-w] [-f] + +**Synopsis**. *To be provided.* + +Extract Base File/Directory Name (basename) +******************************************* + +**Command Syntax**:: + + basename [] + +**Synopsis**. Extract the final string from a ```` by +removing the preceding path segments and (optionally) removing any +trailing ````. + +Terminate a Loop (break) +************************ + +**Command Syntax**:: + + break + +**Synopsis**. The ``break`` command is only meaningful within the +body of the a `while <#looping>`__ or `until <#looping>`__ loop, +between the ``do`` and ``done`` tokens. Outside of a loop, +``break`` command does nothing. If the ``break`` command is +executed within the body of a loop, the loop will immediately +terminate and execution will continue with the next command +immediately following the ``done`` token. + +Concatenate Files (cat) +*********************** + +**Command Syntax**:: + + cat [ [ ...]] + +**Synopsis**. This command copies and concatenates all of the +files at ```` to the console (or to another file if the +output is redirected). + +Change Current Working Directory (cd) +************************************* + +**Command Syntax**:: + + cd [|-|~|..] + +**Synopsis**. Changes the current working directory (``PWD``). +Also sets the previous working directory environment variable +(``OLDPWD``). + +**Forms:** + +================== ===================================== +``cd `` sets the current working directory to . +``cd -`` sets the current working directory to the previous + working directory ($OLDPWD). Equivalent to cd $OLDPWD. +``cd`` or ``cd ~`` set the current working directory to the 'home' directory. + The home directory can be configured by setting CONFIG_LIB_HOMEDIR + in the configuration file. The default home directory is /. +``cd ..`` sets the current working directory to the parent directory. +================== ===================================== + +Compare Files (cmp) +******************* + +**Command Syntax**:: + + cmp + +**Synopsis**. Compare of the contents of the file at ```` +with the contents of the file at ````. Returns an +indication only if the files differ. + +Copy Files (cp) +*************** + +**Command Syntax**:: + + cp + +**Synopsis**. Copy of the contents of the file at +```` to the location in the file system indicated by +````. + +Show or set the date and time (date) +************************************ + +**Command Syntax**:: + + date [-s "MMM DD HH:MM:SS YYYY"] + +**Synopsis**. Show or set the current date and time. + +Only one format is used both on display and when setting the +date/time: ``MMM DD HH:MM:SS YYYY``. For example, + +24-hour time is used. + +Copy and Convert Files (dd) +*************************** + +**Command Syntax**:: + + dd if= of= [bs=] [count=] [skip=] + +**Synopsis**. Copy blocks from to . or + may be the path to a standard file, a character device, +or a block device. Examples follow: + +Read from character device, write to regular file. This will +create a new file of the specified size filled with zero:: + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 zero + nsh> dd if=/dev/zero of=/tmp/zeros bs=64 count=16 + nsh> ls -l /tmp + /tmp: + -rw-rw-rw- 1024 ZEROS + +Read from character device, write to block device. This will fill +the entire block device with zeros:: + + nsh> ls -l /dev + /dev: + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 zero + nsh> dd if=/dev/zero of=/dev/ram0 + +Read from a block device, write to a character device. This will +read the entire block device and dump the contents in the bit +bucket:: + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> dd if=/dev/ram0 of=/dev/null + +Delete a Routing Table Entry (delroute) +*************************************** + +**Command Syntax**:: + + delroute [] + +**Synopsis**. The entry removed will be the first entry in the +routing table that matches the external network characterized by +the IP address and the network mask + +The netmask may also be expressed using IPv4 CIDR or IPv6 slash +notation. In that case, the netmask need not be provided. + +**Example**:: + + nsh> delroute 11.0.0.0 255.255.255.0 + +which is equivalent to:: + + nsh> delroute 11.0.0.0/24 + +Show Volume Status (df) +*********************** + +**Command Syntax**:: + + df [-h] + +**Synopsis**. Show the state of each mounted volume. As an +example:: + + nsh> mount + /etc type romfs + /tmp type vfat + nsh> df + Block Number + Size Blocks Used Available Mounted on + 64 6 6 0 /etc + 512 985 2 983 /tmp + nsh> + +If ``CONFIG_NSH_CMDOPT_DF_H`` is defined in the NuttX +configuration, then the ``df`` will also support an option ``-h`` +which may be used to show the volume information in *human +readable* format. + +Extract Path to a File/Directory (dirname) +****************************************** + +**Command Syntax**:: + + dirname + +**Synopsis**. Extract the path string leading up to the full +```` by removing the final directory or file name. + +Dump Buffered SYSLOG Output (dmesg) +*********************************** + +**Command Syntax**:: + + dmesg + +**Synopsis**. This command can be used to dump (and clear) the +content of any buffered syslog output messages. This command is +only available if ``CONFIG_RAMLOG_SYSLOG`` is enabled. In that +case, syslog output will be collected in an in-memory, circular +buffer. Entering the ``dmesg`` command will dump the content of +that in-memory, circular buffer to the NSH console output. +``dmesg`` has the side effect of clearing the buffered data so +that entering ``dmesg`` again will show only newly buffered data. + +Echo Strings and Variables (echo) +********************************* + +**Command Syntax**:: + + echo [-n] [ [...]] + +**Synopsis**. Copy the sequence of strings and expanded +environment variables to console output (or to a file if the +output is re-directed). + +The ``-n`` option suppresses the trailing newline character. + +Show Environment Variables (env) +******************************** + +**Command Syntax**:: + + env + +**Synopsis**. Show the current name-value pairs in the +environment. Example:: + + nsh> env + PATH=/bin + + nsh> set foo bar + nsh> env + PATH=/bin + foo=bar + + nsh> unset PATH + nsh> env + foo=bar + + nsh> + +.. note::NSH local variables are *not* shown by the ``env`` + command. + +Execute User Code (exec) +************************ + +**Command Syntax**:: + + exec + +**Synopsis**. Execute the user logic at address ````. +NSH will pause until the execution unless the user logic is +executed in background via ``exec &``. + +Exit NSH (exit) +*************** + +**Command Syntax**:: + + exit + +**Synopsis**. Exit NSH. Only useful for the serial front end if +you have started some other tasks (perhaps using the ``exec`` +command) and you would like to have NSH out of the way. For the +telnet front-end, ``exit`` terminates the telnet session. + +Set an Environment Variable (export) +************************************ + +**Command Syntax**:: + + export [] + +**Synopsis**. The ``export`` command sets an environment variable, +or promotes an NSH variable to an environment variable. As +examples: + + #. Using ``export`` to promote an NSH variable to an environment + variable:: + + nsh> env + PATH=/bin + + nsh> set foo bar + nsh> env + PATH=/bin + + nsh> export foo + nsh> env + PATH=/bin + foo=bar + + A group-wide environment variable is created with the same + value as the local NSH variable; the local NSH variable is + removed. + + .. note::This behavior differs from the Bash shell. Bash would + retain the local Bash variable which will shadow the + environment variable of the same name and same value. + + #. Using ``export`` to set an environment variable:: + + nsh> export dog poop + nsh> env + PATH=/bin + foo=bar + dog=poop + +The ``export`` command is not supported by NSH unless both +``CONFIG_NSH_VARS=y`` and ``CONFIG_DISABLE_ENVIRON``\ is not set. + +Show Memory Manager Status (free) +********************************* + +**Command Syntax**:: + + free + +**Synopsis**. Show the current state of the memory allocator. For +example:: + + nsh> free + total used free largest + Mem: 4194288 1591552 2602736 2601584 + nsh> + +**Where:** + +======= ====================================== +total This is the total size of memory allocated for use by malloc in bytes. +used This is the total size of memory occupied by chunks handed out by malloc. +free This is the total size of memory occupied by free (not in use) chunks. +largest Size of the largest free (not in use) chunk. +======= ====================================== + +Get File Via TFTP (get) +*********************** + +**Command Syntax**:: + + get [-b|-n] [-f ] -h + +**Synopsis**. Copy the file at ```` from the host +whose IP address is identified by ````. + +**Other options** + +=================== ============================================ +``-f `` The file will be saved relative to the current working directory unless is provided. +``-n`` Selects text ("netascii") transfer mode (default). +``-b`` Selects binary ("octet") transfer mode +=================== ============================================ + +Show Usage Command Usage (help) +******************************* + +**Command Syntax**:: + + help [-v] [] + +**Synopsis**. Presents summary information about NSH commands to +console. + +**Options** + +========= ==================== +``-v`` how verbose output will full command usage. +```` Show full command usage only for this command. +========= ==================== + +Hexadecimal Dump of File or Device (hexdump) +******************************************** + +**Command Syntax**:: + + hexdump [skip=] [count=] + +**Synopsis**. Dump data in hexadecimal format from a file or +character device + +================= ================================== +``skip=`` Will skip number of bytes from the beginning. +``count=`` Will stop after dumping number of bytes. +================= ================================== + +The ``skip`` and ``count`` options are only available if +``CONFIG_NSH_CMDOPT_HEXDUMP`` is defined in the NuttX +configuration. + +Manage Network Configuration (ifconfig) +*************************************** + +**Command Syntax**:: + + ifconfig [nic_name [|dhcp]] [dr|gw|gateway ] [netmask ] [dns ] [hw ]] + +**Synopsis**. Multiple forms of the ``ifconfig`` command are +supported: + + #. With one or no arguments, ``ifconfig`` will shows the current + configuration of the network and, perhaps, the status of + Ethernet device:: + + ifconfig + ifconfig [nic_name] + + As an example:: + + nsh> ifconfig + eth0 HWaddr 00:18:11:80:10:06 + IPaddr:10.0.0.2 DRaddr:10.0.0.1 Mask:255.255.255.0 + + If network statistics are enabled (``CONFIG_NET_STATISTICS``), + then this command will also show the detailed state of network. + + #. If both the network interface name and an IP address are + supplied as arguments, then ``ifconfig`` will set the address + of the Ethernet device:: + + ifconfig nic_name ip_address + + #. Other forms *to be provided* + +.. note:: This commands depends upon having the *procfs* file system + configured into the system. The *procfs* file system must also + have been mounted with a command like:: + + nsh> mount -t procfs /proc + +Take a network down (ifdown) +**************************** + +**Command Syntax**:: + + ifdown + +**Synopsis**. Take down the interface identified by the name +. + +**Example**:: + + ifdown eth0 + +Bring a network up (ifup) +************************* + +**Command Syntax**:: + + ifup + +**Synopsis**. Bring up down the interface identified by the name +. + +**Example**:: + + ifup eth0 + +Install an OS module (insmod) +***************************** + +**Command Syntax**:: + + insmod + +**Synopsis**. Install the loadable OS module at as +module . + +**Example**:: + + nsh> ls -l /mnt/romfs + /mnt/romfs: + dr-xr-xr-x 0 . + -r-xr-xr-x 9153 chardev + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 ttyS0 + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + nsh> insmod /mnt/romfs/chardev mydriver + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 chardev + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 ttyS0 + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + + +Show Interrupt Status (irqinfo) +******************************* + +**Command Syntax**:: + + irqinfo + +**Synopsis**. Show the current count of interrupts taken on all +attached interrupts. + +**Example**:: + + nsh> irqinfo + IRQ HANDLER ARGUMENT COUNT RATE + 3 00001b3d 00000000 156 19.122 + 15 0000800d 00000000 817 100.000 + 30 00000fd5 20000018 20 2.490 + +Send a signal to a task (kill) +****************************** + +**Command Syntax**:: + + kill - + +**Synopsis**. Send the to the task identified by . + +**Example**:: + + nsh> mkfifo /dev/fifo + nsh> cat /dev/fifo & + cat [2:128] + nsh> ps + PID PRI POLICY TYPE NPX STATE EVENT SIGMASK COMMAND + 0 0 FIFO Kthread --- Ready 00000000 Idle Task + 1 128 RR Task --- Running 00000000 init + 2 128 FIFO pthread --- Waiting Semaphore 00000000 (51ea50) + nsh> kill -9 2 + nsh> ps + PID PRI POLICY TYPE NPX STATE EVENT SIGMASK COMMAND + 0 0 FIFO Kthread --- Ready 00000000 Idle Task + 1 128 RR Task --- Running 00000000 init + nsh> + +.. note:: NuttX does not support a FULL POSIX signaling system. A + few standard signal names like ``SIGCHLD``, ``SIGUSR1``, + ``SIGUSR2``, ``SIGALRM``, and ``SIGPOLL`` exist in the system. + However, they do not have the default actions that you might + expect. Rather, NuttX supports only what are referred to as POSIX + real-time signals. These signals may be used to communicate with + running tasks, may be use to waiting waiting tasks, etc. + + If the configuration option ``CONFIG_SIG_DEFAULT`` is enabled, + then default actions for the ``SIGINT`` and ``SIGKILL`` signals + (only) will be supported. In that case, as an example, ``kill -9`` + (SIGKILL) will, indeed, terminate a task. Caution should be + exercised, however, because this is likely to cause memory leaks + and to strand resource since there is insufficient clean-up in + certain build configurations. + +Setup/teardown the Loop Device (losetup) +**************************************** + +**Command Syntax 1**:: + + losetup [-o ] [-r] + +**Synopsis**. Setup the loop device at to access the +file at as a block device. In the following example a +256K file is created (``dd``) and ``losetup`` is used to make the +file accessible as a block device. A FAT file system is created +(``mkfatfs``) and mounted (``mount``). Files can then be managed +on the loop-mounted file:: + + nsh> dd if=/dev/zero of=/tmp/image bs=512 count=512 + nsh> ls -l /tmp + /tmp: + -rw-rw-rw- 262144 IMAGE + nsh> losetup /dev/loop0 /tmp/image + nsh> ls -l /dev + /dev: + brw-rw-rw- 0 loop0 + nsh> mkfatfs /dev/loop0 + nsh> mount -t vfat /dev/loop0 /mnt/example + nsh> ls -l /mnt + ls -l /mnt + /mnt: + drw-rw-rw- 0 example/ + nsh> echo "This is a test" >/mnt/example/atest.txt + nsh> ls -l /mnt/example + /mnt/example: + -rw-rw-rw- 16 ATEST.TXT + nsh> cat /mnt/example/atest.txt + This is a test + nsh> + +**Command Syntax 2**:: + + losetup d + +**Synopsis**. Teardown the setup for the loop device at +. + +Link to a File or Directory (ln) +******************************** + +**Command Syntax**:: + + ln [-s] + +**Synopsis**. The ``ln`` command will create a new symbolic link +at for the existing file or directory, . This +implementation is simplified for use with NuttX in these ways: + + - Links may be created only within the NuttX top-level, `pseudo + file system `__. No + file system currently supported by NuttX provides symbolic + links. + - For the same reason, only soft links are implemented. + - File privileges are ignored. + - ``c_time`` is not updated. + +List Directory Contents (ls) +**************************** + +**Command Syntax**:: + + ls [-lRs] + +**Synopsis**. Show the contents of the directory at +````. NOTE: ```` must refer to a directory and +no other file system object. + +**Options** + +====== ================================ +``-R`` Show the contents of specified directory and all of its sub-directories. +``-s`` Show the size of the files along with the filenames in the listing +``-l`` Show size and mode information along with the filenames in the listing. +====== ================================ + +Show information about installed OS modules (lsmod) +*************************************************** + +**Command Syntax**:: + + lsmod + +**Synopsis**. Show information about the currently installed OS +modules. This information includes: + + - The module name assigned to the module when it was installed + (``NAME``, string). + - The address of the module initialization function (``INIT``, + hexadecimal). + - The address of the module un-initialization function + (``UNINIT``, hexadecimal). + - An argument that will be passed to the module un-initialization + function (``ARG``, hexadecimal). + - The start of the .text memory region (``TEXT``, hexadecimal). + - The size of the .text memory region size (``SIZE``, decimal). + - The start of the .bss/.data memory region (``DATA``, + hexadecimal). + - The size of the .bss/.data memory region size (``SIZE``, + decimal). + +**Example**:: + + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + +Calculate MD5 (md5) +******************* + +**Command Syntax**:: + + md5 [-f] + +**Synopsis**. *To be provided.* + +Access Memory (mb, mh, and mw) +****************************** + +**Command Syntax**:: + + mb [=][ ] + mh [=][ ] + mw [=][ ] + +**Synopsis**. Access memory using byte size access (mb), 16-bit +accesses (mh), or 32-bit access (mw). In each case, + +============================= ============================================== +```` Specifies the address to be accessed. The current + value at that address will always be read and displayed. +``=`` Read the value, then write to the location. +```` Perform the mb, mh, or mw operation on a total of + bytes, increment the + appropriately after each access. +============================= ============================================== + +**Example**:: + + nsh> mh 0 16 + 0 = 0x0c1e + 2 = 0x0100 + 4 = 0x0c1e + 6 = 0x0110 + 8 = 0x0c1e + a = 0x0120 + c = 0x0c1e + e = 0x0130 + 10 = 0x0c1e + 12 = 0x0140 + 14 = 0x0c1e + nsh> + +Show Current Tasks and Threads (ps) +*********************************** + +**Command Syntax**:: + + ps + +**Synopsis**. Show the currently active threads and tasks. For +example:: + + nsh> ps + PID PRI POLICY TYPE NPX STATE EVENT SIGMASK COMMAND + 0 0 FIFO Kthread --- Ready 00000000 Idle Task + 1 128 RR Task --- Running 00000000 init + 2 128 FIFO Task --- Waiting Semaphore 00000000 nsh_telnetmain() + 3 100 RR pthread --- Waiting Semaphore 00000000 (21) + nsh> + +NOTE: This commands depends upon having the *procfs* file system +configured into the system. The *procfs* file system must also +have been mounted with a command like:: + + nsh> mount -t procfs /proc + +Create a Directory (mkdir) +************************** + +**Command Syntax**:: + + mkdir + +**Synopsis**. Create the directory at ````. All components +of ```` except the final directory name must exist on a +mounted file system; the final directory must not. + +**Limited to Mounted File Systems**. Recall that NuttX uses a +`pseudo file system `__ +for its root file system. The ``mkdir`` command can only be used +to create directories in volumes set up with the +```mount`` <#cmdmount>`__ command; it cannot be used to create +directories in the *pseudo* file system. + +**Example**:: + + nsh> mkdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + drw-rw-rw- 0 TMP/ + nsh> + +Create a FAT File System (mkfatfs) +********************************** + +**Command Syntax** + + mkfatfs [-F ] [-r ] + +**Synopsis**. Format a fat file system on the block device +specified by ```` path. The FAT size may be provided +as an option. Without the ```` option, ``mkfatfs`` will +select either the FAT12 or FAT16 format. For historical reasons, +if you want the FAT32 format, it must be explicitly specified on +the command line. + +The ``-r`` option may be specified to select the the number of +entries in the root directory for FAT12 and FAT16 file systems. +Typical values for small volumes would be 112 or 224; 512 should +be used for large volumes, such as hard disks or very large SD +cards. The default is 512 entries in all cases. + +The reported number of root directory entries used with FAT32 is +zero because the FAT32 root directory is a cluster chain. + +NSH provides this command to access the +```mkfatfs()`` `__ NuttX API. This block device must +reside in the NuttX `pseudo file +system `__ and must have +been created by some call to ``register_blockdriver()`` (see +``include/nuttx/fs/fs.h``). + +Create a FIFO (mkfifo) +********************** + +**Command Syntax**:: + + mkfifo + +**Synopsis**. Creates a FIFO character device anywhere in the +pseudo file system, creating whatever pseudo directories that may +be needed to complete the ````. By convention, however, +device drivers are place in the standard ``/dev`` directory. After +it is created, the FIFO device may be used as any other device +driver. NSH provides this command to access the +```mkfifo()`` `__ NuttX API. + +**Example**:: + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> mkfifo /dev/fifo + nsh> ls -l /dev + ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 fifo + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> + +Create a RAMDISK (mkrd) +*********************** + +**Command Syntax**:: + + mkrd [-m ] [-s ] + +**Synopsis**. Create a ramdisk consisting of ````, each +of size ```` (or 512 bytes if ```` is +not specified. The ramdisk will be registered as +``/dev/ram``. If ```` is not specified, ``mkrd`` +will attempt to register the ramdisk as ``/dev/ram0``. + +**Example**:: + + nsh> ls /dev + /dev: + console + null + ttyS0 + ttyS1 + nsh> mkrd 1024 + nsh> ls /dev + /dev: + console + null + ram0 + ttyS0 + ttyS1 + nsh> + +Once the ramdisk has been created, it may be formatted using the +``mkfatfs`` command and mounted using the ``mount`` command. + +**Example**:: + + nsh> mkrd 1024 + nsh> mkfatfs /dev/ram0 + nsh> mount -t vfat /dev/ram0 /tmp + nsh> ls /tmp + /tmp: + nsh> + +Mount a File System (mount) +*************************** + +**Command Syntax**:: + + mount -t [-o ] + +**Synopsis**. The ``mount`` command performs one of two different +operations. If no parameters are provided on the command line +after the ``mount`` command, then the ``mount`` command will +enumerate all of the current mountpoints on the console. + +If the mount parameters are provided on the command after the +``mount`` command, then the ``mount`` command will mount a file +system in the NuttX pseudo-file system. ``mount`` performs a three +way association, binding: + + #. **File System.** The '-t ````' option identifies the + type of file system that has been formatted on the + ````. As of this writing, ``vfat`` is the only + supported value for ```` + #. **Block Device.** The ```` argument is the full + or relative path to a block driver inode in the `pseudo file + system `__. By + convention, this is a name under the ``/dev`` sub-directory. + This ```` must have been previously formatted + with the same file system type as specified by ```` + #. **Mount Point.** The mount point, ````, is the + location in the `pseudo file + system `__ where the + mounted volume will appear. This mount point can only reside in + the NuttX `pseudo file + system `__. By + convention, this mount point is a subdirectory under ``/mnt``. + The mount command will create whatever pseudo directories that + may be needed to complete the full path but the full path must + not already exist. + +After the volume has been mounted in the NuttX `pseudo file +system `__, it may be +access in the same way as other objects in the file system. + +**Examples**: + +Using ``mount`` to mount a file system:: + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 console + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> ls /mnt + nsh: ls: no such directory: /mnt + nsh> mount -t vfat /dev/ram0 /mnt/fs + nsh> ls -l /mnt/fs/testdir + /mnt/fs/testdir: + -rw-rw-rw- 15 TESTFILE.TXT + nsh> echo "This is a test" >/mnt/fs/testdir/example.txt + nsh> ls -l /mnt/fs/testdir + /mnt/fs/testdir: + -rw-rw-rw- 15 TESTFILE.TXT + -rw-rw-rw- 16 EXAMPLE.TXT + nsh> cat /mnt/fs/testdir/example.txt + This is a test + nsh> + +Using ``mount`` to enumerate mounts:: + + nsh> mount + /etc type romfs + /mnt/fs type vfat + /tmp type vfat + +Rename a File (mv) +****************** + +**Command Syntax**:: + + mv + +**Synopsis**. Rename the file object at ```` to +````. Both paths must reside in the same mounted file +system. + +Mount an NFS file system (nfsmount) +*********************************** + +**Command Syntax**:: + + nfsmount + +**Synopsis**. Mount the remote NFS server directory +at on the target machine. is the IP +address of the remote server. + +Lookup a network address (nslookup) +*********************************** + +**Command Syntax**:: + + nslookup + +**Synopsis**. Lookup and print the IP address associated with +````. + +Change a User's Password (passwd) +********************************* + +**Command Syntax**:: + + passwd + +**Synopsis**. Set the password for the existing user to +. + +Manage Power Management Subsystem (pmconfig) +******************************************** + +**Command Syntax**:: + + pmconfig [stay|relax] [normal|idle|standby|sleep] + +**Synopsis**. Control power management subsystem. + +Shut the system down (poweroff) +******************************* + +**Command Syntax**:: + + poweroff [] + +**Synopsis**. Shutdown and power off the system immediately. This +command depends on board-specific hardware support to power down +the system. The optional,decimal numeric argument may be included +to provide power off mode to board-specific power off logic. + +NOTE: Supporting both the ``poweroff`` and ``shutdown`` commands +is redundant. + +Send File Via TFTP (put) +************************ + +**Command Syntax**:: + + put [-b|-n] [-f ] -h + +**Synopsis**. Copy the file at ```` to the host +whose IP address is identified by ````. + +**Other options:** + +==================== ============================================= +``-f `` The file will be saved relative with the same + name on the host unless is provided. +``-b|-n`` Selects either binary ("octet") or text ("netascii") + transfer mode. Default: text. +==================== ============================================= + +Show Current Working Directory (pwd) +************************************ + +**Command Syntax**:: + + pwd + +**Synopsis**. Show the current working directory:: + + nsh> cd /dev + nsh> pwd + /dev + nsh> + +Same as ``echo $PWD``:: + + nsh> echo $PWD + /dev + nsh> + +Show target of a link (readlink) +******************************** + +**Command Syntax**:: + + readlink + +**Synopsis**. Show the target of the soft link at the path +````. + +Reboot the system (reboot) +************************** + +**Command Syntax**:: + + reboot [] + +**Synopsis**. Reset and reboot the system immediately. This +command depends on hardware support to reset the system. The +optional, decimal numeric argument may be included to provide +a reboot mode to board-specific reboot logic. + +NOTE: Supporting both the ``reboot`` and ``shutdown`` commands is +redundant. + +Remove a File (rm) +****************** + +**Command Syntax**:: + + rm + +**Synopsis**. Remove the specified ```` name from the +mounted file system. Recall that NuttX uses a `pseudo file +system `__ for its root +file system. The ``rm`` command can only be used to remove +(unlink) files in volumes set up with the +```mount`` <#cmdmount>`__ command; it cannot be used to remove +names in the *pseudo* file system. + +**Example**:: + + nsh> ls /mnt/fs/testdir + /mnt/fs/testdir: + TESTFILE.TXT + EXAMPLE.TXT + nsh> rm /mnt/fs/testdir/example.txt + nsh> ls /mnt/fs/testdir + /mnt/fs/testdir: + TESTFILE.TXT + nsh> + +Remove a Directory (rmdir) +************************** + +**Command Syntax**:: + + rmdir + +**Synopsis**. Remove the specified ```` directory from +the mounted file system. Recall that NuttX uses a `pseudo file +system `__ for its root +file system. The ``rmdir`` command can only be used to remove +directories from volumes set up with the ```mount`` <#cmdmount>`__ +command; it cannot be used to remove directories from the *pseudo* +file system. + +**Example**:: + + nsh> mkdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + drw-rw-rw- 0 TMP/ + nsh> rmdir /mnt/fs/tmp + nsh> ls -l /mnt/fs + /mnt/fs: + drw-rw-rw- 0 TESTDIR/ + nsh> + +Remove on OS Module (rmmod) +*************************** + +**Command Syntax**:: + + rmmod + +**Synopsis**. Remove the loadable OS module with the +. NOTE: An OS module can only be removed if it is not +busy. + +**Example**:: + + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + mydriver 20404659 20404625 0 20404580 552 204047a8 0 + nsh> rmmod mydriver + nsh> lsmod + NAME INIT UNINIT ARG TEXT SIZE DATA SIZE + nsh> + +Show routing table (route) +************************** + +**Command Syntax**:: + + route ipv4|ipv6 + +**Synopsis**. Show the contents of routing table for IPv4 or IPv6. + +If only IPv4 or IPv6 is enabled, then the argument is optional +but, if provided, must match the enabled internet protocol +version. + +Start/Stop the OpenAMP RPC Tunnel (rptun) +***************************************** + +**Command Syntax**:: + + rptun start|stop + +**Synopsis**. Start or stop the OpenAMP RPC tunnel device at . + +Set a Variable (set) +******************** + +**Command Syntax**:: + + set [{+|-}{e|x|xe|ex}] [ ] + +**Synopsis**. Set the variable ```` to the string ```` and +or set NSH parser control options. + +For example, a variable may be set like this:: + + nsh> echo $foobar + + nsh> set foobar foovalue + nsh> echo $foobar + foovalue + nsh> + +If ``CONFIG_NSH_VARS`` is selected, the effect of this ``set`` command +is to set the local NSH variable. Otherwise, the group-wide environment +variable will be set. + +If the local NSH variable has already been *promoted* to an environment +variable via the ```export`` <#cmdexport>`__, then the ``set`` command +will set the value of the environment variable rather than the local NSH +variable. + +.. note:: The Bash shell does not work this way. Bash would set the value + of both the local Bash variable and the environment variable of the + same name to the same value. + +If ``CONFIG_NSH_VARS=y`` is selected and no arguments are provided, then +the ``set`` command will list all of the local NSH variables:: + + nsh> set + foolbar=foovalue + +Set the *exit on error control* and/or *print a trace* of commands when +parsing scripts in NSH. The settings are in effect from the point of +execution, until they are changed again, or in the case of the +initialization script, the settings are returned to the default settings +when it exits. Included child scripts will run with the parents settings +and changes made in the child script will effect the parent on return. + + - Use ``set -e`` to enable and ``set +e`` to disable (ignore) the exit + condition on commands. The default is -e. Errors cause script to + exit. + + - Use ``set -x`` to enable and ``set +x`` to disable (silence) printing + a trace of the script commands as they are executed. The default is + ``+x``: no printing of a trace of script commands as they are + executed. + +Example 1 - no exit on command not found:: + + set +e + notacommand + +Example 2 - will exit on command not found:: + + set -e + notacommand + +Example 3 - will exit on command not found, and print a trace of the +script commands:: + + set -ex + +Example 4 - will exit on command not found, and print a trace of the +script commands and set foobar to foovalue:: + + set -ex foobar foovalue + nsh> echo $foobar + foovalue + +Execute an NSH Script (sh) +************************** + +**Command Syntax**:: + + sh + +**Synopsis**. Execute the sequence of NSH commands in the file referred +to by ````. + +Shut the system down (shutdown) +******************************* + +**Command Syntax**:: + + shutdown [--reboot] + +**Synopsis**. Shutdown and power off the system or, optionally, reset +and reboot the system immediately. This command depends on hardware +support to power down or reset the system; one, both, or neither +behavior may be supported. + +NOTE: The ``shutdown`` command duplicates the behavior of the +``poweroff`` and ``eboot`` commands. + +Wait for Seconds (sleep) +************************ + +**Command Syntax**:: + + sleep + +**Synopsis**. Pause execution (sleep) for ```` seconds. + +Time Start the Telnet Daemon (telnetd) +************************************** + +**Command Syntax**:: + + telnetd + +**Synopsis**. Start the Telnet daemon if it is not already running. + +The Telnet daemon may be started either programmatically by calling +``nsh_telnetstart()`` or it may be started from the NSH command line +using this ``telnetd`` command. + +Normally this command would be suppressed with +``CONFIG_NSH_DISABLE_TELNETD`` because the Telnet daemon is +automatically started in ``nsh_main.c``. The exception is when +``CONFIG_NSH_NETLOCAL`` is selected. In that case, the network is not +enabled at initialization but rather must be enabled from the NSH +command line or via other applications. + +In that case, when ``nsh_telnetstart()`` is called before the the +network is initialized, it will fail. + +Time execution of another command (time) +**************************************** + +**Command Syntax**:: + + time "" + +**Synopsis**. Perform command timing. This command will execute the +following string and then show how much time was required to +execute the command. Time is shown with a resolution of 100 microseconds +which may be beyond the resolution of many configurations. Note that the + must be enclosed in quotation marks if it contains spaces or +other delimiters. + +**Example**:: + + nsh> time "sleep 2" + + 2.0100 sec + nsh> + +The additional 10 milliseconds in this example is due to the way that +the sleep command works: It always waits one system clock tick longer +than requested and this test setup used a 10 millisecond periodic system +timer. Sources of error could include various quantization errors, +competing CPU usage, and the additional overhead of the time command +execution itself which is included in the total. + +The reported time is the elapsed time from starting of the command to +completion of the command. This elapsed time may not necessarily be just +the processing time for the command. It may included interrupt level +processing, for example. In a busy system, command processing could be +delayed if pre-empted by other, higher priority threads competing for +CPU time. So the reported time includes all CPU processing from the +start of the command to its finish possibly including unrelated +processing time during that interval. + +Notice that:: + + nsh> time "sleep 2 &" + sleep [3:100] + + 0.0000 sec + nsh> + +Since the sleep command is executed in background, the sleep command +completes almost immediately. As opposed to the following where the time +command is run in background with the sleep command:: + + nsh> time "sleep 2" & + time [3:100] + nsh> + 2.0100 sec + +Set the Size of a File (truncate) +********************************* + +**Command Syntax**:: + + truncate -s + +**Synopsis**. Shrink or extend the size of the regular file at + to the specified. + +A argument that does not exist is created. The +option is NOT optional. + +If a is larger than the specified size, the extra data is +lost. If a is shorter, it is extended and the extended part +reads as zero bytes. + +Unmount a File System (umount) +****************************** + +**Command Syntax**:: + + umount + +**Synopsis**. Un-mount the file system at mount point ````. +The ``umount`` command can only be used to un-mount volumes previously +mounted using ```mount`` <#cmdmount>`__ command. + +**Example**:: + + nsh> ls /mnt/fs + /mnt/fs: + TESTDIR/ + nsh> umount /mnt/fs + nsh> ls /mnt/fs + /mnt/fs: + nsh: ls: no such directory: /mnt/fs + nsh> + +Print system information (uname) +******************************** + +**Command Syntax**:: + + uname [-a | -imnoprsv] + +**Synopsis**. Print certain system information. With no options, the +output is the same as -s. + +========== ======================================== +``-a`` Print all information, in the following + order, except omit -p and -i if unknown: +``-s, -o`` Print the operating system name (NuttX) +``-n`` Print the network node hostname (only available if CONFIG_NET=y) +``-r`` Print the kernel release +``-v`` Print the kernel version +``-m`` Print the machine hardware name +``-i`` Print the machine platform name +``-p`` Print "unknown" +========== ======================================== + +Unset an Environment Variable (unset) +************************************* + +**Command Syntax**: + + unset + +**Synopsis**. Remove the value associated with the variable ````. +This will remove the name-value pair from both the NSH local variables +and the group-wide environment variables. For example:: + + nsh> echo $foobar + foovalue + nsh> unset foobar + nsh> echo $foobar + + nsh> + +URL Decode (urldecode) +********************** + +**Command Syntax**:: + + urldecode [-f] + +**Synopsis**. *To be provided.* + +URL Encode (urlencode) +********************** + +**Command Syntax**:: + + urlencode [-f] + +**Synopsis**. *To be provided.* + +Add a New User (useradd) +************************ + +**Command Syntax**:: + + useradd + +**Synopsis**. Add a new user with and . + +Delete a user (userdel) +*********************** + +**Command Syntax**:: + + userdel + +**Synopsis**. Delete the user with the name . + +Wait for Microseconds (usleep) +****************************** + +**Command Syntax**:: + + usleep + +**Synopsis**. Pause execution (sleep) of ```` microseconds. + +Get File Via HTTP (wget) +************************ + +**Command Syntax** + + wget [-o ] + +**Synopsis**. Use HTTP to copy the file at ```` to the current +directory. + +**Options** + +=================== ================================================= +``-o `` The file will be saved relative to the current working + directory and with the same name as on the HTTP server + unless is provided. +=================== ================================================= + +Hexadecimal Dump of Memory (xd) +******************************* + +**Command Syntax**:: + + xd + +**Synopsis**. Dump ```` bytes of data from address +````. + +**Example**:: + + nsh> xd 410e0 512 + Hex dump: + 0000: 00 00 00 00 9c 9d 03 00 00 00 00 01 11 01 10 06 ................ + 0010: 12 01 11 01 25 08 13 0b 03 08 1b 08 00 00 02 24 ....%..........$ + ... + 01f0: 08 3a 0b 3b 0b 49 13 00 00 04 13 01 01 13 03 08 .:.;.I.......... + nsh> + +Built-In Commands +================= + +In addition to the commands that are part of NSH listed in the previous +section above, there can be additional, external *built-in* applications +that can be added to NSH. These are separately excecuble programs but +will appear much like the commands that are a part of NSH. The primary +difference from the user's perspective is that help information about +the built-in applications is not available directly from NSH. Rather, +you will need to execute the application with the ``-h`` option to get +help about using the built-in applications. + +There are several built-in applications in the ``apps/`` repository. No +attempt is made here to enumerate all of them. But a few of the more +common, useful built-in applications are listed below. + +Check Network Peer (ping/ping6) +******************************* + +**Command Syntax**:: + + ping [-c ] [-i ] + ping6 [-c ] [-i ] + +**Synopsis**. Test the network communication with a remote peer. +Example:: + + nsh> ping 10.0.0.1 + PING 10.0.0.1 56 bytes of data + 56 bytes from 10.0.0.1: icmp_seq=1 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=2 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=3 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=4 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=5 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=6 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=7 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=8 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=9 time=0 ms + 56 bytes from 10.0.0.1: icmp_seq=10 time=0 ms + 10 packets transmitted, 10 received, 0% packet loss, time 10190 ms + nsh> + +``ping6`` differs from ``ping`` in that it uses IPv6 addressing. + + diff --git a/doc/components/nsh/config.rst b/doc/components/nsh/config.rst new file mode 100644 index 00000000000..e3e74d8a8ee --- /dev/null +++ b/doc/components/nsh/config.rst @@ -0,0 +1,486 @@ +.. |br| raw:: html + +
+ +====================== +Configuration Settings +====================== + +The availability of the above commands depends upon features that may or +may not be enabled in the NuttX configuration file. The following +`table <#cmddependencies>`__ indicates the dependency of each command on +NuttX configuration settings. General configuration settings are +discussed in the `NuttX Porting Guide. `__ +Configuration settings specific to NSH as discussed at the +`bottom <#nshconfiguration>`__ of this document. + +Note that in addition to general NuttX configuration settings, each NSH +command can be individually disabled via the settings in the rightmost +column. All of these settings make the configuration of NSH potentially +complex but also allow it to squeeze into very small memory footprints. + +Command Dependencies on Configuration Settings +============================================== + +====================== =========================================== ====================== +Command Depends on Configuration Can Be Disabled with +====================== =========================================== ====================== +``[`` ! ``CONFIG_NSH_DISABLESCRIPT`` ``CONFIG_NSH_DISABLE_TEST`` +``addroute`` ``CONFIG_NET`` && ``CONFIG_NET_ROUTE`` ``CONFIG_NSH_DISABLE_ADDROUTE`` +``arp`` ``CONFIG_NET`` && ``CONFIG_NET_ARP`` ``CONFIG_NSH_DISABLE_ARP`` +``base64dec`` ``CONFIG_NETUTILS_CODECS`` && ``CONFIG_NSH_DISABLE_BASE64DEC`` + ``CONFIG_CODECS_BASE64`` +``base64enc`` ``CONFIG_NETUTILS_CODECS`` && ``CONFIG_NSH_DISABLE_BASE64ENC`` + ``CONFIG_CODECS_BASE64`` +``basename`` . ``CONFIG_NSH_DISABLE_BASENAME`` +``break`` ! ``CONFIG_NSH_DISABLESCRIPT`` && . + ! ``CONFIG_NSH_DISABLE_LOOPS``   +``cat`` ``CONFIG_NSH_DISABLE_CAT`` . +``cd`` ! ``CONFIG_DISABLE_ENVIRON`` ``CONFIG_NSH_DISABLE_CD`` +``cmp`` ``CONFIG_NSH_DISABLE_CMP`` . +``cp`` ``CONFIG_NSH_DISABLE_CP`` . +``date`` ``CONFIG_NSH_DISABLE_DATE`` . +``dd`` ``CONFIG_NSH_DISABLE_DD`` . +``delroute`` ``CONFIG_NET`` && ``CONFIG_NET_ROUTE`` ``CONFIG_NSH_DISABLE_DELROUTE`` +``df`` ! ``CONFIG_DISABLE_MOUNTPOINT`` ``CONFIG_NSH_DISABLE_DF`` +``dirname`` ``CONFIG_NSH_DISABLE_DIRNAME`` . +``dmesg`` ``CONFIG_RAMLOG_SYSLOG`` ``CONFIG_NSH_DISABLE_DMESG`` +``echo`` ``CONFIG_NSH_DISABLE_ECHO`` . +``env`` ``CONFIG_FS_PROCFS`` && ``CONFIG_NSH_DISABLE_ENV`` + ! ``CONFIG_DISABLE_ENVIRON`` && |br| + ! ``CONFIG_PROCFS_EXCLUDE_ENVIRON`` +``exec`` ``CONFIG_NSH_DISABLE_EXEC`` . +``exit`` ``CONFIG_NSH_DISABLE_EXIT`` . +``export`` ``CONFIG_NSH_VARS`` && + ! ``CONFIG_DISABLE_ENVIRON`` ``CONFIG_NSH_DISABLE_EXPORT`` +``free`` ``CONFIG_NSH_DISABLE_FREE`` . +``get`` ``CONFIG_NET`` && ``CONFIG_NET_UDP`` && ``CONFIG_NSH_DISABLE_GET`` + *MTU* >= 58\ [#1]_ +``help`` [#3]_ ``CONFIG_NSH_DISABLE_HELP`` . +``hexdump`` ``CONFIG_NSH_DISABLE_HEXDUMP`` . +``ifconfig`` ``CONFIG_NET`` && ``CONFIG_FS_PROCFS`` && ``CONFIG_NSH_DISABLE_IFCONFIG`` + ! ``CONFIG_FS_PROCFS_EXCLUDE_NET`` +``ifdown`` ``CONFIG_NET`` && ``CONFIG_FS_PROCFS`` && ``CONFIG_NSH_DISABLE_IFUPDOWN`` + ! ``CONFIG_FS_PROCFS_EXCLUDE_NET`` +``ifup`` ``CONFIG_NET`` && ``CONFIG_FS_PROCFS`` && + ! ``CONFIG_FS_PROCFS_EXCLUDE_NET`` ``CONFIG_NSH_DISABLE_IFUPDOWN`` +``insmod`` ``CONFIG_MODULE`` ``CONFIG_NSH_DISABLE_MODCMDS`` +``irqinfo`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && . + ``CONFIG_FS_PROCFS`` && |br| + ``CONFIG_SCHED_IRQMONITOR`` +``kill`` ``CONFIG_NSH_DISABLE_KILL`` . +``losetup`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_LOSETUP`` + ``CONFIG_DEV_LOOP`` +``ln`` ``CONFIG_PSEUDOFS_SOFTLINKS`` ``CONFIG_NSH_DISABLE_LN`` +``ls`` ``CONFIG_NSH_DISABLE_LS`` . +``lsmod`` ``CONFIG_MODULE`` && ``CONFIG_FS_PROCFS`` ``CONFIG_NSH_DISABLE_MODCMDS`` + && |br| + ! ``CONFIG_FS_PROCFS_EXCLUDE_MODULE`` +``md5`` ``CONFIG_NETUTILS_CODECS`` && ``CONFIG_NSH_DISABLE_MD5`` + ``CONFIG_CODECS_HASH_MD5`` +``mb,mh,mw`` . ``CONFIG_NSH_DISABLE_MB``, |br| + ``CONFIG_NSH_DISABLE_MH``, |br| + ``CONFIG_NSH_DISABLE_MW`` +``mkdir`` (! ``CONFIG_DISABLE_MOUNTPOINT`` \|\| ``CONFIG_NSH_DISABLE_MKDIR`` + ! ``CONFIG_DISABLE_PSEUDOFS_OPERATIONS``) +``mkfatfs`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_MKFATFS`` + ``CONFIG_FSUTILS_MKFATFS`` +``mkfifo`` ``CONFIG_PIPES`` && ``CONFIG_NSH_DISABLE_MKFIFO`` + ``CONFIG_DEV_FIFO_SIZE`` > 0 +``mkrd`` ! ``CONFIG_DISABLE_MOUNTPOINT`` ``CONFIG_NSH_DISABLE_MKRD`` +``mount`` ! ``CONFIG_DISABLE_MOUNTPOINT`` ``CONFIG_NSH_DISABLE_MOUNT`` +``mv`` ! ``CONFIG_DISABLE_MOUNTPOINT`` \|\| ``CONFIG_NSH_DISABLE_MV`` + ! ``CONFIG_DISABLE_PSEUDOFS_OPERATIONS`` +``nfsmount`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_NFSMOUNT`` + ``CONFIG_NET`` && ``CONFIG_NFS`` +``nslookup`` ``CONFIG_LIBC_NETDB`` && ``CONFIG_NSH_DISABLE_NSLOOKUP`` + ``CONFIG_NETDB_DNSCLIENT`` +``passwd`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_PASSWD`` + ``CONFIG_NSH_LOGIN_PASSWD`` +``pmconfig`` ``CONFIG_PM`` ``CONFIG_NSH_DISABLE_PMCONFIG`` +``poweroff`` ``CONFIG_BOARDCTL_POWEROFF`` ``CONFIG_NSH_DISABLE_POWEROFF`` +``ps`` ``CONFIG_FS_PROCFS`` && ``CONFIG_NSH_DISABLE_PS`` + ! ``CONFIG_FS_PROCFS_EXCLUDE_PROC`` +``put`` ``CONFIG_NET`` && ``CONFIG_NET_UDP`` && ``CONFIG_NSH_DISABLE_PUT`` + ``MTU >= 558`` [#1]_, [#2]_ +``pwd`` ! ``CONFIG_DISABLE_ENVIRON`` ``CONFIG_NSH_DISABLE_PWD`` +``readlink`` ``CONFIG_PSEUDOFS_SOFTLINKS`` ``CONFIG_NSH_DISABLE_READLINK`` +``reboot`` ``CONFIG_BOARD_RESET`` ``CONFIG_NSH_DISABLE_REBOOT`` +``rm`` ! ``CONFIG_DISABLE_MOUNTPOINT`` \|\| ``CONFIG_NSH_DISABLE_RM`` + ! ``CONFIG_DISABLE_PSEUDOFS_OPERATIONS`` +``rmdir`` ! ``CONFIG_DISABLE_MOUNTPOINT`` \|\ + ! ``CONFIG_DISABLE_PSEUDOFS_OPERATIONS`` ``CONFIG_NSH_DISABLE_RMDIR`` +``rmmod`` ``CONFIG_MODULE`` ``CONFIG_NSH_DISABLE_MODCMDS`` +``route`` ``CONFIG_FS_PROCFS`` && ``CONFIG_NSH_DISABLE_ROUTE`` + ``CONFIG_FS_PROCFS_EXCLUDE_NET`` && |br| + ! ``CONFIG_FS_PROCFS_EXCLUDE_ROUTE`` && + ``CONFIG_NET_ROUTE`` && |br| + ! ``CONFIG_NSH_DISABLE_ROUTE`` && |br| + (``CONFIG_NET_IPv4`` \|\ + ``CONFIG_NET_IPv6``) +``rptun`` ``CONFIG_RPTUN`` ``CONFIG_NSH_DISABLE_RPTUN`` +``set`` ``CONFIG_NSH_VARS`` \|\| ``CONFIG_NSH_DISABLE_SET`` + ! ``CONFIG_DISABLE_ENVIRON`` +``shutdown`` ``CONFIG_BOARDCTL_POWEROFF`` \|\| ``CONFIG_NSH_DISABLE_SHUTDOWN`` + ``CONFIG_BOARD_RESET`` +``sleep`` . ``CONFIG_NSH_DISABLE_SLEEP`` +``source`` ``CONFIG_NFILE_STREAMS > 0`` && ``CONFIG_NSH_DISABLE_SOURCE`` + ! ``CONFIG_NSH_DISABLESCRIPT`` +``telnetd`` ``CONFIG_NSH_TELNET`` ``CONFIG_NSH_DISABLE_TELNETD`` +``test`` ! ``CONFIG_NSH_DISABLESCRIPT`` ``CONFIG_NSH_DISABLE_TEST`` +``time`` . ``CONFIG_NSH_DISABLE_TIME`` +``truncate`` ! ``CONFIG_DISABLE_MOUNTPOINT`` ``CONFIG_NSH_DISABLE_TRUNCATE`` +``umount`` ! ``CONFIG_DISABLE_MOUNTPOINT`` ``CONFIG_NSH_DISABLE_UMOUNT`` +``uname`` . ``CONFIG_NSH_DISABLE_UNAME`` +``unset`` ``CONFIG_NSH_VARS`` \|\| ``CONFIG_NSH_DISABLE_UNSET`` + ! ``CONFIG_DISABLE_ENVIRON`` +``urldecode`` ! ``CONFIG_NETUTILS_CODECS`` && ``CONFIG_NSH_DISABLE_URLDECODE`` + ``CONFIG_CODECS_URLCODE`` +``urlencode`` ! ``CONFIG_NETUTILS_CODECS`` && ``CONFIG_NSH_DISABLE_URLENCODE`` + ``CONFIG_CODECS_URLCODE`` +``useradd`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_USERADD`` + ``CONFIG_NSH_LOGIN_PASSWD`` +``userdel`` ! ``CONFIG_DISABLE_MOUNTPOINT`` && ``CONFIG_NSH_DISABLE_USERDEL`` + ``CONFIG_NSH_LOGIN_PASSWD`` +``usleep`` . ``CONFIG_NSH_DISABLE_USLEEP`` +``wget`` ``CONFIG_NET`` && ``CONFIG_NET_TCP`` ``CONFIG_NSH_DISABLE_WGET`` +``xd`` . ``CONFIG_NSH_DISABLE_XD`` +====================== =========================================== ====================== + +.. [#1] Because of hardware padding, the actual required packet size may be larger +.. [#2] Special TFTP server start-up options will probably be required to permit creation of files for the correct operation of the ``put`` command. +.. [#3] Verbose help output can be suppressed by defining ``CONFIG_NSH_HELP_TERSE``. In that case, the help command is still available but will be slightly smaller. + +Built-In Command Dependencies on Configuration Settings +======================================================= + +All built-in applications require that support for NSH built-in +applications has been enabled. This support is enabled with +``CONFIG_BUILTIN=y`` and ``CONFIG_NSH_BUILTIN_APPS=y``. + +============= ================================================================================================== +Command Depends on Configuration +============= ================================================================================================== +``ping`` ``CONFIG_NET`` && ``CONFIG_NET_ICMP`` && ``CONFIG_NET_ICMP_SOCKET`` && ``CONFIG_SYSTEM_PING`` +``ping6`` ``CONFIG_NET`` && ``CONFIG_NET_ICMPv6`` && ``CONFIG_NET_ICMPv6_SOCKET`` && ``CONFIG_SYSTEM_PING6`` +============= ================================================================================================== + +NSH-Specific Configuration Settings +=================================== + +The behavior of NSH can be modified with the following settings in the +``boards////defconfig`` file: + +=================================== ================================== +Configuration Description +=================================== ================================== + ``CONFIG_NSH_READLINE`` Selects the minimal implementation of ``readline()``. + This minimal implementation provides on backspace for command + line editing. It expects some minimal VT100 command support from the terminal. + + ``CONFIG_NSH_CLE`` Selects the more extensive, EMACS-like command line editor. + Select this option only if (1) you don't mind a modest increase + in the FLASH footprint, and (2) you work with a terminal that + supports extensive VT100 editing commands. Selecting this option + will add probably 1.5-2KB to the FLASH footprint. + + ``CONFIG_NSH_BUILTIN_APPS`` Support external registered, "builtin" applications that can + be executed from the NSH command line (see apps/README.txt for + more information). This required ``CONFIG_BUILTIN`` to enable + NuttX support for "builtin" applications. + + ``CONFIG_NSH_FILEIOSIZE`` Size of a static I/O buffer used for file access (ignored if there + is no file system). Default is 1024. + + ``CONFIG_NSH_STRERROR`` ``strerror(errno)`` makes more readable output but + ``strerror()`` is very large and will not be used unless this + setting is *y*. This setting depends upon the ``strerror()`` + having been enabled with ``CONFIG_LIBC_STRERROR``. + + ``CONFIG_NSH_LINELEN`` The maximum length of one command line and of one output line. + Default: 80 + + ``CONFIG_NSH_DISABLE_SEMICOLON`` By default, you can enter multiple NSH commands on a line + with each command separated by a semicolon. You can disable this + feature to save a little memory on FLASH challenged platforms. + Default: n + + ``CONFIG_NSH_CMDPARMS`` If selected, then the output from commands, from file applications, + and from NSH built-in commands can be used as arguments to other + commands. The entity to be executed is identified by + enclosing the command line in back quotes. For example:: + + set FOO `myprogram $BAR` + + will execute the program named ``myprogram`` passing it the + value of the environment variable ``BAR``. The value of the + environment variable ``FOO`` is then set output of ``myprogram`` + on ``stdout``. Because this feature commits significant + resources, it is disabled by default. The ``CONFIG_NSH_CMDPARMS`` interim + output will be retained in a temporary file. Full path to a + directory where temporary files can be created is taken from + ``CONFIG_LIBC_TMPDIR`` and it defaults to ``/tmp`` if + ``CONFIG_LIBC_TMPDIR`` is not set. + + ``CONFIG_NSH_MAXARGUMENTS`` The maximum number of NSH command arguments. Default: 6 + + ``CONFIG_NSH_ARGCAT`` Support concatenation of strings with environment variables or + command output. For example:: + + set FOO XYZ + set BAR 123 + set FOOBAR ABC_${FOO}_${BAR} + + would set the environment variable ``FOO`` to ``XYZ``, + ``BAR`` to ``123`` and ``FOOBAR`` to ``ABC_XYZ_123``. If + ``CONFIG_NSH_ARGCAT`` is not selected, then a slightly small + FLASH footprint results but then also only simple environment + variables like ``$FOO`` can be used on the command line. + + ``CONFIG_NSH_VARS`` By default, there are no internal NSH variables. NSH will use OS + environment variables for all variable storage. If this option, + NSH will also support local NSH variables. These variables are, + for the most part, transparent and work just like the OS + environment variables. The difference is that when you + create new tasks, all of environment variables are + inherited by the created tasks. NSH local variables are not. + If this option is enabled (and ``CONFIG_DISABLE_ENVIRON`` is not), + then a new command called 'export' is enabled. The export + command works very must like the set command except that is + operates on environment variables. When CONFIG_NSH_VARS + is enabled, there are changes in the behavior of certain commands. + See table :ref:`_nsh_vars_table`. + + ``CONFIG_NSH_QUOTE`` Enables back-slash quoting of certain characters within the + command. This option is useful for the case where an NSH script + is used to dynamically generate a new NSH script. In that case, + commands must be treated as simple text strings without + interpretation of any special characters. Special characters + such as ``$``, :literal:`\``, ``"``, and others must be + retained intact as part of the test string. This option is + currently only available is ``CONFIG_NSH_ARGCAT`` is also + selected. + + ``CONFIG_NSH_NESTDEPTH`` The maximum number of nested ``if-then[-else]-fi`` <#conditional>`__ + sequences that are permissible. Default: 3 + + ``CONFIG_NSH_DISABLESCRIPT`` This can be set to *y* to suppress support for scripting. + This setting disables the ```sh`` <#cmdsh>`__, + ```test`` <#cmdtest>`__, and ```[`` <#cmtest>`__ commands and + the ```if-then[-else]-fi`` <#conditional>`__ + construct. This would only be set on systems where a minimal + footprint is a necessity and scripting is not. + + ``CONFIG_NSH_DISABLE_ITEF`` If scripting is enabled, then then this option can be selected + to suppress support for ``if-then-else-fi`` sequences in + scripts. This would only be set on systems where some minimal + scripting is required but ``if-then-else-fi`` is not. + + ``CONFIG_NSH_DISABLE_LOOPS`` If scripting is enabled, then then this option can be selected + suppress support ``for while-do-done`` and + ``until-do-done`` sequences in scripts. This would only be set + on systems where some minimal scripting is required but looping + is not. + + ``CONFIG_NSH_DISABLEBG`` This can be set to *y* to suppress support for background + commands. This setting disables the ```nice`` <#cmdoverview>`__ + command prefix and the ```&`` <#cmdoverview>`__ command + suffix. This would only be set on systems where a minimal footprint + is a necessity and background command execution is not. + + ``CONFIG_NSH_MMCSDMINOR`` If the architecture supports an MMC/SD slot and if the NSH + architecture specific logic is present, this option will provide + the MMC/SD minor number, i.e., the MMC/SD block driver will be + registered as ``/dev/mmcsd``\ *N* where *N* is the minor number. + Default is zero. + + ``CONFIG_NSH_ROMFSETC`` Mount a ROMFS file system at ``/etc`` and provide a startup + script at ``/etc/init.d/rcS``. + The default startup script will mount a FAT FS RAMDISK at + ``/tmp`` but the logic is `easily extensible <#startupscript>`__. + + ``CONFIG_NSH_CONSOLE`` If ``CONFIG_NSH_CONSOLE`` is set to *y*, then a serial console + front-end is selected. + + Normally, the serial console device is a UART and RS-232 + interface. However, if ``CONFIG_USBDEV`` is defined, + then a USB serial device may, instead, be used if the one of + the following are defined: + + - ``CONFIG_PL2303`` and ``CONFIG_PL2303_CONSOLE``. + Sets up the Prolifics PL2303 emulation as a console device + at ``/dev/console``. + - ``CONFIG_CDCACM`` and ``CONFIG_CDCACM_CONSOLE``. + Sets up the CDC/ACM serial device as a console device at + ``/dev/console``. + - ``CONFIG_NSH_USBCONSOLE``. If defined, then an arbitrary USB + device may be used to as the NSH console. In this case, + ``CONFIG_NSH_USBCONDEV`` must be defined to indicate which + USB device to use as the console. The advantage of + using a device other that ``/dev/console`` is that + normal debug output can then use ``/dev/console`` while NSH + uses ``CONFIG_NSH_USBCONDEV``. + + ``CONFIG_NSH_USBCONDEV``. If ``CONFIG_NSH_USBCONSOLE`` is + set to 'y', then ``CONFIG_NSH_USBCONDEV`` must also be set to select the USB + device used to support the NSH console. This should be set to + the quoted name of a readable/write-able USB driver + such as: ``CONFIG_NSH_USBCONDEV="/dev/ttyACM0"``. + + If there are more than one USB slots, then a USB device minor + number may also need to be provided: + + - ``CONFIG_NSH_UBSDEV_MINOR``: The minor device number of the USB device. Default: 0 + + If USB tracing is enabled (``CONFIG_USBDEV_TRACE``), then + NSH will initialize USB tracing as requested by the following. + Default: Only USB errors are traced. + + - ``CONFIG_NSH_USBDEV_TRACEINIT``: Show initialization events + - ``CONFIG_NSH_USBDEV_TRACECLASS``: Show class driver events + - ``CONFIG_NSH_USBDEV_TRACETRANSFERS``: Show data transfer events + - ``CONFIG_NSH_USBDEV_TRACECONTROLLER``: Show controller events + - ``CONFIG_NSH_USBDEV_TRACEINTERRUPTS``: Show interrupt-related events. + + ``CONFIG_NSH_ALTCONDEV`` and If ``CONFIG_NSH_CONSOLE`` is set ``CONFIG_NSH_CONDEV`` + to *y*, then ``CONFIG_NSH_ALTCONDEV`` may also + be selected to enable use of an alternate character device to + support the NSH console. If ``CONFIG_NSH_ALTCONDEV`` is + selected, then ``CONFIG_NSH_CONDEV`` holds the + quoted name of a readable/write-able character + driver such as: ``CONFIG_NSH_CONDEV="/dev/ttyS1"``. + This is useful, for example, to separate the NSH command line + from the system console when the system console is used to provide + debug output. Default: ``stdin`` and ``stdout`` (probably + "``/dev/console``") + + - **NOTE 1:** When any other device other than + ``/dev/console`` is used for a user interface, (1) linefeeds + (``\n``) will not be expanded to carriage return / linefeeds + (``\r\n``). You will need to configure your terminal + program to account for this. + And (2) input is not automatically echoed so you + will have to turn local echo on. + - **NOTE 2:** This option forces the console of all sessions to + use NSH_CONDEV. Hence, this option only makes sense for a + system that supports only a single session. This option + is, in particular, incompatible with Telnet + sessions because each Telnet session must use a different + console device. + + ``CONFIG_NSH_TELNET`` If ``CONFIG_NSH_TELNET`` is set to *y*, then a TELNET server + front-end is selected. When this option is provided, you may log + into NuttX remotely using telnet in order to access NSH. + + ``CONFIG_NSH_ARCHINIT`` Set ``CONFIG_NSH_ARCHINIT`` if your board provides architecture + specific initialization via the board-specific function + ``board_app_initialize()``. This function will be called early in + NSH initialization to allow board logic to do such things as + configure MMC/SD slots. +=================================== ================================== + +.. _nsh_vars_table: + +================== =================================== ============================================= +CMD w/o ``CONFIG_NSH_VARS`` w/``CONFIG_NSH_VARS`` +================== =================================== ============================================= +``set `` Set environment variable to Set NSH variable to (Unless the NSH variable has been *promoted* via + ``export``, in which case the env ironment variable of the same name is set to ). +``set`` Causes an error. Lists all NSH variables. +``unset `` Unsets environment variable Unsets both environment variable *and* NSH variable with and name +``export `` Causes an error, Unsets NSH variable . Sets environment variable to . +``export `` Causes an error. Sets environment variable to the value of NSH variable (or "" if the + NSH variable has not been set). Unsets NSH local variable . +``env`` Lists all environment variables Lists all environment variables (*only*) +================== =================================== ============================================= + + +If Telnet is selected for the NSH console, then we must configure the +resources used by the Telnet daemon and by the Telnet clients. + +====================================== ================================ +Configuration Description +====================================== ================================ +``CONFIG_NSH_TELNETD_PORT`` The telnet daemon will listen on this TCP port number for connections. Default: 23 +``CONFIG_NSH_TELNETD_DAEMONPRIO`` Priority of the Telnet daemon. Default: ``SCHED_PRIORITY_DEFAULT`` +``CONFIG_NSH_TELNETD_DAEMONSTACKSIZE`` Stack size allocated for the Telnet daemon. Default: 2048 +``CONFIG_NSH_TELNETD_CLIENTPRIO`` Priority of the Telnet client. Default: ``SCHED_PRIORITY_DEFAULT`` +``CONFIG_NSH_TELNETD_CLIENTSTACKSIZE`` Stack size allocated for the Telnet client. Default: 2048 +====================================== ================================ + +One or both of ``CONFIG_NSH_CONSOLE`` and ``CONFIG_NSH_TELNET`` must be +defined. If ``CONFIG_NSH_TELNET`` is selected, then there some other +configuration settings that apply: + +====================================== ================================ +Configuration Description +====================================== ================================ +``CONFIG_NET=y`` Of course, networking must be enabled. +``CONFIG_NSOCKET_DESCRIPTORS`` And, of course, you must allocate some socket descriptors. +``CONFIG_NET_TCP=y`` TCP/IP support is required for telnet (as well as various other + TCP-related configuration settings). +``CONFIG_NSH_IOBUFFER_SIZE`` Determines the size of the I/O buffer to use for sending/ receiving + TELNET commands/responses +``CONFIG_NSH_DHCPC`` Obtain the IP address via DHCP. +``CONFIG_NSH_IPADDR`` If ``CONFIG_NSH_DHCPC`` is NOT set, then the static IP address must be + provided. +``CONFIG_NSH_DRIPADDR`` Default router IP address +``CONFIG_NSH_NETMASK`` Network mask +``CONFIG_NSH_NOMAC`` Set if your Ethernet hardware has no built-in MAC address. If set, a + bogus MAC will be assigned. +``CONFIG_NSH_MAX_ROUNDTRIP`` This is the maximum round trip for a response to a ICMP ECHO request. It + is in units of deciseconds. The default is 20 (2 seconds). +====================================== ================================ + +If you use DHCPC, then some special configuration network options are +required. These include: + +============================================== ============================================================ +Configuration Description +============================================== ============================================================ +``CONFIG_NET=y`` Of course, networking must be enabled. +``CONFIG_NSOCKET_DESCRIPTORS`` And, of course, you must allocate some socket descriptors. +``CONFIG_NET_UDP=y`` UDP support is required for DHCP (as well as various other + UDP-related configuration settings). +``CONFIG_NET_BROADCAST=y`` UDP broadcast support is needed. +``CONFIG_NET_ETH_PKTSIZE=650`` (or larger) Per RFC2131 (p. 9), the DHCP client must be prepared to receive + DHCP messages of up to 576 bytes (excluding Ethernet, IP, or + UDP headers and FCS). NOTE: Note that the actual MTU setting + will depend upon the specific link protocol. Here Ethernet + is indicated. +============================================== ============================================================ + +If ``CONFIG_NSH_ROMFSETC`` is selected, then the following additional +configuration setting apply: + +============================== ============================================================== +Configuration Description +============================== ============================================================== +``CONFIG_NSH_ARCHROMFS`` May be defined to specify an alternative ROMFS image + that can be found at ``boards////include/nsh_romfsimg.h``. +``CONFIG_NSH_ROMFSMOUNTPT`` The default mountpoint for the ROMFS volume is ``"/etc"``, + but that can be changed with this setting. This must be a + absolute path beginning with '``/``' and enclosed in quotes. +``CONFIG_NSH_INITSCRIPT`` This is the relative path to the startup script within the + mountpoint. The default is ``"init.d/rcS"``. This is a relative + path and must not start with '``/``' but must be enclosed in quotes. +``CONFIG_NSH_ROMFSDEVNO`` This is the minor number of the ROMFS block device. + The default is '``0``' corresponding to ``/dev/ram0``. +``CONFIG_NSH_ROMFSSECTSIZE`` This is the sector size to use with the ROMFS volume. Since the + default volume is very small, this defaults to 64 but should + be increased if the ROMFS volume were to be become large. + Any value selected must be a power of 2. +============================== ============================================================== + +When the default ``rcS`` file used when ``CONFIG_NSH_ROMFSETC`` is +selected, it will mount a FAT FS under ``/tmp``. The following +selections describe that FAT FS. + +============================== ======================================================= +Configuration Description +============================== ======================================================= +``CONFIG_NSH_FATDEVNO`` This is the minor number of the FAT FS block device. + The default is '``1``' corresponding to ``/dev/ram1``. +``CONFIG_NSH_FATSECTSIZE`` This is the sector size use with the FAT FS. Default is 512. +============================== ======================================================= + diff --git a/doc/components/nsh/customizing.rst b/doc/components/nsh/customizing.rst new file mode 100644 index 00000000000..fcd293b71b5 --- /dev/null +++ b/doc/components/nsh/customizing.rst @@ -0,0 +1,213 @@ +************************* +Customizing the NuttShell +************************* + +**Overview.** The NuttShell (NSH) is a simple shell application that may +be used with NuttX. It supports a variety of commands and is (very) +loosely based on the Bash shell and the common utilities used with Bash +shell programming. The paragraphs in this appendix will focus on +customizing NSH: Adding new commands, changing the initialization +sequence, etc. + +The NSH Library and NSH Initialization +************************************** + +**Overview.** NSH is implemented as a library that can be found at +``apps/nshlib``. As a library, it can be custom built into any +application that follows the NSH initialization sequence described +below. As an example, the code at ``apps/examples/nsh/nsh_main.c`` +illustrates how to start NSH and the logic there was intended to be +incorporated into your own custom code. Although code was generated +simply as an example, in the end most people just use this example code +as their application ``main()`` function. That initialization performed +by that example is discussed in the following paragraphs. + +NSH Initialization sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The NSH start-up sequence is very simple. As an example, the code at +``apps/system/nsh/nsh_main.c`` illustrates how to start NSH. It simple +does the following: + + #. This function calls ``nsh_initialize()`` which initializes the NSH + library. ``nsh_initialize()`` is described in more detail below. + + #. If the Telnetconsole is enabled, it calls ``nsh_telnetstart()`` which + resides in the NSH library. ``nsh_telnetstart()`` will start the + Telnet daemon that will listen for Telnet connections and start + remote NSH sessions. + + #. If a local console is enabled (probably on a serial port), then + ``nsh_consolemain()`` is called. ``nsh_consolemain()`` also resides + in the NSH library. ``nsh_consolemain()`` does not return so that + finished the entire NSH initialization sequence. + +``nsh_initialize()`` +~~~~~~~~~~~~~~~~~~~~ + +The NSH initialization function, ``nsh_initialize()``, be found in +``apps/nshlib/nsh_init.c``. It does only three things: + + #. ``nsh_romfsetc()``: If so configured, it executes an NSH start-up + script that can be found at ``/etc/init.d/rcS`` in the target file + system. The ``nsh_romfsetc()`` function can be found in + ``apps/nshlib/nsh_romfsetc.c``. This function will (1) register a + ROMFS file system, then (2) mount the ROMFS file system. ``/etc`` is + the default location where a read-only, ROMFS file system is mounted + by ``nsh_romfsetc()``. + + The ROMFS image is, itself, just built into the firmware. By default, + this ``rcS`` start-up script contains the following logic:: + + # Create a RAMDISK and mount it at XXXRDMOUNTPOINTXXX + + mkrd -m XXXMKRDMINORXXX -s XXMKRDSECTORSIZEXXX XXMKRDBLOCKSXXX + mkfatfs /dev/ramXXXMKRDMINORXXX + mount -t vfat /dev/ramXXXMKRDMINORXXX XXXRDMOUNTPOINTXXX + + Where the ``XXXX*XXXX`` strings get replaced in the template when the + ROMFS image is created: + + - ``XXXMKRDMINORXXX`` will become the RAM device minor number. + Default: 0 + + - ``XXMKRDSECTORSIZEXXX`` will become the RAM device sector size + + - ``XXMKRDBLOCKSXXX`` will become the number of sectors in the + device. + + - ``XXXRDMOUNTPOINTXXX`` will become the configured mount point. + Default: ``/etc`` + + By default, the substituted values would yield an ``rcS`` file like:: + + # Create a RAMDISK and mount it at /tmp + + mkrd -m 1 -s 512 1024 + mkfatfs /dev/ram1 + mount -t vfat /dev/ram1 /tmp + + This script will, then: + + - Create a RAMDISK of size 512*1024 bytes at ``/dev/ram1``, + + - Format a FAT file system on the RAM disk at ``/dev/ram1``, and + then + + - Mount the FAT file system at a configured mountpoint, ``/tmp``. + + This ``rcS`` template file can be found at + ``apps/nshlib/rcS.template``. The resulting ROMFS file system can be + found in ``apps/nshlib/nsh_romfsimg.h``. + + #. ``board_app_initialize()``: Next any architecture-specific NSH + initialization will be performed (if any). For the STM3240G-EVAL, + this architecture specific initialization can be found at + ``boards/arm/stm32/stm3240g-eval/src/stm32_appinit.c``. This it does + things like: (1) Initialize SPI devices, (2) Initialize SDIO, and (3) + mount any SD cards that may be inserted. + + #. ``nsh_netinit()``: The ``nsh_netinit()`` function can be found in + ``apps/nshlib/nsh_netinit.c``. + +NSH Commands +************ + +**Overview.** NSH supports a variety of commands as part of the NSH +program. All of the NSH commands are listed in the NSH documentation +`above <#cmdoverview>`__. Not all of these commands may be available at +any time, however. Many commands depend upon certain NuttX configuration +options. You can enter the help command at the NSH prompt to see the +commands actual available: + +For example, if network support is disabled, then all network-related +commands will be missing from the list of commands presented by +'``nsh> help``'. You can see the specific command dependencies in the +table `above <#cmddependencies>`__. + +Adding New NSH Commands +~~~~~~~~~~~~~~~~~~~~~~~ + +New commands can be added to the NSH very easily. You simply need to add +two things: + + #. The implementation of your command, and + + #. A new entry in the NSH command table + +**Implementation of Your Command.** For example, if you want to add a +new a new command called ``mycmd`` to NSH, you would first implement the +``mycmd`` code in a function with this prototype: + +.. code-block:: c + + int cmd_mycmd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); + +The ``argc`` and ``argv`` are used to pass command line arguments to the +NSH command. Command line parameters are passed in a very standard way: +``argv[0]`` will be the name of the command, and ``argv[1]`` through +``argv[argc-1]`` are the additional arguments provided on the NSH +command line. + +The first parameter, ``vtbl``, is special. This is a pointer to +session-specific state information. You don't need to know the contents +of the state information, but you do need to pass this ``vtbl`` argument +when you interact with the NSH logic. The only use you will need to make +of the ``vtbl`` argument will be for outputting data to the console. You +don't use ``printf()`` within NSH commands. Instead you would use: + +.. code-block:: c + + void nsh_output(FAR struct nsh_vtbl_s *vtbl, const char *fmt, ...); + +So if you only wanted to output "Hello, World!" on the console, then +your whole command implementation might be: + +.. code-block:: c + + int cmd_mycmd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) + { + nsh_output(vtbl, "Hello, World!"); + return 0; + } + +The prototype for the new command should be placed in +``apps/examples/nshlib/nsh.h``. + +**Adding You Command to the NSH Command Table**. All of the commands +support by NSH appear in a single table called: + +.. code-block:: c + + const struct cmdmap_s g_cmdmap[] + +That table can be found in the file +``apps/examples/nshlib/nsh_parse.c``. The structure ``cmdmap_s`` is also +defined in ``apps/nshlib/nsh_parse.c``: + +.. code-block:: c + + struct cmdmap_s + { + const char *cmd; /* Name of the command */ + cmd_t handler; /* Function that handles the command */ + uint8_t minargs; /* Minimum number of arguments (including command) */ + uint8_t maxargs; /* Maximum number of arguments (including command) */ + const char *usage; /* Usage instructions for 'help' command */ + }; + +This structure provides everything that you need to describe your +command: Its name (``cmd``), the function that handles the command +(``cmd_mycmd()``), the minimum and maximum number of arguments needed by +the command, and a string describing the command line arguments. That +last string is what is printed when enter "``nsh> help``". + +So, for you sample command, you would add the following the to the +``g_cmdmap[]`` table: + +.. code-block:: c + + { "mycmd", cmd_mycmd, 1, 1, NULL }, + +This entry is particularly simply because ``mycmd`` is so simple. Look +at the other commands in ``g_cmdmap[]`` for more complex examples. diff --git a/doc/components/nsh/index.rst b/doc/components/nsh/index.rst new file mode 100644 index 00000000000..a1a6044d1f9 --- /dev/null +++ b/doc/components/nsh/index.rst @@ -0,0 +1,18 @@ +=============== +NuttShell (NSH) +=============== + +.. warning:: + This document is being migrated from previous documentation format, + it is a work in progress. + +.. toctree:: + :maxdepth: 2 + + nsh.rst + commands.rst + config.rst + customizing.rst + builtin.rst + installation.rst + login.rst diff --git a/doc/components/nsh/installation.rst b/doc/components/nsh/installation.rst new file mode 100644 index 00000000000..60ed8e62307 --- /dev/null +++ b/doc/components/nsh/installation.rst @@ -0,0 +1,187 @@ +****************************** +Customizing NSH Initialization +****************************** + +**Ways to Customize NSH Initialization**. There are three ways to +customize the NSH start-up behavior. Here they are presented in order of +increasing difficulty: + + #. You can extend the initialization logic in + ``boards/arm/stm32/stm3240g-eval/src/stm32_appinit.c``. The logic + there is called each time that NSH is started and is good place in + particular for any device-related initialization. + + #. You replace the sample code at ``apps/examples/nsh/nsh_main.c`` with + whatever start-up logic that you want. NSH is a library at + ``apps/nshlib``. ``apps.examples/nsh`` is just a tiny, example + start-up function (``CONFIG_USER_ENTRYPOINT``\ ()) that that runs + immediately and illustrates how to start NSH If you want something + else to run immediately then you can write your write your own custom + ``CONFIG_USER_ENTRYPOINT``\ () function and then start other tasks + from your custom ``CONFIG_USER_ENTRYPOINT``\ (). + + #. NSH also supports a start-up script that executed when NSH first + runs. This mechanism has the advantage that the start-up script can + contain any NSH commands and so can do a lot of work with very little + coding. The disadvantage is that is is considerably more complex to + create the start-up script. It is sufficiently complex that is + deserves its own paragraph + +NuttShell Start up Scripts +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First of all you should look at `NSH Start-Up Script <#startupscript>`__ +paragraph. Most everything you need to know can be found there. That +information will be repeated and extended here for completeness. + +**NSH Start-Up Script**. NSH supports options to provide a start up +script for NSH. The start-up script contains any command support by NSH +(i.e., that you see when you enter 'nsh> help'). In general this +capability is enabled with ``CONFIG_NSH_ROMFSETC=y``, but has several +other related configuration options as described with the `NSH-specific +configuration settings <#nshconfiguration>`__ paragraph. This capability +also depends on: + + - ``CONFIG_DISABLE_MOUNTPOINT=n``. If mount point support is disabled, + then you cannot mount *any* file systems. + + - ``CONFIG_NFILE_DESCRIPTORS > 4``. Of course you have to have file + descriptions to use any thing in the file system. + + - ``CONFIG_FS_ROMFS`` enabled. This option enables ROMFS file system + support. + +**Default Start-Up Behavior**. The implementation that is provided is +intended to provide great flexibility for the use of Start-Up files. +This paragraph will discuss the general behavior when all of the +configuration options are set to the default values. + +In this default case, enabling ``CONFIG_NSH_ROMFSETC`` will cause NSH to +behave as follows at NSH start-up time: + + - NSH will create a read-only RAM disk (a ROM disk), containing a tiny + ROMFS file system containing the following:: + + `--init.d/ + `-- rcS + + Where ``rcS`` is the NSH start-up script. + + - NSH will then mount the ROMFS file system at ``/etc``, resulting in:: + + |--dev/ + | `-- ram0 + `--etc/ + `--init.d/ + `-- rcS + + - By default, the contents of ``rcS`` script are:: + + # Create a RAMDISK and mount it at /tmp + + mkrd -m 1 -s 512 1024 + mkfatfs /dev/ram1 + mount -t vfat /dev/ram1 /tmp + + - NSH will execute the script at ``/etc/init.d/rcS`` at start-up + (before the first NSH prompt). After execution of the script, the + root FS will look like:: + + |--dev/ + | |-- ram0 + | `-- ram1 + |--etc/ + | `--init.d/ + | `-- rcS + `--tmp/ + +**Example Configurations**. Here are some configurations that have +``CONFIG_NSH_ROMFSETC=y`` in the NuttX configuration file. They might +provide useful examples: + + - ``boards/arm/stm32/hymini-stm32v/nsh2`` + - ``boards/arm/dm320/ntosd-dm320/nsh`` + - ``boards/sim/sim/sim/nsh`` + - ``boards/sim/sim/sim/nsh2`` + - ``boards/sim/sim/sim/nx`` + - ``boards/sim/sim/sim/nx11`` + - ``boards/sim/sim/sim/touchscreen`` + +In most of these cases, the configuration sets up the *default* +``/etc/init.d/rcS`` script. The default script is here: +``apps/nshlib/rcS.template``. (The funny values in the template like +``XXXMKRDMINORXXX`` get replaced via ``sed`` at build time). This +default configuration creates a ramdisk and mounts it at ``/tmp`` as +discussed above. + +If that default behavior is not what you want, then you can provide your +own custom ``rcS`` script by defining ``CONFIG_NSH_ARCHROMFS=y`` in the +configuration file. + +**Modifying the ROMFS Image**. The contents of the ``/etc`` directory +are retained in the file ``apps/nshlib/nsh_romfsimg.h`` OR, if +``CONFIG_NSH_ARCHROMFS`` is defined, +``include/arch/board/nsh_romfsimg.h``. In order to modify the start-up +behavior, there are three things to study: + + #. **Configuration Options.** The additional ``CONFIG_NSH_ROMFSETC`` + configuration options discussed with the other `NSH-specific + configuration settings <#nshconfiguration>`__. + + #. ``tools/mkromfsimg.sh`` **Script**. The script + ``tools/mkromfsimg.sh`` creates ``nsh_romfsimg.h``. It is not + automatically executed. If you want to change the configuration + settings associated with creating and mounting the ``/tmp`` + directory, then it will be necessary to re-generate this header file + using the ``tools/mkromfsimg.sh`` script. + + The behavior of this script depends upon several things: + + #. The configuration settings then installed configuration. + + #. The ``genromfs`` tool(available from + `http://romfs.sourceforge.net `__) + or included within the NuttX buildroot toolchain. There is also a + snapshot available in the NuttX tools repository + `here `__. + + #. The ``xxd`` tool that is used to generate the C header files (xxd + is a normal part of a complete Linux or Cygwin installation, + usually as part of the ``vi`` package). + + #. The file ``apps/nshlib/rcS.template`` (OR, if + ``CONFIG_NSH_ARCHROMFS`` is defined + ``include/arch/board/rcs.template``. + + #. ``rcS.template``. The file ``apps/nshlib/rcS.template`` contains the + general form of the ``rcS`` file; configured values are plugged into + this template file to produce the final ``rcS`` file. + + To generate a custom ``rcS`` file a copy of ``rcS.template`` needs to + be placed at ``tools/`` and changed according to the desired start-up + behaviour. Running ``tools/mkromfsimg.h`` creates ``nsh_romfsimg.h`` + which needs to be copied to ``apps/nshlib`` OR if + ``CONFIG_NSH_ARCHROMFS`` is defined to + ``boards////include``. + +``rcS.template``. The default ``rcS.template``, +``apps/nshlib/rcS.template``, generates the standard, default +``apps/nshlib/nsh_romfsimg.h`` file. + +If ``CONFIG_NSH_ARCHROMFS`` is defined in the NuttX configuration file, +then a custom, board-specific ``nsh_romfsimg.h`` file residing in +``boards////include``\ will be used. NOTE when the OS +is configured, ``include/arch/board`` will be linked to +``boards////include``. + +All of the startup-behavior is contained in ``rcS.template``. The role +of ``mkromfsimg.sh`` script is to (1) apply the specific configuration +settings to ``rcS.template`` to create the final ``rcS``, and (2) to +generate the header file ``nsh_romfsimg.h`` containing the ROMFS file +system image. To do this, ``mkromfsimg.sh`` uses two tools that must be +installed in your system: + + #. The ``genromfs`` tool that is used to generate the ROMFS file system + image. + + #. The ``xxd`` tool that is used to create the C header file. diff --git a/doc/components/nsh/login.rst b/doc/components/nsh/login.rst new file mode 100644 index 00000000000..76b23904cbc --- /dev/null +++ b/doc/components/nsh/login.rst @@ -0,0 +1,261 @@ +*********** +Shell Login +*********** + +Enabling Shell Logins +********************* + +NuttShell sessions can be protected by requiring that the user supply +username and password credentials at the beginning of the session. +Logins can be enabled for standard USB or serial consoles with:: + + CONFIG_NSH_CONSOLE_LOGIN=y + +Logins for Telnet sessions can be enabled separately with:: + + CONFIG_NSH_TELNET_LOGIN=y + +Logins can be enabled for either or both session types. On a successful +login, the user will have access to the NSH session:: + + login: admin + password: + User Logged-in! + + NuttShell (NSH) + nsh> + +After each failed login attempt, a delay can be set up. The purpose of +this delay is to discourage attempts to crack the password by brute +force. That delay is configured with:: + + CONFIG_NSH_LOGIN_FAILDELAY=0 + +This setting provides the login failure delay in units of milliseconds. +The system will pause this amount of time after each failed login +attempt. After a certain number of failed login attempts, the session +will be closed. That number is controlled by:: + + CONFIG_NSH_LOGIN_FAILCOUNT=3 + +Verification of Credentials +*************************** + +There are three ways that NSH can be configured to verify user +credentials at login time: + + #. The simplest implementation simply uses fixed login credentials and + is selected with:: + + CONFIG_NSH_LOGIN_FIXED=y + + The fixed login credentials are selected via:: + + CONFIG_NSH_LOGIN_USERNAME=admin + CONFIG_NSH_LOGIN_PASSWORD="Administrator" + + This is not very flexible since there can be only one user and the + password is fixed in the FLASH image. This option is also not very + secure because a malicious user could get the password by just + looking at the ``.text`` stings in the flash image. + + #. NSH can also be configured to defer the entire user credential + verification to platform-specific logic with this setting:: + + CONFIG_NSH_LOGIN_PLATFORM=y + + In this case, NSH will call a platform-specific function to perform + the verification of user credentials. The platform-specific logic + must provide a function with the following prototype: + + .. code-block:: c + + int platform_user_verify(FAR const char *username, FAR const char *password); + + which is prototyped an described in ``apps/include/nsh.h`` and which + may be included like: + + .. code-block:: c + + #include + + An appropriate place to implement this function might be in the + directory ``apps/platform/``. + + #. A final option is to use a password file contained encrypted password + information. This final option is selected with the following and + described in more detail in the following paragraph:: + + CONFIG_NSH_LOGIN_PASSWD=y + +Password Files +************** + +NuttX can also be configured to support a password file, by default at +``/etc/passwd``. This option enables support for a password file:: + + CONFIG_NSH_LOGIN_PASSWD=y + +This options requires that you have selected ``CONFIG_FSUTILS_PASSWD=y`` +to enable the access methods of ``apps/fsutils/passwd``:: + + CONFIG_FSUTILS_PASSWD=y + +And this determines the location of the password file in a mounted +volume:: + + CONFIG_FSUTILS_PASSWD_PATH="/etc/passwd" + +``/etc/passwd`` is a *standard* location, but you will need to locate +the password where ever you have a mounted volume. + +The password file can be a fixed list of users in a ROMFS file system or +a modifiable list maintained in a file in some writable file system. If +the password file lies in a read-only file system like ROMFS, then you +should also indicate that the password file is read-only. + + CONFIG_FSUTILS_PASSWD_READONLY=y + +If the password file is writable, then additional NSH commands will be +enabled to modify the password file: ```useradd`` <#cmduseradd>`__, +```userdel`` <#cmduserdel>`__, and ```passwd`` <#cmdpasswd>`__. If you +do not wish you have these commands available, then they should be +specifically disabled. + +The password file logic requires a few additional settings: + + #. The size of dynamically allocated and freed buffer that is used for + file access:: + + CONFIG_FSUTILS_PASSWD_IOBUFFER_SIZE=512 + + #. And the 128-bit encryption key. The password file currently uses the + Tiny Encryption Algorithm (TEA), but could be extended to use + something more powerful. + + CONFIG_FSUTILS_PASSWD_KEY1=0x12345678 + CONFIG_FSUTILS_PASSWD_KEY2=0x9abcdef0 + CONFIG_FSUTILS_PASSWD_KEY3=0x12345678 + CONFIG_FSUTILS_PASSWD_KEY4=0x9abcdef0 + +Password can only be decrypted with access to this key. Note that this +key could potentially be fished out of your FLASH image, but without any +symbolic information, that would be a difficult job since the TEA KEY is +binary data and not distinguishable from other binary data in the FLASH +image. + +If the password file is enabled (``CONFIG_NSH_LOGIN_PASSWD=y``), then +the fixed user credentials will not be used for the NSH session login. +Instead, the password file will be consulted to verify the user +credentials. + +Creating a Password File for a ROMFS File System +************************************************ + +What we want to accomplish is a ROMFS file system, mounted at ``/etc`` +and containing the password file, ``passwd`` like:: + + NuttShell (NSH) + nsh> ls -Rl /etc + /etc: + dr-xr-xr-x 0 . + dr-xr-xr-x 0 init.d/ + -r--r--r-- 39 passwd + /etc/init.d: + dr-xr-xr-x 0 .. + -r--r--r-- 110 rcS + nsh> + +Where ``/etc/init.d/rcS`` is the start-up script; ``/etc/passwd`` is a +the password file. Note that here we assume that you are already using a +start-up script. We can then piggyback the passwd file into the ``/etc`` +file system already mounted for the NSH start up file as described above +`above <#custinit>`__. + +I use the sim/nsh configuration to create a new password file, but other +configurations could also be used. That configuration already supports a +ROMFS file system, passwords, and login prompts. First, I make these +changes to that configuration. + + #. Disable logins: + + .. code-block:: diff + + - CONFIG_NSH_CONSOLE_LOGIN=y + + # CONFIG_NSH_CONSOLE_LOGIN is not set + # CONFIG_NSH_TELNET_LOGIN is not set + + #. Move the password file to a write-able file system: + + .. code-block:: diff + + - CONFIG_FSUTILS_PASSWD_PATH="/etc/passwd" + + CONFIG_FSUTILS_PASSWD_PATH="/tmp/passwd" + + #. Make the password file modifiable + + .. code-block:: diff + + - CONFIG_FSUTILS_PASSWD_READONLY=y + # CONFIG_FSUTILS_PASSWD_READONLY is not set + +Now rebuild the simulation. No login should be required to enter the +shell and you should find the ```useradd`` <#cmduseradd>`__, +```userdel`` <#cmduserdel>`__, and ```passwd`` <#cmdpasswd>`__ commands +available in the help summary, provided that they are enabled. Make +certain that the ``useradd`` command is not disabled:: + + # CONFIG_NSH_DISABLE_USERADD is not set + +Use the NSH ```useradd`` <#cmduseradd>`__ command to add new uses with +new user passwords like:: + + nsh> useradd + +Do this as many times as you would like. Each time that you do this a +new entry with an encrypted password will be added to the ``passwd`` +file at ``/tmp/passwd``. You can see the content of the password file +like:: + + nsh> cat /tmp/passwd + +When you are finished, you can simply copy the ``/tmp/passwd`` content +from the ``cat`` command and paste it into an editor. Make sure to +remove any carriage returns that may have ended up on the file if you +are using Windows. + +Then create/re-create the ``nsh_romfsimg.h`` file as described below. + + #. The content on the ``nsh_romfsimg.h`` header file is generated from a + template directory structure. Create the directory structure:: + + mkdir etc + mkdir etc/init.d + + And copy your existing startup script into ``etc/init.c`` as ``rcS``. + + #. Save your new password file in the ``etc/`` directory as ``passwd``. + + #. Create the new ROMFS image:: + + genromfs -f romfs_img -d etc -V MyVolName + + #. Convert the ROMFS image to a C header file:: + + xxd -i romfs_img >nsh_romfsimg.h + + #. Edit ``nsh_romfsimg.h``: Mark both data definitions as ``const`` so + that the data will be stored in FLASH. + + #. Edit nsh_romfsimg.h, mark both data definitions as ``const`` so that + that will be stored in FLASH. + +There is a good example of how to do this in the NSH simulation +configuration at +`boards/sim/sim/sim/configs/nsh `__. +The ROMFS support files are provided at +`boards/sim/include `__ +and the +`README.txt `__ +file at the location provides detailed information about creating and +modifying the ROMFS file system. diff --git a/doc/components/nsh/nsh.rst b/doc/components/nsh/nsh.rst new file mode 100644 index 00000000000..89841929186 --- /dev/null +++ b/doc/components/nsh/nsh.rst @@ -0,0 +1,361 @@ +.. include:: /substitutions.rst + +******** +Overview +******** + +**The NSH Library**. The ``apps/nshlib`` sub-directory contains the +NuttShell (NSH) library. This library can easily to linked to +produce a NSH application (See as an example +``apps/examples/nsh``). The NSH Library provides a simple shell +application for NuttX. + +Console/NSH Front End +********************* + +**NSH Consoles**. Using settings in the configuration file, NSH may be +configured to use (1) the serial stdin/out, (2) a USB serial +device (such as CDC/ACM), or (3) a telnet connection as the +console. Or, perhaps even all at once since or BOTH. An indefinite +number of telnet sessions are supported. + +**Start-Up prompt**. When NSH is started, you will see the a welcome +message such the following on the selected console: + +.. code-block:: + + NuttShell (NSH) + nsh> + +The greeting may also include NuttX versioning information if you +are using a versioned copy of NuttX. ``nsh>`` is the NSH prompt +and indicates that you may enter a command from the console. + +**USB console startup**. When using a USB console, the start-up +sequence differs a little: In this case, you are required to press +*ENTER* three times. Then NSH prompt will appear as described +above. This is required for the following reasons: + + #. This assures that the USB connection is stable. The USB + connection may be made, broken, and re-established a few times + if the USB cable is not yet fully seated. Waiting for *ENTER* + to be pressed three times assures that the connection is + stable. + #. The establishment of the connection is two step process: First, + the USB serial connection is made with the host PC. Then the + application that uses the serial interface is started on the + host. When the serial connection is established on the host, + the host operating system may send several *AT* modem commands + to the host depending upon how the host serial port is + configured. By waiting for *ENTER* to be pressed three + consecutive times, all of these modem commands will go to the + bit-bucket and will not be interpreted as NSH command input. + #. Similarly, in the second step when the applications is started, + there may be additional *AT* modem commands sent out the serial + port. Most serial terminal programs will do this unless they + are specifically configured to suppress the modem command + output. Waiting for the *ENTER* input eliminates the invalid + command errors from both (2) and (3). + #. Finally, if NSH did not wait for some positive indication that + the serial terminal program is up and running, then the output + of the NSH greeting and initial NSH prompt would be lost. + +**Extended Command Line Editing**. By default, NuttX uses a simple +command line editor that allows command entry after the ``nsh>`` +and supports only the *backspace* key for editing. However, a more +complete command line editor can be selected by setting +``CONFIG_NSH_CLE=y`` in the NuttX configuration file. When that +option is selected, the following EMACS-like line editing commands +are supported: + +===================== ================================================ +Key Binding Editor Action +===================== ================================================ +``^A`` Move cursor to start of the line +``^B`` Move left one character +``^D`` or *Del* Delete a single character at the cursor position +``^E`` Move cursor to end of current line +``^F`` Move right one character +``^H`` or *Backspace* Delete character, left (backspace) +``^K`` Delete to the end of the line +``^U`` Delete the entire line +===================== ================================================ + +Command Overview +**************** + +**Simple, Re-directed, and Background Commands**. The NuttShell +(NSH) is a simple shell application. NSH supports the following +commands forms: + +=============================== ====================================== +Simple command ```` +Command with re-directed output `` > >> `` +Background command `` &`` +Re-directed background command `` > & >> &`` +=============================== ====================================== + +Where: + + * ```` is any one of the simple commands listed later. + * ```` is the full or relative path to any writable object in the file system name space (file or character driver). Such objects will be referred to simply as files throughout this document. + +``nice`` **'d Background Commands**. NSH executes at the +mid-priority (128). Backgrounded commands can be made to execute +at higher or lower priorities using ``nice``:: + + [nice [-d >]] [> |>> ] [&] + +Where ```` is any value between -20 and 19 where lower +(more negative values) correspond to higher priorities. The +default niceness is 10. + +**Multiple commands per line**. NSH will accept multiple commands +per command line with each command separated with the semi-colon +character (;). + +**Optional Syntax Extensions** Because these features commit +significant resources, they are disabled by default. + + - ``CONFIG_NSH_CMDPARMS``: If selected, then the output from + commands, from file applications, and from NSH built-in + commands can be used as arguments to other commands. The entity + to be executed is identified by enclosing the command line in + back quotes. For example, + + .. code-block:: bash + + set FOO myprogram $BAR + + Will execute the program named ``myprogram`` passing it the + value of the environment variable ``BAR``. The value of the + environment variable ``FOO`` is then set output of + ``myprogram`` on ``stdout``. + + - ``CONFIG_NSH_ARGCAT``: Support concatenation of strings + with environment variables or command output. For example: + + .. code-block:: bash + + set FOO XYZ + set BAR 123 + set FOOBAR ABC_${FOO}_${BAR} + + would set the environment variable ``FOO`` to ``XYZ``, ``BAR`` + to ``123`` and ``FOOBAR`` to ``ABC_XYZ_123``. If + ``CONFIG_NSH_ARGCAT`` is not selected, then a slightly smaller + FLASH footprint results but then also only simple environment + variables like ``$FOO`` can be used on the command line. + + - ``CONFIG_NSH_QUOTE``: Enables back-slash quoting of certain + characters within the command. This option is useful for the + case where an NSH script is used to dynamically generate a new + NSH script. In that case, commands must be treated as simple + text strings without interpretation of any special characters. + Special characters such as ``$``, :literal:`\``, ``"``, and + others must be retained intact as part of the test string. This + option is currently only available is ``CONFIG_NSH_ARGCAT`` is + also selected. + +Conditional Command Execution +***************************** + +An ``if-then[-else]-fi`` construct is also supported in order to +support conditional execution of commands. This works from the +command line but is primarily intended for use within NSH scripts +(see the ```sh`` <#cmdsh>`__ command). The syntax is as follows: + +.. code-block:: bash + + if [!] + then + [sequence of ] + else + [sequence of ] + fi + +Where ```` is a `simple command <#cmdoverview>`__. The +command success value of zero is treated true; a non-zero command +failure value is treated false. The ```test`` <#cmdtest>`__ +command is frequently used for comparisons. + +Looping +******* + +**Looping Constructs**. ``while-do-done`` and ``until-do-done`` +looping constructs are also supported. These work from the command +line but are primarily intended for use within NSH scripts (see +the ```sh`` <#cmdsh>`__ command). + + - ``while-do-done``: Execute ``[sequence of ]`` as long + as ```` has an exit status of zero. The syntax is as + follows: + + .. code-block:: bash + + while + do + [sequence of ] + done + + - ``until-do-done``: Execute ``[sequence of ]`` as long + as ```` has a non-zero exit status. The syntax is as + follows: + + .. code-block:: + + until + do + [sequence of ] + done + +Where ```` is a `simple command <#cmdoverview>`__. The +command success value of zero is treated true; a non-zero command +failure value is treated false. The ```test`` <#cmdtest>`__ +command is frequently used for comparisons. + +**The** ``break`` **Command**. A ``break`` command is also supported. +The ``break`` command is only meaningful within the body of the a +``while`` or ``until`` loop, between the ``do`` and ``done`` tokens. +If the ``break`` command is executed within the body of a loop, +the loop will immediately terminate and execution will continue +with the next command immediately following the ``done`` token. + +Built-In Variables +****************** + +====== ==================================================== +``$?`` The result of the last simple command execution. |br| + On backgrounded commands, this variable holds only |br| + the result of spawning the background command. +====== ==================================================== + +Current Working Directory +************************* + +``cd`` **and** ``pwd``. All path arguments to commands may be +either an absolute path or a path relative to the current working +directory. The current working directory is set using the +``cd`` command and can be queried either by using the +``pwd`` command or by using the ``echo $PWD`` command. + +Environment Variables +********************* + +========== ================================================ +``PATH`` The default path in the file systems to look |br| + for executable, binary programs working directory +``PWD`` The current working directory +``OLDPWD`` The previous working directory +========== ================================================ + +NSH Start-Up Script +******************* + +**NSH Start-Up Script**. NSH supports options to provide a start +up script for NSH. In general this capability is enabled with +``CONFIG_NSH_ROMFSETC``, but has several other related +configuration options as described with the `NSH-specific +configuration settings <#nshconfiguration>`__. This capability +also depends on: + + - ``CONFIG_DISABLE_MOUNTPOINT`` not set + - ``CONFIG_NFILE_DESCRIPTORS`` > 4 + - ``CONFIG_FS_ROMFS`` enabled + +**Default Start-Up Behavior**. The implementation that is provided +is intended to provide great flexibility for the use of Start-Up +files. This paragraph will discuss the general behavior when all +of the configuration options are set to the default values. + +In this default case, enabling ``CONFIG_NSH_ROMFSETC`` will cause +NSH to behave as follows at NSH startup time: + + - NSH will create a read-only RAM disk (a ROM disk), containing a + tiny ROMFS file system containing the following:: + + `--init.d/ + `-- rcS + + Where rcS is the NSH start-up script. + + - NSH will then mount the ROMFS file system at ``/etc``, + resulting in:: + + |--dev/ + | `-- ram0 + `--etc/ + `--init.d/ + `-- rcS + + - By default, the contents of rcS script are:: + + # Create a RAMDISK and mount it at XXXRDMOUNTPOINTXXX + + mkrd -m 1 -s 512 1024 + mkfatfs /dev/ram1 + mount -t vfat /dev/ram1 /tmp + + - NSH will execute the script at ``/etc/init.d/rcS`` at start-up + (before the first NSH prompt). After execution of the script, + the root FS will look like:: + + |--dev/ + | |-- ram0 + | `-- ram1 + |--etc/ + | `--init.d/ + | `-- rcS + `--tmp/ + +**Modifying the ROMFS Image**. The contents of the ``/etc`` +directory are retained in the file ``apps/nshlib/nsh_romfsimg.h`` +OR, if ``CONFIG_NSH_ARCHROMFS`` is defined, +``include/arch/board/rcs.template``). In order to modify the +start-up behavior, there are three things to study: + + #. **Configuration Options.** The additional + ``CONFIG_NSH_ROMFSETC`` configuration options discussed with + the other `NSH-specific configuration + settings <#nshconfiguration>`__. + #. `tools/mkromfsimg.sh`` **Script**. The script + ``tools/mkromfsimg.sh`` creates ``nsh_romfsimg.h``. It is not + automatically executed. If you want to change the configuration + settings associated with creating and mounting the ``/tmp`` + directory, then it will be necessary to re-generate this header + file using the ``tools/mkromfsimg.sh`` script. + + The behavior of this script depends upon three things: + + - The configuration settings then installed configuration. + - The ``genromfs`` tool (available from + http://romfs.sourceforge.net). + - The file ``apps/nshlib/rcS.template`` (OR, if + ``CONFIG_NSH_ARCHROMFS`` is defined + ``include/arch/board/rcs.template``. + + #. ``rcS.template``: The file ``apps/nshlib/rcS.template`` + contains the general form of the ``rcS`` file; configured + values are plugged into this template file to produce the final + ``rcS`` file. + +.. note:: + ``apps/nshlib/rcS.template`` generates the standard, + default ``nsh_romfsimg.h`` file. If ``CONFIG_NSH_ARCHROMFS`` is + defined in the NuttX configuration file, then a custom, + board-specific ``nsh_romfsimg.h`` file residing in the + ``boards////include`` directory will be used. + NOTE when the OS is configured, ``include/arch/board`` will be + linked to ``boards////include``. + +All of the startup-behavior is contained in ``rcS.template``. The +role of ``mkromfsimg.sh`` is to (1) apply the specific +configuration settings to ``rcS.template`` to create the final +``rcS``, and (2) to generate the header file ``nsh_romfsimg.h`` +containing the ROMFS file system image. + +**Further Information**. See the section on `Customizing the +NuttShell <#customizingnsh>`__ for additional, more detailed +information about the NSH start-up script and how to modify it. + + diff --git a/doc/components/nxflat.rst b/doc/components/nxflat.rst new file mode 100644 index 00000000000..0a494e9b833 --- /dev/null +++ b/doc/components/nxflat.rst @@ -0,0 +1,469 @@ +====== +NXFLAT +====== + +Overview +======== + +Functionality +------------- + +NXFLAT is a customized and simplified version of binary format +implemented a few years ago called +`XFLAT `__ With the NXFLAT binary format +you will be able to do the following: + + - Place separately linked programs in a file system, and + - Execute those programs by dynamically linking them to the base NuttX + code. + +This allows you to extend the NuttX base code after it has been written +into FLASH. One motivation for implementing NXFLAT is support clean CGI +under an HTTPD server. + +This feature is especially attractive when combined with the NuttX ROMFS +support: ROMFS allows you to execute programs in place (XIP) in flash +without copying anything other than the .data section to RAM. In fact, +the initial NXFLAT release only worked on ROMFS. Later extensions also +support execution NXFLAT binaries from an SRAM copy as well. + +This NuttX feature includes: + + - A dynamic loader that is built into the NuttX core (See + `GIT `__). + - Minor changes to RTOS to support position independent code, and + - A linker to bind ELF binaries to produce the NXFLAT binary format + (See GIT). + +Background +---------- + +NXFLAT is derived from `XFLAT `__. XFLAT +is a toolchain add that provides full shared library and XIP executable +support for processors that have no Memory Management Unit +(MMU:sup:`1`). NXFLAT is greatly simplified for the deeply embedded +environment targeted by Nuttx: + + - NXFLAT does not support shared libraries, because + - NXFLAT does not support *exportation* of symbol values from a module + +Rather, the NXFLAT module only *imports* symbol values. In the NXFLAT +model, the (PIC:sup:`2`) NXFLAT module resides in a FLASH file system +and when it is loaded at run time, it is dynamically linked only to the +(non-PIC) base NuttX code: The base NuttX *exports* a symbol table; the +NXFLAT module *imports* those symbol value to dynamically bind the +module to the base code. + +Limitations +----------- + + - **ROMFS (or RAM mapping) Only**: + The current NXFLAT release will work only with either (1) NXFLAT + executable modules residing on a ROMFS file system, or (2) executables + residing on other file systems provided that CONFIG_FS_RAMMAP is + defined. This limitation is because the loader depends on the capability + to mmap() the code segment. See the NuttX User Guide for further information. + + NUTTX does not provide any general kind of file mapping capability. + In fact, true file mapping is only possible with MCUs that provide an MMU1. + Without an MMU, file system may support eXecution In Place (XIP) to mimic + file mapping. Only the ROMFS file system supports that kind of XIP execution + need by NXFLAT. + + It is also possible to simulate file mapping by allocating memory, copying + the NXFLAT binary file into memory, and executing from the copy of the + executable file in RAM. That capability can be enabled with the CONFIG_FS_RAMMAP + configuration option. With that option enabled, NXFLAT will work that kind + of file system but will require copying of all NXFLAT executables to RAM. + + - **GCC/ARM/Cortex-M3/4 Only**: + At present, the NXFLAT toolchain is only available for ARM and Cortex-M3/4 (thumb2) targets. + + - **Read-Only Data in RAM**: + With older GCC compilers (at least up to 4.3.3), read-only data must + reside in RAM. In code generated by GCC, all data references are + indexed by the PIC2 base register (that is usually R10 or sl for the + ARM processors). The includes read-only data (.rodata). Embedded + firmware developers normally like to keep .rodata in FLASH with + the code sections. But because all data is referenced with the + PIC base register, all of that data must lie in RAM. A NXFLAT + change to work around this is under investigation3. + + Newer GCC compilers (at least from 4.6.3), read-only data is + no long GOT-relative, but is now accessed PC-relative. + With PC relative addressing, read-only data must reside in the I-Space. + + - **Globally Scoped Function Function Pointers**: + If a function pointer is taken to a statically defined function, + then (at least for ARM) GCC will generate a relocation that NXFLAT + cannot handle. The workaround is make all such functions global in + scope. A fix would involve a change to the GCC compiler as described + in Appendix B. + + - **Special Handling of Callbacks**: + Callbacks through function pointers must be avoided or, when + then cannot be avoided, handled very specially. The reason + for this is that the PIC module requires setting of a special + value in a PIC register. If the callback does not set the PIC + register, then the called back function will fail because it + will be unable to correctly access data memory. Special logic + is in place to handle some NuttX callbacks: Signal callbacks + and watchdog timer callbacks. But other callbacks (like those + used with qsort() must be avoided in an NXFLAT module. + +Supported Processors +-------------------- + +As mentioned `above <#limitations>`__, the NXFLAT toolchain is only +available for ARM and Cortex-M3 (thumb2) targets. Furthermore, NXFLAT +has only been tested on the Eagle-100 LMS6918 Cortex-M3 board. + +Development Status +------------------ + +The initial release of NXFLAT was made in NuttX version 0.4.9. Testing +is limited to the tests found under ``apps/examples/nxflat`` in the +source tree. Some known problems exist (see the +`TODO `__ list). As +such, NXFLAT is currently in an early alpha phase. + +NXFLAT Toolchain +================ + +Building the NXFLAT Toolchain +----------------------------- + +In order to use NXFLAT, you must use special NXFLAT tools to create the +binary module in FLASH. To do this, you will need to download the +buildroot package and build it on your Linux or Cygwin machine. The +buildroot can be downloaded from +`Bitbucket.org `__. You +will need version 0.1.7 or later. + +Here are some general build instructions: + +- You must have already configured Nuttx in ``/nuttx`` +- Download the buildroot package ``buildroot-0.x.y`` into + ```` +- Unpack ``/buildroot-0.x.y.tar.gz`` using a command like ``tar zxf buildroot-0.x.y``. This will result in a new directory like ``/buildroot-0.x.y`` +- Move this into position: + ``mv /buildroot-0.x.y``\ /buildroot +- ``cd``\ /buildroot +- Copy a configuration file into the top buildroot directory: + ``cp boards/abc-defconfig-x.y.z .config``. +- Enable building of the NXFLAT tools by ``make menuconfig``. Select to + build the NXFLAT toolchain with GCC (you can also select omit + building GCC with and only build the NXFLAT toolchain for use with + your own GCC toolchain). +- Make the toolchain: ``make``. When the make completes, the tool + binaries will be available under + ``/buildroot/build_abc/staging_dir/bin`` + +mknxflat +-------- + +``mknxflat`` is used to build a *thunk* file. See below +for usage:: + + Usage: mknxflat [options] + + Where options are one or more of the following. Note + that a space is always required between the option and + any following arguments. + + -d Use dynamic symbol table. [symtab] + -f + Take next commands from [cmd-line] + -o + Output to [stdout] + -v Verbose output [no output] + -w Import weakly declared functions, i.e., weakly + declared functions are expected to be provided at + load-time [not imported] + +ldnxflat +-------- + +``ldnxflat`` is use to link your object files along with the *thunk* +file generated by ``mknxflat`` to produce the NXFLAT +binary module. See below for usage:: + + Usage: ldnxflat [options] + + Where options are one or more of the following. Note + that a space is always required between the option and + any following arguments. + + -d Use dynamic symbol table [Default: symtab] + -e + Entry point to module [Default: _start] + -o + Output to [Default: .nxf] + -s + Set stack size to [Default: 4096] + -v Verbose output. If -v is applied twice, additional + debug output is enabled [Default: no verbose output]. + +mksymtab +-------- + +There is a small helper program available in ``nuttx/tools`` call +``mksymtab``. ``mksymtab`` can be sued to generate symbol tables for the +NuttX base code that would be usable by the typical NXFLAT application. +``mksymtab`` builds symbol tables from common-separated value (CSV) +files. In particular, the CSV files: + + #. ``nuttx/syscall/syscall.csv`` that describes the NuttX RTOS + interface, and + #. ``nuttx/libc/libc.csv`` that describes the NuttX C library interface. + #. ``nuttx/libc/math.cvs`` that descirbes any math library. + +:: + + USAGE: ./mksymtab + + Where: + + : The path to the input CSV file + : The path to the output symbol table file + -d : Enable debug output + +For example, + +:: + + cd nuttx/tools + cat ../syscall/syscall.csv ../libc/libc.csv | sort >tmp.csv + ./mksymtab.exe tmp.csv tmp.c + +Making an NXFLAT module +----------------------- + +Below is a snippet from an NXFLAT make file (simplified from NuttX +`Hello, +World! `__ +example). + +* Target 1: + + .. code-block:: makefile + + hello.r1: hello.o + abc-nuttx-elf-ld -r -d -warn-common -o $@ $^ + +* Target 2: + + .. code-block:: makefile + + hello-thunk.S: hello.r1 + mknxflat -o $@ $^ + +* Target 3: + + .. code-block:: makefile + + hello.r2: hello-thunk.S + abc-nuttx-elf-ld -r -d -warn-common -T binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections -o $@ hello.o hello-thunk.o + +* Target 4: + + .. code-block:: makefile + + hello: hello.r2 + ldnxflat -e main -s 2048 -o $@ $^ + +**Target 1**. This target links all of the module's object files +together into one relocatable object. Two relocatable objects will be +generated; this is the first one (hence, the suffic ``.r1``). In this +"Hello, World!" case, there is only a single object file, ``hello.o``, +that is linked to produce the ``hello.r1`` object. + +When the module's object files are compiled, some special compiler +CFLAGS must be provided. First, the option ``-fpic`` is required to tell +the compiler to generate position independent code (other GCC options, +like ``-fno-jump-tables`` might also be desirable). For ARM compilers, +two additional compilation options are required: ``-msingle-pic-base`` +and ``-mpic-register=r10``. + +**Target 2**. Given the ``hello.r1`` relocatable object, this target +will invoke ```mknxflat`` <#mknxflat>`__ to make the *thunk* file, +``hello-thunk.S``. This *thunk* file contains all of the information +needed to create the imported function list. + +**Target 3** This target is similar to **Target 1**. In this case, it +will link together the module's object files (only ``hello.o`` here) +along with the assembled *thunk* file, ``hello-thunk.o`` to create the +second relocatable object, ``hello.r2``. The linker script, +``gnu-nxflat-gotoff.ld`` is required at this point to correctly position +the sections. This linker script produces two segments: An *I-Space* +(Instruction Space) segment containing mostly ``.text`` and a *D-Space* +(Data Space) segment containing ``.got``, ``.data``, and ``.bss`` +sections. The I-Space section must be origined at address 0 (so that the +segment's addresses are really offsets into the I-Space segment) and the +D-Space section must also be origined at address 0 (so that segment's +addresses are really offsets into the I-Space segment). The option +``-no-check-sections`` is required to prevent the linker from failing +because these segments overlap. + +**NOTE:** There are two linker scripts located at ``binfmt/libnxflat/``. + + #. ``binfmt/libnxflat/gnu-nxflat-gotoff.ld``. Older versions of GCC + (at least up to GCC 4.3.3), use GOT-relative addressing to access RO + data. In that case, read-only data (.rodata) must reside in D-Space + and this linker script should be used. + #. ``binfmt/libnxflat/gnu-nxflat-pcrel.ld``. Newer versions of GCC + (at least as of GCC 4.6.3), use PC-relative addressing to access RO + data. In that case, read-only data (.rodata) must reside in I-Space + and this linker script should be used. + +**Target 4**. Finally, this target will use the ``hello.r2`` relocatable +object to create the final, NXFLAT module ``hello`` by executing +``ldnxflat``. + +Binary Loader APIs +================== + +**Relevant Header Files:** + + - The interface to the binary loader is described in the header file + ```include/nuttx/binfmt/binfmt.h``. + A brief summary of the APIs prototyped in that header file are listed + below. + - NXFLAT APIs needed to register NXFLAT as a binary loader appear in + the header file + ``include/nuttx/binfmt/nxflat.h``. + - The format of an NXFLAT object itself is described in the header + file: + ``include/nuttx/binfmt/nxflat.h``. + +**binfmt Registration** These first interfaces are used only by a binary +loader module, such as NXFLAT itself. NXFLAT (or any future binary +loader) calls ``register_binfmt()`` to incorporate itself into the +system. In this way, the binary loader logic is dynamically extensible +to support any kind of loader. Normal application code should not be +concerned with these interfaces. + +.. c:function:: int register_binfmt(FAR struct binfmt_s *binfmt) + + Register a loader for a binary format + + :return: This is a NuttX internal function so it follows the + convention that 0 (``OK``) is returned on success and a + negated errno is returned on failure. + +.. c:function:: int unregister_binfmt(FAR struct binfmt_s *binfmt) + + Register a loader for a binary format + + :return: This is a NuttX internal function so it follows the + convention that 0 (``OK``) is returned on success and a + negated errno is returned on failure. + +**Binary Loader Interfaces**. The remaining APIs are called by user +applications to maintain modules in the file system. + +.. c:function:: int load_module(FAR struct binary_s *bin) + + Load a module into memory, bind it to an exported symbol take, + and prep the module for execution. + + :return: This is a NuttX internal function so it follows the + convention that 0 (``OK``) is returned on success and a + negated errno is returned on failure. + +.. c:function:: int unload_module(FAR struct binary_s *bin) + + Unload a (non-executing) module from memory. If the module + has been started (via :c:func:`exec_module`), calling this + will be fatal. + + :return: This is a NuttX internal function so it follows the + convention that 0 (``OK``) is returned on success and a + negated errno is returned on failure. + +.. c:function:: int exec_module(FAR const struct binary_s *bin) + + Execute a module that has been loaded into memory by + :c:func:`load_module`. + + :return: This is a NuttX internal function so it follows the + convention that 0 (``OK``) is returned on success and a + negated errno is returned on failure. + +Appendix A: No GOT Operation +============================ + +When GCC generate position independent code, new code sections will +appear in your programs. One of these is the GOT (Global Offset Table) +and, in ELF environments, another is the PLT (Procedure Lookup Table. +For example, if your C code generated (ARM) assembly language like this +without PIC: + +.. code-block:: c-objdump + + ldr r1, .L0 /* Fetch the offset to 'x' */ + ldr r0, [r10, r1] /* Load the value of 'x' with PIC offset */ + /* ... */ + .L0: .word x /* Offset to 'x' */ + +Then when PIC is enabled (say with the -fpic compiler option), it will +generate code like this: + +.. code-block:: c-objdump + + ldr r1, .L0 /* Fetch the offset to the GOT entry */ + ldr r1, [r10, r1] /* Fetch the (relocated) address of 'x' from the GOT */ + ldr r0, [r1, #0] /* Fetch the value of 'x' */ + /* ... */ + .L1 .word x(GOT) /* Offset to entry in the GOT */ + +See +`reference `__ + +Notice that the generates an extra level of indirection through the GOT. +This indirection is not needed by NXFLAT and only adds more RAM usage +and execution time. + +NXFLAT (like `XFLAT `__) can work even +better without the GOT. Patches against older version of GCC exist to +eliminate the GOT indirections. Several are available +`here `__ if +you are inspired to port them to a new GCC version. + +Appendix B: PIC Text Workaround +=============================== + +There is a problem with the memory model in GCC that prevents it from +being used as you need to use it in the NXFLAT context. The problem is +that GCC PIC model assumes that the executable lies in a flat, +contiguous (virtual) address space like:: + + Virtual + .text + .got + .data + .bss + +It assumes that the PIC base register (usually r10 for ARM) points to +the base of ``.text`` so that any address in ``.text``, ``.got``, +``.data``, ``.bss`` can be found with an offset from the same base +address. But that is not the memory arrangement that we need in the XIP +embedded environment. We need two memory regions, one in FLASH +containing shared code and on per task in RAM containing task-specific +data:: + + Flash RAM + .text .got + .data + .bss + +The PIC base register needs to point to the base of the ``.got`` and +only addresses in the ``.got``, ``.data``, and ``.bss`` sections can be +accessed as an offset from the PIC base register. See also this `XFLAT +discussion `__. + +Patches against older version of GCC exist to correct this GCC behavior. +Several are available +`here `__ if +you are inspired to port them to a new GCC version. + diff --git a/Documentation/NXOrganization.gif b/doc/components/nxgraphics/NXOrganization.gif similarity index 100% rename from Documentation/NXOrganization.gif rename to doc/components/nxgraphics/NXOrganization.gif diff --git a/Documentation/NuttXScreenShot.jpg b/doc/components/nxgraphics/NuttXScreenShot.jpg similarity index 100% rename from Documentation/NuttXScreenShot.jpg rename to doc/components/nxgraphics/NuttXScreenShot.jpg diff --git a/doc/components/nxgraphics/appendix.rst b/doc/components/nxgraphics/appendix.rst new file mode 100644 index 00000000000..4d510836116 --- /dev/null +++ b/doc/components/nxgraphics/appendix.rst @@ -0,0 +1,657 @@ +======== +Appendix +======== + +``graphics/`` Directory Structure +================================= + +The graphics capability consist both of components internal to the RTOS +and of user-callable interfaces. In the NuttX kernel mode build there +are some components of the graphics subsystem are callable in user mode +and other components that are internal to the RTOS. The directory +``nuttx/graphics`` contains only those components that are internal to +the RTOS. User callable functions must be part of a library that can be +linked against user applications. This user callable interfaces are +provided in sub-directories under ``nuttx/libnx``. + +``libnx/nx`` + Common callable interfaces that are, logically, part of both nxmu and + nxsu. +``graphics/nxglib`` and ``libnx/nxglib`` + The NuttX tiny graphics library. The directory contains generic + utilities support operations on primitive graphics objects and logic + to rasterize directly into a framebuffer or through an LCD driver + interface. It has no concept of windows (other than the one, + framebuffer or LCD window). +``graphics/nxbe`` + This is the *back-end* of a tiny windowing system. It can be used + with either of two front-ends to complete a windowing system (see + ``nxmu`` and ``nxsu`` below). It contains most of the important + window management logic: clipping, window controls, window drawing, + etc. +``graphics/nxmu`` and ``libnx/nxmu`` + This is the NX multi user *front end*. When combined with the generic + *back-end* (``nxbe``), it implements a multi-threaded, multi-user + windowing system. The files in this directory present the window APIs + described in ``include/nuttx/nx/nx.h``. The multi-user front end + includes a graphics server that executes on its own thread; multiple + graphics clients then communicate with the server via a POSIX message + queue to serialize window operations from many threads. +``libnx/nxfonts`` + This is where the NXFONTS implementation resides. This is a + relatively low-level set of charset set/glyph management APIs. See + ``include/nuttx/nx/nxfonts.h``. +``libnx/nxtk`` + This is where the NXTOOLKIT implementation resides. This toolkit is + built on top of NX and works with the multi-user NX front-end. See + ``include/nuttx/nx/nxtk.h``. +``apps/graphics/NxWidgets`` + The `NxWidgets `__ code is provided as a separate + package provided in the ``apps/`` repository. +``graphics/nxterm`` + The NxTerm driver is built on top of NX and works with the multi-user + NX front-end. See ``include/nuttx/nx/nxterm.h``. + +NX Configuration Options +======================== + +General Configuration Settings +------------------------------ + +``CONFIG_NX`` + Enables overall support for graphics library and NX +``CONFIG_NX_RAMBACKED`` + Enables RAM backed window support. If this option is selected, then + windows may be optionally created with a RAM framebuffer backing up + the window content. Rending into the window will result in rending + into the backup framebuffer, then updating the physical display from + the framebuffer. + + The advantage of this option is that the application that manages + window will no longer receive redraw() callbacks. Those calls + normally occur, for example, when a window "above" moves exposing a + portion of the window below. If this option is selected, then the + system will redraw the exposed portion of the window from the backup + framebuffer without intervention of the window applications. This + greatly reduces the complexity of the application and performance of + the window at the expense of increased memory usage. + + An exception is the case when the window is resized to a wider and/or + taller size. In that case, the redraw callback will till occur. It is + necessary in that case to provide new graphic content for the + extended window area. + + Redraw requests in other cases are also suppressed: Changes to window + position, size, etc. + +NXGL Configuration Settings +--------------------------- + +``CONFIG_NX_NPLANES``: + Some YUV color formats requires support for multiple planes, one for + each color component. Unless you have such special hardware, this + value should be undefined or set to 1. +``CONFIG_NX_DISABLE_1BPP``, ``CONFIG_NX_DISABLE_2BPP``, ``CONFIG_NX_DISABLE_4BPP``, ``CONFIG_NX_DISABLE_8BPP`` ``CONFIG_NX_DISABLE_16BPP``, ``CONFIG_NX_DISABLE_24BPP``, and ``CONFIG_NX_DISABLE_32BPP``: + NX supports a variety of pixel depths. You can save some memory by + disabling support for unused color depths. +``CONFIG_NX_PACKEDMSFIRST``: + If a pixel depth of less than 8-bits is used, then NX needs to know + if the pixels pack from the MS to LS or from LS to MS +``CONFIG_NX_LCDDRIVER``: + By default, NX builds to use a framebuffer driver (see + ``include/nuttx/video/fb.h``). If this option is defined, NX will + build to use an LCD driver (see ``include/nuttx/lcd/lcd.h``). +``CONFIG_NX_ANTIALIASING``: + Enable support for anti-aliasing when rendering lines as various + orientations. This option is only available for use with frame buffer + drivers and only with 16-, 24-, or 32-bit RGB color formats. + +Configuration Settings +---------------------- + +``CONFIG_NX_XYINPUT``: + Build in support for an X/Y input such as a mouse or a touscreen. +``CONFIG_NX_KBD``: + Build in support of keypad/keyboard input. +``CONFIG_NX_WRITEONLY``: + Define if the underlying graphics device does not support read + operations. Automatically defined if ``CONFIG_NX_LCDDRIVER`` and + ``CONFIG_LCD_NOGETRUN`` are defined. + +NX Server Configuration Settings +-------------------------------- + +``CONFIG_NX_BLOCKING`` + Open the client message queues in blocking mode. In this case, + ``nx_eventhandler()`` will not return until a message is received and + processed. +``CONFIG_NX_MXSERVERMSGS`` and ``CONFIG_NX_MXCLIENTMSGS`` + Specifies the maximum number of messages that can fit in the message + queues. No additional resources are allocated, but this can be set to + prevent flooding of the client or server with too many messages + (``CONFIG_PREALLOC_MQ_MSGS`` controls how many messages are + pre-allocated). + +NXTK Configuration Settings +--------------------------- + +``CONFIG_NXTK_BORDERWIDTH``: + Specifies the width of the border (in pixels) used with framed + windows. The default is 4. +``CONFIG_NXTK_BORDERCOLOR1``, ``CONFIG_NXTK_BORDERCOLOR2``, and ``CONFIG_NXTK_BORDERCOLOR3``: + Specify the colors of the border used with framed windows. +``CONFIG_NXTK_BORDERCOLOR2`` + The shadow side color and so is normally darker. +``CONFIG_NXTK_BORDERCOLOR3`` + The shiny side color and so is normally brighter. The default is + medium, dark, and light grey, respectively +``CONFIG_NXTK_AUTORAISE``: + If set, a window will be raised to the top if the mouse position is + over a visible portion of the window. Default: A mouse button must be + clicked over a visible portion of the window. + +NXFONTS Configuration Settings +------------------------------ + +``CONFIG_NXFONTS_CHARBITS``: + The number of bits in the character set. Current options are only 7 + and 8. The default is 7. +``CONFIG_NXFONT_SANS17X22``: + This option enables support for a tiny, 17x22 san serif font (font + ``ID FONTID_SANS17X22`` == 14). +``CONFIG_NXFONT_SANS20X26``: + This option enables support for a tiny, 20x26 san serif font (font + ``ID FONTID_SANS20X26`` == 15). +``CONFIG_NXFONT_SANS23X27``: + This option enables support for a tiny, 23x27 san serif font (font + ``ID FONTID_SANS23X27`` == 1). +``CONFIG_NXFONT_SANS22X29``: + This option enables support for a small, 22x29 san serif font (font + ``ID FONTID_SANS22X29`` == 2). +``CONFIG_NXFONT_SANS28X37``: + This option enables support for a medium, 28x37 san serif font (font + ``ID FONTID_SANS28X37`` == 3). +``CONFIG_NXFONT_SANS39X48``: + This option enables support for a large, 39x48 san serif font (font + ``ID FONTID_SANS39X48`` == 4). +``CONFIG_NXFONT_SANS17X23B``: + This option enables support for a tiny, 17x23 san serif bold font + (font ``ID FONTID_SANS17X23B`` == 16). +``CONFIG_NXFONT_SANS20X27B``: + This option enables support for a tiny, 20x27 san serif bold font + (font ``ID FONTID_SANS20X27B`` == 17). +``CONFIG_NXFONT_SANS22X29B``: + This option enables support for a small, 22x29 san serif bold font + (font ID ``FONTID_SANS22X29B`` == 5). +``CONFIG_NXFONT_SANS28X37B``: + This option enables support for a medium, 28x37 san serif bold font + (font ID ``FONTID_SANS28X37B`` == 6). +``CONFIG_NXFONT_SANS40X49B``: + This option enables support for a large, 40x49 san serif bold font + (font ID ``FONTID_SANS40X49B`` == 7). +``CONFIG_NXFONT_SERIF22X29``: + This option enables support for a small, 22x29 font (with serifs) + (font ID ``FONTID_SERIF22X29`` == 8). +``CONFIG_NXFONT_SERIF29X37``: + This option enables support for a medium, 29x37 font (with serifs) + (font ID ``FONTID_SERIF29X37`` == 9). +``CONFIG_NXFONT_SERIF38X48``: + This option enables support for a large, 38x48 font (with serifs) + (font ID ``FONTID_SERIF38X48`` == 10). +``CONFIG_NXFONT_SERIF22X28B``: + This option enables support for a small, 27x38 bold font (with + serifs) (font ID ``FONTID_SERIF22X28B`` == 11). +``CONFIG_NXFONT_SERIF27X38B``: + This option enables support for a medium, 27x38 bold font (with + serifs) (font ID ``FONTID_SERIF27X38B`` == 12). +``CONFIG_NXFONT_SERIF38X49B``: + This option enables support for a large, 38x49 bold font (with + serifs) (font ID ``FONTID_SERIF38X49B`` == 13). + +NxTerm Configuration Settings +----------------------------- + +General NxTerm settings. + +``CONFIG_NXTERM``: + Enables building of the NxTerm driver. + +NxTerm output text/graphics options: + +``CONFIG_NXTERM_BPP``: + Currently, NxTerm supports only a single pixel depth. This + configuration setting must be provided to support that single pixel + depth. Default: The smallest enabled pixel depth. (see + ``CONFIG_NX_DISABLE_*BPP``) +``CONFIG_NXTERM_CURSORCHAR``: + The bitmap code to use as the cursor. Default '_' +``CONFIG_NXTERM_MXCHARS``: + NxTerm needs to remember every character written to the console so + that it can redraw the window. This setting determines the size of + some internal memory allocations used to hold the character data. + Default: 128. +``CONFIG_NXTERM_CACHESIZE``: + NxTerm supports caching of rendered fonts. This font caching is + required for two reasons: (1) First, it improves text performance, + but more importantly (2) it preserves the font memory. Since the NX + server runs on a separate server thread, it requires that the + rendered font memory persist until the server has a chance to render + the font. Unfortunately, the font cache would be quite large if all + fonts were saved. The ``CONFIG_NXTERM_CACHESIZE`` setting will + control the size of the font cache (in number of glyphs). Only that + number of the most recently used glyphs will be retained. Default: + 16. + + NOTE: There can still be a race condition between the NxTerm + driver and the NX task. If you every see character corruption + (especially when printing a lot of data or scrolling), then + increasing the value of ``CONFIG_NXTERM_CACHESIZE`` is something + that you should try. Alternatively, you can reduce the size of + ``CONFIG_MQ_MAXMSGSIZE`` which will force NxTerm task to pace the + server task. ``CONFIG_NXTERM_CACHESIZE`` should be larger than + ``CONFIG_MQ_MAXMSGSIZE`` in any event. + +``CONFIG_NXTERM_LINESEPARATION``: + This the space (in rows) between each row of test. Default: 0 +``CONFIG_NXTERM_NOWRAP``: + By default, lines will wrap when the test reaches the right hand side + of the window. This setting can be defining to change this behavior + so that the text is simply truncated until a new line is encountered. + +NxTerm input options: + +``CONFIG_NXTERM_NXKBDIN``: + Take input from the NX keyboard input callback. By default, keyboard + input is taken from stdin (``/dev/console``). If this option is set, + then the interface\ ``nxterm_kdbin()`` is enabled. That interface may + be driven by window callback functions so that keyboard input *only* + goes to the top window. +``CONFIG_NXTERM_KBDBUFSIZE``: + If ``CONFIG_NXTERM_NXKBDIN`` is enabled, then this value may be used + to define the size of the per-window keyboard input buffer. Default: + 16 +``CONFIG_NXTERM_NPOLLWAITERS``: + The number of threads that can be waiting for read data available. + Default: 4 + +Installing New Fonts +==================== + +**The BDF Font Converter**. There is a tool called *bdf-converter* in +the directory ``tools/.``. The *bdf-converter* program be used to +convert fonts in Bitmap Distribution Format (BDF) into fonts that can be +used in the NX graphics system. The BDF format most well known as a font +format traditionally used for X-11 bitmap fonts. + + A Note about Font Copyrights: My understanding is that the underlying + bitmap font data for traditional fonts cannot be copyrighted (the + same is not true for scalable fonts). This is because a copyright + covers only the form of delivery of the font and not the underlying + font content and, at least for the traditional typefaces, the + underlying font designs are ancient. There could be issues, however, + if you convert from modern, trademarked images. However, remember + that I am a programmer not an attorney and that my knowledge of font + copyright issues is limited to what I glean by Googling. + +**Font Installation Steps**, Below are general instructions for creating +and installing a new font in the NX graphic system. The first two steps +only apply if you are using the BDF font converter program. + +#. Locate a font in BDF format. There are many good BDF bitmap fonts + bundled with X-11. See `this + link `__, as an + example, + +#. Use the *bdf-converter* program to convert the BDF font to the NuttX + font format. This will result in a C header file containing + definitions. That header file should be installed at, for example, + ``graphics/nxfonts/nxfonts_myfont.h``. + +The remaining steps apply however you managed to create the NuttX C font +header file. After you have your C font header file, the next thing to +do is to create a new NuttX configuration variable to select the font. +For example, suppose you define the following variable: +``CONFIG_NXFONT_MYFONT``. Then you would need to: + +3. Define ``CONFIG_NXFONT_MYFONT=y`` in your NuttX configuration file. + +A font ID number has to be assigned for each new font. The font IDs are +defined in the file ``include/nuttx/nx/nxfonts.h``. Those definitions +have to be extended to support your new font. Look at how the font ID +enabled by ``CONFIG_NXFONT_SANS23X27`` is defined and add an ID for +yournew font in a similar fashion: + +4. ``include/nuttx/nx/nxfonts.h``. Add you new font as a possible + system default font: + + .. code-block:: c + + #if defined(CONFIG_NXFONT_SANS23X27) + # define NXFONT_DEFAULT FONTID_SANS23X27 + #elif defined(CONFIG_NXFONT_MYFONT) + # define NXFONT_DEFAULT FONTID_MYFONT + #endif + + Then define the actual font ID. Make sure that the font ID value is + unique: + + .. code-block:: c + + #if defined(CONFIG_NXFONT_SANS23X27) + # define NXFONT_DEFAULT FONTID_SANS23X27 + #elif defined(CONFIG_NXFONT_MYFONT) + # define NXFONT_DEFAULT FONTID_MYFONT + #endif + +New Add the font to the NX build system. There are several files that +you have to modify to do this. Look how the build system uses the font +CONFIG_NXFONT_SANS23X27 for examaples: + +5. ``nuttx/graphics/Makefile``. This file needs logic to + auto-generate a C source file from the header file that you generated + with the *bdf-converter* program. Notice ``NXFONTS_FONTID=2``; this + must be set to the same font ID value that you defined in the + ``include/nuttx/nx/nxfonts.h`` file. + + .. code-block:: makefile + + genfontsources: + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=1 EXTRAFLAGS=$(EXTRAFLAGS) + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + @$(MAKE) -C nxfonts -f Makefile.sources TOPDIR=$(TOPDIR) NXFONTS_FONTID=2 EXTRAFLAGS=$(EXTRAFLAGS) + endif + +6. ``nuttx/graphics/nxfonts/Make.defs``. Set the make variable + ``NXFSET_CSRCS``. ``NXFSET_CSRCS`` determines the name of the font C + file to build when ``NXFONTS_FONTID=2``: + + .. code-block:: makefile + + ifeq ($(CONFIG_NXFONT_SANS23X27),y) + NXFSET_CSRCS += nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(CONFIG_NXFONT_MYFONT),y) + NXFSET_CSRCS += nxfonts_bitmaps_myfont.c + endif + +7. ``nuttx/graphics/nxfonts/Makefile.sources``. This is the Makefile + used in step 5 that will actually generate the font C file. So, given + your NXFONTS_FONTID=2, it needs to determine a prefix to use for + auto-generated variable and function names and (again) the name of + the autogenerated file to create (this must be the same name that was + used in ``nuttx/graphics/nxfonts/Make.defs``): + + .. code-block:: makefile + + ifeq ($(NXFONTS_FONTID),1) + NXFONTS_PREFIX := g_sans23x27_ + GEN_CSRC = nxfonts_bitmaps_sans23x27.c + endif + ifeq ($(NXFONTS_FONTID),2) + NXFONTS_PREFIX := g_myfont_ + GEN_CSRC = nxfonts_bitmaps_myfont.c + endif + +8. ``graphics/nxfonts/nxfonts_bitmaps.c``. This is the file that + contains the generic font structures. It is used as a "template&qout; + file by ``nuttx/graphics/nxfonts/Makefile.sources``\ to create your + customized font data set at build time. + + .. code-block:: c + + #if NXFONTS_FONTID == 1 + # include "nxfonts_sans23x27.h" + #elif NXFONTS_FONTID == 2 + # include "nxfonts_myfont.h" + #else + # error "No font ID specified" + #endif + + Where ``nxfonts_myfont.h`` is the NuttX font file that we generated + in step 2 using the *bdf-converter* tool. + +9. ``graphics/nxfonts/nxfonts_getfont.c``. Finally, we need to + extend the logic that does the run-time font lookups so that can find + our new font. The lookup function is + ```NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid)`` <#nxfgetfonthandle>`__. + Note that the lookup is based on the font ID that was defined in step + 4. The new font information needs to be added to data structures used + by that function: + + .. code-block:: c + + #ifdef CONFIG_NXFONT_SANS23X27 + extern const struct nx_fontpackage_s g_sans23x27_package; + #endif + #ifdef CONFIG_NXFONT_MYFONT + extern const struct nx_fontpackage_s g_myfont_package; + #endif + + static FAR const struct nx_fontpackage_s *g_fontpackages[] = + { + #ifdef CONFIG_NXFONT_SANS23X27 + &g_sans23x27_package, + #endif + #ifdef CONFIG_NXFONT_MYFONT + &g_myfont_package, + #endif + NULL + }; + + +NX Test Coverage +================ + +``apps/examples/nx``. The primary test tool for debugging NX resides +at ``apps/examples/nx``. + +**Building** ``apps/examples/nx``. NX testing was performed using +``apps/examples/nx`` with the Linux/Cygwin-based NuttX simulator. +Configuration files for building this test can be found in +``boards/sim/sim/sim/configs/nx`` and +``boards/sim/sim/sim/configs/nx11``. There are two alternative +configurations for building the simulation: + +#. The configuration using the configuration file at + ``boards/sim/sim/sim/configs/nx/defconfig``. This default + configuration exercises the NX logic a 8 BPP but provides no visual + feedback. In this configuration, a very simple, simulated framebuffer + driver is used that is based upon a simple region of memory posing as + video memory. That default configuration can be built as follows:: + + tools/configure.sh sim:nx + make + ./nuttx + +#. The preferred configuration is at + ``boards/sim/sim/sim/configs/nx11/defconfig``. This configuration + extends the test with a simulated framebuffer driver that uses an X + window as a framebuffer. This is a superior test configuration + because the X window appears at your desktop and you can see the NX + output. This preferred configuration can be built as follows:: + + tools/configure sim:nx11 + make + ./nuttx + + *Update:* The sim target has suffered some bit-rot over the years and + so the following caveats need to be added: + + - The X target builds under recent Cygwin configurations, but does + not execute. (It fails inside of ``XOpenDisplay()``. + + - The X target does not build under current (9.09) Ubuntu + distributions. I needed to make the following changes: + + The build will also fail to locate the X header files unless you + install an X11 development package. + + - The sim target itself is broken under 64-bit Linux. This is + because the sim target is based upon some assembly language + setjmp/longjmp logic that only works on 32-bit systems. + + NOTE: There is a workaround in this case: You can build for 32-bit + execution on a 64-bit machine by adding ``-m3`` to the ``CFLAGS`` + and ``-m32 -m elf_i386`` to the ``LDFLAGS``. The + configuration/build system will do this for you; you simply need + to select ``CONFIG_SIM_M32=y`` in your configuration file. + + - Refer to the readme file in sim configuration + `README.txt `__ + file for additional information. + +**Test Coverage**. At present, ``apps/examples/nx``\ t only exercises a +subset of NX; the remainder is essentially untested. The following table +describes the testing performed on each NX API: + +NXGLIB API Test Coverage +------------------------ + +================================ ==================================== ======== +Function Special Setup/Notes Verified +================================ ==================================== ======== +``nxgl_rgb2yuv()`` . NO +``nxgl_yuv2rgb()`` . NO +``nxgl_rectcopy()`` . YES +``nxgl_rectoffset()`` . YES +``nxgl_vectoradd()`` . YES +``nxgl_vectorsubtract()`` . YES +``nxgl_rectintersect()`` . YES +``nxgl_rectunion()`` . YES +``nxgl_nonintersecting()`` . YES +``nxgl_rectoverlap()`` . YES +``nxgl_rectinside()`` . YES +``nxgl_rectsize()`` . YES +``nxgl_nullrect()`` . YES +``nxgl_runoffset()`` Verified by apps/examples/nxlines. YES +``nxgl_runcopy()`` . NO +``nxgl_trapoffset()`` Verified by apps/examples/nxlines. YES +``nxgl_trapcopy()`` Verified by apps/examples/nxlines. YES +``nxgl_colorcopy`` . YES +``nxgl_splitline`` Verified using apps/examples/nxlines YES + Generally works well, but has some + accuracy/overflow problems wide + lines that are nearly horizontal. + There is a "fudge factor" that seems + to eliminate the problem, but there + could still be issues in some + configurations. +``nxgl_circlepts`` Verified by apps/examples/nxlines. YES +``nxgl_circletraps`` Verified by apps/examples/nxlines. YES +================================ ==================================== ======== + +NX Server Callbacks Test Coverage +--------------------------------- + +============== ==================== ======== +Function Special Setup/Notes Verified +============== ==================== ======== +``redraw()`` . YES +``position()`` . YES +``mousein()`` . YES +``kbdin()`` . YES +============== ==================== ======== + +NX API Test Coverage +-------------------- + +========================= =============================================================== ======== +Function Special Setup/Notes Verified +========================= =============================================================== ======== +``nx_runinstance()`` . YES +``nx_connectinstance()`` . YES +``nx_disconnect()`` . YES +``nx_eventhandler()`` . YES +``nx_eventnotify()`` This is not used in the current version of apps/examples/nx, NO + was tested in a previous version) +``nx_openwindow()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config file`` +``nx_closewindow()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` YES + in the ``/.config`` file +``nx_requestbkgd()`` Verified by ``apps/examples/nxtext`` and YES + ``apps/examples/nxhello``. +``nx_releasebkgd()`` Verified by ``apps/examples/nxtext`` and YES + ``apps/examples/nxhello``. +``nx_getposition()`` . NO +``nx_setposition()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_setsize()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_raise()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_lower()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_modal()`` . NO +``nx_setvisibility()`` Exercized using Twm4Nx YES, Informally +``nx_ishidden()`` Exercized using Twm4Nx YES, Informally +``nx_fill()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_getrectangle()`` . YES +``nx_filltrapezoid()`` Verified by ``apps/examples/nxlines``. YES +``nx_drawline()`` by ``apps/examples/nxlines``. YES +``nx_drawcircle()`` Verified by ``apps/examples/nxlines``. YES +``nx_fillcircle()`` Verified by ``apps/examples/nxlines``. YES +``nx_setbgcolor()`` . YES +``nx_move()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file +``nx_bitmap()`` Change to ``CONFIG_EXAMPLES_NX_RAWWINDOWS=y`` in the YES + ``/.config`` file. +``nx_kbdin()`` . YES +``nx_mousein()`` . YES +========================= =============================================================== ======== + +NXTK API Test Coverage +---------------------- + +============================ ========================= ======== +Function Special Setup/Notes Verified +============================ ========================= ======== +``nxtk_openwindow()`` . YES +``nxtk_closewindow()`` . YES +``nxtk_getposition()`` . NO +``nxtk_setposition()`` . YES +``nxtk_setsize()`` . YES +``nxtk_raise()`` . YES +``nxtk_lower()`` . YES +``nxtk_modal()`` . NO +``nxtk_setvisibility()`` Exercized using Twm4Nx YES, informally +``nxtk_ishidden()`` Exercized using Twm4Nx YES, informally +``nxtk_fillwindow()`` . YES +``nxtk_getwindow()`` . NO +``nxtk_filltrapwindow()`` . NO +``nxtk_drawlinewindow()`` . YES +``nxtk_drawcirclewindow()`` . YES +``nxtk_fillcirclewindow()`` . YES +``nxtk_movewindow()`` . NO +``nxtk_bitmapwindow()`` . YES +``nxtk_opentoolbar()`` . YES +``nxtk_closetoolbar()`` . YES +``nxtk_filltoolbar()`` . YES +``nxtk_gettoolbar()`` . NO +``nxtk_filltraptoolbar()`` . NO +``nxtk_drawlinetoolbar()`` . NO +``nxtk_drawcircletoolbar()`` . NO +``nxtk_fillcircletoolbar()`` . NO +``nxtk_movetoolbar()`` . NO +``nxtk_bitmaptoolbar()`` . NO +============================ ========================= ======== + +NXFONTS API Test Coverage +------------------------- + +======================== ============================= ======== +Function Special Setup/Notes Verified +======================== ============================= ======== +``nxf_getfonthandle()`` . YES +``nxf_getfontset()`` . YES +``nxf_getbitmap()`` . YES +``nxf_convert_2bpp()`` . NO +``nxf_convert_4bpp()`` . NO +``nxf_convert_8bpp()`` Use defconfig when building. YES +``nxf_convert_16bpp()`` . YES +``nxf_convert_24bpp()`` . NO +``nxf_convert_32bpp()`` . YES +======================== ============================= ======== + diff --git a/doc/components/nxgraphics/index.rst b/doc/components/nxgraphics/index.rst new file mode 100644 index 00000000000..1c49a934c1b --- /dev/null +++ b/doc/components/nxgraphics/index.rst @@ -0,0 +1,174 @@ +===================== +NX Graphics Subsystem +===================== + +This document describes the tiny graphics support included in NuttX. It +includes an overview description of that graphics support, detailed +descriptions of the NuttX graphics APIs, and discussion of code +organization, and OS configuration options. + +.. figure:: NuttXScreenShot.jpg + :align: center + + **Figure 1**. This screnshot shows the final frame for the NuttX example + at ``apps/examples/nx`` running on the simulated, Linux x86 platform with + simulated framebuffer output to an X window. This picture shows to framed window + with (blank) toolbars. Each window has displayed text as received from the + NX keyboard interface The second window has just been raised to the top of the display. + +Objectives +========== + +The objective of this development was to provide a tiny windowing system +in the spirit of X, but greatly scaled down and appropriate for most +resource-limited embedded environments. The current NX implementation +supports the general following, high-level features: + +- **Virtual Vertical Graphics Space**. Windows that reside in a + virtual, *vertical* space so that it makes sense to talk about one + window being on top of another and obscuring the window below it. +- **Client/Server Model**. A standard client server/model was adopted. + NX may be considered a server and other logic that presents the + windows are NX clients. +- **Multi-User Support**. NX includes *front-end* logic to support a + separate NX server thread that can serve multiple NX client threads. + The NX is a server thread/daemon the serializes graphics operations + from multiple clients. +- **Minimal Graphics Toolset**. The actual implementation of the + graphics operations is performed by common, *back-end* logic. This + back-end supports only a primitive set of graphic and rendering + operations. +- **Device Interface**. NX supports any graphics device either of two + device interfaces: + + - Any device with random access video memory using the NuttX + framebuffer driver interface (see ``include/nuttx/video/fb.h``). + - Any LCD-like device than can accept raster line *runs* through a + parallel or serial interface (see ``include/nuttx/lcd/lcd.h``). By + default, NX is configured to use the frame buffer driver unless + ``CONFIG_NX_LCDDRIVER`` is defined =y in your NuttX configuration + file. + +- **Transparent to NX Client**. The window client on "sees" the + sub-window that is operates in and does not need to be concerned with + the virtual, vertical space (other that to respond to *redraw* + requests from NX when needed). +- **Framed Windows and Toolbars**. NX also adds the capability to + support windows with frames and toolbars on top of the basic + windowing support. These are windows such as those shown in the + `screenshot <#screenshot>`__ above. These framed windows sub-divide + one one window into three relatively independent subwindows: A frame, + the contained window and an (optional) toolbar window. +- **Mouse Support**. NX provides support for a mouse or other X/Y + pointing devices. APIs are provided to allow external devices to give + X/Y position information and mouse button presses to NX. NX will then + provide the mouse input to the relevant window clients via callbacks. + Client windows only receive the mouse input callback if the mouse is + positioned over a visible portion of the client window; X/Y position + is provided to the client in the relative coordinate system of the + client window. +- **Keyboard input**. NX also supports keyboard/keypad devices. APIs + are provided to allow external devices to give keypad information to + NX. NX will then provide the mouse input to the top window on the + display (the window that has the *focus*) via a callback function. + +Organization +============ + +NX is organized into 6 (and perhaps someday 7 or 8) logical modules. +These logical modules also correspond to the directory organization. +That NuttX directory organization is discussed in `Appendix +B <#grapicsdirs>`__ of this document. The logic modules are discussed in +the following sub-paragraphs. + +.. figure:: NXOrganization.gif + :align: center + +NX Graphics Library (``NXGL``) +------------------------------ + +NXGLIB is a standalone library that contains low-level graphics +utilities and direct framebuffer or LCD rendering logic. NX is built on +top NXGLIB. + +NX (``NXSU`` and ``NXMU``) +-------------------------- + +NX is the tiny NuttX windowing system for raw windows (i.e., simple +regions of graphics memory). NX includes a small-footprint, multi-user +implementation (NXMU as described below). NX can be used without +NxWidgets and without NXTOOLKIT for raw window displays. + +:sup:`1`\ NXMU and NXSU are interchangeable other than (1) certain +start-up and initialization APIs (as described below), and (2) timing. +With NXSU, NX APIs execute immediately; with NXMU, NX APIs defer and +serialize the operations and, hence, introduce different timing and +potential race conditions that you would not experience with NXSU. + +**NXNULL?** At one time, I also envisioned a *NULL* front-end that did +not support windowing at all but, rather, simply provided the entire +framebuffer or LCD memory as one dumb window. This has the advantage +that the same NX APIs can be used on the one dumb window as for the +other NX windows. This would be in the NuttX spirit of scalability. + +However, the same end result can be obtained by using the +```nx_requestbkgd()`` <#nxrequestbkgd>`__ API. It still may be possible +to reduce the footprint in this usage case by developing and even +thinner NXNULL front-end. That is a possible future development. + +NX Tool Kit (``NXTK``) +---------------------- + +NXTK is a s set of C graphics tools that provide higher-level window +drawing operations. This is the module where the framed windows and +toolbar logic is implemented. NXTK is built on top of NX and does not +depend on NxWidgets. + +NX Fonts Support (``NXFONTS``) +------------------------------ + +A set of C graphics tools for present (bitmap) font images. The font +implementation is at a very low level or graphics operation, comparable +to the logic in NXGLIB. NXFONTS does not depend on any NX module other +than some utilities and types from NXGLIB. + +NX Widgets (``NxWidgets``) +-------------------------- + +`NxWidgets `__ is a higher level, C++, object-oriented +library for object-oriented access to graphical "widgets." NxWidgets is +provided as a separate library in the ``apps/`` repository NxWidgets is +built on top of the core NuttX graphics subsystem, but is part of the +application space rather than part of the core OS graphics subsystems. + +Terminal Driver (``NxTerm``) +---------------------------- + +NxTerm is a write-only character device (not shown) that is built on top +of an NX window. This character device can be used to provide ``stdout`` +and ``stderr`` and, hence, can provide the output side of NuttX console. +). + +NX Header Files +=============== + +``include/nuttx/nx/nxglib.h`` + Describes the NXGLIB C interfaces +``include/nuttx/nx/nx.h`` + Describes the NX C interfaces +``include/nutt/nxtk.h`` + Describe the NXTOOLKIT C interfaces +``include/nutt/nxfont.h`` + Describe sthe NXFONT C interfaces + +.. toctree:: + :Caption: User APIs + + nxgl.rst + nx.rst + nxtk.rst + nxfonts.rst + nxcursor.rst + sample.rst + appendix.rst + diff --git a/doc/components/nxgraphics/nx.rst b/doc/components/nxgraphics/nx.rst new file mode 100644 index 00000000000..c21ed181b11 --- /dev/null +++ b/doc/components/nxgraphics/nx.rst @@ -0,0 +1,742 @@ +== +NX +== + +Pre-Processor Definitions +========================= + +The default server message queue name used by the :c:macro:`nx_run` macro: + +.. code-block:: c + + #define NX_DEFAULT_SERVER_MQNAME "/dev/nxs" + +Mouse button bits: + +.. code-block:: c + + #define NX_MOUSE_NOBUTTONS 0x00 + #define NX_MOUSE_LEFTBUTTON 0x01 + #define NX_MOUSE_CENTERBUTTON 0x02 + #define NX_MOUSE_RIGHTBUTTON 0x04 + +NX Types +======== + +The interface to the NX server is managed using a opaque handle: + +.. c:type:: FAR void *NXHANDLE + +The interface to a specific window is managed using an opaque handle: + +.. c:type:: FAR void *NXWINDOW + +These define callbacks that must be provided to :c:func:`nx_openwindow`. +These callbacks will be invoked as part of the processing performed by +:c:func:`nx_eventhandler`. + +.. c:struct:: nx_callback_s + + .. code-block:: c + + struct nx_callback_s + { + void (*redraw)(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, + bool more, FAR void *arg); + void (*position)(NXWINDOW hwnd, FAR const struct nxgl_size_s *size, + FAR const struct nxgl_point_s *pos, + FAR const struct nxgl_rect_s *bounds, + FAR void *arg); + #ifdef CONFIG_NX_XYINPUT + void (*mousein)(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, + uint8_t buttons, FAR void *arg); + #endif + #ifdef CONFIG_NX_KBD + void (*kbdin)(NXWINDOW hwnd, uint8_t nch, FAR const uint8_t *ch, FAR void *arg); + #endif + }; + +Starting the NX Server +====================== + +The *NX Server* is a kernel daemon that receives and serializes graphic +commands. Before you can use the NX graphics system, you must first +start this daemon. There are two ways that this can be done: + +#. The NX server may be started in your board startup logic by simply + calling the function ``nxmu_start()``. The board startup logic + usually resides the the ``boards/arch/chip/board/src`` directory. The + board startup logic can run automatically during the early system if + ``CONFIG_BOARD_LATE_INITIALIZE`` is defined in the configuration. Or, + the board startup logic can execute under control of the application + by calling the ``boardctl(BOARDIOC_INIT, arg)`` OS interface. + + The board initialization logic will run in either case and the simple + call to ``nxmu_start()`` will start the NX server. + +#. The NX server may also be started later by the application via the + ``boardctl(BOARDIOC_NX_START, arg)`` + +.. c:function:: int nxmu_start(int display, int plane); + + Provides a wrapper function to + simplify and standardize the starting of the NX server. + + :param display: The display number to be served by this new NXMU instance. + :param plane: The plane number to use to get information about the display geometry and color format. + + :return: Zero (``OK``) is returned on success. This indicates + that the NX server has been successfully started, is running, and + waiting to accept connections from NX clients. + A negated ``errno`` value is returned on failure. The ``errno`` value + indicates the nature of the failure. + +.. c:function:: void boardctl(...) + + Generic NuttX interface that among + many of it functions, may also be used to start the NX server. + + In a small embedded system, there will typically be a much greater + interaction between application and low-level board features. The + canonically correct to implement such interactions is by implementing a + character driver and performing the interactions via low level + ``ioctl()`` calls. This, however, may not be practical in many cases and + will lead to "correct" but awkward implementations. + + ``boardctl()`` is non-standard OS interface to alleviate the problem. It + basically circumvents the normal device driver ioctl interlace and + allows the application to perform direction IOCTL-like calls to the + board-specific logic. In it is especially useful for setting up board + operational and test configurations. + + When called with the ``cmd`` of ``BOARDIOC_NX_START``, then the + ``boardctl()`` will call ``nxmu_start`` indirectly on behalf of the + application. In this case the ``arg`` parameter is ignored. + + :param cmd: Identifies the board command to be executed + :param arg: The argument that accompanies the command. The nature of the argument + is determined by the specific command. + + :return: On success zero (``OKERROR``) is returned on failure + with the ``errno`` variable set to indicate the nature of the failure. + +NX Server Callbacks +=================== + +.. c:function:: void redraw(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, bool more, FAR void *arg); + + NX requests that the client re-draw the portion of the + window within with rectangle. + + :param hwnd: + The handle created by :c:func:`nx_openwindow` or :c:func:`nx_requestbkgd` + :param rect: + The rectangle that needs to be re-drawn (in window relative + coordinates) + :param more: + true: More re-draw requests will follow + :param arg: + User provided argument (see :c:func:`nx_openwindow`) + +.. c:function:: void position(NXWINDOW hwnd, FAR const struct nxgl_size_s *size, \ + FAR const struct nxgl_point_s *pos, \ + FAR const struct nxgl_rect_s *bounds, \ + FAR void *arg); + + The size or position of the window has changed (or the + window was just created with zero size. + + :param hwnd: + The handle created by :c:func:`nx_openwindow` or :c:func:`nx_requestbkgd` + :param size: + The size of the window + :param pos: + The position of the upper left hand corner of the window on the + overall display + :param bounds: + The bounding rectangle that the describes the entire display + :param arg: + User provided argument (see :c:func:`nx_openwindow`) + +.. c:function:: void mousein(NXWINDOW hwnd, FAR const struct nxgl_point_s *pos, \ + uint8_t buttons, FAR void *arg); + + New mouse data is available for the window + + :param hwnd: + The handle created by :c:func:`nx_openwindow` or :c:func:`nx_requestbkgd` + :param pos: + The (x,y) position of the mouse + :param buttons: + See ``NX_MOUSE_*`` definitions + :param arg: + User provided argument (see :c:func:`nx_openwindow`) + +.. c:var:: void (*kbdin)(NXWINDOW hwnd, uint8_t nch, FAR const uint8_t *ch, FAR void *arg); + + New keyboard/keypad data is available for the window. + + :param hwnd: + The handle created by :c:func:`nx_openwindow` or :c:func:`nx_requestbkgd` + :param nch: + The number of characters that are available in ch[] + :param ch: + The array of characters + :param arg: + User provided argument (see :c:func:`nx_openwindow`) + +.. c:var:: void (*event)(NXWINDOW hwnd, enum nx_event_e event, FAR void *arg1, FAR void *arg2); + + This callback is used to communicate server events to the window listener. + + - ``NXEVENT_BLOCKED``: Window messages are blocked. + This callback is the response from :c:func:`nx_block`, + :c:func:`nxtk_block`. Those blocking interfaces are used + to assure that no further messages are directed to the window. + Receipt of the blocked callback signifies that (1) there are no + further pending callbacks and (2) that the window is now *defunct* + and will receive no further callbacks. This callback supports + coordinated destruction of a window. In the multi-user mode, the + client window logic must stay intact until all of the queued + callbacks are processed. Then the window may be safely closed. + Closing the window prior with pending callbacks can lead to bad + behavior when the callback is executed. + - ``NXEVENT_SYNCHED``: Synchronization handshake + This completes the handshake started by + :c:func:`nx_synch`, or :c:func:`nxtk_synch`. + Those interfaces send a synchronization messages to the NX server + which responds with this event. The sleeping client is awakened and + continues graphics processing, completing the handshake. Due to the + highly asynchronous nature of client-server communications, + synchronization is sometimes necessary to assure that the client and + server are working together properly. + + :param hwnd: + TWindow handle of window receiving the event + :param event: + The server event + :param arg1: + User provided argument (see :c:func:`nx_openwindow`, + :c:func:`nx_requestbkgd`, or :c:func:`nxtk_opentoolbar`) + :param arg2: + TUser provided argument (see :c:func:`nx_block`, :c:func:`nxtk_block`, + :c:func:`nx_synch`, or :c:func:`nxtk_synch`) + +.. c:macro:: nx_run(fb) + + .. code-block:: c + + #define nx_run(fb) nx_runinstance(NX_DEFAULT_SERVER_MQNAME, dev) + +.. c:function:: int nx_runinstance(FAR const char *mqname, FAR struct fb_vtable_s *fb) + + This is the server entry point. It does not return; the + calling thread is dedicated to supporting NX server. + + NOTE that multiple instances of the NX server may run at the same time, + with different callback and message queue names. ``nx_run()`` is simply + a macro that can be used when only one server instance is required. In + that case, a default server name is used. + + :param mqname: The name for the server incoming message queue + :param dev: Framebuffer or LCD driver "object" to be used + + :return: This function usually does not return. If it does + return, it will return ``ERROR`` and ``errno`` will be set + appropriately. + +.. c:macro:: nx_connect(cb) + + .. code-block:: c + + #define nx_connect(cb) nx_connectinstance(NX_DEFAULT_SERVER_MQNAME) + +.. c:function:: NXHANDLE nx_connectinstance(FAR const char *svrmqname); + + Open a connection from a client to the NX server. One + one client connection is normally needed per thread as each connection + can host multiple windows. + + NOTES: + + - This function returns before the connection is fully instantiated. it + is necessary to wait for the connection event before using the + returned handle. + - Multiple instances of the NX server may run at the same time, each + with different message queue names. + - ``nx_connect()`` is simply a macro that can be used when only one + server instance is required. In that case, a default server name is + used. + + :param svrmqname: The name for the server incoming message queue + + :return: Success: A non-NULL handle used with subsequent NX accesses + Failure: NULL is returned and errno is set appropriately. + +.. c:function:: void nx_disconnect(NXHANDLE handle) + + Disconnect a client from the NX server and/or free + resources reserved by :c:func:`nx_connect`/c:func:`nx_connectinstance`. + + :param handle: The handle returned by :c:func:`nx_connectinstance`. + +.. c:function:: int nx_eventhandler(NXHANDLE handle); + + The client code must call this function periodically to + process incoming messages from the server. If ``CONFIG_NX_BLOCKING`` is + defined, then this function not return until a server message is + received. + + When ``CONFIG_NX_BLOCKING`` is not defined, the client must exercise + caution in the looping to assure that it does not eat up all of the CPU + bandwidth calling nx_eventhandler repeatedly. + ```nx_eventnotify()`` <#nxeventnotify>`__ may be called to get a signal + event whenever a new incoming server event is available. + + :param handle: The handle returned by ```nx_connect()`` <#nxconnectinstance>`__. + + :return: + - ``OK``: No errors occurred. If ``CONFIG_NX_BLOCKING`` is defined, + then one or more server messages were processed. + - ``ERROR``: An error occurred and ``errno`` has been set + appropriately. Of particular interest, it will return + ``errno == EHOSTDOWN`` when the server is disconnected. After that + event, the handle can no longer be used. + +.. c:function:: int nx_eventnotify(NXHANDLE handle, int signo); + + Rather than calling :c:func:`nx_eventhandler` periodically, the client may + register to receive a signal when a server event is available. The + client can then call :c:func:nx_eventhandler` only + when incoming events are available. + + The underlying implementation used ``mq_notifiy()`` and, as a result, + the client must observe the rules for using ``mq_notifiy()``: + + - Only one event is signalled. Upon receipt of the signal, if the + client wishes further notifications, it must call + ``nx_eventnotify()`` again. + - The signal will only be issued when the message queue transitions + from empty to not empty. + + :param handle: The handle returned by ```nx_connect()`` <#nxconnectinstance>`__. + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_block(NXWINDOW hwnd, FAR void *arg); + + The response to this function call is two things: (1) + any queued callback messages to the window are 'blocked' and then (2) + also subsequent window messaging is blocked. + + The ``event`` callback with the ``NXEVENT_BLOCKED`` event is the + response from ``nx_block()``. This blocking interface is used to assure + that no further messages are are directed to the window. Receipt of the + ``NXEVENT_BLOCKED`` event signifies that (1) there are no further + pending callbacks and (2) that the window is now *defunct* and will + receive no further callbacks. + + This callback supports coordinated destruction of a window. The client + window logic must stay intact until all of the queued callbacks are + processed. Then the window may be safely closed. Closing the window + prior with pending callbacks can lead to bad behavior when the callback + is executed. + + :param wnd: The window to be blocked + :param arg: An argument that will accompany the block messages (This is ``arg2`` in + the event callback). + + :return: OK on success; ERROR on failure with errno set + appropriately. + +.. c:function:: int nx_synch(NXWINDOW hwnd, FAR void *arg); + + This interface can be used to synchronize the window + client with the NX server. It really just implements an *echo*: A synch + message is sent from the window client to the server which then responds + immediately by sending the ``NXEVENT_SYNCHED`` back to the windows + client. + + Due to the highly asynchronous nature of client-server communications, + ``nx_synch()`` is sometimes necessary to assure that the client and + server are fully synchronized in time. + + Usage by the window client might be something like this: + + .. code-block:: c + + extern bool g_synched; + extern sem_t g_synch_sem; + + g_synched = false; + ret = nx_synch(hwnd, handle); + if (ret < 0) + { + -- Handle the error -- + } + + while (!g_synched) + { + ret = sem_wait(&g_sync_sem); + if (ret < 0) + { + -- Handle the error -- + } + } + + When the window listener thread receives the ``NXEVENT_SYNCHED`` event, + it would set ``g_synched`` to ``true`` and post ``g_synch_sem``, waking + up the above loop. + + :param wnd: The window to be synched + :param arg: An argument that will accompany the synch messages (This is ``arg2`` in the event callback). + + :return: OK on success; ERROR on failure with errno set + appropriately + +.. c:function:: NXWINDOW nx_openwindow(NXHANDLE handle, uint8_t flags, \ + FAR const struct nx_callback_s *cb, \ + FAR void *arg); + + Create a new window. + + :param handle: The handle returned by ```nx_connect()`` <#nxconnectinstance>`__. + :param flags: Optional flags. These include: + - ``NXBE_WINDOW_RAMBACKED``: Creates a RAM backed window. This + option is only valid if ``CONFIG_NX_RAMBACKED`` is enabled. + - ``NXBE_WINDOW_HIDDEN``: The window is create in the HIDDEN state + and can be made visible later with ``nx_setvisibility()``. + + :param cb: Callbacks used to process window events + :param arg: User provided value that will be returned with NX callbacks. + + :return: Success: A non-NULL handle used with subsequent NX accesses + Failure: NULL is returned and errno is set appropriately. + +.. c:function:: int nx_closewindow(NXWINDOW hwnd) + + Destroy a window created by :c:func:`nx_openwindow` window. + + :param hwnd: The handle returned by ```nx_openwindow()`` <#nxopenwindow>`__ that + identifies the window to be destroyed. This handle must not have been + one returned by ```nx_requestbkgd()`` <#nxrequestbkgd>`__. + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_requestbkgd(NXHANDLE handle, \ + FAR const struct nx_callback_s *cb, \ + FAR void *arg); + + NX normally controls a separate window called the + background window. It repaints the window as necessary using only a + solid color fill. The background window always represents the entire + screen and is always below other windows. It is useful for an + application to control the background window in the following + conditions: + + - If you want to implement a windowless solution. The single screen can + be used to create a truly simple graphic environment. + - When you want more on the background than a solid color. For example, + if you want an image in the background, or animations in the + background, or live video, etc. + + This API only requests the handle of the background window. That handle + will be returned asynchronously in a subsequent position and redraw + callbacks. + + Cautions: + + - The following should never be called using the background window. + They are guaranteed to cause severe crashes: :c:func:`nx_setposition`, + :c:func:`nx_setsize`, :c:func:`nx_raise`, or :c:func:`nx_lower`, + :c:func:`nx_modal`, :c:func:`nx_setvisibility`. + - Neither :c:func:`nx_requestbkgd` nor :c:func:`nx_releasebkgd` + should be called more than once. Multiple instances of the + background window are not supported. + + :param handle: The handle returned by ```nx_connect()`` <#nxconnectinstance>`__. + :param cb: Callbacks to use for processing background window events + :param arg: User provided argument (see ```nx_openwindow()`` <#nxopenwindow>`__) + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_releasebkgd(NXWINDOW hwnd) + + Release the background window previously acquired using + :c:func:`nx_requestbkgd` and return control of the background to NX. + + :param handle: The handle returned indirectly by :c:func:`nx_requestbkgd`. + This handle must not have been one created by :c:func:`nx_openwindow`. + + :return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately + +.. c:function:: int nx_getposition(NXWINDOW hwnd) + + Request the position and size information for the + selected window. The values will be return asynchronously through the + client callback function pointer. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd`. + + :return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately + +.. c:function:: int nx_setposition(NXWINDOW hwnd, FAR struct nxgl_point_s *pos) + + Set the position and size for the selected window. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`. + :param pos: The new position of the window + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_setsize(NXWINDOW hwnd, FAR struct nxgl_size_s *size) + + Set the size of the selected window. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`. + :param size: The new size of the window (in pixels). + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_raise(NXWINDOW hwnd) + + Bring the specified window to the top of the display. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`_. + + :return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately + +.. c:function:: int nx_lower(NXWINDOW hwnd); + + Lower the specified window to the bottom of the display. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`. + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_modal(NXWINDOW hwnd, bool modal) + + May be used to either (1) raise a window to the top of + the display and select modal behavior, or (2) disable modal behavior. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`. + :param modal: True: enter modal state; False: leave modal state + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_setvisibility(NXWINDOW hwnd, bool hide); + + Select if the window is visible or hidden. A hidden + window is still present and will update normally, but will not be + visible on the display until it is unhidden. + + :param hwnd: The handle returned by :c:func:`nx_openwindow`. This + handle must not have been created by :c:func:`nx_requestbkgd`. + :param hide: True: Window will be hidden; false: Window will be visible + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: bool nx_ishidden(NXWINDOW hwnd); + + Return true if the window is hidden. + + **NOTE**: There will be a delay between the time that the visibility of + the window is changed via :c:func:`nx_setvisibily` + before that new setting is reported by :c:func:`nx_ishidden`. ``nx_synch()`` + may be used if temporal synchronization is required. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` that + identifies the window to be queried. + + :return: *True*: the window is hidden, *false*: the window is + visible + +.. c:function:: int nx_fill(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, \ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + + Fill the specified rectangle in the window with the + specified color. + + :param hwnd: The handle returned by ```nx_openwindow()`` <#nxopenwindow>`__ or + ```nx_requestbkgd()`` <#nxrequestbkgd>`__ + :param rect: The location to be filled + :param color: The color to use in the fill + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: void nx_getrectangle(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, \ + unsigned int plane, FAR uint8_t *dest, \ + unsigned int deststride); + + Get the raw contents of graphic memory within a + rectangular region. NOTE: Since raw graphic memory is returned, the + returned memory content may be the memory of windows above this one and + may not necessarily belong to this window unless you assure that this is + the top window. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` + :param rect: The location to be copied + :param plane: Specifies the color plane to get from + :param dest: The location to copy the memory region + :param deststride: The width, in bytes, of the dest memory + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_filltrapezoid(NXWINDOW hwnd, FAR const struct nxgl_rect_s *clip, \ + FAR const struct nxgl_trapezoid_s *trap, \ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + + Fill the specified trapezoidal region in the window + with the specified color. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` + :param clip: Clipping rectangle relative to window (may be null) + :param trap: The trapezoidal region to be filled + :param color: The color to use in the fill + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_drawline(NXWINDOW hwnd, FAR struct nxgl_vector_s *vector, \ + nxgl_coord_t width, nxgl_mxpixel_t color[CONFIG_NX_NPLANES], \ + uint8_t caps); + + Fill the specified trapezoidal region in the window + with the specified color. Fill the specified line in the window with the + specified color. This is simply a wrapper that uses :c:func:`nxgl_splitline` + to break the line into trapezoids and then calls :c:func:`nx_filltrapezoid` + to render the line. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` + :param vector: Describes the line to be drawn. + :param width: The width of the line + :param color: The color to use to fill the line + :param caps: Draw a circular cap on the ends of the line to support better line + joins. One of:: + + /* Line caps */ + + #define NX_LINECAP_NONE 0x00, /* No line caps */ + #define NX_LINECAP_PT1 0x01 /* Line cap on pt1 on of the vector only */ + #define NX_LINECAP_PT2 0x02 /* Line cap on pt2 on of the vector only */ + #define NX_LINECAP_BOTH 0x03 /* Line cap on both ends of the vector only */ + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_drawcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, \ + nxgl_coord_t radius, nxgl_coord_t width, \ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + + Draw a circular outline using the specified line + thickness and color. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` + :param center: A pointer to the point that is the center of the circle. + :param radius: The radius of the circle in pixels. + :param width: The width of the line + :param color: The color to use to fill the line + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_fillcircle(NXWINDOW hwnd, FAR const struct nxgl_point_s *center, \ + nxgl_coord_t radius, nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + + Fill a circular region using the specified color. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` + :param center: A pointer to the point that is the center of the circle. + :param radius: The width of the line + :param color: The color to use to fill the circle + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_setbgcolor(NXHANDLE handle, \ + nxgl_mxpixel_t color[CONFIG_NX_NPLANES]); + +Set the color of the background. + +:param handle: The handle created by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` +:param color: The color to use in the background + +:return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_move(NXWINDOW hwnd, FAR const struct nxgl_rect_s *rect, \ + FAR const struct nxgl_point_s *offset); + +Move a rectangular region within the window. + +:param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` that specifies the window within which the move is to be done +:param rect: Describes the (source) rectangular region to move +:param offset: The offset to move the region + +:return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately + +.. c:function:: int nx_bitmap(NXWINDOW hwnd, FAR const struct nxgl_rect_s *dest, \ + FAR const void *src[CONFIG_NX_NPLANES], \ + FAR const struct nxgl_point_s *origin, \ + unsigned int stride); + + Copy a rectangular region of a larger image into the + rectangle in the specified window. + + :param hwnd: The handle returned by :c:func:`nx_openwindow` or + :c:func:`nx_requestbkgd` that specifies the window that will receive the bitmap image. + :param dest: Describes the rectangular on the display that will receive the bit map. + :param src: The start of the source image. This is an array source images of size ``CONFIG_NX_NPLANES`` (probably 1). + :param origin: The origin of the upper, left-most corner of the full bitmap. Both + dest and origin are in window coordinates, however, the origin may + lie outside of the display. + :param stride: The width of the full source image in bytes. + + :return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately + +.. c:function:: int nx_kbdchin(NXHANDLE handle, uint8_t ch); +.. c:function:: int nx_kbdin(NXHANDLE handle, uint8_t nch, FAR const uint8_t *ch); + + Used by a thread or interrupt handler that manages some + kind of keypad hardware to report text information to the NX server. + That text data will be routed by the NX server to the appropriate window + client. + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. c:function:: int nx_mousein(NXHANDLE handle, nxgl_coord_t x, nxgl_coord_t y, uint8_t buttons) + + Used by a thread or interrupt handler that manages some + kind of pointing hardware to report new positional data to the NX + server. That positional data will be routed by the NX server to the + appropriate window client. + + :return: ``OK`` on success; ``ERROR`` on failure with + ``errno`` set appropriately + +.. _nx-tool-kit-nxtk-1: + + diff --git a/doc/components/nxgraphics/nxcursor.rst b/doc/components/nxgraphics/nxcursor.rst new file mode 100644 index 00000000000..77205ab3d05 --- /dev/null +++ b/doc/components/nxgraphics/nxcursor.rst @@ -0,0 +1,50 @@ +================================ +NX Cursor Support (``NXCURSOR``) +================================ + +.. c:function:: int nxcursor_enable(NXHANDLE hnd, bool enable) + + Enable/disable presentation of the cursor. The disabled + cursor still exits and still may be controlled, but is not visible on + the display. + + :param hnd: + The server handle returned by :c:func:`nx_connect`. + :param enable: The new cursor position + + :return: OK on success; ERROR on failure with errno set appropriately. + +.. c:function:: int nxcursor_setimage(NXHANDLE hnd, FAR const struct nx_cursorimage_s *image) + + Set the cursor image. + + The image is provided a a 2-bits-per-pixel image. The two bit incoding + is as following: + + - 00: The transparent background. + - 01: Color1: The main color of the cursor. + - 10: Color2: The color of any border. + - 11: Color3: A blend color for better imaging (fake anti-aliasing). + + **NOTE:** The NX logic will reference the user image buffer repeatedly. + That image buffer must persist for as long as the NX server connection + persists. + + :param hnd: The server handle returned by :c:func:`nx_connect` + :param image: + An instance of ``struct struct nx_cursorimage_s`` that describes the + cursor image. See ```` for the full description + of this structure. + + :return: OK on success; ERROR on failure with errno set appropriately. + +.. c:function:: int nxcursor_setposition(NXHANDLE hnd, FAR const struct nxgl_point_s *pos) + + Move the cursor to the specified position. + + :param hnd: The server handle returned by :c:func:`nx_connect` + :param pos: The new cursor position + + :return: OK on success; ERROR on failure with errno set appropriately. + + diff --git a/doc/components/nxgraphics/nxfonts.rst b/doc/components/nxgraphics/nxfonts.rst new file mode 100644 index 00000000000..98da7d38425 --- /dev/null +++ b/doc/components/nxgraphics/nxfonts.rst @@ -0,0 +1,127 @@ +============================== +NX Fonts Support (``NXFONTS``) +============================== + +NXFONTS types +============= + +.. c:struct:: nx_fontmetric_s + + This structures provides the metrics for one glyph: + + .. code-block:: c + + struct nx_fontmetric_s + { + uint32_t stride : 2; /* Width of one font row in bytes */ + uint32_t width : 6; /* Width of the font in bits */ + uint32_t height : 6; /* Height of the font in rows */ + uint32_t xoffset : 6; /* Top, left-hand corner X-offset in pixels */ + uint32_t yoffset : 6; /* Top, left-hand corner y-offset in pixels */ + uint32_t unused : 6; + }; + +.. c:struct:: nx_fontbitmap_s + + This structure binds the glyph metrics to the glyph bitmap: + + .. code-block:: c + + struct nx_fontbitmap_s + { + struct nx_fontmetric_s metric; /* Character metrics */ + FAR const uint8_t *bitmap; /* Pointer to the character bitmap */ + }; + + +.. c:struct:: nx_fontset_s + + This structure describes one contiguous grouping of glyphs that can be + described by an array starting with encoding ``first`` and extending + through (``first`` + ``nchars`` - 1). + + .. code-block:: c + + struct nx_fontset_s + { + uint8_t first; /* First bitmap character code */ + uint8_t nchars; /* Number of bitmap character codes */ + FAR const struct nx_fontbitmap_s *bitmap; + }; + +.. c:struct:: nx_font_s + + This structure describes the overall fontset. + + .. code-block:: c + + struct nx_font_s + { + uint8_t mxheight; /* Max height of one glyph in rows */ + uint8_t mxwidth; /* Max width of any glyph in pixels */ + uint8_t mxbits; /* Max number of bits per character code */ + uint8_t spwidth; /* The width of a space in pixels */ + }; + +.. c:function:: NXHANDLE nxf_getfonthandle(enum nx_fontid_e fontid); + + Given a numeric font ID, return a handle that may be + subsequently be used to access the font data sets. + + :param fontid: Identifies the font set to use + + :return: A handle that may be subsequently be used to access the font data sets. + +.. c:function:: FAR const struct nx_font_s *nxf_getfontset(NXHANDLE handle); + + Return information about the current font set. + + :param handle: A font handle previously returned by :c:func:`nxf_getfonthandle`. + :return: An instance of ``struct nx_font_s`` describing the font set. + +.. c:function:: FAR const struct nx_fontbitmap_s *nxf_getbitmap(NXHANDLE handle, uint16_t ch) + + Return font bitmap information for the selected + character encoding. + + :param ch: The char code for the requested bitmap. + :param handle: A font handle previously returned by :c:func:`nxf_getfonthandle`. + :return: An instance of :c:struct:`nx_fontbitmap_s` describing the glyph. + +.. c:function:: int nxf_convert_2bpp(FAR uint8_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); + +.. c:function:: int nxf_convert_4bpp(FAR uint8_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); +.. c:function:: int nxf_convert_8bpp(FAR uint8_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); +.. c:function:: int nxf_convert_16bpp(FAR uint16_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); +.. c:function:: int nxf_convert_24bpp(FAR uint32_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); +.. c:function:: int nxf_convert_32bpp(FAR uint32_t *dest, uint16_t height, \ + uint16_t width, uint16_t stride, \ + FAR const struct nx_fontbitmap_s *bm, \ + nxgl_mxpixel_t color); + + Convert the 1BPP font to a new pixel depth. + + :param dest: The destination buffer provided by the caller. + :param height: The max height of the returned char in rows. + :param width: The max width of the returned char in pixels. + :param stride: The width of the destination buffer in bytes. + :param bm: Describes the character glyph to convert + :param color: The color to use for '1' bits in the font bitmap (0 bits are transparent). + + :return: ``OK`` on success; ``ERROR`` on failure with ``errno`` set appropriately. + diff --git a/doc/components/nxgraphics/nxgl.rst b/doc/components/nxgraphics/nxgl.rst new file mode 100644 index 00000000000..45d89cd77cb --- /dev/null +++ b/doc/components/nxgraphics/nxgl.rst @@ -0,0 +1,259 @@ +.. _nx-graphics-library-nxgl-1: + +============================== +NX Graphics Library (``NXGL``) +============================== + +NXGL provides many APIs, some available for use internally by NX and +others for use by applications as well. Only those APIs intended for +application usage are documented here See ``include/nuttx/nx/nxglib.h`` +for the full set of APIs; those APIs might be of interest if you are +rendering directly into framebuffer or LCD memory. + +NXGL Types +---------- + +.. c:type:: nxgl_mxpixel_t + + Holds one device pixel. NXGLIB will select the + smallest size for the ``nxgl_mxpixel_t`` that just contains the pixel: + ``byte`` if 16, 24, and 32 resolution support is disabled, ``uint16_t`` + if 24, and 32 resolution support is disabled, or ``uint32_t``. + +.. c:type:: nxgl_coord_t + + A given coordinate is limited to the screen height an + width. If either of those values exceed 32,767 pixels, then the + following will have to need to change: + +.. c:struct:: nxgl_point_s + + Describes a point on the display: + + .. code-block:: c + + struct nxgl_point_s + { + nxgl_coord_t x; /* X position, range: 0 to screen width - 1 */ + nxgl_coord_t y; /* Y position, range: 0 to screen height - 1 */ + }; + +.. c:struct:: nxgl_size_s + + Describes the size of a rectangular region. + + .. code-block:: c + + struct nxgl_size_s + { + nxgl_coord_t w; /* Width in pixels */ + nxgl_coord_t h; /* Height in rows */ + }; + +.. c:struct:: nxgl_rect_s + + Describes a positioned rectangle on the display. + + .. code-block:: c + + struct nxgl_rect_s + { + struct nxgl_point_s pt1; /* Upper, left-hand corner */ + struct nxgl_point_s pt2; /* Lower, right-hand corner */ + }; + +.. c:struct:: nxgl_run_s + + Describes a run, i.e., a horizontal line. Note + that the start/end positions have fractional precision. This is + necessary for good joining of trapezoids when a more complex shape is + decomposed into trapezoids. + + .. code-block:: c + + struct nxgl_run_s + { + b16_t x1; /* Left X position, range: 0 to x2 */ + b16_t x2; /* Right X position, range: x1 to screen width - 1 */ + nxgl_coord_t y; /* Top Y position, range: 0 to screen height - 1 */ + }; + +.. c:struct:: nxgl_trapezoid_s + + Describes a horizontal trapezoid on the + display in terms the run at the top of the trapezoid and the run at the + bottom. + + .. code-block:: c + + struct nxgl_trapezoid_s + { + struct nxgl_run_s top; /* Top run */ + struct nxgl_run_s bot; /* bottom run */ + }; + +.. c:function:: void nxgl_rgb2yuv(uint8_t r, uint8_t g, uint8_t b, uint8_t *y, uint8_t *u, uint8_t *v) + + Convert 8-bit RGB triplet to 8-bit YUV triplet. + +.. c:function:: void nxgl_yuv2rgb(uint8_t y, uint8_t u, uint8_t v, uint8_t *r, uint8_t *g, uint8_t *b); + + Convert 8-bit YUV triplet to 8-bit RGB triplet. + +.. c:function:: void nxgl_rectcopy(FAR struct nxgl_rect_s *dest, FAR const struct nxgl_rect_s *src) + + This is essentially ``memcpy()``\ for rectangles. We + don't do structure assignments because some compilers are not good at + that. + +.. c:function:: void nxgl_rectoffset(FAR struct nxgl_rect_s *dest, \ + FAR const struct nxgl_rect_s *src, \ + nxgl_coord_t dx, nxgl_coord_t dy); + + Offset the rectangle position by the specified dx, dy + values. + +.. c:function:: void nxgl_vectoradd(FAR struct nxgl_point_s *dest, \ + FAR const struct nxgl_point_s *v1, \ + FAR const struct nxgl_point_s *v2); + + + Add two 2x1 vectors and save the result to a third. + +.. c:function:: void nxgl_vectsubtract(FAR struct nxgl_point_s *dest, \ + FAR const struct nxgl_point_s *v1, \ + FAR const struct nxgl_point_s *v2); + + Add subtract vector ``v2`` from vector ``v1`` and + return the result in vector dest. + +.. c:function:: void nxgl_rectintersect(FAR struct nxgl_rect_s *dest, \ + FAR const struct nxgl_rect_s *src1, \ + FAR const struct nxgl_rect_s *src2); + + Return the rectangle representing the intersection of + the two rectangles. + +.. c:function:: void nxgl_rectunion(FAR struct nxgl_rect_s *dest, \ + FAR const struct nxgl_rect_s *src1, \ + FAR const struct nxgl_rect_s *src2); + + Given two rectangles, ``src1`` and ``src2``, return the + larger rectangle that contains both, ``dest``. + +.. c:function:: void nxgl_nonintersecting(FAR struct nxgl_rect_s result[4], \ + FAR const struct nxgl_rect_s *rect1, \ + FAR const struct nxgl_rect_s *rect2); + + Return the regions of rectangle ``rect1`` that do not + intersect with ``rect2``. This will four rectangles, some of which may + be degenerate (and can be picked off with :c:func:`nxgl_nullrect`). + +.. c:function:: bool nxgl_rectoverlap(FAR struct nxgl_rect_s *rect1, \ + FAR struct nxgl_rect_s *rect2); + + Return true if the two rectangles overlap. + +.. c:function:: bool nxgl_rectinside(FAR const struct nxgl_rect_s *rect, \ + FAR const struct nxgl_point_s *pt); + + Return true if the point ``pt`` lies within ``rect``. + +.. c:function:: void nxgl_rectsize(FAR struct nxgl_size_s *size, \ + FAR const struct nxgl_rect_s *rect); + + Return the size of the specified rectangle. + +.. c:function:: bool nxgl_nullrect(FAR const struct nxgl_rect_s *rect); + + Return true if the area of the retangle is <= 0. + +.. c:function:: void nxgl_runoffset(FAR struct nxgl_run_s *dest, \ + FAR const struct nxgl_run_s *src, \ + nxgl_coord_t dx, nxgl_coord_t dy); + + Offset the run position by the specified ``dx``, ``dy`` + values. + +.. c:function:: void nxgl_runcopy(FAR struct nxgl_run_s *dest, \ + FAR const struct nxgl_run_s *src); + + This is essentially ``memcpy()``\ for runs. We don't do + structure assignments because some compilers are not good at that. + +.. c:function:: void nxgl_trapoffset(FAR struct nxgl_trapezoid_s *dest, \ + FAR const struct nxgl_trapezoid_s *src, \ + nxgl_coord_t dx, nxgl_coord_t dy); + + Offset the trapezoid position by the specified ``dx``, + ``dy`` values. + +.. c:function:: void nxgl_trapcopy(FAR struct nxgl_trapezoid_s *dest, \ + FAR const struct nxgl_trapezoid_s *src); + + This is essentially ``memcpy()``\ for trapezoids. We + don't do structure assignments because some compilers are not good at + that. + +.. c:function:: void nxgl_colorcopy(nxgl_mxpixel_t dest[CONFIG_NX_NPLANES], \ + const nxgl_mxpixel_t src[CONFIG_NX_NPLANES]); + + This is essentially ``memcpy()``\ for colors. This does + very little for us other than hide all of the conditional compilation + for planar colors in one place. + +.. c:function:: int nxgl_splitline(FAR struct nxgl_vector_s *vector, FAR struct nxgl_trapezoid_s *traps, \ + FAR struct nxgl_rect_s *rect, nxgl_coord_t linewidth); + + In the general case, a line with width can be + represented as a parallelogram with a triangle at the top and bottom. + Triangles and parallelograms are both degenerate versions of a + trapezoid. This function breaks a wide line into triangles and + trapezoids. This function also detects other degenerate cases: + + #. If ``y1 == y2`` then the line is horizontal and is better represented + as a rectangle. + #. If ``x1 == x2`` then the line is vertical and also better represented + as a rectangle. + #. If the width of the line is 1, then there are no triangles at the top + and bottom (this may also be the case if the width is narrow and the + line is near vertical). + #. If the line is oriented is certain angles, it may consist only of the + upper and lower triangles with no trapezoid in between. In this case, + 3 trapezoids will be returned, but traps[1] will be degenerate. + + :param vector: A pointer to the vector described the line to be drawn. + :param traps: A pointer to a array of trapezoids (size 3). + :param rect: A pointer to a rectangle. + + :return: + - 0: Line successfully broken up into three trapezoids. Values in traps[0], traps[1], and traps[2] are valid. + - 1: Line successfully represented by one trapezoid. Value in traps[1] is valid. + - 2: Line successfully represented by one rectangle. Value in rect is valid + - <0: On errors, a negated errno value is returned. + +.. c:function:: void nxgl_circlepts(FAR const struct nxgl_point_s *center, nxgl_coord_t radius, \ + FAR struct nxgl_point_s *circle); + + Given a description of a circle, return a set of 16 + points on the circumference of the circle. These points may then be used + by :c:func:`nx_drawcircle` or related APIs to draw a + circle outline. + + :param center: A pointer to the point that is the center of the circle. + :param radius: The radius of the circle in pixels. + :param circle: A pointer the first entry in an array of 16 points where the circle points will be returned. + +.. c:function:: void nxgl_circletraps(FAR const struct nxgl_point_s *center, nxgl_coord_t radius, \ + FAR struct nxgl_trapezoid_s *circle); + + + Given a description of a a circle, return 8 trapezoids + that can be used to fill the circle by + :c:func:`nx_fillcircle` and other interfaces. + + :param center: A pointer to the point that is the center of the circle. + :param radius: The radius of the circle in pixels. + :param circle: A pointer the first entry in an array of 8 trapezoids where the + circle description will be returned. + diff --git a/doc/components/nxgraphics/nxtk.rst b/doc/components/nxgraphics/nxtk.rst new file mode 100644 index 00000000000..89642a4f975 --- /dev/null +++ b/doc/components/nxgraphics/nxtk.rst @@ -0,0 +1,732 @@ +====================== +NX Tool Kit (``NXTK``) +====================== + +NXTK implements where the *framed window*. NX framed windows consist of +three components within one NX window: + + #. The window *border*, + #. The main *client window* area, and + #. A *toolbar* area + +Each sub-window represents a region within one window. `Figure +1 <#screenshot>`__ shows some simple NX framed windows. NXTK allows +these sub-windows to be managed more-or-less independently: + + - Each component has its own callbacks for redraw and position events + as well as mouse and keyboard inputs. The client sub-window callbacks + are registered when the framed window is created with a call to + :c:func:`nxtk_openwindow`; Separate toolbar + sub-window callbacks are reigistered when the toolbar is added using + :c:func:`nxtk_opentoolbar`. (NOTES: (1) only the + client sub-window receives keyboard input and, (2) border callbacks + are not currently accessible by the user). + - All position informational provided within the callback is relative + to the specific sub-window. That is, the origin (0,0) of the + coordinate system for each sub-window begins at the top left + corner of the subwindow. This means that toolbar logic need not + be concerned about client window geometry (and vice versa) and, + for example, common toolbar logic can be used with different windows. + +.. c:type:: FAR void *NXTKWINDOW + + This is the handle that can be used to access the window data region. + +.. c:function:: int nxtk_block(NXWINDOW hwnd, FAR void *arg) + + The response to this function call is two things: (1) + any queued callback messages to the window are 'blocked' and then (2) + also subsequent window messaging is blocked. + + The ``event`` callback with the ``NXEVENT_BLOCKED`` event is the + response from ``nxtk_block()``. This blocking interface is used to + assure that no further messages are are directed to the window. Receipt + of the ``NXEVENT_BLOCKED`` event signifies that (1) there are no further + pending callbacks and (2) that the window is now *defunct* and will + receive no further callbacks. + + This callback supports coordinated destruction of a window. The client + window logic must stay intact until all of the queued callbacks are + processed. Then the window may be safely closed. Closing the window + prior with pending callbacks can lead to bad behavior when the callback + is executed. + + :param wnd: The window to be blocked + :param arg: An argument that will accompany the block messages (This is ``arg2`` in + the event callback). + + :return: OK on success; ERROR on failure with errno set + appropriately. + +2.4.3 ``nxtk_synch()`` +~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** This interface can be used to synchronize the window +client with the NX server. It really just implements an *echo*: A synch +message is sent from the window client to the server which then responds +immediately by sending the ``NXEVENT_SYNCHED`` back to the windows +client. + +Due to the highly asynchronous nature of client-server communications, +``nx_synch()`` is sometimes necessary to assure that the client and +server are fully synchronized in time. + +Usage by the window client might be something like this: + +When the window listener thread receives the ``NXEVENT_SYNCHED`` event, +it would set ``g_synched`` to ``true`` and post ``g_synch_sem``, waking +up the above loop. + +**Input Parameters:** + +``wnd`` + The window to be synched +``arg`` + An argument that will accompany the synch messages (This is ``arg2`` + in the event callback). + +**Returned Value:** OK on success; ERROR on failure with errno set +appropriately + +2.4.4 ``nxtk_openwindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Create a new, framed window. + +**Input Parameters:** + +``handle`` + The handle returned by ```nx_connect()`` <#nxconnectinstance>`__. +``flags`` + Optional flags. These include: + + - ``NXBE_WINDOW_RAMBACKED``: Creates a RAM backed window. This + option is only valid if ``CONFIG_NX_RAMBACKED`` is enabled. + - ``NXBE_WINDOW_HIDDEN``: The window is create in the HIDDEN state + and can be made visible later with ``nxtk_setvisibility()``. + +``cb`` + Callbacks used to process window events +``arg`` + User provided argument (see ```nx_openwindow()`` <#nxopenwindow>`__) + +**Returned Value:** + +2.4.5 ``nxtk_closewindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Close the window opened by +```nxtk_openwindow()`` <#nxtkopenwindow>`__. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.6 ``nxtk_getposition()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Request the position and size information for the +selected framed window. The size/position for the client window and +toolbar will be return asynchronously through the client callback +function pointer. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.7 ``nxtk_setposition()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Set the position for the selected client window. This +position does not include the offsets for the borders nor for any +toolbar. Those offsets will be added in to set the full window position. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``pos`` + The new position of the client sub-window + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.8 ``nxtk_setsize()`` +~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Set the size for the selected client window. This size +does not include the sizes of the borders nor for any toolbar. Those +sizes will be added in to set the full window size. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``size`` + The new size of the client sub-window. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.9 ``nxtk_raise()`` +~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Bring the window containing the specified client +sub-window to the top of the display. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__ specifying the window to + be raised. +```` + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.10 ``nxtk_lower()`` +~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Lower the window containing the specified client +sub-window to the bottom of the display. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__ specifying the window to + be lowered. +```` + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.11 ``nxtk_modal()`` +~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** May be used to either (1) raise a window to the top of +the display and select modal behavior, or (2) disable modal behavior. + +**Input Parameters:** + +``hwnd`` + The handle returned by ```nxtk_openwindow()`` <#nxtkopenwindow>`__ + specifying the window to be modified. +``modal`` + True: enter modal state; False: leave modal state + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.12 ``nxtk_setvisibility()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Select if the window is visible or hidden. A hidden +window is still present and will update normally, but will not be +visible on the display until it is unhidden. + +**Input Parameters:** + +``hwnd`` + The handle returned by ```nxtk_openwindow()`` <#nxtkopenwindow>`__ + specifying the window to be modified. +``hide`` + True: Window will be hidden; false: Window will be visible + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.13 ``nxtk_ishidden()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Return true if the window is hidden. + +**NOTE**: There will be a delay between the time that the visibility of +the window is changed via +```nxtk_setvisibily()`` <#nxtksetvisibility>`__ before that new setting +is reported by ``nxtk_ishidden()``. ``nxtk_synch()`` may be used if +temporal synchronization is required. + +**Input Parameters:** + +``hfwnd`` + The handle returned by ```nxtk_openwindow()`` <#nxtkopenwindow>`__ + that identifies the window to be queried. + +**Returned Value:** *True*: the window is hidden, *false*: the window is +visible + +2.4.14 ``nxtk_fillwindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified rectangle in the client window with +the specified color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``rect`` + The location within the client window to be filled +``color`` + The color to use in the fill + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.15 ``nxtk_getwindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Get the raw contents of graphic memory within a +rectangular region. NOTE: Since raw graphic memory is returned, the +returned memory content may be the memory of windows above this one and +may not necessarily belong to this window unless you assure that this is +the top window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``rect`` + The location within the client window to be retrieved. +``plane`` + Specifies the color plane to get from. +``dest`` + The location to copy the memory region +``deststride`` + The width, in bytes, of the dest memory + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.16 ``nxtk_filltrapwindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified trapezoid in the client window with +the specified color + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``trap`` + The trapezoidal region to be filled. +``color`` + The color to use in the fill. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.17 ``nxtk_drawlinewindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified trapezoidal region in the window +with the specified color. Fill the specified line in the window with the +specified color. This is simply a wrapper that uses ``nxgl_splitline()`` +to break the line into trapezoids and then calls +``nxtk_filltrapwindow()`` to render the line. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``vector`` + Describes the line to be drawn. +``width`` + The width of the line +``color`` + The color to use to fill the line +``caps`` + Draw a circular cap on the ends of the line to support better line + joins. One of: + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.18 ``nxtk_drawcirclewindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Draw a circular outline using the specified line +thickness and color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``center`` + A pointer to the point that is the center of the circle. +``radius`` + The radius of the circle in pixels. +``width`` + The width of the line +``color`` + The color to use to fill the line + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.19 ``nxtk_fillcirclewindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill a circular region using the specified color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``center`` + A pointer to the point that is the center of the circle. +``radius`` + The width of the line +``color`` + The color to use to fill the circle + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.20 ``nxtk_movewindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Move a rectangular region within the client sub-window +of a framed window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__ specifying the client + sub-window within which the move is to be done. +``rect`` + Describes the rectangular region relative to the client sub-window to + move. +``offset`` + The offset to move the region + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.21 ``nxtk_bitmapwindow()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Copy a rectangular region of a larger image into the +rectangle in the specified client sub-window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__ specifying the client + sub-window that will receive the bitmap. +``dest`` + Describes the rectangular region on in the client sub-window will + receive the bit map. +``src`` + The start of the source image(s). This is an array source images of + size ``CONFIG_NX_NPLANES`` (probably 1). +``origin`` + The origin of the upper, left-most corner of the full bitmap. Both + dest and origin are in sub-window coordinates, however, the origin + may lie outside of the sub-window display. +``stride`` + The width of the full source image in pixels. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.22 ``nxtk_opentoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Create a tool bar at the top of the specified framed +window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``height`` + The requested height of the toolbar in pixels. +``cb`` + Callbacks used to process toolbar events. +``arg`` + User provided value that will be returned with toolbar callbacks. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.23 ``nxtk_closetoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Remove the tool bar at the top of the specified framed +window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +```` + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.24 ``nxtk_filltoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified rectangle in the toolbar sub-window +with the specified color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``rect`` + The location within the toolbar window to be filled. +``color`` + The color to use in the fill. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.25 ``nxtk_gettoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Get the raw contents of graphic memory within a +rectangular region. NOTE: Since raw graphic memory is returned, the +returned memory content may be the memory of windows above this one and +may not necessarily belong to this window unless you assure that this is +the top window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``rect`` + The location within the toolbar window to be retrieved. +``plane`` + TSpecifies the color plane to get from. +``dest`` + TThe location to copy the memory region. +``deststride`` + The width, in bytes, of the dest memory. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.26 ``nxtk_filltraptoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified trapezoid in the toolbar sub-window +with the specified color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``trap`` + The trapezoidal region to be filled +``color`` + The color to use in the fill + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.27 ``nxtk_drawlinetoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill the specified line in the toolbar sub-window with +the specified color. This is simply a wrapper that uses +``nxgl_splitline()`` to break the line into trapezoids and then calls +``nxtk_filltraptoolbar()`` to render the line. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``vector`` + Describes the line to be drawn. +``width`` + The width of the line +``color`` + The color to use to fill the line +``caps`` + Draw a circular cap on the ends of the line to support better line + joins. One of: + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.28 ``nxtk_drawcircletoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Draw a circular outline using the specified line +thickness and color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``center`` + A pointer to the point that is the center of the circle. +``radius`` + The radius of the circle in pixels. +``width`` + The width of the line +``color`` + The color to use to fill the line + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.29 ``nxtk_fillcircletoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Fill a circular region using the specified color. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``center`` + A pointer to the point that is the center of the circle. +``radius`` + The width of the line +``color`` + The color to use to fill the circle + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.30 ``nxtk_movetoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Move a rectangular region within the toolbar sub-window +of a framed window. + +**Input Parameters:** + +``hfwnd`` + A handle identifying sub-window containing the toolbar within which + the move is to be done. This handle must have previously been + returned by ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``rect`` + Describes the rectangular region relative to the toolbar sub-window + to move. +``offset`` + The offset to move the region + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +2.4.31 ``nxtk_bitmaptoolbar()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Function Prototype:** + +**Description:** Copy a rectangular region of a larger image into the +rectangle in the specified toolbar sub-window. + +**Input Parameters:** + +``hfwnd`` + A handle previously returned by + ```nxtk_openwindow()`` <#nxtkopenwindow>`__. +``dest`` + Describes the rectangular region on in the toolbar sub-window will + receive the bit map. +``src`` + The start of the source image. +``origin`` + The origin of the upper, left-most corner of the full bitmap. Both + dest and origin are in sub-window coordinates, however, the origin + may lie outside of the sub-window display. +``stride`` + The width of the full source image in bytes. + +**Returned Value:** ``OK`` on success; ``ERROR`` on failure with +``errno`` set appropriately + +.. _nx-fonts-support-nxfonts-1: + + diff --git a/doc/components/nxgraphics/sample.rst b/doc/components/nxgraphics/sample.rst new file mode 100644 index 00000000000..7de9601fe84 --- /dev/null +++ b/doc/components/nxgraphics/sample.rst @@ -0,0 +1,30 @@ +=========== +Sample Code +=========== + +``apps/examples/nx*``. No sample code is provided in this document. +However, examples can be found in the NuttX source tree at the follow +locations: That example code is intended to test NX. Since it is test +code, it is designed to exercise functionality and does not necessarily +represent best NX coding practices. + +- ``apps/examples/nx``. This is a test of windows, optionally with + toolbars. Two windows are created, re-sized, moved, raise lowered. + Simulated mouse and keyboard input is provided. +- ``apps/examples/nxhello``. This is intended to be simplest NX test: + It simply displays the words "Hello, World!" centered on the display. +- ``apps/examples/nxtext``. This illustrates how fonts may be managed + to provide scrolling text windows. Pop-up windows are included to + verify the clipping and re-drawing of the text display. + +In its current form, the NX graphics system provides a low level of +graphics and window support. Most of the complexity of manage redrawing +and handling mouse and keyboard events must be implemented by the NX +client code. + +**Building** ``apps/examples/nx``. Testing was performed using the +Linux/Cygwin-based NuttX simulator. Instructions are provided for +building that simulation are provided in `Appendix C <#testcoverage>`__ +of this document. + + diff --git a/doc/components/nxwidgets.rst b/doc/components/nxwidgets.rst new file mode 100644 index 00000000000..01cba46d561 --- /dev/null +++ b/doc/components/nxwidgets.rst @@ -0,0 +1,59 @@ +========= +NxWidgets +========= + +In order to better support NuttX based platforms, a special graphical +userinterface has been created called NXWidgets. NXWidgets is written in +C++ and integrates seamlessly with the NuttX `NX graphics +subsystem `__ in order to provide graphic +objects, or "widgets," in the NX Graphics Subsystem + +Some of the features of NXWidgets include: + +- **Conservative C++**. NXWidgets is written entirely in C++ but using + only selected "embedded friendly" C++ constructs that are fully + supported under NuttX. No additional C++ support libraries are + required. +- **NX Integration**. NXWidgets integrate seamlessly with the `NX + graphics subsystem `__. Think of the X + server under Linux … the NX graphics system is like a tiny X server + that provides windowing under NuttX. By adding NXWidgets, you can + support graphics objects like buttons and text boxes in the NX + windows and toolbars. +- **Small Footprint**. NXWidgets is tailored for use MCUs in embedded + applications. It is ideally suited for mid- and upper-range of most + MCU families. A complete NXWidgets is possible in as little as 40K of + FLASH and maybe 4K of SRAM. +- **Output Devices**. NXWidgets will work on the high-end frame buffer + devices as well as on LCDs connected via serial or parallel ports to + a small MCU. +- **Input Devices**. NXWidgets will accept position and selection + inputs from a mouse or a touchscreen. It will also support character + input from a keyboard such as a USB keyboard. NXWidgets supports on + very special widget called CKeypad that will provide keyboard input + via an on-screen keypad that can be operated via mouse or touchscreen + inputs. +- **Many Graphic Objects**. Some of the graphic objects supported by + NXWidgets include labels, buttons, text boxes, button arrays, check + boxes, cycle buttons, images, sliders, scrollable list boxes, + progress bars, and more. +- **DOxygen Documentation** DOxygen documentation is available. + +Note: Many of the fundamental classed in NxWidgets derive from the +Antony Dzeryn's "Woopsi" project: http://woopsi.org/ which also has a +BSD style license. See the COPYING file for details. + +NXWidgets DOxygen Documentation +=============================== + +Release notes, DOxygen documentation, as well as downloads for the +latest NxWidgets releases are available online: + +**NxWidgets-1.19**: +`Documentation `__, +`Release +notes `__, +and +`Downloads `__ + +Thanks go to Jose Pablo Carballo for contributing this! diff --git a/doc/components/paging.rst b/doc/components/paging.rst new file mode 100644 index 00000000000..92d9c608f59 --- /dev/null +++ b/doc/components/paging.rst @@ -0,0 +1,423 @@ +================ +On-Demand Paging +================ + +Introduction +============ + +Overview +-------- + +This document summarizes the design of NuttX on-demand paging. This +feature permits embedded MCUs with some limited RAM space to execute +large programs from some non-random access media. + +What kind of platforms can support NuttX on-demang paging? + + #. The MCU should have some large, probably low-cost non-volatile + storage such as serial FLASH or an SD card. This storage probably + does not support non-random access (otherwise, why not just execute + the program directly on the storage media). SD and serial FLASH are + inexpensive and do not require very many pins and SPI support is + prevalent in just about all MCUs. This large serial FLASH would + contain a big program. Perhaps a program of several megabytes in + size. + #. The MCU must have a (relatively) small block of fast SRAM from which + it can execute code. A size of, say 256K (or 192K as in the NXP + LPC3131) would be sufficient for many applications. + #. The MCU has an MMU (again like the NXP LPC3131). + +If the platform meets these requirement, then NuttX can provide +on-demand paging: It can copy .text from the large program in +non-volatile media into RAM as needed to execute a huge program from the +small RAM. + +Terminology +----------- + + ``g_waitingforfill``: + An OS list that is used to hold the TCBs of tasks that are waiting + for a page fill. + ``g_pftcb``: + A variable that holds a reference to the TCB of the thread that is + currently be re-filled. + ``g_pgworker``: + The *process* ID of the thread that will perform the page fills. + ``pg_callback()``: + The callback function that is invoked from a driver when the fill is + complete. + ``pg_miss()``: + The function that is called from architecture-specific code to handle + a page fault. + ``TCB``: + Task Control Block + +NuttX Common Logic Design Description +===================================== + +Initialization +-------------- + +The following declarations will be added. + +- ``g_waitingforfill``. A doubly linked list that will be used to + implement a prioritized list of the TCBs of tasks that are waiting + for a page fill. +- ``g_pgworker``. The *process* ID of the thread that will perform + the page fills + +During OS initialization in ``sched/init/nx_start.c``, the following +steps will be performed: + +- The ``g_waitingforfill`` queue will be initialized. +- The special, page fill worker thread, will be started. The ``pid`` of + the page will worker thread will be saved in ``g_pgworker``. Note + that we need a special worker thread to perform fills; we cannot use + the "generic" worker thread facility because we cannot be assured + that all actions called by that worker thread will always be resident + in memory. + +Declarations for ``g_waitingforfill``, ``g_pgworker``, and other +internal, private definitions will be provided in +``sched/paging/paging.h``. All public definitions that should be used by +the architecture-specific code will be available in +``include/nuttx/page.h``. Most architecture-specific functions are +declared in ``include/nuttx/arch.h``, but for the case of this paging +logic, those architecture specific functions are instead declared in +``include/nuttx/page.h``. + +Page Faults +----------- + +**Page fault exception handling**. Page fault handling is performed by +the function ``pg_miss()``. This function is called from +architecture-specific memory segmentation fault handling logic. This +function will perform the following operations: + +#. **Sanity checking**. This function will ASSERT if the currently + executing task is the page fill worker thread. The page fill worker + thread is how the page fault is resolved and all logic associated + with the page fill worker must be "`locked <#MemoryOrg>`__" and + always present in memory. +#. **Block the currently executing task**. This function will call + ``up_block_task()`` to block the task at the head of the ready-to-run + list. This should cause an interrupt level context switch to the next + highest priority task. The blocked task will be marked with state + ``TSTATE_WAIT_PAGEFILL`` and will be retained in the + ``g_waitingforfill`` prioritized task list. +#. **Boost the page fill worker thread priority**. Check the priority of + the task at the head of the ``g_waitingforfill`` list. If the + priority of that task is higher than the current priority of the page + fill worker thread, then boost the priority of the page fill worker + thread to that priority. Thus, the page fill worker thread will + always run at the priority of the highest priority task that is + waiting for a fill. +#. **Signal the page fill worker thread**. Is there a page already being + filled? If not then signal the page fill worker thread to start + working on the queued page fill requests. + +When signaled from ``pg_miss()``, the page fill worker thread will be +awakenend and will initiate the fill operation. + +**Input Parameters.** None -- The head of the ready-to-run list is +assumed to be that task that caused the exception. The current task +context should already be saved in the TCB of that task. No additional +inputs are required. + +**Assumptions**. + +- It is assumed that this function is called from the level of an + exception handler and that all interrupts are disabled. +- The ``pg_miss()`` must be "`locked <#MemoryOrg>`__" in memory. + Calling ``pg_miss()`` cannot cause a nested page fault. +- It is assumed that currently executing task (the one at the head of + the ready-to-run list) is the one that cause the fault. This will + always be true unless the page fault occurred in an interrupt + handler. Interrupt handling logic must always be available and + "`locked <#MemoryOrg>`__" into memory so that page faults never come + from interrupt handling. +- The architecture-specific page fault exception handling has already + verified that the exception did not occur from interrupt/exception + handling logic. +- As mentioned above, the task causing the page fault must not be the + page fill worker thread because that is the only way to complete the + page fill. + +Fill Initiation +--------------- + +The page fill worker thread will be awakened on one of three conditions: + +- When signaled by ``pg_miss()``, the page fill worker thread will be + awakenend (see above), +- From ``pg_callback()`` after completing last fill (when + ``CONFIG_PAGING_BLOCKINGFILL`` is defined... see below), or +- A configurable timeout expires with no activity. This timeout can be + used to detect failure conditions such things as fills that never + complete. + +The page fill worker thread will maintain a static variable called +``struct tcb_s *g_pftcb``. If no fill is in progress, ``g_pftcb`` will +be NULL. Otherwise, it will point to the TCB of the task which is +receiving the fill that is in progress. + +When awakened from ``pg_miss()``, no fill will be in progress and +``g_pftcb`` will be NULL. In this case, the page fill worker thread will +call ``pg_startfill()``. That function will perform the following +operations: + +- Call the architecture-specific function ``up_checkmapping()`` to see + if the page fill still needs to be performed. In certain conditions, + the page fault may occur on several threads and be queued multiple + times. In this corner case, the blocked task will simply be restarted + (see the logic below for the case of normal completion of the fill + operation). +- Call ``up_allocpage(tcb, &vpage)``. This architecture-specific + function will set aside page in memory and map to virtual address + (vpage). If all available pages are in-use (the typical case), this + function will select a page in-use, un-map it, and make it available. +- Call the architecture-specific function ``up_fillpage()``. Two + versions of the up_fillpage function are supported -- a blocking and + a non-blocking version based upon the configuration setting + ``CONFIG_PAGING_BLOCKINGFILL``. + + - If ``CONFIG_PAGING_BLOCKINGFILL`` is defined, then up_fillpage is + blocking call. In this case, ``up_fillpage()`` will accept only + (1) a reference to the TCB that requires the fill. + Architecture-specific context information within the TCB will be + sufficient to perform the fill. And (2) the (virtual) address of + the allocated page to be filled. The resulting status of the fill + will be provided by return value from ``up_fillpage()``. + - If ``CONFIG_PAGING_BLOCKINGFILL`` is defined, then up_fillpage is + non-blocking call. In this case ``up_fillpage()`` will accept an + additional argument: The page fill worker thread will provide a + callback function, ``pg_callback``. This function is non-blocking, + it will start an asynchronous page fill. After calling the + non-blocking ``up_fillpage()``, the page fill worker thread will + wait to be signaled for the next event -- the fill completion + event. The callback function will be called when the page fill is + finished (or an error occurs). The resulting status of the fill + will be providing as an argument to the callback functions. This + callback will probably occur from interrupt level. + +In any case, while the fill is in progress, other tasks may execute. If +another page fault occurs during this time, the faulting task will be +blocked, its TCB will be added (in priority order) to +``g_waitingforfill``, and the priority of the page worker task may be +boosted. But no action will be taken until the current page fill +completes. NOTE: The IDLE task must also be fully +`locked <#MemoryOrg>`__ in memory. The IDLE task cannot be blocked. It +the case where all tasks are blocked waiting for a page fill, the IDLE +task must still be available to run. + +The architecture-specific functions, ``up_checkmapping()``, +``up_allocpage(tcb, &vpage)`` and ``up_fillpage(page, pg_callback)`` +will be prototyped in ``include/nuttx/arch.h`` + +Fill Complete +------------- + +For the blocking ``up_fillpage()``, the result of the fill will be +returned directly from the call to ``up_fillpage``. + +For the non-blocking ``up_fillpage()``, the architecture-specific driver +call the ``pg_callback()`` that was provided to ``up_fillpage()`` when +the fill completes. In this case, the ``pg_callback()`` will probably be +called from driver interrupt-level logic. The driver will provide the +result of the fill as an argument to the callback function. NOTE: +``pg_callback()`` must also be `locked <#MemoryOrg>`__ in memory. + +In this non-blocking case, the callback ``pg_callback()`` will perform +the following operations when it is notified that the fill has +completed: + +- Verify that ``g_pftcb`` is non-NULL. +- Find the higher priority between the task waiting for the fill to + complete in ``g_pftcb`` and the task waiting at the head of the + ``g_waitingforfill`` list. That will be the priority of he highest + priority task waiting for a fill. +- If this higher priority is higher than current page fill worker + thread, then boost worker thread's priority to that level. Thus, the + page fill worker thread will always run at the priority of the + highest priority task that is waiting for a fill. +- Save the result of the fill operation. +- Signal the page fill worker thread. + +Task Resumption +--------------- + +For the non-blocking ``up_fillpage()``, the page fill worker thread will +detect that the page fill is complete when it is awakened with +``g_pftcb`` non-NULL and fill completion status from ``pg_callback``. In +the non-blocking case, the page fill worker thread will know that the +page fill is complete when ``up_fillpage()`` returns. + +In this either, the page fill worker thread will: + +- Verify consistency of state information and ``g_pftcb``. +- Verify that the page fill completed successfully, and if so, +- Call ``up_unblocktask(g_pftcb)`` to make the task that just received + the fill ready-to-run. +- Check if the ``g_waitingforfill`` list is empty. If not: + + - Remove the highest priority task waiting for a page fill from + ``g_waitingforfill``, + - Save the task's TCB in ``g_pftcb``, + - If the priority of the thread in ``g_pftcb``, is higher in + priority than the default priority of the page fill worker thread, + then set the priority of the page fill worker thread to that + priority. + - Call ``pg_startfill()`` which will start the next fill (as + described above). + +- Otherwise, + + - Set ``g_pftcb`` to NULL. + - Restore the default priority of the page fill worker thread. + - Wait for the next fill related event (a new page fault). + +Architecture-Specific Support Requirements +========================================== + +Memory Organization +------------------- + +**Memory Regions**. Chip specific logic will map the virtual and +physical address spaces into three general regions: + +#. A .text region containing "`locked-in-memory <#MemoryOrg>`__" code + that is always available and will never cause a page fault. This + locked memory is loaded at boot time and remains resident for all + time. This memory regions must include: + + - All logic for all interrupt paths. All interrupt logic must be + locked in memory because the design present here will not support + page faults from interrupt handlers. This includes the page fault + handling logic and ```pg_miss()`` <#PageFaults>`__ that is called + from the page fault handler. It also includes the + ```pg_callback()`` <#FillComplete>`__ function that wakes up the + page fill worker thread and whatever architecture-specific logic + that calls ``pg_callback()``. + - All logic for the IDLE thread. The IDLE thread must always be + ready to run and cannot be blocked for any reason. + - All of the page fill worker thread must be locked in memory. This + thread must execute in order to unblock any thread waiting for a + fill. It this thread were to block, there would be no way to + complete the fills! + +#. A .text region containing pages that can be assigned allocated, + mapped to various virtual addresses, and filled from some mass + storage medium. +#. And a fixed RAM space for .bss, .text, and .heap. + +This memory organization is illustrated in the following table. Notice +that: + +- There is a one-to-one relationship between pages in the virtual + address space and between pages of .text in the non-volatile mass + storage device. +- There are, however, far fewer physical pages available than virtual + pages. Only a subset of physical pages will be mapped to virtual + pages at any given time. This mapping will be performed on-demand as + needed for program execution. + +============================= ============================ ==================== +SRAM Virtual Address Space Non-Volatile Storage +============================= ============================ ==================== +. DATA . +. Virtual Page *n* (*n* > *m*) Stored Page *n* +. Virtual Page *n-1* Stored Page *n-1* +DATA ... ... +Physical Page *m* (*m* < *n*) ... ... +Physical Page *m-1* ... ... +... ... ... +Physical Page *1* Virtual Page *1* Stored Page *1* +Locked Memory Locked Memory Memory Resident +============================= ============================ ==================== + +**Example**. As an example, suppose that the size of the SRAM is 192K +(as in the NXP LPC3131). And suppose further that: + +- The size of the locked, memory resident .text area is 32K, and +- The size of the DATA area is 64K. +- The size of one, managed page is 1K. +- The size of the whole .text image on the non-volatile, mass storage + device is 1024K. + +Then, the size of the locked, memory resident code is 32K (*m*\ =32 +pages). The size of the physical page region is 96K (96 pages), and the +size of the data region is 64 pages. And the size of the virtual paged +region must then be greater than or equal to (1024-32) or 992 pages +(*n*). + +**Building the Locked, In-Memory Image**. One way to accomplish this +would be a two phase link: + +- In the first phase, create a partially linked objected containing all + interrupt/exception handling logic, the page fill worker thread plus + all parts of the IDLE thread (which must always be available for + execution). +- All of the ``.text`` and ``.rodata`` sections of this partial link + should be collected into a single section. +- The second link would link the partially linked object along with the + remaining object to produce the final binary. The linker script + should position the "special" section so that it lies in a reserved, + "non-swappable" region. + +Architecture-Specific Functions +------------------------------- + +Most standard, architecture-specific functions are declared in +``include/nuttx/arch.h``. However, for the case of this paging logic, +the architecture specific functions are declared in +``include/nuttx/page.h``. Standard, architecture-specific functions that +should already be provided in the architecture port. The following are +used by the common paging logic: + +.. c:function:: void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) + + The currently executing task at the head of the ready to run list + must be stopped. Save its context and move it to the inactive list + specified by task_state. This function is called by the on-demand + paging logic in order to block the task that requires the page fill, + and to + +.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb) + + A task is currently in an inactive task list but has been prepped to + execute. Move the TCB to the ready-to-run list, restore its context, + and start execution. This function will be called + +New, additional functions that must be implemented just for on-demand +paging support: + +.. c:function:: int up_checkmapping(FAR struct tcb_s *tcb) + + The function ``up_checkmapping()`` returns an indication if the page + fill still needs to performed or not. In certain conditions, the page + fault may occur on several threads and be queued multiple times. This + function will prevent the same page from be filled multiple times. + +.. c:function:: int up_allocpage(FAR struct tcb_s *tcb, FAR void *vpage) + + This architecture-specific function will set aside page in memory and + map to its correct virtual address. Architecture-specific context + information saved within the TCB will provide the function with the + information needed to identify the virtual miss address. This function + will return the allocated physical page address in ``vpage``. The size + of the underlying physical page is determined by the configuration + setting ``CONFIG_PAGING_PAGESIZE``. NOTE: This function must *always* + return a page allocation. If all available pages are in-use (the typical + case), then this function will select a page in-use, un-map it, and make + it available. + +.. c:function:: int up_fillpage(FAR struct tcb_s *tcb, FAR const void *vpage, void (*pg_callback)(FAR struct tcb_s *tcb, int result)) + + The actual filling of the page with data from the non-volatile, must be + performed by a separate call to the architecture-specific function, + ``up_fillpage()``. This will start asynchronous page fill. The common + paging logic will provide a callback function, ``pg_callback``, that + will be called when the page fill is finished (or an error occurs). This + callback is assumed to occur from an interrupt level when the device + driver completes the fill operation. + diff --git a/Documentation/pm.png b/doc/components/pm.png similarity index 100% rename from Documentation/pm.png rename to doc/components/pm.png diff --git a/doc/components/power.rst b/doc/components/power.rst new file mode 100644 index 00000000000..3a41debd0e3 --- /dev/null +++ b/doc/components/power.rst @@ -0,0 +1,241 @@ +================ +Power Management +================ + +NuttX supports a simple power management (PM) sub-system which: + + - Monitors activity from drivers (and from other parts of the + system), and + + - Provides hooks to place drivers (and the whole system) into + reduce power modes of operation. + +|figure| + +The PM sub-system integrates the MCU idle loop with a collection +of device drivers to support: + + - Reports of relevant driver or other system activity. + + - Registration and callback mechanism to interface with + individual device drivers. + + - IDLE time polling of overall driver activity. + + - Coordinated, global, system-wide transitions to lower power + usage states. + +**Low Power Consumption States**. Various "sleep" and low power +consumption states have various names and are sometimes used in +conflicting ways. In the NuttX PM logic, we will use the following +terminology: + + ``NORMAL`` + The normal, full power operating mode. + ``IDLE`` + This is still basically normal operational mode, the system is, + however, ``IDLE`` and some simple simple steps to reduce power + consumption provided that they do not interfere with normal + Operation. Simply dimming the a backlight might be an example + some that that would be done when the system is idle. + ``STANDBY`` + Standby is a lower power consumption mode that may involve more + extensive power management steps such has disabling clocking or + setting the processor into reduced power consumption modes. In + this state, the system should still be able to resume normal + activity almost immediately. + ``SLEEP`` + The lowest power consumption mode. The most drastic power + reduction measures possible should be taken in this state. It + may require some time to get back to normal operation from + ``SLEEP`` (some MCUs may even require going through reset). + +.. c:enum:: pm_state_e + + These various states are represented with type :c:enum:`pm_state_e` + in ``include/nuttx/power/pm.h``. + +**Power Management Domains**. Each PM interfaces includes a +integer *domain* number. By default, only a single power domain is +supported (``CONFIG_PM_NDOMAINS=1``). But that is configurable; +any number of PM domains can be supported. Multiple PM domains +might be useful, for example, if you would want to control power +states associated with a network separately from power states +associated with a user interface. + +Interfaces +========== + +All PM interfaces are declared in the file ``include/nuttx/power/pm.h``. + +.. c:function:: void pm_initialize(void) + + Called by MCU-specific one-time logic + at power-on-reset in order to initialize the power management + capabilities. This function must be called *very* early in the + initialization sequence *before* any other device drivers are + initialized (since they may attempt to register with the power + management subsystem). + +.. c:function:: int pm_register(FAR struct pm_callback_s *callbacks) + + Called by a device driver in + order to register to receive power management event callbacks. + Refer to the :ref:`components/power:Callbacks` section for more + details. + + :param callbacks: + An instance of :c:struct:`pm_callback_s` + providing the driver callback functions. + + :return: + Zero (``OK``) on success; otherwise a negated + ``errno`` value is returned. + +.. c:function:: int pm_unregister(FAR struct pm_callback_s *callbacks) + + Called by a device driver in + order to unregister previously registered power management event + callbacks. Refer to the :ref:`components/power:Callbacks` section for + more details. + + **Input Parameters:** + + :param callbacks: + An instance of :c:struct:`pm_callback_s` + providing the driver callback functions. + + :return: + Zero (``OK``) on success; otherwise a negated + ``errno`` value is returned. + +.. c:function:: void pm_activity(int domain, int priority) + + Called by a device driver to + indicate that it is performing meaningful activities (non-idle). + This increment an activity count and/or will restart a idle timer + and prevent entering reduced power states. + + :param domain: Identifies the domain of the new PM activity + :param priority: + Activity priority, range 0-9. Larger values correspond to + higher priorities. Higher priority activity can prevent the + system from entering reduced power states for a longer period + of time. As an example, a button press might be higher priority + activity because it means that the user is actively interacting + with the device. + + **Assumptions:** This function may be called from an interrupt + handler (this is the ONLY PM function that may be called from an + interrupt handler!). + +.. c:function:: enum pm_state_e pm_checkstate(int domain) + + Called from the MCU-specific + IDLE loop to monitor the power management conditions. This + function returns the "recommended" power management state based on + the PM configuration and activity reported in the last sampling + periods. The power management state is not automatically changed, + however. The IDLE loop must call :c:func:`pm_changestate` in order to + make the state change. + + These two steps are separated because the platform-specific IDLE + loop may have additional situational information that is not + available to the PM sub-system. For example, the IDLE loop may + know that the battery charge level is very low and may force lower + power states even if there is activity. + + NOTE: That these two steps are separated in time and, hence, the + IDLE loop could be suspended for a long period of time between + calling :c:func:`pm_checkstate` and :c:func:`pm_changestate`. The IDLE + loop may need to make these calls atomic by either disabling + interrupts until the state change is completed. + + :param domain: Identifies the PM domain to check + :return: The recommended power management state. + +.. c:function:: int pm_changestate(int domain, enum pm_state_e newstate) + + This function is used by platform-specific power + management logic. It will announce the power management power + management state change to all drivers that have registered for + power management event callbacks. + + :param domain: Identifies the domain of the new PM state + :param newstate: Identifies the new PM state + + :return: + 0 (``OK``) means that the callback function + for all registered drivers returned ``OK`` (meaning that they + accept the state change). Non-zero means that one of the drivers + refused the state change. In this case, the system will revert to + the preceding state. + + **Assumptions:** It is assumed that interrupts are disabled when + this function is called. This function is probably called from the + IDLE loop... the lowest priority task in the system. Changing + driver power management states may result in renewed system + activity and, as a result, can suspend the IDLE thread before it + completes the entire state change unless interrupts are disabled + throughout the state change. + +Callbacks +========= + + +.. c:struct:: pm_callback_s + + This struct includes the pointers to the driver + callback functions. This structure is defined + ``include/nuttx/power/pm.h``. These callback functions can be used + to provide power management information to the driver. + +.. c:var:: int (*prepare)(FAR struct pm_callback_s *cb, int domain, enum pm_state_e pmstate) + + Request the driver to prepare for a new power + state. This is a warning that the system is about to enter into a + new power state. The driver should begin whatever operations that + may be required to enter power state. The driver may abort the + state change mode by returning a non-zero value from the callback + function. + + :param cb: + Returned to the driver. The driver version of the callback + structure may include additional, driver-specific state data at + the end of the structure. + :param domain: + Identifies the activity domain of the state change + :param pmstate: + Identifies the new PM state + + :return: + Zero (``OK``) means the event was successfully + processed and that the driver is prepared for the PM state change. + Non-zero means that the driver is not prepared to perform the + tasks needed achieve this power setting and will cause the state + change to be aborted. NOTE: The ``prepare()`` method will also be + called when reverting from lower back to higher power consumption + modes (say because another driver refused a lower power state + change). Drivers are not permitted to return non-zero values when + reverting back to higher power consumption modes! + +.. c:var:: void (*notify)(FAR struct pm_callback_s *cb, int domain, enum pm_state_e pmstate) + + Notify the driver of new power state. This + callback is called after all drivers have had the opportunity to + prepare for the new power state. + + :param cb: + Returned to the driver. The driver version of the callback + structure may include additional, driver-specific state data at + the end of the structure. + :param domain: + Identifies the activity domain of the state change + :param pmstate: + Identifies the new PM state + + The driver already agreed to transition + to the low power consumption state when when it returned ``OK`` to + the :c:var:`prepare` call. + +.. |figure| image:: pm.png diff --git a/doc/components/syslog.rst b/doc/components/syslog.rst new file mode 100644 index 00000000000..58b1467cc38 --- /dev/null +++ b/doc/components/syslog.rst @@ -0,0 +1,511 @@ +====== +SYSLOG +====== + + +SYSLOG Interfaces +================= + +Standard SYSLOG Interfaces +-------------------------- + +The NuttX SYSLOG is an architecture for getting debug and status +information from the system. The syslogging interfaces are defined +in the header file ``include/syslog.h``. The primary interface to +SYSLOG sub-system is the function ``syslog()`` and, to a lesser +extent, its companion ``vsyslog()``: + +.. c::function:: int syslog(int priority, FAR const IPTR char *format, ...); + + Generates a log message. The + priority argument is formed by ORing the facility and the level + values (see ``include/syslog.h``). The remaining arguments are a + format, as in ``printf()`` and any arguments to the format. + + The NuttX implementation does not support any special formatting + characters beyond those supported by ``printf()``. + +.. c::function:: void vsyslog(int priority, FAR const IPTR char *src, va_list ap); + + Performs the same task as :c:func:`syslog` + with the difference that it takes a set of arguments which have + been obtained using the ``stdarg`` variable argument list macros. + +.. c::function:: int setlogmask(int mask); + + The additional setlogmask() interface can use use to filter SYSLOG output. + This function sets the logmask and returns the previous mask. + If the mask argument is zero, the current logmask is not modified. + + The SYSLOG priorities are: ``LOG_EMERG``, ``LOG_ALERT``, ``LOG_CRIT``, + ``LOG_ERR``, ``LOG_WARNING``, ``LOG_NOTICE``, ``LOG_INFO``, and ``LOG_DEBUG``. + The bit corresponding to a priority ``p`` is ``LOG_MASK(p)``; ``LOG_UPTO(p)`` + provides the mask of all priorities in the above list up to and including ``p``. + + Per *OpenGroup.org* "If the ``maskpri`` argument is 0, + the current log mask is not modified." In this implementation, + the value zero is permitted in order to disable all SYSLOG levels. + + .. note:: + REVISIT: Per POSIX the SYSLOG mask should be a per-process value but + in NuttX, the scope of the mask is dependent on the nature of the build: + + - *Flat Build*: There is one, global SYSLOG mask that controls + all output. + + - *Protected Build*: There are two SYSLOG masks. One within the + kernel that controls only kernel output. And one in user-space + that controls only user SYSLOG output. + + - *Kernel Build*: The kernel build is compliant with the POSIX + requirement: There will be one mask for for each user process, + controlling the SYSLOG output only form that process. There + will be a separate mask accessible only in the kernel code to + control kernel SYSLOG output. + +The above are all standard interfaces as defined at +`OpenGroup.org `__. +Those interfaces are available for use by application software. +The remaining interfaces discussed in this section are non-standard, OS-internal interfaces. + +Debug Interfaces +---------------- + +In NuttX, syslog output is really synonymous to debug output and, +therefore, the debugging interface macros defined in the header +file ``include/debug.h`` are also syslogging interfaces. Those +macros are simply wrappers around ``syslog()``. The debugging +interfaces differ from the syslog interfaces in that: + + - They do not take a priority parameter; the priority is inherent + in the debug macro name. + + - They decorate the output stream with information such as the + file name + + - They can each be disabled via configuration options. + +Each debug macro has a base name that represents the priority and +a prefix that represents the sub-system. Each macro is +individually initialized by both priority and sub-system. For +example, ``uerr()`` is the macro used for error level messages +from the USB subsystem and is enabled with +``CONFIG_DEBUG_USB_ERROR``. + +The base debug macro names, their priority, and configuration +variable are summarized below: + +- ``info()``. The ``info()`` macro is the lowest priority + (``LOG_INFO``) and is intended to provide general information + about the flow of program execution so that you can get an + overview of the behavior of the program. ``info()`` is often + very chatty and voluminous and usually more information than + you may want to see. The ``info()`` macro is controlled via + CONFIG_DEBUG_subsystem_INFO + +- ``warn()``. The ``warn()`` macro has medium priority + (``LOG_WARN``) and is controlled by + ``CONFIG_DEBUG_subsystem_WARN``. The ``warn()`` is intended to + note exceptional or unexpected conditions that might be + potential errors or, perhaps, minor errors that easily + recovered. + +- ``err()``. This is a high priority debug macro (``LOG_ERROR``) + and controlled by ``CONFIG_DEBUG_subsystem_ERROR``. The + ``err()`` is reserved to indicate important error conditions. + +- ``alert()``. The highest priority debug macro (``LOG_EMERG``) + and is controlled by ``CONFIG_DEBUG_ALERT``. The ``alert()`` + macro is reserved for use solely by assertion and crash + handling logic. It also differs from the other macros in that + it cannot be enabled or disabled per subsystem. + +SYSLOG Channels +=============== + +SYSLOG Channel Interfaces +------------------------- + +In the NuttX SYSLOG implementation, the underlying device logic +the supports the SYSLOG output is referred to as a SYSLOG +*channel*. Each SYSLOG channel is represented by an interface +defined in ``include/nuttx/syslog/syslog.h``: + +.. code-block:: c + + /* This structure provides the interface to a SYSLOG device */ + + typedef CODE int (*syslog_putc_t)(int ch); + typedef CODE int (*syslog_flush_t)(void); + + struct syslog_channel_s + { + /* I/O redirection methods */ + + syslog_putc_t sc_putc; /* Normal buffered output */ + syslog_putc_t sc_force; /* Low-level output for interrupt handlers */ + syslog_flush_t sc_flush; /* Flush buffered output (on crash) */ + + /* Implementation specific logic may follow */ + }; + +The channel interface is instantiated by calling +:c:func:`syslog_channel()`. + +.. c:function:: int syslog_channel(FAR const struct syslog_channel_s *channel); + + Configure the SYSLOG function to use the provided + channel to generate SYSLOG output. + + ``syslog_channel()`` is a non-standard, internal OS interface and + is not available to applications. It may be called numerous times + as necessary to change channel interfaces. By default, all system + log output goes to console (``/dev/console``). + + :param channel: Describes the interface to the channel to be used. + + :return: + Zero (OK)is returned on success. A negated errno value is + returned on any failure. + +SYSLOG Channel Initialization +----------------------------- + +The initial, default SYSLOG channel is established with statically +initialized global variables so that some level of SYSLOG output +may be available immediately upon reset. This initialized data is +in the file ``drivers/syslog/syslog_channel.c``. The initial +SYSLOG capability is determined by the selected SYSLOG channel: + +- *In-Memory Buffer (RAMLOG)*. Full SYSLOG capability as + available at reset. + +- *Serial Console*. If the serial implementation provides the + low-level character output function ``up_putc()``, then that + low level serial output is available as soon as the serial + device has been configured. + +- For all other SYSLOG channels, all SYSLOG output goes to the + bit- bucket until the SYSLOG channel device has been + initialized. + +The syslog channel device is initialized when the bring-up logic +calls :c:func:`syslog_initialize()`. + +.. c:function:: int syslog_initialize(void) + + .. code-block:: c + + #include + #ifndef CONFIG_ARCH_SYSLOG + int syslog_initialize(void); + #else + # define syslog_initialize() + #endif + + One power up, the SYSLOG facility is non-existent + or limited to very low-level output. This function is called later + in the initialization sequence after full driver support has been + initialized. It installs the configured SYSLOG drivers and enables + full SYSLOG capability. + + This function performs these basic operations: + + - Initialize the SYSLOG device + + - Call :c:func:`syslog_channel` to begin using that device. + + - If ``CONFIG_ARCH_SYSLOG`` is selected, then the + architecture-specific logic will provide its own SYSLOG device + initialize which must include as a minimum a call to + :c:func:`syslog_channel` to use the device. + + :return: + Zero (``OK``) is returned on success; a + negated ``errno`` value is returned on any failure. + +Different types of SYSLOG devices have different OS initialization +requirements. Some are available immediately at reset, some are +available after some basic OS initialization, and some only after +OS is fully initialized. + +There are other types of SYSLOG channel devices that may require +even further initialization. For example, the file SYSLOG channel +(described below) cannot be initialized until the necessary file +systems have been mounted. + +Interrupt Level SYSLOG Output +----------------------------- + +As a general statement, SYSLOG output only supports *normal* +output from NuttX tasks. However, for debugging purposes, it is +also useful to get SYSLOG output from interrupt level logic. In an +embedded system, that is often where the most critical operations +are performed. + +There are three conditions under which SYSLOG output generated +from interrupt level processing can a included the SYSLOG output +stream: + + #. **Low-Level Serial Output**. If you are using a SYSLOG console + channel (``CONFIG_SYSLOG_CONSOLE``) and if the underlying + architecture supports the low-level ``up_putc()`` + interface(\ ``CONFIG_ARCH_LOWPUTC``), then the SYSLOG logic + will direct the output to ``up_putc()`` which is capable of + generating the serial output within the context of an interrupt + handler. + + There are a few issues in doing this however: + + - ``up_putc()`` is able to generate debug output in any + context because it disables serial interrupts and polls the + hardware directly. These polls may take many milliseconds + and during that time, all interrupts are disable within the + interrupt handler. This, of course, interferes with the + real-time behavior of the RTOS. + + - The output generated by ``up_putc()`` is immediate and in + real-time. The normal SYSLOG output, on the other hand, is + buffered in the serial driver and may be delayed with + respect to the immediate output by many lines. Therefore, + the interrupt level SYSLOG output provided through + ``up_putc()`` is grossly out of synchronization with other + debug output + + #. **In-Memory Buffering**. If the RAMLOG SYSLOG channel is + supported, then all SYSLOG output is buffered in memory. + Interrupt level SYSLOG output is no different than normal + SYSLOG output in this case. + + #. **Serialization Buffer**. A final option is the use of an + *interrupt buffer* to buffer the interrupt level SYSLOG output. + In this case: + + - SYSLOG output generated from interrupt level process in not + sent to the SYSLOG channel immediately. Rather, it is + buffered in the interrupt serialization buffer. + + - Later, when the next normal syslog output is generated, it + will first empty the content of the interrupt buffer to the + SYSLOG device in the proper context. It will then be + followed by the normal syslog output. In this case, the + interrupt level SYSLOG output will interrupt the normal + output stream and the interrupt level SYSLOG output will be + inserted into the correct position in the SYSLOG output when + the next normal SYSLOG output is generated. + +The SYSLOG interrupt buffer is enabled with +``CONFIG_SYSLOG_INTBUFFER``. When the interrupt buffer is +enabled, you must also provide the size of the interrupt buffer +with ``CONFIG_SYSLOG_INTBUFSIZE``. + +SYSLOG Channel Options +====================== + +SYSLOG Console Device +--------------------- + +The typical SYSLOG device is the system console. If you are using +a serial console, for example, then the SYSLOG output will appear +on that serial port. + +This SYSLOG channel is automatically selected by +``syslog_initialize()`` in the LATE initialization phase based on +configuration options. The configuration options that affect this +channel selection include: + + - ``CONFIG_DEV_CONSOLE``. This setting indicates that the system + supports a console device, i.e., that the character device + ``/dev/console`` exists. + + - ``CONFIG_SERIAL_CONSOLE``. This configuration option is + automatically selected when a UART or USART is configured as + the system console. There is no user selection. + + - ``CONFIG_SYSLOG_CONSOLE``. This configuration option is + manually selected from the SYSLOG menu. This is the option that + actually enables the SYSLOG console device. It depends on + ``CONFIG_DEV_CONSOLE``. + + - ``CONFIG_ARCH_LOWPUTC``. This is an indication from the + architecture configuration that the platform supports the + ``up_putc()`` interface. ``up_putc()`` is a very low level UART + interface that can even be used from interrupt handling. + +Interrupt level SYSLOG output will be lost unless: (1) the +interrupt buffer is enabled to support serialization, or (2) a +serial console is used and ``up_putc()`` is supported. + +.. note:: + The console channel uses the fixed character device at + ``/dev/console``. The console channel is not synonymous with + ``stdout`` (or file descriptor 1). ``stdout`` is the current + output from a task when, say, ``printf()`` if used. Initially, + ``stdout`` does, indeed, use the ``/dev/console`` device. However, + ``stdout`` may subsequently be redirected to some other device or + file. This is always the case, for example, when a transient + device is used for a console -- such as a USB console or a Telnet + console. The SYSLOG channel is not redirected as ``stdout`` is; + the SYSLOG channel will stayed fixed (unless it is explicitly + changed via ``syslog_channel()``). + +References: ``drivers/syslog/syslog_consolechannel.c`` and +``drivers/syslog/syslog_device.c`` + +SYSLOG Character Device +----------------------- + +The system console device, ``/dev/console``, is a character driver +with some special properties. However, any character driver may be +used as the SYSLOG output channel. For example, suppose you have a +serial console on ``/dev/ttyS0`` and you want SYSLOG output on +``/dev/ttyS1``. Or suppose you support only a Telnet console but +want to capture debug output ``/dev/ttyS0``. + +This SYSLOG device channel is selected with ``CONFIG_SYSLOG_CHAR`` +and has no other dependencies. Differences from the SYSLOG console +channel include: + + - ``CONFIG_SYSLOG_DEVPATH``. This configuration option string + must be set provide the full path to the character device to be + used. + + - The forced SYSLOG output always goes to the bit-bucket. This + means that interrupt level SYSLOG output will be lost unless + the interrupt buffer is enabled to support serialization. + + - ``CONFIG_SYSLOG_CHAR_CRLF``. If ``CONFIG_SYSLOG_CHAR_CRLF`` is + selected, then linefeeds in the SYSLOG output will be expanded + to Carriage Return plus Linefeed. Since the character device is + not a console device, the addition of carriage returns to line + feeds would not be performed otherwise. You would probably want + this expansion if you use a serial terminal program with the + character device output. + +References: ``drivers/syslog/syslog_devchannel.c`` and +``drivers/syslog/syslog_device.c`` + +SYSLOG File Device +------------------ + +Files can also be used as the sink for SYSLOG output. There is, +however, a very fundamental difference in using a file as opposed +the system console, a RAM buffer, or character device: You must +first mount the file system that supports the SYSLOG file. That +difference means that the file SYSLOG channel cannot be supported +during the boot-up phase but can be instantiated later when board +level logic configures the application environment, including +mounting of the file systems. + +The interface ``syslog_file_channel()`` is used to configure the +SYSLOG file channel: + +.. c:function:: int syslog_file_channel(FAR const char *devpath); + + Configure to use a file in a mounted file system + at ``devpath`` as the SYSLOG channel. + + This tiny function is simply a wrapper around + ``syslog_dev_initialize()`` and ``syslog_channel()``. It calls + ``syslog_dev_initialize()`` to configure the character file at + ``devpath`` then calls ``syslog_channel()`` to use that device as + the SYSLOG output channel. + + File SYSLOG channels differ from other SYSLOG channels in that + they cannot be established until after fully booting and mounting + the target file system. This function would need to be called from + board-specific bring-up logic AFTER mounting the file system + containing ``devpath``. + + SYSLOG data generated prior to calling ``syslog_file_channel()`` + will, of course, not be included in the file. + + NOTE interrupt level SYSLOG output will be lost in this case + unless the interrupt buffer is used. + + :param devpath: + The full path to the file to be used for SYSLOG + output. This may be an existing file or not. If the file + exists, ``syslog_file_channel()`` will append new SYSLOG data + to the end of the file. If it does not, then + ``syslog_file_channel()`` will create the file. + + :return: + Zero (``OK``) is returned on success; a + negated ``errno`` value is returned on any failure. + + References: ``drivers/syslog/syslog_filechannel.c``, + ``drivers/syslog/syslog_device.c``, and + ``include/nuttx/syslog/syslog.h``. + +SYSLOG RAMLOG Device +-------------------- + +The RAMLOG is a standalone feature that can be used to buffer any +character data in memory. There are, however, special +configurations that can be used to configure the RAMLOG as a +SYSLOG channel. The RAMLOG functionality is described in a more +general way in the following paragraphs. + +RAM Logging Device +================== + +The RAM logging driver is a driver that was intended to support +debugging output (SYSLOG) when the normal serial output is not +available. For example, if you are using a Telnet or USB serial +console, the debug output will get lost -- or worse. For example, +what if you want to debug the network over Telnet? +The RAM logging driver can also accept debug output data from +interrupt handler with no special serialization buffering. As an +added benefit, the RAM logging driver is much less invasive. Since +no actual I/O is performed with the debug output is generated, the +RAM logger tends to be much faster and will interfere much less +when used with time critical drivers. + +The RAM logging driver is similar to a pipe in that it saves the +debugging output in a circular buffer in RAM. It differs from a +pipe in numerous details as needed to support logging. + +This driver is built when ``CONFIG_RAMLOG`` is defined in the +Nuttx configuration. + +``dmesg`` command +----------------- + +When the RAMLOG (with SYSLOG) is enabled, a new NuttShell (NSH) +command will appear: ``dmesg``. The ``dmesg`` command will dump +the contents of the circular buffer to the console (and also clear +the circular buffer). + +RAMLOG Configuration options +---------------------------- + +- ``CONFIG_RAMLOG``: Enables the RAM logging feature + +- ``CONFIG_RAMLOG_SYSLOG``: Use the RAM logging device for the + SYSLOG interface. If this feature is enabled, then all debug + output will be re-directed to the circular buffer in RAM. This + RAM log can be viewed from NSH using the ``dmesg`` command. + NOTE: Unlike the limited, generic character driver SYSLOG + device, the RAMLOG *can* be used to capture debug output from + interrupt level handlers. + +- ``CONFIG_RAMLOG_NPOLLWAITERS``: The number of threads than can + be waiting for this driver on ``poll()``. Default: 4 + +- ``CONFIG_RAMLOG_BUFSIZE``: The size of the circular buffer to + use. Default: 1024 bytes. + +Other miscellaneous settings + +- ``CONFIG_RAMLOG_CRLF``: Pre-pend a carriage return before every + linefeed that goes into the RAM log. + +- ``CONFIG_RAMLOG_NONBLOCKING``: Reading from the RAMLOG will + never block if the RAMLOG is empty. If the RAMLOG is empty, + then zero is returned (usually interpreted as end-of-file). If + you do not define this, the NSH ``dmesg`` command will lock up + when called! So you probably do want this! + +- ``CONFIG_RAMLOG_NPOLLWAITERS``: The maximum number of threads + that may be waiting on the poll method. diff --git a/doc/conf.py b/doc/conf.py new file mode 100644 index 00000000000..a2b4d1850c2 --- /dev/null +++ b/doc/conf.py @@ -0,0 +1,85 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'NuttX' +copyright = '2020, The Apache Software Foundation' +author = 'NuttX community' +version = release = 'latest' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx_rtd_theme", + "recommonmark", + 'sphinx.ext.autosectionlabel' +] + +autosectionlabel_prefix_document = True + +# do not set Python as primary domain for code blocks +highlight_language = "none" +primary_domain = None + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +html_show_sphinx = False + +html_theme_options = { + 'prev_next_buttons_location': None +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +html_css_files = [ + 'custom.css' +] + +html_show_license = True + +html_logo = '../Documentation/NuttX.png' +html_favicon = '_static/favicon.ico' + +today_fmt = '%d %B %y at %H:%M' + +c_id_attributes = [ + 'FAR', + 'CODE', + 'noreturn_function' +] diff --git a/doc/contributing/coding_style.rst b/doc/contributing/coding_style.rst new file mode 100644 index 00000000000..5f0aedac9ae --- /dev/null +++ b/doc/contributing/coding_style.rst @@ -0,0 +1,2656 @@ +================= +C Coding Standard +================= + +NuttX follows a specific coding style which needs to be followed at all times +a contribution to be accepted. Please read this document before working on +new code so that you can follow the style from the start. To check your code +for conformance to the coding style, you should use the `nxstyle <#nxstyle>`_ +tool included under ``tools/`` in the main NuttX repository. + +******************* +General Conventions +******************* + +File Organization +================= + +**File Extensions** Use the ``.h`` extension for C header files +and ``.c`` for C source files. + +**File header**. Every C, C++, make file, or script begins with a file header. +That file header is enclosed with a *block comment* (see below). Within the +block comment, the following must appear: + + - The relative path to the file from the top-level directory. + - An optional, one-line description of the file contents. + - A blank line + - A copyright notice indented two additional spaces + - A line identifying the author and contact information with the + same indentation as the copyright notice. + - A blank line + - NuttX standard Apache 2.0 licensing information as provided in + the `appendix <#appndxa>`__. + +**Sample File Headers**. Sample file headers are provided in an +`Appendix <#appndxa>`__ to this document. No new software may be +included in the NuttX source tree that does not have licensing +information included in the file. No new software may be included +in the NuttX source tree that does not have a Apache 2.0 license +or license (or, in the case of 3rd party file, a compatible +license such as the BSD or MIT licenses). If the file does not +follow Apache 2.0 licensing, then the appropriate license +information should be provided in the header rather than the +Apache 2.0 licensing information and a NOTE should be included in +the top-level ``COPYING`` file to indicate any variations from +Apache 2.0 licensing. + +**Grouping**. All like components in a C source or header file are +grouped together. Definitions do not appear arbitrarily through +the file, rather, like definitions are grouped together and +preceded by a *block comment* identifying the grouping. + +**Block Comments**. Each grouping in the file is separated with a +*block comment*. The block comment consists of: + +- A line that consists of the opening C comment (``/*``) followed + by a series of asterisks extending to the length of the line + (usually to column 78). +- The name of the grouping, starting at column 4. An asterisk + preceives the name of the grouping in column 1. +- A line that consists of the closing C comment (``*/``) at the + end of the line (usually column 78) preceded by a series of + asterisks extending to column 1. + +**Examples of Block Comments**. See `Appendix A <#appndxa>`__ for +examples of block comments. + +**Order of Groupings**. The following groupings should appear in +all C source files in the following order: + + #. Included Files + #. Pre-processor Definitions + #. Private Types (definitions) + #. Private Function Prototypes (declarations) + #. Private Data (definitions) + #. Public Data (definitions) + #. Private Functions (definitions) + #. Public Functions (definitions) + +The following groupings should appear in all C header files in the +following order: + + #. Included Files + #. Pre-processor Definitions + #. Public Types (definitions) + #. Public Data (declarations) + #. Inline Functions (definitions) + #. Public Function Prototypes (declarations) + +**Large vs. Small Files**. In larger files, block comments should +be included for all groupings, even if they are empty; the empty +grouping provides important information in itself. Smaller files +may omit some of the block comments; it is awkard if the block +comments are larger than the file content! + +**Header File Idempotence**. C header file must protect against +multiple inclusion through the use of macros that "guard" against +multiple definitions if the header file is included multiple +times. + +- Each header file must contain the following pre-processor + conditional logic near the beginning of the header file: + Between the file header and the "Included Files" block comment. + For example:: + + #ifndef __INCLUDE_NUTTX_ARCH_H + #define __INCLUDE_NUTTX_ARCH_H + + Notice that the definitions within of the header do not follow + the usually rules: The presence of the conditional test at the + top of the file does not cause the remaining definitions within + the file to be indented. + +- Then conditional compilation is closed at the fine line of the + header file with:: + + #endif /* __INCLUDE_NUTTX_ARCH_H */ + +**Forming Guard Names**. Then pre-processor macro name used in the +guard is formed from the full, relative path to the header for +from the top-level, controlled directory. That path is preceded by +``__`` and ``_`` replaces each character that would otherwise be +invalid in a macro name. So, for example, ``__INCLUDE_NUTTX_ARCH_H`` +corresponds to the header file ``include/nuttx/arch.h`` + +**Deoxygen Information**. NuttX does not use Deoxygen for +documentation and no file should contain Doxygen tags or Doxygen +style comments. + +**Sample File Formats**. C source and header file templates are +provided in an `Appendix <#appndxa>`__ to this document. + +Lines +===== + +**Line Endings**. Files should be formatted with the newline +character (``\n``) as the line ending (Unix-style line endings) +and specifically *not* the carriage return, newline sequence +(``\r\n``) used with Windows-style line endings. There should be +no extra whitespace at the end of the line. In addition, all text +files should end in a single newline (``\n``). This avoids the +*"No newline at end of file"* warning generated by certain tools. + +**Line Width**. Text should not extend past column 78 in the +typical C source or header file. Sometimes the nature of the +content of a file may require that the lines exceed this limit. +This often occurs in header files with naturally long definitions. +If the line width must extend 78 lines, then some wider line width +may be used in the file provided that it is used consistently. + +**Line Wrapping**. + +.. error:: This is incorrect + + .. code-block:: c + + struct some_long_struct_name_s + { + struct some_long_struct_name_s *flink; /* The forward link to the next instance of struct some_long_struct_name_s in a singly linked list */ + int short_name1; /* Short comment 1 */ + int short_name2; /* This is a very long comment describing subtle aspects of the short_name2 field */ + }; + + struct some_medium_name_s *ptr = (struct some_medium_name_s *)malloc(sizeof(some_medium_name_s); + + struct some_long_struct_name_s *ptr = (struct some_long_struct_name_s *)malloc(sizeof(some_long_struct_name_s); + + ret = some_function_with_many parameters(long_parameter_name_1, long_parameter_name_2, long_parameter_name_3, long_parameter_name_4, long_parameter_name_5, long_parameter_name_6, long_parameter_name_7, long_parameter_name_8); + + ret = some_function_with_many parameters(long_parameter_name_1, + long_parameter_name_2, + long_parameter_name_3 + long_parameter_name_4, + long_parameter_name_5, + long_parameter_name_6, + long_parameter_name_7, + long_parameter_name_8); + +.. hint:: This is correct + + .. code-block:: c + + struct some_long_struct_name_s + { + /* The forward link to the next instance of struct + * some_long_struct_name_s in a singly linked list. + */ + + struct some_long_struct_name_s *flink; + int short_name1; /* Short comment 1. */ + int short_name2; /* This is a very long comment describing subtle + * aspects of the short_name2 field. */ + }; + + FAR struct some_medium_name_s *ptr = (FAR struct some_medium_name_s *) + malloc(sizeof(some_medium_name_s); + + FAR struct some_medium_name_s *ptr = + (FAR struct some_medium_name_s *)malloc(sizeof(some_medium_name_s); + + FAR struct some_long_struct_name_s *ptr = + (FAR struct some_long_struct_name_s *) + malloc(sizeof(some_long_struct_name_s); + + ret = some_function_with_many parameters(long_parameter_name_1, + long_parameter_name_2, + long_parameter_name_3, + long_parameter_name_4, + long_parameter_name_5, + long_parameter_name_6, + long_parameter_name_7, + long_parameter_name_8); + +**NOTE**: See the discussion of `pointers <#farnear>`__ for +information about the ``FAR`` qualifier used above. + +**Double Spacing**. A single blank line may be use to separate +logical groupings as the designer feels fit. Single blank lines +are also required in certain contexts as defined in this standard. +Additional blanks lines (two or more) are prohibited. + +**Columnar Organization**. Similar things should be aligned on the +same column unless doing so would cause the line width to be +exceeded. + +.. note:: This is acceptable + + .. code-block:: c + + dog = cat; + monkey = oxen; + aardvark = macaque; + +.. hint:: This is preferred + + .. code-block:: c + + dog = cat; + monkey = oxen; + aardvark = macaque; + +**Block Comments** The final asterisk (``*``) should occur at +column 78 (or the line width of files with longer lines). Note +that the final comment delimiter of the block comment is an +exception an lies at column 79. + +Comments +======== + +**General**. Within a comment, the text must be standard English +conforming to standard English rules of grammar and spelling (US +English spelling). Of course, this is not the place to summarize +all English grammar, but as examples of common grammatic issues in +comments: + +- All sentences should begin with an upper-case character and end + with either '.', '?', or '!'. +- Sentence fragments and phrases are generally treated the same + as sentences. +- The punctuation '.' and ':' is followed by two spaces; the + punctuation ',' and ';' is followed by a single space. +- Text following '.' or ':' begins with an upper-case character; + text following ',' or ';' begins with a lower-case character. + +**Line Spacing** A single blank line should precede and follow +each comment. The only exceptions are: + +For the file header block comment that begins on line one; there +is no preceding blank line in that case. +For conditional compilation. Conditional compilation should +include the conditional logic *and* all comments associated with +the conditional logic. In this case, the blank line appears +*before* the conditional, not after it. No blank lines precede any +comments following the conditional. +With braces. No blank line separates the line containing the +opening left brace from a comment. No blank line follows a comment +that may be the final line preceding a closing right brace. +With Labels. No blank line separates the line containing the label +from a comment. + +.. error:: This is incorrect + + .. code-block:: c + + /* set a equal to b */ + a = b; + /* set b equal to c */ + b = c; + + /* Do the impossible */ + + #ifdef CONFIG_THE_IMPOSSIBLE + the_impossible(); + #endif + + if (a == b) + { + + /* Only a comment */ + + } + + here: + + /* This is the place */ + +.. tip:: This is correct + + .. code-block:: c + + /* Set a equal to b. */ + + a = b; + + /* Set b equal to c. */ + + b = c; + + #ifdef CONFIG_THE_IMPOSSIBLE + /* Do the impossible */ + + the_impossible(); + #endif + + if (a == b) + { + /* Only a comment */ + } + + here: + /* This is the place */ + +**Indentation** Comments should, typically, be placed before the +code section to which they apply. The comment indentation should +be the same as the follow indentation rules as the following code +(if applicable). + +**Short, Single line comments**. Short comments must lie on a +single line. The comment delimiters must lie on the same line. + +.. error:: This is incorrect + + .. code-block:: c + + /* + * This is a single line comment + */ + +.. tip:: This is correct + + .. code-block:: c + + /* This is a single line comment. */ + +**Multi-line comments**. If the comment is too long to fit on a +single, it must be broken into a multi-line comment. The comment +must be begin on the first line of the multi-line comment with the +opening comment delimiter (``/*``). The following lines of the +multi-line comment must be with an asterisk (``*``) aligned in the +same column as the asterisk in the preceding line. The closing +comment delimiter must lie on a separate line with the asterisk +(``*``) aligned in the same column as the asterisk in the +preceding line. + +.. error:: This is incorrect + + .. code-block:: c + + /* + This is the first line of a multi-line comment. + This is the second line of a multi-line comment. + This is the third line of a multi-line comment. */ + + /* This is the first line of another multi-line comment. */ + /* This is the second line of another multi-line comment. */ + /* This is the third line of another multi-line comment. */ + +.. tip:: This is correct + + .. code-block:: c + + /* This is the first line of a multi-line comment. + * This is the second line of a multi-line comment. + * This is the third line of a multi-line comment. + */ + +**Comments to the Right of Statements**. Comments to the right of +statements in C source files are discouraged. If such comments are +used, they should be (1) very short so that they do not exceed the +line width (typically 78 characters), (2) aligned so that the +comment begins in the same column on each line. + +.. error:: This is incorrect + + .. code-block:: c + + dog = cat; /* Make the dog be a cat */ + monkey = oxen; /* Make the monkey be an oxen */ + aardvark = macaque; /* Make the aardvark be a macaque */ + +.. note:: This is acceptable + + .. code-block:: c + + dog = cat; /* Make the dog be a cat. */ + monkey = oxen; /* Make the monkey be an oxen. */ + aardvark = macaque; /* Make the aardvark be a macaque. */ + +.. tip:: This is preferred + + .. code-block:: c + + /* Make the dog be a cat. */ + + dog = cat; + + /* Make the monkey be an oxen. */ + + monkey = oxen; + + /* Make the aardvark be a macaque. */ + + aardvark = macaque; + +**Comments to the Right of Data Definitions**. Comments to the +right of a declaration with an enumeration or structure, on the +other hand, are encouraged, provided that the comments are short +and do not exceed the maximum line width (usually 78 characters). +Columnar alignment of comments is very desirable (but often cannot +be achieved without violating the line width). + +.. error:: This is incorrect + + .. code-block:: c + + struct animals_s + { + int dog; /* This is a dog */ + int cat; /* This is a cat */ + double monkey; /* This is a monkey */ + double oxen; /* This is an oxen */ + bool aardvark; /* This is an aardvark */ + bool macaque; /* This is a macaque */ + }; + +.. note:: This is acceptable + + .. code-block:: c + + struct animals_s + { + int dog; /* This is a dog. */ + int cat; /* This is a cat. */ + double monkey; /* This is a monkey. */ + double oxen; /* This is an oxen. */ + bool aardvark; /* This is an aardvark. */ + bool macaque; /* This is a macaque. */ + }; + +.. tip:: This is preferred + + .. code-block:: c + + struct animals_s + { + int dog; /* This is a dog. */ + int cat; /* This is a cat. */ + double monkey; /* This is a monkey. */ + double oxen; /* This is an oxen. */ + bool aardvark; /* This is an aardvark. */ + bool macaque; /* This is a macaque. */ + }; + +**Long Comments on the Right**. Comments on the right of +statements or data definitions must be short and fit on the same +line without exceeding the maximum line length. If a longer +comment is needed, then it should appear above the statement of +definition rather than to the right of the definition. + +**Breaking Long Comments to the Right of Statements** Breaking +long comments to the right of statements is acceptable as well, +but not encouraged. In this case the comment must be begin on the +first line of the multi-line, right-hand comment with the opening +comment delimiter (/*). The following lines of the multi-line, +right hand comment must be with an asterisk (*) aligned in the +same column as the asterisk in the preceding line. The closing +comment delimiter must lie on the *same* line with the asterisk. + +.. error:: This is incorrect + + .. code-block:: c + + dog = cat; /* This assignment will convert what was at one time a lowly dog into a ferocious feline. */ + +.. note:: This is acceptable + + .. code-block:: c + + dog = cat; /* This assignment will convert what was at one time a + * lowly dog into a ferocious feline. */ + +.. tip:: This is preferred + + .. code-block:: c + + /* This assignment will convert what was at one time a lowly dog into a + * ferocious feline. + */ + + dog = cat; + +**Note** that if the comment is continued on multiple lines, the +comment alignment and multi-line comment rules still apply with +one exception: The closing ``*/`` appears on the same line as the +final text of the comment. This exception to the rule is enforced +to keep the statements and definitions from becoming to spread +out. + +**Block comments**. Block comments are only used to delimit +groupings with the overall `file +organization <#fileorganization>`__ and should not be used unless +the usage is consistent with delimiting logical groupings in the +program. + +**C Style Comments**. C99/C11/C++ style comments (beginning with +``//``) should not be used with NuttX. NuttX generally follows C89 +and all code outside of architecture specific directories must be +compatible with C89. + +.. error:: This is incorrect + + .. code-block:: c + + // This is a structure of animals + struct animals_s + { + int dog; // This is a dog + int cat; // This is a cat + double monkey; // This is a monkey + double oxen; // This is an oxen + bool aardvark; // This is an aardvark + bool macaque; // This is a macaque + }; + +.. tip:: This is correct + + .. code-block:: c + + /* This is a structure of animals. */ + + struct animals_s + { + int dog; /* This is a dog. */ + int cat; /* This is a cat. */ + double monkey; /* This is a monkey. */ + double oxen; /* This is an oxen. */ + bool aardvark; /* This is an aardvark. */ + bool macaque; /* This is a macaque. */ + }; + +**"Commenting Out" Large Code Blocks**. Do not use C or C++ comments to +disable compilation of large blocks of code. Instead, use ``#if 0`` to +do that. Make sure there is a comment before the ``#if 0`` to explain +why the code is not compiled. + +.. error:: This is incorrect + + .. code-block:: c + + void some_function(void) + { + ... compiled code ... + + /* + ... disabled code .. + */ + + ... compiled code ... + } + + void some_function(void) + { + ... compiled code ... + + // + // ... disabled code .. + // + + ... compiled code ... + } + +.. tip:: This is correct + + .. code-block:: c + + void some_function(void) + { + ... compiled code ... + + /* The following code is disabled because it is no longer needed. */ + + #if 0 + ... disabled code .. + #endif + + ... compiled code ... + } + +Braces +====== + +In general, the use of braces in the NuttX coding standard is similar to +the use of braces in the `GNU Coding +standards `__ with a +few subtle differences. + +**Coding Standard:** + +- **Always on Separate Lines**. Braces always appear on a separate line + containing nothing else other than white space. +- **Never Comments on Braces**. Do not put comments on the same line as + braces. +- **Compound Statements**. Within this document, an opening left brace + followed by a sequence of statements, and ending with a closing right + brace is referred to as a *compound statement*. +- **Nested Compound Statements**. In the case where there are nested + compound statements that end with several consecutive right braces, + each closing right brace must lie on a separate line and must be + indented to match the corresponding opening brace. +- **Final brace followed by a single blank line**. The *final* right + brace must be followed by a blank line as per standard rules. There + are two exceptions to this rule: + + #. In the case where there are nested several consecutive right + braces, no blank lines should be inserted except for after the + *final* right brace. + #. No blank should be used to separate the final, closing right brace + when it is followed by a ``break;`` statement. + +- **Special Indentation Rules**. Special `indentation + rules <#indentation>`__ apply to braces. + +.. error:: This is incorrect + + .. code-block:: c + + while (true) + { + if (valid) + { + ... + } /* if valid */ + else + { + ... + } /* not valid */ + } /* end forever */ + if (a < b) { + if (a < 0) { + c = -a; + } else { + c = a; + } + } else { + if (b < 0) { + c = -b; + } else { + c = b; + } + } + +.. tip:: This is correct + + .. code-block:: c + + while (true) + { + if (valid) + { + ... + } + else + { + ... + } + } + + if (a < b) + { + if (a < 0) + { + c = -a; + } + else + { + c = a; + } + } + else + { + if (b < 0) + { + c = -b; + } + else + { + c = b; + } + } + +**Exception to Indentation Rule for Braces**. The exception is braces +that following structure, enumeration, union, and function declarations. +There is no additional indentation for those braces; those braces align +with the beginning of the definition + +.. error:: This is incorrect + + .. code-block:: c + + enum kinds_of_dogs_e + { + ... + }; + + struct dogs_s { + ... + union { + ... + } u; + ... + }; + + struct cats_s + { + ... + union + { + ... + } u; + ... + }; + + int animals(int animal) + { + ... + } + +.. tip:: This is correct + + .. code-block:: c + + enum kinds_of_dogs_e + { + ... + }; + + struct dogs_s + { + ... + union + { + ... + } u; + ... + }; + + struct cats_s + { + ... + union + { + ... + } u; + ... + }; + + int animals(int animal) + { + ... + } + +Indentation +=========== + +In general, the indentation in the NuttX coding standard is similar to +the indentation requirements of the `GNU Coding +standards `__ with a +few subtle differences. + +**Indentation Unit**. Indentation is in units of two spaces; Each +indentation level is twos spaces further to the right than the preceding +indentation levels. TAB characters may not be used for indentation. + +.. error:: This is incorrect + + .. code-block:: c + + if (x == y) { + dosomething(x); + } + + if (x == y) { + dosomething(x); + } + +.. tip:: This is correct + + .. code-block:: c + + if (x == y) + { + dosomething(x); + } + +**Use of TAB Characters**. The use of TAB characters for indentation is +prohibited in C source and header files. TAB characters are, however, +used in make files, assembly language source files, Kconfig files and +some script files. When TAB characters are used in these files, spaces +may not be used for indentation. The correct TAB setting is 4 spaces +(not 8) in these cases. + +**Alignment of Braces**. Note that since braces must be on a separate +line (see above), this indentation by two spaces has an interesting +property: + +- All C statements (and case selectors) lie on lines that are multiples + of 4 spaces (beginning with an indentation of two): 2, 6, 10, ... + (4*n + 2) (for indentation level n = 0, 1, ...) + +- Braces lie on a separate line also indented by multiple of 4 spaces: + 4, 8, 12, ... 4*n (for indentation level n = 1, 2, ...) + +Thus, all code at the indentation level should align on the same column. +Similarly, opening and closing braces at the same indentation level +should also align on the same (but different) column. + +**Indentation of Pre-Processor Lines**. C Pre-processor commands +following any conditional computation are also indented following +basically the indentation same rules, differing in that the ``#`` always +remains in column 1. + +When C pre-processor statements are indented, they should be should be +indented by 2 spaces per level-of-indentation following the ``#``. C +pre-processor statements should be indented when they are enclosed +within C pre-processor conditional logic (``#if``..\ ``#endif``). The +level of indentation increases with each level of such nested +conditional logic. + +C pre-processor statements should always be indented in this way in the +``Pre-processor Definitions`` `section <#cfilestructure>`__ of each +file. C pre-processor statements may be indented in the +``Public/Private Data`` and ``Public/Private Functions`` sections of the +file. However, often the indentation of C pre-processor statements +conflicts with the indentation of the C code and makes the code more +difficult to read. In such cases, indentation of C pre-processor +statements should be omitted in those sections (only). + +.. error:: This is incorrect + + .. code-block:: c + + #ifdef CONFIG_ABC + #define ABC_THING1 1 + #define ABC_THING2 2 + #define ABC_THING3 3 + #endif + + #ifdef CONFIG_ABC + #define ABC_THING1 1 + #define ABC_THING2 2 + #define ABC_THING3 3 + #endif + +.. tip:: This is correct + + .. code-block:: c + + #ifdef CONFIG_ABC + # define ABC_THING1 1 + # define ABC_THING2 2 + # define ABC_THING3 3 + #endif + + #ifdef CONFIG_ABC + # define ABC_THING1 1 + # define ABC_THING2 2 + # define ABC_THING3 3 + #endif + +**Exception**. Each header file includes `idempotence +definitions <#idempotence>`__ at the beginning of the header file. This +conditional compilation does *not* cause any change to the indentation. + +.. error:: This is incorrect + + .. code-block:: c + + #ifndef __INCLUDE_SOMEHEADER_H + # define __INCLUDE_SOMEHEADER_H + ... + # define THING1 1 + # define THING2 2 + # define THING3 3 + ... + #endif /* __INCLUDE_SOMEHEADER_H */ + +.. tip:: This is correct + + .. code-block:: c + + #ifndef __INCLUDE_SOMEHEADER_H + #define __INCLUDE_SOMEHEADER_H + ... + #define THING1 1 + #define THING2 2 + #define THING3 3 + ... + #endif /* __INCLUDE_SOMEHEADER_H */ + + +Parentheses +=========== + +**Coding Standard:** + +- **Space after key words**. Do not put a left parenthesis (``(``) + immediately after any C keywords (``for``, ``switch``, ``while``, + ``do``, ``return``, etc.). Put a space before the left parenthesis in + these cases. +- **Otherwise, no space before left parentheses**. Otherwise, there + should be no space before the left parentheses +- **No space between function name and argument list**. There should be + no space between a function name and an argument list. +- **Never space before the right parentheses**. There should never be + space before a right parenthesis ( ``)`` ). +- **No parentheses around returned values**. Returned values should + never be enclosed in parentheses unless the parentheses are required + to force the correct order of operations in a computed return value. + +.. error:: This is incorrect + + .. code-block:: c + + int do_foobar ( void ) + { + int ret = 0; + int i; + + for( i = 0; ( ( i < 5 ) || ( ret < 10 ) ); i++ ) + { + ret = foobar ( i ); + } + + return ( ret ); + } + +.. tip:: This is correct + + .. code-block:: c + + int do_foobar(void) + { + int ret = 0; + int i; + + for (i = 0; i < 5 || ret < 10; i++) + { + ret = foobar(i); + } + + return ret; + } + +**NOTE:** Many people do not trust their understanding of the precedence +of operators and so use lots of parentheses in expressions to force the +order of evaluation even though the parentheses may have no effect. This +will certainly avoid errors due to an unexpected order of evaluation, +but can also make the code ugly and overly complex (as in the above +example). In general, NuttX does not use unnecessary parentheses to +force order of operations. There is no particular policy in this regard. +However, you are are advised to check your C Programming Language book +if necessary and avoid unnecessary parenthesis when possible. + +************************* +Data and Type Definitions +************************* + +One Definition/Declaration Per Line +=================================== + +.. error:: This is incorrect + + .. code-block:: c + + extern long time, money; + char **ach, *bch; + int i, j, k; + +.. tip:: This is correct + + .. code-block:: c + + extern long time; + extern long money; + FAR char **ach; + FAR char *bch; + int i; + int j; + int k; + +**NOTE**: See the discussion of `pointers <#farnear>`__ for information +about the ``FAR`` qualifier used above. + +Global Variables +================ + +**Global vs. Local vs. Public vs. Private** By a *global* variable it is +meant any variable defined outside of a function. The distinction is +between this kind of *global* and function *local* definition and refers +to the scope a symbol *within a file*. A related concept for all +*global* names defined within a file is the scope of the name across +different files. If the global symbol is pre-pended with the ``static`` +storage class then the scope of the global symbol is within the file +only. This is a somewhat different concept and within NuttX you will +find these distinguished as *private* vs. *public* global symbols. +However, within this standard, the term *global variable* will refer to +any variable that has more than local scope. + +**Coding Standard:** + +- **Short global variable names**. Names should be terse, but generally + descriptive of what the variable is for. Try to say something with + the variable name, but don't try to say too much. For example, the + variable name of ``g_filelen`` is preferable to something like + ``g_lengthoffile``. +- **Global variable prefix**. All global variables begin with the + prefix ``g_`` to indicate the scope of variable. +- **Module name prefix** If a global variable belongs in a *module* + with a name of, say ``xyz``, then that module should be included as + part of the prefix like: ``g_xyz_``. +- **Lowercase**, Use all lower case letters. +- **Minimal use of** ``_``. Preferably there are no ``_`` + separators within the name. Long variable names might require some + delimitation using ``_``. Long variable names, however, are + discouraged. +- **Use structures**. If possible, wrap all global variables within a + structure to minimize the liklihood of name collisions. +- **Avoid global variables when possible**. Use of global variables, in + general, is discourage unless there is no other reasonable solution. + +.. error:: This is incorrect + + .. code-block:: c + + extern int someint; + static int anotherint; + uint32_t dwA32BitInt; + uint32_t gAGlobalVariable; + +.. note:: This is acceptable + + .. code-block:: c + + extern int g_someint; + static int g_anotherint; + uint32_t g_a32bitint; + uint32_t g_aglobal; + +.. tip:: This is preferred + + .. code-block:: c + + struct my_variables_s + { + uint32_t a32bitint; + uint32_t aglobal; + }; + + extern int g_someint; + static int g_anotherint; + struct my_variables_s g_myvariables; + +Parameters and Local Variables +============================== + +**Coding Standard:** + +- **Common naming standard**. Naming for function parameters and local + variables is the same. +- **Short variable names**. Names should be terse, but generally + descriptive of what the variable is for. Try to say something with + the variable name, but don't try to say too much. For example, the + variable name of ``len`` is preferable to something like + ``lengthofiobuffer``. +- **No special ornamentation**. There is no special ornamentation of + the name to indication that the variable is a local variable. The + prefix ``p`` or ``pp`` may be used on names of pointers (or pointer + to pointers) if it helps to distinguish the variable from some other + local variable with a similar name. Even this convention is + discouraged when not necessary. +- **Lowercase** Use all lower case letters. +- **Minimal use of single character variable names**. Short variable + names are preferred. However, single character variable names should + be avoided. Exceptions to this include ``i``, ``j``, and ``k`` which + are reserved only for use as loop indices (part of our Fortran + legacy). +- **Minimal use of** ``_``. Preferably there are no ``_`` + separators within the name. Long variable names might require some + delimitation using ``_``. Long variable names, however, are + discouraged. + +.. error:: This is incorrect + + .. code-block:: c + + uint32_t somefunction(int a, uint32_t dwBValue) + { + uint32_t this_is_a_long_variable_name = 1; + int i; + + for (i = 0; i < a; i++) + { + this_is_a_long_variable_name *= dwBValue--; + } + + return this_is_a_long_variable_name; + } + +.. tip:: This is correct + + .. code-block:: c + + uint32_t somefunction(int limit, uint32_t value) + { + uint32_t ret = 1; + int i; + + for (i = 0; i < limit; i++) + { + ret *= value--; + } + + return ret; + } + + +**NOTE:** You will see the local variable named ``ret`` is frequently +used in the code base for the name of a local variable whose value will +be returned or to received the returned value from a called function. + +Type Definitions +================ + +**Coding Standard:** + +- **Short type names**. Type names should be terse, but generally + descriptive of what the type is for. Try to say something with the + type name, but don't try to say too much. For example, the type name + of ``fhandle_t`` is preferable to something like + ``openfilehandle_t``. +- **Type name suffix**. All ``typedef``'ed names end with the suffix + ``_t``. +- **Module name prefix** If a type belongs in a *module* with a name + of, say ``xyz``, then that module should be included as a prefix to + the type name like: ``xyz_``. +- **Lowercase**. Use all lower case letters. +- **Minimal use of** ``_``. Preferably there are few ``_`` + separators within the type name. Long type names might require some + delimitation using ``_``. Long type names, however, are + discouraged. + +.. error:: This is incorrect + + .. code-block:: c + + typedef void *myhandle; + typedef int myInteger; + +.. tip:: This is correct + + .. code-block:: c + + typedef FAR void *myhandle_t; + typedef int myinteger_t; + +**NOTE**: See the discussion of `pointers <#farnear>`__ for information +about the ``FAR`` qualifier used above. + +Structures +========== + +**Structure Naming** + +- **No un-named structures**. All structures must be named, even if + they are part of a type definition. That is, a structure name must + follow the reserved word ``struct`` in all structure definitions. + There are two exceptions to this rule: + + #. First for structures that are defined within another union or + structure (discouraged). In those cases, the structure name should + always be omitted. + #. Second for structures as the type of a local variable. In this + case, again, the structure name should always be omitted. + +- **Structured defined with structures discouraged**. Fields within a + structure may be another structure that is defined only with the + scope of the containing structure. This practice is acceptable, but + discouraged. +- **No un-named structure fields**. Structure may contain other + structures as fields. This this case, the structure field must be + named. C11 permits such un-named structure fields within a structure. + NuttX generally follows C89 and all code outside of architecture + specific directories must be compatible with C89. +- **No structure definitions within Type Definition**. The practice of + defining a structure within a type definition is discouraged. It is + preferred that the structure definition and the type definition be + separate definitions. In general, the NuttX coding style discourages + any ``typdef``-ing of structures; normally the full structure name is + used as types throughout the code. The reason for this is that is + structure pointers may be forward referenced in header files without + having to include the file the provides the type definition. This + greatly reduces header file coupling. +- **Short structure names**. Structure names should be terse, but + generally descriptive of what the structure contains. Try to say + something with the structure name, but don't try to say too much. For + example, the structure name of ``xyz_info_s`` is preferable to + something like ``xyz_datainputstatusinformation_s``. +- **Structure name suffix**. All structure names end with the suffix + ``_s``. +- **Module name prefix** If a structure belongs to a *module* with a + name of, say ``xyz``, then that module should be included as a prefix + to the structure name like: ``xyz_``. +- **Lowercase**. Use all lower case letters. +- **Minimal use of** ``_``. Preferably there are few ``_`` + separators within the structure name. Long variable names might + require some delimitation using ``'_'``. Long variable names, + however, are discouraged. + +**Structure Field Naming** + +- **Common variable naming**. Structure field naming is generally the + same as for local variables. +- **One definition per line**. The `one definition per + line <#onedatperline>`__ rule applies to structure fields, including + bit field definitions. +- **Each field should be commented**. Each structure field should be + commented. Commenting should follow the `standard + conventions <#comments>`__. +- **Optional structure field prefix**. It make be helpful to add a + two-letter prefix to each field name so that is is clear which + structure the field belongs to. Although a good practice, that + convention has not been used consistently in NuttX. +- **Lowercase**. Use all lower case letters. +- **Minimal use of** ``_``. Preferably there are few ``_`` + separators within the field name. Long variable names might require + some delimitation using ``'_'``. Long variable names, however, are + discouraged. + +**Other Applicable Coding Standards**. See sections related to `line +formatting <#lines>`__, `use of braces <#braces>`__, +`indentation <#indentation>`__, and `comments <#comments>`__. + +**Size Optimizations**. When declaring fields in structures, order the +declarations in such a way as to minimize memory waste due of data +alignment. This essentially means that that fields should be organized +by data size, not by functionality: Put all pointers togeter, all +``uint8_t``'s together, all ``uint32_t``'s together. Data types withi +well known like ``uint8_t`` and ``uint32_t`` should also be place in +either ascending or descending size order. + +.. error:: This is incorrect + + .. code-block:: c + + typedef struct /* Un-named structure */ + { + ... + int val1, val2, val3; /* Values 1-3 */ + ... + } xzy_info_t; + + struct xyz_information + { + ... + uint8_t bita : 1, /* Bit A */ + bitb : 1, /* Bit B */ + bitc : 1; /* Bit C */ + ... + }; + + struct abc_s + { + ... + struct + { + int a; /* Value A */ + int b; /* Value B */ + int c; /* Value C */ + }; /* Un-named structure field */ + ... + }; + +.. tip:: This is correct + + .. code-block:: c + + struct xyz_info_s + { + ... + int val1; /* Value 1 */ + int val2; /* Value 2 */ + int val3; /* Value 3 */ + ... + }; + +.. warning:: This is discouraged + + .. code-block:: c + + typedef struct xyz_info_s xzy_info_t; + +The use of typedef'ed structures is acceptable but discouraged. + +.. tip:: This is correct + + .. code-block:: c + + struct xyz_info_s + { + ... + uint8_t bita : 1, /* Bit A */ + uint8_t bitb : 1, /* Bit B */ + uint8_t bitc : 1, /* Bit C */ + ... + }; + +.. warning:: This is discouraged + + .. code-block:: c + + struct abc_s + { + ... + struct + { + int a; /* Value A */ + int b; /* Value B */ + int c; /* Value C */ + } abc; + ... + }; + +The use of structures defined within other structures is acceptable provided that they define named fields. +The general practice of defining a structure within the scope of another structure, however, is still but discouraged in any case. +The following is preferred: + +.. tip:: This is preferred + + .. code-block:: c + + struct abc_s + { + ... + int a; /* Value A */ + int b; /* Value B */ + int c; /* Value C */ + ... + }; + +Unions +====== + +**Union and Field Names**. Naming of unions and fields within unions +follow the same naming rules as for `structures and structure +fields <#structures>`__. The only difference is that the suffix ``_u`` +is used to identify unions. + +**Other Applicable Coding Standards**. See sections related to `line +formatting <#lines>`__, `use of braces <#braces>`__, +`indentation <#indentation>`__, and `comments <#comments>`__. + +.. note:: This is acceptable + + .. code-block:: c + + union xyz_union_u /* All unions must be named */ + { + uint8_t b[4]; /* Byte values. */ + uint16_t h[2]; /* Half word values. */ + uint32_t w; /* Word Value. */ + }; + + typedef union xyz_union_u xzy_union_t; + +The use of typedef'ed unions is acceptable but discouraged. + +.. tip:: This is preferred + + .. code-block:: c + + struct xyz_info_s + { + ... + union + { + uint8_t b[4]; /* Byte values. */ + uint16_t h[2]; /* Half word values. */ + uint32_t w; /* Word Value. */ + } u; /* All union fields must be named */ + ... + }; + +**NOTE:** Note that the union fields within structures are often named +``u``. This is another exception to the prohibition against using single +character variable and field names. The short field name ``u`` clearly +identifies a union field and prevents the full name of the union value +from being excessively long. + +Enumerations +============ + +**Enumeration Naming**. Naming of enumerations follow the same naming +rules as for `structure <#structures>`__ and `union <#unions%22>`__ +naming. The only difference is that the suffix ``_e`` is used to +identify an enumeration. + +**Enumeration Value Naming**. Enumeration values, however, following a +naming convention more similar to `macros <#macros>`__. + +- **Uppercase**. Enumeration values are always in upper case. +- **Use of** ``_`` **encouraged**. Unlike other naming, use of the + underscore character ``_`` to break up enumeration names is + encouraged. +- **Prefix**. Each value in the enumeration should begin with an + upper-case prefix that identifies the value as a member of the + enumeration. This prefix should, ideally, derive from the name of the + enumeration. +- **No dangling commas**. There should be no dangling comma on the + final value of the enumeration. The most commonly used tool chain are + tolerant of such dangling commas, but others will not. + +**Other Applicable Coding Standards**. See sections related to `line +formatting <#lines>`__, `use of braces <#braces>`__, +`indentation <#indentation>`__, and `comments <#comments>`__. + +.. tip:: This is correct + + .. code-block:: c + + enum xyz_state_e + { + XYZ_STATE_UNINITIALIZED = 0, /* Uninitialized state. */ + XYZ_STATE_WAITING, /* Waiting for input state. */ + XYZ_STATE_BUSY, /* Busy processing input state. */ + XYZ_STATE_ERROR, /* Halted due to an error. */ + XYZ_STATE_TERMINATING, /* Terminating stated. */ + XYZ_STATE_TERMINATED /* Terminating stated. */ + }; + +C Pre-processor Macros +====================== + +**Coding Standard:** + +**Macro Naming**. Macro naming following a naming convention similar to +the naming of `enumeration values <#enumerations>`__. + +- **Uppercase**. Macro names are always in upper case. +- **Lowercase Exceptions**. There are a few lower case values in NuttX + macro names. Such as a lower-case ``p`` for a period or decimal point + (such as ``VOLTAGE_3p3V``). I have also used lower-case ``v`` for a + version number (such as ``CONFIG_NET_IPv6``). However, these are + exceptions to the rule rather than illustrating a rule. +- **Macros that could be functions**. Lower-case macro names are also + acceptable if the macro is a substitute for a function name that + might be used in some other context. In that case, normal function + naming applies. +- **Use of** ``_`` **encouraged**. Unlike other naming, use of the + underscore character ``_`` to break up macro names is encouraged. +- **Prefix**. Each related macro value should begin with an upper-case + prefix that identifies the value as part of a set of values (and also + to minimize the likelihood of naming collisions). +- **Single space after** ``#define``. A single space character should + separate the ``#define`` from the macro name. Tabs are never used. +- **Normal commenting rules**. Normal commenting rules apply. +- **Line continuations**. Macro definitions may be continued on the + next line by terminating the line with the ``\`` character just + before the newline character. There should be a single space before + the ``\`` character. Aligned ``\`` characters on multiple line + continuations are discouraged because they are a maintenance problem. +- **Parentheses around macro argument expansions**. Macros may have + argument lists. In the macros expansion, each argument should be + enclosed in parentheses. +- **Real statements**. If a macro functions as a statement, then the + macro expansion should be wrapped in ``do { ... } while (0)`` to + assume that the macros is, indeed, a statement. +- **Magic numbers are prohibited in code**. Any numeric value is not + intuitively obvious, must be properly named and provided as either a + pre-processor macro or an enumeration value. +- **Side effects**. Be careful of side effects. +- **Indentation**. See the `Indentation of Pre-Processor + Lines <#indentation>`__ requirements above. + +**Other Applicable Coding Standards**. See sections related to `line +formatting <#lines>`__, `indentation <#indentation>`__, and +`comments <#comments>`__. + +.. error:: This is incorrect + + .. code-block:: c + + #define max(a,b) a > b ? a : b + + #define ADD(x,y) x + y + + #ifdef HAVE_SOMEFUNCTION + int somefunction(struct somestruct_s* psomething); + #else + #define SOMEFUNCTION() (0) + #endif + + # define IS_A_CAT(c) ((c) == A_CAT) + + #define LONG_MACRO(a,b) \ + { \ + int value; \ + value = b-1; \ + a = b*value; \ + } + + #define DO_ASSIGN(a,b) a = b + +.. tip:: This is correct + + .. code-block:: c + + #define MAX(a,b) (((a) > (b)) ? (a) : (b)) + + #define ADD(x,y) ((x) + (y)) + + #ifdef HAVE_SOMEFUNCTION + int somefunction(struct somestruct_s* psomething); + #else + # define somefunction(p) (0) + #endif + + # define IS_A_CAT(c) ((c) == A_CAT) + + #define LONG_MACRO(a,b) \ + { \ + int value; \ + value = (b)-1; \ + (a) = (b)*value; \ + } + + #define DO_ASSIGN(a,b) do { (a) = (b); } while (0) + +.. _farnear: + +Pointer Variables +================= + +**Pointer Naming**. Pointers following same naming conventions as for +other variable types. A pointer (or pointer-to-a-pointer) variable may +be prefaced with ``p`` (or ``pp``) with no intervening underscore +character ``_`` in order to identify that variable is a pointer. That +convention is not encouraged, however, and is only appropriate if there +is some reason to be concerned that there might otherwise be confusion +with another variable that differs only in not being a pointer. + +**White Space**. The asterisk used in the declaration of a pointer +variable or to dereference a pointer variable should be placed +immediately before the variable name with no intervening spaces. A space +should precede the asterisk in a cast to a pointer type. + +.. error:: This is incorrect + + .. code-block:: c + + int somefunction(struct somestruct_s* psomething); + + ptr = (struct somestruct_s*)value; + +.. tip:: This is correct + + .. code-block:: c + + int somefunction(FAR struct somestruct_s *something); + + ptr = (FAR struct somestruct_s *)value; + +.. c:macro:: FAR + +``FAR``, ``NEAR``, ``DSEG`` and ``CODE`` pointers. Some architectures +require a qualifier on pointers to identify the address space into which +the pointer refers. The macros ``FAR``, ``NEAR``, ``DSEG`` and ``CODE`` +are defined in ``include/nuttx/compiler.h`` to provide meaning for this +qualifiers when needed. For portability, the general rule is that +pointers to data that may lie in the stack, heap, ``.bss``, or ``.data`` +should be prefaced by the qualifier ``FAR``; pointers to functions +probably lie in a code address space and should have the qualifier +``CODE``. The typical effect of these macros on architectures where they +have meaning to determine the size of the pointer (size in the sense of +the width of the pointer value in bits). + +Initializers +============ + +**Applicable Coding Standards**. See the section related to +`parentheses <#parentheses>`__. + +**C89 Compatibility**. All common NuttX code must conform to ANSII C89 +requirements. Newer C standards permit more flexible initialization with +named initializers and array initializers. However, these are not +backward compatible with C89 and cannot be used in common code. Newer +C99 features may be included in architecture-specific sub-directories +where there is no possibility of the use of such older toolchains. C11 +is included in NuttX, but has not been verified and, hence, it not +encourage anywhere. + +********* +Functions +********* + +Function Headers +================ + +**Coding Standard:** + +- **Function headers**. Each function is preceded by a function header. + The function header is a *block comment* that provides information + about the function. The block comment consists of the following: + + - The block comment begins with a line that consists of the opening + C comment in column 1 (``/*``) followed by a series of asterisks + extending to the length of the line (usually to column 78). + - The block comment ends with a line that consists of series of + asterisks beginning at column 2 and extending to the near the end + line (usually to column 77) followed by the closing C comment in + (usually at column 78 for a total length of 79 characters). + - Information about the function is included in lines between the + first and final lines. Each of these begin with a space in column + 1, an sterisk (``*``) in column 2, and a space in column 3. + +- **Function header preceded by one blank line**. Exactly one blank + line precedes each function header. +- **Function header followed by one blank line**. Exactly one blank + line is placed after function header and before the function + definition. +- **Function header sections**. Within the function header, the + following data sections must be provided: + + - ``* Name:`` followed by the name of the function on the same + line. + - ``* Description:`` followed by a description of the function + beginning on the second line. Each line of the function + description is indented by two additional spaces. + - ``* Input Parameters:`` followed by a description of the of + each input parameter beginning on the second line. Each input + parameter begins on a separator line indented by two additional + spaces. The description needs to include (1) the name of the input + parameters, and (2) a short description of the input parameter. + - ``* Returned Value:`` followed by a description of the of + returned value(s) beginning on the second line. The description of + the returned value should identify all error values returned by + the function. + - ``* Assumptions/Limitations:`` followed by a any additional + information that is needed to use the function correctly. This + section is optional and may be omitted with there is no such + special information required for use of the function. + + Each of these data sections is separated by a single line like ``*``. + +**Function header template**. Refer to `Appendix A <#cfilestructure>`__ +for the template for a function header. + +Function Naming +=============== + +**Coding Standard:** + +- **Short function names**. Function names should be terse, but + generally descriptive of what the function is for. Try to say + something with the function name, but don't try to say too much. For + example, the variable name of ``xyz_putvalue`` is preferable to + something like ``xyz_savethenewvalueinthebuffer``. +- **Lowercase**. Use all lower case letters. +- **Module prefix**. All functions in the same *module*, or + *sub-system*, or within the same file should have a name beginning + with a common prefix separated from the remainder of the function + name with the underscore, ``'_'``, character. For example, for a + module called *xyz*, all of the functions should begin with ``xyz_``. +- **Extended prefix**. Other larger functional grouping should have + another level in the naming convention. For example, if module *xyz* + contains a set of functions that manage a set of I/O buffers (IOB), + then those functions all should get naming beginning with a common + prefix like ``xyz_iob_``. +- **Use of** ``_`` **discouraged**. Further use of the ``'_'`` separators + is discouraged in function naming. Long function names might require + some additional elimitation using ``'_'``. Long function names, + however, are also discouraged. +- **Verbs and Objects**. The remainder of the function name should be + either in the form of *verb-object* or *object-verb*. It does not + matter which as long as the usage is consistent within the *module*. + Common verbs include *get* and *set* (or *put*) for operations that + retrieve or store data, respectively. The verb *is* is reserved for + functions that perform some test and return a boolean value to + indicate the result of the test. In this case, the *object* should + indicate what is testing and the return value of ``true`` should be + consistent with result of the test being true. + +Parameter Lists +=============== + +**Coding Standards**. See general rules for `parameter +naming <#localvariable>`__. See also the sections related to the use of +`parentheses <#parentheses>`__. + +**Use of** ``const`` **parameters**. Use of the ``const`` storage class is +encouraged. This is appropriate to indicate that the function will not +modify the object. + +Function Body +============= + +**Coding Standard:** + +- **Single compound statement**. The function body consists of a single + compound statement. +- **Braces in column 1** The opening and close braces of the compound + statement must be placed in column one. +- **First definition or statement in column 3**. The first data + definitions or statements in the function body are idented by two + spaces. Standards for statements are covered in the `following + paragraph <#statements>`__ +- **Local variables first**. Because NuttX conforms to the older C89 + standard, all variables that have scope over the compound statement + must be defined at the beginning of the compound statement prior to + any executable statements. Local variable definitions intermixed + within the following sequence of executable statements are forbidden. + A single blank line must follow the local variable definitions + separating the local variable definitions from the following + executable statements. **NOTE** that a function body consists of a + compound statement, but typically so does the statement following + ``if``, ``else``, ``for``, ``while``, ``do``. Local variable + definitions are also acceptable at the beginning of these compound + statements as with any other. +- **Long functions are discouraged**. As a rule of thumb, the length of + a function should be limited so that it would fit on a single page + (if you were to print the source code). +- **Return Statement**. The argument of the ``return`` statement should + *not* be enclosed in parentheses. A reasonable exception is the case + where the returned value argument is a complex expression and where + the parentheses improve the readability of the code. Such complex + expressions might be Boolean expressions or expressions containing + conditions. Simple arithmetic computations would not be considered + *complex* expressions. +- **Space after the function body**. A one (and only one) blank line + must follow the closing right brace of the function body. + +**Other Applicable Coding Standards**. See sections related to `General +Conventions <#general>`__, `Parameters and Local +Variables <#localvariable>`__, and `Statements <#statements>`__. + +.. error:: This is incorrect + + .. code-block:: c + + int myfunction(int a, int b) + { + int c, d; + c = a + d = b; + + int e = c + d; + + for (int i = 0; i < a; i++) + { + for (int j = 0; j < b; j++) + { + e += j * d; + } + } + + return (e / a); + } + +.. tip:: This is correct + + .. code-block:: c + + int myfunction(int a, int b) + { + int c; + int d; + int e; + int i; + + c = a + d = b; + e = c + d; + + for (i = 0; i < a; i++) + { + int j; + + for (j = 0; j < b; j++) + { + e += j * d; + } + } + + return e / a; + } + +Returned Values +=============== + +**OS Internal Functions**. In general, OS internal functions return a +type ``int`` to indicate success or failure conditions. Non-negative +values indicate success. The return value of zero is the typical success +return value, but other successful return can be represented with other +positive values. Errors are always reported with negative values. These +negative values must be a well-defined ``errno`` as defined in the file +``nuttx/include/errno.h``. + +**Application/OS Interface**. All but a few OS interfaces conform to +documented standards that have precedence over the coding standards of +this document. + +**Checking Return Values**. Callers of internal OS functions should +always check return values for an error. At a minimum, a debug statement +should indicate that an error has occurred. Ignored return values are +always suspicious. All calls to ``malloc`` or ``realloc``, in +particular, must be checked for failures to allocate memory to avoid use +of NULL pointers. + +********** +Statements +********** + +One Statement Per Line +====================== + +**Coding Standard:** + +- **One statement per line**. There should never be more than one + statement on a line. +- **No more than one assignment per statement**. Related to this, there + should never be multiple assignments in the same statement. +- **Statements should never be on the same line as any keyword**. + Statements should never be on the same line as case selectors or any + C keyword. + +**Other Applicable Coding Standards**. See the section related to the +use of `braces <#braces>`__. + +.. error:: This is incorrect + + .. code-block:: c + + if (var1 < var2) var1 = var2; + + case 5: var1 = var2; break; + + var1 = 5; var2 = 6; var3 = 7; + + var1 = var2 = var3 = 0; + +.. tip:: This is correct + + .. code-block:: c + + if (var1 < var2) + { + var1 = var2; + } + + case 5: + { + var1 = var2; + } + break; + + var1 = 5; + var2 = 6; + var3 = 7; + + var1 = 0; + var2 = 0; + var3 = 0; + +Casts +===== + +**Coding Standard:** + +- **No space in cast**. There should be no space between a cast and the + value being cast. + +.. error:: This is incorrect + + .. code-block:: c + + struct something_s *x = (struct something_s*) y; + +.. tip:: This is correct + + .. code-block:: c + + struct something_s *x = (struct something_s *)y; + +Operators +========= + +**Spaces before and after binary operators**. All binary operators +(operators that come between two values), such as ``+``, ``-``, ``=``, +``!=``, ``==``, ``>``, etc. should have a space before and after the +operator, for readability. As examples: + +.. error:: This is incorrect + + .. code-block:: c + + for=bar; + if(a==b) + for(i=0;i<5;i++) + +.. tip:: This is correct + + .. code-block:: c + + for = bar; + if (a == b) + for (i = 0; i < 5; i++) + +**No space separating unary operators**. Unary operators (operators that +operate on only one value), such as ``++``, should *not* have a space +between the operator and the variable or number they are operating on. + +.. error:: This is incorrect + + .. code-block:: c + + x ++; + +.. tip:: This is correct + + .. code-block:: c + + x++; + +**Forbidden Multicharacter Forms**. Many operators are expressed as a +character in combination with ``=`` such as ``+=``, ``>=``, ``>>=``, +etc. Some compilers will accept the ``=`` at the beginning or the end of +the sequence. This standard, however, requires that the ``=`` always +appear last in order to avoid amiguities that may arise if the ``=`` +were to appear first. For example, ``a =++ b;`` could also be +interpreted as ``a =+ +b;`` or ``a = ++b`` all of which are very +different. + +``if then else`` Statement +========================== + +**Coding Standard:** + +- ``if`` **separated from** ````. The ``if`` keyword and the + ```` must appear on the same line. The ``if`` keyword and + the ```` must be separated by a single space. +- **Indentation and parentheses**. ``if `` follows the + standard indentation and parentheses rules. +- **Alignment**. The ``if`` in the ``if `` line and the + ``else`` must be aligned at the same column. +- **Statement(s) always enclosed in braces**. Statement(s) following + the ``if `` and ``else`` keywords must always be enclosed + in braces. Braces must follow the ``if `` and ``else`` + lines even in the cases where (a) there is no contained statement or + (b) there is only a single statement! +- **Braces and indentation**. The placement of braces and statements + must follow the standard rules for `braces and + indentation <#braces>`__. +- **Final brace followed by a single blank line**. The *final* right + brace of the ``if``-``else`` must be followed by a blank line in most + cases (the exception given below). This may be the final brace of the + ``if`` compound statement if the ``else`` keyword is not present. Or + it may be the the final brace of the ``else`` compound statement if + present. A blank line never follows the right brace closing the + ``if`` compound statement if the ``else`` keyword is present. Use of + braces must follow all other standard rules for `braces and + spacing <#braces>`__. +- **Exception**. That blank line must also be omitted for certain cases + where the ``if ``-``else`` statement is nested within + another compound statement; there should be no blank lines between + consecutive right braces as discussed in the standard rules for use + of `braces <#braces>`__. + +**Other Applicable Coding Standards**. See sections related to `use of +braces <#braces>`__ and `indentation <#indentation>`__. + +.. error:: This is incorrect + + .. code-block:: c + + if(var1 < var2) var1 = var2; + + if(var > 0) + var--; + else + var = 0; + + if (var1 > 0) { + var1--; + } else { + var1 = 0; + } + var2 = var1; + +.. tip:: This is correct + + .. code-block:: c + + if (var1 < var2) + { + var1 = var2; + } + + if (var > 0) + { + var--; + } + else + { + var = 0; + } + + if (var1 > 0) + { + var1--; + } + else + { + var1 = 0; + } + + var2 = var1; + +**Ternary operator** (`` ? : ``): + +- **Only if the expression is short**. Use of this form is only + appropriate if the entire sequence is short and fits neatly on the + line. +- **Multiple lines forbidden**. This form is forbidden if it extends to + more than one line. +- **Use of parentheses**. The condition and the entire sequence are + often enclosed in parentheses. These are, however, not required if + the expressions evaluate properly without them. + +**Other Applicable Coding Standards**. See sections related to +`parentheses <#parentheses>`__. + +.. tip:: This is correct + + .. code-block:: c + + int arg1 = arg2 > arg3 ? arg2 : arg3; + int arg1 = ((arg2 > arg3) ? arg2 : arg3); + +``switch`` Statement +==================== + +**Definitions:** + +- **Case logic**. By *case logic* it is mean the ``case`` or + ``default`` and all of the lines of code following the ``case`` or + ``default`` up to the next ``case``, ``default``, or the right brace + indicating the end of the switch statement. + +**Coding Standard:** + +- ``switch`` **separated from** ````. The ``switch`` keyword and + the switch ```` must appear on the same line. The ``if`` + keyword and the ```` must be separated by a single space. +- **Falling through**. Falling through a case statement into the next + case statement is be permitted as long as a comment is included. +- ``default`` **case**. The ``default`` case should always be present + and trigger an error if it is reached when it should not be. +- **Case logic in braces**. It is preferable that all *case logic* + (except for the ``break``) be enclosed in braces. If you need to + instantiate local variables in case logic, then that logic must be + surrounded with braces. +- ``break`` **outside of braces**. ``break`` statements are normally + indented by two spaces. When used conditionally with *case logic*, + the placement of the break statement follows normal indentation + rules. +- **Case logic followed by a single blank line**. A single blank line + must separate the *case logic* and any following ``case`` or + ``default``. The should, however, be no blank lines between the *case + logic* and the closing right brace. +- **Switch followed by a single blank line**. The final right brace + that closes the ``switch `` statement must be followed by a + single blank line. +- **Exception**. That blank line must be omitted for certain cases + where the ``switch `` statement is nested within another + compound statement; there should be no blank lines between + consecutive right braces as discussed in the standard rules for use + of `braces <#braces>`__. + +**Other Applicable Coding Standards**. See sections related to `use of +braces <#braces>`__, `indentation <#indentation>`__, and +`comments <#comments>`__. + +.. tip:: This is correct + + .. code-block:: c + + switch (...) + { + case 1: /* Example of a comment following a case selector. */ + ... + + /* Example of a comment preceding a case selector. */ + + case 2: + { + /* Example of comment following the case selector. */ + + int value; + ... + } + break; + + default: + break; + } + +``while`` Statement +=================== + +**Coding Standard:** + +- ``while`` **separated from** ````. The ``while`` keyword + and the ```` must appear on the same line. The ``while`` + keyword and the ```` must be separated by a single space. +- **Keywords on separate lines**. ``while `` must lie on a + separate line with nothing else present on the line. +- **Indentation and parentheses**. ``while `` follows the + standard indentation and parentheses rules. +- **Statements enclosed in braces** Statement(s) following the + ``while `` must always be enclosed in braces, even if only + a single statement follows. +- **No braces on null statements**. No braces are required if no + statements follow the ``while ``. The single semicolon + (null statement) is sufficient; +- **Braces and indentation**. The placement of braces and statements + must follow the standard rules for braces and indentation. +- **Followed by a single blank line**. The final right brace that + closes the ``while `` statement must be followed by a + single blank line. +- **Exception**. That blank line must be omitted for certain cases + where the ``while `` statement is nested within another + compound statement; there should be no blank lines between + consecutive right braces as discussed in the standard rules for use + of `braces <#braces>`__. + +**Other Applicable Coding Standards**. See sections related to `use of +braces <#braces>`__, `indentation <#indentation>`__, and +`comments <#comments>`__. + +.. error:: This is incorrect + + .. code-block:: c + + while( notready() ) + { + } + ready = true; + + while (*ptr != '\0') ptr++; + +.. tip:: This is correct + + .. code-block:: c + + while (notready()); + + ready = true; + + while (*ptr != '\0') + { + ptr++; + } + +``do while`` Statement +====================== + +**Coding Standard:** + +- **Keywords on separate lines**. ``do`` and ``while `` must + lie on separate lines with nothing else present on the line. +- **Indentation and parentheses**. ``do .. while `` follows + the standard indentation and parentheses rules. +- **Statements enclosed in braces** Statement(s) following the ``do`` + must always be enclosed in braces, even if only a single statement + (or no statement) follows. +- **Braces and indentation**. The placement of braces and statements + must follow the standard rules for braces and indentation. +- ``while`` **separated from** ````. The ``while`` keyword + and the ```` must appear on the same line. The ``while`` + keyword and the ```` must be separated by a single space. +- **Followed by a single blank line**. The concluding + ``while `` must be followed by a single blank line. + +**Other Applicable Coding Standards**. See sections related to `use of +braces <#braces>`__, `indentation <#indentation>`__, and +`comments <#comments>`__. + +.. error:: This is incorrect + + .. code-block:: c + + do { + ready = !notready(); + } while (!ready); + senddata(); + + do ptr++; while (*ptr != '\0'); + +.. error:: This is incorrect + + .. code-block:: c + + do + { + ready = !notready(); + } + while (!ready); + + senddata(); + + do + { + ptr++; + } + while (*ptr != '\0'); + +Use of ``goto`` +=============== + +**Coding Standard:** + +- **Limited Usage of** ``goto``. All use of the ``goto`` statement is + prohibited except for one usage: for handling error conditions in + complex, nested logic. A simple ``goto`` in those conditions can + greatly improve the readability and complexity of the code. +- **Label Naming**. Labels must all lower case. The underscore + character ``_`` is permitted to break up long labels. +- **Error Exit Labels**. The error exit label is normally called + ``errout``. Multiple error labels are often to required to *unwind* + to recover resources committed in logic prior to the error to + otherwise *undo* preceding operations. Naming for these other labels + would be some like ``errout_with_allocation``, + ``errout_with_openfile``, etc. +- **Label Positioning**. Labels are never indented. Labels must always + begin in column 1. + +.. tip:: This is correct + + .. code-block:: c + + FAR struct some_struct_s *ptr; + int fd; + int ret; + ... + + if (arg == NULL) + { + ret = -EINVAL; + goto errout; + } + ... + ptr = (FAR struct some_struct_s *)malloc(sizeof(struct some_struct_s)); + if (!ptr) + { + ret = -ENOMEM; + goto errout; + } + ... + fd = open(filename, O_RDONLY); + if (fd < 0) + { + errcode = -errno; + DEBUGASSERT(errcode > 0); + goto errotout_with_alloc; + } + ... + ret = readfile(fd); + if (ret < 0) + { + goto errout_with_openfile; + } + ... + errout_with_openfile: + close(fd); + + errout_with_alloc: + free(ptr); + + error: + return ret; + +**NOTE**: See the discussion of `pointers <#farnear>`__ for information +about the ``FAR`` qualifier used above. + +*** +C++ +*** + +There is no existing document that provides a complete coding standard +for NuttX C++ files. This section is included here to provide some +minimal guidance in C++ code development. In most details like +indentation, spacing, and file organization, it is identical to the C +coding standard. But there are significant differences in the acceptable +standard beyond that. The primary differences are as follows: + +C++ style comments are not only permissible but are required (other than +for the following exception). This includes the block comments of in the +*Source File Structure* described in an `Appendix <#appndxa>`__ to this +standard. + +Deoxygen tags are acceptable. As are C style comments when needed to +provide DOxygen tags. + +There is currently no requirement to conform any specific C++ version. +However, for portability reasons, conformance to older, pre-C++11 +standards is encouraged where reasonable. + +C++ file name extensions: The extension ``.cxx`` is used for C++ source +files; the extension ``.hxx`` is used for C++ header files. + +All naming must use *CamelCase*. Use of the underbar character, '_' is +discouraged. This includes variables, classes, structures, ..., etc.: +All user-nameable C++ elements. Pre-processor definitions are still +required to be all upper case. + +Local variable, method names, and function names must all begin with a +lower case letter. As examples, ``myLocalVariable`` would be a compliant +name for a local variable; ``myMethod`` would be a compliant name for a +method; + +Namespaces, global variable, class, structure, template, and enumeration +names begin with a capital letter identifying what is being named: + + *Namespace Names* + Namespaces begin with an upper case character but no particular + character is specified. As an example, ``MyNamespace`` is fully + compliant. + *Global Variable Names* + Global variables and singletons begin with an upper case '**G**'. For + example, ``GMyGlobalVariable``. The prefix ``g_`` is never used. + *Implementation Class Names* + Classes that implement methods begin with an upper case '**C**'. For + example, ``CMyClass``. A fully qualified method of ``CMyClass`` could + be ``MyNamespace::CMyClass::myMethod`` + *Pure Virtual Base Class Names* + Such base classes begin with an upper case '**I**'. For example, + ``IMyInterface``. + *Template Class Names* + Template classes begin with an upper case '**T**'. For example, + ``TMyTemplate``. + *``typedef``'d Type Names* + Currently all such types also begin with an upper case '**T**'. That + probably needs some resolution to distinguish for template names. The + suffix ``_t`` is never used. + *Structure Names* + Structures begin with an upper case '**S**'. For example, + ``SMyStructure``. The suffix ``_s`` is never used. + *Enumerations Names* + Enumerations begin with an upper case '**E**'. For example, + ``EMyEnumeration``. The suffix ``_e`` is never used. + +.. _appndxa: + +******** +Appendix +******** + +.. _cfilestructure: + +C Source File Structure +======================= + + +.. code-block:: c + + /**************************************************************************** + * + * + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + + /**************************************************************************** + * Included Files + ****************************************************************************/ + +*All header files are included here.* + +.. code-block:: c + + /**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +*All C pre-processor macros are defined here.* + + +.. code-block:: c + + /**************************************************************************** + * Private Types + ****************************************************************************/ + +*Any types, enumerations, structures or unions used by the file are +defined here.* + +.. code-block:: c + + /**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +*Prototypes of all static functions in the file are provided here.* + +.. code-block:: c + + /**************************************************************************** + * Private Data + ****************************************************************************/ + +*All static data definitions appear here.* + +.. code-block:: c + + /**************************************************************************** + * Public Data + ****************************************************************************/ + +*All data definitions with global scope appear here.* + +.. code-block:: c + + /**************************************************************************** + * Private Functions + ****************************************************************************/ + + /**************************************************************************** + * Name: + * + * Description: + * Description of the operation of the static function. + * + * Input Parameters: + * A list of input parameters, one-per-line, appears here along with a + * description of each input parameter. + * + * Returned Value: + * Description of the value returned by this function (if any), + * including an enumeration of all possible error values. + * + * Assumptions/Limitations: + * Anything else that one might need to know to use this function. + * + ****************************************************************************/ + +*All static functions in the file are defined in this grouping. Each is +preceded by a function header similar to the above.* + +.. code-block:: c + + /**************************************************************************** + * Public Functions + ****************************************************************************/ + + /**************************************************************************** + * Name: + * + * Description: + * Description of the operation of the function. + * + * Input Parameters: + * A list of input parameters, one-per-line, appears here along with a + * description of each input parameter. + * + * Returned Value: + * Description of the value returned by this function (if any), + * including an enumeration of all possible error values. + * + * Assumptions/Limitations: + * Anything else that one might need to know to use this function. + * + ****************************************************************************/ + +*All global functions in the file are defined here.* + +C Header File Structure +======================= + +.. code-block:: c + + /**************************************************************************** + * + * + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +*Header file* `idempotence <#idempotence>`__ *definitions go here* + +.. code-block:: c + + /**************************************************************************** + * Included Files + ****************************************************************************/ + +*All header files are included here.* + +.. code-block:: c + + /**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +*All C pre-processor macros are defined here.* + +.. code-block:: c + + /**************************************************************************** + * Public Types + ****************************************************************************/ + + #ifndef __ASSEMBLY__ + +*Any types, enumerations, structures or unions are defined here.* + +.. code-block:: c + + /**************************************************************************** + * Public Data + ****************************************************************************/ + + #ifdef __cplusplus + #define EXTERN extern "C" + extern "C" + { + #else + #define EXTERN extern + #endif + +*All data declarations with global scope appear here, preceded by the +definition* ``EXTERN``. + +.. code-block:: c + + /**************************************************************************** + * Inline Functions + ****************************************************************************/ + + /**************************************************************************** + * Name: + * + * Description: + * Description of the operation of the inline function. + * + * Input Parameters: + * A list of input parameters, one-per-line, appears here along with a + * description of each input parameter. + * + * Returned Value: + * Description of the value returned by this function (if any), + * including an enumeration of all possible error values. + * + * Assumptions/Limitations: + * Anything else that one might need to know to use this function. + * + ****************************************************************************/ + +*Any static inline functions may be defined in this grouping. Each is +preceded by a function header similar to the above.* + +.. code-block:: c + + /**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + /**************************************************************************** + * Name: + * + * Description: + * Description of the operation of the function. + * + * Input Parameters: + * A list of input parameters, one-per-line, appears here along with a + * description of each input parameter. + * + * Returned Value: + * Description of the value returned by this function (if any), + * including an enumeration of all possible error values. + * + * Assumptions/Limitations: + * Anything else that one might need to know to use this function. + * + ****************************************************************************/ + +*All global functions in the file are prototyped here. The keyword* +``extern`` *or the definition* ``EXTERN`` *are never used with function +prototypes.* + +.. code-block:: c + + #undef EXTERN + #ifdef __cplusplus + } + #endif + + #endif /* __INCLUDE_ASSERT_H */ + +Ending with the header `idempotence <#idempotence>`__ ``#endif``. diff --git a/doc/contributing/documentation.rst b/doc/contributing/documentation.rst new file mode 100644 index 00000000000..0e2e90d28b2 --- /dev/null +++ b/doc/contributing/documentation.rst @@ -0,0 +1,170 @@ +.. include:: /substitutions.rst + +.. note:: This is a first version of the document, will be updated once new documentation + system is in place. + +Documentation +============= + +The Apache NuttX Documentation is made using the +`Sphinx documentation system `_. Sphinx documentation +is written in `ReStructured Text `_ (RST). RST is +the format used for `Python documentation `_ and is also used +in many other projects. + +Contributions and fixes to the Apache NuttX Companion are encouraged and welcome. Here's how to do +it. + +#. Fork the Apache NuttX Documentation Repository + + Visit this link and hit the Fork button in the upper right of the page: + + * `NuttX (v01d's fork) `_ + + |br| + +#. Clone the Forked Repository + + Click the "Clone or Download" button and copy the clone URL. Then do this: + + .. code-block:: bash + + $ git clone + +#. Install Sphinx + + On the command line, change directories to the newly-downloaded repository directory: + + .. code-block:: bash + + $ cd incubator-nuttx + $ # install pyenv + $ curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash + $ # install python + $ pyenv install 3.7.3 + $ pyenv local 3.7.3 + $ # install pipenv + $ pip install pipenv + $ # install sphinx and related software + $ pipenv install + $ # activate the virtual environent + $ pipenv shell + +#. Build the HTML Documentation Locally + + .. code-block:: bash + + $ cd docs + $ make html + Running Sphinx v2.4.1 + making output directory... done + building [mo]: targets for 0 po files that are out of date + building [html]: targets for 12 source files that are out of date + updating environment: [new config] 12 added, 0 changed, 0 removed + reading sources... [100%] user/simulator + looking for now-outdated files... none found + pickling environment... done + checking consistency... done + preparing documents... done + writing output... [100%] user/simulator + generating indices... genindexdone + writing additional pages... searchdone + copying static files... ... done + copying extra files... done + dumping search index in English (code: en)... done + dumping object inventory... done + build succeeded. + + The HTML pages are in ``_build/html``. + +#. Check Out a New Branch + + .. code-block:: bash + + $ git checkout -b feature/my-branch + +#. Make Your Changes + + .. code-block:: bash + + $ vim user/intro.rst # or use the editor of your choice + # on whatever file you want to change + +#. Rebuild the HTML Documentation + + .. code-block:: bash + + $ make html + +#. View the Documentation in a Web Browser + + You can open the file ``docs/_build/html/index.html``. + |br| + |br| + +#. Iterate + + Repeat Steps 6, 7, and 8 until you're happy with the result. + |br| + |br| + +#. Commit the Changes + + .. code-block:: bash + + $ git add introduction/main.rst # or whatever files you changed + $ git commit + +#. Push to Your Branch + + .. code-block:: bash + + $ git push + +#. Submit Your Pull Request + + Go to the `Apache NuttX (v01d's fork) `_ page + on Github and click the "Pull Request" button. See Github's `Creating a Pull Request + `__ + page for more info. + + Use this template for the Pull Request description text: + + :: + + ### Summary + ### Impact + ### Limitations / TODO + ### Detail + ### Testing + ### How To Verify + + Fill out the sections describing your changes. The summary should be a concise bulleted + list. + + The ``How To Verify`` section is only needed if you change how the project is built or + add some other programs or scripts. + |br| + |br| + +#. Make Changes If Requested + + When you submit your Pull Request, the Apache NuttX Documentation team will review the changes, + and may request that you modify your submission. Please work with them to get your + changes accepted. + |br| + |br| + +#. You're Done! + + Feel good that you've made Apache NuttX documentation better for yourself and others. You've + just made the world a better place! + +Sphinx Resources +---------------- + +* `Sphinx documentation system `__ +* `ReStructured Text documentation `__ +* `Sphinx Guide to ReStructured Text `__ +* `Restructured Text cheat sheet `__ + diff --git a/doc/contributing/index.rst b/doc/contributing/index.rst new file mode 100644 index 00000000000..11c7e6edc85 --- /dev/null +++ b/doc/contributing/index.rst @@ -0,0 +1,15 @@ +Contributing +============ + +.. toctree:: + :maxdepth: 2 + :hidden: + :caption: Contents: + + workflow.rst + coding_style.rst + documentation.rst + +.. note:: + Brief description on how contributing to NuttX works (GitHub, PRs), which documents should be read + before the first contribution (coding style, etc). Brief description on how to participate more closely in NuttX project (commiter, PMC member). diff --git a/doc/contributing/workflow.rst b/doc/contributing/workflow.rst new file mode 100644 index 00000000000..60579ff83d6 --- /dev/null +++ b/doc/contributing/workflow.rst @@ -0,0 +1,7 @@ +Development Workflow +==================== + +.. note:: + This document should describe how a proper contribution should be made, and what is the + NuttX development workflow (PR based, CI checks). Could be divided into sections oriented + towards new users as well as others intending to participate in NuttX as commiter/PMC. diff --git a/doc/guides/index.rst b/doc/guides/index.rst new file mode 100644 index 00000000000..0744df52e38 --- /dev/null +++ b/doc/guides/index.rst @@ -0,0 +1,8 @@ +Guides +====== + +.. note:: This would contain "tutorial" type documentation for specific subjects not to be covered in more general terms. + +.. toctree:: + nfs.rst + usbtrace.rst diff --git a/doc/guides/nfs.rst b/doc/guides/nfs.rst new file mode 100644 index 00000000000..8c267f59157 --- /dev/null +++ b/doc/guides/nfs.rst @@ -0,0 +1,285 @@ +================= +NFS Client How-To +================= + +Adding NFS to the NuttX Configuration +===================================== + +The NFS client is easily added to your configuration: You simply need to +add ``CONFIG_NFS`` to your ``nuttx/.config`` file. There are, however, a +few dependencies on other system settings: + +First, there are things that you must configure in order to be able to +use any file system: + + - ``CONFIG_DISABLE_MOUNTPOINT=n``. You must include support for mount + points in the pseudo-file system. + +And there are several dependencies on the networking configuration. At a +minimum, you need to have the following selections: + + - ``CONFIG_NET=y``. General networking support. + - ``CONFIG_NET_UDP=y``. Support for UDP. + +Mount Interface +=============== + +A low-level, C-callable interface is provided to mount a file system. +That interface is called ``mount()`` and is mentioned in the +```porting guide`` `__ and is +prototyped in the header file ``include/sys/mount.h``: + +.. c:function:: int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data) + + ``mount()`` attaches the filesystem specified by the + ``source`` block device name into the root file system at the path + specified by ``target``. + + :param source: A null-terminated string providing the fill path to a + block driver in the NuttX pseudo-file system. + :param target: The location in the NuttX pseudo-file system where the + volume will be mounted. + :param filesystemtype: A string identifying the type of file system to + use. + :param mountflags: Various flags that can be used to qualify how the + file system is mounted. + :param data: Opaque data that is passed to the file system with the + mount occurs. + + :return: Zero is returned on success; -1 is returned on an + error and ``errno`` is set appropriately: + + - ``EACCES``. A component of a path was not searchable or mounting a + read-only filesystem was attempted without giving the ``MS_RDONLY`` + flag. + - ``EBUSY``. ``source`` is already mounted. + - ``EFAULT``. One of the pointer arguments points outside the user + address space. + - ``EINVAL``. ``source`` had an invalid superblock. + - ``ENODEV``. ``filesystemtype`` not configured + - ``ENOENT``. A pathname was empty or had a nonexistent component. + - ``ENOMEM``. Could not allocate a memory to copy filenames or data + into. + - ``ENOTBLK``. ``source`` is not a block device + +This same interface can be used to mount a remote, NFS file system using +some special parameters. The NFS mount differs from the *normal* file +system mount in that: (1) there is no block driver for the NFS file +system, and (2) special parameters must be passed as ``data`` to +describe the remote NFS server. Thus the following code snippet might +represent how an NFS file system is mounted: + +.. code-block:: c + + #include + #include + + struct nfs_args data; + char *mountpoint; + + ret = mount(NULL, mountpoint, string "nfs", 0, (FAR void *)&data); + +NOTE that: (1) the block driver parameter is ``NULL``. The ``mount()`` +is smart enough to know that no block driver is needed with the NFS file +system. (2) The NFS file system is identified with the simple string +"nfs" (3) A reference to ``struct nfs_args`` is passed as an +NFS-specific argument. + +The NFS-specific interface is described in the file +``include/nuttx/fs/nfs.h``. There you can see that ``struct nfs_args`` +is defined as: + +.. code-block:: c + + struct nfs_args + { + uint8_t addrlen; /* Length of address */ + uint8_t sotype; /* Socket type */ + uint8_t flags; /* Flags, determines if following are valid: */ + uint8_t timeo; /* Time value in deciseconds (with NFSMNT_TIMEO) */ + uint8_t retrans; /* Times to retry send (with NFSMNT_RETRANS) */ + uint16_t wsize; /* Write size in bytes (with NFSMNT_WSIZE) */ + uint16_t rsize; /* Read size in bytes (with NFSMNT_RSIZE) */ + uint16_t readdirsize; /* readdir size in bytes (with NFSMNT_READDIRSIZE) */ + char *path; /* Server's path of the directory being mount */ + struct sockaddr_storage addr; /* File server address (requires 32-bit alignment) */ + }; + +NFS Mount Command +================= + +The `NuttShell (NSH) `__ also supports a command called +``nfsmount`` that can be used to mount a remote file system via the NSH +command line. + +**Command Syntax:** + +.. code-block:: + + fsmount + +**Synopsis**. The ``nfsmount`` command mounts a network file system in +the NuttX pseudo filesystem. The ``nfsmount`` will use NFSv3 UDP +protocol to mount the remote file system. + +**Command Line Arguments**. The ``nfsmount`` takes three arguments: + + #. The ```` is the IP address of the server exporting + the file system you wish to mount. This implementation of NFS for the + NuttX RTOS is only for a local area network, so the server and client + must be in the same network. + #. The ```` is the location in the NuttX pseudo filesystem + where the mounted volume will appear. This mount point can only + reside in the NuttX pseudo filesystem. By convention, this mount + point is a subdirectory under ``/mnt``. The mount command will create + whatever pseudo directories that may be needed to complete the full + path (but the full path must not already exist). + #. The ```` is the file system ``/`` directory being + exported from server. This ``/`` directory must have been configured + for exportation on the server before when the NFS server was set up. + +After the volume has been mounted in the NuttX pseudo filesystem, it may +be access in the same way as other objects in the file system. + +**Example**. Suppose that the NFS server has been configured to export +the directory ``/export/shared``. The the following command would mount +that file system (assuming that the target also has privileges to mount +the file system). + +.. code-block:: fish + + NuttShell (NSH) + nsh> ls /mnt + /mnt: + nsh: ls: no such directory: /mnt + nsh> nfsmount 10.0.0.1 /mnt/nfs /export/shared + nsh> ls -l /mnt/nfs + /mnt/nfs: + drwxrwxrwx 4096 .. + drwxrwxrwx 4096 testdir/ + -rw-rw-rw- 6 ctest.txt + -rw-r--r-- 15 btest.txt + drwxrwxrwx 4096 . + nsh> echo "This is a test" >/mnt/nfs/testdir/testfile.txt + nsh> ls -l /mnt/nfs/testdir + /mnt/nfs/testdir: + -rw-rw-rw- 21 another.txt + drwxrwxrwx 4096 .. + drwxrwxrwx 4096 . + -rw-rw-rw- 16 testfile.txt + nsh> cat /mnt/nfs/testdir/testfile.txt + This is a test + +Configuring the NFS server (Ubuntu) +=================================== + +Setting up the server will be done in two steps: First, setting up the +configuration file for NFS, and then starting the NFS services. But +first, you need to install the nfs server on Ubuntu with these two +commands: + +.. code-block:: console + + # sudo apt-get install nfs-common + # sudo apt-get install nfs-kernel-server + +After that, we need to make or choose the directory we want to export +from the NFS server. In our case, we are going to make a new directory +called ``/export``. + +.. code-block:: console + + # sudo mkdir /export + + +It is important that ``/export`` directory allow access to everyone (777 +permissions) as we will be accessing the NFS share from the client with +no authentication. + +.. code-block:: console + + # sudo chmod 777 /export + +When all this is done, we will need to edit the configuration file to +set up an NFS server: ``/etc/exports``. This file contains a list of +entries; each entry indicates a volume that is shared and how it is +shared. For more information for a complete description of all the setup +options for this file you can check in the man pages (``man export``). + +An entry in ``/etc/exports`` will typically look like this: + +.. code-block:: + + directory machine1(option11,option12) + +So for our example we export ``/export`` to the client 10.0.0.2 add the +entry: + +.. code-block:: + + /export 10.0.0.2(rw) + +In our case we are using all the default options except for the ``ro`` +that we replaced with ``rw`` so that our client will have read and write +access to the directory that we are exporting. + +After we do all the require configurations, we are ready to start the +server with the next command: + +.. code-block:: console + + # sudo /etc/init.d/nfs-kernel-server start + +Note: If you later decide to add more NFS exports to the /etc/exports +file, you will need to either restart NFS daemon or run command +exportfs. + +.. code-block:: console + + # sudo /etc/init.d/nfs-kernel-server start + +Or + +.. code-block:: console + + # exportfs -ra + +Now we can check if the export directory and our mount point is properly +set up. + +.. code-block:: console + + # sudo showmount -e + # sudo showmount -a + +And also we can verify if NFS is running in the system with: + +.. code-block:: console + + # rpcinfo –p + program vers proto port + 100000 2 tcp 111 portmapper + 100000 2 udp 111 portmapper + 100011 1 udp 749 rquotad + 100011 2 udp 749 rquotad + 100005 1 udp 759 mountd + 100005 1 tcp 761 mountd + 100005 2 udp 764 mountd + 100005 2 tcp 766 mountd + 100005 3 udp 769 mountd + 100005 3 tcp 771 mountd + 100003 2 udp 2049 nfs + 100003 3 udp 2049 nfs + 300019 1 tcp 830 amd + 300019 1 udp 831 amd + 100024 1 udp 944 status + 100024 1 tcp 946 status + 100021 1 udp 1042 nlockmgr + 100021 3 udp 1042 nlockmgr + 100021 4 udp 1042 nlockmgr + 100021 1 tcp 1629 nlockmgr + 100021 3 tcp 1629 nlockmgr + 100021 4 tcp 1629 nlockmgr + + +Now your NFS sever is sharing ``/export`` directory to be accessed. diff --git a/doc/guides/usbtrace.rst b/doc/guides/usbtrace.rst new file mode 100644 index 00000000000..31089c125f5 --- /dev/null +++ b/doc/guides/usbtrace.rst @@ -0,0 +1,214 @@ +================ +USB Device Trace +================ + +**USB Device Tracing Controls**. The NuttX USB device subsystem supports +a fairly sophisticated tracing facility. The basic trace cabability is +controlled by these NuttX configuration settings: + + - ``CONFIG_USBDEV_TRACE``: Enables USB tracing + - ``CONFIG_USBDEV_TRACE_NRECORDS``: Number of trace entries to remember + +**Trace IDs**. The trace facility works like this: When enabled, USB +events that occur in either the USB device driver or in the USB class +driver are logged. These events are described in +``include/nuttx/usb/usbdev_trace.h``. The logged events are identified +by a set of event IDs: + +========================= ================================== +``TRACE_INIT_ID`` Initialization events +``TRACE_EP_ID`` Endpoint API calls +``TRACE_DEV_ID`` USB device API calls +``TRACE_CLASS_ID`` USB class driver API calls +``TRACE_CLASSAPI_ID`` Other class driver system API calls +``TRACE_CLASSSTATE_ID`` Track class driver state changes +``TRACE_INTENTRY_ID`` Interrupt handler entry +``TRACE_INTDECODE_ID`` Decoded interrupt event +``TRACE_INTEXIT_ID`` Interrupt handler exit +``TRACE_OUTREQQUEUED_ID`` Request queued for OUT endpoint +``TRACE_INREQQUEUED_ID`` Request queued for IN endpoint +``TRACE_READ_ID`` Read (OUT) action +``TRACE_WRITE_ID`` Write (IN) action +``TRACE_COMPLETE_ID`` Request completed +``TRACE_DEVERROR_ID`` USB controller driver error event +``TRACE_CLSERROR_ID`` USB class driver error event +========================= ================================== + +**Logged Events**. Each logged event is 32-bits in size and includes + + #. 8-bits of the trace ID (values associated with the above) + #. 8-bits of additional trace ID data, and + #. 16-bits of additional data. + +**8-bit Trace Data** The 8-bit trace data depends on the specific event +ID. As examples, + + - For the USB serial and mass storage class, the 8-bit event data is + provided in ``include/nuttx/usb/usbdev_trace.h``. + - For the USB device driver, that 8-bit event data is provided within + the USB device driver itself. So, for example, the 8-bit event data + for the LPC1768 USB device driver is found in + ``arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c``. + +**16-bit Trace Data**. The 16-bit trace data provided additional context +data relevant to the specific logged event. + +**Trace Control Interfaces**. Logging of each of these kinds events can +be enabled or disabled using the interfaces described in +``include/nuttx/usb/usbdev_trace.h``. + +**Enabling USB Device Tracing**. USB device tracing will be configured +if ``CONFIG_USBDEV`` and either of the following are set in the NuttX +configuration file: + + - ``CONFIG_USBDEV_TRACE``, or + - ``CONFIG_DEBUG_FEATURES and CONFIG_DEBUG_USB`` + +**Log Data Sink**. The logged data itself may go to either (1) an +internal circular buffer, or (2) may be provided on the console. If +``CONFIG_USBDEV_TRACE`` is defined, then the trace data will go to the +circular buffer. The size of the circular buffer is determined by +``CONFIG_USBDEV_TRACE_NRECORDS``. Otherwise, the trace data goes to +console. + +**Example**. Here is an example of USB trace output using +``apps/examples/usbserial`` for an LPC1768 platform with the following +NuttX configuration settings: + + - ``CONFIG_DEBUG_FEATURES``, ``CONFIG_DEBUG_INFO``, ``CONFIG_USB`` + - ``CONFIG_EXAMPLES_USBSERIAL_TRACEINIT``, + ``CONFIG_EXAMPLES_USBSERIAL_TRACECLASS``, + ``CONFIG_EXAMPLES_USBSERIAL_TRACETRANSFERS``, + ``CONFIG_EXAMPLES_USBSERIAL_TRACECONTROLLER``, + ``CONFIG_EXAMPLES_USBSERIAL_TRACEINTERRUPTS`` + +Console Output:: + + ABDE + usbserial_main: Registering USB serial driver + uart_register: Registering /dev/ttyUSB0 + usbserial_main: Successfully registered the serial driver + 1 Class API call 1: 0000 + 2 Class error: 19:0000 + usbserial_main: ERROR: Failed to open /dev/ttyUSB0 for reading: 107 + usbserial_main: Not connected. Wait and try again. + 3 Interrupt 1 entry: 0039 + 4 Interrupt decode 7: 0019 + 5 Interrupt decode 32: 0019 + 6 Interrupt decode 6: 0019 + 7 Class disconnect(): 0000 + 8 Device pullup(): 0001 + 9 Interrupt 1 exit: 0000 + +The numbered items are USB USB trace output. You can look in the file +``drivers/usbdev/usbdev_trprintf.c`` to see examctly how each output +line is formatted. Here is how each line should be interpreted: + +== ==================== ================ ================================== ================= +N. USB EVENT ID 8-bit EVENT DATA MEANING 16-bit EVENT DATA +1 TRACE_CLASSAPI_ID1 1 USBSER_TRACECLASSAPI_SETUP1 0000 +2 TRACE_CLSERROR_ID1 19 USBSER_TRACEERR_SETUPNOTCONNECTED1 0000 +3 TRACE_INTENTRY_ID1 1 LPC17_40_TRACEINTID_USB2 0039 +4 TRACE_INTDECODE_ID2 7 LPC17_40_TRACEINTID_DEVSTAT2 0019 +5 TRACE_INTDECODE_ID2 32 LPC17_40_TRACEINTID_SUSPENDCHG2 0019 +6 TRACE_INTDECODE_ID2 6 LPC17_40_TRACEINTID_DEVRESET2 0019 +7 TRACE_CLASS_ID1 3 (See TRACE_CLASSDISCONNECT1) 0000 +8 TRACE_DEV_ID1 6 (See TRACE_DEVPULLUP1) 0001 +9 TRACE_INTEXIT_ID1 1 LPC17_40_TRACEINTID_USB2 0000 +== ==================== ================ ================================== ================= + +NOTES: + + 1. See include/nuttx/usb/usbdev_trace.h + 2. See arch/arm/src/lpc17xx_40xx/lpc17_40_usbdev.c + +In the above example you can see that: + + - **1**. The serial class USB setup method was called for the USB + serial class. This is the corresponds to the following logic in + ``drivers/usbdev/pl2303.c``: + + .. code-block:: c + + static int pl2303_setup(FAR struct uart_dev_s *dev) + { + ... + usbtrace(PL2303_CLASSAPI_SETUP, 0); + ... + + - **2**. An error occurred while processing the setup command because + no configuration has yet been selected by the host. This corresponds + to the following logic in ``drivers/usbdev/pl2303.c``: + + .. code-block:: c + + static int pl2303_setup(FAR struct uart_dev_s *dev) + { + ... + /* Check if we have been configured */ + + if (priv->config == PL2303_CONFIGIDNONE) + { + usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_SETUPNOTCONNECTED), 0); + return -ENOTCONN; + } + ... + + - **3-6**. Here is a USB interrupt that suspends and resets the device. + - **7-8**. During the interrupt processing the serial class is + disconnected + - **9**. And the interrupt returns + +**USB Monitor**. The *USB monitor* is an application in the +``apps/system/usbmonitor`` that provides a convenient way to get debug +trace output. If tracing is enabled, the USB device will save encoded +trace output in in-memory buffer; if the USB monitor is also enabled, +that trace buffer will be periodically emptied and dumped to the system +logging device (the serial console in most configurations). The +following are some of the relevant configuration options: + +=========================================== =================================================== +Device Drivers -> USB Device Driver Support . +``CONFIG_USBDEV_TRACE=y`` Enable USB trace feature +``CONFIG_USBDEV_TRACE_NRECORDS=nnnn`` Buffer nnnn records in memory. If you lose trace data, +. then you will need to increase the size of this buffer +. (or increase the rate at which the trace buffer is emptied). +``CONFIG_USBDEV_TRACE_STRINGS=y`` Optionally, convert trace ID numbers to strings. +. This feature may not be supported by all drivers. +=========================================== =================================================== + +=========================================== =================================================== +Application Configuration -> NSH LIbrary . +``CONFIG_NSH_USBDEV_TRACE=n`` Make sure that any built-in tracing from NSH is disabled. +``CONFIG_NSH_ARCHINIT=y`` Enable this option only if your board-specific logic +. has logic to automatically start the USB monitor. +. Otherwise the USB monitor can be started or stopped +. with the usbmon_start and usbmon_stop commands from the NSH console. +=========================================== =================================================== + + + +=============================================== ============================================ +Application Configuration -> System NSH Add-Ons . +``CONFIG_USBMONITOR=y`` Enable the USB monitor daemon +``CONFIG_USBMONITOR_STACKSIZE=nnnn`` Sets the USB monitor daemon stack size to nnnn. The default is 2KiB. +``CONFIG_USBMONITOR_PRIORITY=50`` Sets the USB monitor daemon priority to nnnn. +. This priority should be low so that it does not +. interfere with other operations, but not so low that +. you cannot dump the buffered USB data sufficiently +. rapidly. The default is 50. +``CONFIG_USBMONITOR_INTERVAL=nnnn`` Dump the buffered USB data every nnnn seconds. +. If you lose buffered USB trace data, then dropping +. this value will help by increasing the rate at which +. the USB trace buffer is emptied. +``CONFIG_USBMONITOR_TRACEINIT=y`` Selects which USB event(s) that you want to be traced. +``CONFIG_USBMONITOR_TRACECLASS=y`` . +``CONFIG_USBMONITOR_TRACETRANSFERS=y`` . +``CONFIG_USBMONITOR_TRACECONTROLLER=y`` . +``CONFIG_USBMONITOR_TRACEINTERRUPTS=y`` . +=============================================== ============================================ + + +NOTE: If USB debug output is also enabled, both outputs will appear on +the serial console. However, the debug output will be asynchronous with +the trace output and, hence, difficult to interpret. diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 00000000000..ace34593a5b --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,30 @@ +=================== +NuttX Documentation +=================== + +NuttX is a real-time operating system (RTOS) with an emphasis on standards compliance and small footprint. Scalable from 8-bit to 32-bit microcontroller environments, the primary governing standards in NuttX are Posix and ANSI standards. Additional standard APIs from Unix and other common RTOS’s (such as VxWorks) are adopted for functionality not available under these standards, or for functionality that is not appropriate for deeply-embedded environments (such as fork()). + +.. warning:: + These pages are meant to be an experiment in replacing the `Apache NuttX Documentation `_ + with something easier to navigate, extend, and modify. + This is a work in progress, some formatting issues may still be present and are being worked on. Also, some links may be broken. Please + refer to :doc:`contributing documentation` to propose fixes/improvements. + +Last Updated: |today| + +.. toctree:: + :caption: Contents: + :maxdepth: 2 + + Home + introduction/index.rst + quickstart/index.rst + reference/index.rst + components/index.rst + applications/index.rst + boards/index.rst + guides/index.rst + releases/index.rst + contributing/index.rst + +.. include:: substitutions.rst diff --git a/doc/introduction/about.rst b/doc/introduction/about.rst new file mode 100644 index 00000000000..2ac32356dc6 --- /dev/null +++ b/doc/introduction/about.rst @@ -0,0 +1,277 @@ +=========== +About NuttX +=========== + +**Goals**. NuttX is a real time embedded operating system (RTOS). Its goals are: + +* **Small Footprint** + Usable in all but the tightest micro-controller environments, the focus is on the + tiny-to-small, deeply embedded environment. + +* **Rich Feature OS Set** + The goal is to provide implementations of most standard POSIX OS interfaces to support a + rich, multi-threaded development environment for deeply embedded processors. + + NON-GOALS: It is not a goal to provide the level of OS features like those provided by Linux. In order to work with + smaller MCUs, small footprint must be more important than an extensive feature set. But standard compliance is more + important than small footprint. Surely a smaller RTOS could be produced by ignoring standards. Think of NuttX is a + tiny Linux work-alike with a much reduced feature set. + +* **Highly Scalable** + Fully scalable from tiny (8-bit) to moderate embedded (32-bit). Scalability with rich feature set + is accomplished with: Many tiny source files, link from static libraries, highly configurable, + use of weak symbols when available. + +* **Standards Compliance** + NuttX strives to achieve a high degree of standards compliance. The primary governing standards + are POSIX and ANSI standards. Additional standard APIs from Unix and other common RTOS's are + adopted for functionality not available under these standards or for functionality that is not + appropriate for the deeply-embedded RTOS (such as ``fork()``). + + Because of this standards conformance, software developed under other standard OSs (such as + Linux) should port easily to NuttX. + +* **Real-Time** + Fully pre-emptible; fixed priority, round-robin, and "sporadic" scheduling. + +* **Totally Open** + Non-restrictive BSD license. + +* **GNU Toolchains** + Compatible GNU toolchains based on `buildroot `__ available for `download `__ + to provide a complete development environment for many architectures. + + +**Feature Set**. Key features of NuttX include: + +* **Standards Compliant Core Task Management** + + * Fully pre-emptible. + * Naturally scalable. + * Highly configurable. + * Easily extensible to new processor architectures, SoC architecture, or board architectures. A `Porting Guide `__ is available. + * FIFO and round-robin scheduling. + * Realtime, deterministic, with support for priority inheritance + * Tickless Operation + * POSIX/ANSI-like task controls, named message queues, counting semaphores, clocks/timers, + signals, pthreads, robust mutexes, cancellation points, environment variables, filesystem. + * Standard default signal actions (optional). + * VxWorks-like task management and watchdog timers. + * BSD socket interface. + * Extensions to manage pre-emption. + * Optional tasks with address environments (*Processes*). + * Loadable kernel modules; lightweight, embedded shared libraries. + * Memory Configurations: (1) Flat embedded build, (2) Protected build with MPU, and (3) Kernel build with MMU. + * Memory Allocators: (1) standard heap memory allocation, (2) granule allocator, (3) shared memory, and + (4) dynamically sized, per-process heaps. + * Inheritable "controlling terminals" and I/O re-direction. + * Pseudo-terminals + * On-demand paging. + * System logging. + * May be built either as an open, flat embedded RTOS or as a separately built, secure, monolithic kernel with a + system call interface. + * Built-in, per-thread CPU load measurements. + * Well documented in the NuttX User Guide. + +* **File system** + + * Tiny, in-memory, root pseudo-file-system. + * Virtual file system (VFS) supports drivers and mountpoints. + * Mount-able volumes. Bind mountpoint, filesystem, and block device driver. + * Generic system logging (SYSLOG) support. + * FAT12/16/32 filesystem support with optional FAT long file name support1. + * NFS Client. Client side support for a Network File System (NFS, version 3, UDP). + * NXFFS. The tiny NuttX wear-leveling FLASH file system. + * SMART. FLASH file system from Ken Pettit. + * SPIFFS. FLASH file system, originally by Peter Anderson. + * LittleFS. FLASH file system from ARM mbed.. + * ROMFS filesystem support (XIP capable). + * CROMFS (Compressed ROMFS) filesystem support. + * TMPFS RAM filesystem support. + * BINFS pseudo-filesystem support. + * HOSTFS filesystem support (simulation only). + * Union filesystem - Supports combining and overlaying file systems. + * UserFS - User application file system. + * ``procfs/`` pseudo-filesystem support. + * A `binary loader `__ with support for the following formats: + + - Separately linked ELF modules. + - Separately linked `NXFLAT `__ modules. NXFLAT is a binary format that can be XIP from a + file system. + - "Built-In" applications. + + * PATH variable support. + * File transfers via TFTP and FTP (``get`` and ``put``), HTML (``wget``), and Zmodem (``sz`` + and ``rz``). Intel HEX file conversions. + + * FAT long file name support may be subject to certain Microsoft patent restrictions if enabled. + See the top-level ``COPYING`` file for details. + +* **Device Drivers** + + * Supports character and block drivers as well as specialized driver interfaces. + * Full VFS integration. Asynchronous I/O (AIO) + * Network, USB (host), USB (device), serial, I2C, I2S, NAND, CAN, ADC, DAC, PWM, Quadrature Encoder, I/O Expander, Wireless, + generic timer, and watchdog timer driver architectures. + * RAMDISK, pipes, FIFO, ``/dev/null``, ``/dev/zero``, ``/dev/random``, and loop drivers. + * Generic driver for SPI-based or SDIO-based MMC/SD/SDH cards. + * Graphics: framebuffer drivers, graphic- and segment-LCD drivers. VNC server. + * Audio subsystem: CODECs, audio input and output drivers. Command line and graphic media player applications. + * Cryptographic subsystem. + * `Power Management `__ sub-system. + * ModBus support provided by built-in `FreeModBus `__ version 1.5.0. + +* **C/C++ Libraries** + + * Standard C Library Fully integrated into the OS. + * Includes floating point support via a Standard Math Library. + * Add-on `uClibc++ `__ module provides Standard C++ Library (LGPL). + +* **Networking** + + * Multiple network interface support; multiple network link layer support. + * IPv4, IPv6, TCP/IP, UDP, ICMP, ICMPv6, IGMPv2 and MLDv1/v2 (client) stacks. + * IP Forwarding (routing) support. + * User space stacks. + * Stream and datagram sockets. + * Address Families: IPv4/IPv6 (``AF_INET``/``AF_INET6``), Raw socket (``AF_PACKET``), raw IEEE + 802.15.4 (``AF_IEEE802154``), raw Bluetooth (``AF_BLUETOOTH``), and local, Unix domain socket support (``AF_LOCAL``). + * Special ``INET`` protocol sockets: Raw ICMP and ICMPv6 protocol ping sockets (``IPPROTO_ICMP``/``IPPROTO_ICMP6``). + * Custom user sockets. + * IP Forwarding. + * DNS name resolution / NetDB + * IEEE 802.11 FullMac + * Radio Network Drivers: IEEE 802.15.4 MAC, Generic Packet Radio, Bluetooth LE + * 6LoWPAN for radio network drivers (IEEE 802.15.4 MAC and generic packet radios) + * SLIP, TUN/PPP, Local loopback devices + * A port cJSON + * Small footprint. + * BSD compatible socket layer. + * Networking utilities (DHCP server and client, SMTP client, Telnet server and client, FTP server and + client, TFTP client, HTTP server and client, PPPD, NTP client). Inheritable TELNET server sessions (as "controlling + terminal"). VNC server. + * ICMPv6 autonomous auto-configuration + * NFS Client. Client side support for a Network File System (NFS, version 3, UDP). + * A NuttX port of Jeff Poskanzer's `THTTPD `__ + HTTP server integrated with the NuttX `binary loader `__ to provide true, embedded CGI. + * PHY Link Status Management. + * UDP Network Discovery (Contributed by Richard Cochran). + * XML RPC Server (Contributed by Richard Cochran). + * Support for networking modules (e.g., ESP8266). + +* **FLASH Support** + + * *MTD*\ -inspired interface for *M*\ emory *T*\ echnology *D*\ evices. + * NAND support. + * *FTL*. Simple *F*\ lash *T*\ ranslation *L*\ ayer support file systems on FLASH. + * Wear-Leveling FLASH File Systems: NXFFS, SmartFS, SPIFFS. + * Support for SPI-based FLASH and FRAM devices. + +* **USB Host Support** + + * USB host architecture for USB host controller drivers and device-dependent USB class drivers. + * USB host controller drivers available for the Atmel SAMA5Dx, NXP LPC17xx, LPC31xx, and STmicro STM32 + * Device-dependent USB class drivers available for USB mass storage, CDC/ACM serial, HID keyboard, and HID mouse. + * Seam-less support for USB hubs. + +* **USB Device Support** + + * *Gadget*-like architecture for USB device controller drivers and device-dependent USB class drivers. + * USB device controller drivers available for the most MCU architectures includeing PIC32, + Atmel AVR, SAM3, SAM4, SAMv7, and SAMA5Dx, NXP/Freescale LPC17xx, LPC214x, LPC313x, LPC43xx, and + Kinetis, Silicon Laboraties EFM32, STMicro STM32 F1, F2, F3, F4, and F7, TI DM320, and others. + * Device-dependent USB class drivers available for USB serial (CDC/ACM and a PL2303 emulation), + for USB mass storage, for USB networking (RNDIS and CDC/ECM), DFU, and for a dynamically + configurable, composite USB devices. + * Built-in `USB device `__ and USB host trace functionality for non-invasive USB debug. + +* **Graphics Support** + + * Framebuffer drivers. + * Graphic LCD drivers for both parallel and SPI LCDs and OLEDs. + * Segment LCD drivers. + * VNC Server. + * ``mmap``-able, framebuffer character driver. + * NX: A graphics library, tiny windowing system and tiny font support that works with either + framebuffer or LCD drivers. Documented in the `NX Graphics Subsystem `__ + manual. + * Font management sub-system. + * `NxWidgets `__: NXWidgets is library of graphic objects, or "widgets," (labels, + buttons, text boxes, images, sliders, progress bars, etc.). NXWidgets is written in C++ and + integrates seamlessly with the NuttX NX graphics and font management subsystems. + * `NxWM `__: NxWM is the tiny NuttX window manager based on NX and NxWidgets. + +* **Input Devices** + + * Touchscreen, USB keyboard, GPIO-based buttons and keypads. + +* **Analog Devices** + + * Support for Analog-to-Digital conversion (ADC), Digital-to-Analog conversion (DAC), multiplexers, and + amplifiers. + +* **Motor Control** + + * Pulse width modulation (PWM) / Pulse count modulation. + +* **NuttX Add-Ons**. + The following packages are available to extend the basic NuttX feature set: + + * **NuttShell (NSH)** + A small, scalable, bash-like shell for NuttX with rich feature set and small footprint. See the `NuttShell User Guide `__. + * **BAS 2.4** + Seamless integration of Michael Haardt's BAS 2.4: "Bas is an interpreter for the classic dialect of the programming language BASIC. It is pretty compatible to typical BASIC interpreters of the 1980s, unlike some other UNIX BASIC interpreters, that implement a different syntax, breaking compatibility to existing programs. Bas offers many ANSI BASIC statements for structured programming, such as procedures, local variables and various loop types. Further there are matrix operations, automatic LIST indentation and many statements and functions found in specific classic dialects. Line numbers are not required." + +**Look at all those files and features... How can it be a tiny OS?**. The NuttX feature list (above) is fairly long and if you +look at the NuttX source tree, you will see that there are hundreds of source files comprising NuttX. How can NuttX be a tiny +OS with all of that? + + * **Lots of Features -- More can be smaller!** + + The philosophy behind that NuttX is that lots of features are great... *BUT* also that if you + don't use those features, then you should not have to pay a penalty for the unused features. + And, with NuttX, you don't! If you don't use a feature, it will not be included in the final + executable binary. You only have to pay the penalty of increased footprint for the features that + you actually use. + + Using a variety of technologies, NuttX can scale from the very tiny to the moderate-size system. + I have executed NuttX with some simple applications in as little as 32K *total* memory (code and + data). On the other hand, typical, richly featured NuttX builds require more like 64K (and + if all of the features are used, this can push 100K). + + * **Many, many files -- More really is smaller!** + + One may be intimidated by the size NuttX source tree. There are hundreds of source files! How can + that be a tiny OS? Actually, the large number of files is one of the tricks to keep NuttX small + and as scalable as possible. Most files contain only a single function. Sometimes just one tiny + function with only a few lines of code. Why? + + - **Static Libraries**. + Because in the NuttX build processed, objects are compiled and saved into *static libraries* + (*archives*). Then, when the file executable is linked, only the object files that are + needed are extracted from the archive and added to the final executable. By having many, + many tiny source files, you can assure that no code that you do not execute is ever + included in the link. And by having many, tiny source files you have better granularity -- + if you don't use that tiny function of even just a few lines of code, it will not be + included in the binary. + +* **Other Tricks** + + As mentioned above, the use of many, tiny source files and linking from static libraries + keeps the size of NuttX down. Other tricks used in NuttX include: + + - **Configuration Files**. + + Before you build NuttX, you must provide a configuration file that specifies what features you plan to use and + which features you do not. This configuration file contains a long list of settings that control what is + built into NuttX and what is not. There are hundreds of such settings (see the + `Configuration Variable Documentation `__ + for a partial list that excludes platform specific settings). These many, many configuration options allow + NuttX to be highly tuned to meet size requirements. The downside to all of these configuration options is that + it greatly complicates the maintenance of NuttX -- but that is my problem, not yours. - + + - **Weak Symbols** + The GNU toolchain supports *weak* symbols and these also help to keep the size of NuttX down. + Weak symbols prevent object files from being drawn into the link even if they are accessed from source code. + Careful use of weak symbols is another trick for keep unused code out of the final binary. + diff --git a/doc/introduction/detailed_support.rst b/doc/introduction/detailed_support.rst new file mode 100644 index 00000000000..75c6b8a4354 --- /dev/null +++ b/doc/introduction/detailed_support.rst @@ -0,0 +1,3536 @@ +========================= +Detailed Platform Support +========================= + +.. note:: This is a work in progress, the details of each board is not completely migrated as it is possible that this information will be moved to the "supported boards" section and improved. + +.. warning:: The following list is not yet completely migrated, in the meantime + you can see this `here `__ + +**Details**. The details, caveats and fine print follow. For even more +information see the *README* files that can be found +`here `__. + + + +Linux User Mode. + +| + +A user-mode port of NuttX to the x86 Linux/Cygwin platform is available. +The purpose of this port is primarily to support OS feature development. + + + +ARM7TDMI. + +| + +TI TMS320C5471 (also called **C5471** or **TMS320DA180** or **DA180**). +NuttX operates on the ARM7 of this dual core processor. This port uses +the `Spectrum Digital `__ evaluation +board with a GNU arm-nuttx-elf toolchain\* under Linux or Cygwin. + +| + +-------------- + +| + +NXP LPC214x. Support is provided for the NXP LPC214x family of +processors. In particular, support is provided for (1) the mcu123.com +lpc214x evaluation board (LPC2148) and (1) the The0.net ZPA213X/4XPA +development board (with the The0.net UG-2864AMBAG01 OLED) This port also +used the GNU arm-nuttx-elf toolchain\* under Linux or Cygwin. + +| + +-------------- + +| + +NXP LPC2378. Support is provided for the NXP LPC2378 MCU. In particular, +support is provided for the Olimex-LPC2378 development board. This port +was contributed by Rommel Marcelo is was first released in NuttX-5.3. +This port also used the GNU arm-nuttx-elf toolchain\* under Linux or +Cygwin. + +| + +-------------- + +| + +STMicro STR71x. Support is provided for the STMicro STR71x family of +processors. In particular, support is provided for the Olimex STR-P711 +evaluation board. This port also used the GNU arm-nuttx-elf toolchain\* +under Linux or Cygwin. + + + +ARM920T. + +| + +Freescale MC9328MX1 or i.MX1. This port uses the Freescale MX1ADS +development board with a GNU arm-nuttx-elf toolchain\* under either +Linux or Cygwin. + + + +ARM926EJS. + +| + +TI TMS320DM320 (also called **DM320**). NuttX operates on the ARM9 of +this dual core processor. This port uses the `Neuros +OSD `__ +with a GNU arm-nuttx-elf toolchain\* under Linux or Cygwin. The port was +performed using the OSD v1.0, development board. + +| + +-------------- + +| + +NXP LPC3131. Two boards based on the NXP LPC3131 are supported: + +- First, a port for the NXP + `LPC3131 `__ + on the `Embedded Artists + EA3131 `__ + development board was first released in NuttX-5.1 (but was not + functional until NuttX-5.2). + +- A second port to the NXP + `LPC3131 `__ + on the `Olimex + LPC-H3131 `__ + development board was added in NuttX-6.32. + +| + +-------------- + +| + +NXP LPC315x. Support for the NXP +`LPC315x `__ +family has been incorporated into the code base as of NuttX-6.4. Support +was added for the Embedded Artists EA3152 board in NuttX-6.11. + + + +Other ARMv4. + +| + +MoxaRT A port to the Moxa NP51x0 series of 2-port advanced +RS-232/422/485 serial device servers was contributed by Anton D. +Kachalov in NuttX-7.11. This port includes a NuttShell (NSH) +configuration with support for the Faraday FTMAC100 Ethernet MAC Driver. + + + +ARM1176JZ. + +| + +Broadcom BCM2708. Very basic support for the Broadcom BCM2708 was +released with NuttX-7.23. + +Raspberry Pi Zero. This support was provided for the Raspberry Pi Zero +which is based on the BCM2835. Basic logic is in place but the port is +incomplete and completely untested as of the NuttX-7.23 released. Refer +to the NuttX board +`README `__ +file for further information. + +**Obsoleted:**: Support for the Raspberry Pi Zero was never completed. +The incomplete port along with all support for the BCM2708 was removed +from the repository with the NuttX-7.28 release but can still be be +found in the *Obsoleted* repository. + + + +ARM Cortex-A5. + +| + +Atmel SAMA5D2. + +- **Atmel SAMA5D2 Xplained Ultra development board**. This is the port + of NuttX to the Atmel SAMA5D2 Xplained Ultra development board. This + board features the Atmel SAMA5D27 microprocessor. + +| + +-------------- + +| + +Atmel SAMA5D3. There are ports to two Atmel SAMA5D3 boards: + +- **Atmel SAMA5D3\ x-EK development boards**. This is the port of NuttX + to the Atmel SAMA5D3\ *x*-EK development boards (where *x*\ =1,3,4, + or 5). These boards feature the Atmel SAMA5D3\ *x* microprocessors. + Four different SAMA5D3\ *x*-EK kits are available + + - SAMA5D31-EK with the + `ATSAMA5D31 `__ + - SAMA5D33-EK with the + `ATSAMA5D33 `__ + - SAMA5D34-EK with the + `ATSAMA5D34 `__ + - SAMA5D35-EK with the + `ATSAMA5D35 `__ + + The each kit consist of an identical base board with different + plug-in modules for each CPU. All four boards are supported by NuttX + with a simple reconfiguration of the processor type. + + **STATUS**. Initial support for the SAMA5D3x-EK was released in + NuttX-6.29. That initial support was minimal: There are simple test + configurations that run out of internal SRAM and extended + configurations that run out of the on-board NOR FLASH: + + - A barebones NuttShell (`NSH `__) configuration + that can be used as the basis for further application development. + - A full-loaded NuttShell (`NSH `__) configuration + that demonstrates all of the SAMA5D3x features. + + The following support was added in Nuttx 6.30: + + - DMA support, and + - PIO interrupts, + + And drivers for + + - SPI (with DMA support), + - AT25 Serial Flash, + - Two Wire Interface (TWI), and + - HSMCI memory cards. + + NuttX-6.30 also introduces full USB support: + + - High speed device controller driver, + - OHCI (low- and full-speed) and + - EHCI (high-speed) host controller driver support. + + With NuttX-6.31, these additional drivers were added: + + - A 10/100Base-T Ethernet (EMAC) driver, + - A 1000Base-T Ethernet (GMAC) driver, + - A Real Time Clock (RTC) driver and integrated with the NuttX + system time logic + - ``/dev/random`` using the SAMA5D3x True Random Number Generator + (TRNG), + - A Watchdog Timer (WDT) driver, + - A Timer/Counter (TC) library with interface that make be used by + other drivers that need timer support, + - An ADC driver that can collect multiple samples using the + sequencer, can be trigger by a timer/counter, and supports DMA + data transfers, + - A touchscreen driver based on the special features of the SAMA5D3 + ADC peripheral, An LCD controller (LCDC) frame buffer driver, and + - A CAN driver (Testing of the CAN has been delayed because of + cabling issues). + + Additional board configurations were added to test and demonstrate + these new drivers including new graphics and NxWM configurations. + + These drivers were added in NuttX-6.32: + + - A PWM driver with DMA support + - An SSC-based I2S driver + - Support for Programmable clock outputs + - NAND support including support for the PMECC hardware ECC and for + DMA transfers. + + DBGU support was added in NuttX-7.2 (primarily for the SAMA5D3 + Xplained board). + + NuttX-7.4 added support for the on-board WM8904 CODEC chip and for + *Tickless* operation. + + Refer to the NuttX board + `README `__ + file for further information. + +**Atmel SAMA5D3 Xplained development board** This is the port of NuttX +to the Atmel SAMA5D3 Xplained development board. The board features the +Atmel SAMA5D36 microprocessor. See the `Atmel +Website `__ for additional +information about this board. + +**STATUS**. This port is complete as of this writing and ready for +general use. The basic port is expected to be simple because of the +similarity to the SAMAD3\ *x*-EK boards and is available in the NuttX +7.2 release. + +Most of the drivers and capabilities of the SAMA5D3x-EK boards can be +used with the SAMA5D3 Xplained board. The primary difference between the +ports is that the SAMA5D3x-EK supports NOR FLASH and NuttX can be +configured to boot directly from NOR FLASH. The SAMA5D3 Xplained board +does not have NOR FLASH and, as a consequence NuttX must boot into SDRAM +with the help of U-Boot. + +Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +Atmel SAMA5D4. There is a port in progress on one Atmel SAMA5D4 board: + +- **Atmel SAMA5D4-EK/MB development boards** This is the port of NuttX + to the Atmel SAMA5D4-MB Rev C. development board (which should be + compatible with the SAMA5D4-EK). These boards feature the Atmel + SAMA5D44 microprocessors with compatibility with most of the SAMA5D3 + peripherals. + + **STATUS**. At the time of the release of NuttX-7.3, the basic port + for the SAMA5D4-MB was complete. The board had basic functionality. + But full functionality was not available until NuttX-7.4. In + NuttX-7.4 support was added for the L2 cache, many security features, + XDMAC, HSMCI and Ethernet integrated with XDMAC, the LCDC, TWI, SSC, + and most of the existing SAMA5 drivers. Timers were added to support + *Tickless* operation. The TM7000 LCDC with the maXTouch multi-touch + controller are also fully support in a special NxWM configuration for + that larger display. Support for a graphics media player is included + (although there were issues with the WM8904 audio CODEC on my board). + An SRAM bootloader was also included. Refer to the NuttX board + `README `__ + file for current status. + +| + +-------------- + +| + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain, or 4) Native Windows. All testing has been performed +with the CodeSourcery toolchain (GCC version 4.7.3) in the Cygwin +environment under Windows. + + + +ARM Cortex-A8. + +| + +Allwinner A10. These following boards are based on the Allwinner A10 +have are supported by NuttX: + +- **pcDuino v1**. A port of NuttX to the pcDuino v1 board was first + released in NuttX-6.33. See http://www.pcduino.com/ for information + about pcDuino Lite, v1, and v2 boards. These boards are based around + the Allwinner A10 Cortex-A8 CPU. This port was developed on the v1 + board, but the others may be compatible: + + Refer to the NuttX board + `README `__ + file for further information. + + **STATUS**. This port was an experiment was was not completely + developed. This configuration builds and runs an NuttShell (NSH), but + only if a patch to work around some issues is applied. While not + ready for "prime time", the pcDuino port is functional and could the + basis for a more extensive development. There is, at present, no work + in progress to extend this port, however. + +| + +-------------- + +| + +TI/Sitara AM335x. These following boards are based on the TI/Sitara +AM335x are supported by NuttX: + +- **Beaglebone Black**. A port of NuttX to the Beaglebone Black board + was first released in NuttX-7.28. This port was contributed by Petro + Karashchenko. This board is based on the TI/Sitara AM3358 Cortex-A8 + CPU running 1GHz. + + - **NuttX-7.28**. This initial port in NuttX-7.28 is very sparse. + While not ready for prodcution use, the Beaglebone Black port is + functional and will be the basis for a more extensive development. + Additional work in progress to extend this port and more capable + is anticipated in NuttX-7.29. + - **NuttX-9.0** CAN support was added. Clock Configuration was + added. + - **NuttX-7.31**. An LCD driver was added in NuttX-7.31. + + Refer to the Beaglebone Black board + `README `__ + file for further, up-to-date information. + + + +ARM Cortex-A9. + +| + +NXP/Freescale i.MX6. The basic port has been completed for the following +i.MX6 board + +- **Sabre-6Quad**. This is a port to the NXP/Freescale Sabre-6Quad + board. Refer to the NuttX board + `README `__ + file for further information. + + **STATUS:** The basic, minimal port is code complete and introduced + in NuttX-7.15, but had not yet been tested at that time due to the + inavailability of hardware. This basic port was verified in the + NuttX-7.16 release, however. The port is still minimal and more + device drivers are needed to make the port usable. + + Basic support of NuttX running in SMP mode on the i.MX6Q was also + accomplished in NuttX-7.16. However, there are still known issues + with SMP support on this platform as described in the + `README `__ + file for the board. + + + +ARM Cortex-R4. + +| + +TI/Hercules TMS570LS04xx. A port is available for the Texas Instruments +Hercules TMS570LS04x/03x LaunchPad Evaluation Kit (*LAUNCHXL-TMS57004*) +featuring the Hercules TMS570LS0432PZ chip. + +| + +TI/Hercules TMS570LS31xx. Architecture support for the TMS570LS3137ZWT +part was added in NuttX 7.25 by Ivan Ucherdzhiev. Ivan also added +support for the TI Hercules TMS570LS31x USB Kit. + + + +ARM Cortex-M0/M0+. + +| + +nuvoTon NUC120. This is a port of NuttX to the nuvoTon NuTiny-SDK-NUC120 +that features the NUC120LE3AN MCU. + +**STATUS**. Initial support for the NUC120 was released in NuttX-6.26. +This initial support is very minimal: There is a NuttShell +(`NSH `__) configuration that might be the basis for an +application development. As of this writing, more device drivers are +needed to make this a more complete port. Refer to the NuttX board +`README `__ +file for further information. + +**Memory Usage**. For a full-featured RTOS such as NuttX, providing +support in a usable and meaningful way within the tiny memories of the +NUC120 demonstrates the scalability of NuttX. The NUC120LE2AN comes in a +48-pin package and has 128KB FLASH and 16KB of SRAM. When running the +NSH configuration (itself a full up application), there is still more +than 90KB of FLASH and 10KB or SRAM available for further application +development). + +Static memory usage can be shown with ``size`` command: + +NuttX, the NSH application, and GCC libraries use 34.2KB of FLASH +leaving 93.8KB of FLASH (72%) free from additional application +development. Static SRAM usage is about 1.2KB (<4%) and leaves 14.8KB +(86%) available for heap at runtime. SRAM usage at run-time can be shown +with the NSH ``free`` command: + +You can see that 10.0KB (62%) is available for further application +development. + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain, or 4) Native Windows. A DIY toolchain for Linux or +Cygwin is provided by the NuttX +`buildroot `__ +package. + +| + +-------------- + +| + +FreeScale KL25Z. There are two board ports for the KL25Z parts: + +**Freedom KL25Z**. This is a port of NuttX to the Freedom KL25Z board +that features the MKL25Z128 Cortex-M0+ MCU, 128KB of FLASH and 16KB of +SRAM. See the +`Freescale `__ +website for further information about this board. + +**PJRC Teensy-LC**. This is a port of NuttX to the PJRC Teensy-LC board +that features the MKL25Z64 Cortex-M0+ MCU, 64KB of FLASH and 8KB of +SRAM. The Teensy LC is a DIP style breakout board for the MKL25Z64 and +comes with a USB based bootloader. See the +`Freescale `__ +website for further information about this board. + +| + +-------------- + +| + +FreeScale Freedom KL26Z. This is a port of NuttX to the Freedom KL25Z +board that features the MK26Z128VLH4 Cortex-M0+ MCU, 128KB of FLASH and +16KB of SRAM. See the +`Freescale `__ +website for further information about this board. + +| + +-------------- + +| + +Atmel SAMD20. The port of NuttX to the Atmel SAMD20-Xplained Pro +development board. This board features the ATSAMD20J18A MCU (Cortex-M0+ +with 256KB of FLASH and 32KB of SRAM). + +| + +-------------- + +| + +Atmel SAMD21. There two boards supported for the SAMD21: + +#. The port of NuttX to the Atmel SAMD21-Xplained Pro development board + added in NuttX-7.11, and +#. The port of NuttX to the Arduino-M0 contributed by Alan Carvalho de + Assis in NuttX-8.2. The initial release included *nsh* and *usbnsh* + configurations. + +| + +-------------- + +| + +Atmel SAML21. The port of NuttX to the Atmel SAML21-Xplained Pro +development board. This board features the ATSAML21J18A MCU (Cortex-M0+ +with 256KB of FLASH and 32KB of SRAM). + +| + +-------------- + +| + +NXP LPC11xx. Support is provided for the NXP LPC11xx family of +processors. In particular, support is provided for LPCXpresso LPC1115 +board. This port was contributed by Alan Carvalho de Assis. + +| + +-------------- + +| + +NXP S32K11x. Support is provided for the NXP S32K11x family of +processors and, in particular, the S32K118EVB development board. + + + +ARM Cortex-M3. + +| + +TI/Stellaris LM3S6432. This is a port of NuttX to the Stellaris RDK-S2E +Reference Design Kit and the MDL-S2E Ethernet to Serial module +(contributed by Mike Smith). + +| + +-------------- + +| + +TI/Stellaris LM3S6432S2E. This port uses Serial-to-Ethernet Reference +Design Kit (`RDK-S2E `__) and has +similar support as for the other Stellaris family members. A +configuration is available for the NuttShell (NSH) (see the `NSH User +Guide `__). The NSH +configuration including networking support with a Telnet NSH console. +This port was contributed by Mike Smith. + +| + +-------------- + +| + +TI/Stellaris LM3S6918. This port uses the +`Micromint <%20http://www.micromint.com/>`__ Eagle-100 development board +with a GNU arm-nuttx-elf toolchain\* under either Linux or Cygwin. + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain (CodeSourcery or devkitARM), or 4) Native Windows. A +DIY toolchain for Linux or Cygwin is provided by the NuttX +`buildroot `__ +package. + +| + +-------------- + +| + +TI/Stellaris LM3S6965. This port uses the Stellaris LM3S6965 Ethernet +Evaluation Kit with a GNU arm-nuttx-elf toolchain\* under either Linux +or Cygwin. + +**Development Environments:** See the Eagle-100 LM3S6918 above. + +| + +-------------- + +| + +TI/Stellaris LM3S8962. This port uses the Stellaris EKC-LM3S8962 +Ethernet+CAN Evaluation Kit with a GNU arm-nuttx-elf toolchain\* under +either Linux or Cygwin. Contributed by Larry Arnold. + +| + +-------------- + +| + +TI/Stellaris LM3S9B92. Architectural support for the LM3S9B92 was +contributed by Lwazi Dube in NuttX 7.28. No board support for boards +using the LM3S9B92 are currently available. + +| + +-------------- + +| + +TI/Stellaris LM3S9B96. Header file support was contributed by Tiago +Maluta for this part. Jose Pablo Rojas V. is used those header file +changes to port NuttX to the TI/Stellaris EKK-LM3S9B96. That port was +available in the NuttX-6.20 release. Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +TI/SimpleLink CC13x0. Basic, unverified architectural support for the +CC13x0 was added in NuttX-7.28. This is a work in progress and, with any +luck, a fully verified port will be available in NuttX-7.29. + +| + +-------------- + +| + +SiLabs EFM32 Gecko. This is a port for the Silicon Laboratories' EFM32 +*Gecko* family. Board support is available for the following: + +#. **SiLabs EFM32 Gecko Starter Kit (EFM32-G8XX-STK)**. The Gecko + Starter Kit features: + + - EFM32G890F128 MCU with 128 kB flash and 16 kB RAM + - 32.768 kHz crystal (LXFO) and 32 MHz crystal (HXFO) + - Advanced Energy Monitoring + - Touch slider + - 4x40 LCD + - 4 User LEDs + - 2 pushbutton switches + - Reset button and a switch to disconnect the battery. + - On-board SEGGER J-Link USB emulator + - ARM 20 pin JTAG/SWD standard Debug in/out connector + + **STATUS**. The basic port is verified and available now. This + includes on-board LED and button support and a serial console + available on LEUART0. A single configuration is available using the + NuttShell NSH and the LEUART0 serial console. DMA and USART-based SPI + supported are included, but not fully tested. + + Refer to the EFM32 Gecko Starter Kit + `README.txt `__ + file for further information. + +#. **Olimex EFM32G880F120-STK**. This board features: + + - EFM32G880F128 with 128 kB flash and 16 kB RAM + - 32.768 kHz crystal (LXFO) and 32 MHz crystal (HXFO) + - LCD custom display + - DEBUG connector with ARM 2x10 pin layout for programming/debugging + with ARM-JTAG-EW + - UEXT connector + - EXT extension connector + - RS232 connector and driver + - Four user buttons + - Buzzer + + **STATUS**. The board support is complete but untested because of + tool-related issues. An OpenOCD compatible, SWD debugger would be + required to make further progress in testing. + + Refer to the Olimex EFM32G880F120-STK + `README.txt `__ + for further information. + +| + +-------------- + +| + +SiLabs EFM32 Giant Gecko. This is a port for the Silicon Laboratories' +EFM32 *Giant Gecko* family. This board features the EFM32GG990F1024 MCU +with 1 MB flash and 128 kB RAM. + +Board support is available for the following: + +- **SiLabs EFM32 Giant Gecko Starter Kit t (EFM32GG-STK3700)**. The + Gecko Starter Kit features: + + - EFM32GG990F1024 MCU with 1 MB flash and 128 kB RAM + - 32.768 kHz crystal (LXFO) and 48 MHz crystal (HXFO) + - 32 MB NAND flash + - Advanced Energy Monitoring + - Touch slider + - 8x20 LCD + - 2 user LEDs + - 2 user buttons + - USB interface for Host/Device/OTG + - Ambient light sensor and inductive-capacitive metal sensor + - EFM32 OPAMP footprint + - 20 pin expansion header + - Breakout pads for easy access to I/O pins + - Power sources (USB and CR2032 battery) + - Backup Capacitor for RTC mode + - Integrated Segger J-Link USB debugger/emulator + + **STATUS**. + + - The basic board support for the *Giant Gecko* was introduced int + the NuttX source tree in NuttX-7.6. A verified configuration was + available for the basic NuttShell (NSH) using LEUART0 for the + serial console. + - Development of USB support is in started, but never completed. + - Reset Management Unit (RMU) was added Pierre-noel Bouteville in + NuttX-7.7. + +| + +-------------- + +| + +STMicro STM32L152 (STM32L "EnergyLite" Line). Two boards are supported: + +- STM32L-Discovery. This is a port of NuttX to the STMicro + STM32L-Discovery development board. The STM32L-Discovery board is + based on the STM32L152RBT6 MCU (128KB FLASH and 16KB of SRAM). + + The STM32L-Discovery and STM32L152C DISCOVERY kits are functionally + equivalent. The difference is the internal Flash memory size + (STM32L152RBT6 with 128 Kbytes or STM32L152RCT6 with 256 Kbytes). + Both boards feature: + + - An ST-LINK/V2 embedded debug tool interface, + - LCD (24 segments, 4 commons), + - LEDs, + - Pushbuttons, + - A linear touch sensor, and + - Four touchkeys. + +- Nucleo-L152RE. Board support for the Nucleo-L152RE was contributed by + Mateusz Szafoni in NuttX-7.28. Available configurations include NSH, + ADC, and PWM. + +**STATUS**. Initial support for the STM32L-Discovery was released in +NuttX-6.28. Addition (architecture-only) support for the STM32L152xC +family was added in NuttX-7.21. Support for the Nucleo-L152RE was added +in NuttX-7.28. + +That initial STM32L-Discovery support included a configuration using the +NuttShell (`NSH `__) that might be the basis for an +application development. A driver for the on-board segment LCD is +included as well as an option to drive the segment LCD from an NSH +"built-in" command. Refer to the STM32L-Discovery board +`README `__ +file for further information. + +**Memory Usage**. + + REVISIT: These numbers are out of date. Current NuttX sizing might be + somewhat larger. + +For a full-featured RTOS such as NuttX, providing support in a usable +and meaningful way within the tiny memories of the STM32L152RBT6 +demonstrates the scalability of NuttX. The STM32L152RBT6 comes in a +64-pin package and has 128KB FLASH and 16KB of SRAM. + +Static memory usage can be shown with ``size`` command: + +NuttX, the NSH application, and GCC libraries use 38.7KB of FLASH +leaving 89.3B of FLASH (70%) free from additional application +development. Static SRAM usage is about 1.2KB (<4%) and leaves 14.8KB +(86%) available for heap at runtime. + +SRAM usage at run-time can be shown with the NSH ``free`` command: + +You can see that 9.9KB (62%) of SRAM heap is still available for further +application development while NSH is running. + +| + +-------------- + +| + +STMicro STM32L152x/162x (STM32 L1 "EnergyLite" Medium+ Density Family). +Support for the STM32L152 and STM32L162 Medium+ density parts from Jussi +Kivilinna and Sami Pelkonen was included in NuttX-7.3, extending the +basic STM32L152x support. This is *architecture-only* support, meaning +that support for the boards with these chips is available, but no +support for any publicly available boards is included. + +| + +-------------- + +| + +STMicro STM32F0xx (STM32 F0, ARM Cortex-M0). Support for the STM32 F0 +family was contributed by Alan Carvalho de Assis in NuttX-7.21. There +are ports to three different boards in this repository: + +- **STM32F0-Discovery** This board features the STM32 2F051R8 and was + used by Alan to produce the initial STM32 F0 port. However, its very + limited 8KB SRAM makes this port unsuitable for for usages. + Contributed by Alan Carvalho de Assis in NuttX-7.21. +- **Nucleo-F072RB** With 16KB of SRAM the STM32 F072RB makes a much + more usable platform. +- **Nucleo-F091RC** With 32KB of SRAM the STM32 F091RC this board is a + great match for NuttX. Contributed by Juha Niskanen in NuttX-7.21. + +| + +STMicro STM32L0xx (STM32 L0, ARM Cortex-M0). Support for the STM32 FL +family was contributed by Mateusz Sfafoni in NuttX-7.28. There are ports +to two different STM32 L0 boards in the repository: + +- **B-L072Z-LRWAN1** Contributed byMateusz Sfafoni in NuttX-7.28. +- **Nucleo-L073RZ** Contributed byMateusz Sfafoni in NuttX-7.28. + +| + +STMicro STM32G0xx (STM32 G0, ARM Cortex-M0+). Support for the STM32 FL +family was contributed by Mateusz Sfafoni in NuttX-7.28. There are ports +to two different STM32 L0 boards in the repository: + +- **Nucleo-G071RB** Initial support for Nucleo-G071RB was contributed + by Mateusz Szafoni in NuttX-7.31. Refer to the board + `README `__ + file for further information. +- **Nucleo-G070RB** Contributed by Daniel Pereira Volpato. in + NuttX-8.2. Refer to the board + `README `__ + file for further information. + +| + +**STATUS:** Status for the STM32F0xx, STM32L0xx, and STM32G0xx is shown +together since these parts share many drivers in common. + +**NuttX-7.21**. In this initial release, the level of support for the +STM32 F0 family is minimal. Certainly enough is in place to support a +robust NSH configuration. There are also unverified I2C and USB device +drivers available in NuttX-7.21. + +**NuttX-7.28** Added support for GPIO EXTI. From Mateusz Sfafoni. + +**NuttX-7.29** Added an SPI driver. From Mateusz Sfafoni. + +**NuttX-7.30** Added ADC and I2C drivers. From Mateusz Szafoni. Add AES +and RND drivers for the L0. From Mateusz Szafoni. Add support for HS148 +for L0. From Mateusz Szafoni. + +**NuttX-8.2** Added PWM and TIM drivers for the G0. From Daniel Pereira +Volpato. + +**NuttX-9.0** Added I2C support for F0, L0 and G0. + +| + +-------------- + +| + +STMicro STM32F100x (STM32 F1 "Value Line"Family). + +- **Proprietary Boards** Chip support for these STM32 "Value Line" + family was contributed by Mike Smith and users have reported that + they have successful brought up NuttX on their proprietary boards + using this logic. + +- **STM32VL-Discovery**. In NuttX-6.33, support for the STMicro + STM32VL-Discovery board was contributed by Alan Carvalho de Assis. + The STM32VL-Discovery board features an STM32F100RB MCU. Refer to the + NuttX board + `README `__ + file for further information. + +| + +-------------- + +| + +STMicro STM32F102. Architecture support (only) for the STM32 F102 family +was contributed by the PX4 team in NuttX-7.7. + +| + +-------------- + +| + +STMicro STM32F103C4/8 (STM32 F1 Low- and Medium-Density Family). There +are two ports available for this family: + +- One port is for "STM32 Tiny" development board. This board is + available from several vendors on the net, and may be sold under + different names. It is based on a STM32 F103C8T6 MCU, and is bundled + with a nRF24L01 wireless communication module. + +- The other port is for a generic minimal STM32F103CBT6 "blue" board + contributed by Alan Carvalho de Assis. Alan added support for + numerous sensors, tone generators, user LEDs, and LCD support in + NuttX 7.18. + +**STATUS:** + +| + +-------------- + +| + +STMicro STM32F103x (STM32 F1 Family). Support for five board +configurations are available. MCU support includes all of the high +density and connectivity line families. Board supported is available +specifically for: STM32F103ZET6, STM32F103RET6, STM32F103VCT, +STM32F103VET6, STM32F103RBT6, and STM32103CBT6. Boards supported +include: + +#. **STM3210E-EVAL**. A port for the `STMicro <%20http://www.st.com/>`__ + STM3210E-EVAL development board that features the STM32F103ZET6 MCU. + Refer to the NuttX board + `README `__ + file for further information. + +#. **HY-Mini STM32v board**. This board is based on the STM32F103VCT + chip. Port contributed by Laurent Latil. Refer to the NuttX board + `README `__ + file. + +#. **The M3 Wildfire development board (STM32F103VET6), version 2**. See + http://firestm32.taobao.com (the current board is version 3). Refer + to the NuttX board + `README `__ + file for further information. + +#. **LeafLab's Maple and Maple Mini boards**. These boards are based on + the STM32F103RBT6 chip for the standard version and on the + STM32F103CBT6 for the mini version. See the + `LeafLabs `__ web site + for hardware information; see the NuttX board + `README `__ + file for further information about the NuttX port. + +#. **Olimexino-STM32**. This port uses the Olimexino STM32 board + (STM32F103RBT6). See the http://www.olimex.com for further + information. Contributed by David Sidrane. + +#. **Nucleo-STM32F103RB**. This port uses the STM32F103RBT6. It was + contributed by Mateusz Szafoni in NuttX-7.28, + +These ports uses a GNU arm-nuttx-elf toolchain\* under either Linux or +Cygwin (with native Windows GNU tools or Cygwin-based GNU tools). + +**STATUS:** + +- **Basic Support/Drivers**. The basic STM32 port was released in NuttX + version 0.4.12. The basic port includes boot-up logic, interrupt + driven serial console, and system timer interrupts. The 0.4.13 + release added support for SPI, serial FLASH, and USB device.; The + 4.14 release added support for buttons and SDIO-based MMC/SD and + verified DMA support. Verified configurations are available for the + NuttShell (NSH) example, the USB serial device class, and the USB + mass storage device class example. + +- **Additional Drivers**. Additional drivers and configurations were + added in NuttX 6.13 and later releases for the STM32 F1 and F4. F1 + compatible drivers include an Ethernet driver, ADC driver, DAC + driver, PWM driver, IWDG, WWDG, and CAN drivers. + +- **M3 Wildfire**. Support for the Wildfire board was included in + version 6.22 of NuttX. The board port is basically functional. Not + all features have been verified. Support for FAT file system on an an + SD card had been verified. The ENC28J60 network is functional (but + required lifting the chip select pin on the W25x16 part). + Customizations for the v3 version of the Wildfire board are + selectable (but untested). + +- **Maple**. Support for the Maple boards was contributed by Yiran Liao + and first appear in NuttX 6-30. + +- **Olimexino-STM32**. Contributed by David Sidrane and introduced with + NuttX 7.9. Configurations are included for the NuttShell (NSH), a + tiny version of the NuttShell, USB composite CDC/ACM + MSC, CAN + support, and two tiny, small-footprint NSH configurations. + +- **Nucleo-STM32F103RB**. Contributed by Mateusz Szafoni and introduced + with NuttX 7.28. Configurations are included for the NuttShell (NSH), + ADC, and PWM. + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain (RIDE7, CodeSourcery or devkitARM), or 4) Native +Windows. A DIY toolchain or Linux or Cygwin is provided by the NuttX +`buildroot `__ +package. + +| + +-------------- + +| + +STMicro STM32F105x. Architecture support (only) for the STM32 F105R was +contribed in NuttX-7.17 by Konstantin Berezenko. There is currently no +support for boards using any STM32F105x parts in the source tree. + +| + +-------------- + +| + +STMicro STM32F107x (STM32 F1 "Connectivity Line" family). Chip support +for the STM32 F1 "Connectivity Line" family has been present in NuttX +for some time and users have reported that they have successful brought +up NuttX on their proprietary boards using this logic. + +**Olimex STM32-P107** Support for the `Olimex +STM32-P107 `__ was +contributed by Max Holtzberg and first appeared in NuttX-6.21. That port +features the STMicro STM32F107VC MCU. + +**STATUS:** A configuration for the NuttShell (NSH) is available and +verified. Networking is functional. Support for an external ENCX24J600 +network was added in NuttX 6.30. + +**Shenzhou IV** A port of NuttX to the Shenzhou IV development board +(See `www.armjishu.com `__) featuring the +STMicro STM32F107VCT MCU was added in NuttX-6.22. + +**STATUS:** In progress. The following have been verified: (1) Basic +Cortex-M3 port, (2) Ethernet, (3) On-board LEDs. Refer to the NuttX +board +`README `__ +file for further information. + +**ViewTool STM32F103/F107** Support for the `Viewtool +STM32F103/F107 `__ board was added in +NuttX-6.32. That board features the STMicro STM32F107VCT6 MCU. +Networking, LCD, and touchscreen support were added in NuttX-6.33. + +Three configurations are available: + +#. A standard NuttShell (NSH) configuration that will work with either + the STM32F103 or STM32F107 part. +#. A network-enabled NuttShell (NSH) configuration that will work only + with the STM32F107 part. +#. The configuration that was used to verify the Nuttx `high-priority, + nested interrupt + feature `__. + +**STATUS:** Networking and touchscreen support are well test. But, at +present, neither USB nor LCD functionality have been verified. Refer to +the Viewtool STM32F103/F107 +`README `__ +file for further information. + +**Kamami STM32 Butterfly 2** Support for the `Kamami STM32 Butterfly +2 `__ +was contributed by Michał Łyszczek in NuttX-7.18. That port features the +STMicro STM32F107VC MCU. + +**STATUS:** A configuration for the NuttShell (NSH), NSH with +networking, and NSH with USB host are available and verified. + +| + +-------------- + +| + +STMicro STM32F205 (STM32 F2 family). Architecture only support for the +STM32F205RG was contributed as an anonymous contribution in NuttX-7.10. + +**Particle.io Phone**. Support for the Particle.io Photon board was +contributed by Simon Pirious in NuttX-7.21. The Photon board features +the STM32F205RG MCU. The STM32F205RG is a 120 MHz Cortex-M3 operation +with 1Mbit Flash memory and 128kbytes. The board port includes support +for the on-board Broadcom BCM43362 WiFi and fully usable FullMac network +support. + +**STATUS:** In addition to the above-mention WiFI support, the Photon +board support includes buttons, LEDS, IWDG, USB OTG HS, and procfs +support. Configurations available for nsh, usbnsh, and wlan +configurations. See the Photon +`README `__ +file for additional information. + +| + +-------------- + +| + +STMicro STM32F207 (STM32 F2 family). + +- Support for the STMicro STM3220G-EVAL development board was + contributed by Gary Teravskis and first released in NuttX-6.16. This + board uses the STM32F207IG. +- Martin Lederhilger contributed support for the Olimex STM32 P207 + board using the STM32F207ZE MCU. +- Board support for the Nucleo-L152RE was contributed by Mateusz + Szafoni in NuttX-7.28. Available configurations include NSH, ADC, and + PWM. + +| + +-------------- + +| + +Atmel SAM3U. This port uses the `Atmel `__ +SAM3U-EK development board that features the SAM3U4E MCU. This port uses +a GNU arm-nuttx-elf or arm-nuttx-eabi toolchain\* under either Linux or +Cygwin (with native Windows GNU tools or Cygwin-based GNU tools). + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain (CodeSourcery or devkitARM), or 4) Native Windows. A +DIY toolchain for inux or Cygwin is provided by the NuttX +`buildroot `__ +package. + +| + +-------------- + +| + +Atmel SAM3X. There are two SAM3X boards supported: + +#. The `Arduino `__ Due development board that + features the ATSAM3X8E MCU running at 84MHz. See the `Arduino + Due `__ page for more + information. +#. The Mikroelektronika `Flip&Click + SAM3X `__ development + board. This board is an Arduino Due *work-alike* with additional + support for 4 mikroBUS Click boards. + +**Development Environments:** See the Atmel SAM3U discussion +`above. <#at91sam3u>`__ + +| + +-------------- + +| + +NXP LPC1766, LPC1768, and LPC1769. Drivers are available for CAN, DAC, +Ethernet, GPIO, GPIO interrupts, I2C, UARTs, SPI, SSP, USB host, and USB +device. Additional drivers for the RTC, ADC, DAC, Timers, PWM and MCPWM +were contributed by Max (himax) in NuttX-7.3. Verified LPC17xx +configurations are available for these boards: + +- The Nucleus 2G board from `2G Engineering `__ + (LPC1768), +- The mbed board from `mbed.org `__ (LPC1768, + Contributed by Dave Marples), and +- The LPC1766-STK board from `Olimex `__ + (LPC1766). +- The Embedded Artists base board with NXP LPCXpresso LPC1768. +- Zilogic's ZKIT-ARM-1769 board. +- The `Micromint `__ Lincoln60 board with an NXP + LPC1769. +- A version of the LPCXPresso LPC1768 board with special support for + the U-Blox model evaluation board. +- Support for the Keil MCB1700 was contributed by Alan Carvalho de + Assis in NuttX-7.23. +- Support for the NXP Semiconductors' PN5180 NFC Frontend Development + Kit was contributed by Michael Jung in NuttX-7.1. This board is based + on the NXP LPC1769 MCU. + +The Nucleus 2G board, the mbed board, the LPCXpresso, and the MCB1700 +all feature the NXP LPC1768 MCU; the Olimex LPC1766-STK board features +an LPC1766. All use a GNU arm-nuttx-elf or arm-eabi toolchain\* under +either Linux or Cygwin (with native Windows GNU tools or Cygwin-based +GNU tools). + +**STATUS:** The following summarizes the features that has been +developed and verified on individual LPC17xx-based boards. These +features should, however, be common and available for all LPC17xx-based +boards. + +#. **Nucleus2G LPC1768** + + - Some initial files for the LPC17xx family were released in NuttX + 5.6, but + - The first functional release for the NXP LPC1768/Nucleus2G + occurred with NuttX 5.7 with Some additional enhancements through + NuttX-5.9. Refer to the NuttX board + `README `__ + file for further information. + + That initial, 5.6, basic release included *timer* interrupts and a + *serial console* and was verified using the NuttX OS test + (``apps/examples/ostest``). Configurations available include include + a verified NuttShell (NSH) configuration (see the `NSH User + Guide `__). The + NSH configuration supports the Nucleus2G's microSD slot and + additional configurations are available to exercise the USB serial + and USB mass storage devices. However, due to some technical reasons, + neither the SPI nor the USB device drivers are fully verified. + (Although they have since been verified on other platforms; this + needs to be revisited on the Nucleus2G). + + **Obsoleted**. Support for the Nucleus2G board was terminated on + 2016-04-12. There has not been any activity with the commercial board + in a few years and it no longer appears to be available from the + 2g-eng.com website. Since the board is commercial and no longer + publicly available, it no longer qualifies for inclusion in the open + source repositories. A snapshot of the code is still available in the + `Obsoleted + repository `__ + and can easily be *reconstitued* if needed. + +#. **mbed LPC1768** + + - Support for the mbed board was contributed by Dave Marples and + released in NuttX-5.11. Refer to the NuttX board + `README `__ + file for further information. + +#. **Olimex LPC1766-STK** + + - Support for that Olimex-LPC1766-STK board was added to NuttX 5.13. + - The NuttX-5.14 release extended that support with an *Ethernet + driver*. + - The NuttX-5.15 release further extended the support with a + functional *USB device driver* and *SPI-based micro-SD*. + - The NuttX-5.16 release added a functional *USB host controller + driver* and *USB host mass storage class driver*. + - The NuttX-5.17 released added support for low-speed USB devices, + interrupt endpoints, and a *USB host HID keyboard class driver*. + - Refer to the NuttX board + `README `__ + file for further information. + + Verified configurations are now available for the NuttShell with + networking and microSD support(NSH, see the `NSH User + Guide `__), for + the NuttX network test, for the + `THTTPD `__ webserver, for USB + serial deive and USB storage devices examples, and for the USB host + HID keyboard driver. Support for the USB host mass storage device can + optionally be configured for the NSH example. A driver for the *Nokia + 6100 LCD* and an NX graphics configuration for the Olimex LPC1766-STK + have been added. However, neither the LCD driver nor the NX + configuration have been verified as of the NuttX-5.17 release. + +#. **Embedded Artists base board with NXP LPCXpresso LPC1768** + + An fully verified board configuration is included in NuttX-6.2. The + Code Red toolchain is supported under either Linux or Windows. + Verified configurations include DHCPD, the NuttShell (NSH), NuttX + graphis (NX), THTTPD, and USB mass storage device. Refer to the NuttX + board + `README `__ + file for further information. + +#. **Zilogic's ZKIT-ARM-1769 board** + + Zilogic System's ARM development Kit, ZKIT-ARM-1769. This board is + based on the NXP LPC1769. The initial release was included + NuttX-6.26. The Nuttx Buildroot toolchain is used by default. Verifed + configurations include the "Hello, World!" example application and a + THTTPD demonstration. Refer to the NuttX board + `README `__ + file for further information. + +#. **Micromint Lincoln60 board with an NXP LPC1769** + + This board configuration was contributed and made available in + NuttX-6.20. As contributed board support, I am unsure of what all has + been verfied and what has not. See the Microment website + `Lincoln60 `__ board + and the NuttX board + `README `__ + file for further information about the Lincoln board. + +#. **U-Blox Modem Evaluation (LPCXpresso LPC1768)** + + This board configuration was contributed by Vladimir Komendantskiy + and made available in NuttX-7.15. This is a variant of the LPCXpresso + LPC1768 board support with special provisions for the U-Blox Model + Evaluation board. See the NuttX board + `README `__ + file for further information about this port. + +#. **Keil MCB1700 (LPC1768)** + + This board configuration was contributed by Alan Carvalho de Assis in + NuttX-7.23. + +#. **PN5180 NFC Frontend Development Kit** + + This board configuration was contributed by Michael Jung in + NuttX-7.31. + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain (CodeSourcery devkitARM or Code Red), or 4) Native +Windows. A DIY toolchain for Linux or Cygwin is provided by the NuttX +`buildroot `__ +package. + +| + +-------------- + +| + +NXP LPC1788. The port of NuttX to the WaveShare Open1788 is a +collaborative effort between Rommel Marcelo and myself (with Rommel +being the leading contributor and I claiming only a support role). You +can get more information at the Open1788 board from the WaveShare +`website `__. + +| + +-------------- + +| + +ON Semiconductor LC823450 (Dual core ARM Cortex-M3). In NuttX-7.22, +Masayuki Ishikawa contributed support for both the LC823450 architecture +and for ON Semiconductor's **LC823450XGEVK board**: + + The LC823450XGEVK is an audio processing system Evaluation Board Kit + used to demonstrate the LC823450. This part can record and playback, + and offers High-Resolution 32-bit & 192 kHz audio processing + capability. It is possible to cover most of the functions necessary + for a portable audio with only this LSI as follows. It has Dual CPU + and DSP with High processing capability, and internal 1656K-Byte + SRAM, which make it possible to implement large scale program. And it + has integrated analog functions (low-power Class D HP amplifier, PLL, + ADC etc.) so that PCB space and cost is reduced, and it has various + interface (USB, SD, SPI, UART, etc.) to make extensibility high. Also + it is provided with various function including SBC/AAC codec by DSP + and UART and ASRC (Asynchronous Sample Rate Converter) for Bluetooth® + audio. It is very small chip size in spite of the multi-funciton as + described above and it realizes the low power consumption. Therefore, + it is applicable to portable audio markets such as Wireless headsets + and will show high performance. + +Further information about the LC823450XGEVK is available on from the the +`ON +Semiconductor `__ +website as are LC823450 `related technical +documents `__. +Refer to the NuttX board +`README `__ +file for details of the NuttX port. + +This port is intended to test LC823450 features including SMP. Supported +peripherals include UART, TIMER, RTC, GPIO, DMA, I2C, SPI, LCD, eMMC, +and USB device. ADC, Watchdog, IPC2, and I2S support was added by +Masayuki Ishikawa in NuttX-7.23. Bluetooth, SPI, and *PROTECTED* build +support were added by Masayuki Ishikawa in NuttX-7.26. Support for for +SPI flash boot was added in NuttX-7.28. + +| + +-------------- + +| + +Maxim Integrated MAX36600. Architectural upport for the MAX32660 was +added (along with partial support for other members of the MAX326xx +family) in NuttX 7.28. + +**MAX32660-EVSYS**. Basic support for the Maxim Integrated MAC3X660 +EVSYS was included in the NuttX-7.28 release. A basic NSH configuration +is available and is fully functional. Includes unverified support for an +SPI0-based SD card. + +**STATUS:** + +` <#>`__ (ARM Cortex-M3) + + + +ARM Cortex-M4. + +| + +Infineon XMC45xx. An initial but still incomplete port to the XMC4500 +Relax board was released with NuttX-7.21 (although it was not really +ready for prime time). Basic NSH functionality was a serial console was +added by Alan Carvahlo de Assis in NuttX-7.23. Alan also added an SPI +driver in NuttX-7.25. + +This initial porting effort uses the Infineon XMC4500 Relax v1 board as +described on the manufacturer's +`website `__. +The current status of the board is available in the board +`README `__ +file + +| + +-------------- + +| + +Nordic Semiconductor/NRF52xxx. Initial architecture support of the NRF52 +including UART, Timer, and GPIOs was contributed by Janne Rosberg in +NuttX-7.25. Janne also contributed board support for the NRF52-PCA10040 +development board at that time. + +The NRF52 was generalized by Hanya Zou in NuttX-7.28 for any similar +board based on the NRF52832 MCU. Support was specifically included for +the Adafruit NRF52 Feather board. + +Available drivers include: + +- **NuttX-7.25**. UART, Timer, and GPIOs from Janne Rosberg and a + watchdog timer driver was added by Levin Li. +- **NuttX-7.25**. Flash PROGMEM support was added by Alan Carvalho de + Assis. +- **NuttX-7.29**. Support for the 52804 family and an RNG drivers was + added by Levin Li. + +| + +-------------- + +| + +NXP/FreeScale Kinetis K20/Teensy-3.x. Architecture support (only) was +added in NuttX-7.10. This support was taken from PX4 and is the work of +Jakob Odersky. Support was added for the PJRC Teensy-3.1 board in +NuttX-7.11. Backward compatible support for the Teensy-3.0 is included. + +| + +-------------- + +| + +NXP/FreeScale Kinetis K28F/Freedom-K28F. Architecture support for the +Kinetis K28F along with board support for the Freedom-K28F was added in +NuttX-7.15. The Freedom-K28F board is based on the Kinetis +MK28FN2M0VMI15 MCU (ARM Cortex-M4 at150 MHz, 1 MB SRAM, 2 MB flash, HS +and FS USB, 169 MAPBGA package). More information is available from the +`NXP +website `__. + +| + +-------------- + +| + +NXP/FreeScale Kinetis K40. This port uses the Freescale Kinetis KwikStik +K40. Refer to the `Freescale web +site `__ +for further information about this board. The Kwikstik is used with the +FreeScale Tower System (mostly just to provide a simple UART connection) + +| + +-------------- + +| + +NXP/FreeScale Kinetis K60. This port uses the **Freescale Kinetis +TWR-K60N512** tower system. Refer to the `Freescale web +site `__ +for further information about this board. The TWR-K60N51 includes with +the FreeScale Tower System which provides (among other things) a DBP +UART connection. + +**MK60N512VLL100**. Architecture support for the MK60N512VLL100 was +contributed by Andrew Webster in NuttX-7.14. + +| + +-------------- + +| + +NXP/FreeScale Kinetis K64. Support for the Kinetis K64 family and +specifically for the **NXP/Freescale Freedom K64F** board was added in +NuttX 7.17. Initial release includes two NSH configurations with support +for on-board LEDs, buttons, and Ethernet with the on-board KSZ8081 PHY. +SDHC supported has been integrated, but not verified. Refer to the NuttX +board +`README `__ +file for further information. + +**MK64FN1M0VMD12**. Architecture support for the \_MK64FN1M0VMD12 was +contributed by Maciej Skrzypek in NuttX-7.20. + +**NXP/Freescale Kinetis TWR-K64F120M**. Support for the Freescale +Kinetis TWR-K64F120M was contributed in NuttX-7.20 by Maciej Skrzypek. +Refer to the `Freescale web +site `__ +for further information about this board. The board may be complemented +by +`TWR-SER `__ +which includes (among other things), an RS232 and Ethernet connections. +Refer to the NuttX board +`README `__ +file for further information. + +| + +**Driver Status**. + +- **NuttX-6.8**. Ethernet and SD card (SDHC) drivers also exist: The + SDHC driver is partially integrated in to the NSH configuration but + has some outstanding issues. Additional work remaining includes: (1) + integrate th SDHC drivers, and (2) develop support for USB host and + device. NOTE: Most of these remaining tasks are the same as the + pending K40 tasks described above. +- **NuttX-7.14**. The Ethernet driver became stable in NuttX-7.14 + thanks to the efforts of Andrew Webster. +- **NuttX-7.17**. Ethernet support was extended and verified on the + Freedom K64F. A Kinetis USB device controller driver and PWM support + was contributed by kfazz. + +| + +-------------- + +| + +NXP/FreeScale Kinetis K66. Support for the Kinetis K64 family and +specifically for the **NXP/Freescale Freedom K66F** board was +contributed by David Sidrane in NuttX 7.20. Refer to the NuttX board +`README `__ +file for further information. + +| + +**Driver Status**. + +- Most K6x drivers are compatible with the K66. +- **NuttX-7.20**. David Sidrane also contributed support for a serial + driver on the K66's LPUART. +- **NuttX-7.22**. David Sidrane contributed improvements to the USB and + I2C device drivers, RTC alarm functionality, and new SPI driver. +- **NuttX-7.26**. David Sidrane contributed DMA support to the Kinetis + K6x family. + +| + +-------------- + +| + +Sony CXD56\ xx (6 x ARM Cortex-M4). Support for the CXD56\ *xx* was +introduced by Nobuto Kobayashi in NuttX-7.30. + +**Sony Spresence**. Spresense is a compact development board based on +Sony’s power-efficient multicore microcontroller CXD5602. Basic support +for the Sony Spresense board was included in the contribution of Nobuto +Kobayashi in NuttX-7.30. *NOTE*: That was an initial, bare bones basic +Spresense port sufficient for running a NuttShell (NSH) and should not +be confused with the full Spresence SDK offered from Sony. Since then +there has been much development of the NuttX CXD56xx port. + +**Features:** + +- Integrated GPS: Embedded GNSS with support for GPS, QZSS. +- Hi-res audio output and multi mic inputs" Advanced 192kHz/24 bit + audio codec and amplifier for audio output, and support for up to 8 + mic input channels. +- Multicore microcontroller: Spresense is powered by Sony's CXD5602 + microcontroller (ARM® Cortex®-M4F × 6 cores), with a clock speed of + 156 MHz. + +**Driver Status:** + +**NuttX-3.31**. In this release, many new architectural features, +peripheral drivers, and board configurations were contributed primarily +through the work of Alin Jerpelea. These new architectural features +include: Inter-core communications, power management, and clock +management. New drivers include: GPIO, PMIC, USB, SDHC, SPI, I2C, DMA, +RTC, PWM, Timers, Watchdog Timer, UID, SCU, ADC, eMMC, Camera CISIF, +GNSS, and others. + +**NuttX-8.1**. Alin Jerpelea brought in ten (external) sensor drivers +that integrate through the CXD56xx's SCU. + +**NuttX-8.2**. Masayuki Ishikawa implemented SMP operation of the +CX56Dxx parts. Alin Jerpelea: Added support for the Altair LTE modem +support, enabled support for accelerated format converter, rotation and +so on using the CXD5602 image processing accelerator, added ISX012 +camera support, added audio and board audio control implementation, +added an audio_tone_generator, added optional initialization of GNSS and +GEOFENCE at boot if the drivers are enabled, added an lcd examples +configuration. + +| + +-------------- + +| + +STMicro STM32 F302 (STM32 F3 family). Architecture (only) support for +the STM32 F302 was contributed in NuttX-7.10 by Ben Dyer (via the PX4 +team and David Sidrane). + +Support for the Nucleo-F302R8 board was added by raiden00pl in +NuttX-7.27. Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +STMicro STM32 F303 (STM32 F3 family). + +- **STM32F3-Discovery**. This port uses the STMicro STM32F3-Discovery + board featuring the STM32F303VCT6 MCU (STM32 F3 family). Refer to the + `STMicro web + site `__ for + further information about this board. + +- **STMicro ST Nucleo F303RE board**. The basic port for the Nucleo + F303RE was contributed by Paul Alexander Patience and first released + in NuttX-7.12. Refer to the NuttX board + `README `__ + file for further information. + +- **STMicro ST Nucleo F303ZE board**. Support for the Nucleo-F303ZE + board was added by Mateusz Szafoni in NuttX-7.27. Refer to the NuttX + board + `README `__ + file for further information. + +| + +-------------- + +| + +STMicro STM32 F334 (STM32 F3 family, ARM Cortex-M4). + +Support for the STMicro **STM32F334-Disco** board was contributed by +Mateusz Szafoni in NuttX-7.22 and for the **Nucleo-STM32F334R8** was +contributed in an earlier release. + +| + +-------------- + +| + +STMicro STM32 F372/F373 (ARM Cortex-M4). + +Basic architecture support for the STM32F372/F373 was contributed by +Marten Svanfeldt in NuttX 7.9. There are no STM32F*72 boards currently +supported, however. + +| + +-------------- + +| + +STMicro STM324x1 (STM32 F4 family). + +**Nucleo F401RE**. This port uses the STMicro Nucleo F401RE board +featuring the STM32F401RE MCU. Refer to the `STMicro web +site `__ for +further information about this board. + +**Nucleo F411RE**. This port uses the STMicro Nucleo F411RE board +featuring the STM32F411RE MCU. Refer to the `STMicro web +site `__ for +further information about this board. + +**STATUS:** + +- **NuttX-7.2** The basic port for STMicro Nucleo F401RE board was + contributed by Frank Bennett. +- **NuttX-7.6** The basic port for STMicro Nucleo F401RE board was + added by Serg Podtynnyi. +- **NuttX-7.25** Architecture support (only) for STMicro STM32F401xB + and STM32F401xC pars was added. +- Refer to the NuttX board + `README `__ + file for further information. + +| + +-------------- + +| + +STMicro STM32410 (STM32 F4 family). + +Architecture-only support was contributed to NuttX-7.21 by Gwenhael +Goavec-Merou. + +| + +-------------- + +| + +STMicro STM32405x/407x (STM32 F4 family). + +**STMicro STM3240G-EVAL**. This port uses the STMicro STM3240G-EVAL +board featuring the STM32F407IGH6 MCU. Refer to the `STMicro web +site `__ for +further information about this board. + +**STATUS:** + +- **NuttX-6.12** The basic port is complete and first appeared in + NuttX-6.12. The initial port passes the NuttX OS test and includes a + validated configuration for the NuttShell (NSH, see the `NSH User + Guide `__) as well + as several other configurations. +- **NuttX-6.13-6.16** Additional drivers and configurations were added + in NuttX 6.13-6.16. Drivers include an Ethernet driver, ADC driver, + DAC driver, PWM driver, CAN driver, F4 RTC driver, Quadrature + Encoder, DMA, SDIO with DMA (these should all be compatible with the + STM32 F2 family and many should also be compatible with the STM32 F1 + family as well). +- **NuttX-6.16** The NuttX 6.16 release also includes and logic for + saving/restoring F4 FPU registers in context switches. Networking + intensions include support for Telnet NSH sessions and new + configurations for DHPCD and the networking test (nettest). +- **NuttX-6.17** The USB OTG device controller driver, and LCD driver + and a function I2C driver were added in NuttX 6.17. +- **NuttX-6.18** STM32 IWDG and WWDG watchdog timer drivers were added + in NuttX 6.18 (should be compatible with F1 and F2). An LCD driver + and a touchscreen driver for the STM3240G-EVAL based on the STMPE811 + I/O expander were also added in NuttX 6.18. +- **NuttX-6.21** A USB OTG host controller driver was added in NuttX + 6.21. +- **NuttX-7.3** Support for the Olimex STM32 H405 board was added in + NuttX-7.3. +- **NuttX-7.14** Support for the Olimex STM32 H407 board was added in + NuttX-7.14. +- **NuttX-7.17** Support for the Olimex STM32 E407 board was added in + NuttX-7.17. +- **NuttX-7.19** Support for the Olimex STM32 P407 board was added in + NuttX-7.19. +- **NuttX-7.21** Support for the MikroElektronika Clicker2 for STM32 + (STM32 P405) board was added in NuttX-7.21. +- **NuttX-7.29** Support for the OmnibusF4 architecture (STM32 P405) + board was added in NuttX-7.29. + +Refer to the STM3240G-EVAL board +`README `__ +file for further information. + +**STMicro STM32F4-Discovery**. This port uses the STMicro +STM32F4-Discovery board featuring the STM32F407VGT6 MCU. The +STM32F407VGT6 is a 168MHz Cortex-M4 operation with 1Mbit Flash memory +and 128kbytes. The board features: + +- On-board ST-LINK/V2 for programming and debugging, +- LIS302DL, ST MEMS motion sensor, 3-axis digital output accelerometer, +- MP45DT02, ST MEMS audio sensor, omni-directional digital microphone, +- CS43L22, audio DAC with integrated class D speaker driver, +- Eight LEDs and two push-buttons, +- USB OTG FS with micro-AB connector, and +- Easy access to most MCU pins. + +Support for the STM3F4DIS-BB base board was added in NuttX-7.5. This +includes support for the serial communications via the on-board DB-9 +connector, Networking, and the microSD card slot. + +Refer to the `STMicro web +site `__ for +further information about this board and to + +**MikroElektronika Mikromedia for STM32F4**. This is another board +supported by NuttX that uses the same STM32F407VGT6 MCU as does the +STM32F4-Discovery board. This board, however, has very different +on-board peripherals than does the STM32F4-Discovery: + +- TFT display with touch panel, +- VS1053 stereo audio codec with headphone jack, +- SD card slot, +- Serial FLASH memory, +- USB OTG FS with micro-AB connector, and +- Battery connect and batter charger circuit. + +See the +`Mikroelektronika `__ +website for more information about this board and the NuttX board +`README `__ +file for further information about the NuttX port. + +**Olimex STM32 H405**. Support for the Olimex STM32 H405 development +board was contributed by Martin Lederhilger and appeared in NuttX-7.3. +See the NuttX board +`README `__ +file for further information about the NuttX port. + +**Olimex STM32 H407**. Support for the Olimex STM32 H407 development +board was contributed by Neil Hancock and appeared in NuttX-7.14. See +the NuttX board +`README `__ +file for further information about the NuttX port. + +**Olimex STM32 E407**. Support for the Olimex STM32 E407 development +board was contributed by Mateusz Szafoni and appeared in NuttX-7.17. +Networking configurations were added in NuttX-7.18. See the NuttX board +`README `__ +file for further information about the NuttX port. + +**Olimex STM32 P407**. Support for the Olimex STM32 P407 development +board appeared in NuttX-7.19. See the NuttX board +`README `__ +file for further information about the NuttX port. + +**MikroElektronika Clicker2 for STM32**. This is yet another board +supported by NuttX that uses the same STM32F407VGT6 MCU as does the +STM32F4-Discovery board. This board has been used primarily with the +MRF24J40 Click board for the development of IEEE 802.15.4 MAC and +6LoWPAN support. + +See the +`Mikroelektronika `__ +website for more information about this board and the NuttX board +`README `__ +file for further information about the NuttX port. + +**OmnibusF4**. Initial support for the OmnibusF4 family of flight +management units was contributed by Bill Gatliff in NuttX-7.29. +"OmnibusF4" is not a product name *per se*, but rather a design +specification that many product vendors adhere to. The specification +defines the major components, and how those components are wired into +the microcontroller. *Airbot* is one such vendor. They publish a +`schematic `__. Other software that supports the +OmnibusF4 family include Betaflight, iNAV, and many others. PX4 recently +added support as well, also based on NuttX. No code from those resources +is included in this port. The OmnibusF4 specification mandates the +InvenSense MPU6000 which is included in NuttX-7.29 along with a driver +for the MAX7546 OSD. + +| + +-------------- + +| + +STMicro STM32 F427/437. General architectural support was provided for +the F427/437 family in NuttX 6.27. Specific support includes the +STM32F427I, STM32F427Z, and STM32F427V chips. This is +*architecture-only* support, meaning that support for the boards with +these chips is available, but not support for any publicly available +boards is included. This support was contributed by Mike Smith. + +The F427/437 port adds (1) additional SPI ports, (2) additional UART +ports, (3) analog and digital noise filters on the I2C ports, (4) up to +2MB of flash, (5) an additional lower-power mode for the internal +voltage regulator, (6) a new prescaling option for timer clock, (7) a +larger FSMSC write FIFO, and (8) additional crypto modes (F437 only). + +**Axlotoi**. In NuttX-7.31, Jason Harris contributed support for the +Axloti board. That is the board for the Axoloti open source synthesizer +board featuring the STM32F427IGH6 MCU The STM32F427IGH6 has a 180MHz +Cortex-M4 core with 1MiB Flash memory and 256KiB of SRAM The Axloti +board features: + +- ADAU1961 24-bit 96 kHz stereo CODEC +- 1/4" in/out jacks for analog audio signals +- 3.5 mm jack for analog audio signals +- 8 MiB of SDRAM (Alliance Memory AS4C4M16SA) +- Serial MIDI in/out ports +- SD Card slot +- Two user LEDs and one (GPIO) push-button +- USB OTG FS with Micro-AB connector (USB device mode operation) +- USB OTG HS with Type-A connector (USB host mode operation) +- Easy access to most IO pins + +Refer to `Axloti `__ website for further +information about this board. + +| + +-------------- + +| + +STMicro STM32 F429. Support for STMicro STM32F429I-Discovery development +board featuring the STM32F429ZIT6 MCU was contributed in NuttX-6.32 by +Ken Pettit. The STM32F429ZIT6 is a 180MHz Cortex-M4 operation with 2Mbit +Flash memory and 256kbytes. + +**STATUS**: + +- The initial release included support from either OTG FS or OTG HS in + FS mode. +- The F429 port adds support for the STM32F439 LCD and OTG HS (in FS + mode). +- In Nutt-7.6, Brennan Ashton added support for concurrent OTG FS and + OTG HS (still in FS mode) and Marco Krahl added support for an + SPI-based LCD . +- In Nutt-7.7, Marco Krahl included support for a framebuffer based + driver using the LTDC and DMA2D. Marcos's implementation included + extensions to support more advance LTDC functions through an + auxiliary interface. +- Support for the uVision GCC IDE added for theSTM32F429I-Discovery + board in NuttX 7.16. From Kha Vo. + +Refer to the STM32F429I-Discovery board +`README `__ +file for further information. + +| + +-------------- + +| + +STMicro STM32 F433. Architecture-only support for the STM32 F433 family +was contributed by Alan Carvalho de Assis in NuttX-7.22 (meaning that +the parts are supported, but there is no example board supported in the +system). This support was contributed by David Sidrane and made +available in NuttX-7.11. + +| + +-------------- + +| + +STMicro STM32 F446. Architecture-only support is available for the STM32 +F446 family (meaning that the parts are supported, but there is no +example board supported in the system). This support was contributed by +David Sidrane and made available in NuttX-7.11. + +| + +-------------- + +| + +STMicro STM32 F46xx. Architecture-only support is available for the +STM32 F46xx family (meaning that the parts are supported, but there is +no example board supported in the system). This support was contributed +by Paul Alexander Patienc and made available in NuttX-7.15. + +| + +-------------- + +| + +STMicro STM32 G474. One board is supported in this family: + +- **B-G474E-DPOW1 Discovery Kit**. Initial board support for the + STMicro B-G474E-DPOW1 board from ST Micro was added in NuttX-9.1. See + the `STMicro + website `__ + and the board + `README `__ + file for further information. + +**Status**: + +**NuttX-9.1**. Initial support for booting NuttX to a functional NSH +prompt on this board. + +| + +-------------- + +| + +STMicro STM32 L475. One board in supported in this family: + +- **B-L475E-IOT01A Discovery Kit**. Board support for the STMicro + B-L475E-IOT01A board from ST Micro was contributed by Simon Piriou in + NuttX-7.22. See the `STMicro + website `__ + and the board + `README `__ + file for further information. + + This board STMicro is powered by STM32L475VG Cortex-M4 and targets + IoT nodes with a choice of connectivity options including WiFi, + Bluetooth LE, NFC, and sub-GHZ RF at 868 or 915 MHz, as well as a + long list of various environmental sensors. + +**Status**: + +**NuttX-7.22**. The initial board support was released. Since this board +is highly compatible with the related, more mature STM32 L4 parts, it is +expected that there is a high degree of compatibility and with those +part. + +This board has been used extensive to develop NuttX PktRadio support for +the onboard Spirit1 radio (SPSGRF-915) radio. 6LoWPAN radio +communications are fully supported in point-to-point and in star +topologies. + +Simon Pirou also contributed support for the on-board Macronix QuadSPI +FLASH in NuttX 7.22. + +| + +-------------- + +| + +STMicro STM32 L476. Three boards are supported in this family: + +- **Nucleo-L476RG**. Board support for the STMicro NucleoL476RG board + from ST Micro was contributed by Sebastien Lorquet in NuttX-7.15. See + the `STMicro website `__ and the + board + `README `__ + file for further information. + +- **STM32L476VG Discovery**. Board support for the STMicro STM32L476VG + Discovery board from ST Micro was contributed by Dave in NuttX-7.15. + See the `STMicro website `__ and + the board + `README `__ + file for further information. + +- **STM32L476 MDK**. Very basic support for NuttX on the Motorola Moto + Z MDK was contributed by Jim Wylder in NuttX 7.18. A simple NSH + configuration is available for the STM32L476 chip. See the `Moto Mods + Development Kit `__ and the board + `README `__ + file for further information. + +**Status**: + +**NuttX-7.15**. Only the first initial release of support for this +family is present. It includes these basics: + +- RCC, clocking, Interrupts, System timer +- UART, USART, Serial Console +- GPIO, DMA, I2C, RNG, SPI + +**NuttX-7.16**. Additional drivers were contributed: + +- QSPI with DMA and memory mapped support. From Dave (ziggurat29). +- CAN contributed by Sebastien Lorquet. +- I2C made functional by Dave (ziggurat29). + +**NuttX-7.17**. Additional drivers/features were contributed: + +- Support for tickless mode. +- CAN driver enhancements. + +**NuttX-7.18**. Additional drivers were contributed: + +- Oneshot timer driver. +- Quadrature encode contributed by Sebastien Lorquet. + +**NuttX-7.20**. Additional drivers were added: + +- Serial Audio Interface (SAI). +- Power Management. +- LPTIM. +- Comparator (COMP). + +**NuttX-7.21**. Additional drivers were added: + +- Internal Watchdog (IWDG). + +**NuttX-7.22**. + +- DAC and ADC drivers were contributed by Juha Niskanen. + +**NuttX-7.30**. + +- Added USB FS device driver, CRS and HSI38 support from Juha Niskanen. + +**NuttX-8.2**. + +Add DMA support for STM32L4+ series. From Jussi Kivilinna. + +Add support for LPTIM timers on the STM32L4 as PWM outputs. From Matias +N. + +Enable OTGFS for STM32L4+ series. The OTGFS peripheral on stm32l4x6 and +stm32l4rxxx reference manual is exactly the same. From Jussi Kivilinna. + +| + +-------------- + +| + +STMicro STM32 L4x2. Architecture support for STM32 L4x2 family was +contributed by Juha Niskanen in NuttX-7.21. Support was extended for the +STM32L412 and STM32L422 chips in NuttX-7.27. Two boards are currently +supported. + +- **Nucleo-L432KC**. Board support for the STMicro Nucleo-L432KC board + from ST Micro was contributed by JSebastien Lorquet in NuttX-7.21. + See the `STMicro + website `__ + and the board + `README `__ + file for further information. + +- **Nucleo-L452RE**. Board support for the STMicro Nucleo-L452RE board + from ST Micro was contributed by Juha Niskanen in NuttX-7.21. See the + `STMicro + website `__ + and the board + `README `__ + file for further information. + +See also the status above for the STM32 L476 most of which also applies +to these parts. + +| + +-------------- + +| + +STMicro STM32 L496. Architecture support for STM32 L496 was contributed +by Juha Niskanen along with board support for the Nucleo-L496ZG in +NuttX-7.21: + +- **Nucleo-L496ZG**. Board support for the STMicro Nucleo-L496ZG board + from ST Micro was contributed by Juha Niskanen in NuttX-7.21. See the + `STMicro + website `__ + and the board + `README `__ + file for further information. See also the status above for the STM32 + L476 most of which also applies to this part. + +| + +-------------- + +| + +STMicro STM32 L4Rx. Architecture support for STM32 L4+ family was +contributed by Juha Niskanen along with board support for the +STM32L4R9I-Discovery in NuttX-7.26. Additional support for the +STM32L4R5ZI part was added by Jussi in NuttX-8.2. + +- **STM32L4R9I-Discovery**. Board support for the STMicro + STM32L4R9I-Discovery board from ST Micro was contributed by Juha + Niskanen in NuttX-7.26. That development board uses the STM32L4R9AI + part. See the `STMicro + website `__ + and the board + `README `__ + file for further information. See also the status above for the + opther STM32 L4 parts, most of which also applies to this part. + +| + +-------------- + +| + +NCP LPC40xx. The LPC40xx family is very similar to the LPC17xx family +except that it features a Cortex-M4F versus the LPC17xx's Cortex-M3. +Architectural support for the LPC40xx family was built on top of the +existing LPC17xx by jjlange in NuttX-7.31. With that architectural +support came support for two boards also contributed by jjlange: + +**LX CPU**. Pavel Pisa add support for the PiKRON LX CPU board. This +board may be configured to use either the LPC4088 or the LPC1788. + +**Driver Status.** + +| + +-------------- + +| + +NCP LPC43xx. Several board ports are available for this higher end, NXP +Cortex-M4F part: + +**NXG Technologies LPC4330-Xplorer**. This NuttX port is for the +LPC4330-Xplorer board from NGX Technologies featuring the NXP +LPC4330FET100 MCU. See the `NXG +website `__ +for further information about this board. + +- **STATUS:** Refer to the NuttX board + `README `__ + file for more detailed information about this port. + +- **NuttX-6.20** The basic LPC4330-Xplorer port is complete. The basic + NuttShell (NSH) configuration is present and fully verified. This + includes verified support for: SYSTICK system time, pin and GPIO + configuration, and a serial console. + +**NXP/Embest LPC4357-EVB**. This NuttX port is for the LPC4357-EVB from +NXP/Embest featuring the NXP LPC4357FET256 MCU. The LPC4357 differs from +the LPC4330 primarily in that it includes 1024KiB of on-chip NOR FLASH. +See the `NXP +website `__ +for more detailed information about the LPC4357 and the LPC4357-EVB. + +- **STATUS:** Refer to the NuttX board + `README `__ + file for more detailed information about this port. + +- **NuttX-7.6**. The basic port is was contributed by Toby Duckworth. + This port leverages from the LPC4330-Xplorer port (and, as of this + writing, still requires some clean up of the technical discussion in + some files). The basic NuttShell (NSH) configuration is present and + has been verified. Support is generally the same as for the + LPC4330-Xplorer as discussed above. + +**NXP LPC4370-Link2**. This is the NuttX port to the NXP LPC4370-Link2 +development board featuring the NXP LPC4370FET100 MCU. + +- **STATUS:** Refer to the NuttX board + `README `__ + file for more detailed information about this port. + +- **NuttX-7.12** The NXP LPC4370-Link2 port is was contributed by Lok + Tep and first released in NuttX-7.12. + +**WaveShare LPC4337-WS**. This is the NuttX port to the WaveShare +LPC4337-WS development board featuring the NXP LPC4337JBD144 MCU. + +- **STATUS:** Refer to the NuttX board + `README `__ + file for more detailed information about this port. + +- **NuttX-7.14** The NXP WaveShare LPC4337-WS port is was contributed + by Lok Tep and first released in NuttX-7.14. + +- **NuttX-7.16** Support for the LPC4337JET100 chip was contribed by + Alexander Vasiljev. Alexander also contributed an LPC43xx AES driver + available in NuttX-7.16. + +| + +**Driver Status**. + +- **NuttX-6.20** Several drivers have been copied from the related + LPC17xx port but require integration into the LPC43xx: ADC, DAC, + GPDMA, I2C, SPI, and SSP. The registers for these blocks are the same + in both the LPC43xx and the LPC17xx and they should integrate into + the LPC43xx very easily by simply adapting the clocking and pin + configuration logic. + + Other LPC17xx drivers were not brought into the LPC43xx port because + these peripherals have been completely redesigned: CAN, Ethernet, USB + device, and USB host. + + So then there is no support for the following LPC43xx peripherals: + SD/MMC, EMC, USB0,USB1, Ethernet, LCD, SCT, Timers 0-3, MCPWM, QEI, + Alarm timer, WWDT, RTC, Event monitor, and CAN. + + Some of these can be leveraged from other MCUs that appear to support + the same peripheral IP: + + - The LPC43xx USB0 peripheral appears to be the same as the USB OTG + peripheral for the LPC31xx. The LPC31xx USB0 device-side driver + has been copied from the LPC31xx port but also integration into + the LPC43xx (clocking and pin configuration). It should be + possible to complete porting of this LPC31xx driver with a small + porting effort. + - The Ethernet block looks to be based on the same IP as the STM32 + Ethernet and, as a result, it should be possible to leverage the + NuttX STM32 Ethernet driver with a little more effort. + +- **NuttX-6.21** Added support for a SPIFI block driver and for RS-485 + option to the serial driver. + +- **NuttX-7.17** EMC support was extended to include support SDRAM by + Vytautas Lukenska. + +- **NuttX-7.23** A CAN driver was contributed by Alexander Vasiljev in + NuttX-7.23. + +- **NuttX-7.24** RTC and Windowed Watchdog Timer (WWDT) drivers were + leveraged from the LPC17 and contributed by Gintaras Drukteinis. + Leveraged the LPC54xx SD/MMC to the LPC43xx. There are still + remaining issues with the SD/MMC driver and it is not yet functional. + +| + +-------------- + +| + +NCP LPC54xx. A port to the +`LPCXpresso-LPC54628 `__ +was added in NuttX-7.24. Initial configurations include: A basic NSH +configuration (nsh), a networking configuration (netnsh), and three +graphics configurations (nxwm, fb, and lvgl). + +**LPC4508**. The port was verified on an LPC5408 by a NuttX user with +relevant changes incorporated in NuttX-7.26. + +| + +**Driver Status**. + +- **NuttX-7.24** The initial release for the LPC54xx in NuttX included + the following drivers: UARTs, SysTick, SD/MMC, DMA, GPIO, GPIO + interrupts, LEDs and buttons, LCD, WWDT, RTC, RNG, Ethernet, and SPI. + The SPI driver is untested and there are known issues with the SD/MMC + driver, however. + +- **NuttX-7.29** Configurations were added to verify the "Per-Window + Framebuffer" feature also added in NuttX-7.29. + +Refer to the LPCXpresso-LPC54628 board +`README `__ +file for more detailed information about this port. + +| + +-------------- + +| + +NXP S32K14x. Support for the S32K14x family was added in NuttX-8.1. Two +boards are supported + +- **S32K146EVB**. A port to the S32K146EVB was included in NuttX-8.1. + The initial release supports two full-featured NSH configurations. + Refer to the S32K146EVB board + `README `__ + file for more detailed information about this port. +- **S32K148EVB**. A port to the S32K148EVB was also provided in + NuttX-8.1. The initial release supports two full-featured NSH + configurations. Refer to the S32K148EVB board + `README `__ + file for more detailed information about this port. + +Both boards featured two NSH configurations: One for execution out of +FLASH and a *safe* version that executes out of SRAM and, hence, cannot +lock up the system because of a bad FLASH image. + +| + +**Driver Status**. + +- **NuttX-8.1** The initial release for the S32K14x boards in NuttX + included the following verfied drivers: Basic boot up logic, clock + configuration, LPUART console, Systick timer, and GPIO controls. + Additional complete-but-unverified drivers were also included: GPIO + interrupts, eDMA, LPSPI, LPI2C, and Ethernet (S32K148 only). + +| + +-------------- + +| + +TI Stellaris LM4F120. This port uses the TI Stellaris LM4F120 LaunchPad. +Jose Pablo Carballo and I are doing this port. + +| + +-------------- + +| + +TI Tiva TM4C123G. This port uses the Tiva C Series TM4C123G LaunchPad +Evaluation Kit +`(EK-TM4C123GXL) `__. + +**TI Tiva TM4C123H**. Architectural support for the Tiva TM4C123AH6PM +was contributed in NuttX-8.1 by Nathan Hartman. + +**STATUS:** + +- **NuttX-7.1**. Initial architectural support for the EK-TM4C123GXL + was implemented and was released in NuttX 7.1. Basic board support + the EK-TM4C123GXL was also included in that release but was not fully + tested. This basic board support included a configuration for the + NuttShell + `NSH `__). +- **NuttX-7.2**. The fully verified port to the EK-TM4C123GXL was + provided in NuttX-7.2. +- **NuttX-7.7**. An I2C driver was added in NuttX-7.7. +- **NuttX-8.1**. Along with TM4C123AH6PM support, Nathan Hartman also + reinstated and extended the Tiva Quadrature Encoder driver. + +| + +-------------- + +| + +TI Tiva TM4C1294. This port uses the TI Tiva C Series TM4C1294 Connected +LaunchPad `(EK-TM4C1294XL) `__. + +**STATUS:** + +- Support for the EK-TM4C1294XL was contributed by Frank Sautter and + was released in NuttX 7.9. This basic board support included a + configuration for the NuttShell + `NSH `__) and a + configuration for testing IPv6. See drivers for the `TI Tiva + TM4C129X <#titm4c129x>`__. +- FLASH and EEPROM drivers from Shirshak Sengupta were included in + NuttX-7.25. + +Refer to the EK-TM4C1294XL board +`README `__ +file for more detailed information about this port. + +| + +-------------- + +| + +TI Tiva TM4C129X. This port uses the TI Tiva C Series TM4C129X Connected +Development Kit `(DK-TM4C129X) `__. + +**STATUS:** + +- A mature port to the DK-TM4C129X was implemented and was released in + NuttX 7.7. +- At the initial release, verified drivers were available for Ethernet + interface, I2C, and timers as well as board LEDs and push buttons. + Other Tiva/Stellaris drivers should port to the TM4C129X without + major difficulty. +- This board supports included two configurations for the NuttShell + (`NSH `__). Both + are networked enabled: One configured to support IPv4 and one + configured to supported IPv6. Instructions are included in the board + `README `__ + file for configuring both IPv4 and IPv6 simultaneously. +- Tiva PWM and Quadrature Encoder drivers were contributed to NuttX in + 7.18 by Young. + +Refer to the DK-TM4C129X board +`README `__ +file for more detailed information about this port. + +| + +-------------- + +| + +TI/SimpleLink CC13x2. Basic, unverified architectural support for the +CC13x2 was added in NuttX-7.28. Fragmentary support for very similar +CC26x2 family is included. This is a work in progress and, with any +luck, a fully verified port will be available in NuttX-7.29. It is +currently code complete (minus some ROM *DriverLib* hooks) but untested. + +**TI LaunchXL-CC1312R1**. Basic board support for the TI +LaunchXL-CC1312R1 board is in place. Board bring-up, however, cannot be +done until the the basic CC13x2 architecture support is complete, +hopefully in NuttX-7.29. + +| + +-------------- + +| + +Atmel SAM4L. This port uses the Atmel SAM4L Xplained Pro development +board. This board features the ATSAM4LC4C MCU running at 48MHz with +256KB of FLASH and 32KB of internal SRAM. + +**STATUS:** As of this writing, the basic port is code complete and a +fully verified configuration exists for the NuttShell +`NSH `__). The first +fully functional SAM4L Xplained Pro port was released in NuttX-6.28. +Support for the SAM4L Xplained modules was added in NuttX-6.29: + +- Support for the SPI-based SD card on the I/O1 module. +- Driver for the LED1 segment LCD module. +- Support for the UG-2832HSWEG04 OLED on the SAM4L Xplained Pro's OLED1 + module + +Refer to the NuttX board +`README `__ +file for further information. + +**Memory Usage**. The ATSAM4LC4C comes in a 100-pin package and has +256KB FLASH and 32KB of SRAM. Below is the current memory usage for the +NSH configuration (June 9, 2013). This is *not* a minimal +implementation, but a full-featured NSH configuration. + +Static memory usage can be shown with ``size`` command: + +NuttX, the NSH application, and GCC libraries use 42.6KB of FLASH +leaving 213.4B of FLASH (83.4%) free from additional application +development. Static SRAM usage is about 2.3KB (<7%) and leaves 29.7KB +(92.7%) available for heap at runtime. + +SRAM usage at run-time can be shown with the NSH ``free`` command. This +runtime memory usage includes the static memory usage *plus* all dynamic +memory allocation for things like stacks and I/O buffers: + +You can see that 22.8KB (71.1%) of the SRAM heap is still available for +further application development while NSH is running. + +| + +-------------- + +| + +Atmel SAM4CM. General architectural support was provided for SAM4CM +family in NuttX 7.3 This was *architecture-only* support, meaning that +support for the boards with these chips is available, but no support for +any publicly available boards was included. The SAM4CM port should be +compatible with most of the SAM3/4 drivers (like HSMCI, DMAC, etc.) but +those have not be verified on hardware as of this writing. This support +was contributed in part by Max Neklyudov. + +| + +**Atmel SAM4CMP-DB**. Support for the SAM4CMP-DB board was contributed +to NuttX by Masayuki Ishikawa in NuttX-7.19. The SAM4CM is a dual-CPU +part and SMP was included for the ARMv7-M and SAM3/4 families. The +SAM4CMP-DB board support includes an NSH configuration that operates in +an SMP configuration. Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +Atmel SAM4E. General architectural support was provided for the SAM4E +family in NuttX 6.32. This was *architecture-only* support, meaning that +support for the boards with these chips is available, but no support for +any publicly available boards was included. This support was contributed +in part by Mitko. + +**Atmel SAM4E-EK**. Board support was added for the SAM4E-EK development +board in NuttX 7.1. A fully functional NuttShell (NSH) configuration is +available (see the `NSH User +Guide `__). That NSH +configuration includes networking support and support for an AT25 Serial +FLASH file system. + +| + +-------------- + +| + +Atmel SAM4S. There are ports to two Atmel SAM4S board: + +- There is a port the Atmel SAM4S Xplained development board. This + board features the ATSAM4S16 MCU running at 120MHz with 1MB of FLASH + and 128KB of internal SRAM. + +- There is also a port to the Atmel SAM4S Xplained *Pro* development + board. This board features the ATSAM4S32C MCU running at 120MHz with + 2MB of FLASH and 160KB of internal SRAM. + +| + +-------------- + +| + +Atmel SAM4E. General architectural support was provided for the SAM4E +family in NuttX 6.32. This was *architecture-only* support, meaning that +support for the boards with these chips is available, but no support for +any publicly available boards was included. This support was contributed +in part by Mitko. + +**Atmel SAM4E-EK**. Board support was added for the SAM4E-EK development +board in NuttX 7.1. A fully functional NuttShell (NSH) configuration is +available (see the `NSH User +Guide `__). That NSH +configuration includes networking support and support for an AT25 Serial +FLASH file system. + +| + +-------------- + +| + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU Cortex-M3 or 4 toolchain, 3) Cygwin/MSYS +with Windows native GNU Cortex-M3 or M4 toolchain (CodeSourcery or +devkitARM), or 4) Native Windows. A DIY toolchain for Linux or Cygwin is +provided by the NuttX +`buildroot `__ +package. + + + +ARM Cortex-M7. + +| + +Atmel SAMV71. This port uses Atmel SAM V71 Xplained Ultra Evaluation Kit +(SAMV71-XULT). This board features the ATSAMV71Q21 Cortex-M7 +microcontroller. Refer to the `Atmel web +site `__ for further +information about this board. + +**STATUS:** The basic port is complete and there are several different, +verified configurations available. All configurations use the NuttShell +(NSH) and a serial console. The first release of the SAMV71-XULT port +was available in NuttX-7.9. Support for the connect maXTouch Xplained +Pro LCD as added in NuttX-7.10. + +Additional drivers, with status as of 2015-04-03, include: + +- PIO configuration, including PIO interrupts, +- On-board LEDs and buttons, +- DMA, +- SDRAM (not yet functional), +- UART/USART-based serial drivers, including the NuttShell serial + console, +- High Speed Memory Card Interface (HSMCI) with support for the on + board SD card slot, +- SPI (not fully tested), +- TWIHS/I2C, with the support for the on-board serial EEPROM, +- SSC/I2S (not fully tested), +- Ethernet MAC, +- USB device controller driver (complete, partially functional, but not + well tested). +- On-board AT24 I2C EEPROM. +- On-board WM8904 Audio CODEC with CS2100-CP Fractional-N Multiplier + (not yet tested). +- Support for the (optional) maXTouch Xplained Pro LCD module. + +Additional Drivers added in NuttX-7.11 include: + +- MCAN CAN device driver (fully verified in loopback mode only). +- SPI slave driver. + +Additional Drivers added in NuttX-7.13 include: + +- MPU and protected build mode support. +- Timer/Counter driver, one-shot timer, free-running timer support. +- *Tickless* mode of operation. +- QuadSPI driver. +- Support for programming on-chip FLASH. + +And in NuttX-7.14: + +- TRNG driver, +- WDT driver, and +- RSWDT driver. + +Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +Atmel SAME70. This port uses Atmel SAM E70 Xplained Evaluation Kit +(ATSAME70-XPLD). This board is essentially a lower cost version of the +SAMV71-XULT board featuring the ATSAME70Q21 Cortex-M7 microcontroller. +See the `Atmel SAMV71 <#at91samv71>`__ for supported features. Also +refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +Atmel SAMD5x/E5x. The port of NuttX to Adafruit Metro M4 development +board was released with NuttX-7/26. This board is essentially a advanced +version of the Adafruit Metro board based on the SAMD21, but upgraded to +the SAMD51, specifically the SAMD51J19. See the +`Adafruit `__ web page for +additional information about the board. + +A fully-function, basic NuttShell (NSH) configuration was was available +in this initial NuttX-7.26 release. That initial port verifies clock +configuration boot-up logic, SysTick timer, and SERCOM USART for the +serial console. The NSH configuration also includes use of the Cortex-M +Cache Controller (CMCC) which give the SAMD51's Cortex-M4 a performance +boost. + +Because of the similarity in peripherals, several drivers were brought +in from the SAML21 port. Most have not been verified as of the +NuttX-7.26 release. These unverfied drivers include: SPI, I2C, DMA, USB. +Also refer to the NuttX board +`README `__ +file for further information about the current state of the port. + +Nuttx-9.0 added basic support for Microchip SAME54 Xplained Pro board. +An ethernet driver was also added to the SAME5x familly. + +| + +-------------- + +| + +STMicro STM32 F72x/F73x. Support for the F72x/F73x family was provided +by Bob Feretich in NuttX-7.23. A single board is supported in this +family: + +**STATUS**: See `below <#stm32f7drivers>`__ for STM32 F7 driver +availability. + +| + +-------------- + +| + +STMicro STM32 F745/F746. Three boards are supported for this MCU: + +#. **STM32F746G Discovery**. One port uses the STMicro STM32F746G-DISCO + development board featuring the STM32F746NGH6 MCU. The STM32F746NGH6 + is a 216MHz Cortex-M7 operation with 1024Kb Flash. The first release + of the STM32F746G_DISCO port was available in NuttX-7.11. Refer to + the `STMicro web site `__ for + further information about this board. + +#. **Nucleo-144 board with STM32F746ZG**. A basic port for the + Nucleo-144 board with the STM32F746ZG MCU was contributed in + NuttX-7.16 by Kconstantin Berezenko. + +STM32 F7 Driver Status: + +- **NuttX-7.11**. Serial driver and Ethernet driver support, along with + DMA support, were available in this initial release. The STM32 F7 + peripherals are very similar to some members of the STM32 F4 and + additional drivers can easily be ported the F7 as discussed in this + Wiki page: `Porting Drivers to the STM32 + F7 `__ + +- **NuttX-7.17**. David Sidrane contributed PWR, RTC, BBSRAM, and + DBGMCU support. Lok Tep contribed SPI, I2c, ADC, SDMMC, and USB + device driver support. + +- **NuttX-7.22**. Titus von Boxberg also contributed LTDC support for + the onboard LCD in NuttX-7.22. + +- **NuttX-7.29**. In NuttX-7.29, Valmantas Paliksa added a timer + lowerhalf driver for STM32F7, ITM syslog support, a CAN driver with + support for three bxCAN interfaces, and STM32F7 Quad SPI support. + Support for DMA and USB OTG was added by Mateusz Szafoni in + NuttX-7.29. + +- **NuttX-7.30**. From Eduard Niesner contributed a PWM driver. Added + UID access from Valmantas Paliksa. USB High speed driver was added + for STM32F7 series by Ramtin Amin. + +- **NuttX-9.0**. Added serial DMA support. + +| + +-------------- + +| + +STMicro STM32 F756. Architecture-only support is available for the STM32 +F756 family (meaning that the parts are supported, but there is no +example board supported in the system). This support was made available +in NuttX-7.11. See `above <#stm32f7drivers>`__ for STM32 F7 driver +availability. + +| + +-------------- + +| + +STMicro STM32 F76xx/F77xx. Architecture support for the STM32 F76xx and +F77xx families was contributed by David Sidrane in NuttX 7.17. Support +is available for two boards from this family: + +- **Nucleo-F767ZI**. This is a member of the Nucleo-144 board family. + Support for this board was also contributed by David Sidrane in + NuttX-7.17. See the board + `README.txt `__ + file for further information. + +- **STM32F76I-DISCO**. Support for the STM32F76I-DISCO was contributed + by Titus von Boxberg in NuttX-7.22. The STMicro STM32F769I-DISCO + development board features the STM32F769NIH6 MCU. The STM32F769NIH6 + is a 216MHz Cortex-M7 operating with 2048K Flash memory and 512Kb + SRAM. The board features: + + - On-board ST-LINK/V2 for programming and debugging, + - Mbed-enabled (mbed.org) + - 4-inch 800x472 color LCD-TFT with capacitive touch screen + - SAI audio codec + - Audio line in and line out jack + - Two ST MEMS microphones + - SPDIF RCA input connector + - Two pushbuttons (user and reset) + - 512-Mbit Quad-SPI Flash memory + - 128-Mbit SDRAM + - Connector for microSD card + - RF-EEPROM daughterboard connector + - USB OTG HS with Micro-AB connectors + - Ethernet connector compliant with IEEE-802.3-2002 and PoE + + Refer to the http://www.st.com website for further information about + this board (search keyword: stm32f769i-disco). See also the board + `README.txt `__ + file for further information. + +**STATUS**: See `above <#stm32f7drivers>`__ for STM32 F7 driver +availability. + +| + +-------------- + +| + +STMicro STM32 H7x3 Architecture support for the STM32 H7x3 was added +through efforts of several people in NuttX-7.26. Support is available +for one board from this family: + +- **Nucleo-H743ZI**. This is a member of the Nucleo-144 board family. + Support for this board was added in NuttX-7.26. See the board + `README.txt `__ + file for further information. + + The basic NSH configuration is fully, thanks to the bring-up efforts + of Mateusz Szafoni. This port is still a work in progress and + additional drivers are being ported from the F7 family. + +- **STMicro STM32H747I-DISCO**. Support for this board was added in + NuttX-9.0. See the board + `README.txt `__ + file for further information. + + This port is still a work in progress. + +| + +**Driver Availability**: + +**NuttX-7.27**. Add I2C and SPI support for the STM32H7. From Mateusz +Szafoni. + +**NuttX-7.30**. Added support for Ethernet, SDMMC, and Timer drivers. +All from Jukka Laitinen. + +**NuttX-8.1**. Added support for BBSRAM, DTCM, RTC, and UID. All from +David Sidrane. + +**NuttX-8.2**. Added support for SDMMC and FLASH progmem. From David +Sidrane. + +**NuttX-9.0**. Added QSPI support for the STM32H7. + +| + +-------------- + +| + +NXP/Freescale i.MX RT. The initial port to the IMXRT1050-EVKB featuring +the MIMXRT1052DVL6A *Crossover* MCU was included initially in +NuttX-7.25. The initial port was the joint effort of Janne Rosberg, Ivan +Ucherdzhiev, and myself. Ivan gets credit for the bulk of the bring-up +work and for the Hyper FLASH boot logic. + +Another port, this one for the IMXRT1060-EVKB featuring the +MIMXRT1062DVL6A *Crossover* MCU, was added by David Sidrane in +NuttX-7.27. + +**STATUS:** + +- The basic IMXRT1050-EVK port is complete and verified configurations + are available. Refer to the NuttX board + `README `__ + file for further information. + +- The basic IMXRT1060-EVK port was complete but un-verified as of + NuttX-7.27 but has been fully verified since NuttX-7.27 Refer to the + NuttX board + `README `__ + file for more current status information. + +- Architecture-only support for the IMXRT1020 family was contributed in + NuttX-7.30 by Dave Marples. + +- The basic IMXRT1020-EVK port was complete with verified + configurations in NuttX-8.2. This is again the work of Dave Marples. + The initial release includes *nsh*, *netnsh*, and *usdhc* + configurations. Refer to the NuttX board + `README `__ + file for further information. + +**i.MX RT Driver Status:** + +- **NuttX-7.25**. The initial release in NuttX-7.25 includes UART, + Timer, GPIO, DMA, and Ethernet support (Ethernet support was + contributed by Jake Choy). + +- **NuttX-7.26**. NuttX-7.26 added RTC, SNVS, and Serial TERMIOS + support. + +- **NuttX-7.27**. NuttX-7.27 added LPI2C (from Ivan Ucherdzhiev) and SD + card support via USDHC (from Dave Marples). + +- **NuttX-7.28**. GPIO support Input daisy selection was added in + NuttX-7.28 by David Sidrane + +- **NuttX-7.29**. XBAR and OCOTP support was added in NuttX-7.28 by + David Sidrane. LCD Framebuffer support was added by Johannes. + +- **NuttX-7.31**. USB EHCI Host and USDHC drivers were added in + NuttX-7.31 by Dave Marples. + +- **NuttX-8.2**. An LCD drivers was added in NuttX-8.2 by Fabio + Balzano. + + **NuttX-9.0**. Added USB Device support. + +| + +-------------- + +| + +**Development Environments:** The same basic development environment is +recommended for the Cortex-M7 as for the Cortex-M4. It would be wise to +use the latest GNU toolchains for this part because as of this writing +(2015-02-09), support for the Cortex-M7 is a very new GCC feature. + + + +Atmel AVR. + +| + +**AVR ATMega**. + +SoC Robotics ATMega128. This port of NuttX to the Amber Web Server from +`SoC Robotics `__ is partially +completed. The Amber Web Server is based on an Atmel ATMega128. + +LowPowerLab MoteinoMEGA. This port of NuttX to the MoteinoMEGA from +`LowPowerLab `__. The MoteinoMEGA is based +on an Atmel ATMega1284P. See the LowPowerlab +`website `__ +and the board +`README `__ +file for further information. + +Arduino MEGA2560. Extension of the AVR architecture to support the +ATMega2560 and specifi support for the Arduion MEGA2560 board were +contributed by Dimitry Kloper and first released in NuttX-7.14. + +| + +-------------- + +| + +AVR AT90USB64x and AT90USB6128x. + +**Micropendous 3 AT90USB64x** and **AT90USB6128x**. This port of NuttX +to the Opendous Micropendous 3 board. The Micropendous3 is may be +populated with an AT90USB646, 647, 1286, or 1287. I have only the +AT90USB647 version for testing. This version have very limited memory +resources: 64K of FLASH and 4K of SRAM. + +**PJRC Teensy++ 2.0 AT90USB1286**. This is a port of NuttX to the PJRC +Teensy++ 2.0 board. This board was developed by +`PJRC `__. The Teensy++ 2.0 is based on an +Atmel AT90USB1286 MCU. + +| + +-------------- + +| + +**AVR-Specific Issues**. The basic AVR port is solid. The biggest issue +for using AVR is its tiny SRAM memory and its Harvard architecture. +Because of the Harvard architecture, constant data that resides to flash +is inaccessible using "normal" memory reads and writes (only SRAM data +can be accessed "normally"). Special AVR instructions are available for +accessing data in FLASH, but these have not been integrated into the +normal, general purpose OS. + +Most NuttX test applications are console-oriented with lots of strings +used for ``printf()`` and debug output. These strings are all stored in +SRAM now due to these data accessing issues and even the smallest +console-oriented applications can quickly fill a 4-8K memory. So, in +order for the AVR port to be useful, one of two things would need to be +done: + +#. Don't use console applications that required lots of strings. The + basic AVR port is solid and your typical deeply embedded application + should work fine. Or, +#. Create a special version of printf that knows how to access strings + that reside in FLASH (or EEPROM). + +| + +-------------- + +| + +**Development Environments:** 1) Linux with native Linux GNU toolchain, +2) Cygwin/MSYS with Cygwin GNU toolchain, 3) Cygwin/MSYS with Windows +native toolchain, or 4) Native Windows. All testing, however, has been +performed using the NuttX DIY toolchain for Linux or Cygwin is provided +by the NuttX +`buildroot `__ +package. As a result, that toolchain is recommended. + +| + +| + + + +Atmel AVR32. + +| + +AV32DEV1. This port uses the www.mcuzone.com AVRDEV1 board based on the +Atmel AT32UC3B0256 MCU. This port requires a special GNU avr32 toolchain +available from atmel.com website. This is a windows native toolchain and +so can be used only under Cygwin on Windows. + +**STATUS:** This port is has completed all basic development, but there +is more that needs to be done. All code is complete for the basic NuttX +port including header files for all AT32UC3\* peripherals. The untested +AVR32 code was present in the 5.12 release of NuttX. Since then, the +basic RTOS port has solidified: + +- The port successfully passes the NuttX OS test + (apps/examples/ostest). +- A NuttShell (NSH) configuration is in place (see the `NSH User + Guide `__). + Testing of that configuration has been postponed (because it got + bumped by the Olimex LPC1766-STK port). Current Status: I think I + have a hardware problem with my serial port setup. There is a good + chance that the NSH port is complete and functional, but I am not yet + able to demonstrate that. At present, I get nothing coming in the + serial RXD line (probably because the pins are configured wrong or I + have the MAX232 connected wrong). + +The basic, port was be released in NuttX-5.13. A complete port will +include drivers for additional AVR32 UC3 devices -- like SPI and USB --- +and will be available in a later release, time permitting. Refer to the +NuttX board +`README `__ +file for further information. + + + +**Misoc**. + +| + +Misoc LM32 Architectural Support. Architectural support for the Misoc +LM32 was contributed by Ramtin Amin in NuttX 7.19 + +Minerva. Architectural support for the Misoc Minoerva was contributed by +Ramtin Amin in NuttX 7.29. + +**Drivers**. Driver support is basic in these initial releases: Serial, +Timer, and Ethernet. "Board" support is a available for developing with +Misoc LM32 under Qemu or on your custom FPGA. + + + +OpenRISC mor1kx. + +| + +**OpenRISC mor1kx Architectural Support**. Architectural support for the +OpenRISC mor1kx was developed by Matt Thompson Amin and released in +NuttX 7.25. Currently only an mor1kx Qemu simulation is available for +testing. + + + +Freescale M68HCS12. + +| + +**MC9S12NE64**. Support for the MC9S12NE64 MCU and two boards are +included: + +- The Freescale DEMO9S12NE64 Evaluation Board, and +- The Future Electronics Group NE64 /PoE Badge board. + +Both use a GNU arm-nuttx-elf toolchain\* under Linux or Cygwin. The +NuttX `buildroot `__ +provides a properly patched GCC 3.4.4 toolchain that is highly optimized +for the m9s12x family. + + + +Intel 80x86. + +| + +**QEMU/Bifferboard i486**. This port uses the +`QEMU `__ i486 and the native Linux, +Cygwin, MinGW the GCC toolchain under Linux or Cygwin. + +**STATUS:** The basic port was code-complete in NuttX-5.19 and verified +in NuttX-6.0. The port was verified using the OS and NuttShell (NSH) +examples under QEMU. The port is reported to be functional on the +`Bifferboard `__ as well. In NuttX 7.1, +Lizhuoyi contributed additional keyboard and VGA drivers. This is a +great, stable starting point for anyone interested in fleshing out the +x86 port! Refer to the NuttX +`README `__ +file for further information. + +**QEMU/Intel64** An x86_64 flat address port was ported in NuttX-9.0. It +consists of the following feautres: + +- - Runs in x86_64 long mode. +- - Configurable SSE/AVX support. +- - IRQs are managed by LAPIC(X2APIC) and IOAPIC. +- - Used TSC_DEADLINE or APIC timer for systick. +- - Pages are now maps the kernel at 4GB~, but changeable. + +This kernel with ostest have been tested with + +- Qemu/KVM on a Xeon 2630v4 machine. +- Bochs with broadwell_ult emulation. + + + +Microchip PIC32MX (MIPS M4K). + +| + +PIC32MX250F128D. A port is in progress from the DTX1-4000L "Mirtoo" +module from `Dimitech `__. This module uses +Microchip PIC32MX250F128D and the Dimitech DTX1-4000L EV-kit1 V2. See +the `Dimitech `__ website for further +information. + +| + +-------------- + +| + +PIC32MX4xx Family. + +**PIC32MX440F512H**. This port uses the "Advanced USB Storage Demo +Board," Model DB-DP11215, from `Sure +Electronics `__. This board features the +Microchip PIC32MX440F512H. See the `Sure +website `__ for +further information about the DB-DP11215 board. (I believe that that the +DB-DP11215 may be obsoleted now but replaced with the very similar, +DB-DP11212. The DB-DP11212 board differs, I believe, only in its serial +port configuration.) + +**PIC32MX460F512L**. There one two board ports using this chip: + +- **PIC32MX Board from PCB Logic Design Co**. This port is for the + PIC32MX board from PCB Logic Design Co. and used the PIC32MX460F512L. + The board is a very simple -- little more than a carrier for the + PIC32 MCU plus voltage regulation, debug interface, and an OTG + connector. +- **UBW32 Board from Sparkfun** This is the port to the Sparkfun UBW32 + board. This port uses the `original + v2.5 `__ board which is based + on the Microchip PIC32MX460F512L. This older version has been + replaced with this `newer + board `__. See also the + `UBW32 `__ web site. + +| + +-------------- + +| + +PIC32MX795F512L. There one two board ports using this chip: + +- **Microchip PIC32 Ethernet Starter Kit**. This port uses the + Microchip PIC32 Ethernet Starter Kit (DM320004) with the Expansion + I/O board. See the `Microchip website `__ + for further information. +- **Mikroelektronika PIC32MX7 Mulitmedia Board (MMB)**. A port has been + completed for the Mikroelektronika PIC32MX7 Multimedia Board (MMB). + See http://www.mikroe.com/ for further information about this board. + +| + +-------------- + +| + +**Development Environment:** These ports uses either: + +#. The *LITE* version of the PIC32MX toolchain available for download + from the `Microchip `__ website, or +#. The Pinguino MIPS ELF toolchain available from the Pinguino + `website `__. +#. The MIPS SDE toolchain available from the `Mentor + Graphics `__ website. + + + +Microchip PIC32MZ. + +| + +PIC32MZEC Family (MIPS microAptiv). A port is in available for the +PIC32MZ Embedded Connectivity (EC) Starter Kit. There are two +configurations of the Microchip PIC32MZ EC Starter Kit: + +#. The PIC32MZ Embedded Connectivity Starter Kit based on the + PIC32MZ2048ECH144-I/PH chip (DM320006), and +#. The PIC32MZ Embedded Connectivity Starter Kit based on the + PIC32MZ2048ECM144-I/PH w/Crypto Engine (DM320006-C). + +See the `Microchip `__ website for further +information. + +This was a collaborative effort between Kristopher Tate, David Sidrane +and myself. The basic port is functional and a NuttShell (NSH) +configuration is available. + +PIC32MZEF Family (MIPS M5150). A port is in available for the +MikroElectronika `Flip&Click +PIC32MZ `__ development board +based on the PIC32MZ2048EFH100 MCU. This board configuration was added +in NuttX-7.24 and is, for the most part, compatible with the PIC32MZEC +family. + +**STATUS:** + +**NuttX-7.9**. The first official release was in NuttX-7.9. Many drivers +port simply from the PIC32MX; others require more extensive efforts. +Driver status as of (2015-03-29) is provided below: + +- I/O ports include I/O port interrupts +- UART serial driver that provides the NSH console, +- Timer, +- I2C (untested), +- SPI (untested), +- On-board buttons and LEDs, +- Ethernet (code complete, but not yet functional), + +**NuttX-7.29**. Abdelatif Guettouche contributed additional timer +support including: Timer lower half driver, free-running, and one-shot +timers. + +**NuttX-7.31**. Abdelatif Guettouche contributed DMA support. + +**NuttX-9.0**. Cache operations were implemented. + +Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +**Development Environment:** Same as for the PIC32MZ. + +| + +-------------- + + + +Renesas/Hitachi SuperH. + +| + +**SH-1 SH7032**. This port uses the Hitachi SH-1 Low-Cost Evaluation +Board (SH1_LCEVB1), US7032EVB, with a GNU ELF toolchain\* under Linux or +Cygwin. + + + +Renesas M16C/26. + +| + +**Renesas M16C/26 Microcontroller**. This port uses the Renesas SKP16C26 +Starter kit and the GNU M32C toolchain. The development environment is +either Linux or Cygwin under WinXP. + +**STATUS:** Initial source files released in nuttx-0.4.2. At this point, +the port has not been integrated; the target cannot be built because the +GNU ``m16c-nuttx-elf-ld`` link fails with the following message: + +Where the reference line is: + +No workaround is known at this time. This is a show stopper for M16C. +Refer to the NuttX board +`README `__ +file for further information. + + + +Renesas RX65N. + +| + +Support for the Renesas RX65N family was released in NuttX with a +contribution from Anjana. Two boards are supported in this initial +release: + +- **RSK RX65N-2MB**. +- **GR-Rose**. + +**STATUS** + +- **NuttX-8.2** +- **NuttX-9.0** RTC driver for the RX65N was added. + + + +RISC-V. + +| + +RISC-V Architectural Support. Basic support for the RISC-V architecture +was contributed by Ken Pettit in NuttX-7.19. This support is for a +custom NEXT RISC-V NR5Mxx (RV32IM). The initial release is *thin* but a +great starting point for anyone interested in RISC-V development with +NuttX. + +GreenWaves GAP8 (RV32IM). Basic support GreenWaves GAP8 *gapuino* board +was added by hhuysqt in NuttX-7.27. The GAP8 is a 1+8-core DSP-like +RISC-V MCU. The GAP8 features a RI5CY core called Fabric Controller(FC), +and a cluster of 8 RI5CY cores that runs at a bit slower speed. The GAP8 +is an implementation of the opensource PULP platform, a +Parallel-Ultra-Low-Power design. + +`Sipeed Maix bit <#k210>`__ + +Initial support for the Sipeed Maix bit board was added in Nuttx-9.0. + +Litex ARTY_A7. Support for the Digilent ARTY_A7 board along with CPU +VexRiscV SOC were added in NuttX-9.0. + + + +ESP32 (Dual Xtensa LX6). + +| + +**Xtensa LX6 ESP32 Architectural Support**. Basic architectural support +for Xtensa LX6 processors and the port for the Espressif ESP32 were +added in NuttX-7.19. The basic ESP32 port is function in both single CPU +and dual CPU SMP configurations. + +**Espressif ESP32 Core v2 Board** The NuttX release includes support for +Espressif ESP32 Core v2 board. There is an NSH configuration for each +CPU configuration and an OS test configuration for verificatin of the +port. + +**STATUS**. ESP32 support in NuttX-7.19 is functional, but very +preliminary. There is little yet in the way of device driver support. +Outstanding issues include missing clock configuration logic, missing +partition tables to support correct configuration from FLASH, and some +serial driver pin configuration issues. The configuration is usable +despite these limitations. Refer to the NuttX board +`README `__ +file for further information. + + + +Zilog ZNEO Z16F. + +| + +- **Zilog z16f2800100zcog development kit**. This port use the Zilog + z16f2800100zcog development kit and the Zilog ZDS-II Windows command + line tools. The development environment is either Windows native or + Cygwin under Windows. + + **STATUS:** The initial release of support for the z16f was made + available in NuttX version 0.3.7. A working NuttShell (NSH) + configuration as added in NuttX-6.33 (although a patch is required to + work around an issue with a ZDS-II 5.0.1 tool problem). An ESPI + driver was added in NuttX-7.2. Refer to the NuttX board + `README `__ + file for further information. + + + +Zilog eZ80 Acclaim!. + +| + +**Zilog eZ80Acclaim! Microcontroller**. There are four eZ80Acclaim! +ports: + +- The ZiLOG ez80f0910200kitg development kit. +- The ZiLOG ez80f0910200zcog-d development kit. +- The MakerLisp CPU board. +- The Z20x DIY computing system. + +All three boards are based on the eZ80F091 part and all use the Zilog +ZDS-II Windows command line tools. The development environment is either +Windows native or Cygwin or MSYS2 under Windows. + + + +Zilog Z8Encore!. + +| + +**Zilog Z8Encore! Microcontroller**. This port uses the either: + +- Zilog z8encore000zco development kit, Z8F6403 part, or +- Zilog z8f64200100kit development kit, Z8F6423 part + +and the Zilog ZDS-II Windows command line tools. The development +environment is either Windows native or Cygwin under Windows. + +**STATUS:** This release has been verified only on the ZiLOG ZDS-II +Z8Encore! chip simulation as of nuttx-0.3.9. Refer to the NuttX board +README files for the +`z8encore000zco `__ +and for +the\ `z8f64200100kit `__ +for further information. + + + +Zilog Z180. + +| + +**P112**. The P112 is a hobbyist single board computer based on a 16MHz +Z80182 with up to 1MB of memory, serial, parallel and diskette IO, and +realtime clock, in a 3.5-inch drive form factor. The P112 computer +originated as a commercial product of "D-X Designs Pty Ltd"[ of +Australia. + +Dave Brooks was successfully funded through Kickstarter for and another +run of P112 boards in November of 2012. In addition Terry Gulczynski +makes additional P112 derivative hobbyist home brew computers. + +**STATUS:** Most of the NuttX is in port for both the Z80182 and for the +P112 board. Boards from Kickstarter project will not be available, +however, until the third quarter of 2013. So it will be some time before +this port is verified on hardware. Refer to the NuttX board +`README `__ +file for further information. + + + +Zilog Z80. + +| + +**Z80 Instruction Set Simulator**. This port uses the +`SDCC `__ toolchain under Linux or Cygwin +(verified using version 2.6.0). This port has been verified using only a +Z80 instruction simulator called z80sim. + +**STATUS:** This port is complete and stable to the extent that it can +be tested using an instruction set simulator. Refer to the NuttX board +`README `__ +file for further information. + +| + +-------------- + +| + +**XTRS: TRS-80 Model I/III/4/4P Emulator for Unix**. A very similar Z80 +port is available for `XTRS `__, the +TRS-80 Model I/III/4/4P Emulator for Unix. That port also uses the +`SDCC `__ toolchain under Linux or Cygwin +(verified using version 2.6.0). + +**STATUS:** Basically the same as for the Z80 instruction set simulator. +This port was contributed by Jacques Pelletier. Refer to the NuttX board +`README `__ +file for further information. + +**NOTE:** This port was removed from the NuttX source tree on +2017-11-24. It was removed because (1) it is unfinished, unverified, and +unsupported, and (2) the TRS-80 simulation is a sub-optimal platform.i +That platform includes a 16-bit ROM image and only a 48Kb RAM space for +NuttX. The removed board support is still available in the ``Obsoleted`` +repository if anyone would ever like to resurrect it. + + \* A highly modified `buildroot `__ is + available that may be used to build a NuttX-compatible ELF toolchain + under Linux or Cygwin. Configurations are available in that buildroot + to support ARM, Cortex-M3, avr, m68k, m68hc11, m68hc12, m9s12, + blackfin, m32c, h8, and SuperH ports. + diff --git a/doc/introduction/development_environments.rst b/doc/introduction/development_environments.rst new file mode 100644 index 00000000000..116c3022f3b --- /dev/null +++ b/doc/introduction/development_environments.rst @@ -0,0 +1,153 @@ +======================== +Development Environments +======================== + +Linux + GNU ``make`` + GCC/binutils for Linux +============================================= + +The is the most natural development environment for NuttX. Any version +of the GCC/binutils toolchain may be used. There is a highly modified +`buildroot `__ available for download from +the `NuttX +Bitbucket.org `__ +page. This download may be used to build a NuttX-compatible ELF +toolchain under Linux or Cygwin. That toolchain will support ARM, m68k, +m68hc11, m68hc12, and SuperH ports. The buildroot GIT may be accessed in +the NuttX `buildroot GIT `__. + +Linux + GNU ``make`` + SDCC for Linux +===================================== + +Also very usable is the Linux environment using the +`SDCC `__ compiler. The SDCC compiler +provides support for the 8051/2, z80, hc08, and other microcontrollers. +The SDCC-based logic is less well exercised and you will likely find +some compilation issues if you use parts of NuttX with SDCC that have +not been well-tested. + +Windows with Cygwin + GNU ``make`` + GCC/binutils (custom built under Cygwin) +============================================================================= + +This combination works well too. It works just as well as the native +Linux environment except that compilation and build times are a little +longer. The custom NuttX +`buildroot `__ +referenced above may be build in the Cygwin environment as well. + +Windows with Cygwin + GNU ``make`` + SDCC (custom built under Cygwin) +===================================================================== + +I have never tried this combination, but it would probably work just +fine. + +Windows with Cygwin + GNU ``make`` + Windows Native Toolchain +============================================================= + +This is a tougher environment. In this case, the Windows native +toolchain is unaware of the Cygwin *sandbox* and, instead, operates in +the native Windows environment. The primary difficulties with this are: + +- **Paths**. Full paths for the native toolchain must follow Windows + standards. For example, the path ``/home/my\ name/nuttx/include`` my + have to be converted to something like + ``'C:\cygwin\home\my name\nuttx\include'`` to be usable by the + toolchain. +- **Symbolic Links** NuttX depends on symbolic links to install + platform-specific directories in the build system. On Linux, true + symbolic links are used. On Cygwin, emulated symbolic links are used. + Unfortunately, for native Windows applications that operate outside + of the Cygwin *sandbox*, these symbolic links cannot be used. +- **Dependencies** NuttX uses the GCC compiler's ``-M`` option to + generate make dependencies. These dependencies are retained in files + called ``Make.deps`` throughout the system. For compilers other than + GCC, there is no support for making dependencies in this way. + +**Supported Windows Native Toolchains**. At present, the following +Windows native toolchains are in use: + +#. GCC built for Windows (such as CodeSourcery, Atollic, devkitARM, + etc.), +#. SDCC built for Windows, +#. the ZiLOG XDS-II toolchain for Z16F, z8Encore, and eZ80Acclaim parts. + +Windows Native (``CMD.exe``) + GNUWin32 (including GNU ``make``) + MinGW Host GCC compiler + Windows Native Toolchain +===================================================================================================================== + +Build support has been added to support building natively in a Windows +console rather than in a POSIX-like environment. + +This build: + +#. Uses all Windows style paths +#. Uses primarily Windows batch commands from cmd.exe, with +#. A few extensions from GNUWin32 + +This capability first appeared in NuttX-6.24 and should still be +considered a work in progress because: (1) it has not been verfied on +all targets and tools, and (2) still lacks some of the creature-comforts +of the more mature environments. The windows native build logic +initiated if ``CONFIG_WINDOWS_NATIVE=y`` is defined in the NuttX +configuration file: + +At present, this build environment also requires: + +**Windows Console**. The build must be performed in a Windows console +window. This may be using the standard ``CMD.exe`` terminal that comes +with Windows. I prefer the ConEmu terminal which can be downloaded from: +http://code.google.com/p/conemu-maximus5/ + +**GNUWin32**. The build still relies on some Unix-like commands. I +usethe GNUWin32 tools that can be downloaded from +http://gnuwin32.sourceforge.net/. See the top-level ``nuttx/README.txt`` +file for some download, build, and installation notes. + +**MinGW-GCC**. MinGW-GCC is used to compiler the C tools in the +``nuttx/tools`` directory that are needed by the build. MinGW-GCC can be +downloaded from http://www.mingw.org/. If you are using GNUWin32, then +it is recommended that you not install the optional MSYS components as +there may be conflicts. + +Wine + GNU ``make`` + Windows Native Toolchain +============================================== + +I've never tried this one, but I off the following reported by an ez80 +user using the ZiLOG ZDS-II Windows-native toolchain: + + "I've installed ZDS-II 5.1.1 (IDE for ez80-based boards) on wine + (windows emulator for UNIX) and to my surprise, not many changes were + needed to make GIT snapshot of NuttX buildable... I've tried nsh + profile and build process completed successfully. One remark is + necessary: NuttX makefiles for ez80 are referencing ``cygpath`` + utility. Wine provides similar thing called ``winepath`` which is + compatible and offers compatible syntax. To use that, ``winepath`` + (which itself is a shell script) has to be copied as ``cygpath`` + somewhere in ``$PATH``, and edited as in following patch: + + "Better solution would be replacing all ``cygpath`` references in + ``Makefiles`` with ``$(CONVPATH)`` (or ``${CONVPATH}`` in shell + scripts) and setting ``CONVPATH`` to ``cygpath`` or ``winepath`` + regarding to currently used environment. + + + +Other Environments +================== + +**Environment Dependencies**. The primary environmental dependency of +NuttX are (1) GNU make, (2) bash scripting, and (3) Linux utilities +(such as cat, sed, etc.). If you have other platforms that support GNU +make or make utilities that are compatible with GNU make, then it is +very likely that NuttX would work in that environment as well (with some +porting effort). If GNU make is not supported, then some significant +modification of the Make system would be required. + +**MSYS**. I have not used MSYS but what I gather from talking with NuttX +users is that MSYS can be used as an alternative to Cygwin in any of the +above Cygwin environments. This is not surprising since MSYS is based on +an older version of Cygwin (cygwin-1.3). MSYS has been modified, +however, to interoperate in the Windows environment better than Cygwin +and that may be of value to some users. + +MSYS, however, cannot be used with the native Windows NuttX build +because it will invoke the MSYS bash shell instead of the ``CMD.exe`` +shell. Use GNUWin32 in the native Windows build environment. diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst new file mode 100644 index 00000000000..4579abf950a --- /dev/null +++ b/doc/introduction/index.rst @@ -0,0 +1,17 @@ +Introduction +============ + +.. note:: This section should probably not remain empty. Some content of the "about" document could be placed here (a brief description). Also, it would be good to have a graphic showing the layers of NuttX (I would use this as a base: https://nuttx_projects.gitlab.io/nuttx_book/nuttx-architecture.html) + +.. toctree:: + :maxdepth: 1 + + about.rst + supported_platforms.rst + detailed_support.rst + development_environments.rst + licensing.rst + trademarks.rst + resources.rst + + diff --git a/doc/introduction/licensing.rst b/doc/introduction/licensing.rst new file mode 100644 index 00000000000..3a996fb9744 --- /dev/null +++ b/doc/introduction/licensing.rst @@ -0,0 +1,9 @@ +========= +Licensing +========= + +.. warning:: update to Apache! + +NuttX is available under the highly permissive BSD license. Other than some fine print that +you agree to respect the copyright you should feel absolutely free to use NuttX in any environment and without any concern for jeopardizing any proprietary software that you may link with it. + diff --git a/doc/introduction/resources.rst b/doc/introduction/resources.rst new file mode 100644 index 00000000000..2fcc327c04b --- /dev/null +++ b/doc/introduction/resources.rst @@ -0,0 +1,23 @@ +========= +Resources +========= + +.. note:: this should be revised + +Here's a list of Apache NuttX resources that you might find helpful: + + * Apache NuttX + + * `NuttX website `_ + * `Apache NuttX website `_ + * `Apache NuttX online documentation `_ + * `Apache NuttX mailing list `_ – a very active mailing list, the place to get help with your application or any questions you have about NuttX. + * `Apache NuttX YouTube channel `_ – Alan Carvalho de Assis's YouTube channel on NuttX. It's a source of a lot of great practical information. + * `Apache NuttX Coding Standard `_ — How code should look when you submit new files or modify existing ones. + * `Apache NuttX Code Contribution Guidlines `_ — The full workflow to follow for submitting code with all the details. + + * Git + + * `Git Cheat Sheet (by GitHub) `_ + * `Git Book (online) `_ + diff --git a/doc/introduction/supported_platforms.rst b/doc/introduction/supported_platforms.rst new file mode 100644 index 00000000000..2fefaddc17a --- /dev/null +++ b/doc/introduction/supported_platforms.rst @@ -0,0 +1,430 @@ +.. include:: /substitutions.rst + +=================== +Supported Platforms +=================== + +**Supported Platforms by CPU core**. The number of ports to this +CPU follow in parentheses. The state of the various ports vary +from board-to-board. Follow the links for the details: + +.. list-table:: + :widths: auto + + * - + + - `Linux/Cygwin user mode simulation <#linuxusermode>`__ (1) + - ARM + + - `ARM7TDMI <#arm7tdmi>`__ (4) + - `ARM920T <#arm920t>`__ (1) + - `ARM926EJS <#arm926ejs>`__ (4) + - `Other ARMv4 <#armv4>`__ (1) + - `ARM1176JZ <#arm1176jz>`__ (1) + - `ARM Cortex-A5 <#armcortexa5>`__ (3) + - `ARM Cortex-A8 <#armcortexa8>`__ (2) + - `ARM Cortex-A9 <#armcortexa9>`__ (1) + - `ARM Cortex-R4 <#armcortexr4>`__ (2) + - `ARM Cortex-M0/M0+ <#armcortexm0>`__ (13) + - `ARM Cortex-M3 <#armcortexm3>`__ (39) + - `ARM Cortex-M4 <#armcortexm4>`__ (59) + - `ARM Cortex-M7 <#armcortexm7>`__ (15) + + - Atmel AVR + + - `Atmel 8-bit AVR <#atmelavr>`__ (5) + - `Atmel AVR32 <#atmelavr32>`__ (1) + + - Freescale + + - `M68HCS12 <#m68hcs12>`__ (2) + - + + - Intel + + - `Intel 80x86 <#80x86>`__ (2) + + - Microchip + + - `PIC32MX <#pic32mxmips>`__ (MIPS M4K) (4) + - `PIC32MZEC <#pic32mzmips>`__ (MIPS microAptive) (1) + - `PIC32MZEF <#pic32mzmips>`__ (MIPS M5150) (1) + + - Misoc + + - `LM32 <#misoclm32>`__ (1) + - `Minerva <#minerva>`__ (1) + + - OpenRISC + + - `mor1kx <#mor1kx>`__ (1) + + - Renesas/Hitachi: + + - `Renesas/Hitachi SuperH <#superh>`__ (1/2) + - `Renesas M16C/26 <#m16c>`__ (1/2) + - `Renesas RX65N <#rx65n>`__ (2) + - + - `RISC-V <#riscv>`__ (2) + + - `NEXT RISC-V NR5Mxx <#nr5mxx>`__ (1) + - `GreenWaves GAP8 (1) <#gwgap8>`__ + - `Kendryte K210 (1) <#k210>`__ + - `Litex (1) <#artya7>`__ + + - Xtensa LX6: + + - `ESP32 <#esp32>`__ (1) + + - ZiLOG + + - `ZiLOG ZNEO Z16F <#zilogz16f>`__ (2) + - `ZiLOG eZ80 Acclaim! <#zilogez80acclaim>`__ (4) + - `ZiLOG Z8Encore! <#zilogz8encore>`__ (2) + - `ZiLOG Z180 <#zilogz180>`__ (1) + - `ZiLOG Z80 <#zilogz80>`__ (2) + +**Supported Platforms by Manufacturer/MCU Family**. CPU core type +follows in parentheses. The state of the various ports vary from MCU to +MCU. Follow the links for the details: + +.. list-table:: + + * - + + - `Linux/Cygwin user mode simulation <#linuxusermode>`__ (1) ARM + - Allwinner + + - `A10 <#allwinnera10>`__ (Cortex-A8) + + - Broadcom + + - `BCM2708 <#bcm2708>`__ (ARM1176JZ) + + - Espressif + + - `ESP32 <#esp32>`__ (Dual Xtensa LX6) + + - GreenWaves + + - `GAP8 <#gwgap8>`__ (RISC-V RV32IM) + + - Host PC based simulations + + - `Linux/Cygwin user mode simulation <#linuxusermode>`__ + + - Infineon + + - `Infineon XMC45xx <#xmd45xx>`__ + + - Intel + + - `Intel 80x86 <#80x86>`__ + + - Maxim Integrated + + - `MAX32660 <#max3660>`__ (ARM Cortex-M3) + + - Microchip + + - `PIC32MX2xx Family <#pic32mx2xx>`__ (MIPS32 M4K) + - `PIC32MX4xx Family <#pic32mx4xx>`__ (MIPS32 M4K) + - `PIC32MX7xx Family <#pic32mx7xx>`__ (MIPS32 M4K) + - `PIC32MZEC Family <#pic32mzec>`__ (MIPS32 |br| + microAptiv) + - `PIC32MZEF Family <#pic32mzef>`__ (MIPS32 M5150) + + - Microchip (Formerly Atmel) + + - `AVR ATMega128 <#avratmega128>`__ (8-bit AVR) + - `AVR ATMega1284p <#avratmega1284p>`__ (8-bit AVR) + - `AVR ATMega2560 <#avratmega2560>`__ (8-bit AVR) + - `AVR AT90USB64x and AT90USB6128x <#avrat90usbxxx>`__ |br| + (8-bit AVR) + - `AVR32 AT32UC3BXXX <#at32uc3bxxx>`__ (32-bit AVR32) + - `Atmel SAMD20 <#at91samd20>`__ (ARM Cortex-M0+) + - `Atmel SAMD21 <#at91samd21>`__ (ARM Cortex-M0+) + - `Atmel SAML21 <#at91saml21>`__ (ARM Cortex-M0+) + - `Atmel SAM3U <#at91sam3u>`__ (ARM Cortex-M3) + - `Atmel SAM3X <#at91sam3x>`__ (ARM Cortex-M3) + - `Atmel SAM4C <#at91sam4c>`__ (ARM Cortex-M4) + - `Atmel SAM4E <#at91sam4e>`__ (ARM Cortex-M4) + - `Atmel SAM4L <#at91sam4l>`__ (ARM Cortex-M4) + - `Atmel SAM4S <#at91sam4s>`__ (ARM Cortex-M4) + - `Atmel SAMD5x/E5x <#at91samd5e5>`__ (ARM Cortex-M4) + - `Atmel SAME70 <#at91same70>`__ (ARM Cortex-M7) + - `Atmel SAMV71 <#at91samv71>`__ (ARM Cortex-M7) + - `Atmel SAMA5D2 <#at91sama5d2>`__ (ARM Cortex-A5) + - `Atmel SAMA5D3 <#at91sama5d3>`__ (ARM Cortex-A5) + - `Atmel SAMA5D4 <#at91sama5d4>`__ (ARM Cortex-A5) + + - Moxa + + - `Moxa NP51x0 <#moxart>`__ (ARMv4) + + - nuvoTon + + - `nuvoTon NUC120 <#nuvotonnu120>`__ (ARM Cortex-M0) + + - Nordic Semiconductor + + - `NRF52xxx <#nrf52>`__ (ARM Cortex-M4) + + - NXP/Freescale + + - `M68HCS12 <#m68hcs12>`__ + - `NXP/Freescale i.MX1 <#freescaleimx1>`__ |br| + (ARM920-T) + - `NXP/Freescale i.MX6 <#freescaleimx6>`__ |br| + (ARM Cortex-A9) + - `NXP/Freescale i.MX RT <#freescaleimxrt>`__ |br| + (ARM Cortex-M7) + - `NXP/FreeScale KL25Z <#freescalekl25z>`__ |br| + (ARM Cortex-M0+) + - `NXP/FreeScale KL26Z <#freescalekl26z>`__ |br| + (ARM Cortex-M0+) + + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + - + + - NXP/Freescale (Continued) + + - `NXP/FreeScale Kinetis K20 <#kinetisk20>`__ (ARM |br| + Cortex-M4) + - `NXP/FreeScale Kinetis K28 <#kinetisk28>`__ (ARM |br| + Cortex-M4) + - `NXP/FreeScale Kinetis K40 <#kinetisk40>`__ (ARM |br| + Cortex-M4) + - `NXP/FreeScale Kinetis K60 <#kinetisk60>`__ (ARM |br| + Cortex-M4) + - `NXP/FreeScale Kinetis K64 <#kinetisk64>`__ (ARM |br| + Cortex-M4) + - `NXP/FreeScale Kinetis K66 <#kinetisk66>`__ (ARM |br| + Cortex-M4) + + - `NXP LPC11xx <#nxplpc11xx>`__ (Cortex-M0) + - `NXP LPC214x <#nxplpc214x>`__ (ARM7TDMI) + - `NXP LPC2378 <#nxplpc2378>`__ (ARM7TDMI) + - `NXP LPC3131 <#nxplpc3131>`__ (ARM9E6JS) + - `NXP LPC315x <#nxplpc315x>`__ (ARM9E6JS) + - `NXP LPC176x <#nxplpc176x>`__ (ARM Cortex-M3) + - `NXP LPC178x <#nxplpc178x>`__ (ARM Cortex-M3) + - `NXP LPC40xx <#nxplpc40xx>`__ (ARM Cortex-M4) + - `NXP LPC43xx <#nxplpc43xx>`__ (ARM Cortex-M4) + - `NXP LPC54xx <#nxplpc54xx>`__ (ARM Cortex-M4) + + - `NXP S32K11x <#nxps32k11x>`__ (Cortex-M0+) + - `NXP S32K14x <#nxps32k14x>`__ (Cortex-M4F) + + - ON Semiconductor: + + - `LC823450 <#lc823450>`__ (Dual core ARM Cortex-M3) + + - Renesas/Hitachi: + + - `Renesas/Hitachi SuperH <#superh>`__ + - `Renesas M16C/26 <#m16c>`__ + - `Renesas RX65N <#rx65n>`__ + + - Silicon Laboratories, Inc. + + - `EFM32 Gecko <#efm32g>`__ (ARM Cortex-M3) + - `EFM32 Giant Gecko <#efm32gg>`__ (ARM Cortex-M3) + + - Sony. + + - `CXD56\ xx <#cxd56xx>`__ (6 x ARM Cortex-M4) + + - STMicroelectronics + + - `STMicro STR71x <#str71x>`__ (ARM7TDMI) + - `STMicro STM32F0xx <#stm32f0xx>`__ (STM32 F0, |br| + ARM Cortex-M0) + - `STMicro STM32L0xx <#stm32l0xx>`__ (STM32 L0, |br| + ARM Cortex-M0) + - `STMicro STM32G0xx <#stm32g0xx>`__ (STM32 G0 |br| + ARM Cortex-M0+) + - `STMicro STM32L152 <#stm32l152>`__ (STM32 L1 |br| + "EnergyLite" Line, ARM Cortex-M3) + - `STMicro STM32L162 <#stm32l162>`__ (STM32 L1 |br| + "EnergyLite" Medium+ Density, |br| + ARM Cortex-M3) + - `STMicro STM32F100x <#stm32f100x>`__ (STM32 F1 |br| + "Value Line" Family, ARM Cortex-M3) + - `STMicro STM32F102x <#stm32f102x>`__ (STM32 F1 |br| + family, ARM Cortex-M3) + - `STMicro STM32F103C4/C8 <#stm32f103cx>`__ (STM32 F1 |br| + "Low- and Medium-Density Line" |br| + Family, ARM Cortex-M3) + - `STMicro STM32F103x <#stm32f103x>`__ (STM32 F1 |br| + family, ARM Cortex-M3) + - `STMicro STM32F105x <#stm32f105x>`__ (ARM Cortex-M3) + - `STMicro STM32F107x <#stm32f107x>`__ (STM32 F1 |br| + family, "Connectivity Line" |br| + ARM Cortex-M3) + - `STMicro STM32F205x <#stm32f205x>`__ (STM32 F2 |br| + family, ARM Cortex-M3) + - `STMicro STM32F207x <#stm32f207x>`__ (STM32 F2 |br| + family, ARM Cortex-M3) + - `STMicro STM32F302x <#stm32f302x>`__ (STM32 F3 |br| + family, ARM Cortex-M4) + - `STMicro STM32F303x <#stm32f303x>`__ (STM32 F3 |br| + family, ARM Cortex-M4) + - `STMicro STM32F334 <#stm32f334x>`__ (STM32 F3 |br| + family, ARM Cortex-M4) + + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + |br| + + - + + - STMicroelectronics (Continued) + + - `STMicro STM32 F372/F373 <#stm32f372x>`__ |br| + (ARM Cortex-M4) + - `STMicro STM32F4x1 <#stm32f4x1>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32F410 <#stm32f410>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32F405x/407x <#stm32f407x>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 F427/F437 <#stm32f427x>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 F429 <#stm32f429x>`__ |br| + (STM32 FB family, ARM |br| + Cortex-M4) + - `STMicro STM32 F433 <#stm32f433x>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 F446 <#stm32f446x>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 F46xx <#stm32f46xxx>`__ |br| + (STM32 F4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 G474x <#stm32g474x>`__ |br| + (STM32 G4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 L4x2 <#stm32l4x2>`__ |br| + (STM32 L4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 L475 <#stm32l475>`__ |br| + (STM32 L4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 L476 <#stm32l476>`__ |br| + (STM32 L4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 L496 <#stm32l496>`__ |br| + (STM32 L4 family, ARM |br| + Cortex-M4) + - `STMicro STM32 L4Rx <#stm32l4rx>`__ |br| + (STM32 LB family, ARM |br| + Cortex-M4) + - `STMicro STM32 F72x/F73x <#stm32f72x3x>`__ |br| + (STM32 F7 family, ARM |br| + Cortex-M7) + - `STMicro STM32 F745/F746 <#stm32f74x>`__ |br| + (STM32 F7 family, ARM |br| + Cortex-M7) + - `STMicro STM32 F756 <#stm32f75x>`__ |br| + (STM32 F7 family, ARM |br| + Cortex-M7) + - `STMicro STM32 F76xx/F77xx <#stm32f76xx77xx>`__ |br| + (STM32 F7 family, ARM |br| + Cortex-M7) + - `STMicro STM32 H7x3 <#stm32h7x3>`__ |br| + (STM32 H7 family, ARM |br| + Cortex-M7) + + - Texas Instruments + + - (some formerly Luminary) + - `TI TMS320-C5471 <#tms320c5471>`__ |br| + (ARM7TDMI) + - `TI TMS320-DM320 <#titms320dm320>`__ |br| + (ARM9E6JS) + - `TI/Stellaris LM3S6432 <#tilms6432>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S6432S2E <#tilm3s6432s2e>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S6918 <#tilms6918>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S6965 <#tilms6965>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S8962 <#tilms8962>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S9B92 <#tilms9b92>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM3S9B96 <#tilms9b96>`__ |br| + (ARM Cortex-M3) + - `TI/SimpleLink CC13x0 <#tilcc13x0>`__ |br| + (ARM Cortex-M3) + - `TI/Stellaris LM4F120x <#tilm4f120x>`__ |br| + (ARM Cortex-M4) + - `TI/Tiva TM4C123G <#titm4c123g>`__ |br| + (ARM Cortex-M4) + - `TI/Tiva TM4C1294 <#titm4c1294>`__ |br| + (ARM Cortex-M4) + - `TI/Tiva TM4C129X <#titm4c129x>`__ |br| + (ARM Cortex-M4) + - `TI/SimpleLink CC13x2 <#tilcc13x2>`__ |br| + (ARM Cortex-M4) + - `TI/Hercules TMS570LS04xx <#tms570ls04x>`__ |br| + (ARM Cortex-R4) + - `TI/Hercules TMS570LS31xx <#tms570ls31x>`__ |br| + (ARM Cortex-R4) + - `TI/Sitara AM335x <#tiam355x>`__ |br| + (Cortex-A8) + + - ZiLOG + + - `ZiLOG ZNEO Z16F <#zilogz16f>`__ + - `ZiLOG eZ80 Acclaim! <#zilogez80acclaim>`__ + - `ZiLOG Z8Encore! <#zilogz8encore>`__ + - `ZiLOG Z180 <#zilogz180>`__ + - `ZiLOG Z80 <#zilogz80>`__ + diff --git a/doc/introduction/trademarks.rst b/doc/introduction/trademarks.rst new file mode 100644 index 00000000000..20c9e8bc15f --- /dev/null +++ b/doc/introduction/trademarks.rst @@ -0,0 +1,30 @@ +========== +Trademarks +========== + +- NuttX is a registered trademark of Gregory Nutt. +- ARM, ARM7 ARM7TDMI, ARM9, ARM920T, ARM926EJS, Cortex-M3 are + trademarks of Advanced RISC Machines, Limited. +- Beaglebone is a trademark of GHI. +- BSD is a trademark of the University of California, Berkeley, USA. +- Cygwin is a trademark of Red Hat, Incorporated. +- Linux is a registered trademark of Linus Torvalds. +- Eagle-100 is a trademark of `Micromint USA, + LLC <%20http://www.micromint.com/>`__. +- EnergyLite is a trademark of STMicroelectronics. +- EFM32 is a trademark of Silicon Laboratories, Inc. +- LPC2148 is a trademark of NXP Semiconductors. +- POSIX is a trademark of the Institute of Electrical and Electronic + Engineers, Inc. +- RISC-V is a registration pending trade mark of the RISC-V Foundation. +- Sitara is a trademark of Texas Instruments Incorporated. +- TI is a tradename of Texas Instruments Incorporated. +- Tiva is a trademark of Texas Instruments Incorporated. +- UNIX is a registered trademark of The Open Group. +- VxWorks is a registered trademark of Wind River Systems, + Incorporated. +- ZDS, ZNEO, Z16F, Z80, and Zilog are a registered trademark of Zilog, + Inc. + +NOTE: NuttX is *not* licensed to use the POSIX trademark. NuttX uses the +POSIX standard as a development guideline only. diff --git a/doc/make.bat b/doc/make.bat new file mode 100644 index 00000000000..2119f51099b --- /dev/null +++ b/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/quickstart/config_build.rst b/doc/quickstart/config_build.rst new file mode 100644 index 00000000000..6b5331d2a8d --- /dev/null +++ b/doc/quickstart/config_build.rst @@ -0,0 +1,131 @@ +======================== +Configuring and Building +======================== + +Configuring NuttX +================= + +**Manual Configuration**. Configuring NuttX requires only copying +the `board-specific configuration files <#boardconfigsubdirs>`__ +into the top level directory which appears in the make files as +the make variable, ``$(TOPDIR)``. This could be done manually as +follows: + +- Copy + ``boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/configs/[``\ **\ ``/]Make.defs`` + to ``$(TOPDIR)/Make.defs`` (see NOTE below), +- Copy + ``boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/configs/[``\ **\ ``/]defconfig`` + to ``$(TOPDIR)/.config`` + +Where ** is the name of one of the sub-directories of +the NuttX ```boards/`` <#DirStructConfigs>`__ directory. This +sub-directory name corresponds to one of the supported boards +identified `above <#supportedboards>`__. is the +optional, specific configuration directory for the board. And + is the location of the optional application directory. + +NOTE: Recall that the ``Make.defs`` file may reside in either the +``boards/``\ **\ ``/``\ **\ ``/``\ **/``configs/[``\ ** +directory or in the +``boards/``\ **\ ``/``\ **\ ``/``\ **/``scripts``. + +**Automated Configuration**. There is a script that automates +these steps. The following steps will accomplish the same +configuration: + +There is an alternative Windows batch file, ``configure.bat``, +that can be used instead of ``configure.sh`` in the windows native +environment like: + +And, to make sure that other platforms are supported, there is +also a C program at ``tools/configure.c`` that can be compiled to +establish the board configuration on all platforms. + + NOTE (2019-08-6): As of this writing, changes to the boards/ + directly have made ``configure.bat`` unusable. For the native + Windows environment, ``configure.c`` is recommended until that + batch file can be repaired. + +See ``tools/README.txt`` for more information about these scripts. +Or use the -h option with ``configure.sh>`` + +If your application directory is not in the standard location +(``../apps`` or ``../apps-``), then you should also +specify the location of the application directory on the command +line like: + +**Version Files**. The NuttX build expects to find a version file +located in the top-level NuttX build directory. That version file +is called ``.version``. The correct version file is installed in +each versioned NuttX released. However, if you are working from an +GIT snapshot, then there will be no version file. If there is no +version file, the top-level ``Makefile`` will create a dummy +``.version`` file on the first make. This dummy version file will +contain all zeroes for version information. If that is not what +you want, they you should run the ``version.sh`` script to create +a better ``.version`` file. + +You can get help information from the ``version.sh`` script using +the ``-h`` option. For example: + +As an example, the following command will generate a version file +for version 6.1 using the current GIT revision number: + +The ``.version`` file is also used during the build process to +create a C header file at ``include/nuttx/version.h`` that +contains the same version information. That version file may be +used by your C applications for, as an example, reporting version +information. + +**Additional Configuration Steps**. The remainder of configuration +steps will be performed by +```$(TOPDIR)/Makefile`` <#topmakefile>`__ the first time the +system is built as described below. + +Building NuttX +============== + +**Building NuttX**. Once NuttX has been configured as described +`above <#configuringnuttx>`__, it may be built as follows: + +The ``$(TOPDIR)`` directory holds: + +- The top level ```Makefile`` <#topmakefile>`__ that controls the + NuttX build. + +That directory also holds: + +- The makefile fragment ```.config`` <#boardconfigsubdirs>`__ + that describes the current configuration, and +- The makefile fragment ```Make.defs`` <#boardconfigsubdirs>`__ + that provides customized build targets. + +**Environment Variables**. The specific environmental definitions +are unique for each board but should include, as a minimum, +updates to the ``PATH`` variable to include the full path to the +architecture-specific toolchain identified in +```Make.defs`` <#boardconfigsubdirs>`__. + +**First Time Make.** Additional configuration actions will be +taken the first time that system is built. These additional steps +include: + +- Auto-generating the file ``include/nuttx/config.h`` using the + ``$(TOPDIR)/.config`` file. +- Auto-generating the file ``$(TOPDIR)/.version`` with version + 0.0 if one does not exist. +- Auto-generating the file ``include/nuttx/version.h`` using the + ``$(TOPDIR)/.version`` file. +- Creating a link to + ``$(TOPDIR)/arch/``\ **\ ``/include`` at + ``$(TOPDIR)/include/arch``. +- Creating a link to + ``$(TOPDIR)/boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/include`` + at ``$(TOPDIR)/include/arch/board``. +- Creating a link to + ``$(TOPDIR)/boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/src`` + at ``$(TOPDIR)/arch/``\ **\ ``/src/board`` +- Creating a link to ``${APPDIR}/include`` at + ``$(TOPDIR)/include/apps`` +- Creating make dependencies. diff --git a/doc/quickstart/index.rst b/doc/quickstart/index.rst new file mode 100644 index 00000000000..13a8e3aee54 --- /dev/null +++ b/doc/quickstart/index.rst @@ -0,0 +1,15 @@ +========== +Quickstart +========== + +.. note:: + This should be a brief introduction to how NuttX works and how to get it running. A widely used board could be targeted to create a brief demonstration on how to clone, configure, build, flash and run NuttX. + For now, I've included the parts of the old porting guide which seemed more relevant for this section, but should be revised and made + (new) user friendly. + +.. toctree:: + :maxdepth: 1 + + organization.rst + config_build.rst + diff --git a/doc/quickstart/organization.rst b/doc/quickstart/organization.rst new file mode 100644 index 00000000000..03af58cd6b5 --- /dev/null +++ b/doc/quickstart/organization.rst @@ -0,0 +1,501 @@ +=================== +Directory Structure +=================== + +**Directory Structure**. The general directory layout for NuttX is +very similar to the directory structure of the Linux kernel -- at +least at the most superficial layers. At the top level is the main +makefile and a series of sub-directories identified below and +discussed in the following paragraphs: + +**Configuration Files**. The NuttX configuration consists of logic +in processor architecture directories, *chip/SoC* directories, and +board configuration directories. The complete configuration is +specified by several settings in the NuttX configuration file. + +- *Processor architecture specific files*. These are the files + contained in the ``arch/``\ **\ ``/`` directory and + are discussed in a paragraph + `below <#archdirectorystructure>`__. As an example, all ARM + processor architectures are provided under the ``arch/arm/`` + directory which is selected with the ``CONFIG_ARCH="arm"`` + configuration option. + + Variants of the processor architecture may be provided in + sub-directories of the Extending this example, the ARMv7-M ARM + family is supported by logic in ``arch/arm/include/armv7-m`` + and ``arch/arm/src/armv7-m`` directories which are selected by + the ``CONFIG_ARCH_CORTEXM3=y``, ``CONFIG_ARCH_CORTEXM4=y``, or + ``CONFIG_ARCH_CORTEXM7=y`` configuration options + +- *Chip/SoC specific files*. Each processor architecture is + embedded in a *System-on-a-Chip* (SoC) architecture. The full + SoC architecture includes the processor architecture plus + chip-specific interrupt logic, clocking logic, general purpose + I/O (GPIO) logic, and specialized, internal peripherals (such + as UARTs, USB, etc.). + + These chip-specific files are contained within chip-specific + sub-directories also under the ``arch/``\ **\ ``/`` + directory and are selected via the ``CONFIG_ARCH_CHIP`` + selection. + + As an example, the STMicro STM32 SoC architecture is based on + the ARMv7-M processor and is supported by logic in the + ``arch/arm/include/stm32`` and ``arch/arm/src/stm32`` + directories which are selected with the + ``CONFIG_ARCH_CHIP="stm32"`` configuration setting. + +- *Board specific configurations*. In order to be usable, the + chip must be contained in a board environment. The board + configuration defines additional properties of the board + including such things as peripheral LEDs, external peripherals + (such as networks, USB, etc.). + + These board-specific configuration files can be found in the + ``boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/`` + sub-directories and are discussed in a paragraph + `below <#boardsdirectorystructure>`__. + + The directory ``boards/arm/stm32/stm32f4disovery/``, as an + example, holds board-specific logic for the STM32F4 Discovery + board and is selected via the + ``CONFIG_ARCH_BOARD="stm32f4discovery"`` configuration setting. + +Documentation +============= + +General documentation for the NuttX OS resides in this directory. + +``nuttx/arch`` +============== + +Subdirectory Structure +---------------------- + +This directory contains several sub-directories, each containing +architecture-specific logic. The task of porting NuttX to a new +processor consists of add a new subdirectory under ``arch/`` +containing logic specific to the new architecture. The complete +board port in is defined by the architecture-specific code in this +directory (plus the board-specific configurations in the +``config/`` subdirectory). Each architecture must provide a +subdirectory, ** under ``arch/`` with the following +characteristics: + +Summary of Files +---------------- + +- ``include/``\ **\ ``/`` This sub-directory contains + chip-specific header files. +- ``include/arch.h``: This is a hook for any architecture + specific definitions that may be needed by the system. It is + included by ``include/nuttx/arch.h``. +- ``include/types.h``: This provides + architecture/toolchain-specific definitions for standard types. + This file should ``typedef``: + + and if the architecture supports 24- or 64-bit integers + + NOTE that these type names have a leading underscore character. + This file will be included(indirectly) by include/stdint.h and + typedef'ed to the final name without the underscore character. + This roundabout way of doings things allows the stdint.h to be + removed from the include/ directory in the event that the user + prefers to use the definitions provided by their toolchain + header files + + And finally + + Must be defined to the be the size required to hold the + interrupt enable/disable state. + + This file will be included by include/sys/types.h and be made + available to all files. + +- ``include/irq.h``: This file needs to define some architecture + specific functions (usually inline if the compiler supports + inlining) and some structures. These include: + + - ``struct xcptcontext``: This structures represents the saved + context of a thread. + - ``irqstate_t up_irq_save(void)``: Used to disable all + interrupts. In the case of multi-CPU platforms, this + function disables interrupts on CPUs. + - ``void up_irq_restore(irqstate_t flags)``: Used to restore + interrupt enables to the same state as before + ``up_irq_save()`` was called. + + This file must also define ``NR_IRQS``, the total number of + IRQs supported by the board. + +- ``include/syscall.h``: This file needs to define some + architecture specific functions (usually inline if the compiler + supports inlining) to support software interrupts or + *syscall*\ s that can be used all from user-mode applications + into kernel-mode NuttX functions. This directory must always be + provided to prevent compilation errors. However, it need only + contain valid function declarations if the architecture + supports the ``CONFIG_BUILD_PROTECTED`` or + ``CONFIG_BUILD_KERNEL``\ configurations. + + - ``uintptr_t sys_call0(unsigned int nbr)``: ``nbr`` is one of + the system call numbers that can be found in + ``include/sys/syscall.h``. This function will perform a + system call with no (additional) parameters. + - ``uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with one (additional) parameter. + - ``uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with two (additional) parameters. + - ``uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with three (additional) parameters. + - ``uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with four (additional) parameters. + - ``uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with five (additional) parameters. + - ``uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, uintptr_t parm6)``: + ``nbr`` is one of the system call numbers that can be found + in ``include/sys/syscall.h``. This function will perform a + system call with six (additional) parameters. + + This file must also define ``NR_IRQS``, the total number of + IRQs supported by the board. + +- ``src/``\ **\ ``/`` This sub-directory contains + chip-specific source files. +- ``src/Makefile``: This makefile will be executed to build the + targets ``src/libup.a`` and ``src/up_head.o``. The + ``up_head.o`` file holds the entry point into the system + (power-on reset entry point, for example). It will be used in + the final link with ``libup.a`` and other system archives to + generate the final executable. +- *(architecture-specific source files)*. The file + ``include/nuttx/arch.h`` identifies all of the APIs that must + be provided by the architecture specific logic. (It also + includes ``arch/``\ **\ ``/arch.h`` as described + above). + +Supported Architectures +----------------------- + +**Architecture- and Chip-Specific Directories**. All processor +architecture-specific directories are maintained in +sub-directories of the ``arch/`` directory. Different chips or +SoC's may implement the same processor core. Chip-specific logic +can be found in sub-directories under the architecture directory. +Current architecture/chip directories are summarized below: + +- ``arch/sim``: A user-mode port of NuttX to the x86 Linux or + Cygwin platform is available. The purpose of this port is + primarily to support OS feature development. This port does not + support interrupts or a real timer (and hence no round robin + scheduler) Otherwise, it is complete. +- ``arch/arm``: This directory holds common ARM architectures. +- ``arch/avr``: This directory holds common AVR and AVR32 + architectures. +- ``arch/mips``: This directory holds common MIPS architectures. + This include PIC32MX and PIC32MZ. +- ``arch/misoc``: This directory supports the Misoc LM3 + architecture. +- ``arch/or1K``: This directory supports the OpenRISC mor1kx + architecture. +- ``arch/renesas``: This directory is the home for various + Renesas architectures, currently only the M16C and vererable + SuperH-1 architectures. +- ``arch/risc-v``: This directory supports the RISC-V NR5 + architecture. +- ``arch/xtensa``: This directory supports the Xtensa LX6 + architecture as used by the ESP32. +- ``arch/z16f``: Zilog z16f Microcontroller. +- ``arch/z80``: This directory holds 8-bit ZiLOG architectures. + At present, this includes the Zilog z80, ez80Acclaim! and + z8Encore! Microcontrollers. + +nuttx/binfmt +============ + +The ``binfmt/`` subdirectory contains logic for loading binaries +in the file system into memory in a form that can be used to +execute them. + +``nuttx/audio`` +=============== + +The ``audio/`` subdirectory contains the NuttX audio sub-system. + +``nuttx/boards`` +================ + +The ``boards/`` subdirectory contains custom logic and board +configuration data for each board. These board-specific +configurations plus the architecture-specific configurations in +the ``arch/`` subdirectory complete define a customized port of +NuttX. + +Subdirectory Structure +---------------------- + +The ``boards/`` directory contains board specific configuration +files. Each board must provide a sub-directory under +``boards/``\ **\ ``/``>\ **\ ``/`` with the +following characteristics: + +Summary of Files +---------------- + +**Board Specific Logic** + +- ``include/``: This directory contains board specific header + files. This directory will be linked as ``include/arch/board`` + at configuration time and can be included via + ``#include ``. These header file can only + be included by files in ``arch/``\ **\ ``/include/`` + and ``arch/``\ **\ ``/src/``. +- ``src/``: This directory contains board specific drivers. This + directory will be linked as + **\ ``/arch/``\ **\ ``/src/board`` at + configuration time and will be integrated into the build + system. +- ``src/Makefile``: This makefile will be invoked to build the + board specific drivers. It must support the following targets: + ``libext$(LIBEXT)``, ``clean``, and ``distclean``. + +**Board Specific Configuration Sub-Directories** + +The +``boards/``\ **\ ``/``\ **\ ``/``\ **\ ``/configs`` +sub-directory holds all of the files that are necessary to +configure NuttX for the particular board. A board may have various +different configurations using the common source files. Each board +configuration is described by two files: ``Make.defs`` and +``defconfig``. Typically, each set of configuration files is +retained in a separate configuration sub-directory +(**, **, .. in the above diagram). + +NOTE: That the ``Make.defs`` file may reside in one of two +locations: There may be a unique Make.defs file for each +configuration in the configuration directory *OR* if that file is +absent, there may be a common board ``Make.defs`` file in the +``/scripts`` directory. The ``Make.defs`` file in the +configuration takes precedence if it is present. + +The procedure for configuring NuttX is described +`below <#configuringnuttx>`__, This paragraph will describe the +contents of these configuration files. + +- ``Make.defs``: This makefile fragment provides architecture and + tool-specific build options. It will be included by all other + makefiles in the build (once it is installed). This make + fragment should define: + + - Tools: ``CC``, ``LD``, ``AR``, ``NM``, ``OBJCOPY``, + ``OBJDUMP`` + - Tool options: ``CFLAGS``, ``LDFLAGS`` + + When this makefile fragment runs, it will be passed ``TOPDIR`` + which is the path to the root directory of the build. This + makefile fragment should include: + + - ``$(TOPDIR)/.config`` : Nuttx configuration + - ``$(TOPDIR)/tools/Config.mk`` : Common definitions + + Definitions in the ``Make.defs`` file probably depend on some + of the settings in the .\ ``config`` file. For example, the + ``CFLAGS`` will most likely be different if + ``CONFIG_DEBUG_FEATURES=y``. + + The included ``tools/Config.mk`` file contains additional + definitions that may be overridden in the architecture-specific + Make.defs file as necessary: + + - ``COMPILE``, ``ASSEMBLE``, ``ARCHIVE``, ``CLEAN``, and + ``MKDEP`` macros + +- ``defconfig``: This is a configuration file similar to the + Linux configuration file. In contains variable/value pairs + like: + + - ``CONFIG_VARIABLE``\ =value + + This configuration file will be used at build time: + + #. As a makefile fragment included in other makefiles, and + #. to generate ``include/nuttx/config.h`` which is included by + most C files in the system. + +Supported Boards +---------------- + +All of the specific boards supported by NuttX are identified in +the +`README.txt `__ +file. + +Adding a New Board Configuration +-------------------------------- + +Okay, so you have created a new board configuration directory. +Now, how do you hook this board into the configuration system so +that you can select with ``make menuconfig``? + +You will need modify the file ``boards/Kconfig``. Let's look at +the STM32F4-Discovery configuration in the ``Kconfig`` file and +see how we would add a new board directory to the configuration. +For this configuration let's say that you new board resides in the +directory ``boards/myarch/mychip/myboard``; It uses an MCU +selected with ``CONFIG_ARCH_CHIP_MYMCU``; and you want the board +to be selected with ``CONFIG_ARCH_BOARD_MYBOARD``. Then here is +how you can clone the STM32F4-Discovery configuration in +``boards/Kconfig`` to support your new board configuration. + +In ``boards/Kconfig`` for the stm32f4-discovery, you will see a +configuration definition like this: + +The above selects the STM32F4-Discovery board. The ``select`` +lines say that the board has both LEDs and buttons and that the +board can generate interrupts from the button presses. You can +just copy the above configuration definition to a new location +(notice that they the configurations are in alphabetical order). +Then you should edit the configuration to support your board. The +final configuration definition might look something like: + +Later in the ``boards/Kconfig`` file, you will see a long, long +string configuration with lots of defaults like this: + +This logic will assign string value to a configuration variable +called ``CONFIG_ARCH_BOARD`` that will name the directory where +the board-specific files reside. In our case, these files reside +in ``boards/myarch/mychip/myboard`` and we add the following to +the long list of defaults (again in alphabetical order): + +Now the build system knows where to find your board configuration! + +And finally, add something like this near the bottom of +``boards/myarch/mychip/myboard``: + +This includes additional, board-specific configuration variable +definitions in ``boards/myarch/mychip/myboard/Kconfig``. + +``nuttx/crypto`` +================ + +This sub-directory holds the NuttX cryptographic sub-system. + +``nuttx/drivers`` +================= + +This directory holds architecture-independent device drivers. + +``nuttx/fs`` +============ + +This directory contains the NuttX file system. This file system is +described `below <#NxFileSystem>`__. + +``nuttx/graphics`` +================== + +This directory contains files for graphics/video support under +NuttX. + +``nuttx/include`` +================= + +This directory holds NuttX header files. Standard header files +file retained in can be included in the *normal* fashion: + +``nuttx`` +========= + +This is a (almost) empty directory that has a holding place for +generated static libraries. The NuttX build system generates a +collection of such static libraries in this directory during the +compile phase. These libraries are then in a known place for the +final link phase where they are accessed to generated the final +binaries. + +``nuttx/libs/libc`` +=================== + +This directory holds a collection of standard libc-like functions +with custom interfaces into NuttX. + +Normally the logic in this file builds to a single library +(``libc.a``). However, if NuttX is built as a separately compiled +kernel (with ``CONFIG_BUILD_PROTECTED=y`` or +``CONFIG_BUILD_KERNEL=y``), then the contents of this directory +are built as two libraries: One for use by user programs +(``libc.a``) and one for use only within the space +(``libkc.a``). + +These user/kernel space libraries (along with the sycalls of +```nuttx/syscall`` <#DirStructSyscall>`__) are needed to support +the two differing protection domains. + +Directory structure: + +``nuttx/libs/libxx`` +==================== + +This directory holds a tiny, minimal standard std C++ that can be +used to build some, simple C++ applications in NuttX. + +``nuttx/mm`` +============ + +This is the NuttX memory manager. + +``nuttx/net`` +============= + +This directory contains the implementation of the NuttX networking +layer including internal socket APIs. + +``nuttx/sched`` +=============== + +The files forming core of the NuttX RTOS reside here. + +``nuttx/syscall`` +================= + +If NuttX is built as a separately compiled kernel (with +``CONFIG_BUILD_PROTECTED=y`` or ``CONFIG_BUILD_KERNEL=y``), then +the contents of this directory are built. This directory holds a +syscall interface that can be used for communication between +user-mode applications and the kernel-mode RTOS. + +``nuttx/tools`` +=============== + +This directory holds a collection of tools and scripts to simplify +configuring, building and maintaining NuttX. + +Refer to the README file in the ``tools`` directory for more +information about the individual files. Some of these tools are +discussed below as well in the discussion of `configuring and +building <#configandbuild>`__ NuttX. + +``nuttx/wireless`` +================== + +This directory holds support for hardware-independent wireless +support. + +``nuttx/Makefile`` +================== + +The top-level ``Makefile`` in the ``$(TOPDIR)`` directory contains +all of the top-level control logic to build NuttX. Use of this +``Makefile`` to build NuttX is described +`below <#buildingnuttx>`__. diff --git a/doc/reference/index.rst b/doc/reference/index.rst new file mode 100644 index 00000000000..646d4611404 --- /dev/null +++ b/doc/reference/index.rst @@ -0,0 +1,14 @@ +============= +API Reference +============= + +.. note:: + TODO: add brief intro, distinguishing the arch and user facing APIs. Otherwise there could simply be + a top-level document for each API + +.. toctree:: + :caption: Contents: + :maxdepth: 1 + + user/index.rst + os/index.rst diff --git a/doc/reference/os/addrenv.rst b/doc/reference/os/addrenv.rst new file mode 100644 index 00000000000..112cde0b5be --- /dev/null +++ b/doc/reference/os/addrenv.rst @@ -0,0 +1,305 @@ +==================== +Address Environments +==================== + +CPUs that support memory management units (MMUs) may provide +*address environments* within which tasks and their child threads +execute. The configuration indicates the CPUs ability to support +address environments by setting the configuration variable +``CONFIG_ARCH_HAVE_ADDRENV=y``. That will enable the selection of +the actual address environment support which is indicated by the +selection of the configuration variable ``CONFIG_ARCH_ADDRENV=y``. +These address environments are created only when tasks are created +via ``exec()`` or ``exec_module()`` (see +``include/nuttx/binfmt/binfmt.h``). + +When ``CONFIG_ARCH_ADDRENV=y`` is set in the board configuration, +the CPU-specific logic must provide a set of interfaces as defined +in the header file ``include/nuttx/arch.h``. These interfaces are +listed below and described in detail in the following paragraphs. + +The CPU-specific logic must provide two categories in interfaces: + +#. **Binary Loader Support**. These are low-level interfaces used + in ``binfmt/`` to instantiate tasks with address environments. + These interfaces all operate on type ``group_addrenv_t`` which + is an abstract representation of a task group's address + environment and the type must be defined in\ ``arch/arch.h`` if + ``CONFIG_ARCH_ADDRENV`` is defined. These low-level interfaces + include: + + - :c:func:`up_addrenv_create()`: Create an address environment. + - :c:func:`up_addrenv_destroy()`: Destroy an address environment. + - :c:func:`up_addrenv_vtext()`: Returns the virtual base address of the ``.text`` address environment. + - :c:func:`up_addrenv_vdata()`: Returns the virtual base address of the ``.bss``/``.data`` address environment. + - :c:func:`up_addrenv_heapsize()`: Return the initial heap size. + - :c:func:`up_addrenv_select()`: Instantiate an address environment. + - :c:func:`up_addrenv_restore()`: Restore an address environment. + - :c:func:`up_addrenv_clone()`: Copy an address environment from one location to another. + +#. **Tasking Support**. Other interfaces must be provided to + support higher-level interfaces used by the NuttX tasking + logic. These interfaces are used by the functions in ``sched/`` + and all operate on the task group which as been assigned an + address environment by ``up_addrenv_clone()``. + + - :c:func:`up_addrenv_attach()`: Clone the group address environment assigned to a new + thread. This operation is done when a pthread is created + that share's the same address environment. + - :c:func:`up_addrenv_detach()`: Release the thread's reference to a group address + environment when a task/thread exits. + +#. **Dynamic Stack Support**. ``CONFIG_ARCH_STACK_DYNAMIC=y`` + indicates that the user process stack resides in its own + address space. This option is also *required* if + ``CONFIG_BUILD_KERNEL`` and ``CONFIG_LIBC_EXECFUNCS`` are + selected. Why? Because the caller's stack must be preserved in + its own address space when we instantiate the environment of + the new process in order to initialize it. + + **NOTE:** The naming of the ``CONFIG_ARCH_STACK_DYNAMIC`` + selection implies that dynamic stack allocation is supported. + Certainly this option must be set if dynamic stack allocation + is supported by a platform. But the more general meaning of + this configuration environment is simply that the stack has its + own address space. + + If ``CONFIG_ARCH_STACK_DYNAMIC=y`` is selected then the + platform specific code must export these additional interfaces: + + - :c:func:`up_addrenv_ustackalloc()`: Create a stack address environment + - :c:func:`up_addrenv_ustackfree()`: Destroy a stack address environment. + - :c:func:`up_addrenv_vustack()`: Returns the virtual base address of the stack + - :c:func:`up_addrenv_ustackselect()`: Instantiate a stack address environment + +#. If ``CONFIG_ARCH_KERNEL_STACK`` is selected, then each user + process will have two stacks: (1) a large (and possibly + dynamic) user stack and (2) a smaller kernel stack. However, + this option is *required* if both ``CONFIG_BUILD_KERNEL`` and + ``CONFIG_LIBC_EXECFUNCS`` are selected. Why? Because when we + instantiate and initialize the address environment of the new + user process, we will temporarily lose the address environment + of the old user process, including its stack contents. The + kernel C logic will crash immediately with no valid stack in + place. + + If ``CONFIG_ARCH_KERNEL_STACK=y`` is selected then the platform + specific code must export these additional interfaces: + + - :c:func:`up_addrenv_kstackalloc`: Allocate the process kernel stack. + +.. c:function:: int up_addrenv_create(size_t textsize, size_t datasize, \ + size_t heapsize, FAR group_addrenv_t *addrenv); + + This function is called when a new task is created in order to + instantiate an address environment for the new task group. + up_addrenv_create() is essentially the allocator of the physical memory for the new task. + + :param textsize: The size (in bytes) of the ``.text`` address + environment needed by the task. This region may be read/execute + only. + :param datasize: The size (in bytes) of the ``.bss/.data`` address + environment needed by the task. This region may be read/write + only. + :param heapsize: The initial size (in bytes) of the heap address + environment needed by the task. This region may be read/write + only. + :param addrenv: The location to return the representation of the + task address environment. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_destroy(group_addrenv_t *addrenv) + + This function is called when a final thread leaves the task + group and the task group is destroyed. This function then destroys + the defunct address environment, releasing the underlying physical + memory allocated by up_addrenv_create(). + + :param addrenv: The representation of the task address environment + previously returned by ``up_addrenv_create()``. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_vtext(FAR group_addrenv_t addrenv, FAR void **vtext) + + Return the virtual .text address associated with the newly create + address environment. This function is used by the binary loaders + in order get an address that can be used to initialize the new task. + + :param addrenv: The representation of the task address environment + previously returned by ``up_addrenv_create()``. + :param vtext: The location to return the virtual address. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_vdata(FAR group_addrenv_t *addrenv, size_t textsize, FAR void **vdata) + + Return the virtual .text address associated with the newly create + address environment. This function is used by the binary loaders + in order get an address that can be used to initialize the new task. + + :param addrenv: The representation of the task address environment + previously returned by ``up_addrenv_create()``. + :param textsize: For some implementations, the text and data will + be saved in the same memory region (read/write/execute) and, in + this case, the virtual address of the data just lies at this + offset into the common region. + :param vdata: The location to return the virtual address. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: ssize_t up_addrenv_heapsize(FAR const group_addrenv_t *addrenv) + + Return the initial heap allocation size. That is the amount of + memory allocated by up_addrenv_create() when the heap memory + region was first created. This may or may not differ from the + heapsize parameter that was passed to up_addrenv_create(). + + :param addrenv: The representation of the task address environment + previously returned by ``up_addrenv_create()``. + + :return: The initial heap size allocated is returned on success; + a negated errno value on failure. + +.. c:function:: int up_addrenv_select(group_addrenv_t *addrenv, save_addrenv_t *oldenv) + + After an address environment has been established for a task + (via up_addrenv_create()), this function may be called to instantiate + that address environment in the virtual address space. This might be + necessary, for example, to load the code for the task from a file or + to access address environment private data. + + :param addrenv: The representation of the task address environment + previously returned by ``up_addrenv_create()``. + :param oldenv: The address environment that was in place before + ``up_addrenv_select()`` was called. This may be used with + ``up_addrenv_restore()`` to restore the original address + environment that was in place before ``up_addrenv_select()`` + was called. Note that this may be a task agnostic, + platform-specific representation that may or may not be + different from ``group_addrenv_t``. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_restore(save_addrenv_t oldenv) + + After an address environment has been temporarily instantiated + by up_addrenv_select, this function may be called to restore + the original address environment. + + :param oldenv: The platform-specific representation of the address + environment previously returned by ``up_addrenv_select()``. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_clone(FAR const task_group_s *src, FAR struct task_group_s *dest) + + Duplicate an address environment. This does not copy the underlying + memory, only the representation that can be used to instantiate + that memory as an address environment. + + :param src: The address environment to be copied. + :param dest: The location to receive the copied address + environment. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_attach(FAR struct task_group_s *group, FAR struct tcb_s *tcb) + + This function is called from the core scheduler logic when a + thread is created that needs to share the address environment + of its task group. In this case, the group's address environment + may need to be "cloned" for the child thread. + + NOTE: In most platforms, nothing will need to be done in this case. + Simply being a member of the group that has the address environment + may be sufficient. + + :param group: The task group to which the new thread belongs. + :param ctcb: The TCB of the thread needing the address + environment. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_detach(FAR struct task_group_s *group, FAR struct task_group_s *tcb) + + This function is called when a task or thread exits in order + to release its reference to an address environment. The address + environment, however, should persist until up_addrenv_destroy() + is called when the task group is itself destroyed. Any resources + unique to this thread may be destroyed now. + + :param group: The group to which the thread belonged. + :param tcb: The TCB of the task or thread whose the address + environment will be released. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_ustackalloc(FAR struct tcb_s *tcb, size_t stacksize) + + This function is called when a new thread is created in order + to instantiate an address environment for the new thread's stack. + up_addrenv_ustackalloc() is essentially the allocator of the + physical memory for the new task's stack. + + :param tcb: The TCB of the thread that requires the stack address + environment. + :param stacksize: The size (in bytes) of the initial stack address + environment needed by the task. This region may be read/write + only. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_ustackfree(FAR struct tcb_s *tcb) + + This function is called when any thread exits. This function then + destroys the defunct address environment for the thread's stack, + releasing the underlying physical memory. + + :param tcb: The TCB of the thread that no longer requires the + stack address environment. + + :return: Zero (OK) on success; a negated errno value on failure + +.. c:function:: int up_addrenv_vustack(FAR const struct tcb_s *tcb, FAR void **vstack) + + Return the virtual address associated with the newly create stack address environment. + + :param tcb: The TCB of the thread with the stack address environment of interest. + :param vstack: The location to return the stack virtual base address. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_ustackselect(FAR const struct tcb_s *tcb) + + After an address environment has been established for a task's + stack (via up_addrenv_ustackalloc(). This function may be called to + instantiate that address environment in the virtual address space. + This is a necessary step before each context switch to the newly + created thread (including the initial thread startup). + + :param tcb: The TCB of the thread with the stack address + environment to be instantiated. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_kstackalloc(FAR struct tcb_s *tcb) + + This function is called when a new thread is created to allocate the + new thread's kernel stack. This function may be called for certain + terminating threads which have no kernel stack. It must be + tolerant of that case. + + :param tcb: The TCB of the thread that requires the kernel stack. + + :return: Zero (OK) on success; a negated errno value on failure. + +.. c:function:: int up_addrenv_kstackfree(FAR struct tcb_s *tcb); + + This function is called when any thread exits. This function frees the kernel stack. + + :param tcb: The TCB of the thread that no longer requires the + kernel stack. + + :return: Zero (OK) on success; a negated errno value on failure. diff --git a/doc/reference/os/app_vs_os.rst b/doc/reference/os/app_vs_os.rst new file mode 100644 index 00000000000..82ce17204af --- /dev/null +++ b/doc/reference/os/app_vs_os.rst @@ -0,0 +1,103 @@ +========================================= +Application OS vs. Internal OS Interfaces +========================================= + +NuttX provides a standard, portable OS interface for use by +applications. This standard interface is controlled by the +specifications proved at `OpenGroup.org `__. +These application interfaces, in general, should not be used +directly by logic executing within the OS. The reason for this is +that there are certain properties of the standard application +interfaces that make them unsuitable for use within the OS These +properties include: + +#. **Use of the per-thread** ``errno`` **variable**: Handling of + return values, particularly, in the case of returned error + indications. Most legacy POSIX OS interface return information + via a *per-thread* ``errno``. There must be no alteration of + the ``errno`` value that must be stable from the point of view + of the application. So, as a general rule, internal OS logic + must never modify the ``errno`` and particularly not by the + inappropriate use of application OS interfaces within OS + itself. + + Within the OS, functions do not return error information via + the ``errno`` variable. Instead, the majority of internal OS + function return error information as an integer value: Returned + values greater than or equal to zero are success values; + returned values less than zero indicate failures. Failures are + reported by returning a negated ``errno`` value from + ``include/errno.h``, + +#. **Cancellation Points**: Many of the application OS interfaces + are *cancellation points*, i.e., when the task is operating in + *deferred cancellation* state, it cannot be deleted or + cancelled until it calls an application OS interface that is a + cancellation point. + + The POSIX specification is very specific about this, specific + both in identifying which application OS interfaces are + cancellation points and specific in the fact that it is + prohibited for any OS operation other than those listed in the + specification to generate cancellation points. If internal OS + logic were to re-use application OS interfaces directly then it + could very easily violate this POSIX requirement by incorrectly + generating cancellation points on inappropriate OS operations + and could result in very difficult to analyze application + failures. + +#. **Use of per-task Resources**: Many resources are only valid in + the task group context in which a thread operates. Above we + mentioned one: ``errno`` is only valid for the thread that is + currently executing. So, for example, the ``errno`` at the time + of a call is a completely different variable than, say, the + ``errno`` while running in a work queue task. + + File descriptors are an even better example: An open file on + file descriptor 5 on task A is *not* the same open file as + might be used on file descriptor 5 on task B. + + As a result, internal OS logic may not use application OS + interfaces that use file descriptors or any other *per-task* + resource. + +Within NuttX, this is handled by supporting equivalent internal OS +interfaces that do not break the above rules. These internal +interfaces are intended for use *only* within the OS and should +not be used by application logic. Some examples include: + +- ``nxsem_wait()``: functionally + equivalent to the standard application interface + ``sem_wait()``. However, ``nxsem_wait()`` will not modify the + errno value and will not cause a cancellation point. (see + ``include/nuttx/semaphore.h`` for other internal OS interfaces + for semaphores). + +- ``nxsig_waitinfo()``: functionally + equivalent to the standard application interface + ``sigwaitinfo()``. However, ``nxsig_waitinfo()`` will not + modify the errno value and will not cause a cancellation point + (see ``include/nuttx/signal.h`` for other internal OS + interfaces for signals). + +- ``nxmq_send()``: functionally equivalent + to the standard application interface ``mq_send()``. However, + ``nxmq_send()`` will not modify the errno value and will not + cause a cancellation point (see ``include/nuttx/mqueue.h`` for + other internal OS interfaces for POSIX message queues). + +- ``file_read()``: functionally equivalent + to the standard application interface ``read()``. However, + ``file_read()`` will not modify the errno value, will not cause + a cancellation point, and uses a special internal data + structure in place of the file descriptor (see + ``include/nuttx/fs/fs.h`` for other internal OS interfaces for + VFS functions). + +- ``psock_recvfrom()``: functionally + equivalent to the standard application interface + ``recvfrom()``. However, ``psock_recvfrom()`` will not modify + the errno value, will not cause a cancellation point, and uses + a special internal data structure in place of the socket + descriptor (see ``include/nuttx/net/net.h`` for other internal + OS interfaces for sockets). diff --git a/doc/reference/os/arch.rst b/doc/reference/os/arch.rst new file mode 100644 index 00000000000..c9829f3814f --- /dev/null +++ b/doc/reference/os/arch.rst @@ -0,0 +1,329 @@ +===================================================== +APIs Exported by Architecture-Specific Logic to NuttX +===================================================== + +.. c:function:: void up_initialize(void) + + Called once during OS + initialization after the basic OS services have been initialized. + The architecture specific details of initializing the OS will be + handled here. Such things as setting up interrupt service + routines, starting the clock, and registering device + are some of the things that are + different for each processor and hardware platform. + + ``up_initialize()`` is called after the OS initialized but before + the init process has been started and before the libraries have + been initialized. OS services and driver services are available. + +.. c:function:: void up_idle(void) + + The logic that will be executed + when their is no other ready-to-run task. This is processor idle + time and will continue until some interrupt occurs to cause a + context switch from the idle task. + + Processing in this state may be processor-specific. e.g., this is + where power management operations might be performed. + +.. c:function:: void up_initial_state(FAR struct tcb_s *tcb) + + A new thread is being started and a new TCB has + been created. This function is called to initialize the processor + specific portions of the new TCB. + + This function must setup the initial architecture registers and/or + stack so that execution will begin at tcb->start on the next + context switch. + + This function may also need to set up processor registers so that + the new thread executes with the correct privileges. If + ``CONFIG_BUILD_PROTECTED`` or ``CONFIG_BUILD_KERNEL`` have been + selected in the NuttX configuration, then special initialization + may need to be performed depending on the task type specified in + the TCB's flags field: Kernel threads will require kernel-mode + privileges; User tasks and pthreads should have only user-mode + privileges. If neither ``CONFIG_BUILD_PROTECTED`` nor + ``CONFIG_BUILD_KERNEL`` have been selected, then all threads + should have kernel-mode privileges. + +.. c:function:: STATUS up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) + + Allocate a stack for a new thread and setup up + stack-related information in the TCB. + + The following TCB fields must be initialized: + + - ``adj_stack_size``: Stack size after adjustment for hardware, + processor, etc. This value is retained only for debug purposes. + - ``stack_alloc_ptr``: Pointer to allocated stack + - ``adj_stack_ptr``: Adjusted ``stack_alloc_ptr`` for HW. The + initial value of the stack pointer. + + :param tcb: The TCB of new task. + :param stack_size: The requested stack size. At least this much + must be allocated. + :param ttype: The thread type. This may be one of following + (defined in ``include/nuttx/sched.h``): + + - ``TCB_FLAG_TTYPE_TASK``: Normal user task + - ``TCB_FLAG_TTYPE_PTHREAD``: User pthread + - ``TCB_FLAG_TTYPE_KERNEL``: Kernel thread + + This thread type is normally available in the flags field of + the TCB, however, there are certain contexts where the TCB may + not be fully initialized when up_create_stack is called. + + If ``CONFIG_BUILD_PROTECTED`` or ``CONFIG_BUILD_KERNEL`` are + defined, then this thread type may affect how the stack is + allocated. For example, kernel thread stacks should be + allocated from protected kernel memory. Stacks for user tasks + and threads must come from memory that is accessible to user + code. + +.. c:function:: STATUS up_use_stack(FAR struct tcb_s *tcb, FAR void *stack, size_t stack_size) + + Setup up stack-related information in the TCB + using pre-allocated stack memory. This function is called only + from ``nxtask_init()`` when a task or kernel thread is started + (never for pthreads). + + The following TCB fields must be initialized: + + - ``adj_stack_size``: Stack size after adjustment for hardware, + processor, etc. This value is retained only for debug purposes. + - ``stack_alloc_ptr``: Pointer to allocated stack + - ``adj_stack_ptr``: Adjusted ``stack_alloc_ptr`` for HW. The + initial value of the stack pointer. + + :param tcb: The TCB of new task. + :param stack_size: The allocated stack size. + + NOTE: Unlike ``up_stack_create()`` and ``up_stack_release``, this + function does not require the task type (``ttype``) parameter. The + TCB flags will always be set to provide the task type to + ``up_use_stack()`` if the information needs that information. + +.. c:function:: FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) + + Allocate a stack frame in the TCB's stack to hold + thread-specific data. This function may be called any time after + ``up_create_stack()`` or ``up_use_stack()`` have been called but + before the task has been started. + + Thread data may be kept in the stack (instead of in the TCB) if it + is accessed by the user code directly. This includes such things + as ``argv[]``. The stack memory is guaranteed to be in the same + protection domain as the thread. + + The following TCB fields will be re-initialized: + + - ``adj_stack_size``: Stack size after removal of the stack frame + from the stack. + - ``adj_stack_ptr``: Adjusted initial stack pointer after the + frame has been removed from the stack. This will still be the + initial value of the stack pointer when the task is started. + + :param tcb: The TCB of new task. + :param frame_size: The size of the stack frame to allocate. + + :return: + A pointer to bottom of the allocated stack + frame. NULL will be returned on any failures. The alignment of the + returned value is the same as the alignment of the stack itself + +.. c:function:: void up_release_stack(FAR struct tcb_s *dtcb) + + A task has been stopped. Free all stack related + resources retained int the defunct TCB. + + :param dtcb: The TCB containing information about the stack to be + released. + + :param ttype: The thread type. This may be one of following + (defined in ``include/nuttx/sched.h``): + + - ``TCB_FLAG_TTYPE_TASK``: Normal user task + - ``TCB_FLAG_TTYPE_PTHREAD``: User pthread + - ``TCB_FLAG_TTYPE_KERNEL``: Kernel thread + + This thread type is normally available in the flags field of + the TCB, however, there are certain error recovery contexts + where the TCB may not be fully initialized when + up_release_stack is called. + + If ``CONFIG_BUILD_PROTECTED`` or ``CONFIG_BUILD_KERNEL`` are + defined, then this thread type may affect how the stack is + freed. For example, kernel thread stacks may have been + allocated from protected kernel memory. Stacks for user tasks + and threads must have come from memory that is accessible to + user + +.. c:function:: void up_unblock_task(FAR struct tcb_s *tcb) + +A task is currently in an inactive task list but +has been prepped to execute. Move the TCB to the ready-to-run +list, restore its context, and start execution. + +This function is called only from the NuttX scheduling logic. +Interrupts will always be disabled when this function is called. + +:param tcb: Refers to the tcb to be unblocked. This tcb is in one + of the waiting tasks lists. It must be moved to the + ready-to-run list and, if it is the highest priority ready to + run tasks, executed. + +.. c:function:: void up_block_task(FAR struct tcb_s *tcb, tstate_t task_state) + + The currently executing task at the head of the + ready to run list must be stopped. Save its context and move it to + the inactive list specified by task_state. This function is called + only from the NuttX scheduling logic. Interrupts will always be + disabled when this function is called. + + :param tcb: Refers to a task in the ready-to-run list (normally + the task at the head of the list). It must be stopped, its + context saved and moved into one of the waiting task lists. If + it was the task at the head of the ready-to-run list, then a + context switch to the new ready to run task must be performed. + :param task_state: Specifies which waiting task list should be + hold the blocked task TCB. + +.. c:function:: void up_release_pending(void) + + When tasks become ready-to-run but cannot run + because pre-emption is disabled, they are placed into a pending + task list. This function releases and makes ready-to-run all of + the tasks that have collected in the pending task list. This can + cause a context switch if a new task is placed at the head of the + ready to run list. + + This function is called only from the NuttX scheduling logic when + pre-emption is re-enabled. Interrupts will always be disabled when + this function is called. + +.. c:function:: void up_reprioritize_rtr(FAR struct tcb_s *tcb, uint8_t priority) + + Called when the priority of a running or + ready-to-run task changes and the reprioritization will cause a + context switch. Two cases: + + #. The priority of the currently running task drops and the next + task in the ready to run list has priority. + #. An idle, ready to run task's priority has been raised above the + the priority of the current, running task and it now has the + priority. + + This function is called only from the NuttX scheduling logic. + Interrupts will always be disabled when this function is called. + + :param tcb: The TCB of the task that has been reprioritized + :param priority: The new task priority + +.. c:macro:: noreturn_function + +.. c:function:: void up_exit(int status) noreturn_function; + + This function causes the currently executing task + to cease to exist. This is a special case of task_delete(). + + Unlike other UP APIs, this function may be called directly from + user programs in various states. The implementation of this + function should disable interrupts before performing scheduling + operations. + +.. c:function:: void up_assert(FAR const char *filename, int linenum) + + Assertions may be handled in an + architecture-specific way. + +.. c:function:: void up_schedule_sigaction(FAR struct tcb_s *tcb, sig_deliver_t sigdeliver) + + This function is called by the OS when one or + more signal handling actions have been queued for execution. The + architecture specific code must configure things so that the + 'sigdeliver' callback is executed on the thread specified by 'tcb' + as soon as possible. + + This function may be called from interrupt handling logic. + + This operation should not cause the task to be unblocked nor + should it cause any immediate execution of sigdeliver. Typically, + a few cases need to be considered: + + #. This function may be called from an interrupt handler During + interrupt processing, all xcptcontext structures should be + valid for all tasks. That structure should be modified to + invoke sigdeliver() either on return from (this) interrupt or + on some subsequent context switch to the recipient task. + #. If not in an interrupt handler and the tcb is NOT the currently + executing task, then again just modify the saved xcptcontext + structure for the recipient task so it will invoke sigdeliver + when that task is later resumed. + #. If not in an interrupt handler and the tcb IS the currently + executing task -- just call the signal handler now. + +.. c:function:: void up_allocate_heap(FAR void **heap_start, size_t *heap_size) + + This function will be called to dynamically set + aside the heap region. + + For the kernel build (``CONFIG_BUILD_PROTECTED=y`` or + ``CONFIG_BUILD_KERNEL=y``) with both kernel- and user-space heaps + (``CONFIG_MM_KERNEL_HEAP=y``), this function provides the size of + the unprotected, user-space heap. If a protected kernel-space heap + is provided, the kernel heap must be allocated (and protected) by + an analogous ``up_allocate_kheap()``. + +.. c:function:: bool up_interrupt_context(void) + + Return true if we are currently executing in the + interrupt handler context. + +.. c:function:: void up_disable_irq(int irq) + + Disable the IRQ specified by 'irq' On many + architectures, there are three levels of interrupt enabling: (1) + at the global level, (2) at the level of the interrupt controller, + and (3) at the device level. In order to receive interrupts, they + must be enabled at all three levels. + + This function implements enabling of the device specified by 'irq' + at the interrupt controller level if supported by the architecture + (up_irq_save() supports the global level, the device level is + hardware specific). + + If the architecture does not support ``up_disable_irq``, + ``CONFIG_ARCH_NOINTC`` should be defined in the NuttX + configuration file. Since this API cannot be supported on all + architectures, it should be avoided in common implementations + where possible. + +.. c:function:: void up_enable_irq(int irq) + + This function implements disabling of the device + specified by 'irq' at the interrupt controller level if supported + by the architecture (up_irq_restore() supports the global level, + the device level is hardware specific). + + If the architecture does not support ``up_disable_irq``, + ``CONFIG_ARCH_NOINTC`` should be defined in the NuttX + configuration file. Since this API cannot be supported on all + architectures, it should be avoided in common implementations + where possible. + +.. c:function:: void up_prioritize_irq(int irq) + + Set the priority of an IRQ. + + If the architecture supports ``up_enable_irq``, + ``CONFIG_ARCH_IRQPRIO`` should be defined in the NuttX + configuration file. Since this API cannot be supported on all + architectures, it should be avoided in common implementations + where possible. + +.. c:function:: int up_putc(int ch) + + This is a debug interface exported by the + architecture-specific logic. Output one character on the console + diff --git a/doc/reference/os/board.rst b/doc/reference/os/board.rst new file mode 100644 index 00000000000..5ff8227fba6 --- /dev/null +++ b/doc/reference/os/board.rst @@ -0,0 +1,74 @@ +============================================== +APIs Exported by Board-Specific Logic to NuttX +============================================== + +Exported board-specific interfaces are prototyped in the header +file ``include/nuttx/board.h``. There are many interfaces exported +from board- to architecture-specific logic. But there are only a +few exported from board-specific logic to common NuttX logic. +Those few of those related to initialization will be discussed in +this paragraph. There are others, like those used by +```boardctl()`` <#boardctl>`__ that will be discussed in other +paragraphs. + +All of the board-specific interfaces used by the NuttX OS logic +are for controlled board initialization. There are three points in +time where you can insert custom, board-specific initialization +logic: + +First, ``_board_initialize()``: This function is *not* +called from the common OS logic, but rather from the +architecture-specific power on reset logic. This is used only for +initialization of very low-level things like configuration of GPIO +pins, power settings, DRAM initialization, etc. The OS has not +been initialized at this point, so you cannot allocate memory or +initialize device drivers. + +The other two board initialization *hooks* are called from the OS +start-up logic and are described in the following paragraphs: + +.. c:function:: void board_early_initialize(void) + + The next level of initialization is performed by a call to + ``up_initialize()`` (in + ``arch//src/common/up_initialize.c``). The OS has been + initialized at this point and it is okay to initialize drivers in + this phase. ``up_initialize()`` is *not* a board-specific + interface, but rather an architecture-specific, board-independent + interface. + + But at this same point in time, the OS will also call a + board-specific initialization function named + ``board_early_initialize()`` if + ``CONFIG_BOARD_EARLY_INITIALIZE=y`` is selected in the + configuration. The context in which ``board_early_initialize()`` + executes is suitable for early initialization of most, simple + device drivers and is a logical, board-specific extension of + up_initialize(). + + ``board_early_initialize()`` runs on the startup, initialization + thread. Some initialization operations cannot be performed on the + start-up, initialization thread. That is because the + initialization thread cannot wait for event. Waiting may be + required, for example, to mount a file system or or initialize a + device such as an SD card. For this reason, such driver initialize + must be deferred to ``board_late_initialize()``. + +.. c:function:: void board_late_initialize(void) + + And, finally, just before the user application code starts. If + ``CONFIG_BOARD_LATE_INITIALIZE=y`` is selected in the + configuration, then an final, additional initialization call will + be performed in the boot-up sequence to a function called + ``board_late_initialize()``. ``board_late_initialize()`` will be + called well after ``up_initialize()`` and + ``board_early_initialize()`` are called. + ``board_late_initialize()`` will be called just before the main + application task is started. This additional initialization phase + may be used, for example, to initialize more complex, + board-specific device drivers. + + Waiting for events, use of I2C, SPI, etc are permissible in the + context of board_late_initialize(). That is because + ``board_late_initialize()`` will run on a temporary, internal + kernel thread. diff --git a/doc/reference/os/boardctl.rst b/doc/reference/os/boardctl.rst new file mode 100644 index 00000000000..4ac9886d733 --- /dev/null +++ b/doc/reference/os/boardctl.rst @@ -0,0 +1,40 @@ +==================================== +``boardctl()`` Application Interface +==================================== + +.. c:function:: int boardctl(unsigned int cmd, uintptr_t arg) + + In a small embedded system, there will typically be a much + greater interaction between application and low-level board features. + The canonically correct to implement such interactions is by + implementing a character driver and performing the interactions + via low level ioctl() calls. This, however, may not be practical + in many cases and will lead to "correct" but awkward implementations. + + boardctl() is non-standard OS interface to alleviate the problem. + It basically circumvents the normal device driver ioctl() + interlace and allows the application to perform direct + IOCTL-like calls to the board-specific logic. It is especially + useful for setting up board operational and test configurations. + + NOTE: The other interfaces described in this document are internal + OS interface. boardctl() is an application interface to the OS. + There is no point, in fact, of using boardctl() within the OS; + the board interfaces prototyped in include/nuttx/board.h may + be called directly from within the OS. + + Application interfaces are described in the NuttX User Guide. + This application interface interface is described here only + because it is so non-standard and because it is so closely + tied to board porting logic. + + :param cmd: Identifies the board command to be executed. See + ``include/sys/boardctl.h`` for the complete list of common + board commands. Provisions are made to support non-common, + board-specific commands as well. + :param arg: The argument that accompanies the command. The nature + of the argument is determined by the specific command. + + :return: On success zero (OK) is returned; -1 (ERROR) is + returned on failure with the errno variable set to indicate the nature of the failure. + diff --git a/doc/reference/os/conventions.rst b/doc/reference/os/conventions.rst new file mode 100644 index 00000000000..120546830d0 --- /dev/null +++ b/doc/reference/os/conventions.rst @@ -0,0 +1,101 @@ +================================== +Naming and Header File Conventions +================================== + +- **Common Microprocessor Interfaces**. Any interface that is + common to all microprocessors should be prefixed with ``up_`` + and prototyped in ``include/nuttx/arch.h``. The definitions in + that header file provide the common interface between NuttX and + the architecture-specific implementation in ``arch/``. + + ``up_`` is supposed to stand for microprocessor; the ``u`` + is like the Greek letter micron: ľ. So it would be ``ľP`` + which is a common shortening of the word microprocessor. I + don't like that name very much. I wish I would have used a + more obvious prefix like ``arch_`` instead -- then I would + not have to answer this question so often. + +- **Microprocessor-Specific Interfaces**. An interface which is + unique to a certain microprocessor should be prefixed with the + name of the microprocessor, for example ``stm32_``, and be + prototyped in some header file in the ``arch/`` directories. + + There is also a ``arch//include//chip.h`` + header file that can be used to communicate other + microprocessor-specific information between the board logic and + even application logic. Application logic may, for example, + need to know specific capabilities of the chip. Prototypes in + that ``chip.h`` header file should follow the + microprocessor-specific naming convention. + +- **Common Board Interfaces**. Any interface that is common to + all boards should be prefixed with ``board_`` and should also + be prototyped in ``include/nuttx/board.h``. These ``board_`` + definitions provide the interface between the board-level logic + and the commaon and architecture-specific logic. + +- **Board-Specific Interfaces**. Any interface which is unique to + a board should be prefixed with the board name, for example + ``stm32f4discovery_``. Sometimes the board name is too long so + ``stm32_`` would be okay too. These should be prototyped in + ``boards////src/.h`` and should not + be used outside of that directory since board-specific + definitions have no meaning outside of the board directory. + +- **Scope of Inclusions**. Header files are made accessible to + internal OS logic and to applications through symbolic links + and through *include paths* that are provided to the C/C++ + compiler. Through these include paths, the NuttX build system + also enforces modularity in the design. For example, one + important design principle is architectural *layering*. In this + case I am referring to the OS as layered into application + interface, common internal OS logic, and lower level + platform-specific layers. The platform-specific layers all + reside in the either ``arch/`` sub-directories on the + ``config/`` subdirectories: The former sub-directories are + reserved for microcontroller-specific logic and the latter for + board-specific logic. + + In the strict, layered NuttX architecture, the upper level OS + services are always available to platform-specific logic. + However, the opposite is *not* true: Common OS logic must never + have any dependency on the lower level platform-specific code. + The OS logic must be totally agnostic about its hardware + environment. Similarly, microcontroller-specific logic was be + completely ignorant of board-specific logic. + + This strict layering is enforced in the NuttX build system by + controlling the compiler include paths: Higher level code can + never include header files from either; of the + platform-specific source directories; microcontroller-specific + code can never include header files from the board-specific + source directories. The board-specific directories are, then, + at the bottom of the layered hierarchy. + + An exception to these inclusion restrictions is the + platform-specific *include/*. These are made available to + higher level OS logic. The microcontroller-specific include + directory will be linked at ``include/arch/chip`` and, hence, + can be included like ``#include ///include/board.h`` header file + must never include microcontroller-specific header files that + reside in ``arch//src/``. That practice will cause + inclusion failures when the publicly visible file is included + in common logic outside of the platform-specific source + directories. + + diff --git a/doc/reference/os/index.rst b/doc/reference/os/index.rst new file mode 100644 index 00000000000..75f53bad32a --- /dev/null +++ b/doc/reference/os/index.rst @@ -0,0 +1,25 @@ +================= +Architecture APIs +================= + +The file ``include/nuttx/arch.h`` identifies by prototype all of +the APIs that must be provided by the architecture specific logic. +The internal OS APIs that architecture-specific logic must +interface with also also identified in ``include/nuttx/arch.h`` or +in other header files. + +.. toctree:: + conventions.rst + arch.rst + board.rst + time_clock.rst + wqueue.rst + addrenv.rst + nuttx.rst + app_vs_os.rst + boardctl.rst + smp.rst + shm.rst + paging.rst + led.rst + iob.rst diff --git a/doc/reference/os/iob.rst b/doc/reference/os/iob.rst new file mode 100644 index 00000000000..3f4f3b2c5a3 --- /dev/null +++ b/doc/reference/os/iob.rst @@ -0,0 +1,310 @@ +===================== +I/O Buffer Management +===================== + +NuttX supports generic I/O buffer management (IOB) logic. This +logic was originally added to support network I/O buffering, but +has been generalized to meet buffering requirements by all device +drivers. At the time of this writing, IOBs are currently used not +only be networking but also by logic in ``drivers/syslog`` and +``drivers/wireless``. NOTE that some of the wording in this +section still reflects those legacy roots as a part of the +networking subsystem. This objectives of this feature are: + + #. Provide common I/O buffer management logic for all drivers, + #. Support I/O buffer allocation from both the tasking and + interrupt level contexts. + #. Use a fixed amount of pre-allocated memory. + #. No costly, non-deterministic dynamic memory allocation. + #. When the fixed number of pre-allocated I/O buffers is + exhausted, further attempts to allocate memory from tasking + logic will cause the task to block and wait until a an I/O + buffer to be freed. + #. Each I/O buffer should be small, but can be chained together to + support buffering of larger thinks such as full size network + packets. + #. Support *throttling* logic to prevent lower priority tasks from + hogging all available I/O buffering. + +Configuration Options +===================== + +``CONFIG_MM_IOB`` + Enables generic I/O buffer support. This setting will build the + common I/O buffer (IOB) support library. +``CONFIG_IOB_NBUFFERS`` + Number of pre-allocated I/O buffers. Each packet is represented + by a series of small I/O buffers in a chain. This setting + determines the number of preallocated I/O buffers available for + packet data. The default value is setup for network support. + The default is 8 buffers if neither TCP/UDP or write buffering + is enabled (neither ``CONFIG_NET_TCP_WRITE_BUFFERS`` nor + ``CONFIG_NET_TCP``), 24 if only TCP/UDP is enabled, and 36 if + both TCP/UDP and write buffering are enabled. +``CONFIG_IOB_BUFSIZE`` + Payload size of one I/O buffer. Each packet is represented by a + series of small I/O buffers in a chain. This setting determines + the data payload each preallocated I/O buffer. The default + value is 196 bytes. +``CONFIG_IOB_NCHAINS`` + Number of pre-allocated I/O buffer chain heads. These tiny + nodes are used as *containers* to support queueing of I/O + buffer chains. This will limit the number of I/O transactions + that can be *in-flight* at any give time. The default value of + zero disables this features. + These generic I/O buffer chain containers are not currently + used by any logic in NuttX. That is because their other other + specialized I/O buffer chain containers that also carry a + payload of usage specific information. The default value is + zero if nether TCP nor UDP is enabled (i.e., neither + ``CONFIG_NET_TCP`` && !\ ``CONFIG_NET_UDP`` or eight if either + is enabled. +``CONFIG_IOB_THROTTLE`` + I/O buffer throttle value. TCP write buffering and read-ahead + buffer use the same pool of free I/O buffers. In order to + prevent uncontrolled incoming TCP packets from hogging all of + the available, pre-allocated I/O buffers, a throttling value is + required. This throttle value assures that I/O buffers will be + denied to the read-ahead logic before TCP writes are halted. + The default 0 if neither TCP write buffering nor TCP read-ahead + buffering is enabled. Otherwise, the default is 8. +``CONFIG_IOB_DEBUG`` + Force I/O buffer debug. This option will force debug output + from I/O buffer logic. This is not normally something that + would want to do but is convenient if you are debugging the I/O + buffer logic and do not want to get overloaded with other + un-related debug output. NOTE that this selection is not + available if DEBUG features are not enabled + (``CONFIG_DEBUG_FEATURES``) with IOBs are being used to syslog + buffering logic (``CONFIG_SYSLOG_BUFFER``). + +Throttling +========== + +An allocation throttle was added. I/O buffer allocation logic +supports a throttle value originally for read-ahead buffering to +prevent the read-ahead logic from consuming all available I/O +buffers and blocking the write buffering logic. This throttle +logic is only needed for networking only if both write buffering +and read-ahead buffering are used. Of use of I/O buffering might +have other motivations for throttling. + +Public Types +============ + +This structure represents one I/O buffer. A packet is contained by +one or more I/O buffers in a chain. The ``io_pktlen`` is only +valid for the I/O buffer at the head of the chain. + +.. code-block:: c + + struct iob_s + { + /* Singly-link list support */ + + FAR struct iob_s *io_flink; + + /* Payload */ + + #if CONFIG_IOB_BUFSIZE < 256 + uint8_t io_len; /* Length of the data in the entry */ + uint8_t io_offset; /* Data begins at this offset */ + #else + uint16_t io_len; /* Length of the data in the entry */ + uint16_t io_offset; /* Data begins at this offset */ + #endif + uint16_t io_pktlen; /* Total length of the packet */ + + uint8_t io_data[CONFIG_IOB_BUFSIZE]; + }; + +This container structure supports queuing of I/O buffer chains. +This structure is intended only for internal use by the IOB +module. + +.. code-block:: c + + #if CONFIG_IOB_NCHAINS > 0 + struct iob_qentry_s + { + /* Singly-link list support */ + + FAR struct iob_qentry_s *qe_flink; + + /* Payload -- Head of the I/O buffer chain */ + + FAR struct iob_s *qe_head; + }; + #endif /* CONFIG_IOB_NCHAINS > 0 */ + +The I/O buffer queue head structure. + +.. code-block:: c + + #if CONFIG_IOB_NCHAINS > 0 + struct iob_queue_s + { + /* Head of the I/O buffer chain list */ + + FAR struct iob_qentry_s *qh_head; + FAR struct iob_qentry_s *qh_tail; + }; + #endif /* CONFIG_IOB_NCHAINS > 0 */ + +Public Function Prototypes +========================== + + - :c:func:`iob_initialize()` + - :c:func:`iob_alloc()` + - :c:func:`iob_tryalloc()` + - :c:func:`iob_free()` + - :c:func:`iob_free_chain()` + - :c:func:`iob_add_queue()` + - :c:func:`iob_tryadd_queue()` + - :c:func:`iob_remove_queue()` + - :c:func:`iob_peek_queue()` + - :c:func:`iob_free_queue()` + - :c:func:`iob_copyin()` + - :c:func:`iob_trycopyin()` + - :c:func:`iob_copyout()` + - :c:func:`iob_clone()` + - :c:func:`iob_concat()` + - :c:func:`iob_trimhead()` + - :c:func:`iob_trimhead_queue()` + - :c:func:`iob_trimtail()` + - :c:func:`iob_pack()` + - :c:func:`iob_contig()` + - :c:func:`iob_dump()` + +.. c:function:: void iob_initialize(void); + + Set up the I/O buffers for normal operations. + +.. c:function:: FAR struct iob_s *iob_alloc(bool throttled); + + Allocate an I/O buffer by taking the buffer at + the head of the free list. + +.. c:function:: FAR struct iob_s *iob_tryalloc(bool throttled); + + Try to allocate an I/O buffer by taking the + buffer at the head of the free list without waiting for a buffer + to become free. + +.. c:function:: FAR struct iob_s *iob_free(FAR struct iob_s *iob); + + Free the I/O buffer at the head of a buffer chain + returning it to the free list. The link to the next I/O buffer in + the chain is return. + +.. c:function:: void iob_free_chain(FAR struct iob_s *iob); + + Free an entire buffer chain, starting at the + beginning of the I/O buffer chain + +.. c:function:: int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq) + + Add one I/O buffer chain to the end of a queue. + May fail due to lack of resources. + +.. c:function:: void iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq) + + Add one I/O buffer chain to the end of a queue + without waiting for resources to become free. + +.. c:function:: FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq); + + Remove and return one I/O buffer chain from the + head of a queue. + + :return: Returns a reference to the I/O buffer chain at + the head of the queue. + +.. c:function:: FAR struct iob_s *iob_peek_queue(FAR struct iob_queue_s *iobq) + + Return a reference to the I/O buffer chain at the + head of a queue. This is similar to iob_remove_queue except that + the I/O buffer chain is in place at the head of the queue. The I/O + buffer chain may safely be modified by the caller but must be + removed from the queue before it can be freed. + + :return: Returns a reference to the I/O buffer chain at + the head of the queue. + +.. c:function:: void iob_free_queue(FAR struct iob_queue_s *qhead); + + Free an entire queue of I/O buffer chains. + +.. c:function:: int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src, \ + unsigned int len, unsigned int offset, bool throttled); + + Copy data ``len`` bytes from a user buffer into + the I/O buffer chain, starting at ``offset``, extending the chain + as necessary. + +.. c:function:: int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src, \ + unsigned int len, unsigned int offset, bool throttled); + + Copy data ``len`` bytes from a user buffer into + the I/O buffer chain, starting at ``offset``, extending the chain + as necessary BUT without waiting if buffers are not available. + +.. c:function:: int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob, \ + unsigned int len, unsigned int offset); + + Copy data ``len`` bytes of data into the user + buffer starting at ``offset`` in the I/O buffer, returning that + actual number of bytes copied out. + +.. c:function:: int iob_clone(FAR struct iob_s *iob1, FAR struct iob_s *iob2, bool throttled) + + Duplicate (and pack) the data in ``iob1`` in + ``iob2``. ``iob2`` must be empty. + +.. c:function:: void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2) + + Concatenate iob_s chain iob2 to iob1. + +.. c:function:: FAR struct iob_s *iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen) + + Remove bytes from the beginning of an I/O chain. + Emptied I/O buffers are freed and, hence, the beginning of the + chain may change. + +.. c:function:: FAR struct iob_s *iob_trimhead_queue(FAR struct iob_queue_s *qhead, \ + unsigned int trimlen); + + Remove bytes from the beginning of an I/O chain + at the head of the queue. Emptied I/O buffers are freed and, + hence, the head of the queue may change. + + This function is just a wrapper around iob_trimhead() that assures + that the iob at the head of queue is modified with the trimming + operations. + + :return: The new iob at the head of the queue is + returned. + +.. c:function:: FAR struct iob_s *iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen); + + Remove bytes from the end of an I/O chain. + Emptied I/O buffers are freed NULL will be returned in the special + case where the entry I/O buffer chain is freed. + +.. c:function:: FAR struct iob_s *iob_pack(FAR struct iob_s *iob); + + Pack all data in the I/O buffer chain so that the + data offset is zero and all but the final buffer in the chain are + filled. Any emptied buffers at the end of the chain are freed. + +.. c:function:: int iob_contig(FAR struct iob_s *iob, unsigned int len); + + Ensure that there is ``len`` bytes of contiguous + space at the beginning of the I/O buffer chain starting at + ``iob``. + +.. c:function:: void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len, \ + unsigned int offset); + + Dump the contents of a I/O buffer chain + diff --git a/doc/reference/os/led.rst b/doc/reference/os/led.rst new file mode 100644 index 00000000000..f8d443545d5 --- /dev/null +++ b/doc/reference/os/led.rst @@ -0,0 +1,122 @@ +=========== +LED Support +=========== + +A board architecture may or may not have LEDs. If the board does +have LEDs, then most architectures provide similar LED support +that is enabled when ``CONFIG_ARCH_LEDS`` is selected in the NuttX +configuration file. This LED support is part of +architecture-specific logic and is not managed by the core NuttX +logic. However, the support provided by each architecture is +sufficiently similar that it can be documented here. + +Header Files +============ + +LED-related definitions are provided in two header files: + +- LED definitions are provided for each board in the ``board.h`` + that resides in the ``/include/board.h`` file + (which is also linked to ``include/arch/board/board.h`` when + the RTOS is configured). Those definitions are discussed + `below <#leddefinitions>`__. +- The board-specific logic provides unique instances of the LED + interfaces. This is because the implementation of LED support + may be very different on different boards. Prototypes for these + board-specific implementations are, however, provided in + architecture-common header files. That header file is usually + at ``/src/common/up_internal.h``, but could be at + other locations in particular architectures. These prototypes + are discussed `below <#ledapis>`__. + +LED Definitions +=============== + +The implementation of LED support is very specific to a board +architecture. Some boards have several LEDS, others have only one +or two. Some have none. Others LED matrices and show alphanumeric +data, etc. The NuttX logic does not refer to specific LEDS, +rather, it refers to an event to be shown on the LEDS in whatever +manner is appropriate for the board; the way that this event is +presented depends upon the hardware available on the board. + +The model used by NuttX is that the board can show 8 events +defined as follows in ``/include/board.h``: + +.. code-block:: c + + #define LED_STARTED ?? + #define LED_HEAPALLOCATE ?? + #define LED_IRQSENABLED ?? + #define LED_STACKCREATED ?? + #define LED_INIRQ ?? + #define LED_SIGNAL ?? + #define LED_ASSERTION ?? + #define LED_PANIC ?? + +The specific value assigned to each pre-processor variable can be +whatever makes the implementation easiest for the board logic. The +*meaning* associated with each definition is as follows: + +- ``LED_STARTED`` is the value that describes the setting of the + LEDs when the LED logic is first initialized. This LED value is + set but never cleared. +- ``LED_HEAPALLOCATE`` indicates that the NuttX heap has been + configured. This is an important place in the boot sequence + because if the memory is configured wrong, it will probably + crash leaving this LED setting. This LED value is set but never + cleared. +- ``LED_IRQSENABLED`` indicates that interrupts have been + enabled. Again, during bring-up (or if there are hardware + problems), it is very likely that the system may crash just + when interrupts are enabled, leaving this setting on the LEDs. + This LED value is set but never cleared. +- ``LED_STACKCREATED`` is set each time a new stack is created. + If set, it means that the system attempted to start at least + one new thread. This LED value is set but never cleared. +- ``LED_INIRQ`` is set and cleared on entry and exit from each + interrupt. If interrupts are working okay, this LED will have a + dull glow. +- ``LED_SIGNAL`` is set and cleared on entry and exit from a + signal handler. Signal handlers are tricky so this is + especially useful during bring-up or a new architecture. +- ``LED_ASSERTION`` is set if an assertion occurs. +- ``LED_PANIC`` will blink at around 1Hz if the system panics and + hangs. + +Common LED interfaces +===================== + +The ``include/nuttx/board.h`` includes the following declarations: + +.. c:function:: void board_autoled_initialize(void) + + Called early in power-up initialization to initialize the LED hardware. + + .. note:: In most architectures, + ``board_autoled_initialize()`` is called from board-specific + initialization logic. But there are a few architectures + where this initialization function is still called from + common chip architecture logic. This interface is not, + however, a common board interface in any event. + + .. warning:: This interface name will eventually be removed; + do not use it in new board ports. New implementations should + not use the naming convention for common board interfaces, + but should instead use the naming conventions for + microprocessor-specific interfaces or the board-specific + interfaces (such as ``stm32_led_initialize()``). + +.. c:function:: void board_autoled_on(int led) + + Called to instantiate the LED + presentation of the event. The ``led`` argument is one of the + definitions provided in ``/include/board.h``. + +.. c:function:: void board_autoled_off(int led) + + Called to terminate the LED + presentation of the event. The ``led`` argument is one of the + definitions provided in ``/include/board.h``. Note + that only ``LED_INIRQ``, ``LED_SIGNAL``, ``LED_ASSERTION``, and + ``LED_PANIC`` indications are terminated. diff --git a/doc/reference/os/nuttx.rst b/doc/reference/os/nuttx.rst new file mode 100644 index 00000000000..2020583e406 --- /dev/null +++ b/doc/reference/os/nuttx.rst @@ -0,0 +1,50 @@ +===================================================== +APIs Exported by NuttX to Architecture-Specific Logic +===================================================== + +These are standard interfaces that are exported by the OS for use +by the architecture specific logic. + +.. c:function:: void nx_start(void) + + **To be provided** + +OS List Management APIs +======================= + +**To be provided** + +.. c:function:: void nxsched_process_timer(void) + + This function handles system timer events. The + timer interrupt logic itself is implemented in the architecture + specific code, but must call the following OS function + periodically -- the calling interval must be + ``CONFIG_USEC_PER_TICK``. + +.. c:function:: void nxsched_timer_expiration(void) + + Description: if ``CONFIG_SCHED_TICKLESS`` is defined, then this + function is provided by the RTOS base code and called from + platform-specific code when the interval timer used to implemented + the tick-less OS expires. + + **Assumptions**: Base code implementation assumes that this + function is called from interrupt handling logic with interrupts disabled. + +.. c:function:: void nxsched_alarm_expiration(void); + + If ``CONFIG_SCHED_TICKLESS`` is defined, then this + function is provided by the RTOS base code and called from + platform-specific code when the interval timer used to implemented + the tick-less OS expires. + + **Assumptions**: Base code implementation assumes that this + function is called from interrupt handling logic with interrupts disabled. + +.. c:function:: void irq_dispatch(int irq, FAR void *context) + + This function must be called from the + architecture- specific logic in order to display an interrupt to + the appropriate, registered handling logic. + diff --git a/doc/reference/os/paging.rst b/doc/reference/os/paging.rst new file mode 100644 index 00000000000..3c303823deb --- /dev/null +++ b/doc/reference/os/paging.rst @@ -0,0 +1,13 @@ +================ +On-Demand Paging +================ + +The NuttX On-Demand Paging feature permits embedded MCUs with some +limited RAM space to execute large programs from some non-random +access media. If the platform meets certain requirements, then +NuttX can provide on-demand paging: It can copy .text from the +large program in non-volatile media into RAM as needed to execute +a huge program from the small RAM. Design and porting issues for +this feature are discussed in a separate document. Please see the +`NuttX Demand Paging `__ design document +for further information. diff --git a/doc/reference/os/shm.rst b/doc/reference/os/shm.rst new file mode 100644 index 00000000000..339539f2aa8 --- /dev/null +++ b/doc/reference/os/shm.rst @@ -0,0 +1,38 @@ +============= +Shared Memory +============= + +Shared memory interfaces are only available with the NuttX kernel +build (``CONFIG_BUILD_KERNEL=y``). These interfaces support user +memory regions that can be shared between multiple user processes. +The user interfaces are provided in the standard header file +``include/sys/shm.h>``. All logic to support shared memory is +implemented within the NuttX kernel with the exception of two +low-level functions that are require to configure the +platform-specific MMU resources. Those interfaces are described +below: + +.. c:function:: int up_shmat(FAR uintptr_t *pages, unsigned int npages, uintptr_t vaddr) + + Attach, i.e, map, on shared memory region to a user virtual address. + + :param pages: A pointer to the first element in a array of + physical address, each corresponding to one page of memory. + :param npages: The number of pages in the list of physical pages + to be mapped. + :param vaddr: The virtual address corresponding to the beginning + of the (contiguous) virtual address region. + + :return: Zero (OK) is returned on success; a negated errno value is returned on failure. + + +.. c:function:: int up_shmdt(uintptr_t vaddr, unsigned int npages) + + Detach, i.e, unmap, on shared memory region from a user virtual address. + + :param vaddr: The virtual address corresponding to the beginning + of the (contiguous) virtual address region. + :param npages: T The number of pages to be unmapped. + + :return: Zero (OK) is returned on success; a negated errno value is returned on failure. + diff --git a/doc/reference/os/smp.rst b/doc/reference/os/smp.rst new file mode 100644 index 00000000000..3ac45ed5f2f --- /dev/null +++ b/doc/reference/os/smp.rst @@ -0,0 +1,99 @@ +=========================================== +Symmetric Multiprocessing (SMP) Application +=========================================== + +According to Wikipedia: "Symmetric multiprocessing (SMP) involves +a symmetric multiprocessor system hardware and software +architecture where two or more identical processors connect to a +single, shared main memory, have full access to all I/O devices, +and are controlled by a single operating system instance that +treats all processors equally, reserving none for special +purposes. Most multiprocessor systems today use an SMP +architecture. In the case of multi-core processors, the SMP +architecture applies to the cores, treating them as separate +processors. + +"SMP systems are tightly coupled multiprocessor systems with a +pool of homogeneous processors running independently, each +processor executing different programs and working on different +data and with capability of sharing common resources (memory, I/O +device, interrupt system and so on) and connected using a system +bus or a crossbar." + +For a technical description of the NuttX implementation of SMP, +see the NuttX `SMP Wiki +Page `__. + +.. c:function:: spinlock_t up_testset(volatile FAR spinlock_t *lock) + + Perform and atomic test and set operation on the provided spinlock. + + :param lock: The address of spinlock object. + + :return: The spinlock is always locked upon return. The value + of previous value of the spinlock variable is returned, + either SP_LOCKED if the spinlock was previously locked + (meaning that the test-and-set operation failed to obtain the lock) + or SP_UNLOCKED if the spinlock was previously unlocked + (meaning that we successfully obtained the lock) + +.. c:function:: int up_cpu_index(void) + + Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) + that corresponds to the currently executing CPU. + + :return: An integer index in the range of 0 through + (CONFIG_SMP_NCPUS-1) that corresponds to the + currently executing CPU. + +.. c:function:: int up_cpu_start(int cpu) + + In an SMP configuration, only one CPU is initially active (CPU 0). + System initialization occurs on that single thread. At the + completion of the initialization of the OS, just before + beginning normal multitasking, the additional CPUs would + be started by calling this function. + + Each CPU is provided the entry point to is IDLE task when started. + A TCB for each CPU's IDLE task has been initialized and + placed in the CPU's g_assignedtasks[cpu] list. A stack + has also been allocated and initialized. + + The OS initialization logic calls this function repeatedly until + each CPU has been started, 1 through (CONFIG_SMP_NCPUS-1). + + :param cpu: The index of the CPU being started. This will be a + numeric value in the range of from one to + ``(CONFIG_SMP_NCPUS-1)``). (CPU 0 is already active). + + :return: Zero (OK) is returned on success; a negated errno value on failure. + +.. c:function:: int up_cpu_pause(int cpu) + + Save the state of the current task at the head of the + ``g_assignedtasks[cpu]`` task list and then pause task execution on the CPU. + + This function is called by the OS when the logic executing on + one CPU needs to modify the state of the ``g_assignedtasks[cpu]`` + list for another CPU. + + :param cpu: The index of the CPU to be paused. This will not be + the index of the currently executing CPU. + + :return: Zero (OK) is returned on success; a negated errno value on failure. + +.. c:function:: int up_cpu_resume(int cpu) + + Restart the cpu after it was paused via up_cpu_pause(), + restoring the state of the task at the head of the + ``g_assignedtasks[cpu]`` list, and resume normal tasking. + + This function is called after ``up_cpu_pause()`` in order + resume operation of the CPU after modifying its + ``g_assignedtasks[cpu]`` list. + + :param cpu: The index of the CPU being resumed. This will not be + the index of the currently executing CPU. + + :return: Zero (OK) is returned on success; a negated errno value on failure. + diff --git a/doc/reference/os/time_clock.rst b/doc/reference/os/time_clock.rst new file mode 100644 index 00000000000..dc9f18783bd --- /dev/null +++ b/doc/reference/os/time_clock.rst @@ -0,0 +1,660 @@ +===================== +System Time and Clock +===================== + +Basic System Timer +================== + +**System Timer** In most implementations, system time is provided +by a timer interrupt. That timer interrupt runs at rate determined +by ``CONFIG_USEC_PER_TICK`` (default 10000 microseconds or 100Hz. +If ``CONFIG_SCHED_TICKLESS`` is selected, the default is 100 +microseconds). The timer generates an interrupt each +``CONFIG_USEC_PER_TICK`` microseconds and increments a counter +called ``g_system_timer``. ``g_system_timer`` then provides a +time-base for calculating *up-time* and elapsed time intervals in +units of ``CONFIG_USEC_PER_TICK``. The range of ``g_system_timer`` +is, by default, 32-bits. However, if the MCU supports type +``long long`` and ``CONFIG_SYSTEM_TIME16`` is selected, a 64-bit +system timer will be supported instead. + +**System Timer Accuracy** On many system, the exact timer interval +specified by ``CONFIG_USEC_PER_TICK`` cannot be achieved due to +limitations in frequencies or in dividers. As a result, the time +interval specified by ``CONFIG_USEC_PER_TICK`` may only be +approximate and there may be small errors in the apparent +*up-time* time. These small errors, however, will accumulate over +time and after a long period of time may have an unacceptably +large error in the apparent *up-time* of the MCU. + +If the timer tick period generated by the hardware is not exactly +``CONFIG_USEC_PER_TICK`` *and* if there you require accurate +up-time for the MCU, then there are measures that you can take: + +- Perhaps you can adjust ``CONFIG_USEC_PER_TICK`` to a different + value so that an exactly ``CONFIG_USEC_PER_TICK`` can be + realized. +- Or you can use a technique known as *Delta-Sigma Modulation*. + (Suggested by Uros Platise). Consider the example below. + +**Delta-Sigma Modulation Example**. Consider this case: The system +timer is a count-up timer driven at 32.768KHz. There are dividers +that can be used, but a divider of one yields the highest +accuracy. This counter counts up until the count equals a match +value, then a timer interrupt is generated. The desire frequency +is 100Hz (``CONFIG_USEC_PER_TICK`` is 10000). + +This exact frequency of 100Hz cannot be obtained in this case. In +order to obtain that exact frequency a match value of 327.68 would +have to be provided. The closest integer value is 328 but the +ideal match value is between 327 and 328. The closest value, 328, +would yield an actual timer frequency of 99.9Hz! That will may +cause significant timing errors in certain usages. + +Use of Delta-Sigma Modulation can eliminate this error in the long +run. Consider this example implementation: + + #. Initially an accumulator is zero an the match value is + programmed to 328: + + .. code-block:: c + + accumulator = 0; + match = 328; + + #. On each timer interrupt, accumulator is updated with difference + that, in this reflects, 100\* the error in interval that just + passed. So on the first timer interrupt, the accumulator would + be updated like: + + .. code-block:: c + + if (match == 328) + { + accumulator += 32; // 100*(328 - 327.68) + } + else + { + accumulator -= 68; // (100*(327 - 327.68) + } + + #. And on that same timer interrupt a new match value would be + programmed: + + .. code-block:: c + + if (accumulator < 0) + { + match = 328; + } + else + { + match = 327; + } + +In this way, the timer interval is controlled from +interrupt-to-interrupt to produce an average frequency of exactly +100Hz. + +Hardware +======== + +To enable hardware module use the following configuration options: + +``CONFIG_RTC`` + Enables general support for a hardware RTC. Specific + architectures may require other specific settings. +``CONFIG_RTC_EXTERNAL`` + Most MCUs include RTC hardware built into the chip. Other RTCs, + *external* MCUs, may be provided as separate chips typically + interfacing with the MCU via a serial interface such as SPI or + I2C. These external RTCs differ from the built-in RTCs in that + they cannot be initialized until the operating system is fully + booted and can support the required serial communications. + ``CONFIG_RTC_EXTERNAL`` will configure the operating system so + that it defers initialization of its time facilities. +``CONFIG_RTC_DATETIME`` + There are two general types of RTC: (1) A simple battery backed + counter that keeps the time when power is down, and (2) A full + date / time RTC the provides the date and time information, + often in BCD format. If ``CONFIG_RTC_DATETIME`` is selected, it + specifies this second kind of RTC. In this case, the RTC is + used to "seed"" the normal NuttX timer and the NuttX system + timer provides for higher resolution time. +``CONFIG_RTC_HIRES`` + If ``CONFIG_RTC_DATETIME`` not selected, then the simple, + battery backed counter is used. There are two different + implementations of such simple counters based on the time + resolution of the counter: The typical RTC keeps time to + resolution of 1 second, usually supporting a 32-bit ``time_t`` + value. In this case, the RTC is used to "seed" the normal NuttX + timer and the NuttX timer provides for higher resolution time. + If ``CONFIG_RTC_HIRES`` is enabled in the NuttX configuration, + then the RTC provides higher resolution time and completely + replaces the system timer for purpose of date and time. +``CONFIG_RTC_FREQUENCY`` + If ``CONFIG_RTC_HIRES`` is defined, then the frequency of the + high resolution RTC must be provided. If ``CONFIG_RTC_HIRES`` + is not defined, ``CONFIG_RTC_FREQUENCY`` is assumed to be one. +``CONFIG_RTC_ALARM`` + Enable if the RTC hardware supports setting of an alarm. A + callback function will be executed when the alarm goes off + +which requires the following base functions to read and set time: + +- ``up_rtc_initialize()``. Initialize the built-in, MCU hardware + RTC per the selected configuration. This function is called + once very early in the OS initialization sequence. NOTE that + initialization of external RTC hardware that depends on the + availability of OS resources (such as SPI or I2C) must be + deferred until the system has fully booted. Other, RTC-specific + initialization functions are used in that case. +- ``up_rtc_time()``. Get the current time in seconds. This is + similar to the standard ``time()`` function. This interface is + only required if the low-resolution RTC/counter hardware + implementation selected. It is only used by the RTOS during + initialization to set up the system time when ``CONFIG_RTC`` is + set but neither ``CONFIG_RTC_HIRES`` nor + ``CONFIG_RTC_DATETIME`` are set. +- ``up_rtc_gettime()``. Get the current time from the high + resolution RTC clock/counter. This interface is only supported + by the high-resolution RTC/counter hardware implementation. It + is used to replace the system timer (``g_system_tick``). +- ``up_rtc_settime()``. Set the RTC to the provided time. All RTC + implementations must be able to set their time based on a + standard timespec. + +System Tick and Time +==================== + +The system tick is represented by ``g_system_timer``. + +Running at rate of system base timer, used for time-slicing, and +so forth. + +If hardware RTC is present (``CONFIG_RTC``) and and +high-resolution timing is enabled (``CONFIG_RTC_HIRES``), then +after successful initialization variables are overridden by calls +to ``up_rtc_gettime()`` which is running continuously even in +power-down modes. + +In the case of ``CONFIG_RTC_HIRES`` is set the ``g_system_timer`` +keeps counting at rate of a system timer, which however, is +disabled in power-down mode. By comparing this time and RTC +(actual time) one may determine the actual system active time. To +retrieve that variable use: + +Tickless OS +=========== + +**Default System Timer**. By default, a NuttX configuration uses a +periodic timer interrupt that drives all system timing. The timer +is provided by architecture-specific code that calls into NuttX at +a rate controlled by ``CONFIG_USEC_PER_TICK``. The default value +of ``CONFIG_USEC_PER_TICK`` is 10000 microseconds which +corresponds to a timer interrupt rate of 100 Hz. + +On each timer interrupt, NuttX does these things: + +- Increments a counter. This counter is the system time and has a + resolution of ``CONFIG_USEC_PER_TICK`` microseconds. +- Checks if it is time to perform time-slice operations on tasks + that have select round-robin scheduling. +- Checks for expiration of timed events. + +What is wrong with this default system timer? Nothing really. It +is reliable and uses only a small fraction of the CPU band width. +But we can do better. Some limitations of default system timer +are, in increasing order of importance: + +- **Overhead**: Although the CPU usage of the system timer + interrupt at 100Hz is really very low, it is still mostly + wasted processing time. One most timer interrupts, there is + really nothing that needs be done other than incrementing the + counter. +- **Resolution**: Resolution of all system timing is also + determined by ``CONFIG_USEC_PER_TICK``. So nothing that be time + with resolution finer than 10 milliseconds be default. To + increase this resolution, ``CONFIG_USEC_PER_TICK`` an be + reduced. However, then the system timer interrupts use more of + the CPU bandwidth processing useless interrupts. +- **Power Usage**: But the biggest issue is power usage. When the + system is IDLE, it enters a light, low-power mode (for ARMs, + this mode is entered with the ``wfi`` or ``wfe`` instructions + for example). But each interrupt awakens the system from this + low power mode. Therefore, higher rates of interrupts cause + greater power consumption. + +**Tickless OS**. The so-called *Tickless OS* provides one solution +to issue. The basic concept here is that the periodic, timer +interrupt is eliminated and replaced with a one-shot, interval +timer. It becomes event driven instead of polled: The default +system timer is a polled design. On each interrupt, the NuttX +logic checks if it needs to do anything and, if so, it does it. + +Using an interval timer, one can anticipate when the next +interesting OS event will occur, program the interval time and +wait for it to fire. When the interval time fires, then the +scheduled activity is performed. + +Tickless Platform Support +------------------------- + +In order to use the Tickless OS, one must provide special support +from the platform-specific code. Just as with the default system +timer, the platform-specific code must provide the timer resources +to support the OS behavior. Currently these timer resources are +only provided on a few platforms. An example implementation is for +the simulation is at ``nuttx/arch/sim/src/up_tickless.c``. There +is another example for the Atmel SAMA5 at +``nuttx/arch/arm/src/sama5/sam_tickless.c``. These paragraphs will +explain how to provide the Tickless OS support to any platform. + +Tickless Configuration Options +------------------------------ + +- ``CONFIG_ARCH_HAVE_TICKLESS``: If the platform provides + support for the *Tickless OS*, then this setting should be + selected in the ``Kconfig`` file for the board. Here is what + the selection looks in the ``arch/Kconfig`` file for the + simulated platform: + + When the simulation platform is selected, + ``ARCH_HAVE_TICKLESS`` is automatically selected, informing the + configuration system that *Tickless OS* options can be + selected. + +- ``CONFIG_SCHED_TICKLESS``: If ``CONFIG_ARCH_HAVE_TICKLESS`` + is selected, then it will enable the Tickless OS features in + NuttX. + +- ``CONFIG_SCHED_TICKLESS_ALARM``: The tickless option can be + supported either via a simple interval timer (plus elapsed + time) or via an alarm. The interval timer allows programming + events to occur after an interval. With the alarm, you can set + a time in the future and get an event when that alarm goes off. + This option selects the use of an alarm. + + The advantage of an alarm is that it avoids some small timing + errors; the advantage of the use of the interval timer is that + the hardware requirement may be less. + +- ``CONFIG_USEC_PER_TICK``: This option is not unique to + *Tickless OS* operation, but changes its relevance when the + *Tickless OS* is selected. In the default configuration where + system time is provided by a periodic timer interrupt, the + default system timer is configure the timer for 100Hz or + ``CONFIG_USEC_PER_TICK=10000``. If ``CONFIG_SCHED_TICKLESS`` is + selected, then there are no system timer interrupt. In this + case, ``CONFIG_USEC_PER_TICK`` does not control any timer + rates. Rather, it only determines the resolution of time + reported by ``clock_systime_ticks()`` and the resolution of + times that can be set for certain delays including watchdog + timers and delayed work. + + In this case there is still a trade-off: It is better to have + the ``CONFIG_USEC_PER_TICK`` as low as possible for higher + timing resolution. However, the time is currently held in + ``unsigned int``. On some systems, this may be 16-bits in width + but on most contemporary systems it will be 32-bits. In either + case, smaller values of ``CONFIG_USEC_PER_TICK`` will reduce + the range of values that delays that can be represented. So the + trade-off is between range and resolution (you could also + modify the code to use a 64-bit value if you really want both). + + The default, 100 microseconds, will provide for a range of + delays up to 120 hours. + + This value should never be less than the underlying resolution + of the timer. Errors may ensue. + +Tickless Imported Interfaces +---------------------------- + +The interfaces that must be provided by the platform specified +code are defined in ``include/nuttx/arch.h``, listed below, and +summarized in the following paragraphs: + + - ``_timer_initialize()`` Initializes + the timer facilities. Called early in the initialization + sequence (by ``up_initialize()``). + - ``up_timer_gettime()``: Returns the + current time from the platform specific time source. + +The tickless option can be supported either via a simple interval +timer (plus elapsed time) or via an alarm. The interval timer +allows programming events to occur after an interval. With the +alarm, you can set a time in\* the future and get an event when +that alarm goes off. + +If ``CONFIG_SCHED_TICKLESS_ALARM`` is defined, then the platform +code must provide the following: + +- ``up_alarm_cancel()``: Cancels the alarm. +- ``up_alarm_start()``: Enables (or + re-enables) the alarm. + +If ``CONFIG_SCHED_TICKLESS_ALARM`` is *not*\ defined, then the +platform code must provide the following verify similar functions: + +- ``up_timer_cancel()``: Cancels the + interval timer. +- ``up_timer_start()``: Starts (or re-starts) + the interval timer. + +Note that a platform-specific implementation would probably +require two hardware timers: (1) A interval timer to satisfy the +requirements of ``up_timer_start()`` and +``up_timer_cancel()``, and a (2) a counter to +handle the requirement of +``up_timer_gettime()``. Ideally, both timers +would run at the rate determined by ``CONFIG_USEC_PER_TICK`` (and +certainly never slower than that rate). + +Since timers are a limited resource, the use of two timers could +be an issue on some systems. The job could be done with a single +timer if, for example, the single timer were kept in a +free-running at all times. Some timer/counters have the capability +to generate a compare interrupt when the timer matches a +comparison value but also to continue counting without stopping. +If your hardware supports such counters, one might used the +``CONFIG_SCHED_TICKLESS_ALARM`` option and be able to simply set +the comparison count at the value of the free running timer *PLUS* +the desired delay. Then you could have both with a single timer: +An alarm and a free-running counter with the same timer! + +In addition to these imported interfaces, the RTOS will export the +following interfaces for use by the platform-specific interval +timer implementation: + +- ``nxsched_alarm_expiration()``: called by the platform-specific logic when the alarm expires. +- ``nxsched_timer_expiration()``: called by the platform-specific logic when the interval time expires. + +.. c:function:: void archname_timer_initialize(void) + + Initializes all platform-specific timer facilities. This function is + called early in the initialization sequence by up_initialize(). + On return, the current up-time should be available from up_timer_gettime() + and the interval timer is ready for use (but not actively timing). + The naming will depend on the architecture so for STM32 ``archname`` will + be ``stm32``. + + :return: Zero (OK) on success; a negated errno value on failure. + + **Assumptions**: Called early in the initialization sequence before + any special concurrency protections are required. + +.. c:function:: int up_timer_gettime(FAR struct timespec *ts) + + Return the elapsed time since power-up (or, more correctly, since + **\ ``_timer_initialize()`` was called). This function is + functionally equivalent to ``clock_gettime()`` for the clock ID + ``CLOCK_MONOTONIC``. This function provides the basis for + reporting the current time and also is used to eliminate error + build-up from small errors in interval time calculations. + + :param ts: Provides the location in which to return the up-time.. + + :return: Zero (OK) on success; a negated errno value on failure. + + **Assumptions**: Called from the normal tasking context. The + implementation must provide whatever mutual exclusion is necessary + for correct operation. This can include disabling interrupts in + order to assure atomic register operations. + +.. c:function:: int up_alarm_cancel(FAR struct timespec *ts) + + Cancel the alarm and return the time of cancellation of the alarm. + These two steps need to be as nearly atomic as possible. + ``nxsched_timer_expiration()`` will not be called unless the alarm + is restarted with ``up_alarm_start()``. If, as a race condition, + the alarm has already expired when this function is called, then + time returned is the current time. + + :param ts: Location to return the expiration time. The current + time should be returned if the timer is not active. ``ts`` may + be ``NULL`` in which case the time is not returned + + :return: Zero (OK) on success; a negated errno value on failure. + + **Assumptions**: May be called from interrupt level handling or + from the normal tasking level. interrupts may need to be disabled + internally to assure non-reentrancy. + +.. c:function:: int up_alarm_start(FAR const struct timespec *ts) + + Start the alarm. ``nxsched_timer_expiration()`` will be called + when the alarm occurs (unless ``up_alarm_cancel`` is called to + stop it). + + :param ts: The time in the future at the alarm is expected to + occur. When the alarm occurs the timer logic will call + ``nxsched_timer_expiration()``. + + :return: Zero (OK) on success; a negated errno value on failure. + + **Assumptions**: May be called from interrupt level handling or + from the normal tasking level. Interrupts may need to be + disabled internally to assure non-reentrancy. + +.. c:function:: int up_timer_cancel(FAR struct timespec *ts) + +Cancel the interval timer and return the time remaining on the +timer. These two steps need to be as nearly atomic as possible. +``nxsched_timer_expiration()`` will not be called unless the timer +is restarted with ``up_timer_start()``. If, as a race condition, +the timer has already expired when this function is called, then +that pending interrupt must be cleared so that +``nxsched_timer_expiration()`` is not called spuriously and the +remaining time of zero should be returned. + +:param ts: Location to return the remaining time. Zero should be + returned if the timer is not active. + +:return: Zero (OK) on success; a negated errno value on failure. + +**Assumptions**: May be called from interrupt level handling or +from the normal tasking level. interrupts may need to be +disabled internally to assure non-reentrancy. + +.. c:function:: int up_timer_start(FAR const struct timespec *ts) + +Start the interval timer. ``nxsched_timer_expiration()`` will be +called at the completion of the timeout (unless +``up_timer_cancel()`` is called to stop the timing). + +:param ts: Provides the time interval until + ``nxsched_timer_expiration()`` is called. + +:return: Zero (OK) on success; a negated errno value on failure. + +**Assumptions**: May be called from interrupt level handling +or from the normal tasking level. Interrupts may need to be +disabled internally to assure non-reentrancy. + +Watchdog Timer Interfaces +========================= + +NuttX provides a general watchdog timer facility. This facility +allows the NuttX user to specify a watchdog timer function that +will run after a specified delay. The watchdog timer function will +run in the context of the timer interrupt handler. Because of +this, a limited number of NuttX interfaces are available to he +watchdog timer function. However, the watchdog timer function may +use ``mq_send()``, ``sigqueue()``, or ``kill()`` to communicate +with NuttX tasks. + +- :c:func:`wd_create`/:c:func:`wd_static` +- :c:func:`wd_delete` +- :c:func:`wd_start` +- :c:func:`wd_cancel` +- :c:func:`wd_gettime` +- Watchdog Timer Callback + +.. c:function:: WDOG_ID wd_create(void) + + The ``wd_create()`` function will create a timer + by allocating the appropriate resources for the watchdog. The + ``wd_create()`` function returns a pointer to a fully initialized, + dynamically allocated ``struct wdog_s`` instance (which is + ``typedef``'ed as ``WDOG_ID``); + + :return: Pointer to watchdog that may be used as a handle in subsequent + NuttX calls (i.e., the watchdog ID), or NULL if insufficient + resources are available to create the watchdogs. + +.. c:function:: void wd_static(FAR struct wdog_s *wdog) + + Performs the equivalent initialization of a + statically allocated ``struct wdog_s`` instance. No allocation is + performed in this case. The initializer definition, + ``WDOG_INITIALIZER`` is also available for initialization of + static instances of ``struct wdog_s``. NOTE: ``wd_static()`` is + also implemented as a macro definition. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks + provides the following comparable interface: + + .. code-block:: c + + WDOG_ID wdCreate (void); + + Differences from the VxWorks interface include: + + - The number of available watchdogs is fixed (configured at + initialization time). + +.. c:function:: int wd_delete(WDOG_ID wdog) + + Deallocate a watchdog + timer previously allocated via ``wd_create()``. The watchdog timer + will be removed from the timer queue if has been started. + + This function need not be called for statically allocated timers + (but it is not harmful to do so). + + :param wdog: The watchdog ID to delete. This is actually a pointer + to a watchdog structure. + + :return: Zero (``OK``) is returned on success; a negated ``errno`` value + is return to indicate the nature of any failure. + + **Assumptions/Limitations:** It is the responsibility of the + caller to assure that the watchdog is inactive before deleting it. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks + provides the following comparable interface: + + .. code-block:: c + + STATUS wdDelete (WDOG_ID wdog); + + Differences from the VxWorks interface include: + + - Does not make any checks to see if the watchdog is being used + before deallocating it (i.e., never returns ERROR). + +.. c:function:: int wd_start(WDOG_ID wdog, int delay, wdentry_t wdentry, \ + int argc, ...); + + This function adds a watchdog to the timer queue. + The specified watchdog function will be called from the interrupt + level after the specified number of ticks has elapsed. Watchdog + timers may be started from the interrupt level. + + Watchdog times execute in the context of the timer interrupt + handler. + + Watchdog timers execute only once. + + To replace either the timeout delay or the function to be + executed, call wd_start again with the same wdog; only the most + recent wd_start() on a given watchdog ID has any effect. + + :param wdog: Watchdog ID + :param delay: Delay count in clock ticks + :param wdentry: Function to call on timeout + :param argc: The number of uint32_t parameters to pass to wdentry. + :param ...: ``uint32_t`` size parameters to pass to ``wdentry`` + + **NOTE**: All parameters must be of type ``wdparm_t``. + + :return: Zero (``OK``) is returned on success; a negated ``errno`` value + is return to indicate the nature of any failure. + + **Assumptions/Limitations:** The watchdog routine runs in the + context of the timer interrupt handler and is subject to all ISR + restrictions. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks + provides the following comparable interface: + + .. code-block:: c + + STATUS wdStart (WDOG_ID wdog, int delay, FUNCPTR wdentry, int parameter); + + Differences from the VxWorks interface include: + + - The present implementation supports multiple parameters passed + to wdentry; VxWorks supports only a single parameter. The + maximum number of parameters is determined by + +.. c:function:: int wd_cancel(WDOG_ID wdog) + + This function cancels a currently running + watchdog timer. Watchdog timers may be canceled from the interrupt + level. + + :param wdog: ID of the watchdog to cancel. + + :return: ``OK`` or ``ERROR`` + + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks + provides the following comparable interface: + + .. code-block:: c + + STATUS wdCancel (WDOG_ID wdog); + +.. c:function:: int wd_gettime(WDOG_ID wdog) + + Returns the time remaining before + the specified watchdog expires. + + :param wdog: Identifies the watchdog that the request is for. + + :return: The time in system ticks remaining until the + watchdog time expires. Zero means either that wdog is not valid or + that the wdog has already expired. + +.. c:type:: void (*wdentry_t)(int argc, ...) + + **Watchdog Timer Callback**: when a watchdog expires, + the callback function with this type is + called, where ``argc`` is the number of + ``wdparm_t`` type arguments that follow. + + The arguments are passed as scalar ``wdparm_t`` values. For + systems where the ``sizeof(pointer) < sizeof(uint32_t)``, the + following union defines the alignment of the pointer within the + ``uint32_t``. For example, the SDCC MCS51 general pointer is + 24-bits, but ``uint32_t`` is 32-bits (of course). + + We always have ``sizeof(pointer) <= sizeof(uintptr_t)`` by + definition. + + .. code-block:: c + + union wdparm_u + { + FAR void *pvarg; /* The size one generic point */ + uint32_t dwarg; /* Big enough for a 32-bit value in any case */ + uintptr_t uiarg; /* sizeof(uintptr_t) >= sizeof(pointer) */ + }; + + #if UINTPTR_MAX >= UINT32_MAX + typedef uintptr_t wdparm_t; + #else + typedef uint32_t wdparm_t; + #endif diff --git a/doc/reference/os/wqueue.rst b/doc/reference/os/wqueue.rst new file mode 100644 index 00000000000..5749234ac7c --- /dev/null +++ b/doc/reference/os/wqueue.rst @@ -0,0 +1,307 @@ +=========== +Work Queues +=========== + +**Work Queues**. NuttX provides *work queues*. Work queues are +threads that service a queue of work items to be performed. They +are useful for off-loading work to a different threading context, +for delayed processing, or for serializing activities. + +Classes of Work Queues +====================== + +There are three different classes of +work queues, each with different properties and intended usage. +These class of work queues along with the common work queue +interface are described in the following paragraphs. + +High Priority Kernel Work queue +------------------------------- + +The dedicated high-priority +work queue is intended to handle delayed processing from interrupt +handlers. This work queue is required for some drivers but, if +there are no complaints, can be safely disabled. The high priority +worker thread also performs garbage collection -- completing any +delayed memory deallocations from interrupt handlers. If the +high-priority worker thread is disabled, then that clean up will +be performed either by (1) the low-priority worker thread, if +enabled, and if not (2) the IDLE thread instead (which runs at the +lowest of priority and may not be appropriate if memory +reclamation is of high priority) + +**Device Driver Bottom Half**. The high-priority worker thread is +intended to serve as the *bottom half* for device drivers. As a +consequence it must run at a very high, fixed priority rivalling +the priority of the interrupt handler itself. Typically, the high +priority work queue should be the highest priority thread in your +system (the default priority is 224). + +**Thread Pool**. The work queues can be configured to support +multiple, low-priority threads. This is essentially a *thread +pool* that provides multi-threaded servicing of the queue work. +This breaks the strict serialization of the "queue" (and hence, +the work queue is no longer a queue at all). + +Multiple worker threads are required to support, for example, I/O +operations that stall waiting for input. If there is only a single +thread, then the entire work queue processing would stall in such +cases. Such behavior is necessary to support asynchronous I/O, +AIO, for example. + +**Compared to the Low Priority Kernel Work Queue**. For less +critical, lower priority, application oriented worker thread +support, consider enabling the lower priority work queue. The +lower priority work queue runs at a lower priority, of course, but +has the added advantage that it supports *priority inheritance* +(if ``CONFIG_PRIORITY_INHERITANCE=y`` is also selected): The +priority of the lower priority worker thread can then be adjusted +to match the highest priority client. + +**Configuration Options**. + +- ``CONFIG_SCHED_HPWORK``. Enables the hight priority work queue. +- ``CONFIG_SCHED_HPNTHREADS``. The number of threads in the + high-priority queue's thread pool. Default: 1 +- ``CONFIG_SCHED_HPWORKPRIORITY``. The execution priority of the + high-priority worker thread. Default: 224 +- ``CONFIG_SCHED_HPWORKSTACKSIZE``. The stack size allocated for + the worker thread in bytes. Default: 2048. + +**Common Configuration Options**. These options apply to all work +queues: + +- ``CONFIG_SIG_SIGWORK`` The signal number that will be used to + wake-up the worker thread. This same signal is used with the + Default: 17 + +Low Priority Kernel Work Queue +------------------------------ + +This lower priority work queue +is better suited for more extended, application oriented +processing such as file system clean-up, memory garbage collection +and asynchronous I/O operations. + +**Compared to the High Priority Work Queue**. The lower priority +work queue runs at a lower priority than the high priority work +queue, of course, and so is inappropriate to serve as a driver +*bottom half*. It is, otherwise, very similar to the high priority +work queue and most of the discussion above for the high priority +work queue applies equally here. The lower priority work queue +does have one important, however, that make it better suited for +some tasks: + +**Priority Inheritance**. The lower priority worker thread(s) +support *priority inheritance* (if +CONFIG_PRIORITY_INHERITANCE is also selected): The priority of the +lower priority worker thread can then be adjusted to match the +highest priority client. + + **NOTE:** This priority inheritance feature is not automatic. + The lower priority worker thread will always a fixed priority + unless additional logic implements that calls + ``lpwork_boostpriority()`` to raise the priority of the lower + priority worker thread (typically called before scheduling the + work) and then calls the matching ``lpwork_restorepriority()`` + when the work is completed (typically called within the work + handler at the completion of the work). Currently, only the + NuttX asynchronous I/O logic uses this dynamic prioritization + feature. + +The higher priority worker thread, on the other hand, is intended +to serve as the *bottom half* for device drivers. As a consequence +must run at a very high, fixed priority. Typically, it should be +the highest priority thread in your system. + +**Configuration Options**. + +- ``CONFIG_SCHED_LPWORK``. If CONFIG_SCHED_LPWORK is selected + then a lower-priority work queue will be enabled. +- ``CONFIG_SCHED_LPNTHREADS``. The number of threads in the + low-priority queue's thread pool. Default: 1 +- ``CONFIG_SCHED_LPWORKPRIORITY``. The minimum execution priority + of the lower priority worker thread. The priority of the all + worker threads start at this priority. If priority inheritance + is in effect, the priority may be boosted from this level. + Default: 50. +- ``CONFIG_SCHED_LPWORKPRIOMAX``. The maximum execution priority + of the lower priority worker thread. Lower priority worker + threads will be started at ``CONFIG_SCHED_LPWORKPRIORITY`` but + their priority may be boosted due to priority inheritance. The + boosted priority of the low priority worker thread will not, + however, ever exceed ``CONFIG_SCHED_LPWORKPRIOMAX``. This limit + would be necessary, for example, if the higher priority worker + thread were to defer work to the lower priority thread. + Clearly, in such a case, you would want to limit the maximum + priority of the lower priority work thread. Default: 176. +- ``CONFIG_SCHED_LPWORKSTACKSIZE``. The stack size allocated for + the lower priority worker thread. Default: 2048. + +User-Mode Work Queue +-------------------- + +**Work Queue Accessibility**. The high- and low-priority worker +threads are kernel-mode threads. In the normal, *flat* NuttX +build, these work queues are are useful to application code and +may be shared. However, in the NuttX protected and kernel build +modes, kernel mode code is isolated and cannot be accessed from +user-mode code. + +**User-Mode Work Queue**. if either ``CONFIG_BUILD_PROTECTED`` or +``CONFIG_BUILD_KERNEL`` are selected, then the option to enable a +special user-mode work queue is enable. The interface to the +user-mode work queue is identical to the interface to the +kernel-mode work queues and the user-mode work queue is +functionally equivalent to the high priority work queue. It +differs in that its implementation does not depend on internal, +kernel-space facilities. + +**Configuration Options**. + +- ``CONFIG_LIB_USRWORK``. If CONFIG_LIB_USRWORK is also defined + then the user-mode work queue will be enabled. +- ``CONFIG_LIB_USRWORKPRIORITY``. The execution priority of the + user-mode priority worker thread. Default: 100 +- ``CONFIG_LIB_USRWORKSTACKSIZE``. The stack size allocated for + the lower priority worker thread. Default: 2048. + + +Common Work Queue Interfaces +============================ + +Work Queue IDs +-------------- + +**Work queue IDs**. All work queues use the identical interface +functions (at least identical in terms of the function +*signature*). The first parameter passed to the work queue +interface function identifies the work queue: + +**Kernel-Mode Work Queue IDs:** + +- ``HPWORK``. This ID of the high priority work queue that should + only be used for hi-priority, time-critical, driver bottom-half + functions. +- ``LPWORK``. This is the ID of the low priority work queue that + can be used for any purpose. if ``CONFIG_SCHED_LPWORK`` is not + defined, then there is only one kernel work queue and + ``LPWORK`` is equal to ``HPWORK``. + +**User-Mode Work Queue IDs:** + +- ``USRWORK``. This is the ID of the user-mode work queue that + can be used for any purpose by applications. In a flat build, + ``LPWORK`` is equal to ``LPWORK`` so that user applications + will use the lower priority work queue (if there is one). + +Work Queue Interface Types +-------------------------- + +- ``typedef void (*worker_t)(FAR void *arg);`` Defines the type + of the work callback. +- ``struct work_s``. Defines one entry in the work queue. This is + a client-allocated structure. Work queue clients should not + reference any field in this structure since they are subject to + change. The user only needs this structure in order to declare + instances of the work structure. Handling of all fields is + performed by the work queue interfaces described below. + +Work Queue Interfaces +--------------------- + +.. c:function:: int work_queue(int qid, FAR struct work_s *work, worker_t worker, \ + FAR void *arg, uint32_t delay) + + Queue work to be performed at a later time. All + queued work will be performed on the worker thread of execution + (not the caller's). + + The work structure is allocated and must be initialized to all + zero by the caller. Otherwise, the work structure is completely + managed by the work queue logic. The caller should never modify + the contents of the work queue structure directly. If + ``work_queue()`` is called before the previous work as been + performed and removed from the queue, then any pending work will + be canceled and lost. + + :param qid: The work queue ID. + :param work: The work structure to queue + :param worker: The worker callback to be invoked. The callback + will invoked on the worker thread of execution. + + :param arg: The argument that will be passed to the worker + callback function when it is invoked. + + :param delay: Delay (in system clock ticks) from the time queue + until the worker is invoked. Zero means to perform the work + immediately. + + :return: Zero is returned on success; a negated errno is returned on failure. + +.. c:function:: int work_cancel(int qid, FAR struct work_s *work) + + Cancel previously queued work. This removes work + from the work queue. After work has been cancelled, it may be + re-queue by calling ``work_queue()`` again. + + :param qid: The work queue ID. + :param work: The previously queue work structure to cancel. + + :return: Zero is returned on success; a negated ``errno`` is returned on + failure. + + - ``ENOENT``: There is no such work queued. + - ``EINVAL``: An invalid work queue was specified. + +.. c:function:: int work_signal(int qid) + + Signal the worker thread to process the work + queue now. This function is used internally by the work logic but + could also be used by the user to force an immediate re-assessment + of pending work. + + :param qid: The work queue ID. + + :return: Zero is returned on success; a negated errno is returned on failure. + +.. c:function:: bool work_available(FAR struct work_s *work) + + Check if the work structure is available. + + :param work: The work queue structure to check. + + :return: ``true`` if available; ``false`` if busy (i.e., there is still pending work). + +.. c:function:: int work_usrstart(void) + + The function is only available as a user + interface in the kernel-mode build. In the flat build, there is no + user-mode work queue; in the protected mode, the user-mode work + queue will automatically be started by the OS start-up code. But + in the kernel mode, each user process will be required to start is + own, private instance of the user-mode work thread using this + interface. + + :return: The task ID of the worker thread is returned on success. + A negated ``errno`` value is returned on failure. + +.. c:function:: void lpwork_boostpriority(uint8_t reqprio) + + Called by the work queue client to assure that + the priority of the low-priority worker thread is at least at the + requested level, ``reqprio``. This function would normally be + called just before calling ``work_queue()``. + + :param reqprio: Requested minimum worker thread priority. + +.. c:function:: void lpwork_restorepriority(uint8_t reqprio) + + This function is called to restore the priority + after it was previously boosted. This is often done by client + logic on the worker thread when the scheduled work completes. It + will check if we need to drop the priority of the worker thread. + + :param reqprio: Previously requested minimum worker thread + priority to be "unboosted". + diff --git a/doc/reference/user/01_task_control.rst b/doc/reference/user/01_task_control.rst new file mode 100644 index 00000000000..35036dc19aa --- /dev/null +++ b/doc/reference/user/01_task_control.rst @@ -0,0 +1,887 @@ +======================= +Task Control Interfaces +======================= + +**Tasks**. NuttX is a flat address OS. As such it does not support +*processes* in the way that, say, Linux does. NuttX only supports simple +threads running within the same address space. However, the programming +model makes a distinction between *tasks* and *pthreads*: + + - *tasks* are threads which have a degree of independence + - `pthreads <#Pthread>`__ share some resources. + +**File Descriptors and Streams**. This applies, in particular, in the +area of opened file descriptors and streams. When a task is started +using the interfaces in this section, it will be created with at most +three open files. + +If ``CONFIG_DEV_CONSOLE`` is defined, the first three file descriptors +(corresponding to stdin, stdout, stderr) will be duplicated for the new +task. Since these file descriptors are duplicated, the child task can +free close them or manipulate them in any way without effecting the +parent task. File-related operations (open, close, etc.) within a task +will have no effect on other tasks. Since the three file descriptors are +duplicated, it is also possible to perform some level of redirection. + +pthreads, on the other hand, will always share file descriptors with the +parent thread. In this case, file operations will have effect only all +pthreads the were started from the same parent thread. + +**Executing Programs within a File System**. NuttX also provides +internal interfaces for the execution of separately built programs that +reside in a file system. These internal interfaces are, however, +non-standard and are documented with the NuttX `binary +loader `__ and `NXFLAT `__. + +**Task Control Interfaces**. The following task control interfaces are +provided by NuttX: + +.. note:: + Maybe this can be converted into a table, or could otherwise + be replaced by the index if these are sectioned in this way. + +Non-standard task control interfaces inspired by VxWorks interfaces: + + - :c:func:`task_create` + - :c:func:`task_delete` + - :c:func:`task_restart` + +Non-standard extensions to VxWorks-like interfaces to support POSIX +`Cancellation +Points `__. + + - :c:func:`task_setcancelstate` + - :c:func:`task_setcanceltype` + - :c:func:`task_testcancel` + +Standard interfaces + + - :c:func:`exit` + - :c:func:`getpid` + +Standard ``vfork`` and ``exec[v|l]`` interfaces: + + - :c:func:`vfork` + - :c:func:`exec` + - :c:func:`execv` + - :c:func:`execl` + +Standard ``posix_spawn`` interfaces: + + - :c:func:`posix_spawn` and :c:func:`posix_spawnp` + - :c:func:`posix_spawn_file_actions_init` + - :c:func:`posix_spawn_file_actions_destroy` + - :c:func:`posix_spawn_file_actions_addclose` + - :c:func:`posix_spawn_file_actions_adddup2` + - :c:func:`posix_spawn_file_actions_addopen` + - :c:func:`posix_spawnattr_init` + - :c:func:`posix_spawnattr_getflags` + - :c:func:`posix_spawnattr_getschedparam` + - :c:func:`posix_spawnattr_getschedpolicy` + - :c:func:`posix_spawnattr_getsigmask` + - :c:func:`posix_spawnattr_setflags` + - :c:func:`posix_spawnattr_setschedparam` + - :c:func:`posix_spawnattr_setschedpolicy` + - :c:func:`posix_spawnattr_setsigmask` + +Non-standard task control interfaces inspired by ``posix_spawn``: + + - :c:func:`task_spawn` + - :c:func:`task_spawnattr_getstacksize` + - :c:func:`task_spawnattr_setstacksize` + - :c:func:`posix_spawn_file_actions_init` + +Functions +--------- + +.. c:function:: int task_create(char *name, int priority, int stack_size, main_t entry, char * const argv[]) + + This function creates and activates a new task with a + specified priority and returns its system-assigned ID. + + The entry address entry is the address of the "main" function of the + task. This function will be called once the C environment has been set + up. The specified function will be called with four arguments. Should + the specified routine return, a call to :c:func:`exit` will automatically be + made. + + Note that an arbitrary number of arguments may be passed to the spawned + functions. + + The arguments are copied (via ``strdup``) so that the life of the passed + strings is not dependent on the life of the caller to :c:func:`task_create`. + + The newly created task does not inherit scheduler characteristics from + the parent task: The new task is started at the default system priority + and with the ``SCHED_FIFO`` scheduling policy. These characteristics may be + modified after the new task has been started. + + The newly created task does inherit the first three file descriptors + (corresponding to stdin, stdout, and stderr) and redirection of standard + I/O is supported. + + :param name: Name of the new task + :param priority: Priority of the new task + :param stack_size: size (in bytes) of the stack needed + :param entry: Entry point of a new task + :param argv: A pointer to an array of input parameters. The array should + be terminated with a NULL argv[] value. If no parameters are + required, argv may be NULL. + + :return: the non-zero task ID of the new task or ERROR if memory is + insufficient or the task cannot be created + (```errno`` <#ErrnoAccess>`__ is not set). + + **Defined in:** ``sched.h`` + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks provides + the following similar interface: + + .. code-block:: c + + int taskSpawn(char *name, int priority, int options, int stackSize, FUNCPTR entryPt, + int arg1, int arg2, int arg3, int arg4, int arg5, + int arg6, int arg7, int arg8, int arg9, int arg10); + + The NuttX :c:func:`task_create` differs from VxWorks' :c:func:`taskSpawn` in the + following ways: + + - Interface name + - Various differences in types of arguments + - There is no options argument. + - A variable number of parameters can be passed to a task (VxWorks + supports ten). + +.. c:function:: int task_delete(pid_t pid) + + This function causes a specified task to cease to + exist. Its stack and TCB will be deallocated. This function is the + companion to ``task_create()``. This is the version of the function + exposed to the user; it is simply a wrapper around the internal, + ``nxtask_terminate()`` function. + + The logic in this function only deletes non-running tasks. If the + ``pid`` parameter refers to the currently running task, then processing + is redirected to ``exit()``. This can only happen if a task calls + ``task_delete()`` in order to delete itself. + + This function obeys the semantics of pthread cancellation: task deletion + is deferred if cancellation is disabled or if deferred cancellation is + supported (with `Cancellation + Points `__ + enabled). + + :param pid: The task ID of the task to delete. An ID of zero signifies + the calling task. Any attempt by the calling task will be + automatically re-directed to ``exit()``. + + :return: ``OK``, or ``ERROR`` if the task cannot be deleted. The + ```errno`` <#ErrnoAccess>`__ is set to indicate the nature of the + failure. This function can fail, for example, if the provided pid + does not correspond to a currently executing task. + + **Assumptions/Limitations:** + + ``task_delete()`` must be used with caution: If the task holds resources + (for example, allocated memory or semaphores needed by other tasks), + then ``task_delete()`` can strand those resources. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks provides + the following similar interface: + + The NuttX task_delete() differs from VxWorks' taskDelete() in the + following ways: + + - No support is provided for calling the tasks deletion routines + (because the VxWorks ``taskDeleteHookAdd()`` is not supported). + However, if ``atexit()`` or ``on_exit`` support is enabled, those + will be called when the task deleted. + - Deletion of self is supported, but only because ``task_delete()`` + will re-direct processing to ``exit()``. + +.. :c:funcion:: int task_restart(pid_t pid) + + This function *restarts* a task. The task is first + terminated and then reinitialized with same ID, priority, original entry + point, stack size, and parameters it had when it was first started. + + **NOTES:** + + #. The normal task exit clean up is not performed. For example, file + descriptors are not closed; any files opened prior to the restart + will remain opened after the task is restarted. + #. Memory allocated by the task before it was restart is not freed. A + task that is subject to being restart must be designed in such a way + as to avoid memory leaks. + #. Initialized data is not reset. All global or static data is left in + the same state as when the task was terminated. This *feature* may be + used by restart task to detect that it has been restarted, for + example. + + :param pid: The task ID of the task to delete. An ID of zero would + signify the calling task (However, support for a task to restart + itself has not been implemented). + + :return: ``OK``, or ``ERROR`` if the task ID is invalid or the task could not be + restarted. This function can fail if: (1) A pid of zero or the pid of + the calling task is provided (functionality not implemented) (2) The + pid is not associated with any task known to the system. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks provides + the following similar interface: + + .. code-block:: c + + STATUS taskRestart (int tid); + + The NuttX :c:func:`task_restart` differs from VxWorks' :c:func:`taskRestart` in the + following ways: + + - Restart of the currently running task is not supported by NuttX. + - The VxWorks description says that the ID, priority, etc. take the + value that they had when the task was *terminated*. + +.. c:function:: int task_setcancelstate(int state, int *oldstate) + + This function atomically sets + both the calling task's cancellability state to the indicated state and + returns the previous cancellability state at the location referenced by + oldstate. Legal values for state are TASK_CANCEL_ENABLE and + TASK_CANCEL_DISABLE. + + Any pending thread cancellation may occur at the time that the + cancellation state is set to TASK_CANCEL_ENABLE. + + The cancellability state and type of any newly created tasks are + TASK_CANCEL_ENABLE and TASK_CANCEL_DEFERRED respectively. + + :param state: New cancellation state. One of PTHREAD_CANCEL_ENABLE or + PTHREAD_CANCEL_DISABLE. + :param oldstate: Location to return the previous cancellation state. + + :return: Zero (``OK``) on success; ``ERROR`` is returned on any failure + with the ``errno`` value set appropriately: + + - ``ESRCH``. No thread could be found corresponding to that specified + by the given thread ID. + + **POSIX Compatibility:** This is a non-standard interface. It extends + the functionality of ``pthread_setcancelstate()`` to tasks and supports + use of ``task_delete()``. + +.. c:function:: int task_setcanceltype(int type, FAR int *oldtype); + + This function atomically both + sets the calling task's cancellability type to the indicated type and + returns the previous cancellability type at the location referenced by + ``oldtype``. Legal values for type are ``TASK_CANCEL_DEFERRED`` and + ``TASK_CANCEL_ASYNCHRONOUS``. + + The cancellability state and type of any newly created tasks are + ``TASK_CANCEL_ENABLE`` and ``TASK_CANCEL_DEFERRED`` respectively. + + :param type: New cancellation state. One of ``PTHREAD_CANCEL_DEFERRED`` + or ``PTHREAD_CANCEL_ASYNCHRONOUS``. + :param oldtype: Location to return the previous cancellation type. + + :return: Zero (``OK``) on success; ``ERROR`` is returned on any failure with the + ``errno`` value set appropriately: + + - ``ESRCH``. No thread could be found corresponding to that specified + by the given thread ID. + + **POSIX Compatibility:** This is a non-standard interface. It extends + the functionality of ``pthread_setcanceltype()`` to tasks and supports + use of ``task_delete()``. + +.. c:function:: void task_testcancel(void) + + Creates a `Cancellation + Point `__ + in the calling task. The ``task_testcancel()`` function has no effect if + cancellability is disabled. + + **POSIX Compatibility:** This is a non-standard interface. It extends + the functionality of ``pthread_testcancel()`` to tasks and supports use + of ``task_delete()``. + +.. c:function:: void exit(int code) +.. c:function:: void _exit(int code) + + .. #include + .. #include + + Causes the calling task to cease to exist + -- its stack and TCB will be deallocated. exit differs from \_exit in + that it flushes streams, closes file descriptors and will execute any + function registered with ``atexit()`` or ``on_exit()``. + + :param code: (ignored) + + **POSIX Compatibility:** This is equivalent to the ANSI interface: + + :: + + void exit(int code); + + And the UNIX interface: + + :: + + void _exit(int code); + + The NuttX exit() differs from ANSI exit() in the following ways: + + - The ``code`` parameter is ignored. + +.. c:function:: pid_t getpid(void) + +.. #include + + Returns the task ID of the calling task. + The task ID will be invalid if called at the interrupt level. + + :return: The task ID of the calling task. + + **POSIX Compatibility:** Compatible with the POSIX interface of the same + name. + +.. c:function:: pid_t vfork(void) + + The ``vfork()`` function has the same effect as + ``fork()``, except that the behavior is undefined if the process created + by ``vfork()`` either modifies any data other than a variable of type + ``pid_t`` used to store the return value from ``vfork()``, or returns + from the function in which ``vfork()`` was called, or calls any other + function before successfully calling ``_exit()`` or one of the ``exec`` + family of functions. + + NOTE: ``vfork()`` is not an independent NuttX feature, but is + implemented in architecture-specific logic (using only helper + functions from the NuttX core logic). As a result, ``vfork()`` may + not be available on all architectures. + + :return: Upon successful completion, ``vfork()`` returns 0 to + the child process and returns the process ID of the child process to the + parent process. Otherwise, -1 is returned to the parent, no child + process is created, and ``errno`` is set to indicate the error. + + **POSIX Compatibility:** Compatible with the BSD/Linux interface of the + same name. POSIX marks this interface as Obsolete. + +.. c:function:: int exec(FAR const char *filename, FAR char * const *argv, FAR const struct symtab_s *exports, int nexports) + + This non-standard, NuttX function is similar to + ``execv()`` and ``posix_spawn()`` but differs in the following ways; + + - Unlike ``execv()`` and ``posix_spawn()`` this function accepts symbol + table information as input parameters. This means that the symbol + table used to link the application prior to execution is provided by + the caller, not by the system. + - Unlike ``execv()``, this function always returns. + + This non-standard interface is included as a official NuttX API only + because it is needed in certain build modes: ``exec()`` is probably the + only want to load programs in the PROTECTED mode. Other file execution + APIs rely on a symbol table provided by the OS. In the PROTECTED build + mode, the OS cannot provide any meaningful symbolic information for + execution of code in the user-space blob so that is the ``exec()`` + function is really needed in that build case + + The interface is available in the FLAT build mode although it is not + really necessary in that case. It is currently used by some example code + under the ``apps/`` that that generate their own symbol tables for + linking test programs. So although it is not necessary, it can still be + useful. + + The interface would be completely useless and will not be supported in + the KERNEL build mode where the contrary is true: An application process + cannot provide any meaning symbolic information for use in linking a + different process. + + **NOTE**: This function is flawed and useless without + ``CONFIG_SCHED_ONEXIT`` and ``CONFIG_SCHED_HAVE_PARENT`` because without + those features there is then no mechanism to unload the module once it + exits. + + :param filename: The path to the program to be executed. If + ``CONFIG_LIB_ENVPATH`` is defined in the configuration, then this may + be a relative path from the current working directory. Otherwise, + ``path`` must be the absolute path to the program. + :param argv: A pointer to an array of string arguments. The end of the + array is indicated with a NULL entry. + :param exports: The address of the start of the caller-provided symbol + table. This symbol table contains the addresses of symbols exported + by the caller and made available for linking the module into the + system. + :param nexports: The number of symbols in the ``exports`` table. + + :return: Zero (OK) is returned on success; On any failure, ``exec()`` + will return -1 (``ERROR``) and will set the ``errno`` value + appropriately. + + **POSIX Compatibility:** This is a non-standard interface unique to + NuttX. Motivation for inclusion of this non-standard interface in + certain build modes is discussed above. + +.. c:function:: int execv(FAR const char *path, FAR char * const argv[]) + + The standard ``exec`` family of functions will replace + the current process image with a new process image. The new image will + be constructed from a regular, executable file called the new process + image file. There will be no return from a successful ``exec``, because + the calling process image is overlaid by the new process image. + + Simplified ``execl()`` and ``execv()`` functions are provided by NuttX + for compatibility. NuttX is a tiny embedded RTOS that does not support + processes and hence the concept of overlaying a tasks process image with + a new process image does not make any sense. In NuttX, these functions + are wrapper functions that: + + #. Call the non-standard ``binfmt`` function ``exec()``, and then + #. ``exit(0)``. + + Note the inefficiency when ``execv()`` or ``execl()`` is called in the + normal, two-step process: (1) first call ``vfork()`` to create a new + thread, then (2) call ``execv()`` or ``execl()`` to replace the new + thread with a program from the file system. Since the new thread will be + terminated by the ``execv()`` or ``execl()`` call, it really served no + purpose other than to support POSIX compatibility. + + The non-standard binfmt function ``exec()`` needs to have (1) a symbol + table that provides the list of symbols exported by the base code, and + (2) the number of symbols in that table. This information is currently + provided to ``exec()`` from ``execv()`` or ``execl()`` via NuttX + configuration settings: + + - ``CONFIG_LIBC_EXECFUNCS``: Enable ``execv()`` and ``execl()`` support + - ``CONFIG_EXECFUNCS_SYMTAB_ARRAY``: Name of the symbol table used by + ``execv()`` or ``execl()``. + - ``CONFIG_EXECFUNCS_NSYMBOLS_VAR``: Name of the ``int`` variable + holding the number of symbols in the symbol table + + As a result of the above, the current implementations of ``execl()`` and + ``execv()`` suffer from some incompatibilities that may or may not be + addressed in a future version of NuttX. Other than just being an + inefficient use of MCU resource, the most serious of these is that the + ``exec``'ed task will not have the same task ID as the ``vfork``'ed + function. So the parent function cannot know the ID of the ``exec``'ed + task. + + :param path: The path to the program to be executed. If + ``CONFIG_LIB_ENVPATH`` is defined in the configuration, then this may + be a relative path from the current working directory. Otherwise, + :param path: must be the absolute path to the program. + + :return: This function does not return on success. On + failure, it will return -1 (``ERROR``) and will set the ``errno`` value + appropriately. + + **POSIX Compatibility:** Similar with the POSIX interface of the same + name. There are, however, several compatibility issues as detailed in + the description above. + +.. c:function:: int execl(FAR const char *path, ...) + + ``execl()`` is functionally equivalent to + `execv() <#execv>`__, differing only in the form of its input + parameters. See the description of `execv() <#execv>`__ for additional + information. + + :param path: The path to the program to be executed. If + ``CONFIG_LIB_ENVPATH`` is defined in the configuration, then this may + be a relative path from the current working directory. Otherwise, + :param path: must be the absolute path to the program. + + :return: This function does not return on success. On + failure, it will return -1 (``ERROR``) and will set the ``errno`` value + appropriately. + + **POSIX Compatibility:** Similar with the POSIX interface of the same + name. There are, however, several compatibility issues as detailed in + the description of `execv() <#execv>`__. + +.. c:function:: int posix_spawn(FAR pid_t *pid, FAR const char *path, \ + FAR const posix_spawn_file_actions_t *file_actions, \ + FAR const posix_spawnattr_t *attr, \ + FAR char * const argv[], FAR char * const envp[]) + +.. c:function:: int posix_spawnp(FAR pid_t *pid, FAR const char *file, \ + FAR const posix_spawn_file_actions_t *file_actions, \ + FAR const posix_spawnattr_t *attr, \ + FAR char * const argv[], FAR char * const envp[]); + + The ``posix_spawn()`` and ``posix_spawnp()`` functions + will create a new, child task, constructed from a regular executable + file. + + :param pid: Upon successful completion, ``posix_spawn()`` and + ``posix_spawnp()`` will return the task ID of the child task to the + parent task, in the variable pointed to by a non-NULL ``pid`` + argument. If the ``pid`` argument is a null pointer, the process ID + of the child is not returned to the caller. + + :param path: The ``path`` argument to ``posix_spawn()`` is + the absolute path that identifies the file to execute. The ``file`` + argument to ``posix_spawnp()`` may also be a relative path and will + be used to construct a pathname that identifies the file to execute. + In the case of a relative path, the path prefix for the file will be + obtained by a search of the directories passed as the environment + variable PATH. + + NOTE: NuttX provides only one implementation: If + ``CONFIG_LIB_ENVPATH`` is defined, then only ``posix_spawnp()`` + behavior is supported; otherwise, only ``posix_spawn`` behavior is + supported. + + :param file_actions: If ``file_actions`` is a null pointer, then file + descriptors open in the calling process will remain open in the child + process (unless ``CONFIG_FDCLONE_STDIO`` is defined). If + ``file_actions`` is not NULL, then the file descriptors open in the + child process will be those open in the calling process as modified + by the spawn file actions object pointed to by ``file_actions``. + + :param attr: If the value of the ``attr`` parameter is ``NULL``, the all + default values for the POSIX spawn attributes will be used. + Otherwise, the attributes will be set according to the spawn flags. + The ``posix_spawnattr_t`` spawn attributes object type is defined in + ``spawn.h``. It will contains these attributes, not all of which are + supported by NuttX: + + - ``POSIX_SPAWN_SETPGROUP``: Setting of the new task's process group + is not supported. NuttX does not support process groups. + - ``POSIX_SPAWN_SETSCHEDPARAM``: Set new tasks priority to the + ``sched_param`` value. + - ``POSIX_SPAWN_SETSCHEDULER``: Set the new task's scheduler policy + to the ``sched_policy`` value. + - ``POSIX_SPAWN_RESETIDS`` Resetting of the effective user ID of the + child process is not supported. NuttX does not support effective + user IDs. + - ``POSIX_SPAWN_SETSIGMASK``: Set the new task's signal mask. + - ``POSIX_SPAWN_SETSIGDEF``: Resetting signal default actions is not + supported. NuttX does not support default signal actions. + + :param argv: ``argv[]`` is the argument list for the new task. + ``argv[]`` is an array of pointers to null-terminated strings. The + list is terminated with a null pointer. + + :param envp: The ``envp[]`` argument is not used by NuttX and may be + ``NULL``. In standard implementations, ``envp[]`` is an array of + character pointers to null-terminated strings that provide the + environment for the new process image. The environment array is + terminated by a null pointer. In NuttX, the ``envp[]`` argument is + ignored and the new task will inherit the environment of the parent + task unconditionally. + + :return: Zero on success. Otherwise, an error number will be returned as the + function return value to indicate the error: + + - ``EINVAL``: The value specified by ``file_actions`` or ``attr`` is + invalid. + - Any errors that might have been return if ``vfork()`` and + ``exec[l|v]()`` had been called. + + **Assumptions/Limitations:** + + - NuttX provides only ``posix_spawn()`` or ``posix_spawnp()`` behavior + depending upon the setting of ``CONFIG_LIB_ENVPATH``: If + ``CONFIG_LIB_ENVPATH`` is defined, then only ``posix_spawnp()`` + behavior is supported; otherwise, only ``posix_spawn()`` behavior is + supported. + - The ``envp`` argument is not used and the ``environ`` variable is not + altered (NuttX does not support the ``environ`` variable). + - Process groups are not supported (See ``POSIX_SPAWN_SETPGROUP`` + above). + - Effective user IDs are not supported (See ``POSIX_SPAWN_RESETIDS`` + above). + - Signal default actions cannot be modified in the newly task executed + because NuttX does not support default signal actions (See + ``POSIX_SPAWN_SETSIGDEF``). + + **POSIX Compatibility:** The value of the ``argv[0]`` received by the + child task is assigned by NuttX. For the caller of ``posix_spawn()``, + the provided argv[0] will correspond to ``argv[1]`` received by the new + task. + +.. c:function:: int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions) + + Initializes the object referenced by ``file_actions`` to an empty set of + file actions for subsequent use in a call to ``posix_spawn()`` or + ``posix_spawnp()``. + + **Input Parameters:** + + - ``file_actions``: The address of the ``posix_spawn_file_actions_t`` + to be initialized. + + **Returned Value:** On success, this function returns 0; on failure it + will return an error number from ````. + +.. c:function:: int posix_spawn_file_actions_destroy(FAR posix_spawn_file_actions_t *file_actions) + + Destroys the object referenced by ``file_actions`` which was previously + initialized by ``posix_spawn_file_actions_init()``, returning any + resources obtained at the time of initialization to the system for + subsequent reuse. A ``posix_spawn_file_actions_t`` may be reinitialized + after having been destroyed, but must not be reused after destruction, + unless it has been reinitialized. + + :param file_actions: The address of the ``posix_spawn_file_actions_t`` + to be destroyed. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawn_file_actions_addclose(FAR posix_spawn_file_actions_t *file_actions, int fd) + + Adds a *close* operation to the list of operations associated with the + object referenced by ``file_actions``, for subsequent use in a call to + ``posix_spawn()`` or ``posix_spawnp()``. The descriptor referred to by + ``fd`` is closed as if ``close()`` had been called on it prior to the + new child process starting execution. + + :param file_actions: The address of the ``posix_spawn_file_actions_t`` + object to which the *close* operation will be appended. + :param fd: The file descriptor to be closed. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawn_file_actions_adddup2(FAR posix_spawn_file_actions_t *file_actions, int fd1, int fd2) + + Adds a *dup2* operation to the list of operations associated with the + object referenced by ``file_actions``, for subsequent use in a call to + ``posix_spawn()`` or ``posix_spawnp()``. The descriptor referred to by + ``fd2`` is created as if ``dup2()`` had been called on ``fd1`` prior to + the new child process starting execution. + + :param file_actions: The address of the ``posix_spawn_file_actions_t`` + object to which the *dup2* operation will be appended. + :param fd1: The file descriptor to be be duplicated. The first file + descriptor to be argument to ``dup2()``. + :param fd2: The file descriptor to be be created. The second file + descriptor to be argument to ``dup2()``. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawn_file_actions_addopen(FAR posix_spawn_file_actions_t *file_actions, \ + int fd, FAR const char *path, int oflags, mode_t mode); + + Adds an *open* operation to the list of operations associated with the + object referenced by ``file_actions``, for subsequent use in a call to + ``posix_spawn()`` or ``posix_spawnp()``. The descriptor referred to by + ``fd`` is opened using the ``path``, ``oflag``, and ``mode`` arguments + as if ``open()`` had been called on it prior to the new child process + starting execution. The string path is copied by the + ``posix_spawn_file_actions_addopen()`` function during this process, so + storage need not be persistent in the caller. + + :param file_actions: The address of the ``posix_spawn_file_actions_t`` + object to which the *open* operation will be appended. + :param fd: The file descriptor to be opened. + :param path: The path to be opened. + :param oflags: Open flags. + :param mode: File creation mode/ + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_init(FAR posix_spawnattr_t *attr) + + The ``posix_spawnattr_init()`` function initializes the + object referenced by ``attr``, to an empty set of spawn attributes for + subsequent use in a call to ``posix_spawn()`` or ``posix_spawnp()``. + + Then the spawn attributes are no longer needed, they should be destroyed + by calling ``posix_spawnattr_destroyed()``. In NuttX, however, + ``posix_spawnattr_destroyed()`` is just stub: + + For portability, the convention of calling + ``posix_spawnattr_destroyed()`` when the attributes are not longer + needed should still be followed. + + :param attr: The address of the spawn attributes to be initialized. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_getflags(FAR const posix_spawnattr_t *attr, FAR short *flags) + + The ``posix_spawnattr_getflags()`` function will obtain + the value of the *spawn-flags* attribute from the attributes object + referenced by ``attr``. + + :param attr: The address spawn attributes to be queried. + :param flags: The location to return the spawn flags + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_getschedparam(FAR const posix_spawnattr_t *attr, FAR struct sched_param *param) + + The ``posix_spawnattr_getschedparam()`` function will + obtain the value of the *spawn-schedparam* attribute from the attributes + object referenced by ``attr``. + + :param attr: The address spawn attributes to be queried. + :param param: The location to return the *spawn-schedparam* value. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_getschedpolicy(FAR const posix_spawnattr_t *attr, FAR int *policy) + + The ``posix_spawnattr_getschedpolicy()`` function will + obtain the value of the *spawn-schedpolicy* attribute from the + attributes object referenced by ``attr``. + + :param attr: The address spawn attributes to be queried. + :param policy: The location to return the *spawn-schedpolicy* value. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_getsigmask(FAR const posix_spawnattr_t *attr, FAR sigset_t *sigmask) + + ``posix_spawnattr_getsigdefault()`` function will + obtain the value of the *spawn-sigmask* attribute from the attributes + object referenced by ``attr``. + + :param attr: The address spawn attributes to be queried. + :param sigmask: The location to return the *spawn-sigmask* value. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_setflags(FAR posix_spawnattr_t *attr, short flags) + + The ``posix_spawnattr_setflags()`` function will set + the *spawn-flags* attribute in an initialized attributes object + referenced by ``attr``. + + :param attr: The address spawn attributes to be used. + :param flags: The new value of the *spawn-flags* attribute. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_setschedparam(FAR posix_spawnattr_t *attr, FAR const struct sched_param *param) + + The ``posix_spawnattr_setschedparam()`` function will + set the *spawn-schedparam* attribute in an initialized attributes object + referenced by ``attr``. + + :param attr: The address spawn attributes to be used. + :param param: The new value of the *spawn-schedparam* attribute. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_setschedpolicy(FAR posix_spawnattr_t *attr, int policy) + + The ``posix_spawnattr_setschedpolicy()`` function will + set the *spawn-schedpolicy* attribute in an initialized attributes + object referenced by ``attr``. + + :param attr: The address spawn attributes to be used. + :param policy: The new value of the *spawn-schedpolicy* attribute. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawnattr_setsigmask(FAR posix_spawnattr_t *attr, FAR const sigset_t *sigmask) + + The ``posix_spawnattr_setsigmask()`` function will set + the *spawn-sigmask* attribute in an initialized attributes object + referenced by ``attr``. + + :param attr: The address spawn attributes to be used. + :param sigmask: The new value of the *spawn-sigmask* attribute. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int task_spawn(FAR pid_t *pid, FAR const char *name, main_t entry, \ + FAR const posix_spawn_file_actions_t *file_actions, \ + FAR const posix_spawnattr_t *attr, \ + FAR char * const argv[], FAR char * const envp[]) + + The ``task_spawn()`` function will create a new, child + task, where the entry point to the task is an address in memory. + + :param pid: Upon successful completion, ``task_spawn()`` will return the + task ID of the child task to the parent task, in the variable pointed + to by a non-NULL ``pid`` argument. If the ``pid`` argument is a null + pointer, the process ID of the child is not returned to the caller. + + :param name: The name to assign to the child task. + + :param entry: The child task's entry point (an address in memory). + + :param file_actions: If ``file_actions`` is a null pointer, then file + descriptors open in the calling process will remain open in the child + process (unless ``CONFIG_FDCLONE_STDIO`` is defined). If + ``file_actions`` is not NULL, then the file descriptors open in the + child process will be those open in the calling process as modified + by the spawn file actions object pointed to by ``file_actions``. + + :param attr: If the value of the ``attr`` parameter is ``NULL``, the all + default values for the POSIX spawn attributes will be used. + Otherwise, the attributes will be set according to the spawn flags. + The ``posix_spawnattr_t`` spawn attributes object type is defined in + ``spawn.h``. It will contains these attributes, not all of which are + supported by NuttX: + + - ``POSIX_SPAWN_SETPGROUP``: Setting of the new task's process group + is not supported. NuttX does not support process groups. + - ``POSIX_SPAWN_SETSCHEDPARAM``: Set new tasks priority to the + ``sched_param`` value. + - ``POSIX_SPAWN_SETSCHEDULER``: Set the new task's scheduler policy + to the ``sched_policy`` value. + - ``POSIX_SPAWN_RESETIDS`` Resetting of the effective user ID of the + child process is not supported. NuttX does not support effective + user IDs. + - ``POSIX_SPAWN_SETSIGMASK``: Set the new task's signal mask. + - ``POSIX_SPAWN_SETSIGDEF``: Resetting signal default actions is not + supported. NuttX does not support default signal actions. + + And the non-standard: + + - ``TASK_SPAWN_SETSTACKSIZE``: Set the stack size for the new task. + + :param argv: ``argv[]`` is the argument list for the new task. + ``argv[]`` is an array of pointers to null-terminated strings. The + list is terminated with a null pointer. + + :param envp: The ``envp[]`` argument is not used by NuttX and may be + ``NULL``. + + :return: ``task_spawn()`` will return zero on success. + Otherwise, an error number will be returned as the function return value + to indicate the error: + + **POSIX Compatibility:** This is a non-standard interface inspired by + ``posix_spawn()``. + +.. c:function:: int task_spawnattr_getstacksize(FAR const posix_spawnattr_t *attr, FAR size_t *stacksize) + + The ``task_spawnattr_getstacksize()`` function will + obtain the value of the *spawn-stacksize* attribute from the attributes + object referenced by ``attr``. + + :param attr: The address spawn attributes to be queried. + :param policy: The location to return the *spawn-stacksize* value. + + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int task_spawnattr_setstacksize(FAR posix_spawnattr_t *attr, size_t stacksize) + + The ``task_spawnattr_setstacksize()`` function will set + the *spawn-stacksize* attribute in an initialized attributes object + referenced by ``attr``. + + :param attr: The address spawn attributes to be used. + :param policy: The new value of the *spawn-stacksize* attribute. + :return: On success, this function returns 0; on failure it + will return an error number from ```` + +.. c:function:: int posix_spawn_file_actions_init(FAR posix_spawn_file_actions_t *file_actions); + + The ``posix_spawn_file_actions_init()`` function + initializes the object referenced by ``file_actions`` to an empty set of + file actions for subsequent use in a call to ``posix_spawn()`` or + ``posix_spawnp()``. + + :param file_actions: The address of the ``posix_spawn_file_actions_t`` + to be initialized. + :return: On success, this function returns 0; on failure it + will return an error number from ````. diff --git a/doc/reference/user/02_task_scheduling.rst b/doc/reference/user/02_task_scheduling.rst new file mode 100644 index 00000000000..004ea59fe85 --- /dev/null +++ b/doc/reference/user/02_task_scheduling.rst @@ -0,0 +1,180 @@ +Task Scheduling Interfaces +************************** + +By default, NuttX performs strict priority scheduling: Tasks of higher +priority have exclusive access to the CPU until they become blocked. At +that time, the CPU is available to tasks of lower priority. Tasks of +equal priority are scheduled FIFO. + +Optionally, a Nuttx task or thread can be configured with round-robin or +*sporadic* scheduler. The round-robin is similar to priority scheduling +*except* that tasks with equal priority and share CPU time via +*time-slicing*. The time-slice interval is a constant determined by the +configuration setting ``CONFIG_RR_INTERVAL`` to a positive, non-zero +value. Sporadic scheduling scheduling is more complex, varying the +priority of a thread over a *replenishment* period. Support for sporadic +scheduling is enabled by the configuration option +``CONFIG_SCHED_SPORADIC``. + +The OS interfaces described in the following paragraphs provide a POSIX- +compliant interface to the NuttX scheduler: + + - :c:func:`sched_setparam` + - :c:func:`sched_getparam` + - :c:func:`sched_setscheduler` + - :c:func:`sched_getscheduler` + - :c:func:`sched_yield` + - :c:func:`sched_get_priority_max` + - :c:func:`sched_get_priority_min` + - :c:func:`sched_get_rr_interval` + +Functions +--------- + +.. c:function:: int sched_setparam(pid_t pid, FAR const struct sched_param *param) + + This function sets the priority of the task specified + by pid input parameter. + + :param pid: The task ID of the task. If ``pid`` is zero, the priority of + the calling task is set. + :param param: A structure whose member ``sched_priority`` is the integer + priority. The range of valid priority numbers is from + ``SCHED_PRIORITY_MIN`` through ``SCHED_PRIORITY_MAX``. + + :return: On success, sched_setparam() returns 0 (``OK``). On + error, -1 (``ERROR``) is returned, and ```errno`` <#ErrnoAccess>`__ is + set appropriately. + + - ``EINVAL``. The parameter ``param`` is invalid or does not make sense + for the current scheduling policy. + - ``EPERM``. The calling task does not have appropriate privileges. + - ``ESRCH``. The task whose ID is ``pid`` could not be found. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - The range of priority values for the POSIX call is 0 to 255. + + .. note:: Setting a task's priority to the same value has the similar effect + to ``sched_yield()``: The task will be moved to after all other tasks + with the same priority. + +.. c:function:: int sched_getparam(pid_t pid, FAR struct sched_param *param) + + This function gets the scheduling priority of the task + specified by pid. + + :param pid: The task ID of the task. If pid is zero, the priority of the + calling task is returned. + :param param: A structure whose member ``sched_priority`` is the integer + priority. The task's priority is copied to the ``sched_priority`` + element of this structure. + + :return: 0 (``OK``) if successful, otherwise -1 (``ERROR``). + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_setscheduler (pid_t pid, int policy, const struct sched_param *param) + + ``sched_setscheduler()`` sets both the scheduling + policy and the priority for the task identified by ``pid``. If ``pid`` + equals zero, the scheduler of the calling thread will be set. The + parameter ``param`` holds the priority of the thread under the new + policy. + + :param pid: The task ID of the task. If ``pid`` is zero, the priority of + the calling task is set. + :param policy: Scheduling policy requested (either ``SCHED_FIFO`` or + ``SCHED_RR``). + :param param: A structure whose member ``sched_priority`` is the integer + priority. The range of valid priority numbers is from + ``SCHED_PRIORITY_MIN`` through ``SCHED_PRIORITY_MAX``. + + :return: On success, ``sched_setscheduler()`` returns ``OK`` + (zero). On error, ``ERROR`` (-1) is returned, and + ``errno`` is set appropriately: + + - ``EINVAL``: The scheduling ``policy`` is not one of the recognized + policies. + - ``ESRCH``: The task whose ID is ``pid`` could not be found. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_getscheduler (pid_t pid) + + ``sched_getscheduler()`` returns the scheduling policy + currently applied to the task identified by ``pid``. If ``pid`` equals + zero, the policy of the calling process will be retrieved. + + :param pid: The task ID of the task to query. If ``pid`` is zero, the + calling task is queried. + + :return: On success, ``sched_getscheduler()`` returns the policy for the task + (either ``SCHED_FIFO`` or ``SCHED_RR``). On error, ``ERROR`` (-1) is + returned, and ``errno`` is set appropriately: + + - ``ESRCH``: The task whose ID is pid could not be found. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_yield(void) + + This function forces the calling task to give up the + CPU (only to other tasks at the same priority). + + :return: 0 (``OK``) or -1 (``ERROR``) + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_get_priority_max (int policy) + + This function returns the value of the highest possible + task priority for a specified scheduling policy. + + :param policy: Scheduling policy requested. + + :return: The maximum priority value or -1 (``ERROR``). + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_get_priority_min (int policy) + + This function returns the value of the lowest possible + task priority for a specified scheduling policy. + + :param policy: Scheduling policy requested. + + :return: The minimum priority value or -1 (``ERROR``) + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sched_get_rr_interval (pid_t pid, struct timespec *interval) + + ``sched_rr_get_interval()`` writes the timeslice + interval for task identified by ``pid`` into the timespec structure + pointed to by ``interval``. If pid is zero, the timeslice for the + calling process is written into 'interval. The identified process should + be running under the SCHED_RR scheduling policy.' + + :param pid: The task ID of the task. If pid is zero, the priority of the + calling task is returned. + :param interval: A structure used to return the time slice. + + :return: On success, sched_rr_get_interval() returns OK (0). + On error, ERROR (-1) is returned, and ``errno`` is + set to: + + - ``EFAULT``: Cannot copy to interval + - ``EINVAL``: Invalid pid. + - ``ENOSYS``: The system call is not yet implemented. + - ``ESRCH``: The process whose ID is pid could not be found. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. diff --git a/doc/reference/user/03_task_control.rst b/doc/reference/user/03_task_control.rst new file mode 100644 index 00000000000..0fac3165865 --- /dev/null +++ b/doc/reference/user/03_task_control.rst @@ -0,0 +1,458 @@ +======================= +Task Control Interfaces +======================= + +.. warning:: This section name is duplicate with the first, how should it be named? + +- **Scheduler locking interfaces**. These *non-standard* interfaces are + used to enable and disable pre-emption and to test is pre-emption is + currently enabled. + + - :c:func:`sched_lock` + - :c:func:`sched_unlock` + - :c:func:`sched_lockcount` + +- **Task synchronization interfaces** are used to wait for termination of child tasks. + + - :c:func:`waitpid` + - :c:func:`waitid` + - :c:func:`wait` + +- **Task Exit Hooks** may be used to + register callback functions that are executed when a *task group* + terminates. A task group is the functional analog of a process: It is + a group that consists of the main task thread and of all of the + pthreads created by the main task thread or any of the other pthreads + within the task group. Members of a task group share certain + resources such as environment variables, file descriptors, ``FILE`` + streams, sockets, pthread keys and open message queues. + + - :c:func:`atexit` + - :c:func:`on_exit` + + .. note:: + Behavior of features related to task group's depend of + NuttX configuration settings. See the discussion of "Parent and + Child Tasks," below. See also the\ `NuttX + Tasking `__\ page + and the\ `Tasks vs. Threads + FAQ `__\ for + additional information on tasks and threads in NuttX. + + A *task group* terminates when the last thread within the group + exits. + +Parent and Child Tasks +====================== + +The task synchronization interfaces +historically depend upon parent and child relationships between tasks. +But default, NuttX does not use any parent/child knowledge. However, +there are three important configuration options that can change that. + + - ``CONFIG_SCHED_HAVE_PARENT``: If this setting is defined, then it + instructs NuttX to remember the task ID of the parent task when each + new child task is created. This support enables some additional + features (such as ``SIGCHLD``) and modifies the behavior of other + interfaces. For example, it makes ``waitpid()`` more standards + complete by restricting the waited-for tasks to the children of the + caller. + + - ``CONFIG_SCHED_CHILD_STATUS``: If this option is selected, then + the exit status of the child task will be retained after the child + task exits. This option should be selected if you require knowledge + of a child process's exit status. Without this setting, ``wait()``, + ``waitpid()`` or ``waitid()`` may fail. For example, if you do: + + #. Start child task + #. Wait for exit status (using :c:func:`wait`, :c:func:`waitpid` or + :c:func:`waitid`). + + This may fail because the child task may run to completion before the + wait begins. There is a non-standard work-around in this case: The + above sequence will work if you disable pre-emption using + :c:func:`sched_lock` prior to starting the child task, then re-enable + pre-emption with :c:func:`sched_unlock` after the wait completes. This + works because the child task is not permitted to run until the wait + is in place. + + The standard solution would be to enable + ``CONFIG_SCHED_CHILD_STATUS``. In this case the exit status of the + child task is retained after the child exits and the wait will + successful obtain the child task's exit status whether it is called + before the child task exits or not. + + - ``CONFIG_PREALLOC_CHILDSTATUS``. To prevent runaway child status + allocations and to improve allocation performance, child task exit + status structures are pre-allocated when the system boots. This + setting determines the number of child status structures that will be + pre-allocated. If this setting is not defined or if it is defined to + be zero then a value of 2\*\ ``MAX_TASKS`` is used. + + Note that there cannot be more that ``CONFIG_MAX_TASKS`` tasks in + total. However, the number of child status structures may need to be + significantly larger because this number includes the maximum number + of tasks that are running PLUS the number of tasks that have exit'ed + without having their exit status reaped (via :c:func:`wait`, + :c:func:`waitpid` or :c:func:`waitid`). + + Obviously, if tasks spawn children indefinitely and never have the + exit status reaped, then you may have a memory leak! (See **Warning** + below) + +.. warning:: If you enable the ``CONFIG_SCHED_CHILD_STATUS`` feature, + then your application must either (1) take responsibility for reaping + the child status with ``wait()``, ``waitpid()`` or ``waitid()``, or (2) + suppress retention of child status. If you do not reap the child status, + then you have a memory leak and your system will eventually fail. + +Retention of child status can be suppressed on the parent using logic +like: + +.. code-block:: c + + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_NOCLDWAIT; + int ret = sigaction(SIGCHLD, &sa, NULL); + +Functions +========= + +.. c:function:: int sched_lock(void) + + Disables context switching by Disabling + addition of new tasks to the ready-to-run task list. The task that calls + this function will be the only task that is allowed to run until it + either calls sched_unlock (the appropriate number of times) or until it + blocks itself. + + :return: OK or ERROR. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks provides + the comparable interface: + + .. code-block:: c + + STATUS taskLock(void); + +.. c:function:: int sched_unlock(void) + + Decrements the preemption lock count. + Typically this is paired with sched_lock() and concludes a critical + section of code. Preemption will not be unlocked until sched_unlock() + has been called as many times as sched_lock(). When the lockCount is + decremented to zero, any tasks that were eligible to preempt the current + task will execute. + + :return: OK or ERROR. + + **POSIX Compatibility:** This is a NON-POSIX interface. VxWorks provides + the comparable interface: + + .. code-block:: c + + STATUS taskUnlock(void); + +.. c:function:: int32_t sched_lockcount(void) + + Returns the current value of the + lockCount. If zero, preemption is enabled; if non-zero, this value + indicates the number of times that sched_lock() has been called on this + thread of execution. + + :return: The current value of the lockCount. + + **POSIX Compatibility:** None. + +.. c:function:: ipid_t waitpid(pid_t pid, int *stat_loc, int options) + + .. note:: + The following discussion is a general description of the + ``waitpid()`` interface. However, as of this writing, the + implementation of ``waitpid()`` is incomplete (but usable). If + ``CONFIG_SCHED_HAVE_PARENT`` is defined, ``waitpid()`` will be a + little more compliant to specifications. Without + ``CONFIG_SCHED_HAVE_PARENT``, ``waitpid()`` simply supports waiting + for any task to complete execution. With + ``CONFIG_SCHED_HAVE_PARENT``, ``waitpid()`` will use ``SIGCHLD`` and + can, therefore, wait for any child of the parent to complete. The + implementation is incomplete in either case, however: NuttX does not + support any concept of process groups. Nor does NuttX retain the + status of exited tasks so if ``waitpid()`` is called after a task has + exited, then no status will be available. The options argument is + currently ignored. + + The ``waitpid()`` functions will obtain status information pertaining to + one of the caller's child processes. The ``waitpid()`` function will + suspend execution of the calling thread until status information for one + of the terminated child processes of the calling process is available, + or until delivery of a signal whose action is either to execute a + signal-catching function or to terminate the process. If more than one + thread is suspended in ``waitpid()`` awaiting termination of the same + process, exactly one thread will return the process status at the time + of the target process termination. If status information is available + prior to the call to ``waitpid()``, return will be immediate. + + **NOTE**: Because ``waitpid()`` is not fully POSIX compliant, it must be + specifically enabled by setting ``CONFIG_SCHED_WAITPID`` in the NuttX + configuration file. + + :param pid: The task ID of the thread to wait for + :param stat_loc: The location to return the exit status + :param options: ignored + + The ``pid`` argument specifies a set of child processes for which status + is requested. The ``waitpid()`` function will only return the status of + a child process from this set: + + - If ``pid`` is equal to ``(pid_t)-1``), status is requested for any + child process. In this respect, ``waitpid()`` is then equivalent to + ``wait()``. + - If ``pid`` is greater than 0, it specifies the process ID of a single + child process for which status is requested. + - If ``pid`` is 0, status is requested for any child process whose + process group ID is equal to that of the calling process. + - If ``pid`` is less than ``(pid_t)-1``), status is requested for any + child process whose process group ID is equal to the absolute value + of pid. + + The ``options`` argument is constructed from the bitwise-inclusive OR of + zero or more of the following flags, defined in the ```` + header: + + - ``WCONTINUED``. The ``waitpid()`` function will report the status of + any continued child process specified by pid whose status has not + been reported since it continued from a job control stop. + - ``WNOHANG``. The ``waitpid()`` function will not suspend execution of + the calling thread if status is not immediately available for one of + the child processes specified by ``pid``. + - ``WUNTRACED``. The status of any child processes specified by ``pid`` + that are stopped, and whose status has not yet been reported since + they stopped, will also be reported to the requesting process. + + If the calling process has ``SA_NOCLDWAIT`` set or has ``SIGCHLD`` set + to ``SIG_IGN``, and the process has no unwaited-for children that were + transformed into zombie processes, the calling thread will block until + all of the children of the process containing the calling thread + terminate, and ``waitpid()`` will fail and set ``errno`` to ``ECHILD``. + + If ``waitpid()`` returns because the status of a child process is + available, these functions will return a value equal to the process ID + of the child process. In this case, if the value of the argument + stat_loc is not a null pointer, information will be stored in the + location pointed to by ``stat_loc``. The value stored at the location + pointed to by ``stat_loc`` will be 0 if and only if the status returned + is from a terminated child process that terminated by one of the + following means: + + #. The process returned 0 from ``main()``. + #. The process called ``_exit()`` or ``exit()`` with a status argument + of 0. + #. The process was terminated because the last thread in the process + terminated. + + Regardless of its value, this information may be interpreted using the + following macros, which are defined in ```` and evaluate to + integral expressions; the ``stat_val`` argument is the integer value + pointed to by ``stat_loc``. + + - ``WIFEXITED(stat_val)``. Evaluates to a non-zero value if status was + returned for a child process that terminated normally. + - ``WEXITSTATUS(stat_val)``. If the value of ``WIFEXITED(stat_val)`` is + non-zero, this macro evaluates to the low-order 8 bits of the status + argument that the child process passed to ``_exit()`` or ``exit()``, + or the value the child process returned from ``main()``. + - ``WIFSIGNALED(stat_val)``. Evaluates to a non-zero value if status + was returned for a child process that terminated due to the receipt + of a signal that was not caught (see >signal.h<). + - ``WTERMSIG(stat_val)``. If the value of ``WIFSIGNALED(stat_val)`` is + non-zero, this macro evaluates to the number of the signal that + caused the termination of the child process. + - ``WIFSTOPPED(stat_val)``. Evaluates to a non-zero value if status was + returned for a child process that is currently stopped. + - ``WSTOPSIG(stat_val)``. If the value of ``WIFSTOPPED(stat_val)`` is + non-zero, this macro evaluates to the number of the signal that + caused the child process to stop. + - ``WIFCONTINUED(stat_val)``. Evaluates to a non-zero value if status + was returned for a child process that has continued from a job + control stop. + + :return: + If ``waitpid()`` returns because the status of a child process is + available, it will return a value equal to the process ID of the child + process for which status is reported. + + If ``waitpid()`` returns due to the delivery of a signal to the calling + process, -1 will be returned and ``errno`` set to ``EINTR``. + + If ``waitpid()`` was invoked with WNOHANG set in options, it has at + least one child process specified by pid for which status is not + available, and status is not available for any process specified by pid, + 0 is returned. + + Otherwise, ``(pid_t)-1errno`` set to indicate the error: + + - ``ECHILD``. The process specified by ``pid`` does not exist or is not + a child of the calling process, or the process group specified by + ``pid`` does not exist or does not have any member process that is a + child of the calling process. + - ``EINTR``. The function was interrupted by a signal. The value of the + location pointed to by ``stat_loc`` is undefined. + - ``EINVAL``. The ``options`` argument is not valid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name, but the implementation is incomplete (as detailed above). + +.. c:function:: int waitid(idtype_t idtype, id_t id, FAR siginfo_t *info, int options) + + .. note:: + + The following discussion is a general description of the ``waitid()`` + interface. However, as of this writing, the implementation of + ``waitid()`` is incomplete (but usable). If + ``CONFIG_SCHED_HAVE_PARENT`` is defined, ``waitid()`` will be a + little more compliant to specifications. ``waitpid()`` simply + supports waiting a specific child task (``P_PID`` or for any child + task ``P_ALL`` to complete execution. ``SIGCHLD`` is used. The + implementation is incomplete in either case, however: NuttX does not + support any concept of process groups. Nor does NuttX retain the + status of exited tasks so if ``waitpid()`` is called after a task has + exited, then no status will be available. The options argument is + currently ignored. + + The ``waitid()`` function suspends the calling thread until one child of + the process containing the calling thread changes state. It records the + current state of a child in the structure pointed to by ``info``. If a + child process changed state prior to the call to ``waitid()``, + ``waitid()`` returns immediately. If more than one thread is suspended + in ``wait()`` or ``waitpid()`` waiting termination of the same process, + exactly one thread will return the process status at the time of the + target process termination + + The ``idtype`` and ``id`` arguments are used to specify which children + ``waitid()`` will wait for. + + - If ``idtype`` is P_PID, ``waitid()`` will wait for the child with a + process ID equal to (pid_t)``id``. + - If ``idtype`` is P_PGID, ``waitid()`` will wait for any child with a + process group ID equal to (pid_t)``id``. + - If ``idtype`` is P_ALL, ``waitid()`` will wait for any children and + ``id`` is ignored. + + The ``options`` argument is used to specify which state changes + ``waitid()`` will will wait for. It is formed by OR-ing together one or + more of the following flags: + + - ``WEXITED``: Wait for processes that have exited. + - ``WSTOPPED``: Status will be returned for any child that has stopped + upon receipt of a signal. + - ``WCONTINUES``: Status will be returned for any child that was + stopped and has been continued. + - ``WNOHANG``: Return immediately if there are no children to wait for. + - ``WNOWAIT``: Keep the process whose status is returned in ``info`` in + a waitable state. This will not affect the state of the process; the + process may be waited for again after this call completes. + + The ``info`` argument must point to a ``siginfo_t`` structure. If + ``waitid()`` returns because a child process was found that satisfied + the conditions indicated by the arguments ``idtype`` and options, then + the structure pointed to by ``info`` will be filled in by the system + with the status of the process. The ``si_signo`` member will always be + equal to ``SIGCHLD``. + + :return: If ``waitid()`` returns due to the change of state + of one of its children, 0 is returned. Otherwise, -1 is returned and + ``errno`` is set to indicate the error. + + The ``waitid()`` function will fail if: + + - ``ECHILD``: + - ``EINTR``: + - ``EINVAL``: An invalid value was specified for ``options``, or + ``idtype`` and ``id`` specify an invalid set of processes. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name, but the implementation is incomplete (as detailed in the + description above). + +.. c:function:: pid_t wait(FAR int *stat_loc) + + .. note:: + The following discussion is a general description of the :c:func:`wait` + interface. However, as of this writing, the implementation of + :c:func:`wait` is incomplete (but usable). :c:func:`wait` is based + on :c:func:`waitpid` (see description for further information). + + The ``wait()`` function will suspend execution of the calling thread + until status information for one of its terminated child processes is + available, or until delivery of a signal whose action is either to + execute a signal-catching function or to terminate the process. If more + than one thread is suspended in ``wait()`` awaiting termination of the + same process, exactly one thread will return the process status at the + time of the target process termination. If status information is + available prior to the call to\ ``wait()``, return will be immediate. + + The ``waitpid()`` function will behave identically to ``wait()``, if its + ``pid`` argument is (pid_t)-1 and the options argument is 0. Otherwise, + its behavior will be modified by the values of the ``pid`` and + ``options`` arguments. + + :param stat_loc: The location to return the exit status + :return: See the values returned by :c:func:`waitpid` + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name, but the implementation is incomplete (as detailed in the + description ```waitpaid()`` <#waitpid>`__). + +.. c:function:: int atexit(void (*func)(void)) + + Registers a function to be called at program exit. The + ``atexit()`` function registers the given function to be called at + normal process termination, whether via ``exit()`` or via return from + the program's ``main()``. + + .. note:: ``CONFIG_SCHED_ATEXIT`` must be defined to enable this function. + + :param func: A pointer to the function to be called when the task exits. + :return: On success, ``atexit()`` returns OK (0). On error, + ERROR (-1) is returned, and ```errno`` <#ErrnoAccess>`__ is set to + indicate the cause of the failure. + + **POSIX Compatibility:** Comparable to the ISO C interface of the same + name. Limitations in the current implementation: + + #. Only a single ``atexit`` function can be registered unless + ``CONFIG_SCHED_ATEXIT_MAX`` defines a larger number. + #. ``atexit()`` functions are not inherited when a new task is created. + +.. c:function:: int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg) + + Registers a function to be called at program exit. The + ``on_exit()`` function registers the given function to be called at + normal process termination, whether via ``exit()`` or via return from + the program's ``main()``. The function is passed the status argument + given to the last call to ``exit()`` and the ``arg`` argument from + ``on_exit()``. + + .. note: ``CONFIG_SCHED_ONEXIT`` must be defined to enable this + function + + :param func: A pointer to the function to be called when the task exits. + :param arg: An argument that will be provided to the ``on_exit()`` + function when the task exits. + + :return: On success, ``on_exit()`` returns OK (0). On error, + ERROR (-1) is returned, and ```errno`` <#ErrnoAccess>`__ is set to + indicate the cause of the failure. + + **POSIX Compatibility:** This function comes from SunOS 4, but is also + present in libc4, libc5 and glibc. It no longer occurs in Solaris (SunOS + 5). Avoid this function, and use the standard ``atexit()`` instead. + + #. Only a single ``on_exit`` function can be registered unless + ``CONFIG_SCHED_ONEXIT_MAX`` defines a larger number. + #. ``on_exit()`` functions are not inherited when a new task is created. diff --git a/doc/reference/user/04_message_queue.rst b/doc/reference/user/04_message_queue.rst new file mode 100644 index 00000000000..22877039b47 --- /dev/null +++ b/doc/reference/user/04_message_queue.rst @@ -0,0 +1,375 @@ +============================== +Named Message Queue Interfaces +============================== + +NuttX supports POSIX named message queues for inter-task communication. +Any task may send or receive messages on named message queues. Interrupt +handlers may send messages via named message queues. + + - :c:func:`mq_open` + - :c:func:`mq_close` + - :c:func:`mq_unlink` + - :c:func:`mq_send` + - :c:func:`mq_timedsend` + - :c:func:`mq_receive` + - :c:func:`mq_timedreceive` + - :c:func:`mq_notify` + - :c:func:`mq_setattr` + - :c:func:`mq_getattr` + +.. c:function:: mqd_t mq_open(const char *mqName, int oflags, ...) + + Establishes a connection between a named + message queue and the calling task. After a successful call of + mq_open(), the task can reference the message queue using the address + returned by the call. The message queue remains usable until it is + closed by a successful call to mq_close(). + + :param mqName: Name of the queue to open + :param oflags: Open flags. These may be any combination of: + + - ``O_RDONLY``. Open for read access. + - ``O_WRONLY``. Open for write access. + - ``O_RDWR``. Open for both read & write access. + - ``O_CREAT``. Create message queue if it does not already exist. + - ``O_EXCL``. Name must not exist when opened. + - ``O_NONBLOCK``. Don't wait for data. + + :param ``...``: **Optional parameters**. When the O_CREAT flag is specified, + POSIX requires that a third and fourth parameter be supplied: + + - ``mode``. The mode parameter is of type mode_t. In the POSIX + specification, this mode value provides file permission bits for + the message queue. This parameter is required but not used in the + present implementation. + - ``attr``. A pointer to an mq_attr that is provided to initialize. + the message queue. If attr is NULL, then the messages queue is + created with implementation-defined default message queue + attributes. If attr is non-NULL, then the message queue mq_maxmsg + attribute is set to the corresponding value when the queue is + created. The mq_maxmsg attribute determines the maximum number of + messages that can be queued before addition attempts to send + messages on the message queue fail or cause the sender to block; + the mq_msgsize attribute determines the maximum size of a message + that can be sent or received. Other elements of attr are ignored + (i.e, set to default message queue attributes). + + :return: A message queue descriptor or -1 (``ERROR``) + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - The mq_msgsize attributes determines the maximum size of a message + that may be sent or received. In the present implementation, this + maximum message size is limited at 22 bytes. + +.. c:function:: int mq_close(mqd_t mqdes) + + Used to indicate that the calling task + is finished with the specified message queued mqdes. The mq_close() + deallocates any system resources allocated by the system for use by this + task for its message queue. + + If the calling task has attached a notification request to the message + queue via this ``mqdes`` (see ``mq_notify()``), this attachment will be + removed and the message queue is available for another task to attach + for notification. + + :param mqdes: Message queue descriptor. + + :return: 0 (``OK``) if the message queue is closed successfully, otherwise, -1 + (``ERROR``). + + **Assumptions/Limitations:** + + - The behavior of a task that is blocked on either a ``mq_send()`` or + ``mq_receive()`` is undefined when ``mq_close()`` is called. + - The result of using this message queue descriptor after successful + return from ``mq_close()`` is undefined. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int mq_unlink(const char *mqName) + + Removes the message queue named by + "mqName." If one or more tasks have the message queue open when + ``mq_unlink()`` is called, removal of the message queue is postponed + until all references to the message queue have been closed. + + :param mqName: Name of the message queue + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int mq_send(mqd_t mqdes, const void *msg, size_t msglen, int prio) + + Adds the specified message, ``msg``, to + the message queue, ``mqdes``. The ``msglen`` parameter specifies the + length of the message in bytes pointed to by ``msg``. This length must + not exceed the maximum message length from the ``mq_getattr()``. + + If the message queue is not full, ``mq_send()`` will place the ``msg`` + in the message queue at the position indicated by the ``prio`` argument. + Messages with higher priority will be inserted before lower priority + messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``. + + If the specified message queue is full and ``O_NONBLOCK`` is not set in + the message queue, then ``mq_send()`` will block until space becomes + available to the queue the message. + + If the message queue is full and ``NON_BLOCK`` is set, the message is + not queued and ``ERROR`` is returned. + + **NOTE**: ``mq_send()`` may be called from an interrupt handler. + However, it behaves differently when called from the interrupt level: + + - It does not check the size of the queue. It will always post the + message, even if there is already too many messages in queue. This is + because the interrupt handler does not have the option of waiting for + the message queue to become non-full. + - It doesn't allocate new memory (because you cannot allocate memory + from an interrupt handler). Instead, there are are pool of + pre-allocated message structures that may be used just for sending + messages from interrupt handlers. The number of such pre-allocated + messages is a configuration parameter. + + :param mqdes: Message queue descriptor. + :param msg: Message to send. + :param msglen: The length of the message in bytes. + :param prio: The priority of the message. + :return: On success, ``mq_send()`` returns 0 (``OK``); on + error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set + to indicate the error: + + - ``EAGAIN``. The queue was empty, and the ``O_NONBLOCK`` flag was set + for the message queue description referred to by ``mqdes``. + - ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of + ``prio`` is invalid. + - ``EPERM``. Message queue opened not opened for writing. + - ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize`` + attribute of the message queue. + - ``EINTR``. The call was interrupted by a signal handler. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int mq_timedsend(mqd_t mqdes, const char *msg, size_t msglen, int prio, \ + const struct timespec *abstime); + + Adds the specified message, ``msg``, to + the message queue, ``mqdes``. The ``msglen`` parameter specifies the + length of the message in bytes pointed to by ``msg``. This length must + not exceed the maximum message length from the ``mq_getattr()``. + + If the message queue is not full, ``mq_timedsend()`` will place the + ``msg`` in the message queue at the position indicated by the ``prio`` + argument. Messages with higher priority will be inserted before lower + priority messages The value of ``prio`` must not exceed ``MQ_PRIO_MAX``. + + If the specified message queue is full and ``O_NONBLOCK`` is not set in + the message queue, then ``mq_send()`` will block until space becomes + available to the queue the message or until a timeout occurs. + + ``mq_timedsend()`` behaves just like ``mq_send()``, except that if the + queue is full and the ``O_NONBLOCK`` flag is not enabled for the message + queue description, then ``abstime`` points to a structure which + specifies a ceiling on the time for which the call will block. This + ceiling is an absolute timeout in seconds and nanoseconds since the + Epoch (midnight on the morning of 1 January 1970). + + If the message queue is full, and the timeout has already expired by the + time of the call, ``mq_timedsend()`` returns immediately. + + :param mqdes: Message queue descriptor. + :param msg: Message to send. + :param msglen: The length of the message in bytes. + :param prio: The priority of the message. + :return: On success, ``mq_send()`` returns 0 (``OK``); on + error, -1 (``ERROR``) is returned, with ```errno`` <#ErrnoAccess>`__ set + to indicate the error: + + - ``EAGAIN``. The queue was empty, and the ``O_NONBLOCK`` flag was set + for the message queue description referred to by ``mqdes``. + - ``EINVAL``. Either ``msg`` or ``mqdes`` is ``NULL`` or the value of + ``prio`` is invalid. + - ``EPERM``. Message queue opened not opened for writing. + - ``EMSGSIZE``. ``msglen`` was greater than the ``maxmsgsize`` + attribute of the message queue. + - ``EINTR``. The call was interrupted by a signal handler. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: ssize_t mq_receive(mqd_t mqdes, void *msg, size_t msglen, int *prio) + + Receives the oldest of the highest + priority messages from the message queue specified by ``mqdes``. If the + size of the buffer in bytes, ``msgLen``, is less than the ``mq_msgsize`` + attribute of the message queue, ``mq_receive()`` will return an error. + Otherwise, the selected message is removed from the queue and copied to + ``msg``. + + If the message queue is empty and ``O_NONBLOCK`` was not set, + ``mq_receive()`` will block until a message is added to the message + queue. If more than one task is waiting to receive a message, only the + task with the highest priority that has waited the longest will be + unblocked. + + If the queue is empty and ``O_NONBLOCK`` is set, ``ERROR`` will be + returned. + + :param mqdes: Message Queue Descriptor. + :param msg: Buffer to receive the message. + :param msglen: Size of the buffer in bytes. + :param prio: If not NULL, the location to store message priority. + :return: One success, the length of the selected message in + bytes is returned. On failure, -1 (``ERROR``) is returned and the + ```errno`` <#ErrnoAccess>`__ is set appropriately: + + - ``EAGAIN`` The queue was empty and the ``O_NONBLOCK`` flag was set + for the message queue description referred to by ``mqdes``. + - ``EPERM`` Message queue opened not opened for reading. + - ``EMSGSIZE`` ``msglen`` was less than the ``maxmsgsize`` attribute of + the message queue. + - ``EINTR`` The call was interrupted by a signal handler. + - ``EINVAL`` Invalid ``msg`` or ``mqdes`` + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: ssize_t mq_timedreceive(mqd_t mqdes, void *msg, size_t msglen, \ + int *prio, const struct timespec *abstime); + + Receives the oldest of the highest + priority messages from the message queue specified by ``mqdes``. If the + size of the buffer in bytes, ``msgLen``, is less than the ``mq_msgsize`` + attribute of the message queue, ``mq_timedreceive()`` will return an + error. Otherwise, the selected message is removed from the queue and + copied to ``msg``. + + If the message queue is empty and ``O_NONBLOCK`` was not set, + ``mq_timedreceive()`` will block until a message is added to the message + queue (or until a timeout occurs). If more than one task is waiting to + receive a message, only the task with the highest priority that has + waited the longest will be unblocked. + + ``mq_timedreceive()`` behaves just like ``mq_receive()``, except that if + the queue is empty and the ``O_NONBLOCK`` flag is not enabled for the + message queue description, then ``abstime`` points to a structure which + specifies a ceiling on the time for which the call will block. This + ceiling is an absolute timeout in seconds and nanoseconds since the + Epoch (midnight on the morning of 1 January 1970). + + If no message is available, and the timeout has already expired by the + time of the call, ``mq_timedreceive()`` returns immediately. + + :param mqdes: Message Queue Descriptor. + :param msg: Buffer to receive the message. + :param msglen: Size of the buffer in bytes. + :param prio: If not NULL, the location to store message priority. + :param abstime: The absolute time to wait until a timeout is declared. + + :return: One success, the length of the selected message in + bytes is returned. On failure, -1 (``ERROR``) is returned and the + ```errno`` <#ErrnoAccess>`__ is set appropriately: + + - ``EAGAIN``: The queue was empty and the ``O_NONBLOCK`` flag was set + for the message queue description referred to by ``mqdes``. + - ``EPERM``: Message queue opened not opened for reading. + - ``EMSGSIZE``: ``msglen`` was less than the ``maxmsgsize`` attribute + of the message queue. + - ``EINTR``: The call was interrupted by a signal handler. + - ``EINVAL``: Invalid ``msg`` or ``mqdes`` or ``abstime`` + - ``ETIMEDOUT``: The call timed out before a message could be + transferred. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int mq_notify(mqd_t mqdes, FAR const struct sigevent *notification) + + If the ``notification`` input parameter is not + ``NULL``, this function connects the task with the message queue such + that the specified signal will be sent to the task whenever the message + changes from empty to non-empty. One notification can be attached to a + message queue. + + If ``notification``; is ``NULL``, the attached notification is detached + (if it was held by the calling task) and the queue is available to + attach another notification. + + When the notification is sent to the registered task, its registration + will be removed. The message queue will then be available for + registration. + + :param mqdes: Message queue descriptor + :param notification: Real-time signal structure containing: + + - ``sigev_notify``. Should be SIGEV_SIGNAL (but actually ignored) + - ``sigev_signo``. The signo to use for the notification + - ``sigev_value``. Value associated with the signal + + :return: On success ``mq_notify()`` returns 0; on error, -1 + is returned, with ``errno`` set to indicate the error: + + - ``EBADF``. The descriptor specified in ``mqdes`` is invalid. + - ``EBUSY``. Another process has already registered to receive + notification for this message queue. + - ``EINVAL``. ``sevp->sigev_notify`` is not one of the permitted + values; or ``sevp->sigev_notify`` is ``SIGEV_SIGNAL`` and + ``sevp->sigev_signo`` is not a valid signal number. + - ``ENOMEM``. Insufficient memory. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - The notification signal will be sent to the registered task even if + another task is waiting for the message queue to become non-empty. + This is inconsistent with the POSIX specification which states, "If a + process has registered for notification of message arrival at a + message queue and some process is blocked in ``mq_receive`` waiting + to receive a message when a message arrives at the queue, the + arriving message will satisfy the appropriate ``mq_receive()`` ... + The resulting behavior is as if the message queue remains empty, and + no notification will be sent." + +.. c:function:: int mq_setattr(mqd_t mqdes, const struct mq_attr *mqStat, \ + struct mq_attr *oldMqStat); + + Sets the attributes associated with the + specified message queue "mqdes." Only the "O_NONBLOCK" bit of the + "mq_flags" can be changed. + + If ``oldMqStat`` is non-null, mq_setattr() will store the previous message + queue attributes at that location (just as would have been returned by + mq_getattr()). + + :param mqdes: Message queue descriptor + :param mqStat: New attributes + :param oldMqState: Old attributes + + :return: 0 (``OK``) if attributes are set successfully, otherwise -1 + (``ERROR``). + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int mq_getattr(mqd_t mqdes, struct mq_attr *mqStat) + + Gets status information and attributes + associated with the specified message queue. + + :param mqdes: Message queue descriptor + :param mqStat: Buffer in which to return attributes. The returned + attributes include: + + - ``mq_maxmsg``. Max number of messages in queue. + - ``mq_msgsize``. Max message size. + - ``mq_flags``. Queue flags. + - ``mq_curmsgs``. Number of messages currently in queue. + + :return: 0 (``OK``) if attributes provided, -1 (``ERROR``) otherwise. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. diff --git a/doc/reference/user/05_counting_semaphore.rst b/doc/reference/user/05_counting_semaphore.rst new file mode 100644 index 00000000000..96d01b74a78 --- /dev/null +++ b/doc/reference/user/05_counting_semaphore.rst @@ -0,0 +1,455 @@ +============================= +Counting Semaphore Interfaces +============================= + +**Semaphores**. Semaphores are the basis for synchronization and mutual +exclusion in NuttX. NuttX supports POSIX semaphores. + +Semaphores are the preferred mechanism for gaining exclusive access to a +resource. sched_lock() and sched_unlock() can also be used for this +purpose. However, sched_lock() and sched_unlock() have other undesirable +side-effects in the operation of the system: sched_lock() also prevents +higher-priority tasks from running that do not depend upon the +semaphore-managed resource and, as a result, can adversely affect system +response times. + +Priority Inversion. Proper use of semaphores avoids the issues of +``sched_lock()``. However, consider the following example: + + #. Some low-priority task, *Task C*, acquires a semaphore in order to + get exclusive access to a protected resource. + #. *Task C* is suspended to allow some high-priority task, + #. *Task A* attempts to acquire the semaphore held by *Task C* and gets + blocked until *Task C* relinquishes the semaphore. + #. *Task C* is allowed to execute again, but gets suspended by some + medium-priority *Task B*. + +At this point, the high-priority *Task A* cannot execute until *Task B* +(and possibly other medium-priority tasks) completes and until *Task C* +relinquishes the semaphore. In effect, the high-priority task, *Task A* +behaves as though it were lower in priority than the low-priority task, +*Task C*! This phenomenon is called *priority inversion*. + +Some operating systems avoid priority inversion by *automatically* +increasing the priority of the low-priority *Task C* (the operable +buzz-word for this behavior is *priority inheritance*). NuttX supports +this behavior, but only if ``CONFIG_PRIORITY_INHERITANCE`` is defined in +your OS configuration file. If ``CONFIG_PRIORITY_INHERITANCE`` is not +defined, then it is left to the designer to provide implementations that +will not suffer from priority inversion. The designer may, as examples: + + - Implement all tasks that need the semaphore-managed resources at the + same priority level, + - Boost the priority of the low-priority task before the semaphore is + acquired, or + - Use sched_lock() in the low-priority task. + +Priority Inheritance. As mentioned, NuttX does support *priority +inheritance* provided that ``CONFIG_PRIORITY_INHERITANCE`` is defined in +your OS configuration file. However, the implementation and +configuration of the priority inheritance feature is sufficiently +complex that more needs to be said. How can a feature that can be +described by a single, simple sentence require such a complex +implementation: + + - ``CONFIG_SEM_PREALLOCHOLDERS``. First of all, in NuttX priority + inheritance is implement on POSIX counting semaphores. The reason for + this is that these semaphores are the most primitive waiting + mechanism in NuttX; Most other waiting facilities are based on + semaphores. So if priority inheritance is implemented for POSIX + counting semaphores, then most NuttX waiting mechanisms will have + this capability. + + Complexity arises because counting semaphores can have numerous + holders of semaphore counts. Therefore, in order to implement + priority inheritance across all holders, then internal data + structures must be allocated to manage the various holders associated + with a semaphore. The setting ``CONFIG_SEM_PREALLOCHOLDERS`` defines + the maximum number of different threads (minus one per semaphore + instance) that can take counts on a semaphore with priority + inheritance support. This setting defines the size of a single pool + of pre-allocated structures. It may be set to zero if priority + inheritance is disabled OR if you are only using semaphores as + mutexes (only one holder) OR if no more than two threads participate + using a counting semaphore. + + The cost associated with setting ``CONFIG_SEM_PREALLOCHOLDERS`` is + slightly increased code size and around 6-12 bytes times the value of + ``CONFIG_SEM_PREALLOCHOLDERS``. + + - ``CONFIG_SEM_NNESTPRIO``: In addition, there may be multiple + threads of various priorities that need to wait for a count from the + semaphore. These, the lower priority thread holding the semaphore may + have to be boosted numerous times and, to make things more complex, + will have to keep track of all of the boost priorities values in + order to correctly restore the priorities after a count has been + handed out to the higher priority thread. The + ``CONFIG_SEM_NNESTPRIO`` defines the size of an array, one array per + active thread. This setting is the maximum number of higher priority + threads (minus 1) than can be waiting for another thread to release a + count on a semaphore. This value may be set to zero if no more than + one thread is expected to wait for a semaphore. + + The cost associated with setting ``CONFIG_SEM_NNESTPRIO`` is slightly + increased code size and (``CONFIG_SEM_PREALLOCHOLDERS`` + 1) times + the maximum number of active threads. + + - **Increased Susceptibility to Bad Thread Behavior**. These various + structures tie the semaphore implementation more tightly to the + behavior of the implementation. For examples, if a thread executes + while holding counts on a semaphore, or if a thread exits without + call ``sem_destroy()`` then. Or what if the thread with the boosted + priority re-prioritizes itself? The NuttX implement of priority + inheritance attempts to handle all of these types of corner cases, + but it is very likely that some are missed. The worst case result is + that memory could by stranded within the priority inheritance logic. + +Locking versus Signaling Semaphores. Semaphores (and mutexes) may be +used for many different purposes. One typical use is for mutual +exclusion and locking of resources: In this usage, the thread that needs +exclusive access to a resources takes the semaphore to get access to the +resource. The same thread subsequently releases the semaphore count when +it no longer needs exclusive access. Priority inheritance is intended +just for this usage case. + +In a different usage case, a semaphore may to be used to signal an +event: One thread A waits on a semaphore for an event to occur. When the +event occurs, another thread B will post the semaphore waking the +waiting thread A. This is a completely different usage model; notice +that in the mutual exclusion case, the same thread takes and posts the +semaphore. In the signaling case, one thread takes the semaphore and a +different thread posts the semaphore. Priority inheritance should +*never* be used in this signaling case. Subtle, strange behaviors may +result. + +When priority inheritance is enabled with +``CONFIG_PRIORITY_INHERITANCE``, the default *protocol* for the +semaphore will be to use priority inheritance. For signaling semaphores, +priority inheritance must be explicitly disabled by calling +```sem_setprotocol`` <#semsetprotocol>`__ with ``SEM_PRIO_NONE``. For +the case of pthread mutexes, +```pthread_mutexattr_setprotocol`` <#pthreadmutexattrsetprotocol>`__ +with ``PTHREAD_PRIO_NONE``. + +This is discussed in much more detail on this `Wiki +page `__. + +**POSIX semaphore interfaces:** + +- :c:func:`sem_init` +- :c:func:`sem_destroy` +- :c:func:`sem_open` +- :c:func:`sem_close` +- :c:func:`sem_unlink` +- :c:func:`sem_wait` +- :c:func:`sem_timedwait` +- :c:func:`sem_trywait` +- :c:func:`sem_post` +- :c:func:`sem_getvalue` +- :c:func:`sem_getprotocol` +- :c:func:`sem_setprotocol` + +.. c:function:: int sem_init(sem_t *sem, int pshared, unsigned int value) + + Initializes the UN-NAMED semaphore sem. + Following a successful call to sem_init(), the semaphore may be used in + subsequent calls to sem_wait(), sem_post(), and sem_trywait(). The + semaphore remains usable until it is destroyed. + + Only ``sem`` itself may be used for performing synchronization. The + result of referring to copies of ``sem`` in calls to ``sem_wait()``, + ``sem_trywait()``, ``sem_post()``, and ``sem_destroy()``, is not + defined. + + :param sem: Semaphore to be initialized + :param pshared: Process sharing (not used) + :param value: Semaphore initialization value + + :return: 0 (``OK``), or -1 (``ERROR``) if unsuccessful. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - pshared is not used. + +.. c:function:: int sem_destroy(sem_t *sem) + + Used to destroy the un-named semaphore + indicated by ``sem``. Only a semaphore that was created using + ``sem_init()`` may be destroyed using ``sem_destroy()``. The effect of + calling ``sem_destroy()`` with a named semaphore is undefined. The + effect of subsequent use of the semaphore ``sem`` is undefined until + ``sem`` is re-initialized by another call to ``sem_init()``. + + The effect of destroying a semaphore upon which other tasks are + currently blocked is undefined. + + :param sem: Semaphore to be destroyed. + :return: 0 (``OK``), or -1 (``ERROR``) if unsuccessful. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: sem_t *sem_open(const char *name, int oflag, ...) + + Establishes a connection between named + semaphores and a task. Following a call to sem_open() with the semaphore + name, the task may reference the semaphore associated with name using + the address returned by this call. The semaphore may be used in + subsequent calls to sem_wait(), sem_trywait(), and sem_post(). The + semaphore remains usable until the semaphore is closed by a successful + call to sem_close(). + + If a task makes multiple calls to sem_open() with the same name, then + the same semaphore address is returned (provided there have been no + calls to sem_unlink()). + + **Input Parameters:** + + :param name: Semaphore name + :param oflag: Semaphore creation options. This may one of the following + bit settings: + + - ``oflag`` = 0: Connect to the semaphore only if it already exists. + - ``oflag`` = O_CREAT: Connect to the semaphore if it exists, + otherwise create the semaphore. + - ``oflag`` = O_CREAT with O_EXCL (O_CREAT|O_EXCL): Create a new + semaphore unless one of this name already exists. + + :param ``...``: **Optional parameters**. NOTE: When the O_CREAT flag is specified, + POSIX requires that a third and fourth parameter be supplied: + + - ``mode``. The mode parameter is of type mode_t. This parameter is + required but not used in the present implementation. + - ``value``. The value parameter is type unsigned int. The semaphore + is created with an initial value of ``value``. Valid initial + values for semaphores must be less than or equal to + ``SEM_VALUE_MAX`` (defined in ``include/limits.h``). + + :return: A pointer to sem_t or ``SEM_FAILED`` if unsuccessful. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - Treatment of links/connections is highly simplified. It is just a + counting semaphore. + +.. c:function:: int sem_close(sem_t *sem) + + This function is called to indicate that the calling + task is finished with the specified named semaphore, sem. The + sem_close() deallocates any system resources allocated by the system for + this named semaphore. + + If the semaphore has not been removed with a call to sem_unlink(), then + sem_close() has no effect on the named semaphore. However, when the + named semaphore has been fully unlinked, the semaphore will vanish when + the last task closes it. + + Care must be taken to avoid risking the deletion of a semaphore that + another calling task has already locked. + + :param sem: Semaphore descriptor + :return: 0 (``OK``), or -1 (``ERROR``) if unsuccessful. + + **Assumptions/Limitations:** + + - Care must be taken to avoid deletion of a semaphore that another task + has already locked. + - sem_close() must not be called with an un-named semaphore. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sem_unlink(const char *name) + + This function will remove the semaphore named by the + input name parameter. If one or more tasks have the semaphore named by + name open when sem_unlink() is called, destruction of the semaphore will + be postponed until all references have been destroyed by calls to + sem_close(). + + :param name: Semaphore name + :return: 0 (``OK``), or -1 (``ERROR``) if unsuccessful. + + **Assumptions/Limitations:** + + - Care must be taken to avoid deletion of a semaphore that another task + has already locked. + - sem_unlink() must not be called with an un-named semaphore. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - Treatment of links/connections is highly simplified. It is just a + counting semaphore. + - Calls to sem_open() to re-create or re-connect to the semaphore may + refer to the same semaphore; POSIX specifies that a new semaphore + with the same name should be created after sem_unlink() is called. + +.. c:function:: int sem_wait(sem_t *sem) + + This function attempts to lock the semaphore referenced + by sem. If the semaphore as already locked by another task, the calling + task will not return until it either successfully acquires the lock or + the call is interrupted by a signal. + + :param sem: Semaphore descriptor. + :return: 0 (``OK``), or -1 (``ERROR``) is unsuccessful + + If ``sem_wait`` returns -1 (``ERROR``) then the cause of the failure + will be indicated by the thread-specific ```errno`` <#ErrnoAccess>`__. + The following lists the possible values for + ```errno`` <#ErrnoAccess>`__: + + - ``EINVAL``: Indicates that the ``sem`` input parameter is not valid. + - ``EINTR``: Indicates that the wait was interrupt by a signal received + by this task. In this case, the semaphore has not be acquired. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sem_timedwait(sem_t *sem, const struct timespec *abstime) + + This function will lock the semaphore referenced by sem + as in the ``sem_wait()`` function. However, if the semaphore cannot be + locked without waiting for another process or thread to unlock the + semaphore by performing a ``sem_post()`` function, this wait will be + terminated when the specified timeout expires. + + The timeout will expire when the absolute time specified by ``abstime`` + passes, as measured by the clock on which timeouts are based (that is, + when the value of that clock equals or exceeds abstime), or if the + absolute time specified by abstime has already been passed at the time + of the call. This function attempts to lock the semaphore referenced by + ``sem``. If the semaphore is already locked by another task, the calling + task will not return until it either successfully acquires the lock or + the call is interrupted by a signal. + + **Input Parameters:** + + :param sem: Semaphore descriptor. + :param abstime: The absolute time to wait until a timeout is declared. + :return: 0 (``OK``), or -1 (``ERROR``) is unsuccessful + + If ``sem_timedwait`` returns -1 (``ERROR``) then the cause of the + failure will be indicated by the thread-specific + ```errno`` <#ErrnoAccess>`__. The following lists the possible values + for ```errno`` <#ErrnoAccess>`__: + + ``EINVAL``: Indicates that the ``sem`` input parameter is not valid or + the thread would have blocked, and the abstime parameter specified a + nanoseconds field value less than zero or greater than or equal to 1000 + million. + + ``ETIMEDOUT``: The semaphore could not be locked before the specified + timeout expired. + + ``EDEADLK``: A deadlock condition was detected. + + ``EINTR``: Indicates that the wait was interrupt by a signal received by + this task. In this case, the semaphore has not be acquired. + + **POSIX Compatibility:** Derived from IEEE Std 1003.1d-1999. + +.. c:function:: int sem_trywait(sem_t *sem) + + This function locks the specified semaphore only if the + semaphore is currently not locked. In any event, the call returns + without blocking. + + :param sem: The semaphore descriptor + :return: 0 (``OK``) or -1 (``ERROR``) if unsuccessful + + If ``sem_trywait`` returns -1 (``ERROR``) then the cause of the failure + will be indicated by the thread-specific ```errno`` <#ErrnoAccess>`__. + The following lists the possible values for + ```errno`` <#ErrnoAccess>`__: + + - ``EINVAL``: Indicates that the ``sem`` input parameter is not valid. + - ``EAGAIN``: Indicates that the semaphore was not acquired. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sem_post(sem_t *sem) + + When a task has finished with a semaphore, it will call + sem_post(). This function unlocks the semaphore referenced by ``sem`` by + performing the semaphore unlock operation. + + If the semaphore value resulting from this operation is positive, then + no tasks were blocked waiting for the semaphore to become unlocked; The + semaphore value is simply incremented. + + If the value of the semaphore resulting from this operation is zero, + then on of the tasks blocked waiting for the semaphore will be allowed + to return successfully from its call to ``sem_wait()``. + + .. note:: ``sem_post()`` may be called from an interrupt handler. + + :param sem: Semaphore descriptor + :return: 0 (``OK``) or -1 (``ERROR``) if unsuccessful. + + **Assumptions/Limitations:**. When called from an interrupt handler, it + will appear as though the interrupt task is the one that is performing + the unlock. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sem_getvalue(sem_t *sem, int *sval) + + This function updates the location referenced by sval + argument to have the value of the semaphore referenced by sem without + effecting the state of the semaphore. The updated value represents the + actual semaphore value that occurred at some unspecified time during the + call, but may not reflect the actual value of the semaphore when it is + returned to the calling task. + + If sem is locked, the value return by sem_getvalue() will either be zero + or a negative number whose absolute value represents the number of tasks + waiting for the semaphore. + + :param sem: Semaphore descriptor + :param sval: Buffer by which the value is returned + + :return: 0 (``OK``) or -1 (``ERROR``) if unsuccessful. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sem_getprotocol(FAR const pthread_mutexattr_t *attr, FAR int *protocol) + + Return the value of the semaphore protocol attribute. + + :param attr: A pointer to the semaphore to be queried + :param protocol: The user provided location in which to store the + protocol value. May be one of ``SEM_PRIO_NONE``, or + ``SEM_PRIO_INHERIT``, ``SEM_PRIO_PROTECT``. + :return: If successful, the ``sem_getprotocol()`` function will return zero + (``OK``). Otherwise, an -1 (``ERROR``) will be returned and the + ``errno`` value will be set to indicate the nature of the error. + + **POSIX Compatibility:** Non-standard NuttX interface. Should not be + used in portable code. Analogous to + ``pthread_muxtexattr_getprotocol()``. + +.. c:function:: int sem_setprotocol(FAR pthread_mutexattr_t *attr, int protocol) + + Set semaphore protocol attribute. See the paragraph + `Locking versus Signaling Semaphores <#lockingvssignaling>`__ for some + important information about the use of this interface. + + :param attr: A pointer to the semaphore to be modified + :param protocol: The new protocol to use. One of ``SEM_PRIO_NONE``, or + ``SEM_PRIO_INHERIT``, ``SEM_PRIO_PROTECT``. ``SEM_PRIO_INHERIT`` is + supported only if ``CONFIG_PRIORITY_INHERITANCE`` is defined; + ``SEM_PRIO_PROTECT`` is not currently supported in any configuration. + :return: If successful, the ``sem_setprotocol()`` function will return zero + (``OK``). Otherwise, an -1 (``ERROR``) will be returned and the + ``errno`` value will be set to indicate the nature of the error. + + **POSIX Compatibility:** Non-standard NuttX interface. Should not be + used in portable code. Analogous to + ``pthread_muxtexattr_setprotocol()``. diff --git a/doc/reference/user/06_clocks_timers.rst b/doc/reference/user/06_clocks_timers.rst new file mode 100644 index 00000000000..cc96fe7fde4 --- /dev/null +++ b/doc/reference/user/06_clocks_timers.rst @@ -0,0 +1,360 @@ +Clocks and Timers +***************** + +- :c:func:`clock_settime` +- :c:func:`clock_gettime` +- :c:func:`clock_getres` +- :c:func:`mktime` +- :c:func:`gmtime` +- :c:func:`localtime` +- :c:func:`asctime` +- :c:func:`ctime` +- :c:func:`gmtime_r` +- :c:func:`localtime_r` +- :c:func:`asctime_r` +- :c:func:`ctime_r` +- :c:func:`timer_create` +- :c:func:`timer_delete` +- :c:func:`timer_settime` +- :c:func:`timer_gettime` +- :c:func:`timer_getoverrun` +- :c:func:`gettimeofday` + +.. c:function:: int clock_settime(clockid_t clockid, const struct timespec *tp) + + :return: If successful, returns zero (``OK``). Otherwise, + a non-zero error number will be returned to indicate the error. + +.. c:function:: int clock_gettime(clockid_t clockid, struct timespec *tp) + + :return: If successful, returns zero (``OK``). Otherwise, + a non-zero error number will be returned to indicate the error. + +.. c:function:: int clock_getres(clockid_t clockid, struct timespec *res) + + :return: If successful, returns zero (``OK``). Otherwise, + a non-zero error number will be returned to indicate the error. + +.. c:function:: time_t mktime(struct tm *tp); + + :return: If successful, returns zero (``OK``). Otherwise, + a non-zero error number will be returned to indicate the error. + +.. c:function:: FAR struct tm *gmtime(FAR const time_t *timep); + + Represents GMT date/time in a type ``struct tm``. This + function is not re-entrant. + + :param timep: Represents GMT calendar time. This is an absolute time + value representing the number of seconds elapsed since 00:00:00 on + January 1, 1970, Coordinated Universal Time (UTC). + + :return: If successful, the function will return the pointer to a statically defined + instance of ``struct tm``. Otherwise, a NULL will be returned to + indicate the error: + +.. c:function:: FAR struct tm *localtime(FAR const time_t *timep) + + Represents local date/time in a type ``struct tm``. + This function is not re-entrant. + + :param timep: Represents GMT calendar time. This is an absolute time + value representing the number of seconds elapsed since 00:00:00 on + January 1, 1970, Coordinated Universal Time (UTC). + + :return: If successful, the function will return the pointer to a statically defined + instance of ``struct tm``. Otherwise, a NULL will be returned to + indicate the error: + +.. c:function:: FAR char *asctime(FAR const struct tm *tp); + + Converts the time provided in a + ``struct tm`` to a string representation. ``asctime()`` is not + re-entrant. + + :param tp: Pointer to the time to be converted. + :return: If successful, the function will + return a pointer to a statically defined string holding the converted + time. Otherwise, a NULL will be returned to indicate the error. + +.. c:function:: FAR char *ctime(FAR const time_t *timep) + + Converts the time provided in seconds since + the epoch to a string representation. ``ctime()`` is not re-entrant. + + :param timep: The current time represented as seconds since the epoch. + :return: If successful, the function will return + the pointer to the converted string. Otherwise, a NULL will be returned + to indicate the error. + +.. c:function:: struct tm *gmtime_r(const time_t *timep, struct tm *result); + + Represents GMT date/time in a type ``struct tm``. This + function is re-entrant. + + :param timep: Represents GMT calendar time. This is an absolute time + value representing the number of seconds elapsed since 00:00:00 on + January 1, 1970, Coordinated Universal Time (UTC). + :param result: A user-provided buffer to receive the converted time + structure. + :return: If successful, the ``gmtime_r()`` function will + return the pointer, ``result``, provided by the caller. Otherwise, a + NULL will be returned to indicate the error: + +.. c:function:: FAR struct tm *localtime_r(FAR const time_t *timep, FAR struct tm *result) + + Represents local date/time in a type ``struct tm``. + This function is re-entrant. + + :param timep: Represents GMT calendar time. This is an absolute time + value representing the number of seconds elapsed since 00:00:00 on + January 1, 1970, Coordinated Universal Time (UTC). + :param result: A user-provided buffer to receive the converted time + structure. + :return: If successful, the + ``localtime_r()`` function will return the pointer, ``result``, provided + by the caller. Otherwise, a NULL will be returned to indicate the error: + +.. c:function:: FAR char *asctime_r(FAR const struct tm *tp, FAR char *buf) + + Converts the time provided in a + ``struct tm`` to a string representation. ``asctime-r()`` is re-entrant. + + :param tp: Pointer to the time to be converted. + :param buf: The user provider buffer. of size >= 26 characters, to + receive the converted time. + :return: If successful, the ``asctime_r()`` function will + return the pointer, ``buf``, provided by the caller. Otherwise, a NULL + will be returned to indicate the error. + +.. c:function:: FAR char *ctime_r(FAR const time_t *timep, FAR char *buf) + + Converts the time provided in seconds + since the epoch to a string representation. ``ctime()`` is re-entrant. + + :param timep: The current time represented as seconds since the epoch. + :param buf: The user provider buffer. of size >= 26 characters, to + receive the converted time. + :return: If successful, the ``ctime_r()`` function will + return the pointer, ``buf``, provided by the caller. Otherwise, a NULL + will be returned to indicate the error. + +.. c:function:: int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid); + + Creates per-thread + timer using the specified clock, ``clock_id``, as the timing base. The + ``timer_create()`` function returns, in the location referenced by + ``timerid``, a timer ID of type timer_t used to identify the timer in + timer requests. This timer ID is unique until the timer is deleted. The + particular clock, ``clock_id``, is defined in ````. The timer + whose ID is returned will be in a disarmed state upon return from + ``timer_create()``. + + The ``evp`` argument, if non-NULL, points to a ``sigevent`` structure. + This structure is allocated by the called and defines the asynchronous + notification to occur. If the ``evp`` argument is NULL, the effect is as + if the ``evp`` argument pointed to a ``sigevent`` structure with the + ``sigev_notify`` member having the value ``SIGEV_SIGNAL``, the + ``sigev_signo`` having a default signal number, and the ``sigev_value`` + member having the value of the timer ID. + + Each implementation defines a set of clocks that can be used as timing + bases for per-thread timers. All implementations will support a + ``clock_id`` of ``CLOCK_REALTIME``. + + :param clockid: Specifies the clock to use as the timing base. Must be + ``CLOCK_REALTIME``. + :param ``evp``: Refers to a user allocated sigevent structure that defines + the asynchronous notification. evp may be NULL (see above). + :param ``timerid``: The pre-thread timer created by the call to + timer_create(). + :return: If the call succeeds, ``timer_create()`` will return + 0 (``OK``) and update the location referenced by ``timerid`` to a + ``timer_t``, which can be passed to the other per-thread timer calls. If + an error occurs, the function will return a value of -1 (``ERROR``) and + set ``errno`` to indicate the error. + + - ``EAGAIN``. The system lacks sufficient signal queuing resources to + honor the request. + - ``EAGAIN``. The calling process has already created all of the timers + it is allowed by this implementation. + - ``EINVAL``. The specified clock ID is not defined. + - ``ENOTSUP``. The implementation does not support the creation of a + timer attached to the CPU-time clock that is specified by clock_id + and associated with a thread different thread invoking + timer_create(). + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - Only ``CLOCK_REALTIME`` is supported for the ``clockid`` argument. + +.. c:function:: int timer_delete(timer_t timerid); + + Deletes the specified + timer, ``timerid``, previously created by the ``timer_create()`` + function. If the timer is armed when ``timer_delete()`` is called, the + timer will be automatically disarmed before removal. The disposition of + pending signals for the deleted timer is unspecified. + + :param timerid: The pre-thread timer, previously created by the call to + timer_create(), to be deleted. + :return: If successful, the ``timer_delete()`` function will + return zero (``OK``). Otherwise, the function will return a value of -1 + (``ERROR``) and set ``errno`` to indicate the error: + + - ``EINVAL``. The timer specified timerid is not valid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, \ + struct itimerspec *ovalue); + + Sets the time until + the next expiration of the timer specified by ``timerid`` from the + ``it_value`` member of the value argument and arm the timer if the + ``it_value`` member of value is non-zero. If the specified timer was + already armed when ``timer_settime()`` is called, this call will reset + the time until next expiration to the value specified. If the + ``it_value`` member of value is zero, the timer will be disarmed. The + effect of disarming or resetting a timer with pending expiration + notifications is unspecified. + + If the flag ``TIMER_ABSTIME`` is not set in the argument flags, + ``timer_settime()`` will behave as if the time until next expiration is + set to be equal to the interval specified by the ``it_value`` member of + value. That is, the timer will expire in ``it_value`` nanoseconds from + when the call is made. If the flag ``TIMER_ABSTIME`` is set in the + argument flags, ``timer_settime()`` will behave as if the time until + next expiration is set to be equal to the difference between the + absolute time specified by the ``it_value`` member of value and the + current value of the clock associated with ``timerid``. That is, the + timer will expire when the clock reaches the value specified by the + ``it_value`` member of value. If the specified time has already passed, + the function will succeed and the expiration notification will be made. + + The reload value of the timer will be set to the value specified by the + ``it_interval`` member of value. When a timer is armed with a non-zero + ``it_interval``, a periodic (or repetitive) timer is specified. + + Time values that are between two consecutive non-negative integer + multiples of the resolution of the specified timer will be rounded up to + the larger multiple of the resolution. Quantization error will not cause + the timer to expire earlier than the rounded time value. + + If the argument ``ovalue`` is not NULL, the t\ ``imer_settime()`` + function will store, in the location referenced by ``ovalue``, a value + representing the previous amount of time before the timer would have + expired, or zero if the timer was disarmed, together with the previous + timer reload value. Timers will not expire before their scheduled time. + + **NOTE:**\ At present, the ``ovalue`` argument is ignored. + + :param timerid: The pre-thread timer, previously created by the call to + timer_create(), to be be set. + :param flags: Specify characteristics of the timer (see above) + :param value: Specifies the timer value to set + :param ovalue: A location in which to return the time remaining from the + previous timer setting (ignored). + + :return: If the timer_gettime() succeeds, a value of 0 + (``OK``) will be returned. If an error occurs, the value -1 (``ERROR``) + will be returned, and ```errno`` <#ErrnoAccess>`__ set to indicate the + error. + + - ``EINVAL``. The timerid argument does not correspond to an ID + returned by timer_create() but not yet deleted by timer_delete(). + - ``EINVAL``. A value structure specified a nanosecond value less than + zero or greater than or equal to 1000 million, and the it_value + member of that structure did not specify zero seconds and + nanoseconds. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - The ``ovalue`` argument is ignored. + +.. c:function:: int timer_gettime(timer_t timerid, struct itimerspec *value); + + Stores the amount + of time until the specified timer, ``timerid``, expires and the reload + value of the timer into the space pointed to by the ``value`` argument. + The ``it_value`` member of this structure will contain the amount of + time before the timer expires, or zero if the timer is disarmed. This + value is returned as the interval until timer expiration, even if the + timer was armed with absolute time. The ``it_interval`` member of + ``value`` will contain the reload value last set by ``timer_settime()``. + + Due to the asynchronous operation of this function, the time reported by + this function could be significantly more than that actual time + remaining on the timer at any time. + + :param timerid: Specifies pre-thread timer, previously created by the + call to ``timer_create()``, whose remaining count will be returned. + :return: If successful, the ``timer_gettime()`` function will + return zero (``OK``). Otherwise, an non-zero error number will be + returned to indicate the error: + + - ``EINVAL``. The ``timerid`` argument does not correspond to an ID + returned by ``timer_create()`` but not yet deleted by + ``timer_delete()``. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int timer_getoverrun(timer_t timerid); + + Only a single signal will be queued to the process for + a given timer at any point in time. When a timer for which a signal is + still pending expires, no signal will be queued, and a timer overrun + will occur. When a timer expiration signal is delivered to or accepted + by a process, if the implementation supports the *Realtime Signals + Extension*, the ``timer_getoverrun()`` function will return the timer + expiration overrun count for the specified timer. The overrun count + returned contains the number of extra timer expirations that occurred + between the time the signal was generated (queued) and when it was + delivered or accepted, up to but not including an implementation-defined + maximum of ``DELAYTIMER_MAX``. If the number of such extra expirations + is greater than or equal to ``DELAYTIMER_MAX``, then the overrun count + will be set to ``DELAYTIMER_MAX``. The value returned by + ``timer_getoverrun()`` will apply to the most recent expiration signal + delivery or acceptance for the timer. If no expiration signal has been + delivered for the timer, or if the *Realtime Signals Extension* is not + supported, the return value of ``timer_getoverrun()`` is unspecified. + + **NOTE:** This interface is not currently implemented in NuttX. + + :param timerid: Specifies pre-thread timer, previously created by the + call to ``timer_create()``, whose overrun count will be returned. + + :return: If the ``timer_getoverrun()`` function succeeds, it + will return the timer expiration overrun count as explained above. + ``timer_getoverrun()`` will fail if: + + - ``EINVAL``. The ``timerid`` argument does not correspond to an ID + returned by ``timer_create()`` but not yet deleted by + ``timer_delete()``. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the full POSIX implementation include: + + - This interface is not currently implemented by NuttX. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int gettimeofday(struct timeval *tp, void *tzp); + + This implementation of ``gettimeofday()`` is simply a + thin wrapper around :c:func:`clock_gettime`. It simply + calls ``clock_gettime()`` using the ``CLOCK_REALTIME`` timer and + converts the result to the required ``struct timeval``. + + :param tp: The current time will be returned to this user provided + location. + :param tzp: A reference to the timezone -- *IGNORED*. + + :return: See :c:func:`clock_gettime`. diff --git a/doc/reference/user/07_signals.rst b/doc/reference/user/07_signals.rst new file mode 100644 index 00000000000..b396905cfef --- /dev/null +++ b/doc/reference/user/07_signals.rst @@ -0,0 +1,514 @@ +Signal Interfaces +***************** + +**Tasks and Signals**. NuttX provides signal interfaces for tasks and +pthreads. Signals are used to alter the flow control of tasks by +communicating asynchronous events within or between task contexts. Any +task or interrupt handler can post (or send) a signal to a particular +task using its task ID. The task being signaled will execute +task-specified signal handler function the next time that the task has +priority. The signal handler is a user-supplied function that is bound +to a specific signal and performs whatever actions are necessary +whenever the signal is received. + +By default, here are no predefined actions for any signal. The default +action for all signals (i.e., when no signal handler has been supplied +by the user) is to ignore the signal. In this sense, all NuttX are *real +time* signals by default. If the configuration option +``CONFIG_SIG_DEFAULT=y`` is included, some signals will perform their +default actions dependent upon addition configuration settings as +summarized in the following table: + +======= ==================== ========================= +Signal Action Additional Configuration +======= ==================== ========================= +SIGUSR1 Abnormal Termination CONFIG_SIG_SIGUSR1_ACTION +SIGUSR2 Abnormal Termination CONFIG_SIG_SIGUSR2_ACTION +SIGALRM Abnormal Termination CONFIG_SIG_SIGALRM_ACTION +SIGPOLL Abnormal Termination CONFIG_SIG_SIGPOLL_ACTION +SIGSTOP Suspend task CONFIG_SIG_SIGSTOP_ACTION +SIGSTP Suspend task CONFIG_SIG_SIGSTOP_ACTION +SIGCONT Resume task CONFIG_SIG_SIGSTOP_ACTION +SIGINT Abnormal Termination CONFIG_SIG_SIGKILL_ACTION +SIGKILL Abnormal Termination CONFIG_SIG_SIGKILL_ACTION +======= ==================== ========================= + +Tasks may also suspend themselves and wait until a signal is received. + +**Tasks Groups**. NuttX supports both tasks and pthreads. The primary +difference between tasks and pthreads is the tasks are much more +independent. Tasks can create pthreads and those pthreads will share the +resources of the task. The main task and its children pthreads together +are referred as a *task group*. A task group is used in NuttX to emulate +a POSIX *process*. + +.. note:: + Behavior of features related to task group\ s depend of NuttX + configuration settings. See also the\ `NuttX + Tasking `__\ page + and the\ `Tasks vs. Threads + FAQ `__\ for + additional information on tasks and threads in NuttX. + +**Signaling Multi-threaded Task Groups**. The behavior of signals in the +multi-thread task group is complex. NuttX emulates a process model with +task groups and follows the POSIX rules for signaling behavior. Normally +when you signal the task group you would signal using the task ID of the +main task that created the group (in practice, a different task should +not know the IDs of the internal threads created within the task group); +that ID is remembered by the task group (even if the main task thread +exits). + +Here are some of the things that should happen when you signal a +multi-threaded task group: + +- If a task group receives a signal then one and only one indeterminate + thread in the task group which is not blocking the signal will + receive the signal. +- If a task group receives a signal and more than one thread is waiting + on that signal, then one and only one indeterminate thread out of + that waiting group will receive the signal. + +You can mask out that signal using ''sigprocmask()'' (or +''pthread_sigmask()''). That signal will then be effectively disabled +and will never be received in those threads that have the signal masked. +On creation of a new thread, the new thread will inherit the signal mask +of the parent thread that created it. So you if block signal signals on +one thread then create new threads, those signals will also be blocked +in the new threads as well. + +You can control which thread receives the signal by controlling the +signal mask. You can, for example, create a single thread whose sole +purpose it is to catch a particular signal and respond to it: Simply +block the signal in the main task; then the signal will be blocked in +all of the pthreads in the group too. In the one "signal processing" +pthread, enable the blocked signal. This thread will then be only thread +that will receive the signal. + +**Signal Interfaces**. The following signal handling interfaces are +provided by NuttX: + +- :c:func:`sigemptyset` +- :c:func:`sigfillset` +- :c:func:`sigaddset` +- :c:func:`sigdelset` +- :c:func:`sigismember` +- :c:func:`sigaction` +- :c:func:`sigignore` +- :c:func:`sigset` +- :c:func:`sigprocmask` +- :c:func:`sighold` +- :c:func:`sigrelse` +- :c:func:`sigpending` +- :c:func:`sigsuspend` +- :c:func:`sigpause` +- :c:func:`sigwaitinfo` +- :c:func:`sigtimedwait` +- :c:func:`sigqueue` +- :c:func:`kill` +- :c:func:`pause` + +.. c:function:: int sigemptyset(sigset_t *set) + + Initializes the signal set specified by + set such that all signals are excluded. + + :param set: Signal set to initialize. + + :return: 0 (``OK``), or -1 (``ERROR``) if the signal set cannot be + initialized. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigfillset(sigset_t *set); + + Initializes the signal set specified by + set such that all signals are included. + + :param set: Signal set to initialize + + :return: 0 (``OK``), or -1 (``ERROR``) if the signal set cannot be + initialized. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigaddset(sigset_t *set, int signo); + + Adds the signal specified by signo to the + signal set specified by set. + + :param set: Signal set to add signal to + :param signo: Signal to add + + :return: 0 (``OK``), or -1 (``ERROR``) if the signal number is invalid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigdelset(sigset_t *set, int signo); + + Deletes the signal specified by signo + from the signal set specified by set. + + :param set: Signal set to delete the signal from + :param signo: Signal to delete + + :return: 0 (``OK``), or -1 (``ERROR``) if the signal number is invalid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigismember(const sigset_t *set, int signo); + + Tests whether the signal specified by + signo is a member of the set specified by set. + + :param set: Signal set to test + :param signo: Signal to test for + + :return: + - 1 (TRUE), if the specified signal is a member of the set, + - 0 (OK or FALSE), if it is not, or + - -1 (``ERROR``) if the signal number is invalid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigaction(int signo, const struct sigaction *act, \ + struct sigaction *oact); + + Allows the calling task to examine and/or + specify the action to be associated with a specific signal. + + The structure sigaction, used to describe an action to be taken, is + defined to include the following members: + + - ``sa_u.sa_handler``. A pointer to a signal-catching function. + - ``sa_u.sa_sigaction``. An alternative form for the signal catching + function. + - ``sa_mask``. Additional set of signals to be blocked during execution + of the signal-catching function. + - ``sa_flags``: Special flags to affect behavior of a signal. + + If the argument act is not NULL, it points to a structure specifying the + action to be associated with the specified signal. If the argument oact + is not NULL, the action previously associated with the signal is stored + in the location pointed to by the argument oact. If the argument act is + NULL, signal handling is unchanged by this function call; thus, the call + can be used to inquire about the current handling of a given signal. + + When a signal is caught by a signal-catching function installed by the + sigaction() function, a new signal mask is calculated and installed for + the duration of the signal-catching function. This mask is formed by + taking the union of the current signal mask and the value of the sa_mask + for the signal being delivered, and then including the signal being + delivered. If and when the signal handler returns, the original signal + mask is restored. + + Signal catching functions execute in the same address environment as the + task that called sigaction() to install the signal-catching function. + + Once an action is installed for a specific signal, it remains installed + until another action is explicitly requested by another call to + sigaction(). + + :param sig: Signal of interest + :param act: Location of new handler + :param oact: Location to store old handler + + :return: 0 (``OK``), or -1 (``ERROR``) if the signal number is invalid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the POSIX implementation include: + + - There are no default actions so the special value ``SIG_DFL`` is + treated like ``SIG_IGN``. + - All ``sa_flags`` in struct sigaction of act input are ignored (all + treated like ``SA_SIGINFO``). The one exception is if + ``CONFIG_SCHED_CHILD_STATUS`` is defined; then ``SA_NOCLDWAIT`` is + supported but only for ``SIGCHLD``. + +.. c:function:: int sigignore(int signo); + + Sets the disposition of ``signo`` to ``SIG_IGN``. + + :param signo: The signal number to act on + + :return: + - Zero is returned upon successful completion, otherwise -1 (``ERROR``) + is returned with the errno set appropriately. The ``errno`` value of + ``EINVAL``, for example, would indicate that ``signo`` argument is + not a valid signal number. + +.. c:function:: void (*sigset(int signo, void (*disp)(int)))(int); + + Modifies signal dispositions. + The ``signo`` argument specifies the signal. The ``disp`` argument + specifies the signal's disposition, which may be ``SIG_DFL``, + ``SIG_IGN``, or the address of a signal handler. If ``disp`` is the + address of a signal handler, the system will add ``signo`` to the + calling process's signal mask before executing the signal handler; when + the signal handler returns, the system will restore the calling + process's signal mask to its state prior to the delivery of the signal. + ``signo`` will be removed from the calling process's signal mask. + + NOTE: The value ``SIG_HOLD`` for ``disp`` is not currently supported. + + :param signo: The signal number to operate on + :param disp: The new disposition of the signal + + :return: + - Upon successful completion, ``sigset()`` will the previous + disposition of the signal. Otherwise, ``SIG_ERR`` will be returned + and ``errno`` set to indicate the error. + +.. c:function:: int sigprocmask(int how, const sigset_t *set, sigset_t *oset); + + Allows the calling task to examine and/or + change its signal mask. If the set is not NULL, then it points to a set + of signals to be used to change the currently blocked set. The value of + how indicates the manner in which the set is changed. + + If there are any pending unblocked signals after the call to + sigprocmask(), those signals will be delivered before sigprocmask() + returns. + + If sigprocmask() fails, the signal mask of the task is not changed. + + :param how: How the signal mast will be changed. + - ``SIG_BLOCK`` The resulting set is the union of the current set and the signal set pointed to by the ``set`` input parameter. + - ``SIG_UNBLOCK`` The resulting set is the intersection of the current set and the complement of the signal set pointed to by the ``set`` input parameter. + - ``SIG_SETMASK`` The resulting set is the signal set pointed to by the ``set`` input parameter. + + :param set: Location of the new signal mask + :param oset: Location to store the old signal mask + + :return: 0 (``OK``), or -1 (``ERROR``) if how is invalid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sighold(int signo); + + Adds ``signo`` to the calling process's signal mask + + :param signo: Identifies the signal to be blocked. + + :return: + Zero is returned upon successful completion, otherwise -1 (``ERROR``) + is returned with the errno set appropriately. The ``errno`` value of + ``EINVAL``, for example, would indicate that ``signo`` argument is + not a valid signal number. + +.. c:function:: int sigrelse(int signo); + + Removes ``signo`` from the calling process's signal mask + + :param signo: Identifies the signal to be unblocked. + + :return: + Zero is returned upon successful completion, otherwise -1 (``ERROR``) + is returned with the errno set appropriately. The ``errno`` value of + ``EINVAL``, for example, would indicate that ``signo`` argument is + not a valid signal number. + +.. c:function:: int sigpending(sigset_t *set); + + Stores the returns the set of signals + that are blocked for delivery and that are pending for the calling task + in the space pointed to by set. + + If the task receiving a signal has the signal blocked via its + sigprocmask, the signal will pend until it is unmasked. Only one pending + signal (for a given signo) is retained by the system. This is consistent + with POSIX which states: "If a subsequent occurrence of a pending signal + is generated, it is implementation defined as to whether the signal is + delivered more than once." + + :param set: The location to return the pending signal set. + + :return: 0 (``OK``) or -1 (``ERROR``) + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigsuspend(const sigset_t *set); + + Replaces the signal mask with + the set of signals pointed to by the argument set and then suspends the + task until delivery of a signal to the task. + + If the effect of the set argument is to unblock a pending signal, then + no wait is performed. + + The original signal mask is restored when sigsuspend() returns. + + Waiting for an empty signal set stops a task without freeing any + resources (a very bad idea). + + :param set: The value of the signal **mask** to use while suspended. + + :return: -1 (``ERROR``) always + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the POSIX specification include: + + - POSIX does not indicate that the original signal mask is restored. + - POSIX states that sigsuspend() "suspends the task until delivery of a + signal whose action is either to execute a signal-catching function + or to terminate the task." Only delivery of the signal is required in + the present implementation (even if the signal is ignored). + +.. c:function:: int sigpause(int signo); + + Removes ``signo`` from the calling process's signal mask and suspend the calling process + until a signal is received. The ``sigpause()``) function will restore + the process's signal mask to its original state before returning. + + :param set: Identifies the signal to be unblocked while waiting. + + :return: + ``sigpause`` always returns -1 (``ERROR``). On a successful wait for + a signal, the ``errno`` will be set to ``EINTR``. + +.. c:function:: int sigwaitinfo(const sigset_t *set, struct siginfo *info); + +Equivalent to sigtimedwait() with a NULL timeout parameter. (see below). + + :param set: The set of pending signals to wait for. + :param info: The returned signal values + + :return: + Signal number that cause the wait to be terminated, otherwise -1 + (``ERROR``) is returned. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int sigtimedwait(const sigset_t *set, struct siginfo *info, \ + const struct timespec *timeout); + + Selects the pending signal set specified + by the argument set. If multiple signals are pending in set, it will + remove and return the lowest numbered one. If no signals in set are + pending at the time of the call, the calling task will be suspended + until one of the signals in set becomes pending OR until the task + interrupted by an unblocked signal OR until the time interval specified + by timeout (if any), has expired. If timeout is NULL, then the timeout + interval is forever. + + If the info argument is non-NULL, the selected signal number is stored + in the si_signo member and the cause of the signal is store in the + si_code member. The content of si_value is only meaningful if the signal + was generated by sigqueue(). The following values for si_code are + defined in signal.h: + + - ``SI_USER``. Signal sent from kill, raise, or abort + - ``SI_QUEUE``. Signal sent from sigqueue + - ``SI_TIMER``. Signal is result of timer expiration + - ``SI_ASYNCIO``. Signal is the result of asynchronous IO completion + - ``SI_MESGQ``. Signal generated by arrival of a message on an empty + message queue. + + :param set: The set of pending signals to wait for. + :param info: The returned signal values + :param timeout: The amount of time to wait + + :return: Signal number that cause the wait to be terminated, otherwise -1 + (``ERROR``) is returned. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the POSIX interface include: + + - Values for si_codes differ + - No mechanism to return cause of ERROR. (It can be inferred from + si_code in a non-standard way). + - POSIX states that "If no signal is pending at the time of the call, + the calling task will be suspended until one or more signals in set + become pending or until it is interrupted by an unblocked, *caught* + signal." The present implementation does not require that the + unblocked signal be caught; the task will be resumed even if the + unblocked signal is ignored. + +.. c:function:: int sigqueue (int tid, int signo, union sigval value); + + Sends the signal specified by signo with + the signal parameter value to the task specified by tid. + + If the receiving task has the signal blocked via its sigprocmask, the + signal will pend until it is unmasked. Only one pending signal (for a + given signo) is retained by the system. This is consistent with POSIX + which states: "If a subsequent occurrence of a pending signal is + generated, it is implementation defined as to whether the signal is + delivered more than once." + + :param tid: ID of the task to receive signal + :param signo: Signal number + :param value: Value to pass to task with signal + + :return: + On success (at least one signal was sent), zero (``OK``) is returned. + On error, -1 (``ERROR``) is returned, and + ```errno`` <#ErrnoAccess>`__ is set appropriately. + + - ``EGAIN``. The limit of signals which may be queued has been + reached. + - ``EINVAL``. signo was invalid. + - ``EPERM``. The task does not have permission to send the signal to + the receiving process. + - ``ESRCH``. No process has a PID matching pid. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the POSIX interface include: + + - Default action is to ignore signals. + - Signals are processed one at a time in order + - POSIX states that, "If signo is zero (the null signal), error + checking will be performed but no signal is actually sent." There is + no null signal in the present implementation; a zero signal will be + sent. + +.. c:function:: int kill(pid_t pid, int sig); + + The kill() system call can be used to send any signal + to any task. + + If the receiving task has the signal blocked via its sigprocmask, the + signal will pend until it is unmasked. Only one pending signal (for a + given signo) is retained by the system. This is consistent with POSIX + which states: "If a subsequent occurrence of a pending signal is + generated, it is implementation defined as to whether the signal is + delivered more than once." + + :param pid: The id of the task to receive the signal. The POSIX + ``kill()`` specification encodes process group information as zero + and negative pid values. Only positive, non-zero values of pid are + supported by this implementation. ID of the task to receive signal + :param signo: The signal number to send. If signo is zero, no signal is + sent, but all error checking is performed. + + :return: OK or ERROR + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Differences from the POSIX interface include: + + - Default action is to ignore signals. + - Signals are processed one at a time in order + - Sending of signals to 'process groups' is not supported in NuttX. + +.. c:function:: int pause(void); + + Suspends the calling thread until delivery of a non-blocked signal. + + :return: Since ``pause()`` suspends thread execution + indefinitely unless interrupted a signal, there is no successful + completion return value. A value of -1 (``ERROR`` will always be + returned and errno set to indicate the error (``EINTR``). + + **POSIX Compatibility:** In the POSIX description of this function is + the ``pause()`` function will suspend the calling thread until delivery + of a signal whose action is either to execute a signal-catching function + or to terminate the process. This implementation only waits for any + non-blocked signal to be received. diff --git a/doc/reference/user/08_pthread.rst b/doc/reference/user/08_pthread.rst new file mode 100644 index 00000000000..fe51ab697e8 --- /dev/null +++ b/doc/reference/user/08_pthread.rst @@ -0,0 +1,1710 @@ +================== +Pthread Interfaces +================== + +NuttX does not support *processes* in the way that, say, Linux does. +NuttX only supports simple threads or tasks running within the same +address space. However, NuttX does support the concept of a *task +group*. A task group is the functional analog of a process: It is a +group that consists of the main task thread and of all of the pthreads +created by the main thread or any of the other pthreads within the task +group. Members of a task group share certain resources such as +environment variables, file descriptors, ``FILE`` streams, sockets, +pthread keys and open message queues. + +.. note:: Behavior of features related to task groups depend of NuttX + configuration settings. See also the\ `NuttX + Tasking `__\ page + and the\ `Tasks vs. Threads + FAQ `__\ for + additional information on tasks and threads in NuttX. + +The following pthread interfaces are supported in some form by NuttX: + +**pthread control interfaces**. Interfaces that allow you to create and +manage pthreads. + + - :c:func:`pthread_attr_init` + - :c:func:`pthread_attr_destroy` + - :c:func:`pthread_attr_setschedpolicy` + - :c:func:`pthread_attr_getschedpolicy` + - :c:func:`pthread_attr_setschedparam` + - :c:func:`pthread_attr_getschedparam` + - :c:func:`pthread_attr_setinheritsched` + - :c:func:`pthread_attr_getinheritsched` + - :c:func:`pthread_attr_setstacksize` + - :c:func:`pthread_attr_getstacksize` + - :c:func:`pthread_create` + - :c:func:`pthread_detach` + - :c:func:`pthread_exit` + - :c:func:`pthread_cancel` + - :c:func:`pthread_setcancelstate` + - :c:func:`pthread_setcanceltype` + - :c:func:`pthread_testcancel` + - :c:func:`pthread_cleanup_pop` + - :c:func:`pthread_cleanup_push` + - :c:func:`pthread_join` + - :c:func:`pthread_yield` + - :c:func:`pthread_self` + - :c:func:`pthread_getschedparam` + - :c:func:`pthread_setschedparam` + +**Thread Specific Data**. These interfaces can be used to create pthread +*keys* and then to access thread-specific data using these keys. Each +*task group* has its own set of pthread keys. NOTES: (1) pthread keys +create in one *task group* are not accessible in other task groups. (2) +The main task thread does not have thread-specific data. + + - :c:func:`pthread_key_create` + - :c:func:`pthread_setspecific` + - :c:func:`pthread_getspecific` + - :c:func:`pthread_key_delete` + +**pthread Mutexes**. + + - :c:func:`pthread_mutexattr_init` + - :c:func:`pthread_mutexattr_destroy` + - :c:func:`pthread_mutexattr_getpshared` + - :c:func:`pthread_mutexattr_setpshared` + - :c:func:`pthread_mutexattr_gettype` + - :c:func:`pthread_mutexattr_settype` + - :c:func:`pthread_mutexattr_getprotocol` + - :c:func:`pthread_mutexattr_setprotocol` + - :c:func:`pthread_mutex_init` + - :c:func:`pthread_mutex_destroy` + - :c:func:`pthread_mutex_lock` + - :c:func:`pthread_mutex_timedlock` + - :c:func:`pthread_mutex_trylock` + - :c:func:`pthread_mutex_unlock` + +**Condition Variables**. + + - :c:func:`pthread_condattr_init` + - :c:func:`pthread_condattr_destroy` + - :c:func:`pthread_cond_init` + - :c:func:`pthread_cond_destroy` + - :c:func:`pthread_cond_broadcast` + - :c:func:`pthread_cond_signal` + - :c:func:`pthread_cond_wait` + - :c:func:`pthread_cond_timedwait` + +**Barriers**. + + - :c:func:`pthread_barrierattr_init` + - :c:func:`pthread_barrierattr_destroy` + - :c:func:`pthread_barrierattr_setpshared` + - :c:func:`pthread_barrierattr_getpshared` + - :c:func:`pthread_barrier_init` + - :c:func:`pthread_barrier_destroy` + - :c:func:`pthread_barrier_wait` + +**Initialization**. + + - :c:func:`pthread_once` + +**Signals**. + + - :c:func:`pthread_kill` + - :c:func:`pthread_sigmask` + +No support for the following pthread interfaces is provided by NuttX: + + - ``pthread_atfork``. register fork handlers. + - ``pthread_attr_getdetachstate``. get and set the detachstate + attribute. + - ``pthread_attr_getguardsize``. get and set the thread guardsize + attribute. + - ``pthread_attr_getinheritsched``. get and set the inheritsched + attribute. + - ``pthread_attr_getscope``. get and set the contentionscope attribute. + - ``pthread_attr_getstack``. get and set stack attributes. + - ``pthread_attr_getstackaddr``. get and set the stackaddr attribute. + - ``pthread_attr_setdetachstate``. get and set the detachstate + attribute. + - ``pthread_attr_setguardsize``. get and set the thread guardsize + attribute. + - ``pthread_attr_setscope``. get and set the contentionscope attribute. + - ``pthread_attr_setstack``. get and set stack attributes. + - ``pthread_attr_setstackaddr``. get and set the stackaddr attribute. + - ``pthread_condattr_getclock``. set the clock selection condition + variable attribute. + - ``pthread_condattr_getpshared``. get the process-shared condition + variable attribute. + - ``pthread_condattr_setclock``. set the clock selection condition + variable attribute. + - ``pthread_condattr_setpshared``. set the process-shared condition + variable attribute. + - ``pthread_getconcurrency``. get and set the level of concurrency. + - ``pthread_getcpuclockid``. access a thread CPU-time clock. + - ``pthread_mutex_getprioceiling``. get and set the priority ceiling of + a mutex. + - ``pthread_mutex_setprioceiling``. get and set the priority ceiling of + a mutex. + - ``pthread_mutex_timedlock``. lock a mutex. + - ``pthread_mutexattr_getprioceiling``. get and set the prioceiling + attribute of the mutex attributes object. + - ``pthread_mutexattr_setprioceiling``. get and set the prioceiling + attribute of the mutex attributes object. + - ``pthread_rwlockattr_destroy``. destroy and initialize the read-write + lock attributes object. + - ``pthread_rwlockattr_getpshared``. get and set the process-shared + attribute of the read-write lock attributes object. + - ``pthread_rwlockattr_init``. destroy and initialize the read-write + lock attributes object. + - ``pthread_rwlockattr_setpshared``. get and set the process-shared + attribute of the read-write lock attributes object. + - ``pthread_setconcurrency``. get and set the level of concurrency. + - ``pthread_spin_destroy``. destroy or initialize a spin lock object. + - ``pthread_spin_init``. destroy or initialize a spin lock object. + - ``pthread_spin_lock``. lock a spin lock object. + - ``pthread_spin_trylock``. lock a spin lock object. + - ``pthread_spin_unlock``. unlock a spin lock object. + +.. c:function:: int pthread_attr_init(pthread_attr_t *attr); + + Initializes a thread attributes object (attr) with + default values for all of the individual attributes used by the + implementation. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_init()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_destroy(FAR pthread_attr_t *attr); + + An attributes object can be deleted when it is no + longer needed. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_destroy()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_setschedpolicy()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_getschedpolicy(FAR const pthread_attr_t *attr, FAR int *policy); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_getschedpolicy()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_setschedparam(pthread_attr_t *attr, \ + const struct sched_param *param); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_getschedpolicy()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_getschedparam(pthread_attr_t *attr, \ + struct sched_param *param); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_getschedparam()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_setinheritsched(pthread_attr_t *attr, \ + int inheritsched); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_setinheritsched()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_getinheritsched(const pthread_attr_t *attr, \ + int *inheritsched); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_getinheritsched()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_setstacksize(pthread_attr_t *attr, long stacksize); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_setstacksize()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_attr_getstacksize(FAR const pthread_attr_t *attr, FAR size_t *stackaddr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_attr_getstacksize()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_create(pthread_t *thread, pthread_attr_t *attr, \ + pthread_startroutine_t startRoutine, \ + pthread_addr_t arg); + + To create a thread object and runnable thread, a + routine must be specified as the new thread's start routine. An argument + may be passed to this routine, as an untyped address; an untyped address + may also be returned as the routine's value. An attributes object may be + used to specify details about the kind of thread being created. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_create()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_detach(pthread_t thread); + + A thread object may be "detached" to specify that the + return value and completion status will not be requested. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_detach()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: void pthread_exit(pthread_addr_t pvValue); + + A thread may terminate it's own execution. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_exit()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cancel(pthread_t thread); + + The ``pthread_cancel()`` function will request that thread be canceled. + The target thread's cancellability state, enabled, or disabled, + determines when the cancellation takes effect: When the cancellation is + acted on, thread will be terminated. When cancellability is disabled, + all cancellations are held pending in the target thread until the thread + re-enables cancellability. + + The target thread's cancellability state determines how the cancellation + is acted on: Either asynchronously or deferred. Asynchronous + cancellations will be acted upon immediately (when enabled), + interrupting the thread with its processing in an arbitrary state. + + When cancellability is deferred, all cancellations are held pending in + the target thread until the thread changes the cancellability type or a + `Cancellation + Point `__ + function such as ```pthread_testcancel()`` <#pthreadtestcancel>`__ is + entered. + + :param thread: Identifies the thread to be canceled. + + :return: + If successful, the ``pthread_cancel()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``ESRCH``. No thread could be found corresponding to that specified + by the given thread ID. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. Except: + + - The thread-specific data destructor functions will not be called for + the thread. These destructors are not currently supported. + +.. c:function:: int pthread_setcancelstate(int state, int *oldstate); + + The ``pthread_setcancelstate()`` function atomically sets both the + calling thread's cancellability state to the indicated state and returns + the previous cancellability state at the location referenced by + oldstate. Legal values for state are PTHREAD_CANCEL_ENABLE and + PTHREAD_CANCEL_DISABLE. + + Any pending thread cancellation may occur at the time that the + cancellation state is set to PTHREAD_CANCEL_ENABLE. + + **Input Parameters:** + + :param state: New cancellation state. One of PTHREAD_CANCEL_ENABLE or + PTHREAD_CANCEL_DISABLE. + :param oldstate: Location to return the previous cancellation state. + + :return: + If successful, the ``pthread_setcancelstate()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``ESRCH``. No thread could be found corresponding to that specified + by the given thread ID. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_setcanceltype(int type, FAR int *oldtype); + + The ``pthread_setcanceltype()`` function atomically + both sets the calling thread's cancellability type to the indicated type + and returns the previous cancellability type at the location referenced + by ``oldtype``. Legal values for type are ``PTHREAD_CANCEL_DEFERRED`` + and ``PTHREAD_CANCEL_ASYNCHRONOUS``. + + The cancellability state and type of any newly created threads are + ``PTHREAD_CANCEL_ENABLE`` and ``PTHREAD_CANCEL_DEFERRED respectively``. + + **Input Parameters:** + + :param type: New cancellation state. One of ``PTHREAD_CANCEL_DEFERRED`` + or ``PTHREAD_CANCEL_ASYNCHRONOUS``. + :param oldtype: Location to return the previous cancellation type. + + :return: + If successful, the ``pthread_setcancelstate()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: void pthread_testcancel(void); + + The ``pthread_testcancel()`` function creates a `Cancellation + Point `__ + in the calling thread. The ``pthread_testcancel()`` function has no + effect if cancellability is disabled. + + **Input Parameters:** None + + **Returned Value:** None + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: void pthread_cleanup_pop(int execute); + + The ``pthread_cleanup_pop()`` function will remove the routine at the + top of the calling thread's cancellation cleanup stack and optionally + invoke it (if ``execute`` is non-zero). + + **Input Parameters:** + + - ``execute``. Execute the popped cleanup function immediately. + + **Returned Value:** + + If successful, the ``pthread_setcancelstate()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: void pthread_cleanup_push(CODE void (*routine)(FAR void *), FAR void *arg); + + The ``pthread_cleanup_push()`` function will push the specified + cancellation cleanup handler routine onto the calling thread's + cancellation cleanup stack. + + The cancellation cleanup handler will be popped from the cancellation + cleanup stack and invoked with the argument arg when: + + - The thread exits (that is, calls ``pthread_exit()``). + - The thread acts upon a cancellation request. + - The thread calls ``pthread_cleanup_pop()`` with a non-zero execute + argument. + + **Input Parameters:** + + - ``routine``. The cleanup routine to be pushed on the cleanup stack. + - ``arg``. An argument that will accompany the callback. + + **Returned Value:** + + If successful, the ``pthread_setcancelstate()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error. + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_join(pthread_t thread, pthread_addr_t *ppvValue); + + A thread can await termination of another thread and + retrieve the return value of the thread. + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_join()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: void pthread_yield(void); + + A thread may tell the scheduler that its processor can + be made available. + + **Input Parameters:** + + - None + + **Returned Value:** + + - None. The ``pthread_yield()`` function always succeeds. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** This call is nonstandard, but present on + several other systems. Use the POSIX + ```sched_yield()`` <#sched_yield>`__ instead. + +.. c:function:: pthread_t pthread_self(void); + + A thread may obtain a copy of its own thread handle. + + **Input Parameters:** + + - None + + **Returned Value:** + + If successful, the ``pthread_self()`` function will return copy of + caller's thread handle. Otherwise, in exceptional circumstances, the + negated error code ``-ESRCH`` can be returned if the system cannot + deduce the identity of the calling thread. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. The ``-ESRCH`` return value is non-standard; POSIX says + ``pthread_self()`` must always succeed. NuttX implements + ``pthread_self()`` as a macro only, not as a function as required by + POSIX. + +.. c:function:: int pthread_getschedparam(pthread_t thread, int *policy, \ + struct sched_param *param); + + The ``pthread_getschedparam()`` functions will get the + scheduling policy and parameters of threads. For ``SCHED_FIFO`` and + ``SCHED_RR``, the only required member of the ``sched_param`` structure + is the priority ``sched_priority``. + + The ``pthread_getschedparam()`` function will retrieve the scheduling + policy and scheduling parameters for the thread whose thread ID is given + by ``thread`` and will store those values in ``policy`` and ``param``, + respectively. The priority value returned from + ``pthread_getschedparam()`` will be the value specified by the most + recent ``pthread_setschedparam()``, ``pthread_setschedprio()``, or + ``pthread_create()`` call affecting the target thread. It will not + reflect any temporary adjustments to its priority (such as might result + of any priority inheritance, for example). + + The policy parameter may have the value ``SCHED_FIFO``, ``SCHED_RR``, or + ``SCHED_SPORADIC``. ``SCHED_RR`` requires the configuration setting + ``CONFIG_RR_INTERVAL > 0``; ``SCHED_SPORADIC`` requires the + configuration setting ``CONFIG_SCHED_SPORADIC=y``. (``SCHED_OTHER`` and + non-standard scheduler policies, in particular, are not supported). The + ``SCHED_FIFO`` and ``SCHED_RR`` policies will have a single scheduling + parameter: + + - ``sched_priority`` The thread priority. + + The ``SCHED_SPORADIC`` policy has four additional scheduling parameters: + + - ``sched_ss_low_priority`` Low scheduling priority for sporadic + server. + - ``sched_ss_repl_period`` Replenishment period for sporadic server. + - ``sched_ss_init_budget`` Initial budget for sporadic server. + - ``sched_ss_max_repl`` Maximum pending replenishments for sporadic + server. + + **Input Parameters:** + + - ``thread``. The ID of thread whose scheduling parameters will be + queried. + - ``policy``. The location to store the thread's scheduling policy. + - ``param``. The location to store the thread's priority. + + **Returned Value:** 0 (``OK``) if successful. Otherwise, the error code + ``ESRCH`` if the value specified by ``thread`` does not refer to an + existing thread. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_setschedparam(pthread_t thread, int policy, \ + const struct sched_param *param); + + The ``pthread_setschedparam()`` functions will set the + scheduling policy and parameters of threads. For ``SCHED_FIFO`` and + ``SCHED_RR``, the only required member of the ``sched_param`` structure + is the priority ``sched_priority``. + + The ``pthread_setschedparam()`` function will set the scheduling policy + and associated scheduling parameters for the thread whose thread ID is + given by ``thread`` to the policy and associated parameters provided in + ``policy`` and ``param``, respectively. + + The policy parameter may have the value ``SCHED_FIFO`` or ``SCHED_RR``. + (``SCHED_OTHER`` and ``SCHED_SPORADIC``, in particular, are not + supported). The ``SCHED_FIFO`` and ``SCHED_RR`` policies will have a + single scheduling parameter, ``sched_priority``. + + If the ``pthread_setschedparam()`` function fails, the scheduling + parameters will not be changed for the target thread. + + **Input Parameters:** + + - ``thread``. The ID of thread whose scheduling parameters will be + modified. + - ``policy``. The new scheduling policy of the thread. Either + ``SCHED_FIFO`` or ``SCHED_RR``. ``SCHED_OTHER`` and + ``SCHED_SPORADIC`` are not supported. + - ``param``. The location to store the thread's priority. + + **Returned Value:** + + If successful, the ``pthread_setschedparam()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``EINVAL``. The value specified by ``policy`` or one of the + scheduling parameters associated with the scheduling policy + ``policy`` is invalid. + - ``ENOTSUP``. An attempt was made to set the policy or scheduling + parameters to an unsupported value (``SCHED_OTHER`` and + ``SCHED_SPORADIC`` in particular are not supported) + - ``EPERM``. The caller does not have the appropriate permission to set + either the scheduling parameters or the scheduling policy of the + specified thread. Or, the implementation does not allow the + application to modify one of the parameters to the value specified. + - ``ESRCH``. The value specified by thread does not refer to a existing + thread. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) + + This function creates a thread-specific data key visible to all threads + in the system. Although the same key value may be used by different + threads, the values bound to the key by ``pthread_setspecific()`` are + maintained on a per-thread basis and persist for the life of the calling + thread. + + Upon key creation, the value ``NULL`` will be associated with the new + key in all active threads. Upon thread creation, the value ``NULL`` will + be associated with all defined keys in the new thread. + + **Input Parameters:** + + - ``key`` is a pointer to the key to create. + - ``destructor`` is an optional destructor function that may be + associated with each key that is invoked when a thread exits. + However, this argument is ignored in the current implementation. + + **Returned Value:** + + If successful, the ``pthread_key_create()`` function will store the + newly created key value at ``*key`` and return zero (``OK``). Otherwise, + an error number will be returned to indicate the error: + + - ``EAGAIN``. The system lacked sufficient resources to create another + thread-specific data key, or the system-imposed limit on the total + number of keys per task {``PTHREAD_KEYS_MAX``} has been exceeded. + - ``ENOMEM`` Insufficient memory exists to create the key. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + + - The present implementation ignores the ``destructor`` argument. + +.. c:function:: int pthread_setspecific(pthread_key_t key, void *value) + + The ``pthread_setspecific()`` function associates a thread-specific + value with a key obtained via a previous call to + ``pthread_key_create()``. Different threads may bind different values to + the same key. These values are typically pointers to blocks of + dynamically allocated memory that have been reserved for use by the + calling thread. + + The effect of calling ``pthread_setspecific()`` with a key value not + obtained from ``pthread_key_create()`` or after a key has been deleted + with ``pthread_key_delete()`` is undefined. + + **Input Parameters:** + + - ``key``. The data key to set the binding for. + - ``value``. The value to bind to the key. + + **Returned Value:** + + If successful, ``pthread_setspecific()`` will return zero (``OK``). + Otherwise, an error number will be returned: + + - ``ENOMEM``. Insufficient memory exists to associate the value with + the key. + - ``EINVAL``. The key value is invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + + - ``pthread_setspecific()`` may be called from a thread-specific data + destructor function. + +.. c:function:: void *pthread_getspecific(pthread_key_t key) + + The ``pthread_getspecific()`` function returns the value currently bound + to the specified key on behalf of the calling thread. + + The effect of calling ``pthread_getspecific()`` with a key value not + obtained from ``pthread_key_create()`` or after a key has been deleted + with ``pthread_key_delete()`` is undefined. + + **Input Parameters:** + + - ``key``. The data key to get the binding for. + + **Returned Value:** + + The function ``pthread_getspecific()`` returns the thread-specific data + associated with the given key. If no thread specific data is associated + with the key, then the value ``NULL`` is returned. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + + - ``pthread_getspecific()`` may be called from a thread-specific data + destructor function. + +.. c:function:: int pthread_key_delete(pthread_key_t key) + + This POSIX function deletes a thread-specific data key previously + returned by ``pthread_key_create()``. No cleanup actions are done for + data structures related to the deleted key or associated thread-specific + data in any threads. It is undefined behavior to use ``key`` after it + has been deleted. + + **Input Parameters:** + + - ``key``. The key to delete + + **Returned Value:** + + If successful, the ``pthread_key_delete()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``EINVAL``. The parameter ``key`` is invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_init(pthread_mutexattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_init()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_destroy()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, \ + int *pshared); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_getpshared()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, \ + int pshared); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_setpshared()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_gettype(FAR const pthread_mutexattr_t *attr, FAR int *type); + + **Input Parameters:** + + - ``attr``. The mutex attributes to query + - ``type``. Location to return the mutex type. See + ```pthread_mutexattr_settype()`` <#pthreadmutexattrsettype>`__ for a + description of possible mutex types that may be returned. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_settype()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``EINVAL``. Parameters ``attr`` and/or ``attr`` are invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); + + Set the mutex type in the mutex attributes. + + **Input Parameters:** + + - ``attr``. The mutex attributes in which to set the mutex type. + - ``type``. The mutex type value to set. The following values are + supported: + + - ``PTHREAD_MUTEX_NORMAL``. This type of mutex does not detect + deadlock. A thread attempting to re-lock this mutex without first + unlocking it will deadlock. Attempting to unlock a mutex locked by + a different thread results in undefined behavior. Attempting to + unlock an unlocked mutex results in undefined behavior. + - ``PTHREAD_MUTEX_ERRORCHECK``. This type of mutex provides error + checking. A thread attempting to re-lock this mutex without first + unlocking it will return with an error. A thread attempting to + unlock a mutex which another thread has locked will return with an + error. A thread attempting to unlock an unlocked mutex will return + with an error. + - ``PTHREAD_MUTEX_RECURSIVE``. A thread attempting to re-lock this + mutex without first unlocking it will succeed in locking the + mutex. The re-locking deadlock which can occur with mutexes of + type PTHREAD_MUTEX_NORMAL cannot occur with this type of mutex. + Multiple locks of this mutex require the same number of unlocks to + release the mutex before another thread can acquire the mutex. A + thread attempting to unlock a mutex which another thread has + locked will return with an error. A thread attempting to unlock an + unlocked mutex will return with an error. + - ``PTHREAD_MUTEX_DEFAULT``. The default mutex type + (PTHREAD_MUTEX_NORMAL). + + In NuttX, ``PTHREAD_MUTEX_NORMAL`` is not implemented. Rather, the + behavior described for ``PTHREAD_MUTEX_ERRORCHECK`` is the *normal* + behavior. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_settype()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``EINVAL``. Parameters ``attr`` and/or ``attr`` are invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_getprotocol(FAR const pthread_mutexattr_t *attr, \ + FAR int *protocol); + + Return the value of the mutex protocol attribute.. + + **Input Parameters:** + + - ``attr``. A pointer to the mutex attributes to be queried + - ``protocol``. The user provided location in which to store the + protocol value. May be one of ``PTHREAD_PRIO_NONE``, or + ``PTHREAD_PRIO_INHERIT``, ``PTHREAD_PRIO_PROTECT``. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_getprotocol()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutexattr_setprotocol(FAR pthread_mutexattr_t *attr, \ + int protocol); + + Set mutex protocol attribute. See the paragraph + `Locking versus Signaling Semaphores <#lockingvssignaling>`__ for some + important information about the use of this interface. + + **Input Parameters:** + + - ``attr``. A pointer to the mutex attributes to be modified + - ``protocol``. The new protocol to use. One of ``PTHREAD_PRIO_NONE``, + or ``PTHREAD_PRIO_INHERIT``, ``PTHREAD_PRIO_PROTECT``. + ``PTHREAD_PRIO_INHERIT`` is supported only if + ``CONFIG_PRIORITY_INHERITANCE`` is defined; ``PTHREAD_PRIO_PROTECT`` + is not currently supported in any configuration. + + **Returned Value:** + + If successful, the ``pthread_mutexattr_setprotocol()`` function will + return zero (``OK``). Otherwise, an error number will be returned to + indicate the error. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutex_init(pthread_mutex_t *mutex, \ + pthread_mutexattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutex_init()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutex_destroy(pthread_mutex_t *mutex); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_mutex_destroy()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutex_lock(pthread_mutex_t *mutex); + + The mutex object referenced by mutex is locked by + calling ``pthread_mutex_lock()``. If the mutex is already locked, the + calling thread blocks until the mutex becomes available. This operation + returns with the mutex object referenced by mutex in the locked state + with the calling thread as its owner. + + If the mutex type is ``PTHREAD_MUTEX_NORMAL``, deadlock detection is not + provided. Attempting to re-lock the mutex causes deadlock. If a thread + attempts to unlock a mutex that it has not locked or a mutex which is + unlocked, undefined behavior results. + + In NuttX, ``PTHREAD_MUTEX_NORMAL`` is not implemented. Rather, the + behavior described for ``PTHREAD_MUTEX_ERRORCHECK`` is the *normal* + behavior. + + If the mutex type is ``PTHREAD_MUTEX_ERRORCHECK``, then error checking + is provided. If a thread attempts to re-lock a mutex that it has already + locked, an error will be returned. If a thread attempts to unlock a + mutex that it has not locked or a mutex which is unlocked, an error will + be returned. + + If the mutex type is ``PTHREAD_MUTEX_RECURSIVE``, then the mutex + maintains the concept of a lock count. When a thread successfully + acquires a mutex for the first time, the lock count is set to one. Every + time a thread re-locks this mutex, the lock count is incremented by one. + Each time the thread unlocks the mutex, the lock count is decremented by + one. When the lock count reaches zero, the mutex becomes available for + other threads to acquire. If a thread attempts to unlock a mutex that it + has not locked or a mutex which is unlocked, an error will be returned. + + If a signal is delivered to a thread waiting for a mutex, upon return + from the signal handler the thread resumes waiting for the mutex as if + it was not interrupted. + + **Input Parameters:** + + - ``mutex``. A reference to the mutex to be locked. + + **Returned Value:** + + If successful, the ``pthread_mutex_lock()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + Note that this function will never return the error EINTR. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abs_timeout); + + The ``pthread_mutex_timedlock()`` function will lock + the mutex object referenced by ``mutex``. If the mutex is already + locked, the calling thread will block until the mutex becomes available + as in the ```pthread_mutex_lock()`` <#pthreadmutexlock>`__ function. If + the mutex cannot be locked without waiting for another thread to unlock + the mutex, this wait will be terminated when the specified + ``abs_timeout`` expires. + + The timeout will expire when the absolute time specified by + ``abs_timeout`` passes, as measured by the clock on which timeouts are + based (that is, when the value of that clock equals or exceeds + ``abs_timeout``), or if the absolute time specified by ``abs_timeout`` + has already been passed at the time of the call. + + **Input Parameters:** + + - ``mutex``. A reference to the mutex to be locked. + - ``abs_timeout``. Maximum wait time (with ``NULL`` meaning to wait + forever). + + **Returned Value:** + + If successful, the ``pthread_mutex_trylock()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error. Note that the errno ``EINTR`` is never returned by + ``pthread_mutex_timedlock()``. The returned errno is ETIMEDOUT if the + mutex could not be locked before the specified timeout expired + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. This implementation does not return ``EAGAIN`` when the mutex + could not be acquired because the maximum number of recursive locks for + mutex has been exceeded. + +.. c:function:: int pthread_mutex_trylock(pthread_mutex_t *mutex); + + The function ``pthread_mutex_trylock()`` is identical + to ```pthread_mutex_lock()`` <#pthreadmutexlock>`__ except that if the + mutex object referenced by mutex is currently locked (by any thread, + including the current thread), the call returns immediately with the + ``errno`` ``EBUSY``. + + If a signal is delivered to a thread waiting for a mutex, upon return + from the signal handler the thread resumes waiting for the mutex as if + it was not interrupted. + + **Input Parameters:** + + - ``mutex``. A reference to the mutex to be locked. + + **Returned Value:** + + If successful, the ``pthread_mutex_trylock()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + Note that this function will never return the error EINTR. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_mutex_unlock(pthread_mutex_t *mutex); + + The ``pthread_mutex_unlock()`` function releases the mutex object + referenced by mutex. The manner in which a mutex is released is + dependent upon the mutex's type attribute. If there are threads blocked + on the mutex object referenced by mutex when ``pthread_mutex_unlock()`` + is called, resulting in the mutex becoming available, the scheduling + policy is used to determine which thread will acquire the mutex. (In the + case of ``PTHREAD_MUTEX_RECURSIVE`` mutexes, the mutex becomes available + when the count reaches zero and the calling thread no longer has any + locks on this mutex). + + If a signal is delivered to a thread waiting for a mutex, upon return + from the signal handler the thread resumes waiting for the mutex as if + it was not interrupted. + + **Input Parameters:** + + - ``mutex``. + + **Returned Value:** + + If successful, the ``pthread_mutex_unlock()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + Note that this function will never return the error EINTR. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_condattr_init(pthread_condattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_condattr_init()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_condattr_destroy(pthread_condattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_condattr_destroy()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_init()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_destroy(pthread_cond_t *cond); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_destroy()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_broadcast(pthread_cond_t *cond); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_broadcast()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_signal(pthread_cond_t *dond); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_signal()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_wait()`` function will return zero + (``OK``). Otherwise, an error number will be returned to indicate the + error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, \ + const struct timespec *abstime); + + **Input Parameters:** + + - ``To be provided``. + + **Returned Value:** + + If successful, the ``pthread_cond_timedwait()`` function will return + zero (``OK``). Otherwise, an error number will be returned to indicate + the error: + + - ``To be provided``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrierattr_init(FAR pthread_barrierattr_t *attr); + + The ``pthread_barrierattr_init()`` function will + initialize a barrier attribute object ``attr`` with the default value + for all of the attributes defined by the implementation. + + **Input Parameters:** + + - ``attr``. Barrier attributes to be initialized. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if ``attr`` is + invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrierattr_destroy(FAR pthread_barrierattr_t *attr); + + The ``pthread_barrierattr_destroy()`` function will + destroy a barrier attributes object. A destroyed attributes object can + be reinitialized using ``pthread_barrierattr_init()``; the results of + otherwise referencing the object after it has been destroyed are + undefined. + + **Input Parameters:** + + - ``attr``. Barrier attributes to be destroyed. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if attr is + invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrierattr_setpshared(FAR pthread_barrierattr_t *attr, int pshared); + + The process-shared attribute is set to + ``PTHREAD_PROCESS_SHARED`` to permit a barrier to be operated upon by + any thread that has access to the memory where the barrier is allocated. + If the process-shared attribute is ``PTHREAD_PROCESS_PRIVATE``, the + barrier can only be operated upon by threads created within the same + process as the thread that initialized the barrier. If threads of + different processes attempt to operate on such a barrier, the behavior + is undefined. The default value of the attribute is + ``PTHREAD_PROCESS_PRIVATE``. + + **Input Parameters:** + + - ``attr``. Barrier attributes to be modified. + - ``pshared``. The new value of the pshared attribute. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if either + ``attr`` is invalid or ``pshared`` is not one of + ``PTHREAD_PROCESS_SHARED`` or ``PTHREAD_PROCESS_PRIVATE``. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrierattr_getpshared(FAR const pthread_barrierattr_t *attr, FAR int *pshared); + + The ``pthread_barrierattr_getpshared()`` function will + obtain the value of the process-shared attribute from the attributes + object referenced by ``attr``. + + **Input Parameters:** + + - ``attr``. Barrier attributes to be queried. + - ``pshared``. The location to stored the current value of the pshared + attribute. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if either + ``attr`` or ``pshared`` is invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrier_init(FAR pthread_barrier_t *barrier, \ + FAR const pthread_barrierattr_t *attr, unsigned int count); + + The ``pthread_barrier_init()`` function allocates any + resources required to use the barrier referenced by ``barrier`` and + initialized the barrier with the attributes referenced by ``attr``. If + ``attr`` is NULL, the default barrier attributes will be used. The + results are undefined if ``pthread_barrier_init()`` is called when any + thread is blocked on the barrier. The results are undefined if a barrier + is used without first being initialized. The results are undefined if + ``pthread_barrier_init()`` is called specifying an already initialized + barrier. + + **Input Parameters:** + + - ``barrier``. The barrier to be initialized. + - ``attr``. Barrier attributes to be used in the initialization. + - ``count``. The count to be associated with the barrier. The count + argument specifies the number of threads that must call + ``pthread_barrier_wait()`` before any of them successfully return + from the call. The value specified by count must be greater than + zero. + + **Returned Value:** 0 (``OK``) on success or one of the following error + numbers: + + - ``EAGAIN``. The system lacks the necessary resources to initialize + another barrier. + - ``EINVAL``. The ``barrier`` reference is invalid, or the values + specified by ``attr`` are invalid, or the value specified by + ``count`` is equal to zero. + - ``ENOMEM``. Insufficient memory exists to initialize the barrier. + - ``EBUSY``. The implementation has detected an attempt to reinitialize + a barrier while it is in use. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrier_destroy(FAR pthread_barrier_t *barrier); + + The ``pthread_barrier_destroy()`` function destroys the + barrier referenced by ``barrie`` and releases any resources used by the + barrier. The effect of subsequent use of the barrier is undefined until + the barrier is reinitialized by another call to + ``pthread_barrier_init()``. The results are undefined if + ``pthread_barrier_destroy()`` is called when any thread is blocked on + the barrier, or if this function is called with an uninitialized + barrier. + + **Input Parameters:** + + - ``barrier``. The barrier to be destroyed. + + **Returned Value:** 0 (``OK``) on success or one of the following error + numbers: + + - ``EBUSY``. The implementation has detected an attempt to destroy a + barrier while it is in use. + - ``EINVAL``. The value specified by ``barrier`` is invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_barrier_wait(FAR pthread_barrier_t *barrier); + + The ``pthread_barrier_wait()`` function synchronizes + participating threads at the barrier referenced by ``barrier``. The + calling thread is blocked until the required number of threads have + called ``pthread_barrier_wait()`` specifying the same ``barrier``. When + the required number of threads have called ``pthread_barrier_wait()`` + specifying the ``barrier``, the constant + ``PTHREAD_BARRIER_SERIAL_THREAD`` will be returned to one unspecified + thread and zero will be returned to each of the remaining threads. At + this point, the barrier will be reset to the state it had as a result of + the most recent ``pthread_barrier_init()`` function that referenced it. + + The constant ``PTHREAD_BARRIER_SERIAL_THREAD`` is defined in + ``pthread.h`` and its value must be distinct from any other value + returned by ``pthread_barrier_wait()``. + + The results are undefined if this function is called with an + uninitialized barrier. + + If a signal is delivered to a thread blocked on a barrier, upon return + from the signal handler the thread will resume waiting at the barrier if + the barrier wait has not completed. Otherwise, the thread will continue + as normal from the completed barrier wait. Until the thread in the + signal handler returns from it, it is unspecified whether other threads + may proceed past the barrier once they have all reached it. + + A thread that has blocked on a barrier will not prevent any unblocked + thread that is eligible to use the same processing resources from + eventually making forward progress in its execution. Eligibility for + processing resources will be determined by the scheduling policy. + + **Input Parameters:** + + - ``barrier``. The barrier on which to wait. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if the barrier + is not valid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_once(FAR pthread_once_t *once_control, CODE void (*init_routine)(void)); + + The first call to ``pthread_once()`` by any thread with + a given ``once_control``, will call the ``init_routine()`` with no + arguments. Subsequent calls to ``pthread_once()`` with the same + ``once_control`` will have no effect. On return from ``pthread_once()``, + ``init_routine()`` will have completed. + + **Input Parameters:** + + - ``once_control``. Determines if ``init_routine()`` should be called. + ``once_control`` should be declared and initialized as follows: + + ``PTHREAD_ONCE_INIT`` is defined in ``pthread.h``. + - ``init_routine``. The initialization routine that will be called + once. + + **Returned Value:** 0 (``OK``) on success or ``EINVAL`` if either + once_control or init_routine are invalid. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_kill(pthread_t thread, int signo) + + The ``pthread_kill()`` system call can be used to send + any signal to a thread. See ``kill()`` for further information as this + is just a simple wrapper around the ``kill()`` function. + + **Input Parameters:** + + - ``thread``. The id of the thread to receive the signal. Only + positive, non-zero values of ``tthread``\ t are supported. + - ``signo``. The signal number to send. If ``signo`` is zero, no signal + is sent, but all error checking is performed. + + **Returned Value:** + + On success, the signal was sent and zero is returned. On error one of + the following error numbers is returned. + + - ``EINVAL``. An invalid signal was specified. + - ``EPERM``. The thread does not have permission to send the signal to + the target thread. + - ``ESRCH``. No thread could be found corresponding to that specified + by the given thread ID. + - ``ENOSYS``. Do not support sending signals to process groups. + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. + +.. c:function:: int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset); + + This function is a simple wrapper around + ``sigprocmask()``. See the ``sigprocmask()`` function description for + further information. + + **Input Parameters:** + + - ``how``. How the signal mast will be changed: + + - ``SIG_BLOCK``: The resulting set is the union of the current set + and the signal set pointed to by ``set``. + - ``SIG_UNBLOCK``: The resulting set is the intersection of the + current set and the complement of the signal set pointed to by + ``set``. + - ``SIG_SETMASK``: The resulting set is the signal set pointed to by + ``set``. + + - ``set``. Location of the new signal mask. + - ``oset``. Location to store the old signal mask. + + **Returned Value:** + + **Assumptions/Limitations:** + + **POSIX Compatibility:** Comparable to the POSIX interface of the same + name. diff --git a/doc/reference/user/09_env_vars.rst b/doc/reference/user/09_env_vars.rst new file mode 100644 index 00000000000..74a1d3f17b5 --- /dev/null +++ b/doc/reference/user/09_env_vars.rst @@ -0,0 +1,95 @@ +===================== +Environment Variables +===================== + +NuttX supports environment variables that can be used to +control the behavior of programs. In the spirit of NuttX the environment +variable behavior attempts to emulate the behavior of environment +variables in the multi-processing OS: + +- **Task environments**. When a new task is created using + `task_create <#taskcreate>`__, the environment of the child task is + an inherited, exact copy of the environment of the parent. However, + after child task has been created, subsequent operations by the child + task on its environment does not alter the environment of the parent. + No do operations by the parent effect the child's environment. The + environments start identical but are independent and may diverge. +- **Thread environments**. When a pthread is created using + `pthread_create <#pthreadcreate>`__, the child thread also inherits + that environment of the parent. However, the child does not receive a + copy of the environment but, rather, shares the same environment. + Changes to the environment are visible to all threads with the same + parentage. + +Programming Interfaces +====================== + +The following environment variable +programming interfaces are provided by Nuttx and are described in detail +in the following paragraphs. + + - :c:func:`getenv` + - :c:func:`putenv` + - :c:func:`clearenv` + - :c:func:`setenv` + - :c:func:`unsetenv` + +Disabling Environment Variable Support +====================================== + +All support for environment +variables can be disabled by setting ``CONFIG_DISABLE_ENVIRON`` in the +board configuration file. + +Functions +========= + +.. c:function:: FAR char *getenv(const char *name) + + Searches the environment list for a string that matches + the string pointed to by ``name``. + + :param name: The name of the variable to find. + + :return: + The value of the variable (read-only) or NULL on failure. + +.. c:function:: int putenv(char *string) + + Adds or changes the value of environment variables. The + argument string is of the form ``name=value``. If name does + not already exist in the environment, then string is added + to the environment. If name does exist, then the value of name in the + environment is changed to value. + + :param string: ``name=value`` string describing the environment setting to + add/modify. + + :return: Zero on success. + +.. c:function:: int clearenv(void) + + Clears the environment of all name-value pairs and sets + the value of the external variable environ to NULL. + + :return: Zero on success. + +.. c:function:: int setenv(const char *name, const char *value, int overwrite) + + Adds the variable ``name`` to the environment with the specified + ``value`` if the variable ``name`` does not exist. If the ``name`` + does exist in the environment, then its value is changed to ``value`` + if ``overwrite`` is non-zero; if + ``overwrite`` is zero, then the value of ``name`` is unaltered. + + :param name: The name of the variable to change. + :param value: The new value of the variable. + :param value: Replace any existing value if non-zero. + :return: Zero on success. + +.. c:function:: int unsetenv(const char *name) + + Deletes the variable ``name`` from the environment. + + :param name: The name of the variable to delete. + :return: Zero on success. diff --git a/doc/reference/user/10_filesystem.rst b/doc/reference/user/10_filesystem.rst new file mode 100644 index 00000000000..481fe94e9d8 --- /dev/null +++ b/doc/reference/user/10_filesystem.rst @@ -0,0 +1,573 @@ +====================== +File System Interfaces +====================== + +NuttX File System Overview +========================== + +**Overview**. NuttX includes an optional, scalable file system. This +file-system may be omitted altogether; NuttX does not depend on the +presence of any file system. + +**Pseudo Root File System**. A simple *in-memory*, *pseudo* file system +can be enabled by default. This is an *in-memory* file system because it +does not require any storage medium or block driver support. Rather, +file system contents are generated on-the-fly as referenced via standard +file system operations (open, close, read, write, etc.). In this sense, +the file system is *pseudo* file system (in the same sense that the +Linux ``/proc`` file system is also referred to as a pseudo file +system). + +Any user supplied data or logic can be accessed via the pseudo-file +system. Built in support is provided for character and block +`driver `__ *nodes* in the any +pseudo file system directory. (By convention, however, all driver nodes +should be in the ``/dev`` pseudo file system directory). + +**Mounted File Systems** The simple in-memory file system can be +extended my mounting block devices that provide access to true file +systems backed up via some mass storage device. NuttX supports the +standard ``mount()`` command that allows a block driver to be bound to a +mount-point within the pseudo file system and to a a file system. At +present, NuttX supports only the VFAT file system. + +**Comparison to Linux** From a programming perspective, the NuttX file +system appears very similar to a Linux file system. However, there is a +fundamental difference: The NuttX root file system is a pseudo file +system and true file systems may be mounted in the pseudo file system. +In the typical Linux installation by comparison, the Linux root file +system is a true file system and pseudo file systems may be mounted in +the true, root file system. The approach selected by NuttX is intended +to support greater scalability from the very tiny platform to the +moderate platform. + +**File System Interfaces**. The NuttX file system simply supports a set +of standard, file system APIs (``open()``, ``close()``, ``read()``, +``write``, etc.) and a registration mechanism that allows devices +drivers to a associated with *nodes* in a file-system-like name space. + +Driver Operations +================= + +``fcntl.h`` +----------- + +.. c:function:: int creat(FAR const char *path, mode_t mode); + +.. c:function:: int open(FAR const char *path, int oflag, ...); + +.. c:function:: int fcntl(int fd, int cmd, ...); + +``unistd.h`` +------------ + +.. c:function:: int close(int fd); +.. c:function:: int dup(int fd); +.. c:function:: int dup2(int fd1, int fd2); +.. c:function:: off_t lseek(int fd, off_t offset, int whence); +.. c:function:: ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset); +.. c:function:: ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset); +.. c:function:: ssize_t read(int fd, void *buf, size_t nbytes); +.. c:function:: int unlink(const char *path); +.. c:function:: ssize_t write(int fd, const void *buf, size_t nbytes); + +``sys/ioctl.h`` +--------------- + +.. c:function:: int ioctl(int fd, int req, ...) + +``poll.h`` +---------- + +.. c:function:: int poll(struct pollfd *fds, nfds_t nfds, int timeout) + + Waits for one of a set of file descriptors + to become ready to perform I/O. If none of the events requested (and no + error) has occurred for any of the file descriptors, then ``poll()`` + blocks until one of the events occurs. + + **Configuration Settings**. In order to use the select with TCP/IP + sockets test, you must have the following things selected in your NuttX + configuration file: + + - ``CONFIG_NET`` Defined for general network support + - ``CONFIG_NET_TCP`` Defined for TCP/IP support + + In order to for select to work with incoming connections, you must also + select: + + - ``CONFIG_NET_TCPBACKLOG`` Incoming connections pend in a backlog + until ``accept()`` is called. The size of the backlog is selected + when ``listen()`` is called. + + :param fds: List of structures describing file descriptors to be + monitored. + :param nfds: The number of entries in the list. + :param timeout: Specifies an upper limit on the time for which + ``poll()`` will block in milliseconds. A negative value of + ``timeout`` means an infinite timeout. + + :return: + On success, the number of structures that have nonzero ``revents`` + fields. A value of 0 indicates that the call timed out and no file + descriptors were ready. On error, -1 is returned, and ``errno`` is set + appropriately: + + - ``EBADF``. An invalid file descriptor was given in one of the sets. + - ``EFAULT``. The fds address is invalid + - ``EINTR``. A signal occurred before any requested event. + - ``EINVAL``. The nfds value exceeds a system limit. + - ``ENOMEM``. There was no space to allocate internal data structures. + - ``ENOSYS``. One or more of the drivers supporting the file descriptor + does not support the poll method. + +``sys/select.h`` +---------------- + +.. c:function:: int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, \ + FAR fd_set *exceptfds, FAR struct timeval *timeout) + + Allows a program to monitor multiple file + descriptors, waiting until one or more of the file descriptors become + "ready" for some class of I/O operation (e.g., input possible). A file + descriptor is considered ready if it is possible to perform the + corresponding I/O operation (e.g., read(2)) without blocking. + + **NOTE:** ```poll()`` <#poll>`__ is the fundamental API for performing + such monitoring operation under NuttX. ``select()`` is provided for + compatibility and is simply a layer of added logic on top of ``poll()``. + As such, ``select()`` is more wasteful of resources and + ```poll()`` <#poll>`__ is the recommended API to be used. + + :param nfds: the maximum file descriptor number (+1) of any descriptor + in any of the three sets. + :param readfds: the set of descriptions to monitor for read-ready events + :param writefds: the set of descriptions to monitor for write-ready + events + :param exceptfds: the set of descriptions to monitor for error events + :param timeout: Return at this time if none of these events of interest + occur. + + :return: + - ``0:`` Timer expired + - ``>0:`` The number of bits set in the three sets of descriptors + - ``-1:`` An error occurred (``errno`` will be set appropriately, see + ```poll()`` <#poll>`__). + +Directory Operations (``dirent.h``) +----------------------------------- + +.. c:function:: int closedir(DIR *dirp); + +.. c:function:: FAR DIR *opendir(const char *path); + +.. c:function:: FAR struct dirent *readdir(FAR DIR *dirp); + +.. c:function:: int readdir_r(FAR DIR *dirp, FAR struct dirent *entry, FAR struct dirent **result); + +.. c:function:: void rewinddir(FAR DIR *dirp); + +.. c:function:: void seekdir(FAR DIR *dirp, int loc); + +.. c:function:: int telldir(FAR DIR *dirp); + + +UNIX Standard Operations (``unistd.h``) +--------------------------------------- + +.. code-block:: c + + #include + + /* Task Control Interfaces */ + + pid_t vfork(void); + pid_t getpid(void); + void _exit(int status) noreturn_function; + unsigned int sleep(unsigned int seconds); + void usleep(unsigned long usec); + int pause(void); + + /* File descriptor operations */ + + int close(int fd); + int dup(int fd); + int dup2(int fd1, int fd2); + int fsync(int fd); + off_t lseek(int fd, off_t offset, int whence); + ssize_t read(int fd, FAR void *buf, size_t nbytes); + ssize_t write(int fd, FAR const void *buf, size_t nbytes); + ssize_t pread(int fd, FAR void *buf, size_t nbytes, off_t offset); + ssize_t pwrite(int fd, FAR const void *buf, size_t nbytes, off_t offset); + + /* Check if a file descriptor corresponds to a terminal I/O file */ + + int isatty(int fd); + + /* Memory management */ + + #if defined(CONFIG_ARCH_ADDRENV) && defined(CONFIG_MM_PGALLOC) && \ + defined(CONFIG_ARCH_USE_MMU) + FAR void *sbrk(intptr_t incr); + #endif + + /* Special devices */ + + int pipe(int fd[2]); + + /* Working directory operations */ + + int chdir(FAR const char *path); + FAR char *getcwd(FAR char *buf, size_t size); + + /* File path operations */ + + int access(FAR const char *path, int amode); + int rmdir(FAR const char *pathname); + int unlink(FAR const char *pathname); + + #ifdef CONFIG_PSEUDOFS_SOFTLINKS + int link(FAR const char *path1, FAR const char *path2); + ssize_t readlink(FAR const char *path, FAR char *buf, size_t bufsize); + #endif + + /* Execution of programs from files */ + + #ifdef CONFIG_LIBC_EXECFUNCS + int execl(FAR const char *path, ...); + int execv(FAR const char *path, FAR char * const argv[]); + #endif + + /* Networking */ + + #ifdef CONFIG_NET + int gethostname(FAR char *name, size_t size); + int sethostname(FAR const char *name, size_t size); + #endif + + /* Other */ + + int getopt(int argc, FAR char * const argv[], FAR const char *optstring); + +Standard I/O +------------ + +.. code-block:: c + + #include + + /* Operations on streams (FILE) */ + + void clearerr(FAR FILE *stream); + int fclose(FAR FILE *stream); + int fflush(FAR FILE *stream); + int feof(FAR FILE *stream); + int ferror(FAR FILE *stream); + int fileno(FAR FILE *stream); + int fgetc(FAR FILE *stream); + int fgetpos(FAR FILE *stream, FAR fpos_t *pos); + FAR char *fgets(FAR char *s, int n, FAR FILE *stream); + FAR FILE *fopen(FAR const char *path, FAR const char *type); + int fprintf(FAR FILE *stream, FAR const char *format, ...); + int fputc(int c, FAR FILE *stream); + int fputs(FAR const char *s, FAR FILE *stream); + size_t fread(FAR void *ptr, size_t size, size_t n_items, FAR FILE *stream); + FAR FILE *freopen(FAR const char *path, FAR const char *mode, + FAR FILE *stream); + int fseek(FAR FILE *stream, long int offset, int whence); + int fsetpos(FAR FILE *stream, FAR fpos_t *pos); + long ftell(FAR FILE *stream); + size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream); + FAR char *gets(FAR char *s); + FAR char *gets_s(FAR char *s, rsize_t n); + void setbuf(FAR FILE *stream, FAR char *buf); + int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size); + int ungetc(int c, FAR FILE *stream); + + /* Operations on the stdout stream, buffers, paths, and the whole printf-family * / + + int printf(FAR const char *format, ...); + int puts(FAR const char *s); + int rename(FAR const char *source, FAR const char *target); + int sprintf(FAR char *dest, FAR const char *format, ...); + int asprintf(FAR char **ptr, FAR const char *fmt, ...); + int snprintf(FAR char *buf, size_t size, FAR const char *format, ...); + int sscanf(FAR const char *buf, FAR const char *fmt, ...); + void perror(FAR const char *s); + + int vprintf(FAR const char *s, va_list ap); + int vfprintf(FAR FILE *stream, FAR const char *s, va_list ap); + int vsprintf(FAR char *buf, FAR const char *s, va_list ap); + int vasprintf(FAR char **ptr, FAR const char *fmt, va_list ap); + int vsnprintf(FAR char *buf, size_t size, FAR const char *format, va_list ap); + int vsscanf(FAR char *buf, FAR const char *s, va_list ap); + + /* Operations on file descriptors including: + * + * POSIX-like File System Interfaces (fdopen), and + * Extensions from the Open Group Technical Standard, 2006, Extended API Set + * Part 1 (dprintf and vdprintf) + */ + + FAR FILE *fdopen(int fd, FAR const char *type); + int dprintf(int fd, FAR const char *fmt, ...); + int vdprintf(int fd, FAR const char *fmt, va_list ap); + + /* Operations on paths */ + + FAR char *tmpnam(FAR char *s); + FAR char *tempnam(FAR const char *dir, FAR const char *pfx); + int remove(FAR const char *path); + + #include + + int mkdir(FAR const char *pathname, mode_t mode); + int mkfifo(FAR const char *pathname, mode_t mode); + int stat(FAR const char *path, FAR struct stat *buf); + int fstat(int fd, FAR struct stat *buf); + + #include + + int statfs(FAR const char *path, FAR struct statfs *buf); + int fstatfs(int fd, FAR struct statfs *buf); + +Standard Library (``stdlib.h``) +------------------------------- + +Generally addresses other operating system interfaces. +However, the following may also be considered as file system interfaces: + +.. c:function:: int mktemp(FAR char *template); +.. c:function:: int mkstemp(FAR char *template); + +Asynchronous I/O +---------------- + +.. code-block:: c + + #include + + int aio_cancel(int, FAR struct aiocb *aiocbp); + int aio_error(FAR const struct aiocb *aiocbp); + int aio_fsync(int, FAR struct aiocb *aiocbp); + int aio_read(FAR struct aiocb *aiocbp); + ssize_t aio_return(FAR struct aiocb *aiocbp); + int aio_suspend(FAR const struct aiocb * const list[], int nent, + FAR const struct timespec *timeout); + int aio_write(FAR struct aiocb *aiocbp); + int lio_listio(int mode, FAR struct aiocb * const list[], int nent, + FAR struct sigevent *sig); + +Standard String Operations +-------------------------- + +.. code-block:: c + + #include + + char *strchr(const char *s, int c); + FAR char *strdup(const char *s); + const char *strerror(int); + size_t strlen(const char *); + size_t strnlen(const char *, size_t); + char *strcat(char *, const char *); + char *strncat(char *, const char *, size_t); + int strcmp(const char *, const char *); + int strncmp(const char *, const char *, size_t); + int strcasecmp(const char *, const char *); + int strncasecmp(const char *, const char *, size_t); + char *strcpy(char *dest, const char *src); + char *strncpy(char *, const char *, size_t); + char *strpbrk(const char *, const char *); + char *strchr(const char *, int); + char *strrchr(const char *, int); + size_t strspn(const char *, const char *); + size_t strcspn(const char *, const char *); + char *strstr(const char *, const char *); + char *strtok(char *, const char *); + char *strtok_r(char *, const char *, char **); + + void *memset(void *s, int c, size_t n); + void *memcpy(void *dest, const void *src, size_t n); + int memcmp(const void *s1, const void *s2, size_t n); + void *memmove(void *dest, const void *src, size_t count); + + #include + + #define bcmp(b1,b2,len) memcmp(b1,b2,(size_t)len) + #define bcopy(b1,b2,len) (void)memmove(b2,b1,len) + #define bzero(s,n) (void)memset(s,0,n) + #define index(s,c) strchr(s,c) + #define rindex(s,c) strrchr(s,c) + + int ffs(int j); + int strcasecmp(const char *, const char *); + int strncasecmp(const char *, const char *, size_t); + +Pipes and FIFOs +--------------- + +.. c:function:: int pipe(int fd[2]) + + Creates a pair of file descriptors, pointing to a pipe inode, + and places them in the array pointed to by ``fd``. + + :param fd: The user provided array in which to catch the pipe file + descriptors. ``fd[0]`` is for reading, ``fd[1]`` is for writing. + + :return: 0 is returned on success; otherwise, -1 is returned with errno set appropriately. + +.. c:function:: int mkfifo(FAR const char *pathname, mode_t mode); + + mkfifo() makes a FIFO device driver file with name pathname. Unlike Linux, + a NuttX FIFO is not a special file type but simply a device driver instance. + mode specifies the FIFO's permissions (but is ignored in the current implementation). + + Once the FIFO has been created by mkfifo(), any thread can open it for reading + or writing, in the same way as an ordinary file. However, it must have been + opened from both reading and writing before input or output can be performed. + This FIFO implementation will block all attempts to open a FIFO read-only + until at least one thread has opened the FIFO for writing. + + If all threads that write to the FIFO have closed, subsequent calls to + read() on the FIFO will return 0 (end-of-file). + + :param pathname: The full path to the FIFO instance to attach to or to + create (if not already created). + :param mode: Ignored for now + + :return: 0 is returned on success; otherwise, -1 is returned with errno set appropriately. + +``mmap()`` and eXecute In Place (XIP) +------------------------------------- + +NuttX operates in a flat open address space and is focused on MCUs that +do support Memory Management Units (MMUs). Therefore, NuttX generally +does not require ``mmap()`` functionality and the MCUs generally cannot +support true memory-mapped files. + +However, memory mapping of files is the mechanism used by NXFLAT, the +NuttX tiny binary format, to get files into memory in order to execute +them. ``mmap()`` support is therefore required to support NXFLAT. There +are two conditions where ``mmap()`` can be supported: + +1. ``mmap()`` can be used to support *eXecute In Place* (XIP) on random + access media under the following very restrictive conditions: + + a. The file-system supports the ``FIOC_MMAP`` ioctl command. Any file + system that maps files contiguously on the media should support + this ``ioctl`` command. By comparison, most file system scatter + files over the media in non-contiguous sectors. As of this + writing, ROMFS is the only file system that meets this + requirement. + + b. The underlying block driver supports the ``BIOC_XIPBASE`` + ``ioctl`` command that maps the underlying media to a randomly + accessible address. At present, only the RAM/ROM disk driver does + this. + + Some limitations of this approach are as follows: + + a. Since no real mapping occurs, all of the file contents are + "mapped" into memory. + + b. All mapped files are read-only. + + c. There are no access privileges. + +2. If ``CONFIG_FS_RAMMAP`` is defined in the configuration, then + ``mmap()`` will support simulation of memory mapped files by copying + files whole into RAM. These copied files have some of the properties + of standard memory mapped files. There are many, many exceptions + exceptions, however. Some of these include: + + a. The goal is to have a single region of memory that represents a + single file and can be shared by many threads. That is, given a + filename a thread should be able to open the file, get a file + descriptor, and call ``mmap()`` to get a memory region. Different + file descriptors opened with the same file path should get the + same memory region when mapped. + + The limitation in the current design is that there is insufficient + knowledge to know that these different file descriptors correspond + to the same file. So, for the time being, a new memory region is + created each time that ``rammmap()`` is called. Not very useful! + + b. The entire mapped portion of the file must be present in memory. + Since it is assumed that the MCU does not have an MMU, + on-demanding paging in of file blocks cannot be supported. Since + the while mapped portion of the file must be present in memory, + there are limitations in the size of files that may be memory + mapped (especially on MCUs with no significant RAM resources). + + c. All mapped files are read-only. You can write to the in-memory + image, but the file contents will not change. + + d. There are no access privileges. + + e. Since there are no processes in NuttX, all ``mmap()`` and + ``munmap()`` operations have immediate, global effects. Under + Linux, for example, ``munmap()`` would eliminate only the mapping + with a process; the mappings to the same file in other processes + would not be effected. + + f. Like true mapped file, the region will persist after closing the + file descriptor. However, at present, these ram copied file + regions are *not* automatically "unmapped" (i.e., freed) when a + thread is terminated. This is primarily because it is not possible + to know how many users of the mapped region there are and, + therefore, when would be the appropriate time to free the region + (other than when munmap is called). + + NOTE: Note, if the design limitation of a) were solved, then it + would be easy to solve exception d) as well. + +.. c:function:: FAR void *mmap(FAR void *start, size_t length, int prot, int flags, int fd, off_t offset); + + Provides minimal mmap() as needed to support eXecute In Place (XIP) operation (as described above). + + :param start: A hint at where to map the memory -- ignored. The address + of the underlying media is fixed and cannot be re-mapped without MMU + support. + :param length: The length of the mapping -- ignored. The entire + underlying media is always accessible. + :param prot: See the ``PROT_*`` definitions in ``sys/mman.h``. + + - ``PROT_NONE`` - Will cause an error. + - ``PROT_READ`` - ``PROT_WRITE`` and ``PROT_EXEC`` also assumed. + - ``PROT_WRITE`` - ``PROT_READ`` and ``PROT_EXEC`` also assumed. + - ``PROT_EXEC`` - ``PROT_READ`` and ``PROT_WRITE`` also assumed. + + :param flags: See the ``MAP_*`` definitions in ``sys/mman.h``. + + - ``MAP_SHARED`` - Required + - ``MAP_PRIVATE`` - Will cause an error + - ``MAP_FIXED`` - Will cause an error + - ``MAP_FILE`` - Ignored + - ``MAP_ANONYMOUS`` - Will cause an error + - ``MAP_ANON`` - Will cause an error + - ``MAP_GROWSDOWN`` - Ignored + - ``MAP_DENYWRITE`` - Will cause an error + - ``MAP_EXECUTABLE`` - Ignored + - ``MAP_LOCKED`` - Ignored + - ``MAP_NORESERVE`` - Ignored + - ``MAP_POPULATE`` - Ignored + - ``AP_NONBLOCK`` - Ignored + + :param fd: file descriptor of the backing file -- required. + :param offset: The offset into the file to map. + + :return: + + On success, ``mmap()`` returns a pointer to the mapped area. On error, + the value ``MAP_FAILED`` is returned, and ``errno`` is set + appropriately. + + - ``ENOSYS`` - Returned if any of the unsupported ``mmap()`` features + are attempted. + - ``EBADF`` - ``fd`` is not a valid file descriptor. + - ``EINVAL`` - Length is 0. flags contained neither ``MAP_PRIVATE`` or + ``MAP_SHARED``, or contained both of these values. + - ``ENODEV`` - The underlying file-system of the specified file does + not support memory mapping. + diff --git a/doc/reference/user/11_network.rst b/doc/reference/user/11_network.rst new file mode 100644 index 00000000000..12d9629a11b --- /dev/null +++ b/doc/reference/user/11_network.rst @@ -0,0 +1,417 @@ +================== +Network Interfaces +================== + +NuttX supports a BSD-compatible socket interface layer. These socket +interface can be enabled by settings in the architecture `configuration +file `__. Those socket APIs are discussed in +the following paragraphs. + + - :c:func:`socket` + - :c:func:`bind` + - :c:func:`connect` + - :c:func:`listen` + - :c:func:`accept` + - :c:func:`send` + - :c:func:`sendto` + - :c:func:`recv` + - :c:func:`recvfrom` + - :c:func:`setsockopt` + - :c:func:`getsockopt` + +.. c:function:: int socket(int domain, int type, int protocol); + + Creates an endpoint for communication and + returns a descriptor. + + :param domain: (see sys/socket.h) + :param type: (see sys/socket.h) + :param protocol: (see sys/socket.h) + + :return: + 0 on success; -1 on error with + ``errno`` set appropriately: + + - ``EACCES``. Permission to create a socket of the specified type + and/or protocol is denied. + - ``EAFNOSUPPORT``. The implementation does not support the specified + address family. + - ``EINVAL``. Unknown protocol, or protocol family not available. + - ``EMFILE``. Process file table overflow. + - ``ENFILE`` The system limit on the total number of open files has + been reached. + - ``ENOBUFS`` or ``ENOMEM``. Insufficient memory is available. The + socket cannot be created until sufficient resources are freed. + - ``EPROTONOSUPPORT``. The protocol type or the specified protocol is + not supported within this domain. + +.. c:function:: int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) + + Gives the socket sockfd the local address + ``addr``. ``addr`` is ``addrlen`` bytes long. Traditionally, this is + called "assigning a name to a socket." When a socket is created with + ``socket()``, it exists in a name space (address family) but has no name + assigned. + + :param sockfd: Socket descriptor from socket. + :param addr: Socket local address. + :param addrlen: Length of ``addr``. + + :return: 0 on success; -1 on error with ``errno`` set appropriately: + - ``EACCES`` The address is protected, and the user is not the + superuser. + - ``EADDRINUSE`` The given address is already in use. + - ``EBADF`` ``sockfd`` is not a valid descriptor. + - ``EINVAL`` The socket is already bound to an address. + - ``ENOTSOCK`` ``sockfd`` is a descriptor for a file, not a socket. + +.. c:function:: int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); + + ``connect()`` connects the socket referred to by the + file descriptor ``sockfd`` to the address specified by ``addr``. The + ``addrlen`` argument specifies the size of ``addr``. The format of the + address in ``addr`` is determined by the address space of the socket + sockfd. If the socket sockfd is of type SOCK_DGRAM then ``addr`` is the + address to which datagrams are sent by default, and the only address + from which datagrams are received. If the socket is of type SOCK_STREAM + or SOCK_SEQPACKET, this call attempts to make a connection to the socket + that is bound to the address specified by ``addr``. Generally, + connection-based protocol sockets may successfully ``connect()`` only + once; connectionless protocol sockets may use ``connect()`` multiple + times to change their association. Connectionless sockets may dissolve + the association by connecting to an address with the sa_family member of + sockaddr set to AF_UNSPEC. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor returned by ``socket()`` + - ``addr``: Server address (form depends on type of socket) + - ``addrlen``: Length of actual ``addr`` + + **Returned Value:** 0 on success; -1 on error with + ```errno`` <#ErrnoAccess>`__ set appropriately: + + ``EACCES`` or EPERM: The user tried to connect to a broadcast address + without having the socket broadcast flag enabled or the connection + request failed because of a local firewall rule. + + ``EADDRINUSE`` Local address is already in use. + + ``EAFNOSUPPORT`` The passed address didn't have the correct address + family in its sa_family field. + + ``EAGAIN`` No more free local ports or insufficient entries in the + routing cache. For PF_INET. + + ``EALREADY`` The socket is non-blocking and a previous connection + attempt has not yet been completed. + + ``EBADF`` The file descriptor is not a valid index in the descriptor + table. + + ``ECONNREFUSED`` No one listening on the remote address. + + ``EFAULT`` The socket structure address is outside the user's address + space. + + ``EINPROGRESS`` The socket is non-blocking and the connection cannot be + completed immediately. + + ``EINTR`` The system call was interrupted by a signal that was caught. + + ``EISCONN`` The socket is already connected. + + ``ENETUNREACH`` Network is unreachable. + + ``ENOTSOCK`` The file descriptor is not associated with a socket. + + ``ETIMEDOUT`` Timeout while attempting connection. The server may be too + busy to accept new connections. + +.. c:function:: int listen(int sockfd, int backlog); + + To accept connections, a socket is first created with + ``socket()``, a willingness to accept incoming connections and a queue + limit for incoming connections are specified with ``listen()``, and then + the connections are accepted with ``accept()``. The ``listen()`` call + applies only to sockets of type ``SOCK_STREAM`` or ``SOCK_SEQPACKET``. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of the bound socket. + - ``backlog``: The maximum length the queue of pending connections may + grow. If a connection request arrives with the queue full, the client + may receive an error with an indication of ECONNREFUSED or, if the + underlying protocol supports retransmission, the request may be + ignored so that retries succeed. + + **Returned Value:** On success, zero is returned. On error, -1 is + returned, and ```errno`` <#ErrnoAccess>`__ is set appropriately. + + - ``EADDRINUSE``: Another socket is already listening on the same port. + - ``EBADF``: The argument ``sockfd`` is not a valid descriptor. + - ``ENOTSOCK``: The argument ``sockfd`` is not a socket. + - ``EOPNOTSUPP``: The socket is not of a type that supports the listen + operation. + +.. c:function:: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + + The ``accept()`` function is used with connection-based + socket types (``SOCK_STREAM``, ``SOCK_SEQPACKET`` and ``SOCK_RDM``). It + extracts the first connection request on the queue of pending + connections, creates a new connected socket with most of the same + properties as ``sockfd``, and allocates a new socket descriptor for the + socket, which is returned. The newly created socket is no longer in the + listening state. The original socket ``sockfd`` is unaffected by this + call. Per file descriptor flags are not inherited across an accept. + + The ``sockfd`` argument is a socket descriptor that has been created + with ``socket()``, bound to a local address with ``bind()``, and is + listening for connections after a call to ``listen()``. + + On return, the ``addr`` structure is filled in with the address of the + connecting entity. The ``addrlen`` argument initially contains the size + of the structure pointed to by ``addr``; on return it will contain the + actual length of the address returned. + + If no pending connections are present on the queue, and the socket is + not marked as non-blocking, accept blocks the caller until a connection + is present. If the socket is marked non-blocking and no pending + connections are present on the queue, accept returns ``EAGAIN``. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of the listening socket. + - ``addr``: Receives the address of the connecting client. + - ``addrlen``: Input: allocated size of ``addr``, Return: returned size + of ``addr``. + + **Returned Value:** Returns -1 on error. If it succeeds, it returns a + non-negative integer that is a descriptor for the accepted socket. + + - ``EAGAIN`` or ``EWOULDBLOCK``: The socket is marked non-blocking and + no connections are present to be accepted. + - ``EBADF``: The descriptor is invalid. + - ``ENOTSOCK``: The descriptor references a file, not a socket. + - ``EOPNOTSUPP``: The referenced socket is not of type ``SOCK_STREAM``. + - ``EINTR``: The system call was interrupted by a signal that was + caught before a valid connection arrived. + - ``ECONNABORTED``: A connection has been aborted. + - ``EINVAL``: Socket is not listening for connections. + - ``EMFILE``: The per-process limit of open file descriptors has been + reached. + - ``ENFILE``: The system maximum for file descriptors has been reached. + - ``EFAULT``: The addr parameter is not in a writable part of the user + address space. + - ``ENOBUFS`` or ``ENOMEM``: Not enough free memory. + - ``EPROTO``: Protocol error. + - ``EPERM``: Firewall rules forbid connection. + +.. c:function:: ssize_t send(int sockfd, const void *buf, size_t len, int flags); + + The ``send()`` call may be used only when the socket is + in a connected state (so that the intended recipient is known). The only + difference between ``send()`` and ``write()`` is the presence of + ``flags``. With ``zero`` flags parameter, ``send()`` is equivalent to + ``write()``. Also, ``send(s,buf,len,flags)`` is equivalent to + ``sendto(s,buf,len,flags,NULL,0)``. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of socket + - ``buf``: Data to send + - ``len``: Length of data to send + - ``flags``: Send flags + + **Returned Value:** See ```sendto()`` <#sendto>`__. + +.. c:function:: ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, \ + const struct sockaddr *to, socklen_t tolen); + + If ``sendto()`` is used on a connection-mode + (SOCK_STREAM, SOCK_SEQPACKET) socket, the parameters to and tolen are + ignored (and the error EISCONN may be returned when they are not NULL + and 0), and the error ENOTCONN is returned when the socket was not + actually connected. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of socket + - ``buf``: Data to send + - ``len``: Length of data to send + - ``flags``: Send flags + - ``to``: Address of recipient + - ``tolen``: The length of the address structure + + **Returned Value:** On success, returns the number of characters sent. + On error, -1 is returned, and ```errno`` <#ErrnoAccess>`__ is set + appropriately: + + - ``EAGAIN`` or ``EWOULDBLOCK``. The socket is marked non-blocking and + the requested operation would block. + - ``EBADF``. An invalid descriptor was specified. + - ``ECONNRESET``. Connection reset by peer. + - ``EDESTADDRREQ``. The socket is not connection-mode, and no peer + address is set. + - ``EFAULT``. An invalid user space address was specified for a + parameter. + - ``EINTR``. A signal occurred before any data was transmitted. + - ``EINVAL``. Invalid argument passed. + - ``EISCONN``. The connection-mode socket was connected already but a + recipient was specified. (Now either this error is returned, or the + recipient specification is ignored.) + - ``EMSGSIZE``. The socket type requires that message be sent + atomically, and the size of the message to be sent made this + impossible. + - ``ENOBUFS``. The output queue for a network interface was full. This + generally indicates that the interface has stopped sending, but may + be caused by transient congestion. + - ``ENOMEM``. No memory available. + - ``ENOTCONN``. The socket is not connected, and no target has been + given. + - ``ENOTSOCK``. The argument s is not a socket. + - ``EOPNOTSUPP``. Some bit in the flags argument is inappropriate for + the socket type. + - ``EPIPE``. The local end has been shut down on a connection oriented + socket. In this case the process will also receive a SIGPIPE unless + MSG_NOSIGNAL is set. + + +.. c:function:: ssize_t recv(int sockfd, void *buf, size_t len, int flags); + + The ``recv()`` call is identical to + ```recvfrom()`` <#recvfrom>`__ with a NULL ``from`` parameter. + + **Input Parameters:** + + - sockfd: Socket descriptor of socket + - buf: Buffer to receive data + - len: Length of buffer + - flags: Receive flags + + **Returned Value:** See ```recvfrom()`` <#recvfrom>`__. + + +.. c:function:: ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, \ + struct sockaddr *from, socklen_t *fromlen); + + ``recvfrom()`` receives messages from a socket, and may + be used to receive data on a socket whether or not it is + connection-oriented. + + If ``from`` is not NULL, and the underlying protocol provides the source + address, this source address is filled in. The argument ``fromlen`` + initialized to the size of the buffer associated with ``from``, and + modified on return to indicate the actual size of the address stored + there. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of socket. + - ``buf``: Buffer to receive data. + - ``len``: Length of buffer. + - ``flags``: Receive flags. + - ``from``: Address of source. + - ``fromlen``: The length of the address structure. + + **Returned Value:** On success, returns the number of characters sent. + If no data is available to be received and the peer has performed an + orderly shutdown, recv() will return 0. Otherwise, on errors, -1 is + returned, and ```errno`` <#ErrnoAccess>`__ is set appropriately: + + - ``EAGAIN``. The socket is marked non-blocking and the receive + operation would block, or a receive timeout had been set and the + timeout expired before data was received. + - ``EBADF``. The argument ``sockfd`` is an invalid descriptor. + - ``ECONNREFUSED``. A remote host refused to allow the network + connection (typically because it is not running the requested + service). + - ``EFAULT``. The receive buffer pointer(s) point outside the process's + address space. + - ``EINTR``. The receive was interrupted by delivery of a signal before + any data were available. + - ``EINVAL``. Invalid argument passed. + - ``ENOMEM``. Could not allocate memory. + - ``ENOTCONN``. The socket is associated with a connection-oriented + protocol and has not been connected. + - ``ENOTSOCK``. The argument ``sockfd`` does not refer to a socket. + +.. c:function:: int setsockopt(int sockfd, int level, int option, \ + const void *value, socklen_t value_len); + + ``setsockopt()`` sets the option specified by the + ``option`` argument, at the protocol level specified by the ``level`` + argument, to the value pointed to by the ``value`` argument for the + socket associated with the file descriptor specified by the ``sockfd`` + argument. + + The ``level`` argument specifies the protocol level of the option. To + set options at the socket level, specify the level argument as + SOL_SOCKET. + + See ``sys/socket.h`` for a complete list of values for the ``option`` + argument. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of socket + - ``level``: Protocol level to set the option + - ``option``: identifies the option to set + - ``value``: Points to the argument value + - ``value_len``: The length of the argument value + + **Returned Value:** On success, returns the number of characters sent. + On error, -1 is returned, and ```errno`` <#ErrnoAccess>`__ is set + appropriately: + + - ``BADF``. The ``sockfd`` argument is not a valid socket descriptor. + - ``DOM``. The send and receive timeout values are too big to fit into + the timeout fields in the socket structure. + - ``INVAL``. The specified option is invalid at the specified socket + ``level`` or the socket has been shut down. + - ``ISCONN``. The socket is already connected, and a specified option + cannot be set while the socket is connected. + - ``NOPROTOOPT``. The ``option`` is not supported by the protocol. + - ``NOTSOCK``. The ``sockfd`` argument does not refer to a socket. + - ``NOMEM``. There was insufficient memory available for the operation + to complete. + - ``NOBUFS``. Insufficient resources are available in the system to + complete the call. + +.. c:function:: int getsockopt(int sockfd, int level, int option, void *value, socklen_t *value_len); + + ``getsockopt()`` retrieve those value for the option + specified by the ``option`` argument for the socket specified by the + ``sockfd`` argument. If the size of the option value is greater than + ``value_len``, the value stored in the object pointed to by the + ``value`` argument will be silently truncated. Otherwise, the length + pointed to by the ``value_len`` argument will be modified to indicate + the actual length of the ``value``. + + The ``level`` argument specifies the protocol level of the option. To + retrieve options at the socket level, specify the level argument as + SOL_SOCKET. + + See ``sys/socket.h`` for a complete list of values for the ``option`` + argument. + + **Input Parameters:** + + - ``sockfd``: Socket descriptor of socket + - ``level``: Protocol level to set the option + - ``option``: Identifies the option to get + - ``value``: Points to the argument value + - ``value_len``: The length of the argument value + + **Returned Value:** On success, returns the number of characters sent. + On error, -1 is returned, and ```errno`` <#ErrnoAccess>`__ is set + appropriately: + + - ``BADF``. The ``sockfd`` argument is not a valid socket descriptor. + - ``INVAL``. The specified option is invalid at the specified socket + ``level`` or the socket has been shutdown. + - ``NOPROTOOPT``. The ``option`` is not supported by the protocol. + - ``NOTSOCK``. The ``sockfd`` argument does not refer to a socket. + - ``NOBUFS``. Insufficient resources are available in the system to + complete the call. + diff --git a/doc/reference/user/12_shared_memory.rst b/doc/reference/user/12_shared_memory.rst new file mode 100644 index 00000000000..31f1b13d2f7 --- /dev/null +++ b/doc/reference/user/12_shared_memory.rst @@ -0,0 +1,202 @@ +Shared Memory Interfaces +************************ + +Shared memory interfaces are only available with the NuttX kernel build +(``CONFIG_BUILD_KERNEL=y``). These interfaces support user memory +regions that can be shared between multiple user processes. Shared +memory interfaces: + + - :c:func:`shmget` + - :c:func:`shmat` + - :c:func:`shmctl` + - :c:func:`shmdt` + +Functions +--------- + +.. c:function:: int shmget(key_t key, size_t size, int shmflg) + + Returns the shared memory identifier associated with ``key``. + + A shared memory identifier, associated data structure, and shared memory + segment of at least size bytes is created for ``key`` if one of the + following is true: + + - The argument ``key`` is equal to ``IPC_PRIVATE``. + + - The argument ``key`` does not already have a shared memory identifier + associated with it and ``(shmflg & IPC_CREAT)`` is non-zero. + + Upon creation, the data structure associated with the new shared memory + identifier will be initialized as follows: + + - The low-order nine bits of ``shm_perm.mode`` are set equal to the + low-order nine bits of ``shmflg``. + + - The value of ``shm_segsz`` is set equal to the value of size. + + - The values of ``shm_lpid``, ``shm_nattch``, ``shm_atime``, and + ``shm_dtime`` are set equal to 0. + + - The value of ``shm_ctime`` is set equal to the current time. + + When the shared memory segment is created, it will be initialized with + all zero values. + + :param key: The key that is used to access the unique shared memory + identifier. + :param size: The shared memory region that is created will be at least + this size in bytes. + :param shmflg: See ``IPC_*`` definitions in ``sys/ipc.h``. Only the + values ``IPC_PRIVATE`` or ``IPC_CREAT`` are supported. + + :return: Upon successful completion, ``shmget()`` will return + a non-negative integer, namely a shared memory identifier; otherwise, it + will return -1 and set ``errno`` to indicate the error. + + - ``EACCES``. A shared memory identifier exists for key but operation + permission as specified by the low-order nine bits of ``shmflg`` + would not be granted. + - ``EEXIST``. A shared memory identifier exists for the argument key + but ``(shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)`` are non-zero. + - ``EINVAL``. A shared memory segment is to be created and the value of + size is less than the system-imposed minimum or greater than the + system-imposed maximum. + - ``EINVAL``. No shared memory segment is to be created and a shared + memory segment exists for key but the size of the segment associated + with it is less than size and size is not 0. + - ``ENOENT``. A shared memory identifier does not exist for the + argument key and ``(shmflg & IPC_CREAT)`` is 0. + - ``ENOMEM``. A shared memory identifier and associated shared memory + segment will be created, but the amount of available physical memory + is not sufficient to fill the request. + - ``ENOSPC``. A shared memory identifier is to be created, but the + system-imposed limit on the maximum number of allowed shared memory + identifiers system-wide would be exceeded. + + **POSIX Deviations** + + - The values of ``shm_perm.cuid``, ``shm_perm.uid``, ``shm_perm.cgid``, + and ``shm_perm.gid`` should be set equal to the effective user ID and + effective group ID, respectively, of the calling process. The NuttX + ``ipc_perm`` structure, however, does not support these fields + because user and group IDs are not yet supported by NuttX. + +.. c:function:: void *shmat(int shmid, FAR const void *shmaddr, int shmflg) + + Attaches the shared memory + segment associated with the shared memory identifier specified by + ``shmid`` to the address space of the calling process. The segment is + attached at the address specified by one of the following criteria: + + - If ``shmaddr`` is a null pointer, the segment is attached at the + first available address as selected by the system. + + - If ``shmaddr`` is not a null pointer and ``(shmflg & SHM_RND)`` is + non-zero, the segment is attached at the address given by + ``(shmaddr - ((uintptr_t)shmaddr % SHMLBA))``. + + - If ``shmaddr`` is not a null pointer and ``(shmflg & SHM_RND)`` is 0, + the segment is attached at the address given by ``shmaddr``. + + - The segment is attached for reading if ``(shmflg & SHM_RDONLY)`` is + non-zero and the calling process has read permission; otherwise, if + it is 0 and the calling process has read and write permission, the + segment is attached for reading and writing. + + :param shmid: Shared memory identifier + :param smaddr: Determines mapping of the shared memory region + :param shmflg: See ``SHM_*`` definitions in ``include/sys/shm.h``. Only + ``SHM_RDONLY`` and ``SHM_RND`` are supported. + + :return: Upon successful completion, ``shmat()`` will + increment the value of ``shm_nattch`` in the data structure associated + with the shared memory ID of the attached shared memory segment and + return the segment's start address. Otherwise, the shared memory segment + will not be attached, ``shmat()`` will return -1, and ``errno`` will be + set to indicate the error. + + - ``EACCES``. Operation permission is denied to the calling process + - ``EINVAL``. The value of ``shmid`` is not a valid shared memory + identifier, the ``shmaddr`` is not a null pointer, and the value of + ``(shmaddr -((uintptr_t)shmaddr % SHMLBA))`` is an illegal address + for attaching shared memory; or the ``shmaddr`` is not a null + pointer, ``(shmflg & SHM_RND)`` is 0, and the value of ``shmaddr`` is + an illegal address for attaching shared memory. + - ``EMFILE``. The number of shared memory segments attached to the + calling process would exceed the system-imposed limit. + - ``ENOMEM``. The available data space is not large enough to + accommodate the shared memory segment. + +.. c:function:: int shmctl(int shmid, int cmd, FAR struct shmid_ds *buf) + + Provides a variety of shared + memory control operations as specified by ``cmd``. The following values + for ``cmd`` are available: + + - ``IPC_STAT``. Place the current value of each member of the + ``shmid_ds`` data structure associated with ``shmid`` into the + structure pointed to by ``buf``. + + - ``IPC_SET``. Set the value of the ``shm_perm.mode`` member of the + ``shmid_ds`` data structure associated with ``shmid`` to the + corresponding value found in the structure pointed to by ``buf``. + + - ``IPC_RMID``. Remove the shared memory identifier specified by + ``shmid`` from the system and destroy the shared memory segment and + ``shmid_ds`` data structure associated with it. + + :param shmid: Shared memory identifier + :param cmd: ``shmctl()`` command + :param buf: Data associated with the ``shmctl()`` command + + :return: Upon successful completion, ``shmctl()`` will return + 0; otherwise, it will return -1 and set ``errno`` to indicate the error. + + - ``EACCES``. The argument ``cmd`` is equal to ``IPC_STAT`` and the + calling process does not have read permission. + - ``EINVAL``. The value of ``shmid`` is not a valid shared memory + identifier, or the value of ``cmd``\ is not a valid command. + - ``EPERM``. The argument ``cmd`` is equal to ``IPC_RMID`` or + ``IPC_SET`` and the effective user ID of the calling process is not + equal to that of a process with appropriate privileges and it is not + equal to the value of ``shm_perm.cuid`` or ``shm_perm.uid`` in the + data structure associated with ``shmid``. + - ``EOVERFLOW``. The ``cmd`` argument is ``IPC_STAT`` and the ``gid`` + or ``uid`` value is too large to be stored in the structure pointed + to by the ``buf`` argument. + + **POSIX Deviations** + + - ``IPC_SET``. Does not set the ``shm_perm.uid`` or + ``shm_perm.gid``\ members of the ``shmid_ds`` data structure + associated with ``shmid`` because user and group IDs are not yet + supported by NuttX + - ``IPC_SET``. Does not restrict the operation to processes with + appropriate privileges or matching user IDs in ``shmid_ds`` data + structure associated with ``shmid``. Again because user IDs and + user/group privileges are are not yet supported by NuttX + - ``IPC_RMID``. Does not restrict the operation to processes with + appropriate privileges or matching user IDs in ``shmid_ds`` data + structure associated with ``shmid``. Again because user IDs and + user/group privileges are are not yet supported by NuttX + +.. c:function:: int shmdt(FAR const void *shmaddr) + + Detaches the shared memory + segment located at the address specified by ``shmaddr`` from the address + space of the calling process. + + :param shmid: Shared memory identifier + + :return: Upon successful completion, ``shmdt()`` will + decrement the value of ``shm_nattch`` in the data structure associated + with the shared memory ID of the attached shared memory segment and + return 0. + + Otherwise, the shared memory segment will not be detached, ``shmdt()`` + will return -1, and ``errno`` will be set to indicate the error. + + - ``EINVAL``. The value of ``shmaddr`` is not the data segment start + address of a shared memory segment. + diff --git a/doc/reference/user/index.rst b/doc/reference/user/index.rst new file mode 100644 index 00000000000..de648f2b490 --- /dev/null +++ b/doc/reference/user/index.rst @@ -0,0 +1,28 @@ +============= +Userspace API +============= + +.. note:: Migration in progress + +This manual provides general usage information for the NuttX RTOS from +the perspective of the firmware developer. + +The intended audience for this document are firmware developers who are +implementing applications on NuttX. Specifically, this documented is +limited to addressing only NuttX RTOS APIs that are available to the +application developer. As such, this document does not focus on any +technical details of the organization or implementation of NuttX. Those +technical details are provided in the `NuttX Porting +Guide `__. + +Information about configuring and building NuttX is also needed by the +application developer. That information can also be found in the `NuttX +Porting Guide `__. + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :glob: + + *_* + structures.rst diff --git a/doc/reference/user/structures.rst b/doc/reference/user/structures.rst new file mode 100644 index 00000000000..4552a13d17f --- /dev/null +++ b/doc/reference/user/structures.rst @@ -0,0 +1,169 @@ +OS Data Structures +================== + +Scalar Types +************ + +Many of the types used to communicate with NuttX are simple scalar +types. These types are used to provide architecture independence of the +OS from the application. The scalar types used at the NuttX interface +include: + +.. c:type:: pid_t +.. c:type:: size_t +.. c:type:: sigset_t +.. c:type:: time_t + +Hidden Interface Structures +*************************** + +Several of the types used to interface with NuttX are structures that +are intended to be hidden from the application. From the standpoint of +the application, these structures (and structure pointers) should be +treated as simple handles to reference OS resources. These hidden +structures include: + +.. c:struct:: tcb_s +.. c:type:: mqd_t +.. c:type:: sem_t +.. c:type:: WDOG_ID +.. c:type:: pthread_key_t + +In order to maintain portability, applications should not reference +specific elements within these hidden structures. These hidden +structures will not be described further in this user's manual. + +Access to the ``errno`` Variable +******************************** + +A pointer to the thread-specific ``errno`` value is available through a +function call: + +.. c:function:: int *__errno(void) + + ``__errno()`` returns a pointer to the thread-specific + ``errno`` value. Note that the symbol ``errno`` is defined to be + ``__errno()`` so that the usual access by referencing the symbol + ``errno`` will work as expected. + + .. code-block:: c + + #include + #define errno *__errno() + int *__errno(void); + + There is a unique, private ``errno`` value for each NuttX task. However, + the implementation of ``errno`` differs somewhat from the use of + ``errno`` in most multi-threaded process environments: In NuttX, each + pthread will also have its own private copy of ``errno`` and the + ``errno`` will not be shared between pthreads. This is, perhaps, + non-standard but promotes better thread independence. + + :return: A pointer to the thread-specific ``errno`` value. + +User Interface Structures +************************* + +.. c:type:: int (*main_t)(int argc, char *argv[]) + +:c:type:`main_t` defines the type of a task entry point. :c:type:`main_t` is declared in +``sys/types.h``. + +.. c:struct:: sched_param + +This structure is used to pass scheduling priorities to and from NuttX: + +.. code-block:: c + + struct sched_param + { + int sched_priority; + }; + +.. c:struct:: timespec + +This structure is used to pass timing information between the NuttX and +a user application: + +.. code-block:: c + + struct timespec + { + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ + }; + +.. c:struct:: mq_attr + +This structure is used to communicate message queue attributes between +NuttX and a MoBY application: + +.. code-block:: c + + struct mq_attr { + size_t mq_maxmsg; /* Max number of messages in queue */ + size_t mq_msgsize; /* Max message size */ + unsigned mq_flags; /* Queue flags */ + size_t mq_curmsgs; /* Number of messages currently in queue */ + }; + +.. c:struct:: sigaction + +The following structure defines the action to take for given signal: + +.. code-block:: c + + struct sigaction + { + union + { + void (*_sa_handler)(int); + void (*_sa_sigaction)(int, siginfo_t *, void *); + } sa_u; + sigset_t sa_mask; + int sa_flags; + }; + #define sa_handler sa_u._sa_handler + #define sa_sigaction sa_u._sa_sigaction + +.. c:struct:: siginfo +.. c:type:: siginfo_t + +The following types is used to pass parameters to/from signal handlers: + +.. code-block:: c + + typedef struct siginfo + { + int si_signo; + int si_code; + union sigval si_value; + } siginfo_t; + +.. c:union:: sigval + +This defines the type of the struct siginfo si_value field and is used +to pass parameters with signals. + +.. code-block:: c + + union sigval + { + int sival_int; + void *sival_ptr; + }; + +.. c:struct:: sigevent + +The following is used to attach a signal to a message queue to notify a +task when a message is available on a queue. + +.. code-block:: c + + struct sigevent + { + int sigev_signo; + union sigval sigev_value; + int sigev_notify; + }; + diff --git a/doc/releases/index.rst b/doc/releases/index.rst new file mode 100644 index 00000000000..250fdbee1df --- /dev/null +++ b/doc/releases/index.rst @@ -0,0 +1,6 @@ +Releases +======== + +.. note:: + This should link (or include?) release notes. Maybe only show some recent ones and link + older ones diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 00000000000..949d5f9f794 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,3 @@ +sphinx-rtd-theme==0.5.0 +recommonmark==0.6.0 +sphinx==3.1.2 diff --git a/doc/substitutions.rst b/doc/substitutions.rst new file mode 100644 index 00000000000..8b01308acdc --- /dev/null +++ b/doc/substitutions.rst @@ -0,0 +1,5 @@ +.. |br| raw:: html + +
+ +