Use CI-CD-Github-Actions for spelling and formatting, add in the bot formatting action, update the CI-CD workflow files. Fix incorrect spelling and formatting on files. (#1083)

* Use new version of CI-CD Actions,  checkout@v3 instead of checkout@v2 on all jobs
* Use cSpell spell check, and use ubuntu-20.04 for formatting check
* Add in bot formatting action
* Update freertos_demo.yml and freertos_plus_demo.yml files to increase github log readability
* Add in a Qemu demo onto the workflows.
This commit is contained in:
Soren Ptak 2023-09-06 15:35:37 -04:00 committed by GitHub
parent 537007d96c
commit 3a2f6646f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1036 changed files with 134568 additions and 127281 deletions

6150
.github/.cSpellWords.txt vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# /* # /*
# * FreeRTOS V202212.00 # * FreeRTOS V202212.00
# * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. # * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# * # *
# * Permission is hereby granted, free of charge, to any person obtaining a copy of # * Permission is hereby granted, free of charge, to any person obtaining a copy of
# * this software and associated documentation files (the "Software"), to deal in # * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,14 +1,14 @@
certifi==2023.7.22 Deprecated
chardet==4.0.0 GitPython
PyGithub
PyJWT
PyYAML
certifi
chardet
colorama colorama
Deprecated==1.2.10 gitdb
gitdb==4.0.5 idna
GitPython==3.1.32
idna==2.10
PyGithub==1.55
PyJWT==2.4.0
PyYAML==5.4
requests requests
smmap==3.0.4 smmap
urllib3==1.26.5 urllib3
wrapt==1.12.1 wrapt

View file

@ -119,6 +119,7 @@ FREERTOS_IGNORED_EXTENSIONS = [
'.ipcf', '.ipcf',
'.ise', '.ise',
'.jlink', '.jlink',
'.js',
'.json', '.json',
'.la', '.la',
'.launch', '.launch',
@ -172,6 +173,7 @@ FREERTOS_IGNORED_EXTENSIONS = [
'.pl', '.pl',
'.plg', '.plg',
'.png', '.png',
'.props',
'.prc', '.prc',
'.pref', '.pref',
'.prefs', '.prefs',
@ -216,6 +218,7 @@ FREERTOS_IGNORED_EXTENSIONS = [
'.tags', '.tags',
'.tcl', '.tcl',
'.tdt', '.tdt',
'.templ',
'.template', '.template',
'.tgt', '.tgt',
'.tps', '.tps',
@ -250,14 +253,12 @@ FREERTOS_IGNORED_EXTENSIONS = [
'.xmsgs', '.xmsgs',
'.xsl', '.xsl',
'.yml', '.yml',
'.md',
'.zip' '.zip'
] ]
FREERTOS_IGNORED_PATTERNS = [ FREERTOS_IGNORED_PATTERNS = [
r'.*\.git.*', r'.*\.git.*',
r'.*mbedtls_config\.h.*', r'.*mbedtls_config\.h.*',
r'.*mbedtls_config\.h.*',
r'.*CMSIS.*', r'.*CMSIS.*',
r'.*/Nordic_Code/*', r'.*/Nordic_Code/*',
r'.*/Nuvoton_Code/*', r'.*/Nuvoton_Code/*',
@ -275,8 +276,40 @@ FREERTOS_IGNORED_PATTERNS = [
r'.*/trcKernelPortSnapshotConfig\.h.*', r'.*/trcKernelPortSnapshotConfig\.h.*',
r'.*/MicroZed_hw_platform.*', r'.*/MicroZed_hw_platform.*',
r'.*/ThirdParty/.*', r'.*/ThirdParty/.*',
r'FreeRTOS\-Plus/Demo/Common/WinPCap/.*', r'.*/WinPCap/.*',
r'FreeRTOS\-Plus/Source/FreeRTOS-Plus-Trace/.*', r'.*/DRIVERS/.*',
r'.*/FreeRTOS-Plus-Trace/.*',
r'.*/Reliance-Edge/.*',
r'.*/HCS12_CodeWarrior_banked/.*',
r'.*/ARM7_STR75x_GCC/.*',
r'.*/ARM7_STR75x_IAR/.*',
r'.*/lwip-1.4.0/.*',
r'.*/lwip-1.1.0/.*',
r'.*/MSP430X_MSP430F5438_CCS/.*',
r'.*/Atmel/.*',
r'.*/drivers/.*',
r'.*/lwIP/.*',
r'.*/ARM7_AT91FR40008_GCC/.*',
r'.*/ARM7_AT91SAM7S64_IAR/.*',
r'.*/ARM7_LPC2106_GCC/.*',
r'.*/CORTEX_A9_Cyclone_V_SoC_DK/.*',
r'.*/CORTEX_A9_Zynq_ZC702/.*',
r'.*/FreeRTOS-Plus/Demo/FreeRTOS_Plus_Reliance_Edge_and_CLI_Windows_Simulator/ConfigurationFiles//.*',
r'.*/ARM7_AT91FR40008_GCC/.*',
r'.*/ARM7_STR71x_IAR/.*',
r'FreeRTOS/Demo/HCS12_GCC_banked/.*',
r'FreeRTOS/Demo/CORTEX_LM3S102_GCC/hw_include/.*',
r'FreeRTOS/Demo/CORTEX_LM3S102_GCC/hw_include/.*',
r'FreeRTOS/Demo/CORTEX_STM32L152_Discovery_IAR/include/.*',
r'FreeRTOS/Demo/CORTEX_M0_Infineon_XMC1000_IAR_Keil_GCC/.*',
r'FreeRTOS/Demo/CORTEX_M4F_Infineon_XMC4000_Keil/.*',
r'FreeRTOS/Demo/AVR_ATMega4809_Atmel_Studio/RTOSDemo/.*',
r'FreeRTOS/Demo/AVR32_UC3/.*',
r'FreeRTOS/Demo/ARM7_STR75x_GCC/STLibrary/inc/.*',
r'FreeRTOS/Demo/ARM7_STR75x_IAR/STLibrary/inc/.*',
r'FreeRTOS/Demo/CORTEX_R4F_RZ_T_GCC_IAR/System/GCC/inc/.*',
r'FreeRTOS/Demo/CORTEX_A5_SAMA5D2x_Xplained_IAR/AtmelFiles/drivers/misc/.*',
r'FreeRTOS/Demo/CORTEX_ATSAM3X_Atmel_Studio/src/.*',
r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/.*', r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_CLI_with_Trace_Windows_Simulator/Trace_Recorder_Configuration/.*',
r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/common/WinPCap/.*', r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/common/WinPCap/.*',
r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/common/WinPCap/pcap/.*', r'FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_IPv6_Demo/common/WinPCap/pcap/.*',
@ -291,6 +324,7 @@ FREERTOS_IGNORED_PATTERNS = [
] ]
FREERTOS_IGNORED_FILES = [ FREERTOS_IGNORED_FILES = [
'cspell.config.yaml',
'.cproject', '.cproject',
'.project', '.project',
'fyi-another-way-to-ignore-file.txt', 'fyi-another-way-to-ignore-file.txt',
@ -310,12 +344,28 @@ FREERTOS_IGNORED_FILES = [
'reg_test.S', 'reg_test.S',
'gdbinit', 'gdbinit',
'libslirp-version.h', 'libslirp-version.h',
'LPC21xx.h',
'lpc221x.h',
'winbase.h',
'windows.h',
'direct.h',
'stm32f10x_conf.h',
'lwipopts.h',
'lwipopts.h',
'xil_assert.h',
'alt_i2c.h',
'alt_clkmgr.h',
'hal_lcd.c',
'adc.h',
'redconf.c',
'redconf.h',
'redtypes.h',
] ]
FREERTOS_HEADER = [ FREERTOS_HEADER = [
'/*\n', '/*\n',
' * FreeRTOS V202212.00\n', ' * FreeRTOS V202212.00\n',
' * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n', ' * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n',
' *\n', ' *\n',
' * Permission is hereby granted, free of charge, to any person obtaining a copy of\n', ' * Permission is hereby granted, free of charge, to any person obtaining a copy of\n',
' * this software and associated documentation files (the "Software"), to deal in\n', ' * this software and associated documentation files (the "Software"), to deal in\n',
@ -340,7 +390,7 @@ FREERTOS_HEADER = [
' */\n', ' */\n',
] ]
FREERTOS_COPYRIGHT_REGEX = r"^( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$" FREERTOS_COPYRIGHT_REGEX = r"^( *(\/\*|\*|#|\/\/))? Copyright \(C\) 20\d\d Amazon.com, Inc. or its affiliates. All Rights Reserved\.( \*\/)?$"
def main(): def main():
parser = HeaderChecker.configArgParser() parser = HeaderChecker.configArgParser()

38
.github/scripts/qemu_reader.c vendored Normal file
View file

@ -0,0 +1,38 @@
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char * argv[] )
{
setvbuf( stdout, NULL, _IONBF, 0 );
FILE * fp;
char path[ 256 ];
char cmd[ 256 ];
/* Open the command for reading. */
fp = popen("find . -name RTOSDemo.out", "r");
/* Read the output a line at a time - output it. */
while( fgets( path, sizeof( path ), fp ) != NULL )
{
printf( "Path: %s\n", path );
}
sprintf(cmd, "qemu-system-arm -machine mps2-an385 -monitor null -semihosting --semihosting-config enable=on,target=native -serial stdio -nographic -kernel %s", path);
printf("cmd= %s\n", cmd);
fp = popen( cmd, "r" );
if( fp == NULL )
{
printf( "Failed to run command\n" );
exit( 1 );
}
/* Read the output a line at a time - output it. */
while( fgets( path, sizeof( path ), fp ) != NULL )
{
printf( "%s", path );
}
/* close */
pclose( fp );
return 0;
}

View file

@ -1,13 +1,14 @@
certifi>=2020.12.5 Deprecated
chardet>=3.0.4 GitPython
Deprecated>=1.2.10 PyGithub
gitdb>=4.0.5 PyJWT
GitPython>=3.1.11 PyYAML
idna>=2.10 certifi
PyGithub>=1.54 chardet
PyJWT>=1.7.1 colorama
PyYAML>=5.3.1 gitdb
requests>=2.24.0 idna
smmap>=3.0.4 requests
urllib3>=1.25.11 smmap
wrapt>=1.12.1 urllib3
wrapt

View file

@ -26,13 +26,13 @@ jobs:
# Source the release tools from FreeRTOS/FreeRTOS # Source the release tools from FreeRTOS/FreeRTOS
- name: Checkout FreeRTOS Release Tools - name: Checkout FreeRTOS Release Tools
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
path: tools path: tools
# Simpler git auth if we use checkout action and forward the repo to release script # Simpler git auth if we use checkout action and forward the repo to release script
- name: Checkout FreeRTOS - name: Checkout FreeRTOS
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
path: local_core path: local_core
fetch-depth: 0 fetch-depth: 0

View file

@ -1,93 +1,80 @@
name: CI Checks name: CI Checks
env:
bashPass: \033[32;1mPASSED -
bashWarn: \033[33;1mWARNING -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
on: on:
push: push:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
git-secrets: git-secrets:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: Checkout awslabs/git-secrets - name: Checkout awslabs/git-secrets
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
repository: awslabs/git-secrets repository: awslabs/git-secrets
ref: master ref: master
path: git-secrets path: git-secrets
- name: Install git-secrets - name: Install git-secrets
run: cd git-secrets && sudo make install && cd .. run: cd git-secrets && sudo make install && cd ..
- name: Run git-secrets - name: Run git-secrets
run: | run: |
git-secrets --register-aws git-secrets --register-aws
git-secrets --scan git-secrets --scan
formatting: formatting:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Install Uncrustify
run: sudo apt-get install uncrustify=0.69.0+dfsg1-1build1
- name: Run Uncrustify
run: |
# Uncrustify on C files while ignoring symlinks.
# Make a collapsible section in the log to run uncrustify
echo "::group::Uncrustify Check"
# GitHub automtically use "set -e" which causes scripts to fail on the first exit code
# This would mean the first time a file fails the check that we exit without formatting all files.
set +e
uncrustify --version
find FreeRTOS/Demo/Common FreeRTOS/Test \( -name ethernet -o -name drivers -o -path 'FreeRTOS/Test/CMock/CMock' \) -prune -false -o -name "*.[hc]" | xargs uncrustify --no-backup --replace --if-changed -c tools/uncrustify.cfg -l C
echo "::endgroup::"
# Run a git diff to print the differences if any exist, return an error code if there are any
git diff --exit-code
if [ "$?" = "0" ]; then
echo -e "\033[32;3mUncrustify check passed\033[0m"
exit 0
else
echo -e "\033[32;31mFormatting check (using Uncrustify) failed...\033[0m"
# If there is an error, set this flag high again so the exit 1 fails the run
set -e
exit 1
fi
- name: Check For Trailing Whitespace
run: |
# Trailing Whitespace Check
set +e
ERROR=0
find . \( -name '.git' -o -path "./FreeRTOS/Test/CBMC/patches" -o -path "./FreeRTOS-Plus" -o -path "./FreeRTOS/Source" -o -path "./FreeRTOS/Test/CMock/CMock" -o -path "./FreeRTOS/Demo" \) -prune -false -o -type f -a -name "*" -exec grep -In -e "[[:blank:]]$" {} +
if [ "$?" = "0" ]; then
ERROR=1
fi
find FreeRTOS/Demo/Common \( -name "ethernet" \) -prune -o -false -o -type f -a -name "*" -exec grep --color=yes -In -e "[[:blank:]]$" {} + - name: Check Formatting of Common Demo Files
if [ "$?" = "0" ]; then uses: FreeRTOS/CI-CD-Github-Actions/formatting@main
echo -e "\033[32;31mFiles have trailing whitespace.\033[0m" with:
exit 1 path: FreeRTOS/Demo/Common
else exclude-dirs: ethernet, drivers
if [ "$ERROR" -eq "1" ]; then
echo -e "\033[32;31mFiles have trailing whitespace.\033[0m" - name: Check Formatting
exit 1 uses: FreeRTOS/CI-CD-Github-Actions/formatting@main
fi with:
echo -e "\033[32;3mTrailing whitespace check passed\033[0m" exclude-dirs: ethernet, drivers, FreeRTOS/Demo
exit 0
fi spell-check:
runs-on: ubuntu-latest
steps:
- name: Checkout Parent Repo
uses: actions/checkout@v3
- name: Check Spelling of Common Demo Files
uses: FreeRTOS/CI-CD-GitHub-Actions/spellings@main
with:
path: FreeRTOS/Demo/Common
exclude-dirs: ethernet, drivers
- name: Check Spelling
uses: FreeRTOS/CI-CD-GitHub-Actions/spellings@main
with:
exclude-dirs: ethernet, drivers, FreeRTOS/Demo
doxygen: doxygen:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
path: freertos path: freertos
- name: Install Python3 - name: Install Python3
uses: actions/setup-python@v2 uses: actions/setup-python@v3
with:
python-version: '3.8'
- name: Download tag dependency of coreMQTT-Agent - name: Download tag dependency of coreMQTT-Agent
run: | run: |
# We don't need to generate the coreMQTT docs, we only need the tag file. # We don't need to generate the coreMQTT docs, we only need the tag file.
@ -95,8 +82,9 @@ jobs:
mkdir -p freertos/FreeRTOS-Plus/Source/Application-Protocols/coreMQTT-Agent/source/dependency/coreMQTT/docs/doxygen/output mkdir -p freertos/FreeRTOS-Plus/Source/Application-Protocols/coreMQTT-Agent/source/dependency/coreMQTT/docs/doxygen/output
wget -O freertos/FreeRTOS-Plus/Source/Application-Protocols/coreMQTT-Agent/source/dependency/coreMQTT/docs/doxygen/output/mqtt.tag \ wget -O freertos/FreeRTOS-Plus/Source/Application-Protocols/coreMQTT-Agent/source/dependency/coreMQTT/docs/doxygen/output/mqtt.tag \
"https://freertos.org/Documentation/api-ref/coreMQTT/docs/doxygen/output/mqtt.tag" "https://freertos.org/Documentation/api-ref/coreMQTT/docs/doxygen/output/mqtt.tag"
- name: Generate doxygen ZIP - name: Generate doxygen ZIP
uses: FreeRTOS/CI-CD-GitHub-Actions/doxygen@main uses: FreeRTOS/CI-CD-Github-Actions/doxygen@main
with: with:
path: ./freertos path: ./freertos
# List of directories containing libraries whose doxygen output will be generated. # List of directories containing libraries whose doxygen output will be generated.
@ -112,77 +100,49 @@ jobs:
path: ./freertos/doxygen.zip path: ./freertos/doxygen.zip
retention-days: 2 retention-days: 2
spell-check:
runs-on: ubuntu-20.04
steps:
- name: Checkout Parent Repo
uses: actions/checkout@v2
with:
ref: main
repository: FreeRTOS/CI-CD-Github-Actions
path: commonCI
- name: Clone This Repo
uses: actions/checkout@v2
with:
path: ./FreeRTOS
- name: Install spell
run: |
sudo apt-get install spell
sudo apt-get install util-linux
- name: Check spelling
run: |
# Add path to the tool to the environment variable.
PATH=$PATH:commonCI/spellings/tools
# Make sure that only Amazon licenced files are checked.
sed -i 's/`find $DIRNAME \\( -iname \\\*\.\[ch\] -o -iname \\\*\.dox \\) -type f`/`grep -ril "copyright \(c\) \[0-9\]\[0-9\]\[0-9\]\[0-9\] amazon.com" | grep "\\.\[ch\]" | grep -v "FreeRTOS\/FreeRTOS\/Test\/VeriFast"`/g' commonCI/spellings/tools/find-unknown-comment-words
# Run the spell check script.
find-unknown-comment-words --directory FreeRTOS/ --lexicon FreeRTOS/lexicon.txt
# Check the exit status.
if [ "$?" = "0" ]; then
exit 0
else
exit 1
fi
verify-manifest: verify-manifest:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
- name: Install Python3
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Run manifest verifier - name: Run manifest verifier
uses: FreeRTOS/CI-CD-Github-Actions/manifest-verifier@main uses: FreeRTOS/CI-CD-GitHub-Actions/manifest-verifier@v2
with: with:
path: ./ path: ./
exclude-submodules: FreeRTOS-Plus/Test/CMock,FreeRTOS/Test/CMock/CMock,FreeRTOS/Test/litani
fail-on-incorrect-version: true fail-on-incorrect-version: true
memory-statistics: memory-statistics:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
env: env:
ARM_GCC_TOOLCHAIN_URL: "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2?revision=05382cca-1721-44e1-ae19-1e7c3dc96118&la=en&hash=D7C9D18FCA2DD9F894FD9F3C3DC9228498FA281A" ARM_GCC_TOOLCHAIN_URL: "https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2?revision=05382cca-1721-44e1-ae19-1e7c3dc96118&la=en&hash=D7C9D18FCA2DD9F894FD9F3C3DC9228498FA281A"
steps: steps:
- name: Install ARM GCC - name: Install ARM GCC
run: wget -qO- "${{ env.ARM_GCC_TOOLCHAIN_URL }}" | sudo tar --strip-components=1 -xj -C /usr/local run:
wget -qO- "${{ env.ARM_GCC_TOOLCHAIN_URL }}" | sudo tar
--strip-components=1 -xj -C /usr/local
- name: Clone FreeRTOS Repository with submodules - name: Clone FreeRTOS Repository with submodules
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
- name: Clone mbedTLS submodule from corePKCS11 - name: Clone mbedTLS submodule from corePKCS11
run: git submodule update --init --recursive --checkout -- FreeRTOS-Plus/Source/corePKCS11 run:
git submodule update --init --recursive --checkout --
FreeRTOS-Plus/Source/corePKCS11
- name: Clone CI-CD-Github-Actions repository - name: Clone CI-CD-Github-Actions repository
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
repository: FreeRTOS/CI-CD-Github-Actions repository: FreeRTOS/CI-CD-GitHub-Actions
path: tools path: tools
- name: Run script to generate JSON memory statistics - name: Run script to generate JSON memory statistics
run: tools/memory_statistics/memory_statistics.py --json_report --config tools/memory_statistics/paths.json --output freertos_lts_memory_estimates.json run:
- name: Upload memory size report as artifact (for main and release-candidate ONLY) tools/memory_statistics/memory_statistics.py --json_report
--config tools/memory_statistics/paths.json --output
freertos_lts_memory_estimates.json
- name:
Upload memory size report as artifact (for main and
release-candidate ONLY)
if: success() && ( github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-candidate' ) if: success() && ( github.ref == 'refs/heads/main' || github.ref == 'refs/heads/release-candidate' )
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
@ -191,16 +151,24 @@ jobs:
retention-days: 2 retention-days: 2
proof_ci: proof_ci:
if: ${{ github.event.pull_request }}
runs-on: cbmc_ubuntu-latest_16-core runs-on: cbmc_ubuntu-latest_16-core
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- run: | - env:
stepName: Install Dependencies
run: |
echo -e "::group::${{ env.stepName }}"
git submodule update --init --checkout --recursive --depth 1 git submodule update --init --checkout --recursive --depth 1
sudo apt-get update sudo apt-get update
sudo apt-get install --yes --no-install-recommends gcc-multilib sudo apt-get install --yes --no-install-recommends gcc-multilib
echo -e "::endgroup::"
echo -e "${{ env.bashPass }} ${{env.stepName}} ${{ env.bashEnd }}"
- name: Set up CBMC runner - name: Set up CBMC runner
uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main
- name: Run CBMC - name: Run CBMC
uses: FreeRTOS/CI-CD-Github-Actions/run_cbmc@main uses: FreeRTOS/CI-CD-Github-Actions/run_cbmc@main
with: with:
proofs_dir: FreeRTOS/Test/CBMC/proofs proofs_dir: FreeRTOS/Test/CBMC/proofs

View file

@ -18,14 +18,14 @@ jobs:
# Use the checks as defined by the user, so they can locally adjust as needed # Use the checks as defined by the user, so they can locally adjust as needed
- name: Checkout FreeRTOS Tools - name: Checkout FreeRTOS Tools
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
path: tools path: tools
# Checkout user pull request changes # Checkout user pull request changes
- name: Checkout Pull Request - name: Checkout Pull Request
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
path: inspect path: inspect

23
.github/workflows/formatting.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: Format Pull Request Files
on:
issue_comment:
types: [created]
env:
bashPass: \033[32;1mPASSED -
bashInfo: \033[33;1mINFO -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
jobs:
Formatting:
name: Run Formatting Check
if: ${{ github.event.issue.pull_request }} &&
( ( github.event.comment.body == '/bot run uncrustify' ) ||
( github.event.comment.body == '/bot run formatting' ) )
runs-on: ubuntu-20.04
steps:
- name: Apply Formatting Fix
uses: FreeRTOS/CI-CD-Github-Actions/formatting-bot@main
id: check-formatting

View file

@ -1,195 +1,230 @@
name: FreeRTOS Demos name: FreeRTOS Demos
on: on:
push: push:
pull_request: pull_request:
workflow_dispatch: workflow_dispatch:
env:
bashPass: \033[32;1mPASSED -
bashWarn: \033[33;1mWARNING -
bashFail: \033[31;1mFAILED -
bashEnd: \033[0m
pwshPass: "`e[32;1mPASSED -"
pwshWarn: "`e[33;1mWARNING -"
pwshFail: "`e[31;1mFAILED -"
pwshEnd: "`e[0m"
jobs: jobs:
WIN32-MSVC: WIN32-MSVC:
name: WIN32 MSVC name: WIN32 MSVC
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout Repository - env:
uses: actions/checkout@v2 stepName: Checkout Repository
name: ${{ env.stepName }}
uses: actions/checkout@v3
- name: Fetch Kernel Submodule - env:
stepName: Fetch Kernel Submodule
name: ${{ env.stepName }}
shell: bash shell: bash
run: | run: |
# Fetch Kernel Submodule # ${{ env.stepName }}
echo "::group::Fetch Kernel Submodule" echo -e "::group::${{ env.stepName }}"
set +e
git submodule update --checkout --init --depth 1 FreeRTOS/Source git submodule update --checkout --init --depth 1 FreeRTOS/Source
echo "::endgroup::" exitStatus=$?
if [[ "$?" = "0" ]] set -e
then echo -e "::endgroup::"
echo -e "\033[32;3mCloned the Kernel\033[0m" if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{env.stepName}} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mKernel Clone Failed...\033[0m" echo -e "${{ env.bashFail }} ${{env.stepName}} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Add msbuild to PATH - env:
stepName: Add msbuild to PATH
name: ${{ env.stepName }}
uses: microsoft/setup-msbuild@v1.1 uses: microsoft/setup-msbuild@v1.1
- name: Build WIN32-MSVC Full Demo - env:
stepName: Build WIN32-MSVC Full Demo
name: ${{ env.stepName }}
id: build-win32-msvs-full-demo id: build-win32-msvs-full-demo
working-directory: FreeRTOS/Demo/WIN32-MSVC working-directory: FreeRTOS/Demo/WIN32-MSVC
run: | run: |
# Build WIN32-MSVC Full Demo # ${{ env.stepName }}
echo "::group::Build WIN32-MSVC Full Demo" echo "::group::${{ env.stepName }}"
$content = Get-Content -Path 'main.c' -Raw $content = Get-Content -Path 'main.c' -Raw
$newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );' $newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );'
$newContent | Set-Content -Path 'main.c' $newContent | Set-Content -Path 'main.c'
msbuild WIN32.sln -t:rebuild msbuild WIN32.sln -t:rebuild
$exitStatus = $?
echo "::endgroup::" echo "::endgroup::"
if($? -eq 1) { if($exitStatus -eq 1) {
Write-Host -ForegroundColor green "Built the WIN32-MSVC Full Demo" echo "${{ env.pwshPass }} ${{env.stepName}} ${{ env.pwshEnd }}"
}else { }else {
Write-Host -ForegroundColor red "Build WIN32-MSVC Full Demo Failed..." echo "${{ env.pwshFail }} ${{env.stepName}} ${{ env.pwshEnd }}"
exit 1 exit 1
} }
- name: Run and monitor WIN32-MSVC Full Demo - env:
if: success() || failure() && steps.build-win32-msvs-full-demo.outcome == 'success' stepName: Run and monitor WIN32-MSVC Full Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/WIN32-MSVC/Debug/RTOSDemo.exe exe-path: FreeRTOS/Demo/WIN32-MSVC/Debug/RTOSDemo.exe
log-dir: demo_run_logs
timeout-seconds: 60 timeout-seconds: 60
success-line: "No errors - tick count" success-line: "No errors - tick count"
retry-attempts: 3
- name: Build WIN32-MSVC Blinky Demo - env:
stepName: Build WIN32-MSVC Blinky Demo
name: ${{ env.stepName }}
id: build-win32-msvs-blinky-demo id: build-win32-msvs-blinky-demo
working-directory: FreeRTOS/Demo/WIN32-MSVC working-directory: FreeRTOS/Demo/WIN32-MSVC
run: | run: |
# Build WIN32-MSVC Blinky Demo # ${{ env.stepName }}
echo "::group::MSBuild of WIN32-MSVC Blinky Demo" echo "::group::${{ env.stepName }}"
$content = Get-Content -Path 'main.c' -Raw $content = Get-Content -Path 'main.c' -Raw
$newContent = $content -replace '#define\s+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY\s+0', '#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1' $newContent = $content -replace '#define\s+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY\s+0', '#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1'
$newContent | Set-Content -Path 'main.c' $newContent | Set-Content -Path 'main.c'
# Perform MSBuild of WIN32-MSVC Blinky Demo
msbuild WIN32.sln -t:rebuild msbuild WIN32.sln -t:rebuild
echo "::endgroup::" echo "::endgroup::"
if($? -eq 1) { $exitStatus = $?
Write-Host -ForegroundColor green "Built the WIN32-MSVC Blinky Demo" if($exitStatus -eq 1) {
echo "${{ env.pwshPass }} ${{ env.stepName }} ${{ env.pwshEnd }}"
}else { }else {
Write-Host -ForegroundColor red "Build WIN32-MSVC Blinky Demo Failed..." echo "${{ env.pwshFail }} ${{ env.stepName }} ${{ env.pwshEnd }}"
exit 1 exit 1
} }
- name: Run and monitor WIN32-MSVC Blinky Demo - env:
if: success() || failure() && steps.build-win32-msvs-blinky-demo.outcome == 'success' stepName: Run and monitor WIN32-MSVC Blinky Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/WIN32-MSVC/Debug/RTOSDemo.exe exe-path: FreeRTOS/Demo/WIN32-MSVC/Debug/RTOSDemo.exe
log-dir: demo_run_logs timeout-seconds: 60
timeout-seconds: 60 success-line: "Message received from software timer"
success-line: "Message received from software timer" retry-attempts: 3
- name: Build WIN32-MSVC-Static-Allocation-Only Demo - env:
stepName: Build WIN32-MSVC-Static-Allocation-Only Demo
name: ${{ env.stepName }}
id: build-win32-msvs-static-allocation-only-demo id: build-win32-msvs-static-allocation-only-demo
working-directory: FreeRTOS/Demo/WIN32-MSVC-Static-Allocation-Only working-directory: FreeRTOS/Demo/WIN32-MSVC-Static-Allocation-Only
run: | run: |
# Build WIN32-MSVC-Static-Allocation-Only Demo # ${{ env.stepName }}
echo "::group::Build WIN32-MSVC-Static-Allocation-Only Demo" echo "::group::${{ env.stepName }}"
$content = Get-Content -Path 'main.c' -Raw $content = Get-Content -Path 'main.c' -Raw
$newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );' $newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );'
$newContent | Set-Content -Path 'main.c' $newContent | Set-Content -Path 'main.c'
msbuild WIN32.sln -t:rebuild msbuild WIN32.sln -t:rebuild
$exitStatus = $?
echo "::endgroup::" echo "::endgroup::"
if($? -eq 1) { if($exitStatus -eq 1) {
Write-Host -ForegroundColor green "Built the WIN32-MSVC-Static-Allocation-Only Demo" echo "${{ env.pwshPass }} ${{ env.stepName }} ${{ env.pwshEnd }}"
}else { }else {
Write-Host -ForegroundColor red "Build WIN32-MSVC-Static-Allocation-Only Demo Failed..." echo "${{ env.pwshFail }} ${{ env.stepName }} ${{ env.pwshEnd }}"
exit 1 exit 1
} }
- name: Run and monitor WIN32-MSVC-Static-Allocation-Only Demo - env:
if: success() || failure() && steps.build-win32-msvs-static-allocation-only-demo.outcome == 'success' stepName:
Run and monitor WIN32-MSVC-Static-Allocation-Only Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/WIN32-MSVC-Static-Allocation-Only/Debug/RTOSDemo.exe exe-path: FreeRTOS/Demo/WIN32-MSVC-Static-Allocation-Only/Debug/RTOSDemo.exe
log-dir: demo_run_logs timeout-seconds: 60
timeout-seconds: 60 success-line: "No errors - tick count"
success-line: "No errors - tick count" retry-attempts: 3
WIN32-MingW: WIN32-MingW:
name: WIN32 MingW name: WIN32 MingW
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout Repository - env:
uses: actions/checkout@v2 stepName: Checkout Repository
name: ${{ env.stepName }}
uses: actions/checkout@v3
- name: Fetch Kernel Submodule - env:
stepName: Fetch Kernel Submodule
name: ${{ env.stepName }}
shell: bash shell: bash
run: | run: |
# Fetch Kernel Submodule # ${{ env.stepName }}
echo "::group::Fetch Kernel Submodule" echo -e "::group::${{ env.stepName }}"
git submodule update --checkout --init --depth 1 FreeRTOS/Source git submodule update --checkout --init --depth 1 FreeRTOS/Source
echo "::endgroup::" echo -e "::endgroup::"
if [[ "$?" = "0" ]] echo -e "${{ env.bashPass }} ${{env.stepName}} ${{ env.bashEnd }}"
then
echo -e "\033[32;3mCloned the Kernel\033[0m"
else
echo -e "\033[32;31mKernel Clone Failed...\033[0m"
exit 1
fi
- env:
- name: Build WIN32-MingW Full Demo stepName: Build WIN32-MingW Full Demo
name: ${{ env.stepName }}
id: build-win32-mingw-full-demo id: build-win32-mingw-full-demo
working-directory: FreeRTOS/Demo/WIN32-MingW working-directory: FreeRTOS/Demo/WIN32-MingW
run: | run: |
# Build WIN32-MingW Full Demo # ${{ env.stepName }}
echo "::group::Build WIN32-MingW Full Demo" echo "::group::${{ env.stepName }}"
$content = Get-Content -Path 'main.c' -Raw $content = Get-Content -Path 'main.c' -Raw
$newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );' $newContent = $content -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );'
$newContent | Set-Content -Path 'main.c' $newContent | Set-Content -Path 'main.c'
gcc --version gcc --version
make --version make --version
make make
$exitStatus = $?
echo "::endgroup::" echo "::endgroup::"
if($? -eq 1) { if($exitStatus -eq 1) {
Write-Host -ForegroundColor green "Built the WIN32-MingW Full Demo" echo "${{ env.pwshPass }} ${{ env.stepName }} ${{env.pwshEnd}}"
}else { }else {
Write-Host -ForegroundColor red "Build WIN32-MingW Full Demo Failed..." echo "${{ env.pwshFail }} ${{ env.stepName }} ${{env.pwshEnd}}"
exit 1 exit 1
} }
- name: Run and monitor WIN32-MingW Full Demo - env:
if: success() || failure() && steps.build-win32-mingw-full-demo.outcome == 'success' stepName: Run and monitor WIN32-MingW Full Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/WIN32-MingW/build/RTOSDemo.exe exe-path: FreeRTOS/Demo/WIN32-MingW/build/RTOSDemo.exe
log-dir: demo_run_logs
timeout-seconds: 60 timeout-seconds: 60
success-line: "No errors - tick count" success-line: "No errors - tick count"
- name: Build WIN32-MingW Blinky Demo - env:
stepName: Build WIN32-MingW Blinky Demo
name: ${{ env.stepName }}
id: build-win32-mingw-blinky-demo id: build-win32-mingw-blinky-demo
working-directory: FreeRTOS/Demo/WIN32-MingW working-directory: FreeRTOS/Demo/WIN32-MingW
run: | run: |
# Build WIN32-MingW Blinky Demo # ${{ env.stepName }}
echo "::group::Build WIN32-MingW Blinky Demo" echo "::group::${{ env.stepName }}"
$content = Get-Content -Path 'main.c' -Raw $content = Get-Content -Path 'main.c' -Raw
$newContent = $content -replace '#define\s+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY\s+0', '#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1' $newContent = $content -replace '#define\s+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY\s+0', '#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 1'
$newContent = $newContent -replace 'int\s+main(.*?)void(.*?)\r?\n\s*{', 'int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );'
$newContent | Set-Content -Path 'main.c' $newContent | Set-Content -Path 'main.c'
gcc --version gcc --version
make --version make --version
make make
$exitStatus = $?
echo "::endgroup::" echo "::endgroup::"
if($? -eq 1) { if($exitStatus -eq 1) {
Write-Host -ForegroundColor green "Built the WIN32-MingW Blinky Demo" echo "${{ env.pwshPass }} ${{ env.stepName }} ${{ env.pwshEnd }}"
}else { }else {
Write-Host -ForegroundColor red "Build WIN32-MingW Blinky Demo Failed..." echo "${{ env.pwshFail }} ${{ env.stepName }} ${{ env.pwshEnd }}"
exit 1 exit 1
} }
- name: Run and monitor WIN32-MingW Blinky Demo - env:
if: success() || failure() && steps.build-win32-mingw-blinky-demo.outcome == 'success' stepName: Run and monitor WIN32-MingW Blinky Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/WIN32-MingW/build/RTOSDemo.exe exe-path: FreeRTOS/Demo/WIN32-MingW/build/RTOSDemo.exe
log-dir: demo_run_logs
timeout-seconds: 60 timeout-seconds: 60
success-line: "Message received from software timer" success-line: "Message received from software timer"
@ -197,96 +232,111 @@ jobs:
name: Posix GCC name: Posix GCC
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - env:
uses: actions/checkout@v2 stepName: Checkout Repository
name: ${{ env.stepName }}
uses: actions/checkout@v3
- name: Fetch Kernel Submodule - env:
stepName: Fetch Kernel Submodule
name: ${{ env.stepName }}
shell: bash shell: bash
run: | run: |
# Fetch Kernel Submodule # ${{ env.stepName }}
echo "::group::Fetch Kernel Submodule" echo -e "::group::${{ env.stepName }}"
set +e
git submodule update --checkout --init --depth 1 FreeRTOS/Source git submodule update --checkout --init --depth 1 FreeRTOS/Source
echo "::endgroup::" set -e
if [ "$?" = "0" ]; then exitStatus=$?
echo -e "\033[32;3mCloned the Kernel\033[0m" set -e
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mKernel Clone Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Install GCC - env:
stepName: Install GCC
name: ${{ env.stepName }}
shell: bash shell: bash
run: | run: |
# Install GCC # ${{ env.stepName }}
echo "::group::Install GCC" echo -e "::group::${{ env.stepName }}"
set +e
sudo apt-get -y update sudo apt-get -y update
sudo apt-get -y install build-essential sudo apt-get -y install build-essential
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\e[0;32mInstall GCC Passed\e[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\e[0;32mInstall GCC Failed\e[0m" echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
# If there is an error, set this flag high again so the exit 1 fails the run
set -e
exit 1 exit 1
fi fi
- name: Build Posix_GCC Demo for Coverage Test - env:
shell: bash stepName: Build Posix_GCC Full Demo
working-directory: FreeRTOS/Demo/Posix_GCC name: ${{ env.stepName }}
run: make -j COVERAGE_TEST=1
- name: Build Posix_GCC Full Demo
id: build-posix-gcc-full-demo id: build-posix-gcc-full-demo
shell: bash shell: bash
working-directory: FreeRTOS/Demo/Posix_GCC working-directory: FreeRTOS/Demo/Posix_GCC
run: | run: |
# Build Posix_GCC Full Demo # ${{ env.stepName }}
echo "::group::Build Posix_GCC Full Demo" echo -e "::group::${{ env.stepName }}"
set +e
sed -i -z "s/int[[:space:]]*main[[:space:]]*([[:space:]]*void[[:space:]]*)\n{/int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );/g" main.c sed -i -z "s/int[[:space:]]*main[[:space:]]*([[:space:]]*void[[:space:]]*)\n{/int main( void ){setvbuf( stdout, NULL, _IONBF, 0 );/g" main.c
make clean
make -j make -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuild Posix_GCC Full Demo Passed\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild Posix_GCC Full Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Run and monitor Posix_GCC Full Demo - env:
if: success() || failure() && steps.build-posix-gcc-full-demo.outcome == 'success' stepName: Run and monitor Posix_GCC Full Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/Posix_GCC/build/posix_demo exe-path: FreeRTOS/Demo/Posix_GCC/build/posix_demo
log-dir: demo_run_logs timeout-seconds: 60
timeout-seconds: 60 success-line: "OK: No errors"
success-line: "OK: No errors" retry-attempts: 3
- name: Build Posix_GCC Blinky Demo - env:
stepName: Build Posix_GCC Blinky Demo
name: ${{ env.stepName }}
id: build-posix-gcc-blinky-demo id: build-posix-gcc-blinky-demo
if: success() || failure()
shell: bash shell: bash
working-directory: FreeRTOS/Demo/Posix_GCC working-directory: FreeRTOS/Demo/Posix_GCC
run: | run: |
# Build Posix_GCC Blinky Demo # ${{ env.stepName }}
echo "::group::Build Posix_GCC Blinky Demo" echo -e "::group::${{ env.stepName }}"
rm -rf build rm -rf build
set +e
make -j USER_DEMO=BLINKY_DEMO make -j USER_DEMO=BLINKY_DEMO
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuilt the Posix_GCC Blinky Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild Posix_GCC Blinky Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{env.stepName}} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Run and monitor Posix_GCC Blinky Demo - env:
if: success() || failure() && steps.build-posix-gcc-blinky-demo.outcome == 'success' stepName: Run and monitor Posix_GCC Blinky Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with: with:
exe-path: FreeRTOS/Demo/Posix_GCC/build/posix_demo exe-path: FreeRTOS/Demo/Posix_GCC/build/posix_demo
log-dir: demo_run_logs
timeout-seconds: 60 timeout-seconds: 60
success-line: "Message received from software timer" success-line: "Message received from software timer"
@ -294,208 +344,290 @@ jobs:
name: GNU MSP430 Toolchain name: GNU MSP430 Toolchain
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - env:
uses: actions/checkout@v2 stepName: Checkout Repository
name: ${{ env.stepName }}
uses: actions/checkout@v3
with:
submodules: true
- name: Fetch Kernel Submodule - env:
shell: bash stepName: Fetch Kernel Submodule
run: | name: ${{ env.stepName }}
# Fetch Kernel Submodule shell: bash
echo "::group::Fetch Kernel Submodule" run: |
git submodule update --checkout --init --depth 1 FreeRTOS/Source # ${{ env.stepName }}
echo "::endgroup::" echo -e "::group::${{ env.stepName }}"
if [ "$?" = "0" ]; then set +e
echo -e "\033[32;3mCloned the Kernel\033[0m" git submodule update --checkout --init --depth 1 FreeRTOS/Source
else exitStatus=$?
echo -e "\033[32;31mKernel Clone Failed...\033[0m" set -e
exit 1 echo -e "::endgroup::"
fi if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1
fi
- name: Install MSP430 Toolchain - env:
shell: bash stepName: Install MSP430 Toolchain
run: | name: ${{ env.stepName }}
# Install MSP430 Toolchain shell: bash
echo "::group::Install MSP430 Toolchain" run: |
sudo apt-get -y update # ${{ env.stepName }}
sudo apt-get -y install gcc-msp430 build-essential echo -e "::group::${{ env.stepName }}"
echo "::endgroup::" set +e
if [ "$?" = "0" ]; then sudo apt-get -y update
echo -e "\033[32;3mInstalled the MSP430 Toolchain\033[0m" sudo apt-get -y install gcc-msp430 build-essential
else exitStatus=$?
echo -e "\033[32;31mInstalling the MSP430 ToolchainFailed...\033[0m" set -e
exit 1 echo -e "::endgroup::"
fi if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1
fi
- name: Build msp430_GCC Demo - env:
shell: bash stepName: Build msp430_GCC Demo
working-directory: FreeRTOS/Demo/msp430_GCC name: ${{ env.stepName }}
run: | shell: bash
# Build msp430_GCC Demo working-directory: FreeRTOS/Demo/msp430_GCC
echo "::group::Build msp430_GCC Demo" run: |
make -j # ${{ env.stepName }}
echo "::endgroup::" echo -e "::group::${{ env.stepName }}"
if [ "$?" = "0" ]; then set +e
echo -e "\033[32;3mBuilt the msp430_GCC Demo\033[0m" make -j
else exitStatus=$?
echo -e "\033[32;31mBuilding the msp430_GCC Demo Failed...\033[0m" set -e
exit 1 echo -e "::endgroup::"
fi if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1
fi
ARM-GCC: ARM-GCC:
name: GNU ARM Toolchain name: GNU ARM Toolchain
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - env:
uses: actions/checkout@v2 stepName: Checkout Repository
name: ${{ env.stepName }}
uses: actions/checkout@v3
- name: Fetch Kernel Submodule - env:
stepName: Fetch Kernel Submodule
name: ${{ env.stepName }}
shell: bash shell: bash
run: | run: |
# Fetch Kernel Submodule # ${{ env.stepName }}
echo "::group::Fetch Kernel Submodule" echo -e "::group::${{ env.stepName }}"
git submodule update --checkout --init --depth 1 FreeRTOS/Source set +e
echo "::endgroup::" git submodule update --checkout --init --depth 1 FreeRTOS/Source FreeRTOS/Demo/ThirdParty/Community-Supported-Demos
if [ "$?" = "0" ]; then exitStatus=$?
echo -e "\033[32;3mCloned the Kernel\033[0m" set -e
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mKernel Clone Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Fetch Community-Supported-Demos Submodule - env:
stepName: Install GNU ARM Toolchain
name: Install GNU ARM Toolchain
shell: bash shell: bash
run: | run: |
# Fetch Community-Supported-Demos Submodule # ${{ env.stepName }}
echo "::group::Fetch Community-Supported-Demos Submodule" echo -e "::group::${{ env.stepName }}"
git submodule update --checkout --init --depth 1 FreeRTOS/Demo/ThirdParty/Community-Supported-Demos set +e
echo "::engdroup::"
if [ "$?" = "0" ]; then
echo -e "\033[32;3mCloned the Community-Supported-Demos\033[0m"
else
echo -e "\033[32;31mCommunity-Supported-Demos Clone Failed...\033[0m"
exit 1
fi
- name: Install GNU ARM Toolchain
shell: bash
run: |
# Install GNU ARM Toolchain
echo "::group::Install GNU ARM Toolchain"
sudo apt-get -y update sudo apt-get -y update
sudo apt-get -y install gcc-arm-none-eabi build-essential cmake git ninja-build python3-minimal sudo apt-get -y install gcc-arm-none-eabi build-essential cmake git ninja-build python3-minimal
echo "::endgroup::" sudo apt-get -y install qemu-system-arm qemu-efi
if [ "$?" = "0" ]; then exitStatus=$?
echo -e "\033[32;3mInstalled the GNU ARM Toolchain\033[0m" set -e
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mInstalling GNU ARM Toolchain Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_MPU_M3_MPS2_QEMU_GCC Demo - env:
stepName: Build CORTEX_MPU_M3_MPS2_QEMU_GCC Demo
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC working-directory: FreeRTOS/Demo/CORTEX_MPU_M3_MPS2_QEMU_GCC
run: | run: |
# Build CORTEX_MPU_M3_MPS2_QEMU_GCC Demo # ${{ env.stepName }}
echo "::group::Build CORTEX_MPU_M3_MPS2_QEMU_GCC Demo" echo -e "::group::${{ env.stepName }}"
set +e
make -j make -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuild CORTEX_MPU_M3_MPS2_QEMU_GCC Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_MPU_M3_MPS2_QEMU_GCC Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_LM3S102_GCC Demo - env:
stepName: Build CORTEX_LM3S102_GCC Demo
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/CORTEX_LM3S102_GCC working-directory: FreeRTOS/Demo/CORTEX_LM3S102_GCC
run: | run: |
# Build CORTEX_LM3S102_GCC Demo # ${{ env.stepName }}
echo "::group::Build CORTEX_LM3S102_GCC Demo" echo -e "::group::${{ env.stepName }}"
make -j set +e
echo "::endgroup::"
if [ "$?" = "0" ]; then
echo -e "\033[32;3mBuilt the CORTEX_LM3S102_GCC Demo Kernel\033[0m"
else
echo -e "\033[32;31mBuild CORTEX_LM3S102_GCC Demo Failed...\033[0m"
exit 1
fi
- name: Build CORTEX_M3_MPS2_QEMU_GCC Demo
shell: bash
working-directory: FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC
run: |
# Build CORTEX_M3_MPS2_QEMU_GCC Demo
echo "::group::Build CORTEX_M3_MPS2_QEMU_GCC Demo"
make clean make clean
make -j make -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuilt the CORTEX_M3_MPS2_QEMU_GCC Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_M3_MPS2_QEMU_GCC Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_M3_MPS2_QEMU_GCC Full Demo - env:
stepName: Build CORTEX_M3_MPS2_QEMU_GCC Demo
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC working-directory: FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC
run: | run: |
# Build CORTEX_M3_MPS2_QEMU_GCC Full Demo # ${{ env.stepName }}
echo "::group::Build CORTEX_M3_MPS2_QEMU_GCC Full Demo" echo -e "::group::${{ env.stepName }}"
set +e
make clean
make -j
exitStatus=$?
set -e
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1
fi
- env:
stepName: Build CORTEX_M3_MPS2_QEMU_GCC Full Demo
name: ${{ env.stepName }}
shell: bash
working-directory: FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC
run: |
# ${{ env.stepName }}
echo -e "::group::${{ env.stepName }}"
set +e
make clean make clean
make FULL_DEMO=1 -j make FULL_DEMO=1 -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuilt the CORTEX_M3_MPS2_QEMU_GCC Full Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_M3_MPS2_QEMU_GCC Full Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_LM3S811_GCC Demo - env:
stepName: Build CORTEX_LM3S811_GCC Demo
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/CORTEX_LM3S811_GCC working-directory: FreeRTOS/Demo/CORTEX_LM3S811_GCC
run: | run: |
# Build CORTEX_LM3S811_GCC Demo # ${{ env.stepName }}
echo "::group::Build CORTEX_LM3S811_GCC Demo" echo -e "::group::${{ env.stepName }}"
set +e
make -j make -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuilt the CORTEX_LM3S811_GCC Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_LM3S811_GCC Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_M0+_RP2040 Demos - env:
stepName: Build CORTEX_M0+_RP2040 Demos
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/ThirdParty/Community-Supported-Demos/CORTEX_M0+_RP2040 working-directory: FreeRTOS/Demo/ThirdParty/Community-Supported-Demos/CORTEX_M0+_RP2040
run: | run: |
# Build CORTEX_M0+_RP2040 Demos # ${{ env.stepName }}
echo "::group::Build CORTEX_M0+_RP2040 Demos" echo -e "::group::${{ env.stepName }}"
git clone https://github.com/raspberrypi/pico-sdk.git set +e
cmake -B build -DPICO_SDK_PATH=pico-sdk -GNinja git clone https://github.com/raspberrypi/pico-sdk.git
ninja -C build --verbose cmake -B build -DPICO_SDK_PATH=pico-sdk -GNinja
echo "::endgroup::" ninja -C build --verbose
if [ "$?" = "0" ]; then exitStatus=$?
echo -e "\033[32;3mBuilt CORTEX_M0+_RP2040 Demos\033[0m" set -e
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else
echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1
fi
- env:
stepName: Build Qemu Runner File
name: ${{ env.stepName }}
shell: bash
working-directory: .github/scripts
run: |
# ${{ env.stepName }}
echo -e "::group::${{ env.stepName }}"
gcc qemu_reader.c -o ../../FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/qemu_reader.out
exitStatus=$?
echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_M0+_RP2040 Demos Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- name: Build CORTEX_MPS2_QEMU_IAR_GCC Demo - env:
stepName: Build CORTEX_MPS2_QEMU_IAR_GCC Demo
name: ${{ env.stepName }}
shell: bash shell: bash
working-directory: FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC working-directory: FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC
run: | run: |
# Build CORTEX_MPS2_QEMU_IAR_GCC Demo # ${{ env.stepName }}
echo "::group::Build CORTEX_MPS2_QEMU_IAR_GCC Demo" echo -e "::group::${{ env.stepName }}"
set +e
make -C build/gcc -j make -C build/gcc -j
echo "::endgroup::" exitStatus=$?
if [ "$?" = "0" ]; then set -e
echo -e "\033[32;3mBuilt the CORTEX_MPS2_QEMU_IAR_GCC Demo\033[0m" echo -e "::endgroup::"
if [ $exitStatus -eq 0 ]; then
echo -e "${{ env.bashPass }} ${{ env.stepName }} ${{ env.bashEnd }}"
else else
echo -e "\033[32;31mBuild CORTEX_MPS2_QEMU_IAR_GCC Demo Failed...\033[0m" echo -e "${{ env.bashFail }} ${{ env.stepName }} ${{ env.bashEnd }}"
exit 1 exit 1
fi fi
- env:
stepName: Run and monitor CORTEX_MPS2_QEMU_IAR_GCC Demo
name: ${{ env.stepName }}
uses: FreeRTOS/CI-CD-GitHub-Actions/executable-monitor@main
with:
exe-path: FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/qemu_reader.out
timeout-seconds: 20
success-line: "Message received from software timer"
retry-attempts: 1

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: 5 fetch-depth: 5
@ -42,12 +42,12 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
submodules: 'recursive' submodules: 'recursive'
fetch-depth: 5 fetch-depth: 5
- name: Checkout the main branch from the FreeRTOS-Kernel repository - name: Checkout the main branch from the FreeRTOS-Kernel repository
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
path: ./FreeRTOS/Source path: ./FreeRTOS/Source
ref: main ref: main

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134 VisualStudioVersion = 16.0.31205.134

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -160,8 +160,8 @@ static eReportBuilderStatus prvWritePortsArray( char * pcBuffer,
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"{" "{"
"\"" DEFENDER_REPORT_PORT_KEY "\":%u" "\"" DEFENDER_REPORT_PORT_KEY "\":%u"
"},", "},",
( unsigned int ) pusOpenPortsArray[ uxIdx ] ); ( unsigned int ) pusOpenPortsArray[ uxIdx ] );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) ) if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) )
@ -238,9 +238,9 @@ static eReportBuilderStatus prvWriteConnectionsArray( char * pcBuffer,
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"{" "{"
"\""DEFENDER_REPORT_LOCAL_PORT_KEY"\": %u," "\""DEFENDER_REPORT_LOCAL_PORT_KEY "\": %u,"
"\""DEFENDER_REPORT_REMOTE_ADDR_KEY"\": \"%u.%u.%u.%u:%u\"" "\""DEFENDER_REPORT_REMOTE_ADDR_KEY "\": \"%u.%u.%u.%u:%u\""
"},", "},",
( unsigned int ) pxConn->usLocalPort, ( unsigned int ) pxConn->usLocalPort,
( unsigned int ) ( pxConn->ulRemoteIp >> 24 ) & 0xFF, ( unsigned int ) ( pxConn->ulRemoteIp >> 24 ) & 0xFF,
( unsigned int ) ( pxConn->ulRemoteIp >> 16 ) & 0xFF, ( unsigned int ) ( pxConn->ulRemoteIp >> 16 ) & 0xFF,
@ -399,13 +399,13 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"{" "{"
"\""DEFENDER_REPORT_HEADER_KEY"\": {" "\""DEFENDER_REPORT_HEADER_KEY "\": {"
"\""DEFENDER_REPORT_ID_KEY"\": %u," "\""DEFENDER_REPORT_ID_KEY "\": %u,"
"\""DEFENDER_REPORT_VERSION_KEY"\": \"%u.%u\"" "\""DEFENDER_REPORT_VERSION_KEY "\": \"%u.%u\""
"}," "},"
"\""DEFENDER_REPORT_METRICS_KEY"\": {" "\""DEFENDER_REPORT_METRICS_KEY "\": {"
"\""DEFENDER_REPORT_TCP_LISTENING_PORTS_KEY"\": {" "\""DEFENDER_REPORT_TCP_LISTENING_PORTS_KEY "\": {"
"\""DEFENDER_REPORT_PORTS_KEY"\": ", "\""DEFENDER_REPORT_PORTS_KEY "\": ",
( unsigned int ) ulReportId, ( unsigned int ) ulReportId,
( unsigned int ) ulMajorReportVersion, ( unsigned int ) ulMajorReportVersion,
( unsigned int ) ulMinorReportVersion ); ( unsigned int ) ulMinorReportVersion );
@ -447,11 +447,11 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
{ {
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"," ","
"\""DEFENDER_REPORT_TOTAL_KEY"\": %u" "\""DEFENDER_REPORT_TOTAL_KEY "\": %u"
"}," "},"
"\""DEFENDER_REPORT_UDP_LISTENING_PORTS_KEY"\": {" "\""DEFENDER_REPORT_UDP_LISTENING_PORTS_KEY "\": {"
"\""DEFENDER_REPORT_PORTS_KEY"\": ", "\""DEFENDER_REPORT_PORTS_KEY "\": ",
( unsigned int ) pxMetrics->xOpenTcpPortsArrayLength ); ( unsigned int ) pxMetrics->xOpenTcpPortsArrayLength );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) ) if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) )
@ -491,18 +491,18 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
{ {
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"," ","
"\""DEFENDER_REPORT_TOTAL_KEY"\": %u" "\""DEFENDER_REPORT_TOTAL_KEY "\": %u"
"}," "},"
"\""DEFENDER_REPORT_NETWORK_STATS_KEY"\": {" "\""DEFENDER_REPORT_NETWORK_STATS_KEY "\": {"
"\""DEFENDER_REPORT_BYTES_IN_KEY"\": %u," "\""DEFENDER_REPORT_BYTES_IN_KEY "\": %u,"
"\""DEFENDER_REPORT_BYTES_OUT_KEY"\": %u," "\""DEFENDER_REPORT_BYTES_OUT_KEY "\": %u,"
"\""DEFENDER_REPORT_PKTS_IN_KEY"\": %u," "\""DEFENDER_REPORT_PKTS_IN_KEY "\": %u,"
"\""DEFENDER_REPORT_PKTS_OUT_KEY"\": %u" "\""DEFENDER_REPORT_PKTS_OUT_KEY "\": %u"
"}," "},"
"\""DEFENDER_REPORT_TCP_CONNECTIONS_KEY"\": {" "\""DEFENDER_REPORT_TCP_CONNECTIONS_KEY "\": {"
"\""DEFENDER_REPORT_ESTABLISHED_CONNECTIONS_KEY"\": {" "\""DEFENDER_REPORT_ESTABLISHED_CONNECTIONS_KEY "\": {"
"\""DEFENDER_REPORT_CONNECTIONS_KEY"\": ", "\""DEFENDER_REPORT_CONNECTIONS_KEY "\": ",
( unsigned int ) pxMetrics->xOpenUdpPortsArrayLength, ( unsigned int ) pxMetrics->xOpenUdpPortsArrayLength,
( unsigned int ) pxMetrics->pxNetworkStats->uxBytesReceived, ( unsigned int ) pxMetrics->pxNetworkStats->uxBytesReceived,
( unsigned int ) pxMetrics->pxNetworkStats->uxBytesSent, ( unsigned int ) pxMetrics->pxNetworkStats->uxBytesSent,
@ -546,20 +546,20 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
{ {
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"," ","
"\""DEFENDER_REPORT_TOTAL_KEY"\": %u" "\""DEFENDER_REPORT_TOTAL_KEY "\": %u"
"}" "}"
"}" "}"
"}," "},"
"\""DEFENDER_REPORT_CUSTOM_METRICS_KEY"\": {" "\""DEFENDER_REPORT_CUSTOM_METRICS_KEY "\": {"
"\"stack_high_water_mark\": [" "\"stack_high_water_mark\": ["
"{" "{"
"\""DEFENDER_REPORT_NUMBER_KEY"\": %u" "\""DEFENDER_REPORT_NUMBER_KEY "\": %u"
"}" "}"
"]," "],"
"\"task_numbers\": [" "\"task_numbers\": ["
"{" "{"
"\""DEFENDER_REPORT_NUMBER_LIST_KEY"\": ", "\""DEFENDER_REPORT_NUMBER_LIST_KEY "\": ",
( unsigned int ) pxMetrics->xEstablishedConnectionsArrayLength, ( unsigned int ) pxMetrics->xEstablishedConnectionsArrayLength,
( unsigned int ) pxMetrics->ulStackHighWaterMark ); ( unsigned int ) pxMetrics->ulStackHighWaterMark );
@ -600,9 +600,9 @@ eReportBuilderStatus eGenerateJsonReport( char * pcBuffer,
{ {
lCharactersWritten = snprintf( pcCurrentWritePos, lCharactersWritten = snprintf( pcCurrentWritePos,
xRemainingBufferLength, xRemainingBufferLength,
"}" "}"
"]" "]"
"}" "}"
"}" ); "}" );
if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) ) if( !reportbuilderSNPRINTF_SUCCESS( lCharactersWritten, xRemainingBufferLength ) )

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,8 +20,10 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
*
*/ */
#ifndef CORE_MQTT_CONFIG_H #ifndef CORE_MQTT_CONFIG_H
#define CORE_MQTT_CONFIG_H #define CORE_MQTT_CONFIG_H

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -220,7 +220,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
* @brief The name of the MQTT library used and its version, following an "@" * @brief The name of the MQTT library used and its version, following an "@"
* symbol. * symbol.
*/ */
#include "core_mqtt.h" /* Include coreMQTT header for MQTT_LIBRARY_VERSION macro. */ #include "core_mqtt.h" /* Include coreMQTT header for MQTT_LIBRARY_VERSION macro. */
#define democonfigMQTT_LIB "core-mqtt@"MQTT_LIBRARY_VERSION #define democonfigMQTT_LIB "core-mqtt@"MQTT_LIBRARY_VERSION
/** /**

View file

@ -1,6 +1,6 @@
/* /*
* AWS IoT Device SDK for Embedded C V202009.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -18,6 +18,10 @@
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
#ifndef SHADOW_CONFIG_H #ifndef SHADOW_CONFIG_H

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134 VisualStudioVersion = 16.0.31205.134

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -316,11 +316,11 @@ static void prvProvisioningPublishCallback( MQTTContext_t * pxMqttContext,
configASSERT( pxDeserializedInfo->pPublishInfo != NULL ); configASSERT( pxDeserializedInfo->pPublishInfo != NULL );
pxPublishInfo = pxDeserializedInfo->pPublishInfo; pxPublishInfo = pxDeserializedInfo->pPublishInfo;
xStatus = FleetProvisioning_MatchTopic(pxPublishInfo->pTopicName, xStatus = FleetProvisioning_MatchTopic( pxPublishInfo->pTopicName,
pxPublishInfo->topicNameLength, pxPublishInfo->topicNameLength,
&xApi); &xApi );
if (xStatus != FleetProvisioningSuccess) if( xStatus != FleetProvisioningSuccess )
{ {
LogWarn( ( "Unexpected publish message received. Topic: %.*s.", LogWarn( ( "Unexpected publish message received. Topic: %.*s.",
( int ) pxPublishInfo->topicNameLength, ( int ) pxPublishInfo->topicNameLength,
@ -328,7 +328,7 @@ static void prvProvisioningPublishCallback( MQTTContext_t * pxMqttContext,
} }
else else
{ {
if (xApi == FleetProvCborCreateCertFromCsrAccepted) if( xApi == FleetProvCborCreateCertFromCsrAccepted )
{ {
LogInfo( ( "Received accepted response from Fleet Provisioning CreateCertificateFromCsr API." ) ); LogInfo( ( "Received accepted response from Fleet Provisioning CreateCertificateFromCsr API." ) );
@ -341,13 +341,13 @@ static void prvProvisioningPublishCallback( MQTTContext_t * pxMqttContext,
xPayloadLength = pxPublishInfo->payloadLength; xPayloadLength = pxPublishInfo->payloadLength;
} }
else if (xApi == FleetProvCborCreateCertFromCsrRejected) else if( xApi == FleetProvCborCreateCertFromCsrRejected )
{ {
LogError( ( "Received rejected response from Fleet Provisioning CreateCertificateFromCsr API." ) ); LogError( ( "Received rejected response from Fleet Provisioning CreateCertificateFromCsr API." ) );
xResponseStatus = ResponseRejected; xResponseStatus = ResponseRejected;
} }
else if (xApi == FleetProvCborRegisterThingAccepted) else if( xApi == FleetProvCborRegisterThingAccepted )
{ {
LogInfo( ( "Received accepted response from Fleet Provisioning RegisterThing API." ) ); LogInfo( ( "Received accepted response from Fleet Provisioning RegisterThing API." ) );
@ -360,7 +360,7 @@ static void prvProvisioningPublishCallback( MQTTContext_t * pxMqttContext,
xPayloadLength = pxPublishInfo->payloadLength; xPayloadLength = pxPublishInfo->payloadLength;
} }
else if (xApi == FleetProvCborRegisterThingRejected) else if( xApi == FleetProvCborRegisterThingRejected )
{ {
LogError( ( "Received rejected response from Fleet Provisioning RegisterThing API." ) ); LogError( ( "Received rejected response from Fleet Provisioning RegisterThing API." ) );
@ -804,7 +804,7 @@ int prvFleetProvisioningTask( void * pvParameters )
} }
else else
{ {
LogInfo( ( "Sucessfully established connection with provisioned credentials." ) ); LogInfo( ( "Successfully established connection with provisioned credentials." ) );
xConnectionEstablished = true; xConnectionEstablished = true;
} }
} }

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.33027.164 VisualStudioVersion = 16.0.33027.164

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source"> <Filter Include="Source">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,8 +20,10 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
*
*/ */
#ifndef CORE_MQTT_CONFIG_H #ifndef CORE_MQTT_CONFIG_H
#define CORE_MQTT_CONFIG_H #define CORE_MQTT_CONFIG_H

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -213,7 +213,7 @@ extern void vLoggingPrintf( const char * pcFormatString,
* @brief The name of the MQTT library used and its version, following an "@" * @brief The name of the MQTT library used and its version, following an "@"
* symbol. * symbol.
*/ */
#include "core_mqtt.h" /* Include coreMQTT header for MQTT_LIBRARY_VERSION macro. */ #include "core_mqtt.h" /* Include coreMQTT header for MQTT_LIBRARY_VERSION macro. */
#define democonfigMQTT_LIB "core-mqtt@"MQTT_LIBRARY_VERSION #define democonfigMQTT_LIB "core-mqtt@"MQTT_LIBRARY_VERSION
/** /**

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134 VisualStudioVersion = 16.0.31205.134

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -379,26 +379,28 @@ static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkContext
uint16_t usNextRetryBackOff = 0U; uint16_t usNextRetryBackOff = 0U;
#if defined( democonfigCLIENT_USERNAME ) #if defined( democonfigCLIENT_USERNAME )
/*
* When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect /*
* to AWS IoT Core with Custom Authentication on port 443. * When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* * to AWS IoT Core with Custom Authentication on port 443.
* Custom Authentication uses the contents of the username and password *
* fields of the MQTT CONNECT packet to authenticate the client. * Custom Authentication uses the contents of the username and password
* * fields of the MQTT CONNECT packet to authenticate the client.
* For more information, refer to the documentation at: *
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html * For more information, refer to the documentation at:
*/ * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
static const char * ppcAlpnProtocols[] = { "mqtt", NULL }; */
#if democonfigMQTT_BROKER_PORT != 443U static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
#error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn." #if democonfigMQTT_BROKER_PORT != 443U
#endif /* democonfigMQTT_BROKER_PORT != 443U */ #error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */ #else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using /*
* x509 Certificate Authentication. * Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
*/ * x509 Certificate Authentication.
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; */
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */ #endif /* !defined( democonfigCLIENT_USERNAME ) */
/* /*

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -377,26 +377,28 @@ static TlsTransportStatus_t prvConnectToServerWithBackoffRetries( NetworkContext
uint16_t usNextRetryBackOff = 0U; uint16_t usNextRetryBackOff = 0U;
#if defined( democonfigCLIENT_USERNAME ) #if defined( democonfigCLIENT_USERNAME )
/*
* When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect /*
* to AWS IoT Core with Custom Authentication on port 443. * When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* * to AWS IoT Core with Custom Authentication on port 443.
* Custom Authentication uses the contents of the username and password *
* fields of the MQTT CONNECT packet to authenticate the client. * Custom Authentication uses the contents of the username and password
* * fields of the MQTT CONNECT packet to authenticate the client.
* For more information, refer to the documentation at: *
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html * For more information, refer to the documentation at:
*/ * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
static const char * ppcAlpnProtocols[] = { "mqtt", NULL }; */
#if democonfigMQTT_BROKER_PORT != 443U static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
#error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn." #if democonfigMQTT_BROKER_PORT != 443U
#endif /* democonfigMQTT_BROKER_PORT != 443U */ #error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */ #else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using /*
* x509 Certificate Authentication. * Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
*/ * x509 Certificate Authentication.
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; */
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */ #endif /* !defined( democonfigCLIENT_USERNAME ) */
/* /*

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,14 +24,14 @@
* *
*/ */
/** /**
* @file aws_ota_codesigner_certificate.h * @file aws_ota_codesigner_certificate.h
* @brief Code signer certificate as char array. * @brief Code signer certificate as char array.
* *
* Define this char array containing the PEM encode signing certificate. * Define this char array containing the PEM encode signing certificate.
* Note - It is highly recommended to use this for demo purpose and store * Note - It is highly recommended to use this for demo purpose and store
* certificates in secure location in production devices. * certificates in secure location in production devices.
*/ */
#ifndef __CODESIGNER_CERTIFICATE__H__ #ifndef __CODESIGNER_CERTIFICATE__H__
#define __CODESIGNER_CERTIFICATE__H__ #define __CODESIGNER_CERTIFICATE__H__

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,22 +24,22 @@
* *
*/ */
/** /**
* @file code_signature_verification.h * @file code_signature_verification.h
* @brief Interface for code signature verification functions. * @brief Interface for code signature verification functions.
* *
*/ */
#ifndef CODE_SIGNATURE_VERIFICATION_H #ifndef CODE_SIGNATURE_VERIFICATION_H
#define CODE_SIGNATURE_VERIFICATION_H #define CODE_SIGNATURE_VERIFICATION_H
#include "FreeRTOS.h" #include "FreeRTOS.h"
/** /**
* @brief Validate the integrity of the new image to be activated. * @brief Validate the integrity of the new image to be activated.
* @param[in] pFileContext pointer to File context * @param[in] pFileContext pointer to File context
* @return OtaPalMainStatus_t , OtaPalSuccess if the signature of the image is valid. * @return OtaPalMainStatus_t , OtaPalSuccess if the signature of the image is valid.
*/ */
OtaPalMainStatus_t xValidateImageSignature( OtaFileContext_t* const pFileContext ); OtaPalMainStatus_t xValidateImageSignature( OtaFileContext_t * const pFileContext );
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,25 +24,25 @@
* *
*/ */
/** /**
* @file code_signature_verification_mbedtls.c * @file code_signature_verification_mbedtls.c
* @brief Code signature verification using mbedtls crypto. * @brief Code signature verification using mbedtls crypto.
* *
* The file demonstrates implements the code signature verification functionality on * The file demonstrates implements the code signature verification functionality on
* the specified file using mbedtls for SHA256 ECDSA. * the specified file using mbedtls for SHA256 ECDSA.
*/ */
/* C runtime includes. */ /* C runtime includes. */
#include <string.h> #include <string.h>
/* FreeRTOS includes. */ /* FreeRTOS includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
/* mbedTLS includes. */ /* mbedTLS includes. */
#if !defined( MBEDTLS_CONFIG_FILE ) #if !defined( MBEDTLS_CONFIG_FILE )
#include "mbedtls_config_v3.2.1.h" #include "mbedtls_config_v3.2.1.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
@ -60,10 +60,10 @@
/** /**
* @brief SHA256 buffer size for storing cryptographic hash computation results. * @brief SHA256 buffer size for storing cryptographic hash computation results.
*/ */
#define SHA256_DIGEST_BYTES 32 #define SHA256_DIGEST_BYTES 32
/* Size of buffer used in file operations on this platform (Windows). */ /* Size of buffer used in file operations on this platform (Windows). */
#define OTA_PAL_WIN_BUF_SIZE ( ( size_t ) 4096UL ) #define OTA_PAL_WIN_BUF_SIZE ( ( size_t ) 4096UL )
/** /**
* @brief Library-independent cryptographic algorithm identifiers. * @brief Library-independent cryptographic algorithm identifiers.
@ -73,9 +73,9 @@
#define ASYMMETRIC_ALGORITHM_RSA 1 #define ASYMMETRIC_ALGORITHM_RSA 1
#define ASYMMETRIC_ALGORITHM_ECDSA 2 #define ASYMMETRIC_ALGORITHM_ECDSA 2
/** /**
* @brief Internal signature verification context structure. * @brief Internal signature verification context structure.
*/ */
typedef struct SignatureVerificationState typedef struct SignatureVerificationState
{ {
BaseType_t xAsymmetricAlgorithm; BaseType_t xAsymmetricAlgorithm;
@ -92,9 +92,9 @@ typedef struct SignatureVerificationState
* *
* @return pdTRUE if initialization succeeds, or pdFALSE otherwise. * @return pdTRUE if initialization succeeds, or pdFALSE otherwise.
*/ */
static BaseType_t prvSignatureVerificationStart(void** ppvContext, static BaseType_t prvSignatureVerificationStart( void ** ppvContext,
BaseType_t xAsymmetricAlgorithm, BaseType_t xAsymmetricAlgorithm,
BaseType_t xHashAlgorithm); BaseType_t xHashAlgorithm );
/** /**
* @brief Updates a cryptographic hash computation with the specified byte array. * @brief Updates a cryptographic hash computation with the specified byte array.
@ -103,9 +103,9 @@ static BaseType_t prvSignatureVerificationStart(void** ppvContext,
* @param[in] pucData Byte array that was signed. * @param[in] pucData Byte array that was signed.
* @param[in] xDataLength Length in bytes of data that was signed. * @param[in] xDataLength Length in bytes of data that was signed.
*/ */
static void prvSignatureVerificationUpdate(void* pvContext, static void prvSignatureVerificationUpdate( void * pvContext,
const uint8_t* pucData, const uint8_t * pucData,
size_t xDataLength); size_t xDataLength );
/** /**
* @brief Verifies a digital signature computation using the public key from the * @brief Verifies a digital signature computation using the public key from the
@ -120,41 +120,41 @@ static void prvSignatureVerificationUpdate(void* pvContext,
* *
* @return pdTRUE if the signature is correct or pdFALSE if the signature is invalid. * @return pdTRUE if the signature is correct or pdFALSE if the signature is invalid.
*/ */
static BaseType_t prvSignatureVerificationFinal(void* pvContext, static BaseType_t prvSignatureVerificationFinal( void * pvContext,
char* pcSignerCertificate, char * pcSignerCertificate,
size_t xSignerCertificateLength, size_t xSignerCertificateLength,
uint8_t* pucSignature, uint8_t * pucSignature,
size_t xSignatureLength); size_t xSignatureLength );
/* Read the specified signer certificate from the filesystem into a local buffer. The allocated /* Read the specified signer certificate from the filesystem into a local buffer. The allocated
* memory becomes the property of the caller who is responsible for freeing it. * memory becomes the property of the caller who is responsible for freeing it.
*/ */
static uint8_t* otaPal_ReadAndAssumeCertificate(const uint8_t* const pucCertName, static uint8_t * otaPal_ReadAndAssumeCertificate( const uint8_t * const pucCertName,
uint32_t* const ulSignerCertSize) uint32_t * const ulSignerCertSize )
{ {
FILE* pFile; FILE * pFile;
uint8_t* pucSignerCert = NULL; uint8_t * pucSignerCert = NULL;
uint8_t* pucCertData = NULL; uint8_t * pucCertData = NULL;
int32_t lSize = 0; /* For MISRA mandatory. */ int32_t lSize = 0; /* For MISRA mandatory. */
int32_t lWindowsError; int32_t lWindowsError;
pFile = fopen((const char*)pucCertName, "rb"); /*lint !e586 pFile = fopen( ( const char * ) pucCertName, "rb" ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if (pFile != NULL) if( pFile != NULL )
{ {
lWindowsError = fseek(pFile, 0, SEEK_END); /*lint !e586 lWindowsError = fseek( pFile, 0, SEEK_END ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if (lWindowsError == 0) /* fseek returns a non-zero value on error. */ if( lWindowsError == 0 ) /* fseek returns a non-zero value on error. */
{ {
lSize = (int32_t)ftell(pFile); /*lint !e586 Allow call in this context. */ lSize = ( int32_t ) ftell( pFile ); /*lint !e586 Allow call in this context. */
if (lSize != -1L) /* ftell returns -1 on error. */ if( lSize != -1L ) /* ftell returns -1 on error. */
{ {
lWindowsError = fseek(pFile, 0, SEEK_SET); /*lint !e586 lWindowsError = fseek( pFile, 0, SEEK_SET ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
} }
else /* ftell returned an error, pucSignerCert remains NULL. */ else /* ftell returned an error, pucSignerCert remains NULL. */
{ {
@ -162,60 +162,60 @@ static uint8_t* otaPal_ReadAndAssumeCertificate(const uint8_t* const pucCertName
} }
} /* else fseek returned an error, pucSignerCert remains NULL. */ } /* else fseek returned an error, pucSignerCert remains NULL. */
if (lWindowsError == 0) if( lWindowsError == 0 )
{ {
/* Allocate memory for the signer certificate plus a terminating zero so we can load and return it to the caller. */ /* Allocate memory for the signer certificate plus a terminating zero so we can load and return it to the caller. */
pucSignerCert = pvPortMalloc(lSize + 1); /*lint !e732 !e9034 !e9079 Allow conversion. */ pucSignerCert = pvPortMalloc( lSize + 1 ); /*lint !e732 !e9034 !e9079 Allow conversion. */
} }
if (pucSignerCert != NULL) if( pucSignerCert != NULL )
{ {
if (fread(pucSignerCert, 1, lSize, pFile) == (size_t)lSize) /*lint !e586 !e732 !e9034 if( fread( pucSignerCert, 1, lSize, pFile ) == ( size_t ) lSize ) /*lint !e586 !e732 !e9034
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
{ {
/* The crypto code requires the terminating zero to be part of the length so add 1 to the size. */ /* The crypto code requires the terminating zero to be part of the length so add 1 to the size. */
*ulSignerCertSize = lSize + 1; *ulSignerCertSize = lSize + 1;
pucSignerCert[lSize] = 0; pucSignerCert[ lSize ] = 0;
} }
else else
{ /* There was a problem reading the certificate file so free the memory and abort. */ { /* There was a problem reading the certificate file so free the memory and abort. */
vPortFree(pucSignerCert); vPortFree( pucSignerCert );
pucSignerCert = NULL; pucSignerCert = NULL;
} }
} }
else else
{ {
LogError(("Failed to allocate memory for signer cert contents.\r\n")); LogError( ( "Failed to allocate memory for signer cert contents.\r\n" ) );
/* Nothing special to do. */ /* Nothing special to do. */
} }
lWindowsError = fclose(pFile); /*lint !e586 lWindowsError = fclose( pFile ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if (lWindowsError != 0) if( lWindowsError != 0 )
{ {
LogError(("File pointer operation failed.\r\n")); LogError( ( "File pointer operation failed.\r\n" ) );
pucSignerCert = NULL; pucSignerCert = NULL;
} }
} }
else else
{ {
LogError(("No such certificate file: %s. Using aws_ota_codesigner_certificate.h.\r\n", LogError( ( "No such certificate file: %s. Using aws_ota_codesigner_certificate.h.\r\n",
(const char*)pucCertName)); ( const char * ) pucCertName ) );
/* Allocate memory for the signer certificate plus a terminating zero so we can copy it and return to the caller. */ /* Allocate memory for the signer certificate plus a terminating zero so we can copy it and return to the caller. */
lSize = sizeof(signingcredentialSIGNING_CERTIFICATE_PEM); lSize = sizeof( signingcredentialSIGNING_CERTIFICATE_PEM );
pucSignerCert = pvPortMalloc(lSize); /*lint !e9029 !e9079 !e838 malloc proto requires void*. */ pucSignerCert = pvPortMalloc( lSize ); /*lint !e9029 !e9079 !e838 malloc proto requires void*. */
pucCertData = (uint8_t*)signingcredentialSIGNING_CERTIFICATE_PEM; /*lint !e9005 we don't modify the cert but it could be set by PKCS11 so it's not const. */ pucCertData = ( uint8_t * ) signingcredentialSIGNING_CERTIFICATE_PEM; /*lint !e9005 we don't modify the cert but it could be set by PKCS11 so it's not const. */
if (pucSignerCert != NULL) if( pucSignerCert != NULL )
{ {
memcpy(pucSignerCert, pucCertData, lSize); memcpy( pucSignerCert, pucCertData, lSize );
*ulSignerCertSize = lSize; *ulSignerCertSize = lSize;
} }
else else
{ {
LogError(("No memory for certificate of size %d!\r\n", lSize)); LogError( ( "No memory for certificate of size %d!\r\n", lSize ) );
} }
} }
@ -226,29 +226,29 @@ static uint8_t* otaPal_ReadAndAssumeCertificate(const uint8_t* const pucCertName
* @brief Verifies a cryptographic signature based on the signer * @brief Verifies a cryptographic signature based on the signer
* certificate, hash algorithm, and the data that was signed. * certificate, hash algorithm, and the data that was signed.
*/ */
static BaseType_t prvVerifySignature(char* pcSignerCertificate, static BaseType_t prvVerifySignature( char * pcSignerCertificate,
size_t xSignerCertificateLength, size_t xSignerCertificateLength,
BaseType_t xHashAlgorithm, BaseType_t xHashAlgorithm,
uint8_t* pucHash, uint8_t * pucHash,
size_t xHashLength, size_t xHashLength,
uint8_t* pucSignature, uint8_t * pucSignature,
size_t xSignatureLength) size_t xSignatureLength )
{ {
BaseType_t xResult = pdTRUE; BaseType_t xResult = pdTRUE;
mbedtls_x509_crt xCertCtx; mbedtls_x509_crt xCertCtx;
mbedtls_md_type_t xMbedHashAlg = MBEDTLS_MD_SHA256; mbedtls_md_type_t xMbedHashAlg = MBEDTLS_MD_SHA256;
(void)xHashAlgorithm; ( void ) xHashAlgorithm;
memset(&xCertCtx, 0, sizeof(mbedtls_x509_crt)); memset( &xCertCtx, 0, sizeof( mbedtls_x509_crt ) );
/* /*
* Decode and create a certificate context * Decode and create a certificate context
*/ */
mbedtls_x509_crt_init(&xCertCtx); mbedtls_x509_crt_init( &xCertCtx );
if (0 != mbedtls_x509_crt_parse( if( 0 != mbedtls_x509_crt_parse(
&xCertCtx, (const unsigned char*)pcSignerCertificate, xSignerCertificateLength)) &xCertCtx, ( const unsigned char * ) pcSignerCertificate, xSignerCertificateLength ) )
{ {
xResult = pdFALSE; xResult = pdFALSE;
} }
@ -256,15 +256,15 @@ static BaseType_t prvVerifySignature(char* pcSignerCertificate,
/* /*
* Verify the signature using the public key from the decoded certificate * Verify the signature using the public key from the decoded certificate
*/ */
if (pdTRUE == xResult) if( pdTRUE == xResult )
{ {
if (0 != mbedtls_pk_verify( if( 0 != mbedtls_pk_verify(
&xCertCtx.pk, &xCertCtx.pk,
xMbedHashAlg, xMbedHashAlg,
pucHash, pucHash,
xHashLength, xHashLength,
pucSignature, pucSignature,
xSignatureLength)) xSignatureLength ) )
{ {
xResult = pdFALSE; xResult = pdFALSE;
} }
@ -273,7 +273,7 @@ static BaseType_t prvVerifySignature(char* pcSignerCertificate,
/* /*
* Clean-up * Clean-up
*/ */
mbedtls_x509_crt_free(&xCertCtx); mbedtls_x509_crt_free( &xCertCtx );
return xResult; return xResult;
} }
@ -283,23 +283,23 @@ static BaseType_t prvVerifySignature(char* pcSignerCertificate,
/** /**
* @brief Creates signature verification context. * @brief Creates signature verification context.
*/ */
static BaseType_t prvSignatureVerificationStart(void** ppvContext, static BaseType_t prvSignatureVerificationStart( void ** ppvContext,
BaseType_t xAsymmetricAlgorithm, BaseType_t xAsymmetricAlgorithm,
BaseType_t xHashAlgorithm) BaseType_t xHashAlgorithm )
{ {
BaseType_t xResult = pdTRUE; BaseType_t xResult = pdTRUE;
SignatureVerificationState_t* pxCtx = NULL; SignatureVerificationState_t * pxCtx = NULL;
/* /*
* Allocate the context * Allocate the context
*/ */
if (NULL == (pxCtx = (SignatureVerificationStatePtr_t)pvPortMalloc( if( NULL == ( pxCtx = ( SignatureVerificationStatePtr_t ) pvPortMalloc(
sizeof(*pxCtx)))) /*lint !e9087 Allow casting void* to other types. */ sizeof( *pxCtx ) ) ) ) /*lint !e9087 Allow casting void* to other types. */
{ {
xResult = pdFALSE; xResult = pdFALSE;
} }
if (pdTRUE == xResult) if( pdTRUE == xResult )
{ {
*ppvContext = pxCtx; *ppvContext = pxCtx;
@ -312,8 +312,8 @@ static BaseType_t prvSignatureVerificationStart(void** ppvContext,
/* /*
* Initialize the requested hash type * Initialize the requested hash type
*/ */
mbedtls_sha256_init(&pxCtx->xSHA256Context); mbedtls_sha256_init( &pxCtx->xSHA256Context );
(void)mbedtls_sha256_starts(&pxCtx->xSHA256Context, 0); ( void ) mbedtls_sha256_starts( &pxCtx->xSHA256Context, 0 );
} }
return xResult; return xResult;
@ -322,59 +322,58 @@ static BaseType_t prvSignatureVerificationStart(void** ppvContext,
/** /**
* @brief Adds bytes to an in-progress hash for subsequent signature verification. * @brief Adds bytes to an in-progress hash for subsequent signature verification.
*/ */
static void prvSignatureVerificationUpdate(void* pvContext, static void prvSignatureVerificationUpdate( void * pvContext,
const uint8_t* pucData, const uint8_t * pucData,
size_t xDataLength) size_t xDataLength )
{ {
SignatureVerificationState_t* pxCtx = (SignatureVerificationStatePtr_t)pvContext; /*lint !e9087 Allow casting void* to other types. */ SignatureVerificationState_t * pxCtx = ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */
/* /*
* Add the data to the hash of the requested type * Add the data to the hash of the requested type
*/ */
(void)mbedtls_sha256_update(&pxCtx->xSHA256Context, pucData, xDataLength); ( void ) mbedtls_sha256_update( &pxCtx->xSHA256Context, pucData, xDataLength );
} }
/** /**
* @brief Performs signature verification on a cryptographic hash. * @brief Performs signature verification on a cryptographic hash.
*/ */
static BaseType_t prvSignatureVerificationFinal(void* pvContext, static BaseType_t prvSignatureVerificationFinal( void * pvContext,
char* pcSignerCertificate, char * pcSignerCertificate,
size_t xSignerCertificateLength, size_t xSignerCertificateLength,
uint8_t* pucSignature, uint8_t * pucSignature,
size_t xSignatureLength) size_t xSignatureLength )
{ {
BaseType_t xResult = pdFALSE; BaseType_t xResult = pdFALSE;
if (pvContext != NULL) if( pvContext != NULL )
{ {
SignatureVerificationStatePtr_t pxCtx = (SignatureVerificationStatePtr_t)pvContext; /*lint !e9087 Allow casting void* to other types. */ SignatureVerificationStatePtr_t pxCtx = ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */
uint8_t ucSHA256[SHA256_DIGEST_BYTES]; /* Reserve enough space for the larger for SHA256 results. */ uint8_t ucSHA256[ SHA256_DIGEST_BYTES ]; /* Reserve enough space for the larger for SHA256 results. */
uint8_t* pucHash = NULL; uint8_t * pucHash = NULL;
size_t xHashLength = 0; size_t xHashLength = 0;
if ((pcSignerCertificate != NULL) && if( ( pcSignerCertificate != NULL ) &&
(pucSignature != NULL) && ( pucSignature != NULL ) &&
(xSignerCertificateLength > 0UL) && ( xSignerCertificateLength > 0UL ) &&
(xSignatureLength > 0UL)) ( xSignatureLength > 0UL ) )
{ {
/* /*
* Finish the hash. * Finish the hash.
*/ */
(void)mbedtls_sha256_finish(&pxCtx->xSHA256Context, ucSHA256); ( void ) mbedtls_sha256_finish( &pxCtx->xSHA256Context, ucSHA256 );
pucHash = ucSHA256; pucHash = ucSHA256;
xHashLength = SHA256_DIGEST_BYTES; xHashLength = SHA256_DIGEST_BYTES;
/* /*
* Verify the signature. * Verify the signature.
*/ */
xResult = prvVerifySignature(pcSignerCertificate, xResult = prvVerifySignature( pcSignerCertificate,
xSignerCertificateLength, xSignerCertificateLength,
pxCtx->xHashAlgorithm, pxCtx->xHashAlgorithm,
pucHash, pucHash,
xHashLength, xHashLength,
pucSignature, pucSignature,
xSignatureLength); xSignatureLength );
} }
else else
{ {
@ -384,82 +383,83 @@ static BaseType_t prvSignatureVerificationFinal(void* pvContext,
/* /*
* Clean-up * Clean-up
*/ */
vPortFree(pxCtx); vPortFree( pxCtx );
} }
return xResult; return xResult;
} }
/* Verify the signature of the specified file. */ /* Verify the signature of the specified file. */
OtaPalMainStatus_t xValidateImageSignature(OtaFileContext_t* const C) OtaPalMainStatus_t xValidateImageSignature( OtaFileContext_t * const C )
{ {
OtaPalMainStatus_t eResult = OtaPalSuccess; OtaPalMainStatus_t eResult = OtaPalSuccess;
uint32_t ulBytesRead; uint32_t ulBytesRead;
uint32_t ulSignerCertSize; uint32_t ulSignerCertSize;
uint8_t* pucBuf, * pucSignerCert; uint8_t * pucBuf, * pucSignerCert;
void* pvSigVerifyContext; void * pvSigVerifyContext;
/* Verify an ECDSA-SHA256 signature. */ /* Verify an ECDSA-SHA256 signature. */
if (pdFALSE == prvSignatureVerificationStart(&pvSigVerifyContext, ASYMMETRIC_ALGORITHM_ECDSA, HASH_ALGORITHM_SHA256)) if( pdFALSE == prvSignatureVerificationStart( &pvSigVerifyContext, ASYMMETRIC_ALGORITHM_ECDSA, HASH_ALGORITHM_SHA256 ) )
{ {
eResult = OtaPalSignatureCheckFailed; eResult = OtaPalSignatureCheckFailed;
} }
else else
{ {
LogInfo(("Started %s signature verification, file: %s\r\n", LogInfo( ( "Started %s signature verification, file: %s\r\n",
OTA_JsonFileSignatureKey, (const char*)C->pCertFilepath)); OTA_JsonFileSignatureKey, ( const char * ) C->pCertFilepath ) );
pucSignerCert = otaPal_ReadAndAssumeCertificate((const uint8_t* const)C->pCertFilepath, &ulSignerCertSize); pucSignerCert = otaPal_ReadAndAssumeCertificate( ( const uint8_t * const ) C->pCertFilepath, &ulSignerCertSize );
if (pucSignerCert != NULL) if( pucSignerCert != NULL )
{
pucBuf = pvPortMalloc( OTA_PAL_WIN_BUF_SIZE ); /*lint !e9079 Allow conversion. */
if( pucBuf != NULL )
{ {
pucBuf = pvPortMalloc( OTA_PAL_WIN_BUF_SIZE ); /*lint !e9079 Allow conversion. */ /* Rewind the received file to the beginning. */
if( fseek( C->pFile, 0L, SEEK_SET ) == 0 ) /*lint !e586
if (pucBuf != NULL) * C standard library call is being used for portability. */
{ {
/* Rewind the received file to the beginning. */ do
if (fseek(C->pFile, 0L, SEEK_SET) == 0) /*lint !e586
* C standard library call is being used for portability. */
{ {
do ulBytesRead = fread( pucBuf, 1, OTA_PAL_WIN_BUF_SIZE, C->pFile ); /*lint !e586
{ * C standard library call is being used for portability. */
ulBytesRead = fread(pucBuf, 1, OTA_PAL_WIN_BUF_SIZE, C->pFile); /*lint !e586 /* Include the file chunk in the signature validation. Zero size is OK. */
* C standard library call is being used for portability. */ prvSignatureVerificationUpdate( pvSigVerifyContext, pucBuf, ulBytesRead );
/* Include the file chunk in the signature validation. Zero size is OK. */ } while( ulBytesRead > 0UL );
prvSignatureVerificationUpdate(pvSigVerifyContext, pucBuf, ulBytesRead);
} while (ulBytesRead > 0UL);
if (pdFALSE == prvSignatureVerificationFinal(pvSigVerifyContext, if( pdFALSE == prvSignatureVerificationFinal( pvSigVerifyContext,
(char*)pucSignerCert, ( char * ) pucSignerCert,
(size_t)ulSignerCertSize, ( size_t ) ulSignerCertSize,
C->pSignature->data, C->pSignature->data,
C->pSignature->size)) /*lint !e732 !e9034 Allow comparison in this context. */ C->pSignature->size ) ) /*lint !e732 !e9034 Allow comparison in this context. */
{
eResult = OtaPalSignatureCheckFailed;
}
pvSigVerifyContext = NULL; /* The context has been freed by prvSignatureVerificationFinal(). */
}
else
{ {
/* Nothing special to do. */ eResult = OtaPalSignatureCheckFailed;
} }
/* Free the temporary file page buffer. */ pvSigVerifyContext = NULL; /* The context has been freed by prvSignatureVerificationFinal(). */
vPortFree(pucBuf);
} }
else else
{ {
LogError(("Failed to allocate buffer memory.\r\n")); /* Nothing special to do. */
eResult = OtaPalOutOfMemory;
} }
/* Free the signer certificate that we now own after prvReadAndAssumeCertificate(). */ /* Free the temporary file page buffer. */
vPortFree(pucSignerCert); vPortFree( pucBuf );
} }
else else
{ {
eResult = OtaPalBadSignerCert; LogError( ( "Failed to allocate buffer memory.\r\n" ) );
eResult = OtaPalOutOfMemory;
} }
/* Free the signer certificate that we now own after prvReadAndAssumeCertificate(). */
vPortFree( pucSignerCert );
} }
else
{
eResult = OtaPalBadSignerCert;
}
}
return eResult; return eResult;
} }

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -52,7 +52,7 @@ static OtaPalMainStatus_t otaPal_CheckFileSignature( OtaFileContext_t * const C
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static inline BaseType_t prvContextValidate( OtaFileContext_t* pFileContext ) static inline BaseType_t prvContextValidate( OtaFileContext_t * pFileContext )
{ {
return( ( pFileContext != NULL ) && return( ( pFileContext != NULL ) &&
( pFileContext->pFile != NULL ) ); /*lint !e9034 Comparison is correct for file pointer type. */ ( pFileContext->pFile != NULL ) ); /*lint !e9034 Comparison is correct for file pointer type. */
@ -63,19 +63,19 @@ static inline BaseType_t prvContextValidate( OtaFileContext_t* pFileContext )
/* Attempt to create a new receive file for the file chunks as they come in. */ /* Attempt to create a new receive file for the file chunks as they come in. */
OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t* const C ) OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t * const C )
{ {
OtaPalMainStatus_t mainErr = OtaPalUninitialized; OtaPalMainStatus_t mainErr = OtaPalUninitialized;
OtaPalSubStatus_t subErr = 0; OtaPalSubStatus_t subErr = 0;
if( C != NULL ) if( C != NULL )
{ {
if ( C->pFilePath != NULL ) if( C->pFilePath != NULL )
{ {
C->pFile = fopen( ( const char * )C->pFilePath, "w+b" ); /*lint !e586 C->pFile = fopen( ( const char * ) C->pFilePath, "w+b" ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if ( C->pFile != NULL ) if( C->pFile != NULL )
{ {
mainErr = OtaPalSuccess; mainErr = OtaPalSuccess;
LogInfo( ( "Receive file created.\r\n" ) ); LogInfo( ( "Receive file created.\r\n" ) );
@ -99,7 +99,7 @@ OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t* const C )
LogError( ( "ERROR - Invalid file context provided.\r\n" ) ); LogError( ( "ERROR - Invalid file context provided.\r\n" ) );
} }
return OTA_PAL_COMBINE_ERR(mainErr,subErr); return OTA_PAL_COMBINE_ERR( mainErr, subErr );
} }
@ -118,7 +118,7 @@ OtaPalStatus_t otaPal_Abort( OtaFileContext_t * const C )
if( NULL != C->pFile ) if( NULL != C->pFile )
{ {
lFileCloseResult = fclose( C->pFile ); /*lint !e482 !e586 lFileCloseResult = fclose( C->pFile ); /*lint !e482 !e586
* Context file handle state is managed by this API. */ * Context file handle state is managed by this API. */
C->pFile = NULL; C->pFile = NULL;
if( 0 == lFileCloseResult ) if( 0 == lFileCloseResult )
@ -145,7 +145,7 @@ OtaPalStatus_t otaPal_Abort( OtaFileContext_t * const C )
mainErr = OtaPalFileAbort; mainErr = OtaPalFileAbort;
} }
return OTA_PAL_COMBINE_ERR(mainErr,subErr); return OTA_PAL_COMBINE_ERR( mainErr, subErr );
} }
/* Write a block of data to the specified file. */ /* Write a block of data to the specified file. */
@ -159,12 +159,12 @@ int16_t otaPal_WriteBlock( OtaFileContext_t * const C,
if( prvContextValidate( C ) == pdTRUE ) if( prvContextValidate( C ) == pdTRUE )
{ {
lResult = fseek( C->pFile, ulOffset, SEEK_SET ); /*lint !e586 !e713 !e9034 lResult = fseek( C->pFile, ulOffset, SEEK_SET ); /*lint !e586 !e713 !e9034
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if( 0 == lResult ) if( 0 == lResult )
{ {
lResult = fwrite( pacData, 1, ulBlockSize, C->pFile ); /*lint !e586 !e713 !e9034 lResult = fwrite( pacData, 1, ulBlockSize, C->pFile ); /*lint !e586 !e713 !e9034
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
if( lResult < 0 ) if( lResult < 0 )
{ {
@ -216,7 +216,7 @@ OtaPalStatus_t otaPal_CloseFile( OtaFileContext_t * const C )
/* Close the file. */ /* Close the file. */
lWindowsError = fclose( C->pFile ); /*lint !e482 !e586 lWindowsError = fclose( C->pFile ); /*lint !e482 !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
C->pFile = NULL; C->pFile = NULL;
if( lWindowsError != 0 ) if( lWindowsError != 0 )
@ -233,11 +233,10 @@ OtaPalStatus_t otaPal_CloseFile( OtaFileContext_t * const C )
else else
{ {
LogError( ( "Failed to pass %s signature verification: %d.\r\n", LogError( ( "Failed to pass %s signature verification: %d.\r\n",
OTA_JsonFileSignatureKey, OTA_PAL_COMBINE_ERR(mainErr,subErr) ) ); OTA_JsonFileSignatureKey, OTA_PAL_COMBINE_ERR( mainErr, subErr ) ) );
/* If we fail to verify the file signature that means the image is not valid. We need to set the image state to aborted. */ /* If we fail to verify the file signature that means the image is not valid. We need to set the image state to aborted. */
otaPal_SetPlatformImageState( C, OtaImageStateAborted ); otaPal_SetPlatformImageState( C, OtaImageStateAborted );
} }
} }
else /* Invalid OTA Context. */ else /* Invalid OTA Context. */
@ -247,17 +246,17 @@ OtaPalStatus_t otaPal_CloseFile( OtaFileContext_t * const C )
mainErr = OtaPalFileClose; mainErr = OtaPalFileClose;
} }
return OTA_PAL_COMBINE_ERR(mainErr,subErr); return OTA_PAL_COMBINE_ERR( mainErr, subErr );
} }
/* Verify the signature of the specified file. */ /* Verify the signature of the specified file. */
static OtaPalMainStatus_t otaPal_CheckFileSignature( OtaFileContext_t* const C ) static OtaPalMainStatus_t otaPal_CheckFileSignature( OtaFileContext_t * const C )
{ {
OtaPalMainStatus_t eResult = OtaPalSignatureCheckFailed; OtaPalMainStatus_t eResult = OtaPalSignatureCheckFailed;
if ( prvContextValidate( C ) == pdTRUE ) if( prvContextValidate( C ) == pdTRUE )
{ {
eResult = xValidateImageSignature( C ); eResult = xValidateImageSignature( C );
} }
@ -271,40 +270,41 @@ static OtaPalMainStatus_t otaPal_CheckFileSignature( OtaFileContext_t* const C )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t* const pFileContext ) OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t * const pFileContext )
{ {
(void)pFileContext; ( void ) pFileContext;
/* Return no error. Windows implementation does not reset device. */ /* Return no error. Windows implementation does not reset device. */
return OTA_PAL_COMBINE_ERR(OtaPalSuccess,0); return OTA_PAL_COMBINE_ERR( OtaPalSuccess, 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
OtaPalStatus_t otaPal_ActivateNewImage( OtaFileContext_t* const pFileContext ) OtaPalStatus_t otaPal_ActivateNewImage( OtaFileContext_t * const pFileContext )
{ {
(void)pFileContext; ( void ) pFileContext;
/* Return no error. Windows implementation simply does nothing on activate. /* Return no error. Windows implementation simply does nothing on activate.
* To run the new firmware image, double click the newly downloaded exe */ * To run the new firmware image, double click the newly downloaded exe */
return OTA_PAL_COMBINE_ERR(OtaPalSuccess,0); return OTA_PAL_COMBINE_ERR( OtaPalSuccess, 0 );
} }
/* /*
* Set the final state of the last transferred (final) OTA file (or bundle). * Set the final state of the last transferred (final) OTA file (or bundle).
* On Windows, the state of the OTA image is stored in PlaformImageState.txt. * On Windows, the state of the OTA image is stored in PlatformImageState.txt.
*/ */
OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const pFileContext, OtaImageState_t eState ) OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const pFileContext,
OtaImageState_t eState )
{ {
(void)pFileContext; ( void ) pFileContext;
OtaPalMainStatus_t mainErr = OtaPalSuccess; OtaPalMainStatus_t mainErr = OtaPalSuccess;
OtaPalSubStatus_t subErr = 0; OtaPalSubStatus_t subErr = 0;
FILE * pstPlatformImageState; FILE * pstPlatformImageState;
if( eState != OtaImageStateUnknown && eState <= OtaLastImageState ) if( ( eState != OtaImageStateUnknown ) && ( eState <= OtaLastImageState ) )
{ {
pstPlatformImageState = fopen( "PlatformImageState.txt", "w+b" ); /*lint !e586 pstPlatformImageState = fopen( "PlatformImageState.txt", "w+b" ); /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
@ -313,7 +313,7 @@ OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const pFileConte
{ {
/* Write the image state to PlatformImageState.txt. */ /* Write the image state to PlatformImageState.txt. */
if( 1 != fwrite( &eState, sizeof( OtaImageState_t ), 1, pstPlatformImageState ) ) /*lint !e586 !e9029 if( 1 != fwrite( &eState, sizeof( OtaImageState_t ), 1, pstPlatformImageState ) ) /*lint !e586 !e9029
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
{ {
LogError( ( "Unable to write to image state file.\r\n" ) ); LogError( ( "Unable to write to image state file.\r\n" ) );
mainErr = OtaPalBadImageState; mainErr = OtaPalBadImageState;
@ -334,14 +334,14 @@ OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const pFileConte
mainErr = OtaPalBadImageState; mainErr = OtaPalBadImageState;
subErr = errno; subErr = errno;
} }
} /*lint !e481 Allow fopen and fclose calls in this context. */ } /*lint !e481 Allow fopen and fclose calls in this context. */
else /* Image state invalid. */ else /* Image state invalid. */
{ {
LogError( ( "ERROR - Invalid image state provided.\r\n" ) ); LogError( ( "ERROR - Invalid image state provided.\r\n" ) );
mainErr = OtaPalBadImageState; mainErr = OtaPalBadImageState;
} }
return OTA_PAL_COMBINE_ERR(mainErr,subErr); return OTA_PAL_COMBINE_ERR( mainErr, subErr );
} }
/* Get the state of the currently running image. /* Get the state of the currently running image.
@ -358,7 +358,7 @@ OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const pFileConte
*/ */
OtaPalImageState_t otaPal_GetPlatformImageState( OtaFileContext_t * const pFileContext ) OtaPalImageState_t otaPal_GetPlatformImageState( OtaFileContext_t * const pFileContext )
{ {
(void)pFileContext; ( void ) pFileContext;
FILE * pstPlatformImageState; FILE * pstPlatformImageState;
OtaImageState_t eSavedAgentState = OtaImageStateUnknown; OtaImageState_t eSavedAgentState = OtaImageStateUnknown;
@ -369,23 +369,25 @@ OtaPalImageState_t otaPal_GetPlatformImageState( OtaFileContext_t * const pFileC
if( pstPlatformImageState != NULL ) if( pstPlatformImageState != NULL )
{ {
if( 1 != fread( &eSavedAgentState, sizeof(OtaImageState_t), 1, pstPlatformImageState ) ) /*lint !e586 !e9029 if( 1 != fread( &eSavedAgentState, sizeof( OtaImageState_t ), 1, pstPlatformImageState ) ) /*lint !e586 !e9029
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
{ {
/* If an error occurred reading the file, mark the state as aborted. */ /* If an error occurred reading the file, mark the state as aborted. */
LogError( ( "Unable to read image state file.\r\n" ) ); LogError( ( "Unable to read image state file.\r\n" ) );
ePalState = ( OtaPalImageStateInvalid | (errno & OTA_PAL_ERR_MASK) ); ePalState = ( OtaPalImageStateInvalid | ( errno & OTA_PAL_ERR_MASK ) );
} }
else else
{ {
switch (eSavedAgentState) switch( eSavedAgentState )
{ {
case OtaImageStateTesting: case OtaImageStateTesting:
ePalState = OtaPalImageStatePendingCommit; ePalState = OtaPalImageStatePendingCommit;
break; break;
case OtaImageStateAccepted: case OtaImageStateAccepted:
ePalState = OtaPalImageStateValid; ePalState = OtaPalImageStateValid;
break; break;
case OtaImageStateRejected: case OtaImageStateRejected:
case OtaImageStateAborted: case OtaImageStateAborted:
default: default:
@ -394,12 +396,11 @@ OtaPalImageState_t otaPal_GetPlatformImageState( OtaFileContext_t * const pFileC
} }
} }
if( 0 != fclose( pstPlatformImageState ) ) /*lint !e586 if( 0 != fclose( pstPlatformImageState ) ) /*lint !e586
* C standard library call is being used for portability. */ * C standard library call is being used for portability. */
{ {
LogError( ( "Unable to close image state file.\r\n" ) ); LogError( ( "Unable to close image state file.\r\n" ) );
ePalState = (OtaPalImageStateInvalid | ( errno & OTA_PAL_ERR_MASK ) ); ePalState = ( OtaPalImageStateInvalid | ( errno & OTA_PAL_ERR_MASK ) );
} }
} }
else else
@ -415,5 +416,5 @@ OtaPalImageState_t otaPal_GetPlatformImageState( OtaFileContext_t * const pFileC
/* Provide access to private members for testing. */ /* Provide access to private members for testing. */
#ifdef FREERTOS_ENABLE_UNIT_TESTS #ifdef FREERTOS_ENABLE_UNIT_TESTS
#include "aws_ota_pal_test_access_define.h" #include "aws_ota_pal_test_access_define.h"
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -26,7 +26,7 @@
/** /**
* @file ota_pal.h * @file ota_pal.h
* @brief Function declarations for ota_ptal.c. * @brief Function declarations for ota_pal.c.
*/ */
#ifndef _OTA_PAL_H_ #ifndef _OTA_PAL_H_
@ -54,7 +54,7 @@
* OTA_ERR_NONE is returned when aborting access to the open file was successful. * OTA_ERR_NONE is returned when aborting access to the open file was successful.
* OTA_ERR_FILE_ABORT is returned when aborting access to the open file context was unsuccessful. * OTA_ERR_FILE_ABORT is returned when aborting access to the open file context was unsuccessful.
*/ */
OtaPalStatus_t otaPal_Abort( OtaFileContext_t * const C ); OtaPalStatus_t otaPal_Abort( OtaFileContext_t * const C );
/** /**
* @brief Create a new receive file for the data chunks as they come in. * @brief Create a new receive file for the data chunks as they come in.
@ -79,7 +79,7 @@ OtaPalStatus_t otaPal_Abort( OtaFileContext_t * const C );
* OTA_ERR_BOOT_INFO_CREATE_FAILED is returned if the bootloader information file creation fails. * OTA_ERR_BOOT_INFO_CREATE_FAILED is returned if the bootloader information file creation fails.
* OTA_ERR_RX_FILE_CREATE_FAILED is returned for other errors creating the file in the device's non-volatile memory. * OTA_ERR_RX_FILE_CREATE_FAILED is returned for other errors creating the file in the device's non-volatile memory.
*/ */
OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t * const C ); OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t * const C );
/* @brief Authenticate and close the underlying receive file in the specified OTA context. /* @brief Authenticate and close the underlying receive file in the specified OTA context.
* *
@ -104,7 +104,7 @@ OtaPalStatus_t otaPal_CreateFileForRx( OtaFileContext_t * const C );
* OTA_ERR_BAD_SIGNER_CERT is returned for errors in the certificate itself. * OTA_ERR_BAD_SIGNER_CERT is returned for errors in the certificate itself.
* OTA_ERR_FILE_CLOSE is returned when closing the file fails. * OTA_ERR_FILE_CLOSE is returned when closing the file fails.
*/ */
OtaPalStatus_t otaPal_CloseFile( OtaFileContext_t * const C ); OtaPalStatus_t otaPal_CloseFile( OtaFileContext_t * const C );
/** /**
* @brief Write a block of data to the specified file at the given offset. * @brief Write a block of data to the specified file at the given offset.
@ -141,7 +141,7 @@ int16_t otaPal_WriteBlock( OtaFileContext_t * const C,
* @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent * @return The OTA PAL layer error code combined with the MCU specific error code. See OTA Agent
* error codes information in ota.h. * error codes information in ota.h.
*/ */
OtaPalStatus_t otaPal_ActivateNewImage( OtaFileContext_t * const C ); OtaPalStatus_t otaPal_ActivateNewImage( OtaFileContext_t * const C );
/** /**
* @brief Reset the device. * @brief Reset the device.
@ -155,7 +155,7 @@ OtaPalStatus_t otaPal_ActivateNewImage( OtaFileContext_t * const C );
* error codes information in ota.h. * error codes information in ota.h.
*/ */
OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t * const C ); OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t * const C );
/** /**
* @brief Attempt to set the state of the OTA update image. * @brief Attempt to set the state of the OTA update image.
@ -176,8 +176,8 @@ OtaPalStatus_t otaPal_ResetDevice( OtaFileContext_t * const C );
* OTA_ERR_REJECT_FAILED: failed to roll back the update image as requested by OtaImageStateRejected. * OTA_ERR_REJECT_FAILED: failed to roll back the update image as requested by OtaImageStateRejected.
* OTA_ERR_COMMIT_FAILED: failed to make the update image permanent as requested by OtaImageStateAccepted. * OTA_ERR_COMMIT_FAILED: failed to make the update image permanent as requested by OtaImageStateAccepted.
*/ */
OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const C, OtaPalStatus_t otaPal_SetPlatformImageState( OtaFileContext_t * const C,
OtaImageState_t eState ); OtaImageState_t eState );
/** /**
* @brief Get the state of the OTA update image. * @brief Get the state of the OTA update image.

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -672,7 +672,7 @@ static void prvMQTTAgentTask( void * pParam );
* *
* The implementation uses MQTT agent to queue a publish request. It then waits * The implementation uses MQTT agent to queue a publish request. It then waits
* for the request complete notification from the agent. The notification along with result of the * for the request complete notification from the agent. The notification along with result of the
* operation is sent back to the caller task using xTaksNotify API. For publishes involving QOS 1 and * operation is sent back to the caller task using xTaskNotify API. For publishes involving QOS 1 and
* QOS2 the operation is complete once an acknowledgment (PUBACK) is received. OTA agent uses this function * QOS2 the operation is complete once an acknowledgment (PUBACK) is received. OTA agent uses this function
* to fetch new job, provide status update and send other control related messages to the MQTT broker. * to fetch new job, provide status update and send other control related messages to the MQTT broker.
* *
@ -808,7 +808,7 @@ static void prvMqttDataCallback( void * pContext,
* *
* The callback is not subscribed with MQTT broker, but only with local subscription manager. * The callback is not subscribed with MQTT broker, but only with local subscription manager.
* A wildcard OTA job topic is used for subscription so that all unsolicited messages related to OTA is * A wildcard OTA job topic is used for subscription so that all unsolicited messages related to OTA is
* forwarded to this callback for filteration. Right now the callback is used to filter responses to job requests * forwarded to this callback for filtration. Right now the callback is used to filter responses to job requests
* from the OTA service. * from the OTA service.
* *
* @param[in] pvIncomingPublishCallbackContext MQTT context which stores the connection. * @param[in] pvIncomingPublishCallbackContext MQTT context which stores the connection.
@ -1186,12 +1186,12 @@ static void prvCommandCallback( MQTTAgentCommandContext_t * pxCommandContext,
static void prvMQTTSubscribeCompleteCallback( MQTTAgentCommandContext_t * pxCommandContext, static void prvMQTTSubscribeCompleteCallback( MQTTAgentCommandContext_t * pxCommandContext,
MQTTAgentReturnInfo_t * pxReturnInfo ) MQTTAgentReturnInfo_t * pxReturnInfo )
{ {
MQTTAgentSubscribeArgs_t * pSubsribeArgs; MQTTAgentSubscribeArgs_t * pSubscribeArgs;
if( pxReturnInfo->returnCode == MQTTSuccess ) if( pxReturnInfo->returnCode == MQTTSuccess )
{ {
pSubsribeArgs = ( MQTTAgentSubscribeArgs_t * ) ( pxCommandContext->pArgs ); pSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) ( pxCommandContext->pArgs );
prvRegisterOTACallback( pSubsribeArgs->pSubscribeInfo->pTopicFilter, pSubsribeArgs->pSubscribeInfo->topicFilterLength ); prvRegisterOTACallback( pSubscribeArgs->pSubscribeInfo->pTopicFilter, pSubscribeArgs->pSubscribeInfo->topicFilterLength );
} }
/* Store the result in the application defined context so the task that /* Store the result in the application defined context so the task that
@ -1431,41 +1431,43 @@ static BaseType_t prvSocketConnect( NetworkContext_t * pxNetworkContext )
NetworkCredentials_t xNetworkCredentials = { 0 }; NetworkCredentials_t xNetworkCredentials = { 0 };
#if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) #if defined( democonfigUSE_AWS_IOT_CORE_BROKER )
#if defined( democonfigCLIENT_USERNAME ) #if defined( democonfigCLIENT_USERNAME )
/*
* When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* to AWS IoT Core with Custom Authentication on port 443.
*
* Custom Authentication uses the contents of the username and password
* fields of the MQTT CONNECT packet to authenticate the client.
*
* For more information, refer to the documentation at:
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
*/
static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
#if democonfigMQTT_BROKER_PORT != 443U
#error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
* x509 Certificate Authentication.
*/
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */
/* /*
* An ALPN identifier is only required when connecting to AWS IoT core on port 443. * When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html * to AWS IoT Core with Custom Authentication on port 443.
*
* Custom Authentication uses the contents of the username and password
* fields of the MQTT CONNECT packet to authenticate the client.
*
* For more information, refer to the documentation at:
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
*/ */
#if democonfigMQTT_BROKER_PORT == 443U static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
xNetworkCredentials.pAlpnProtos = ppcAlpnProtocols; #if democonfigMQTT_BROKER_PORT != 443U
#elif democonfigMQTT_BROKER_PORT == 8883U #error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
xNetworkCredentials.pAlpnProtos = NULL;
#else /* democonfigMQTT_BROKER_PORT != 8883U */
xNetworkCredentials.pAlpnProtos = NULL;
#error "MQTT connections to AWS IoT Core are only allowed on ports 443 and 8883."
#endif /* democonfigMQTT_BROKER_PORT != 443U */ #endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
* x509 Certificate Authentication.
*/
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */
/*
* An ALPN identifier is only required when connecting to AWS IoT core on port 443.
* https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
*/
#if democonfigMQTT_BROKER_PORT == 443U
xNetworkCredentials.pAlpnProtos = ppcAlpnProtocols;
#elif democonfigMQTT_BROKER_PORT == 8883U
xNetworkCredentials.pAlpnProtos = NULL;
#else /* democonfigMQTT_BROKER_PORT != 8883U */
xNetworkCredentials.pAlpnProtos = NULL;
#error "MQTT connections to AWS IoT Core are only allowed on ports 443 and 8883."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */ #else /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */
xNetworkCredentials.pAlpnProtos = NULL; xNetworkCredentials.pAlpnProtos = NULL;
#endif /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */ #endif /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */
@ -2501,7 +2503,7 @@ static BaseType_t prvRunOTADemo( void )
} }
/** /**
* Remvove callback for receiving messages intended for OTA agent from broker, * Remove callback for receiving messages intended for OTA agent from broker,
* for which the topic has not been subscribed for. * for which the topic has not been subscribed for.
*/ */
removeSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext, removeSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext,

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -76,33 +76,34 @@ extern void vLoggingPrintf( const char * pcFormatString,
*/ */
#define MQTT_STATE_ARRAY_MAX_COUNT 10U #define MQTT_STATE_ARRAY_MAX_COUNT 10U
/*********************** coreMQTT Agent Configurations **********************/ /*********************** coreMQTT Agent Configurations **********************/
/**
* @brief The maximum number of pending acknowledgments to track for a single /**
* connection. * @brief The maximum number of pending acknowledgments to track for a single
* * connection.
* @note The MQTT agent tracks MQTT commands (such as PUBLISH and SUBSCRIBE) th *
* at are still waiting to be acknowledged. MQTT_AGENT_MAX_OUTSTANDING_ACKS set * @note The MQTT agent tracks MQTT commands (such as PUBLISH and SUBSCRIBE) th
* the maximum number of acknowledgments that can be outstanding at any one time. * at are still waiting to be acknowledged. MQTT_AGENT_MAX_OUTSTANDING_ACKS set
* The higher this number is the greater the agent's RAM consumption will be. * the maximum number of acknowledgments that can be outstanding at any one time.
*/ * The higher this number is the greater the agent's RAM consumption will be.
*/
#define MQTT_AGENT_MAX_OUTSTANDING_ACKS ( 20U ) #define MQTT_AGENT_MAX_OUTSTANDING_ACKS ( 20U )
/** /**
* @brief Time in MS that the MQTT agent task will wait in the Blocked state (so * @brief Time in MS that the MQTT agent task will wait in the Blocked state (so
* not using any CPU time) for a command to arrive in its command queue before * not using any CPU time) for a command to arrive in its command queue before
* exiting the blocked state so it can call MQTT_ProcessLoop(). * exiting the blocked state so it can call MQTT_ProcessLoop().
* *
* @note It is important MQTT_ProcessLoop() is called often if there is known * @note It is important MQTT_ProcessLoop() is called often if there is known
* MQTT traffic, but calling it too often can take processing time away from * MQTT traffic, but calling it too often can take processing time away from
* lower priority tasks and waste CPU time and power. * lower priority tasks and waste CPU time and power.
*/ */
#define MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME ( 1000 ) #define MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME ( 1000 )
/** /**
* @brief The number of command structures to allocate in the pool * @brief The number of command structures to allocate in the pool
* for the agent. * for the agent.
*/ */
#define MQTT_COMMAND_CONTEXTS_POOL_SIZE 10 #define MQTT_COMMAND_CONTEXTS_POOL_SIZE 10

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134 VisualStudioVersion = 16.0.31205.134

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -304,13 +304,13 @@
#ifndef democonfigCLIENT_IDENTIFIER #ifndef democonfigCLIENT_IDENTIFIER
/** /**
* @brief The MQTT client identifier used in this example. Each client identifier * @brief The MQTT client identifier used in this example. Each client identifier
* must be unique so edit as required to ensure no two clients connecting to the * must be unique so edit as required to ensure no two clients connecting to the
* same broker use the same client identifier. Using a #define is for convenience * same broker use the same client identifier. Using a #define is for convenience
* of demonstration only - production devices should use something unique to the * of demonstration only - production devices should use something unique to the
* device that can be read from software - such as a production serial number. * device that can be read from software - such as a production serial number.
*/ */
#error "Please define democonfigCLIENT_IDENTIFIER in demo_config.h to something unique for this device." #error "Please define democonfigCLIENT_IDENTIFIER in demo_config.h to something unique for this device."
#endif #endif
@ -320,14 +320,14 @@
#error "Please define Root CA certificate of the MQTT broker(democonfigROOT_CA_PEM) in demo_config.h." #error "Please define Root CA certificate of the MQTT broker(democonfigROOT_CA_PEM) in demo_config.h."
#endif #endif
/* If no username is defined, then a client certificate/key is required. */ /* If no username is defined, then a client certificate/key is required. */
#ifndef democonfigCLIENT_USERNAME #ifndef democonfigCLIENT_USERNAME
/* /*
*!!! Please note democonfigCLIENT_PRIVATE_KEY_PEM in used for *!!! Please note democonfigCLIENT_PRIVATE_KEY_PEM in used for
*!!! convenience of demonstration only. Production devices should *!!! convenience of demonstration only. Production devices should
*!!! store keys securely, such as within a secure element. *!!! store keys securely, such as within a secure element.
*/ */
#ifndef democonfigCLIENT_CERTIFICATE_PEM #ifndef democonfigCLIENT_CERTIFICATE_PEM
#error "Please define client certificate(democonfigCLIENT_CERTIFICATE_PEM) in demo_config.h." #error "Please define client certificate(democonfigCLIENT_CERTIFICATE_PEM) in demo_config.h."
@ -337,14 +337,14 @@
#endif #endif
#else #else
/* If a username is defined, a client password also would need to be defined for /* If a username is defined, a client password also would need to be defined for
* client authentication. */ * client authentication. */
#ifndef democonfigCLIENT_PASSWORD #ifndef democonfigCLIENT_PASSWORD
#error "Please define client password(democonfigCLIENT_PASSWORD) in demo_config.h for client authentication based on username/password." #error "Please define client password(democonfigCLIENT_PASSWORD) in demo_config.h for client authentication based on username/password."
#endif #endif
/* AWS IoT MQTT broker port needs to be 443 for client authentication based on /* AWS IoT MQTT broker port needs to be 443 for client authentication based on
* username/password. */ * username/password. */
#if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) && democonfigMQTT_BROKER_PORT != 443 #if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) && democonfigMQTT_BROKER_PORT != 443
#error "Broker port(democonfigMQTT_BROKER_PORT) should be defined as 443 in demo_config.h for client authentication based on username/password in AWS IoT Core." #error "Broker port(democonfigMQTT_BROKER_PORT) should be defined as 443 in demo_config.h for client authentication based on username/password in AWS IoT Core."
#endif #endif
@ -529,7 +529,7 @@ static void prvMQTTAgentTask( void * pParam );
* *
* The implementation uses MQTT agent to queue a publish request. It then waits * The implementation uses MQTT agent to queue a publish request. It then waits
* for the request complete notification from the agent. The notification along with result of the * for the request complete notification from the agent. The notification along with result of the
* operation is sent back to the caller task using xTaksNotify API. For publishes involving QOS 1 and * operation is sent back to the caller task using xTaskNotify API. For publishes involving QOS 1 and
* QOS2 the operation is complete once an acknowledgment (PUBACK) is received. OTA agent uses this function * QOS2 the operation is complete once an acknowledgment (PUBACK) is received. OTA agent uses this function
* to fetch new job, provide status update and send other control related messages to the MQTT broker. * to fetch new job, provide status update and send other control related messages to the MQTT broker.
* *
@ -593,7 +593,7 @@ static OtaMqttStatus_t prvMQTTUnsubscribe( const char * pTopicFilter,
* within ota_config.h. This function is used to fetch a free buffer from the pool for processing * within ota_config.h. This function is used to fetch a free buffer from the pool for processing
* by the OTA agent task. It uses a mutex for thread safe access to the pool. * by the OTA agent task. It uses a mutex for thread safe access to the pool.
* *
* @return A pointer to an unusued buffer. NULL if there are no buffers available. * @return A pointer to an unused buffer. NULL if there are no buffers available.
*/ */
static OtaEventData_t * prvOTAEventBufferGet( void ); static OtaEventData_t * prvOTAEventBufferGet( void );
@ -667,7 +667,7 @@ static void prvMqttDataCallback( void * pContext,
* *
* The callback is not subscribed with MQTT broker, but only with local subscription manager. * The callback is not subscribed with MQTT broker, but only with local subscription manager.
* A wildcard OTA job topic is used for subscription so that all unsolicited messages related to OTA is * A wildcard OTA job topic is used for subscription so that all unsolicited messages related to OTA is
* forwarded to this callback for filteration. Right now the callback is used to filter responses to job requests * forwarded to this callback for filtration. Right now the callback is used to filter responses to job requests
* from the OTA service. * from the OTA service.
* *
* @param[in] pvIncomingPublishCallbackContext MQTT context which stores the connection. * @param[in] pvIncomingPublishCallbackContext MQTT context which stores the connection.
@ -1043,12 +1043,12 @@ static void prvCommandCallback( MQTTAgentCommandContext_t * pxCommandContext,
static void prvMQTTSubscribeCompleteCallback( MQTTAgentCommandContext_t * pxCommandContext, static void prvMQTTSubscribeCompleteCallback( MQTTAgentCommandContext_t * pxCommandContext,
MQTTAgentReturnInfo_t * pxReturnInfo ) MQTTAgentReturnInfo_t * pxReturnInfo )
{ {
MQTTAgentSubscribeArgs_t * pSubsribeArgs; MQTTAgentSubscribeArgs_t * pSubscribeArgs;
if( pxReturnInfo->returnCode == MQTTSuccess ) if( pxReturnInfo->returnCode == MQTTSuccess )
{ {
pSubsribeArgs = ( MQTTAgentSubscribeArgs_t * ) ( pxCommandContext->pArgs ); pSubscribeArgs = ( MQTTAgentSubscribeArgs_t * ) ( pxCommandContext->pArgs );
prvRegisterOTACallback( pSubsribeArgs->pSubscribeInfo->pTopicFilter, pSubsribeArgs->pSubscribeInfo->topicFilterLength ); prvRegisterOTACallback( pSubscribeArgs->pSubscribeInfo->pTopicFilter, pSubscribeArgs->pSubscribeInfo->topicFilterLength );
} }
/* Store the result in the application defined context so the task that /* Store the result in the application defined context so the task that
@ -1288,42 +1288,43 @@ static BaseType_t prvSocketConnect( NetworkContext_t * pxNetworkContext )
NetworkCredentials_t xNetworkCredentials = { 0 }; NetworkCredentials_t xNetworkCredentials = { 0 };
#if defined( democonfigUSE_AWS_IOT_CORE_BROKER ) #if defined( democonfigUSE_AWS_IOT_CORE_BROKER )
#if defined( democonfigCLIENT_USERNAME ) #if defined( democonfigCLIENT_USERNAME )
/*
* When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* to AWS IoT Core with Custom Authentication on port 443.
*
* Custom Authentication uses the contents of the username and password
* fields of the MQTT CONNECT packet to authenticate the client.
*
* For more information, refer to the documentation at:
* https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
*/
static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
#if democonfigMQTT_BROKER_PORT != 443U
#error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
* x509 Certificate Authentication.
*/
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */
/* /*
* An ALPN identifier is only required when connecting to AWS IoT core on port 443. * When democonfigCLIENT_USERNAME is defined, use the "mqtt" alpn to connect
* https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html * to AWS IoT Core with Custom Authentication on port 443.
*/ *
#if democonfigMQTT_BROKER_PORT == 443U * Custom Authentication uses the contents of the username and password
xNetworkCredentials.pAlpnProtos = ppcAlpnProtocols; * fields of the MQTT CONNECT packet to authenticate the client.
#elif democonfigMQTT_BROKER_PORT == 8883U *
xNetworkCredentials.pAlpnProtos = NULL; * For more information, refer to the documentation at:
#else /* democonfigMQTT_BROKER_PORT != 8883U */ * https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html
xNetworkCredentials.pAlpnProtos = NULL; */
#error "MQTT connections to AWS IoT Core are only allowed on ports 443 and 8883." static const char * ppcAlpnProtocols[] = { "mqtt", NULL };
#if democonfigMQTT_BROKER_PORT != 443U
#error "Connections to AWS IoT Core with custom authentication must connect to TCP port 443 with the \"mqtt\" alpn."
#endif /* democonfigMQTT_BROKER_PORT != 443U */ #endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* if !defined( democonfigCLIENT_USERNAME ) */
/*
* Otherwise, use the "x-amzn-mqtt-ca" alpn to connect to AWS IoT Core using
* x509 Certificate Authentication.
*/
static const char * ppcAlpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
#endif /* !defined( democonfigCLIENT_USERNAME ) */
/*
* An ALPN identifier is only required when connecting to AWS IoT core on port 443.
* https://docs.aws.amazon.com/iot/latest/developerguide/protocols.html
*/
#if democonfigMQTT_BROKER_PORT == 443U
xNetworkCredentials.pAlpnProtos = ppcAlpnProtocols;
#elif democonfigMQTT_BROKER_PORT == 8883U
xNetworkCredentials.pAlpnProtos = NULL;
#else /* democonfigMQTT_BROKER_PORT != 8883U */
xNetworkCredentials.pAlpnProtos = NULL;
#error "MQTT connections to AWS IoT Core are only allowed on ports 443 and 8883."
#endif /* democonfigMQTT_BROKER_PORT != 443U */
#else /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */ #else /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */
xNetworkCredentials.pAlpnProtos = NULL; xNetworkCredentials.pAlpnProtos = NULL;
#endif /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */ #endif /* !defined( democonfigUSE_AWS_IOT_CORE_BROKER ) */
@ -2037,7 +2038,7 @@ static BaseType_t prvRunOTADemo( void )
} }
/** /**
* Remvove callback for receiving messages intended for OTA agent from broker, * Remove callback for receiving messages intended for OTA agent from broker,
* for which the topic has not been subscribed for. * for which the topic has not been subscribed for.
*/ */
removeSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext, removeSubscription( ( SubscriptionElement_t * ) xGlobalMqttAgentContext.pIncomingCallbackContext,
@ -2086,6 +2087,7 @@ void vOtaDemoTask( void * pvParam )
if( xPlatformIsNetworkUp() == pdFALSE ) if( xPlatformIsNetworkUp() == pdFALSE )
{ {
LogInfo( ( "Waiting for the network link up event..." ) ); LogInfo( ( "Waiting for the network link up event..." ) );
while( xPlatformIsNetworkUp() == pdFALSE ) while( xPlatformIsNetworkUp() == pdFALSE )
{ {
vTaskDelay( pdMS_TO_TICKS( 1000U ) ); vTaskDelay( pdMS_TO_TICKS( 1000U ) );

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <Filter Include="Source Files">

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -76,33 +76,34 @@ extern void vLoggingPrintf( const char * pcFormatString,
*/ */
#define MQTT_STATE_ARRAY_MAX_COUNT 10U #define MQTT_STATE_ARRAY_MAX_COUNT 10U
/*********************** coreMQTT Agent Configurations **********************/ /*********************** coreMQTT Agent Configurations **********************/
/**
* @brief The maximum number of pending acknowledgments to track for a single /**
* connection. * @brief The maximum number of pending acknowledgments to track for a single
* * connection.
* @note The MQTT agent tracks MQTT commands (such as PUBLISH and SUBSCRIBE) th *
* at are still waiting to be acknowledged. MQTT_AGENT_MAX_OUTSTANDING_ACKS set * @note The MQTT agent tracks MQTT commands (such as PUBLISH and SUBSCRIBE) th
* the maximum number of acknowledgments that can be outstanding at any one time. * at are still waiting to be acknowledged. MQTT_AGENT_MAX_OUTSTANDING_ACKS set
* The higher this number is the greater the agent's RAM consumption will be. * the maximum number of acknowledgments that can be outstanding at any one time.
*/ * The higher this number is the greater the agent's RAM consumption will be.
*/
#define MQTT_AGENT_MAX_OUTSTANDING_ACKS ( 20U ) #define MQTT_AGENT_MAX_OUTSTANDING_ACKS ( 20U )
/** /**
* @brief Time in MS that the MQTT agent task will wait in the Blocked state (so * @brief Time in MS that the MQTT agent task will wait in the Blocked state (so
* not using any CPU time) for a command to arrive in its command queue before * not using any CPU time) for a command to arrive in its command queue before
* exiting the blocked state so it can call MQTT_ProcessLoop(). * exiting the blocked state so it can call MQTT_ProcessLoop().
* *
* @note It is important MQTT_ProcessLoop() is called often if there is known * @note It is important MQTT_ProcessLoop() is called often if there is known
* MQTT traffic, but calling it too often can take processing time away from * MQTT traffic, but calling it too often can take processing time away from
* lower priority tasks and waste CPU time and power. * lower priority tasks and waste CPU time and power.
*/ */
#define MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME ( 1000 ) #define MQTT_AGENT_MAX_EVENT_QUEUE_WAIT_TIME ( 1000 )
/** /**
* @brief The number of command structures to allocate in the pool * @brief The number of command structures to allocate in the pool
* for the agent. * for the agent.
*/ */
#define MQTT_COMMAND_CONTEXTS_POOL_SIZE 10 #define MQTT_COMMAND_CONTEXTS_POOL_SIZE 10

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in

View file

@ -1,4 +1,4 @@

Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.31205.134 VisualStudioVersion = 16.0.31205.134

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -41,332 +41,345 @@
#include "FreeRTOS_server_private.h" #include "FreeRTOS_server_private.h"
/* Remove the entire file if TCP is not being used. */ /* Remove the entire file if TCP is not being used. */
#if( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) #if ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) )
#if !defined( ARRAY_SIZE ) #if !defined( ARRAY_SIZE )
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] ) #define ARRAY_SIZE( x ) ( BaseType_t ) ( sizeof( x ) / sizeof( x )[ 0 ] )
#endif #endif
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket ); static void prvReceiveNewClient( TCPServer_t * pxServer,
static char *strnew( const char *pcString ); BaseType_t xIndex,
Socket_t xNexSocket );
static char * strnew( const char * pcString );
/* Remove slashes at the end of a path. */ /* Remove slashes at the end of a path. */
static void prvRemoveSlash( char *pcDir ); static void prvRemoveSlash( char * pcDir );
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount ) TCPServer_t * FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG * pxConfigs,
{ BaseType_t xCount )
TCPServer_t *pxServer; {
SocketSet_t xSocketSet; TCPServer_t * pxServer;
SocketSet_t xSocketSet;
/* Create a new server. /* Create a new server.
xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */ * xPort / xPortAlt : Make the service available on 1 or 2 public port numbers. */
xSocketSet = FreeRTOS_CreateSocketSet(); xSocketSet = FreeRTOS_CreateSocketSet();
if( xSocketSet != NULL ) if( xSocketSet != NULL )
{ {
BaseType_t xSize; BaseType_t xSize;
xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] ); xSize = sizeof( *pxServer ) - sizeof( pxServer->xServers ) + xCount * sizeof( pxServer->xServers[ 0 ] );
pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize ); pxServer = ( TCPServer_t * ) pvPortMallocLarge( xSize );
if( pxServer != NULL )
{
struct freertos_sockaddr xAddress;
BaseType_t xNoTimeout = 0;
BaseType_t xIndex;
memset( pxServer, '\0', xSize ); if( pxServer != NULL )
pxServer->xServerCount = xCount; {
pxServer->xSocketSet = xSocketSet; struct freertos_sockaddr xAddress;
BaseType_t xNoTimeout = 0;
BaseType_t xIndex;
for( xIndex = 0; xIndex < xCount; xIndex++ ) memset( pxServer, '\0', xSize );
{ pxServer->xServerCount = xCount;
BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber; pxServer->xSocketSet = xSocketSet;
if( xPortNumber > 0 ) for( xIndex = 0; xIndex < xCount; xIndex++ )
{ {
Socket_t xSocket; BaseType_t xPortNumber = pxConfigs[ xIndex ].xPortNumber;
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP ); if( xPortNumber > 0 )
FreeRTOS_printf( ( "TCP socket on port %d\n", ( int )xPortNumber ) ); {
Socket_t xSocket;
if( xSocket != FREERTOS_INVALID_SOCKET ) xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
{ FreeRTOS_printf( ( "TCP socket on port %d\n", ( int ) xPortNumber ) );
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{
xAddress.sin_address.ulIP_IPv4 = FreeRTOS_GetIPAddress(); /* Single NIC, currently not used */
}
#else
{
xAddress.sin_addr = FreeRTOS_GetIPAddress(); /* Single NIC, currently not used */
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xAddress.sin_port = FreeRTOS_htons( xPortNumber ); if( xSocket != FREERTOS_INVALID_SOCKET )
xAddress.sin_family = FREERTOS_AF_INET; {
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{
xAddress.sin_address.ulIP_IPv4 = FreeRTOS_GetIPAddress(); /* Single NIC, currently not used */
}
#else
{
xAddress.sin_addr = FreeRTOS_GetIPAddress(); /* Single NIC, currently not used */
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) ); xAddress.sin_port = FreeRTOS_htons( xPortNumber );
FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog ); xAddress.sin_family = FREERTOS_AF_INET;
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) ); FreeRTOS_bind( xSocket, &xAddress, sizeof( xAddress ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) ); FreeRTOS_listen( xSocket, pxConfigs[ xIndex ].xBackLog );
#if( ipconfigHTTP_RX_BUFSIZE > 0 ) FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
{ FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, ( void * ) &xNoTimeout, sizeof( BaseType_t ) );
if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )
{
WinProperties_t xWinProps;
memset( &xWinProps, '\0', sizeof( xWinProps ) ); #if ( ipconfigHTTP_RX_BUFSIZE > 0 )
/* The parent socket itself won't get connected. The properties below {
will be inherited by each new child socket. */ if( pxConfigs[ xIndex ].eType == eSERVER_HTTP )
xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE; {
xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE; WinProperties_t xWinProps;
xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;
xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;
/* Set the window and buffer sizes. */ memset( &xWinProps, '\0', sizeof( xWinProps ) );
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
}
}
#endif
FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ|eSELECT_EXCEPT ); /* The parent socket itself won't get connected. The properties below
pxServer->xServers[ xIndex ].xSocket = xSocket; * will be inherited by each new child socket. */
pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType; xWinProps.lTxBufSize = ipconfigHTTP_TX_BUFSIZE;
pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir ); xWinProps.lTxWinSize = ipconfigHTTP_TX_WINSIZE;
prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir ); xWinProps.lRxBufSize = ipconfigHTTP_RX_BUFSIZE;
} xWinProps.lRxWinSize = ipconfigHTTP_RX_WINSIZE;
}
}
}
else
{
/* Could not allocate the server, delete the socket set */
FreeRTOS_DeleteSocketSet( xSocketSet );
}
}
else
{
/* Could not create a socket set, return NULL */
pxServer = NULL;
}
return pxServer; /* Set the window and buffer sizes. */
} FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) );
}
}
#endif /* if ( ipconfigHTTP_RX_BUFSIZE > 0 ) */
FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT );
pxServer->xServers[ xIndex ].xSocket = xSocket;
pxServer->xServers[ xIndex ].eType = pxConfigs[ xIndex ].eType;
pxServer->xServers[ xIndex ].pcRootDir = strnew( pxConfigs[ xIndex ].pcRootDir );
prvRemoveSlash( ( char * ) pxServer->xServers[ xIndex ].pcRootDir );
}
}
}
}
else
{
/* Could not allocate the server, delete the socket set */
FreeRTOS_DeleteSocketSet( xSocketSet );
}
}
else
{
/* Could not create a socket set, return NULL */
pxServer = NULL;
}
return pxServer;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvReceiveNewClient( TCPServer_t *pxServer, BaseType_t xIndex, Socket_t xNexSocket ) static void prvReceiveNewClient( TCPServer_t * pxServer,
{ BaseType_t xIndex,
TCPClient_t *pxClient = NULL; Socket_t xNexSocket )
BaseType_t xSize = 0; {
FTCPWorkFunction fWorkFunc = NULL; TCPClient_t * pxClient = NULL;
FTCPDeleteFunction fDeleteFunc = NULL; BaseType_t xSize = 0;
const char *pcType = "Unknown"; FTCPWorkFunction fWorkFunc = NULL;
FTCPDeleteFunction fDeleteFunc = NULL;
const char * pcType = "Unknown";
/*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure /*_RB_ Can the work and delete functions be part of the xSERVER_CONFIG structure
becomes generic, with no pre-processing required? */ * becomes generic, with no pre-processing required? */
#if( ipconfigUSE_HTTP != 0 ) #if ( ipconfigUSE_HTTP != 0 )
{ {
if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP ) if( pxServer->xServers[ xIndex ].eType == eSERVER_HTTP )
{ {
xSize = sizeof( HTTPClient_t ); xSize = sizeof( HTTPClient_t );
fWorkFunc = xHTTPClientWork; fWorkFunc = xHTTPClientWork;
fDeleteFunc = vHTTPClientDelete; fDeleteFunc = vHTTPClientDelete;
pcType = "HTTP"; pcType = "HTTP";
} }
} }
#endif /* ipconfigUSE_HTTP != 0 */ #endif /* ipconfigUSE_HTTP != 0 */
#if( ipconfigUSE_FTP != 0 ) #if ( ipconfigUSE_FTP != 0 )
{ {
if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP ) if( pxServer->xServers[ xIndex ].eType == eSERVER_FTP )
{ {
xSize = sizeof( FTPClient_t ); xSize = sizeof( FTPClient_t );
fWorkFunc = xFTPClientWork; fWorkFunc = xFTPClientWork;
fDeleteFunc = vFTPClientDelete; fDeleteFunc = vFTPClientDelete;
pcType = "FTP"; pcType = "FTP";
} }
} }
#endif /* ipconfigUSE_FTP != 0 */ #endif /* ipconfigUSE_FTP != 0 */
/* Malloc enough space for a new HTTP-client */ /* Malloc enough space for a new HTTP-client */
if( xSize ) if( xSize )
{ {
pxClient = ( TCPClient_t* ) pvPortMallocLarge( xSize ); pxClient = ( TCPClient_t * ) pvPortMallocLarge( xSize );
} }
if( pxClient != NULL ) if( pxClient != NULL )
{ {
memset( pxClient, '\0', xSize ); memset( pxClient, '\0', xSize );
/* Put the new client in front of the list. */ /* Put the new client in front of the list. */
pxClient->eType = pxServer->xServers[ xIndex ].eType; pxClient->eType = pxServer->xServers[ xIndex ].eType;
pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir; pxClient->pcRootDir = pxServer->xServers[ xIndex ].pcRootDir;
pxClient->pxParent = pxServer; pxClient->pxParent = pxServer;
pxClient->xSocket = xNexSocket; pxClient->xSocket = xNexSocket;
pxClient->pxNextClient = pxServer->pxClients; pxClient->pxNextClient = pxServer->pxClients;
pxClient->fWorkFunction = fWorkFunc; pxClient->fWorkFunction = fWorkFunc;
pxClient->fDeleteFunction = fDeleteFunc; pxClient->fDeleteFunction = fDeleteFunc;
pxServer->pxClients = pxClient; pxServer->pxClients = pxClient;
FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ|eSELECT_EXCEPT ); FreeRTOS_FD_SET( xNexSocket, pxServer->xSocketSet, eSELECT_READ | eSELECT_EXCEPT );
} }
else else
{ {
pcType = "closed"; pcType = "closed";
FreeRTOS_closesocket( xNexSocket ); FreeRTOS_closesocket( xNexSocket );
} }
{
struct freertos_sockaddr xRemoteAddress;
FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, (unsigned)FreeRTOS_ntohl( xRemoteAddress.sin_address.ulIP_IPv4 ) ) );
}
#else
{
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, (unsigned)FreeRTOS_ntohl( xRemoteAddress.sin_addr ) ) );
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
}
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */ {
( void ) pcType; struct freertos_sockaddr xRemoteAddress;
} FreeRTOS_GetRemoteAddress( pxClient->xSocket, &xRemoteAddress );
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, ( unsigned ) FreeRTOS_ntohl( xRemoteAddress.sin_address.ulIP_IPv4 ) ) );
}
#else
{
FreeRTOS_printf( ( "TPC-server: new %s client %xip\n", pcType, ( unsigned ) FreeRTOS_ntohl( xRemoteAddress.sin_addr ) ) );
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
}
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
( void ) pcType;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime ) void FreeRTOS_TCPServerWork( TCPServer_t * pxServer,
{ TickType_t xBlockingTime )
TCPClient_t **ppxClient; {
BaseType_t xIndex; TCPClient_t ** ppxClient;
BaseType_t xRc; BaseType_t xIndex;
BaseType_t xRc;
/* Let the server do one working cycle */ /* Let the server do one working cycle */
xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime ); xRc = FreeRTOS_select( pxServer->xSocketSet, xBlockingTime );
if( xRc != 0 ) if( xRc != 0 )
{ {
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ ) for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
{ {
struct freertos_sockaddr xAddress; struct freertos_sockaddr xAddress;
Socket_t xNexSocket; Socket_t xNexSocket;
socklen_t xSocketLength; socklen_t xSocketLength;
if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET ) if( pxServer->xServers[ xIndex ].xSocket == FREERTOS_NO_SOCKET )
{ {
continue; continue;
} }
xSocketLength = sizeof( xAddress ); xSocketLength = sizeof( xAddress );
xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength); xNexSocket = FreeRTOS_accept( pxServer->xServers[ xIndex ].xSocket, &xAddress, &xSocketLength );
if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) ) if( ( xNexSocket != FREERTOS_NO_SOCKET ) && ( xNexSocket != FREERTOS_INVALID_SOCKET ) )
{ {
prvReceiveNewClient( pxServer, xIndex, xNexSocket ); prvReceiveNewClient( pxServer, xIndex, xNexSocket );
} }
} }
} }
ppxClient = &pxServer->pxClients; ppxClient = &pxServer->pxClients;
while( ( * ppxClient ) != NULL ) while( ( *ppxClient ) != NULL )
{ {
TCPClient_t *pxThis = *ppxClient; TCPClient_t * pxThis = *ppxClient;
/* Almost C++ */ /* Almost C++ */
xRc = pxThis->fWorkFunction( pxThis ); xRc = pxThis->fWorkFunction( pxThis );
if (xRc < 0 ) if( xRc < 0 )
{ {
*ppxClient = pxThis->pxNextClient; *ppxClient = pxThis->pxNextClient;
/* Close handles, resources */ /* Close handles, resources */
pxThis->fDeleteFunction( pxThis ); pxThis->fDeleteFunction( pxThis );
/* Free the space */ /* Free the space */
vPortFreeLarge( pxThis ); vPortFreeLarge( pxThis );
} }
else else
{ {
ppxClient = &( pxThis->pxNextClient ); ppxClient = &( pxThis->pxNextClient );
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static char *strnew( const char *pcString ) static char * strnew( const char * pcString )
{ {
BaseType_t xLength; BaseType_t xLength;
char *pxBuffer; char * pxBuffer;
xLength = strlen( pcString ) + 1; xLength = strlen( pcString ) + 1;
pxBuffer = ( char * ) pvPortMalloc( xLength ); pxBuffer = ( char * ) pvPortMalloc( xLength );
if( pxBuffer != NULL )
{
memcpy( pxBuffer, pcString, xLength );
}
return pxBuffer; if( pxBuffer != NULL )
} {
memcpy( pxBuffer, pcString, xLength );
}
return pxBuffer;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvRemoveSlash( char *pcDir ) static void prvRemoveSlash( char * pcDir )
{ {
BaseType_t xLength = strlen( pcDir ); BaseType_t xLength = strlen( pcDir );
while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) ) while( ( xLength > 0 ) && ( pcDir[ xLength - 1 ] == '/' ) )
{ {
pcDir[ --xLength ] = '\0'; pcDir[ --xLength ] = '\0';
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ipconfigSUPPORT_SIGNALS != 0 ) #if ( ipconfigSUPPORT_SIGNALS != 0 )
/* FreeRTOS_TCPServerWork() calls select(). /* FreeRTOS_TCPServerWork() calls select().
The two functions below provide a possibility to interrupt * The two functions below provide a possibility to interrupt
the call to select(). After the interruption, resume * the call to select(). After the interruption, resume
by calling FreeRTOS_TCPServerWork() again. */ * by calling FreeRTOS_TCPServerWork() again. */
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer ) BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t * pxServer )
{ {
BaseType_t xIndex; BaseType_t xIndex;
BaseType_t xResult = pdFALSE; BaseType_t xResult = pdFALSE;
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
{
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );
xResult = pdTRUE;
break;
}
}
return xResult; for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
} {
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocket( pxServer->xServers[ xIndex ].xSocket );
xResult = pdTRUE;
break;
}
}
#endif /* ipconfigSUPPORT_SIGNALS */ return xResult;
}
#endif /* ipconfigSUPPORT_SIGNALS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ipconfigSUPPORT_SIGNALS != 0 ) #if ( ipconfigSUPPORT_SIGNALS != 0 )
/* Same as above: this function may be called from an ISR, /* Same as above: this function may be called from an ISR,
for instance a GPIO interrupt. */ * for instance a GPIO interrupt. */
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken ) BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t * pxServer,
{ BaseType_t * pxHigherPriorityTaskWoken )
BaseType_t xIndex; {
BaseType_t xResult = pdFALSE; BaseType_t xIndex;
for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ ) BaseType_t xResult = pdFALSE;
{
if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );
xResult = pdTRUE;
break;
}
}
return xResult; for( xIndex = 0; xIndex < pxServer->xServerCount; xIndex++ )
} {
#endif /* ipconfigSUPPORT_SIGNALS */ if( pxServer->xServers[ xIndex ].xSocket != FREERTOS_NO_SOCKET )
{
FreeRTOS_SignalSocketFromISR( pxServer->xServers[ xIndex ].xSocket, pxHigherPriorityTaskWoken );
xResult = pdTRUE;
break;
}
}
return xResult;
}
#endif /* ipconfigSUPPORT_SIGNALS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) */ #endif /* ( ipconfigUSE_TCP == 1 ) && ( ( ipconfigUSE_HTTP == 1 ) || ( ipconfigUSE_FTP == 1 ) ) */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS+TCP V2.0.3 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -19,8 +19,9 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@ -32,43 +33,43 @@
const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] = const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ] =
{ {
/* cmdLen cmdName[7] cmdType checkLogin checkNullArg */ /* cmdLen cmdName[7] cmdType checkLogin checkNullArg */
{ 4, "USER", ECMD_USER, pdFALSE, pdFALSE }, { 4, "USER", ECMD_USER, pdFALSE, pdFALSE },
{ 4, "PASS", ECMD_PASS, pdFALSE, pdFALSE }, { 4, "PASS", ECMD_PASS, pdFALSE, pdFALSE },
{ 4, "ACCT", ECMD_ACCT, pdTRUE, pdFALSE }, { 4, "ACCT", ECMD_ACCT, pdTRUE, pdFALSE },
{ 3, "CWD", ECMD_CWD, pdTRUE, pdTRUE }, { 3, "CWD", ECMD_CWD, pdTRUE, pdTRUE },
{ 4, "CDUP", ECMD_CDUP, pdTRUE, pdFALSE }, { 4, "CDUP", ECMD_CDUP, pdTRUE, pdFALSE },
{ 4, "SMNT", ECMD_SMNT, pdTRUE, pdFALSE }, { 4, "SMNT", ECMD_SMNT, pdTRUE, pdFALSE },
{ 4, "QUIT", ECMD_QUIT, pdTRUE, pdFALSE }, { 4, "QUIT", ECMD_QUIT, pdTRUE, pdFALSE },
{ 4, "REIN", ECMD_REIN, pdTRUE, pdFALSE }, { 4, "REIN", ECMD_REIN, pdTRUE, pdFALSE },
{ 4, "PORT", ECMD_PORT, pdTRUE, pdFALSE }, { 4, "PORT", ECMD_PORT, pdTRUE, pdFALSE },
{ 4, "PASV", ECMD_PASV, pdTRUE, pdFALSE }, { 4, "PASV", ECMD_PASV, pdTRUE, pdFALSE },
{ 4, "TYPE", ECMD_TYPE, pdTRUE, pdFALSE }, { 4, "TYPE", ECMD_TYPE, pdTRUE, pdFALSE },
{ 4, "STRU", ECMD_STRU, pdTRUE, pdFALSE }, { 4, "STRU", ECMD_STRU, pdTRUE, pdFALSE },
{ 4, "MODE", ECMD_MODE, pdTRUE, pdFALSE }, { 4, "MODE", ECMD_MODE, pdTRUE, pdFALSE },
{ 4, "RETR", ECMD_RETR, pdTRUE, pdTRUE }, { 4, "RETR", ECMD_RETR, pdTRUE, pdTRUE },
{ 4, "STOR", ECMD_STOR, pdTRUE, pdTRUE }, { 4, "STOR", ECMD_STOR, pdTRUE, pdTRUE },
{ 4, "STOU", ECMD_STOU, pdTRUE, pdFALSE }, { 4, "STOU", ECMD_STOU, pdTRUE, pdFALSE },
{ 4, "APPE", ECMD_APPE, pdTRUE, pdFALSE }, { 4, "APPE", ECMD_APPE, pdTRUE, pdFALSE },
{ 4, "ALLO", ECMD_ALLO, pdTRUE, pdFALSE }, { 4, "ALLO", ECMD_ALLO, pdTRUE, pdFALSE },
{ 4, "REST", ECMD_REST, pdTRUE, pdFALSE }, { 4, "REST", ECMD_REST, pdTRUE, pdFALSE },
{ 4, "RNFR", ECMD_RNFR, pdTRUE, pdTRUE }, { 4, "RNFR", ECMD_RNFR, pdTRUE, pdTRUE },
{ 4, "RNTO", ECMD_RNTO, pdTRUE, pdTRUE }, { 4, "RNTO", ECMD_RNTO, pdTRUE, pdTRUE },
{ 4, "ABOR", ECMD_ABOR, pdTRUE, pdFALSE }, { 4, "ABOR", ECMD_ABOR, pdTRUE, pdFALSE },
{ 4, "SIZE", ECMD_SIZE, pdTRUE, pdTRUE }, { 4, "SIZE", ECMD_SIZE, pdTRUE, pdTRUE },
{ 4, "MDTM", ECMD_MDTM, pdTRUE, pdTRUE }, { 4, "MDTM", ECMD_MDTM, pdTRUE, pdTRUE },
{ 4, "DELE", ECMD_DELE, pdTRUE, pdTRUE }, { 4, "DELE", ECMD_DELE, pdTRUE, pdTRUE },
{ 3, "RMD", ECMD_RMD, pdTRUE, pdTRUE }, { 3, "RMD", ECMD_RMD, pdTRUE, pdTRUE },
{ 3, "MKD", ECMD_MKD, pdTRUE, pdTRUE }, { 3, "MKD", ECMD_MKD, pdTRUE, pdTRUE },
{ 3, "PWD", ECMD_PWD, pdTRUE, pdFALSE }, { 3, "PWD", ECMD_PWD, pdTRUE, pdFALSE },
{ 4, "LIST", ECMD_LIST, pdTRUE, pdFALSE }, { 4, "LIST", ECMD_LIST, pdTRUE, pdFALSE },
{ 4, "NLST", ECMD_NLST, pdTRUE, pdFALSE }, { 4, "NLST", ECMD_NLST, pdTRUE, pdFALSE },
{ 4, "SITE", ECMD_SITE, pdTRUE, pdFALSE }, { 4, "SITE", ECMD_SITE, pdTRUE, pdFALSE },
{ 4, "SYST", ECMD_SYST, pdFALSE, pdFALSE }, { 4, "SYST", ECMD_SYST, pdFALSE, pdFALSE },
{ 4, "FEAT", ECMD_FEAT, pdFALSE, pdFALSE }, { 4, "FEAT", ECMD_FEAT, pdFALSE, pdFALSE },
{ 4, "STAT", ECMD_STAT, pdTRUE, pdFALSE }, { 4, "STAT", ECMD_STAT, pdTRUE, pdFALSE },
{ 4, "HELP", ECMD_HELP, pdFALSE, pdFALSE }, { 4, "HELP", ECMD_HELP, pdFALSE, pdFALSE },
{ 4, "NOOP", ECMD_NOOP, pdFALSE, pdFALSE }, { 4, "NOOP", ECMD_NOOP, pdFALSE, pdFALSE },
{ 4, "EMPT", ECMD_EMPTY, pdFALSE, pdFALSE }, { 4, "EMPT", ECMD_EMPTY, pdFALSE, pdFALSE },
{ 4, "CLOS", ECMD_CLOSE, pdTRUE, pdFALSE }, { 4, "CLOS", ECMD_CLOSE, pdTRUE, pdFALSE },
{ 4, "UNKN", ECMD_UNKNOWN, pdFALSE, pdFALSE }, { 4, "UNKN", ECMD_UNKNOWN, pdFALSE, pdFALSE },
}; };

View file

@ -1,11 +1,6 @@
/* /*
*! * FreeRTOS V202212.00
*! The protocols implemented in this file are intended to be demo quality only, * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*! and not for production devices.
*!
*
* FreeRTOS+TCP V2.0.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,10 +19,17 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
/**
*!
*! The protocols implemented in this file are intended to be demo quality only,
*! and not for production devices.
*!
*/
/* Standard includes. */ /* Standard includes. */
#include <stdio.h> #include <stdio.h>
@ -40,37 +42,46 @@
const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] = const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ] =
{ {
{ 3, "GET", ECMD_GET }, { 3, "GET", ECMD_GET },
{ 4, "HEAD", ECMD_HEAD }, { 4, "HEAD", ECMD_HEAD },
{ 4, "POST", ECMD_POST }, { 4, "POST", ECMD_POST },
{ 3, "PUT", ECMD_PUT }, { 3, "PUT", ECMD_PUT },
{ 6, "DELETE", ECMD_DELETE }, { 6, "DELETE", ECMD_DELETE },
{ 5, "TRACE", ECMD_TRACE }, { 5, "TRACE", ECMD_TRACE },
{ 7, "OPTIONS", ECMD_OPTIONS }, { 7, "OPTIONS", ECMD_OPTIONS },
{ 7, "CONNECT", ECMD_CONNECT }, { 7, "CONNECT", ECMD_CONNECT },
{ 5, "PATCH", ECMD_PATCH }, { 5, "PATCH", ECMD_PATCH },
{ 4, "UNKN", ECMD_UNK }, { 4, "UNKN", ECMD_UNK },
}; };
const char *webCodename (int aCode) const char * webCodename( int aCode )
{ {
switch (aCode) { switch( aCode )
case WEB_REPLY_OK: // = 200, {
return "OK"; case WEB_REPLY_OK: /* = 200, */
case WEB_NO_CONTENT: // 204 return "OK";
return "No content";
case WEB_BAD_REQUEST: // = 400, case WEB_NO_CONTENT: /* 204 */
return "Bad request"; return "No content";
case WEB_UNAUTHORIZED: // = 401,
return "Authorization Required"; case WEB_BAD_REQUEST: /* = 400, */
case WEB_NOT_FOUND: // = 404, return "Bad request";
return "Not Found";
case WEB_GONE: // = 410, case WEB_UNAUTHORIZED: /* = 401, */
return "Done"; return "Authorization Required";
case WEB_PRECONDITION_FAILED: // = 412,
return "Precondition Failed"; case WEB_NOT_FOUND: /* = 404, */
case WEB_INTERNAL_SERVER_ERROR: // = 500, return "Not Found";
return "Internal Server Error";
} case WEB_GONE: /* = 410, */
return "Unknown"; return "Done";
case WEB_PRECONDITION_FAILED: /* = 412, */
return "Precondition Failed";
case WEB_INTERNAL_SERVER_ERROR: /* = 500, */
return "Internal Server Error";
}
return "Unknown";
} }

View file

@ -1,11 +1,6 @@
/* /*
*! * FreeRTOS V202212.00
*! The protocols implemented in this file are intended to be demo quality only, * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*! and not for production devices.
*!
*
* FreeRTOS+TCP V2.0.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,8 +19,16 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/**
*!
*! The protocols implemented in this file are intended to be demo quality only,
*! and not for production devices.
*!
*/ */
/* Standard includes. */ /* Standard includes. */
@ -46,388 +49,416 @@
#include "FreeRTOS_server_private.h" #include "FreeRTOS_server_private.h"
/* Remove the whole file if HTTP is not supported. */ /* Remove the whole file if HTTP is not supported. */
#if( ipconfigUSE_HTTP == 1 ) #if ( ipconfigUSE_HTTP == 1 )
/* FreeRTOS+FAT includes. */ /* FreeRTOS+FAT includes. */
#include "ff_stdio.h" #include "ff_stdio.h"
#ifndef HTTP_SERVER_BACKLOG #ifndef HTTP_SERVER_BACKLOG
#define HTTP_SERVER_BACKLOG ( 12 ) #define HTTP_SERVER_BACKLOG ( 12 )
#endif #endif
#ifndef USE_HTML_CHUNKS #ifndef USE_HTML_CHUNKS
#define USE_HTML_CHUNKS ( 0 ) #define USE_HTML_CHUNKS ( 0 )
#endif #endif
#if !defined( ARRAY_SIZE ) #if !defined( ARRAY_SIZE )
#define ARRAY_SIZE(x) ( BaseType_t ) (sizeof( x ) / sizeof( x )[ 0 ] ) #define ARRAY_SIZE( x ) ( BaseType_t ) ( sizeof( x ) / sizeof( x )[ 0 ] )
#endif #endif
/* Some defines to make the code more readbale */ /* Some defines to make the code more readbale */
#define pcCOMMAND_BUFFER pxClient->pxParent->pcCommandBuffer #define pcCOMMAND_BUFFER pxClient->pxParent->pcCommandBuffer
#define pcNEW_DIR pxClient->pxParent->pcNewDir #define pcNEW_DIR pxClient->pxParent->pcNewDir
#define pcFILE_BUFFER pxClient->pxParent->pcFileBuffer #define pcFILE_BUFFER pxClient->pxParent->pcFileBuffer
#ifndef ipconfigHTTP_REQUEST_CHARACTER #ifndef ipconfigHTTP_REQUEST_CHARACTER
#define ipconfigHTTP_REQUEST_CHARACTER '?' #define ipconfigHTTP_REQUEST_CHARACTER '?'
#endif #endif
/*_RB_ Need comment block, although fairly self evident. */ /*_RB_ Need comment block, although fairly self evident. */
static void prvFileClose( HTTPClient_t *pxClient ); static void prvFileClose( HTTPClient_t * pxClient );
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex ); static BaseType_t prvProcessCmd( HTTPClient_t * pxClient,
static const char *pcGetContentsType( const char *apFname ); BaseType_t xIndex );
static BaseType_t prvOpenURL( HTTPClient_t *pxClient ); static const char * pcGetContentsType( const char * apFname );
static BaseType_t prvSendFile( HTTPClient_t *pxClient ); static BaseType_t prvOpenURL( HTTPClient_t * pxClient );
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode ); static BaseType_t prvSendFile( HTTPClient_t * pxClient );
static BaseType_t prvSendReply( HTTPClient_t * pxClient,
BaseType_t xCode );
static const char pcEmptyString[1] = { '\0' }; static const char pcEmptyString[ 1 ] = { '\0' };
typedef struct xTYPE_COUPLE typedef struct xTYPE_COUPLE
{ {
const char *pcExtension; const char * pcExtension;
const char *pcType; const char * pcType;
} TypeCouple_t; } TypeCouple_t;
static TypeCouple_t pxTypeCouples[ ] = static TypeCouple_t pxTypeCouples[] =
{ {
{ "html", "text/html" }, { "html", "text/html" },
{ "css", "text/css" }, { "css", "text/css" },
{ "js", "text/javascript" }, { "js", "text/javascript" },
{ "png", "image/png" }, { "png", "image/png" },
{ "jpg", "image/jpeg" }, { "jpg", "image/jpeg" },
{ "gif", "image/gif" }, { "gif", "image/gif" },
{ "txt", "text/plain" }, { "txt", "text/plain" },
{ "mp3", "audio/mpeg3" }, { "mp3", "audio/mpeg3" },
{ "wav", "audio/wav" }, { "wav", "audio/wav" },
{ "flac", "audio/ogg" }, { "flac", "audio/ogg" },
{ "pdf", "application/pdf" }, { "pdf", "application/pdf" },
{ "ttf", "application/x-font-ttf" }, { "ttf", "application/x-font-ttf" },
{ "ttc", "application/x-font-ttf" } { "ttc", "application/x-font-ttf" }
}; };
void vHTTPClientDelete( TCPClient_t *pxTCPClient ) void vHTTPClientDelete( TCPClient_t * pxTCPClient )
{ {
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient; HTTPClient_t * pxClient = ( HTTPClient_t * ) pxTCPClient;
/* This HTTP client stops, close / release all resources. */ /* This HTTP client stops, close / release all resources. */
if( pxClient->xSocket != FREERTOS_NO_SOCKET ) if( pxClient->xSocket != FREERTOS_NO_SOCKET )
{ {
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL ); FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_ALL );
FreeRTOS_closesocket( pxClient->xSocket ); FreeRTOS_closesocket( pxClient->xSocket );
pxClient->xSocket = FREERTOS_NO_SOCKET; pxClient->xSocket = FREERTOS_NO_SOCKET;
} }
prvFileClose( pxClient );
} prvFileClose( pxClient );
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvFileClose( HTTPClient_t *pxClient ) static void prvFileClose( HTTPClient_t * pxClient )
{ {
if( pxClient->pxFileHandle != NULL ) if( pxClient->pxFileHandle != NULL )
{ {
FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) ); FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) );
ff_fclose( pxClient->pxFileHandle ); ff_fclose( pxClient->pxFileHandle );
pxClient->pxFileHandle = NULL; pxClient->pxFileHandle = NULL;
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvSendReply( HTTPClient_t *pxClient, BaseType_t xCode ) static BaseType_t prvSendReply( HTTPClient_t * pxClient,
{ BaseType_t xCode )
struct xTCP_SERVER *pxParent = pxClient->pxParent; {
BaseType_t xRc; struct xTCP_SERVER * pxParent = pxClient->pxParent;
BaseType_t xRc;
/* A normal command reply on the main socket (port 21). */ /* A normal command reply on the main socket (port 21). */
char *pcBuffer = pxParent->pcFileBuffer; char * pcBuffer = pxParent->pcFileBuffer;
xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ), xRc = snprintf( pcBuffer, sizeof( pxParent->pcFileBuffer ),
"HTTP/1.1 %d %s\r\n" "HTTP/1.1 %d %s\r\n"
#if USE_HTML_CHUNKS #if USE_HTML_CHUNKS
"Transfer-Encoding: chunked\r\n" "Transfer-Encoding: chunked\r\n"
#endif #endif
"Content-Type: %s\r\n" "Content-Type: %s\r\n"
"Connection: keep-alive\r\n" "Connection: keep-alive\r\n"
"%s\r\n", "%s\r\n",
( int ) xCode, ( int ) xCode,
webCodename (xCode), webCodename( xCode ),
pxParent->pcContentsType[0] ? pxParent->pcContentsType : "text/html", pxParent->pcContentsType[ 0 ] ? pxParent->pcContentsType : "text/html",
pxParent->pcExtraContents ); pxParent->pcExtraContents );
pxParent->pcContentsType[0] = '\0'; pxParent->pcContentsType[ 0 ] = '\0';
pxParent->pcExtraContents[0] = '\0'; pxParent->pcExtraContents[ 0 ] = '\0';
xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 ); xRc = FreeRTOS_send( pxClient->xSocket, ( const void * ) pcBuffer, xRc, 0 );
pxClient->bits.bReplySent = pdTRUE_UNSIGNED; pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
return xRc; return xRc;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvSendFile( HTTPClient_t *pxClient ) static BaseType_t prvSendFile( HTTPClient_t * pxClient )
{ {
size_t uxSpace; size_t uxSpace;
size_t uxCount; size_t uxCount;
BaseType_t xRc = 0; BaseType_t xRc = 0;
if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED ) if( pxClient->bits.bReplySent == pdFALSE_UNSIGNED )
{ {
pxClient->bits.bReplySent = pdTRUE_UNSIGNED; pxClient->bits.bReplySent = pdTRUE_UNSIGNED;
strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) ); strcpy( pxClient->pxParent->pcContentsType, pcGetContentsType( pxClient->pcCurrentFilename ) );
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ), snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
"Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft ); "Content-Length: %d\r\n", ( int ) pxClient->uxBytesLeft );
/* "Requested file action OK". */ /* "Requested file action OK". */
xRc = prvSendReply( pxClient, WEB_REPLY_OK ); xRc = prvSendReply( pxClient, WEB_REPLY_OK );
} }
if( xRc >= 0 ) do if( xRc >= 0 )
{ {
uxSpace = FreeRTOS_tx_space( pxClient->xSocket ); do
{
uxSpace = FreeRTOS_tx_space( pxClient->xSocket );
if( pxClient->uxBytesLeft < uxSpace ) if( pxClient->uxBytesLeft < uxSpace )
{ {
uxCount = pxClient->uxBytesLeft; uxCount = pxClient->uxBytesLeft;
} }
else else
{ {
uxCount = uxSpace; uxCount = uxSpace;
} }
if( uxCount > 0u ) if( uxCount > 0u )
{ {
if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) ) if( uxCount > sizeof( pxClient->pxParent->pcFileBuffer ) )
{ {
uxCount = sizeof( pxClient->pxParent->pcFileBuffer ); uxCount = sizeof( pxClient->pxParent->pcFileBuffer );
} }
ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );
pxClient->uxBytesLeft -= uxCount;
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 ); ff_fread( pxClient->pxParent->pcFileBuffer, 1, uxCount, pxClient->pxFileHandle );
if( xRc < 0 ) pxClient->uxBytesLeft -= uxCount;
{
break;
}
}
} while( uxCount > 0u );
if( pxClient->uxBytesLeft == 0u ) xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pxParent->pcFileBuffer, uxCount, 0 );
{
/* Writing is ready, no need for further 'eSELECT_WRITE' events. */
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
prvFileClose( pxClient );
}
else
{
/* Wake up the TCP task as soon as this socket may be written to. */
FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
}
return xRc; if( xRc < 0 )
} {
break;
}
}
} while( uxCount > 0u );
}
if( pxClient->uxBytesLeft == 0u )
{
/* Writing is ready, no need for further 'eSELECT_WRITE' events. */
FreeRTOS_FD_CLR( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
prvFileClose( pxClient );
}
else
{
/* Wake up the TCP task as soon as this socket may be written to. */
FreeRTOS_FD_SET( pxClient->xSocket, pxClient->pxParent->xSocketSet, eSELECT_WRITE );
}
return xRc;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvOpenURL( HTTPClient_t *pxClient ) static BaseType_t prvOpenURL( HTTPClient_t * pxClient )
{ {
BaseType_t xRc; BaseType_t xRc;
char pcSlash[ 2 ]; char pcSlash[ 2 ];
pxClient->bits.ulFlags = 0; pxClient->bits.ulFlags = 0;
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 ) #if ( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
{ {
if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL ) if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL )
{ {
size_t xResult; size_t xResult;
xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) ); xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) );
if( xResult > 0 )
{
strcpy( pxClient->pxParent->pcContentsType, "text/html" );
snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
"Content-Length: %d\r\n", ( int ) xResult );
xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */
if( xRc > 0 )
{
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );
}
/* Although against the coding standard of FreeRTOS, a return is
done here to simplify this conditional code. */
return xRc;
}
}
}
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
if( pxClient->pcUrlData[ 0 ] != '/' ) if( xResult > 0 )
{ {
/* Insert a slash before the file name. */ strcpy( pxClient->pxParent->pcContentsType, "text/html" );
pcSlash[ 0 ] = '/'; snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ),
pcSlash[ 1 ] = '\0'; "Content-Length: %d\r\n", ( int ) xResult );
} xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */
else
{
/* The browser provided a starting '/' already. */
pcSlash[ 0 ] = '\0';
}
snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",
pxClient->pcRootDir,
pcSlash,
pxClient->pcUrlData);
pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" ); if( xRc > 0 )
{
xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 );
}
FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename, /* Although against the coding standard of FreeRTOS, a return is
pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) ); * done here to simplify this conditional code. */
return xRc;
}
}
}
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
if( pxClient->pxFileHandle == NULL ) if( pxClient->pcUrlData[ 0 ] != '/' )
{ {
/* "404 File not found". */ /* Insert a slash before the file name. */
xRc = prvSendReply( pxClient, WEB_NOT_FOUND ); pcSlash[ 0 ] = '/';
} pcSlash[ 1 ] = '\0';
else }
{ else
pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize; {
xRc = prvSendFile( pxClient ); /* The browser provided a starting '/' already. */
} pcSlash[ 0 ] = '\0';
}
return xRc; snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s",
} pxClient->pcRootDir,
pcSlash,
pxClient->pcUrlData );
pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" );
FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename,
pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) );
if( pxClient->pxFileHandle == NULL )
{
/* "404 File not found". */
xRc = prvSendReply( pxClient, WEB_NOT_FOUND );
}
else
{
pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize;
xRc = prvSendFile( pxClient );
}
return xRc;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvProcessCmd( HTTPClient_t *pxClient, BaseType_t xIndex ) static BaseType_t prvProcessCmd( HTTPClient_t * pxClient,
{ BaseType_t xIndex )
BaseType_t xResult = 0; {
BaseType_t xResult = 0;
/* A new command has been received. Process it. */ /* A new command has been received. Process it. */
switch( xIndex ) switch( xIndex )
{ {
case ECMD_GET: case ECMD_GET:
xResult = prvOpenURL( pxClient ); xResult = prvOpenURL( pxClient );
break; break;
case ECMD_HEAD: case ECMD_HEAD:
case ECMD_POST: case ECMD_POST:
case ECMD_PUT: case ECMD_PUT:
case ECMD_DELETE: case ECMD_DELETE:
case ECMD_TRACE: case ECMD_TRACE:
case ECMD_OPTIONS: case ECMD_OPTIONS:
case ECMD_CONNECT: case ECMD_CONNECT:
case ECMD_PATCH: case ECMD_PATCH:
case ECMD_UNK: case ECMD_UNK:
{ FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n",
FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n", xWebCommands[ xIndex ].pcCommandName ) );
xWebCommands[xIndex].pcCommandName ) ); break;
} }
break;
}
return xResult; return xResult;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xHTTPClientWork( TCPClient_t *pxTCPClient ) BaseType_t xHTTPClientWork( TCPClient_t * pxTCPClient )
{ {
BaseType_t xRc; BaseType_t xRc;
HTTPClient_t *pxClient = ( HTTPClient_t * ) pxTCPClient; HTTPClient_t * pxClient = ( HTTPClient_t * ) pxTCPClient;
if( pxClient->pxFileHandle != NULL ) if( pxClient->pxFileHandle != NULL )
{ {
prvSendFile( pxClient ); prvSendFile( pxClient );
} }
xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 ); xRc = FreeRTOS_recv( pxClient->xSocket, ( void * ) pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 );
if( xRc > 0 ) if( xRc > 0 )
{ {
BaseType_t xIndex; BaseType_t xIndex;
const char *pcEndOfCmd; const char * pcEndOfCmd;
const struct xWEB_COMMAND *curCmd; const struct xWEB_COMMAND * curCmd;
char *pcBuffer = pcCOMMAND_BUFFER; char * pcBuffer = pcCOMMAND_BUFFER;
if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) ) if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) )
{ {
pcBuffer[ xRc ] = '\0'; pcBuffer[ xRc ] = '\0';
} }
while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )
{
pcBuffer[ --xRc ] = '\0';
}
pcEndOfCmd = pcBuffer + xRc;
curCmd = xWebCommands; while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) )
{
pcBuffer[ --xRc ] = '\0';
}
/* Pointing to "/index.html HTTP/1.1". */ pcEndOfCmd = pcBuffer + xRc;
pxClient->pcUrlData = pcBuffer;
/* Pointing to "HTTP/1.1". */ curCmd = xWebCommands;
pxClient->pcRestData = pcEmptyString;
/* Last entry is "ECMD_UNK". */ /* Pointing to "/index.html HTTP/1.1". */
for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ ) pxClient->pcUrlData = pcBuffer;
{
BaseType_t xLength;
xLength = curCmd->xCommandLength; /* Pointing to "HTTP/1.1". */
if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) ) pxClient->pcRestData = pcEmptyString;
{
char *pcLastPtr;
pxClient->pcUrlData += xLength + 1; /* Last entry is "ECMD_UNK". */
for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ ) for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ )
{ {
char ch = *pcLastPtr; BaseType_t xLength;
if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )
{
*pcLastPtr = '\0';
pxClient->pcRestData = pcLastPtr + 1;
break;
}
}
break;
}
}
if( xIndex < ( WEB_CMD_COUNT - 1 ) ) xLength = curCmd->xCommandLength;
{
xRc = prvProcessCmd( pxClient, xIndex ); if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) )
} {
} char * pcLastPtr;
else if( xRc < 0 )
{ pxClient->pcUrlData += xLength + 1;
/* The connection will be closed and the client will be deleted. */
FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) ); for( pcLastPtr = ( char * ) pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ )
} {
return xRc; char ch = *pcLastPtr;
}
if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) )
{
*pcLastPtr = '\0';
pxClient->pcRestData = pcLastPtr + 1;
break;
}
}
break;
}
}
if( xIndex < ( WEB_CMD_COUNT - 1 ) )
{
xRc = prvProcessCmd( pxClient, xIndex );
}
}
else if( xRc < 0 )
{
/* The connection will be closed and the client will be deleted. */
FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) );
}
return xRc;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static const char *pcGetContentsType (const char *apFname) static const char * pcGetContentsType( const char * apFname )
{ {
const char *slash = NULL; const char * slash = NULL;
const char *dot = NULL; const char * dot = NULL;
const char *ptr; const char * ptr;
const char *pcResult = "text/html"; const char * pcResult = "text/html";
BaseType_t x; BaseType_t x;
for( ptr = apFname; *ptr; ptr++ ) for( ptr = apFname; *ptr; ptr++ )
{ {
if (*ptr == '.') dot = ptr; if( *ptr == '.' )
if (*ptr == '/') slash = ptr; {
} dot = ptr;
if( dot > slash ) }
{
dot++; if( *ptr == '/' )
for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ ) {
{ slash = ptr;
if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 ) }
{ }
pcResult = pxTypeCouples[ x ].pcType;
break; if( dot > slash )
} {
} dot++;
}
return pcResult; for( x = 0; x < ARRAY_SIZE( pxTypeCouples ); x++ )
} {
if( strcasecmp( dot, pxTypeCouples[ x ].pcExtension ) == 0 )
{
pcResult = pxTypeCouples[ x ].pcType;
break;
}
}
}
return pcResult;
}
#endif /* ipconfigUSE_HTTP */ #endif /* ipconfigUSE_HTTP */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -62,28 +62,30 @@
#include "date_and_time.h" #include "date_and_time.h"
enum EStatus { enum EStatus
EStatusLookup, {
EStatusAsking, EStatusLookup,
EStatusPause, EStatusAsking,
EStatusFailed, EStatusPause,
EStatusFailed,
}; };
static struct SNtpPacket xNTPPacket; static struct SNtpPacket xNTPPacket;
#if( ipconfigUSE_CALLBACKS == 0 ) #if ( ipconfigUSE_CALLBACKS == 0 )
static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ]; static char cRecvBuffer[ sizeof( struct SNtpPacket ) + 64 ];
#endif #endif
static enum EStatus xStatus = EStatusLookup; static enum EStatus xStatus = EStatusLookup;
static const char *pcTimeServers[] = { static const char * pcTimeServers[] =
"0.asia.pool.ntp.org", {
"0.europe.pool.ntp.org", "0.asia.pool.ntp.org",
"0.id.pool.ntp.org", "0.europe.pool.ntp.org",
"0.south-america.pool.ntp.org", "0.id.pool.ntp.org",
"0.oceania.pool.ntp.org", "0.south-america.pool.ntp.org",
"0.north-america.pool.ntp.org" "0.oceania.pool.ntp.org",
"0.north-america.pool.ntp.org"
}; };
static SemaphoreHandle_t xNTPWakeupSem = NULL; static SemaphoreHandle_t xNTPWakeupSem = NULL;
@ -92,378 +94,405 @@ static Socket_t xUDPSocket = NULL;
static TaskHandle_t xNTPTaskhandle = NULL; static TaskHandle_t xNTPTaskhandle = NULL;
static TickType_t uxSendTime; static TickType_t uxSendTime;
static void prvNTPTask( void *pvParameters ); static void prvNTPTask( void * pvParameters );
static void vSignalTask( void ) static void vSignalTask( void )
{ {
#if( ipconfigUSE_CALLBACKS == 0 ) #if ( ipconfigUSE_CALLBACKS == 0 )
if( xUDPSocket != NULL ) if( xUDPSocket != NULL )
{ {
/* Send a signal to the socket so that the /* Send a signal to the socket so that the
FreeRTOS_recvfrom will get interrupted. */ * FreeRTOS_recvfrom will get interrupted. */
FreeRTOS_SignalSocket( xUDPSocket ); FreeRTOS_SignalSocket( xUDPSocket );
} }
else else
#endif #endif
if( xNTPWakeupSem != NULL )
{ if( xNTPWakeupSem != NULL )
xSemaphoreGive( xNTPWakeupSem ); {
} xSemaphoreGive( xNTPWakeupSem );
}
} }
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority ) void vStartNTPTask( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority )
{ {
/* The only public function in this module: start a task to contact /* The only public function in this module: start a task to contact
some NTP server. */ * some NTP server. */
if( xNTPTaskhandle != NULL ) if( xNTPTaskhandle != NULL )
{ {
switch( xStatus ) switch( xStatus )
{ {
case EStatusPause: case EStatusPause:
xStatus = EStatusAsking; xStatus = EStatusAsking;
vSignalTask(); vSignalTask();
break; break;
case EStatusLookup:
FreeRTOS_printf( ( "NTP looking up server\n" ) );
break;
case EStatusAsking:
FreeRTOS_printf( ( "NTP still asking\n" ) );
break;
case EStatusFailed:
FreeRTOS_printf( ( "NTP failed somehow\n" ) );
ulIPAddressFound = 0ul;
xStatus = EStatusLookup;
vSignalTask();
break;
}
}
else
{
xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
if( xUDPSocket != FREERTOS_INVALID_SOCKET )
{
struct freertos_sockaddr xAddress;
#if( ipconfigUSE_CALLBACKS != 0 )
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
#else
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
#endif
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) case EStatusLookup:
{ FreeRTOS_printf( ( "NTP looking up server\n" ) );
xAddress.sin_address.ulIP_IPv4 = 0ul; break;
}
#else
{
xAddress.sin_addr = 0ul;
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); case EStatusAsking:
xAddress.sin_family = FREERTOS_AF_INET; FreeRTOS_printf( ( "NTP still asking\n" ) );
break;
FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) ); case EStatusFailed:
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_printf( ( "NTP failed somehow\n" ) );
xTaskCreate( prvNTPTask, /* The function that implements the task. */ ulIPAddressFound = 0ul;
( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */ xStatus = EStatusLookup;
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ vSignalTask();
NULL, /* The task parameter, not used in this case. */ break;
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ }
&xNTPTaskhandle ); /* The task handle. */ }
} else
else {
{ xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
FreeRTOS_printf( ( "Creating socket failed\n" ) );
} if( xUDPSocket != FREERTOS_INVALID_SOCKET )
} {
struct freertos_sockaddr xAddress;
#if ( ipconfigUSE_CALLBACKS != 0 )
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 );
#else
BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 );
#endif
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{
xAddress.sin_address.ulIP_IPv4 = 0ul;
}
#else
{
xAddress.sin_addr = 0ul;
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
xAddress.sin_family = FREERTOS_AF_INET;
FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) );
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
xTaskCreate( prvNTPTask, /* The function that implements the task. */
( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
NULL, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
&xNTPTaskhandle ); /* The task handle. */
}
else
{
FreeRTOS_printf( ( "Creating socket failed\n" ) );
}
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress ) static void vDNS_callback( const char * pcName,
void * pvSearchID,
uint32_t ulIPAddress )
{ {
char pcBuf[16]; char pcBuf[ 16 ];
/* The DNS lookup has a result, or it has reached the time-out. */ /* The DNS lookup has a result, or it has reached the time-out. */
FreeRTOS_inet_ntoa( ulIPAddress, pcBuf ); FreeRTOS_inet_ntoa( ulIPAddress, pcBuf );
FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) ); FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) );
if( ulIPAddressFound == 0ul )
{ if( ulIPAddressFound == 0ul )
ulIPAddressFound = ulIPAddress; {
} ulIPAddressFound = ulIPAddress;
/* For testing: in case DNS doen't respond, still try some NTP server }
with a known IP-address. */
if( ulIPAddressFound == 0ul ) /* For testing: in case DNS doesn't respond, still try some NTP server
{ * with a known IP-address. */
ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 ); if( ulIPAddressFound == 0ul )
{
ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 );
/* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */ /* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */
} }
xStatus = EStatusAsking;
vSignalTask(); xStatus = EStatusAsking;
vSignalTask();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSwapFields( struct SNtpPacket *pxPacket) static void prvSwapFields( struct SNtpPacket * pxPacket )
{ {
/* NTP messages are big-endian */ /* NTP messages are big-endian */
pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay ); pxPacket->rootDelay = FreeRTOS_htonl( pxPacket->rootDelay );
pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion ); pxPacket->rootDispersion = FreeRTOS_htonl( pxPacket->rootDispersion );
pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds ); pxPacket->referenceTimestamp.seconds = FreeRTOS_htonl( pxPacket->referenceTimestamp.seconds );
pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction ); pxPacket->referenceTimestamp.fraction = FreeRTOS_htonl( pxPacket->referenceTimestamp.fraction );
pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds ); pxPacket->originateTimestamp.seconds = FreeRTOS_htonl( pxPacket->originateTimestamp.seconds );
pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction ); pxPacket->originateTimestamp.fraction = FreeRTOS_htonl( pxPacket->originateTimestamp.fraction );
pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds ); pxPacket->receiveTimestamp.seconds = FreeRTOS_htonl( pxPacket->receiveTimestamp.seconds );
pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction ); pxPacket->receiveTimestamp.fraction = FreeRTOS_htonl( pxPacket->receiveTimestamp.fraction );
pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds ); pxPacket->transmitTimestamp.seconds = FreeRTOS_htonl( pxPacket->transmitTimestamp.seconds );
pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction ); pxPacket->transmitTimestamp.fraction = FreeRTOS_htonl( pxPacket->transmitTimestamp.fraction );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvNTPPacketInit( ) static void prvNTPPacketInit()
{ {
memset (&xNTPPacket, '\0', sizeof( xNTPPacket ) ); memset( &xNTPPacket, '\0', sizeof( xNTPPacket ) );
xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */ xNTPPacket.flags = 0xDB; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */ xNTPPacket.poll = 10; /* 10 means 1 << 10 = 1024 seconds */
xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */ xNTPPacket.precision = 0xFA; /* = 250 = 0.015625 seconds */
xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */ xNTPPacket.rootDelay = 0x5D2E; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */ xNTPPacket.rootDispersion = 0x0008CAC8; /* 0x0008CAC8 = 8.7912 seconds */
/* use the recorded NTP time */ /* use the recorded NTP time */
time_t uxSecs = FreeRTOS_time( NULL );/* apTime may be NULL, returns seconds */ time_t uxSecs = FreeRTOS_time( NULL ); /* apTime may be NULL, returns seconds */
xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */ xNTPPacket.referenceTimestamp.seconds = uxSecs; /* Current time */
xNTPPacket.transmitTimestamp.seconds = uxSecs + 3; xNTPPacket.transmitTimestamp.seconds = uxSecs + 3;
/* Transform the contents of the fields from native to big endian. */ /* Transform the contents of the fields from native to big endian. */
prvSwapFields( &xNTPPacket ); prvSwapFields( &xNTPPacket );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvReadTime( struct SNtpPacket * pxPacket ) static void prvReadTime( struct SNtpPacket * pxPacket )
{ {
FF_TimeStruct_t xTimeStruct; FF_TimeStruct_t xTimeStruct;
time_t uxPreviousSeconds; time_t uxPreviousSeconds;
time_t uxPreviousMS; time_t uxPreviousMS;
time_t uxCurrentSeconds; time_t uxCurrentSeconds;
time_t uxCurrentMS; time_t uxCurrentMS;
const char *pcTimeUnit; const char * pcTimeUnit;
int32_t ilDiff; int32_t ilDiff;
TickType_t uxTravelTime; TickType_t uxTravelTime;
uxTravelTime = xTaskGetTickCount() - uxSendTime; uxTravelTime = xTaskGetTickCount() - uxSendTime;
/* Transform the contents of the fields from big to native endian. */ /* Transform the contents of the fields from big to native endian. */
prvSwapFields( pxPacket ); prvSwapFields( pxPacket );
uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970; uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970;
uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967; uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967;
uxCurrentSeconds += uxCurrentMS / 1000; uxCurrentSeconds += uxCurrentMS / 1000;
uxCurrentMS = uxCurrentMS % 1000; uxCurrentMS = uxCurrentMS % 1000;
// Get the last time recorded /* Get the last time recorded */
uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS ); uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS );
// Set the new time with precision in msec. */ /* Set the new time with precision in msec. * / */
FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS ); FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS );
if( uxCurrentSeconds >= uxPreviousSeconds ) if( uxCurrentSeconds >= uxPreviousSeconds )
{ {
ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds ); ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds );
} }
else else
{ {
ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds ); ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds );
} }
if( ( ilDiff < -5 ) || ( ilDiff > 5 ) ) if( ( ilDiff < -5 ) || ( ilDiff > 5 ) )
{ {
/* More than 5 seconds difference. */ /* More than 5 seconds difference. */
pcTimeUnit = "sec"; pcTimeUnit = "sec";
} }
else else
{ {
/* Less than or equal to 5 second difference. */ /* Less than or equal to 5 second difference. */
pcTimeUnit = "ms"; pcTimeUnit = "ms";
uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds; uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds;
int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS; int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS;
int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS; int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS;
ilDiff = iCurMS - iPrevMS; ilDiff = iCurMS - iPrevMS;
} }
uxCurrentSeconds -= iTimeZone;
FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct ); uxCurrentSeconds -= iTimeZone;
/* FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct );
378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
*/
FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n", /*
xTimeStruct.tm_mday, * 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms)
xTimeStruct.tm_mon + 1, * 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms)
xTimeStruct.tm_year + 1900, */
xTimeStruct.tm_hour,
xTimeStruct.tm_min,
xTimeStruct.tm_sec,
( unsigned )uxCurrentMS,
( unsigned )ilDiff,
pcTimeUnit,
uxTravelTime ) );
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */ FreeRTOS_printf( ( "NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n",
( void ) pcTimeUnit; xTimeStruct.tm_mday,
( void ) uxTravelTime; xTimeStruct.tm_mon + 1,
xTimeStruct.tm_year + 1900,
xTimeStruct.tm_hour,
xTimeStruct.tm_min,
xTimeStruct.tm_sec,
( unsigned ) uxCurrentMS,
( unsigned ) ilDiff,
pcTimeUnit,
uxTravelTime ) );
/* Remove compiler warnings in case FreeRTOS_printf() is not used. */
( void ) pcTimeUnit;
( void ) uxTravelTime;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ipconfigUSE_CALLBACKS != 0 ) #if ( ipconfigUSE_CALLBACKS != 0 )
static BaseType_t xOnUDPReceive( Socket_t xSocket, void * pvData, size_t xLength, static BaseType_t xOnUDPReceive( Socket_t xSocket,
const struct freertos_sockaddr *pxFrom, const struct freertos_sockaddr *pxDest ) void * pvData,
{ size_t xLength,
if( xLength >= sizeof( xNTPPacket ) ) const struct freertos_sockaddr * pxFrom,
{ const struct freertos_sockaddr * pxDest )
prvReadTime( ( struct SNtpPacket *)pvData ); {
if( xStatus != EStatusPause ) if( xLength >= sizeof( xNTPPacket ) )
{ {
xStatus = EStatusPause; prvReadTime( ( struct SNtpPacket * ) pvData );
}
}
vSignalTask();
/* Tell the driver not to store the RX data */
return 1;
}
/*-----------------------------------------------------------*/
#endif /* ipconfigUSE_CALLBACKS != 0 */ if( xStatus != EStatusPause )
{
xStatus = EStatusPause;
}
}
vSignalTask();
/* Tell the driver not to store the RX data */
return 1;
}
/*-----------------------------------------------------------*/
static void prvNTPTask( void *pvParameters )
{
BaseType_t xServerIndex = 3;
struct freertos_sockaddr xAddress;
#if( ipconfigUSE_CALLBACKS != 0 )
F_TCP_UDP_Handler_t xHandler;
#endif /* ipconfigUSE_CALLBACKS != 0 */ #endif /* ipconfigUSE_CALLBACKS != 0 */
xStatus = EStatusLookup; static void prvNTPTask( void * pvParameters )
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 ) {
{ BaseType_t xServerIndex = 3;
xNTPWakeupSem = xSemaphoreCreateBinary(); struct freertos_sockaddr xAddress;
}
#endif
#if( ipconfigUSE_CALLBACKS != 0 ) #if ( ipconfigUSE_CALLBACKS != 0 )
{ F_TCP_UDP_Handler_t xHandler;
memset( &xHandler, '\0', sizeof( xHandler ) ); #endif /* ipconfigUSE_CALLBACKS != 0 */
xHandler.pxOnUDPReceive = xOnUDPReceive;
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
}
#endif
#if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
{
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
}
#endif
for( ; ; )
{
switch( xStatus )
{
case EStatusLookup:
if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )
{
if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
{
xServerIndex = 0;
}
FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );
FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 );
}
else
{
xStatus = EStatusAsking;
}
break;
case EStatusAsking: xStatus = EStatusLookup;
{ #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 )
char pcBuf[16]; {
xNTPWakeupSem = xSemaphoreCreateBinary();
}
#endif
prvNTPPacketInit( ); #if ( ipconfigUSE_CALLBACKS != 0 )
{
memset( &xHandler, '\0', sizeof( xHandler ) );
xHandler.pxOnUDPReceive = xOnUDPReceive;
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) );
}
#endif
#if ( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 )
{
FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) );
}
#endif
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) for( ; ; )
{ {
xAddress.sin_address.ulIP_IPv4 = ulIPAddressFound; switch( xStatus )
xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); {
FreeRTOS_inet_ntoa( xAddress.sin_address.ulIP_IPv4, pcBuf ); case EStatusLookup:
}
#else
{
xAddress.sin_addr = ulIPAddressFound;
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xAddress.sin_family = FREERTOS_AF_INET; if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) )
{
if( ++xServerIndex == sizeof( pcTimeServers ) / sizeof( pcTimeServers[ 0 ] ) )
{
xServerIndex = 0;
}
FreeRTOS_printf( ( "Sending UDP message to %s:%u\n", FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) );
pcBuf, FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, ( void * ) NULL, 1200 );
FreeRTOS_ntohs( xAddress.sin_port ) ) ); }
else
{
xStatus = EStatusAsking;
}
uxSendTime = xTaskGetTickCount( ); break;
FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );
}
break;
case EStatusPause: case EStatusAsking:
break; {
char pcBuf[ 16 ];
case EStatusFailed: prvNTPPacketInit();
break;
}
#if( ipconfigUSE_CALLBACKS != 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{ {
xSemaphoreTake( xNTPWakeupSem, 5000 ); xAddress.sin_address.ulIP_IPv4 = ulIPAddressFound;
} xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
#else FreeRTOS_inet_ntoa( xAddress.sin_address.ulIP_IPv4, pcBuf );
{ }
uint32_t xAddressSize; #else
BaseType_t xReturned; {
xAddress.sin_addr = ulIPAddressFound;
xAddress.sin_port = FreeRTOS_htons( NTP_PORT );
FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf );
}
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xAddressSize = sizeof( xAddress ); xAddress.sin_family = FREERTOS_AF_INET;
xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
switch( xReturned ) FreeRTOS_printf( ( "Sending UDP message to %s:%u\n",
{ pcBuf,
case 0: FreeRTOS_ntohs( xAddress.sin_port ) ) );
case -pdFREERTOS_ERRNO_EAGAIN:
case -pdFREERTOS_ERRNO_EINTR: uxSendTime = xTaskGetTickCount();
break; FreeRTOS_sendto( xUDPSocket, ( void * ) &xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) );
default: }
if( xReturned < sizeof( xNTPPacket ) ) break;
{
FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) ); case EStatusPause:
} break;
else
{ case EStatusFailed:
prvReadTime( ( struct SNtpPacket *)cRecvBuffer ); break;
if( xStatus != EStatusPause ) }
{
xStatus = EStatusPause; #if ( ipconfigUSE_CALLBACKS != 0 )
} {
} xSemaphoreTake( xNTPWakeupSem, 5000 );
break; }
} #else
} {
#endif uint32_t xAddressSize;
} BaseType_t xReturned;
xAddressSize = sizeof( xAddress );
xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize );
switch( xReturned )
{
case 0:
case -pdFREERTOS_ERRNO_EAGAIN:
case -pdFREERTOS_ERRNO_EINTR:
break;
default:
if( xReturned < sizeof( xNTPPacket ) )
{
FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) );
}
else
{
prvReadTime( ( struct SNtpPacket * ) cRecvBuffer );
if( xStatus != EStatusPause )
{
xStatus = EStatusPause;
}
}
break;
}
}
#endif /* if ( ipconfigUSE_CALLBACKS != 0 ) */
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS+TCP V2.0.1 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -19,115 +19,118 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
#ifndef __FTPCMD_H__ #ifndef __FTPCMD_H__
#define __FTPCMD_H__ #define __FTPCMD_H__
#define REPL_110 "110 Restart marker reply.\r\n" #define REPL_110 "110 Restart marker reply.\r\n"
#define REPL_120 "120 Try again in 2 minutes.\r\n" #define REPL_120 "120 Try again in 2 minutes.\r\n"
#define REPL_125 "125 Data connection already open; transfer starting.\r\n" #define REPL_125 "125 Data connection already open; transfer starting.\r\n"
#define REPL_150 "150 File status okay; about to open data connection.\r\n" #define REPL_150 "150 File status okay; about to open data connection.\r\n"
#define REPL_200 "200 NOOP command successful.\r\n" #define REPL_200 "200 NOOP command successful.\r\n"
#define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n" #define REPL_200_PROGRESS "200 NOOP: data transfer in progress.\r\n"
#define REPL_202 "202 Command not implemented, superfluous at this site.\r\n" #define REPL_202 "202 Command not implemented, superfluous at this site.\r\n"
#define REPL_211 "221 System status, or system help reply.\r\n" #define REPL_211 "221 System status, or system help reply.\r\n"
#define REPL_211_STATUS "221-status of %s.\r\n" #define REPL_211_STATUS "221-status of %s.\r\n"
#define REPL_211_END "221 End of status.\r\n" #define REPL_211_END "221 End of status.\r\n"
#define REPL_212 "212 Directory status.\r\n" #define REPL_212 "212 Directory status.\r\n"
#define REPL_213 "213 File status.\r\n" #define REPL_213 "213 File status.\r\n"
#define REPL_214 "214 Help message.\r\n" #define REPL_214 "214 Help message.\r\n"
#define REPL_214_END "214 End Help message.\r\n" #define REPL_214_END "214 End Help message.\r\n"
#define REPL_215 "215 %s system type.\r\n" #define REPL_215 "215 %s system type.\r\n"
#define REPL_220 "220 Service ready for new user.\r\n" #define REPL_220 "220 Service ready for new user.\r\n"
#define REPL_221 "221 Service closing control connection.\r\n" #define REPL_221 "221 Service closing control connection.\r\n"
#define REPL_225 "225 Data connection open; no transfer in progress.\r\n" #define REPL_225 "225 Data connection open; no transfer in progress.\r\n"
#define REPL_226 "226 Closing data connection.\r\n" #define REPL_226 "226 Closing data connection.\r\n"
#define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n" #define REPL_227 "227 Entering Passive Mode (%s,%s,%s,%s,%s,%s).\r\n"
#define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n" #define REPL_227_D "227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n"
#define REPL_230 "230 User logged in, proceed.\r\n" #define REPL_230 "230 User logged in, proceed.\r\n"
#define REPL_250 "250 Requested file action okay, completed.\r\n" #define REPL_250 "250 Requested file action okay, completed.\r\n"
#define REPL_257 "257 %s created.\r\n" #define REPL_257 "257 %s created.\r\n"
// #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n" /* #define REPL_257_PWD "257 \"%s\" is current working dir.\r\n" */
#define REPL_257_PWD "257 \"%s\"\r\n" #define REPL_257_PWD "257 \"%s\"\r\n"
#define REPL_331 "331 Only anonymous user is accepted.\r\n" #define REPL_331 "331 Only anonymous user is accepted.\r\n"
#define REPL_331_ANON "331 Anonymous login okay\r\n" #define REPL_331_ANON "331 Anonymous login okay\r\n"
#define REPL_332 "332 Need account for login.\r\n" #define REPL_332 "332 Need account for login.\r\n"
#define REPL_350 "350 Requested file action pending further information.\r\n" #define REPL_350 "350 Requested file action pending further information.\r\n"
#define REPL_421 "421 Service not available, closing control connection.\r\n" #define REPL_421 "421 Service not available, closing control connection.\r\n"
#define REPL_425 "425 Can't open data connection.\r\n" #define REPL_425 "425 Can't open data connection.\r\n"
#define REPL_426 "426 Connection closed; transfer aborted.\r\n" #define REPL_426 "426 Connection closed; transfer aborted.\r\n"
#define REPL_450 "450 Requested file action not taken.\r\n" #define REPL_450 "450 Requested file action not taken.\r\n"
#define REPL_451 "451 Requested action aborted. Local error in processing.\r\n" #define REPL_451 "451 Requested action aborted. Local error in processing.\r\n"
#define REPL_452 "452 Requested action not taken.\r\n" #define REPL_452 "452 Requested action not taken.\r\n"
#define REPL_500 "500 Syntax error, command unrecognized.\r\n" #define REPL_500 "500 Syntax error, command unrecognized.\r\n"
#define REPL_501 "501 Syntax error in parameters or arguments.\r\n" #define REPL_501 "501 Syntax error in parameters or arguments.\r\n"
#define REPL_502 "502 Command not implemented.\r\n" #define REPL_502 "502 Command not implemented.\r\n"
#define REPL_503 "503 Bad sequence of commands.\r\n" #define REPL_503 "503 Bad sequence of commands.\r\n"
#define REPL_504 "504 Command not implemented for that parameter.\r\n" #define REPL_504 "504 Command not implemented for that parameter.\r\n"
#define REPL_530 "530 Not logged in.\r\n" #define REPL_530 "530 Not logged in.\r\n"
#define REPL_532 "532 Need account for storing files.\r\n" #define REPL_532 "532 Need account for storing files.\r\n"
#define REPL_550 "550 Requested action not taken.\r\n" #define REPL_550 "550 Requested action not taken.\r\n"
#define REPL_551 "551 Requested action aborted. Page type unknown.\r\n" #define REPL_551 "551 Requested action aborted. Page type unknown.\r\n"
#define REPL_552 "552 Requested file action aborted.\r\n" #define REPL_552 "552 Requested file action aborted.\r\n"
#define REPL_553 "553 Requested action not taken.\r\n" #define REPL_553 "553 Requested action not taken.\r\n"
#define REPL_553_READ_ONLY "553 Read-only file-system.\r\n" #define REPL_553_READ_ONLY "553 Read-only file-system.\r\n"
enum EFTPCommand { enum EFTPCommand
ECMD_USER, {
ECMD_PASS, ECMD_USER,
ECMD_ACCT, ECMD_PASS,
ECMD_CWD, ECMD_ACCT,
ECMD_CDUP, ECMD_CWD,
ECMD_SMNT, ECMD_CDUP,
ECMD_QUIT, ECMD_SMNT,
ECMD_REIN, ECMD_QUIT,
ECMD_PORT, ECMD_REIN,
ECMD_PASV, ECMD_PORT,
ECMD_TYPE, ECMD_PASV,
ECMD_STRU, ECMD_TYPE,
ECMD_MODE, ECMD_STRU,
ECMD_RETR, ECMD_MODE,
ECMD_STOR, ECMD_RETR,
ECMD_STOU, ECMD_STOR,
ECMD_APPE, ECMD_STOU,
ECMD_ALLO, ECMD_APPE,
ECMD_REST, ECMD_ALLO,
ECMD_RNFR, ECMD_REST,
ECMD_RNTO, ECMD_RNFR,
ECMD_ABOR, ECMD_RNTO,
ECMD_SIZE, ECMD_ABOR,
ECMD_MDTM, ECMD_SIZE,
ECMD_DELE, ECMD_MDTM,
ECMD_RMD, ECMD_DELE,
ECMD_MKD, ECMD_RMD,
ECMD_PWD, ECMD_MKD,
ECMD_LIST, ECMD_PWD,
ECMD_NLST, ECMD_LIST,
ECMD_SITE, ECMD_NLST,
ECMD_SYST, ECMD_SITE,
ECMD_FEAT, ECMD_SYST,
ECMD_STAT, ECMD_FEAT,
ECMD_HELP, ECMD_STAT,
ECMD_NOOP, ECMD_HELP,
ECMD_EMPTY, ECMD_NOOP,
ECMD_CLOSE, ECMD_EMPTY,
ECMD_UNKNOWN, ECMD_CLOSE,
ECMD_UNKNOWN,
}; };
typedef struct xFTP_COMMAND { typedef struct xFTP_COMMAND
BaseType_t xCommandLength; {
const char pcCommandName[7]; BaseType_t xCommandLength;
const unsigned char ucCommandType; const char pcCommandName[ 7 ];
const unsigned char checkLogin; const unsigned char ucCommandType;
const unsigned char checkNullArg; const unsigned char checkLogin;
const unsigned char checkNullArg;
} FTPCommand_t; } FTPCommand_t;
#define FTP_CMD_COUNT (ECMD_UNKNOWN+1) #define FTP_CMD_COUNT ( ECMD_UNKNOWN + 1 )
extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ]; extern const FTPCommand_t xFTPCommands[ FTP_CMD_COUNT ];
#endif // __FTPCMD_H__ #endif // __FTPCMD_H__

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS+TCP V2.0.3 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -19,49 +19,50 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
#ifndef FREERTOS_HTTP_COMMANDS_H #ifndef FREERTOS_HTTP_COMMANDS_H
#define FREERTOS_HTTP_COMMANDS_H #define FREERTOS_HTTP_COMMANDS_H
enum { enum
WEB_REPLY_OK = 200, {
WEB_NO_CONTENT = 204, WEB_REPLY_OK = 200,
WEB_BAD_REQUEST = 400, WEB_NO_CONTENT = 204,
WEB_UNAUTHORIZED = 401, WEB_BAD_REQUEST = 400,
WEB_NOT_FOUND = 404, WEB_UNAUTHORIZED = 401,
WEB_GONE = 410, WEB_NOT_FOUND = 404,
WEB_PRECONDITION_FAILED = 412, WEB_GONE = 410,
WEB_INTERNAL_SERVER_ERROR = 500, WEB_PRECONDITION_FAILED = 412,
WEB_INTERNAL_SERVER_ERROR = 500,
}; };
enum EWebCommand { enum EWebCommand
ECMD_GET, {
ECMD_HEAD, ECMD_GET,
ECMD_POST, ECMD_HEAD,
ECMD_PUT, ECMD_POST,
ECMD_DELETE, ECMD_PUT,
ECMD_TRACE, ECMD_DELETE,
ECMD_OPTIONS, ECMD_TRACE,
ECMD_CONNECT, ECMD_OPTIONS,
ECMD_PATCH, ECMD_CONNECT,
ECMD_UNK, ECMD_PATCH,
ECMD_UNK,
}; };
struct xWEB_COMMAND struct xWEB_COMMAND
{ {
BaseType_t xCommandLength; BaseType_t xCommandLength;
const char *pcCommandName; const char * pcCommandName;
const unsigned char ucCommandType; const unsigned char ucCommandType;
}; };
#define WEB_CMD_COUNT (ECMD_UNK+1) #define WEB_CMD_COUNT ( ECMD_UNK + 1 )
extern const struct xWEB_COMMAND xWebCommands[WEB_CMD_COUNT]; extern const struct xWEB_COMMAND xWebCommands[ WEB_CMD_COUNT ];
extern const char *webCodename (int aCode);
#endif /* FREERTOS_HTTP_COMMANDS_H */
extern const char * webCodename( int aCode );
#endif /* FREERTOS_HTTP_COMMANDS_H */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS+TCP V2.0.3 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -19,107 +19,123 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
/* /*
Some code which is common to TCP servers like HTTP en FTP * Some code which is common to TCP servers like HTTP en FTP
*/ */
#ifndef FREERTOS_TCP_SERVER_H #ifndef FREERTOS_TCP_SERVER_H
#define FREERTOS_TCP_SERVER_H #define FREERTOS_TCP_SERVER_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef FTP_SERVER_USES_RELATIVE_DIRECTORY #ifndef FTP_SERVER_USES_RELATIVE_DIRECTORY
#define FTP_SERVER_USES_RELATIVE_DIRECTORY 0 #define FTP_SERVER_USES_RELATIVE_DIRECTORY 0
#endif #endif
enum eSERVER_TYPE enum eSERVER_TYPE
{ {
eSERVER_NONE, eSERVER_NONE,
eSERVER_HTTP, eSERVER_HTTP,
eSERVER_FTP, eSERVER_FTP,
}; };
struct xFTP_CLIENT; struct xFTP_CLIENT;
#if( ipconfigFTP_HAS_RECEIVED_HOOK != 0 ) #if ( ipconfigFTP_HAS_RECEIVED_HOOK != 0 )
extern void vApplicationFTPReceivedHook( const char *pcFileName, uint32_t ulSize, struct xFTP_CLIENT *pxFTPClient ); extern void vApplicationFTPReceivedHook( const char * pcFileName,
extern void vFTPReplyMessage( struct xFTP_CLIENT *pxFTPClient, const char *pcMessage ); uint32_t ulSize,
#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */ struct xFTP_CLIENT * pxFTPClient );
extern void vFTPReplyMessage( struct xFTP_CLIENT * pxFTPClient,
const char * pcMessage );
#endif /* ipconfigFTP_HAS_RECEIVED_HOOK != 0 */
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 ) #if ( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
/*
* Function is called when a user name has been submitted.
* The function may return a string such as: "331 Please enter your password"
* or return NULL to use the default reply.
*/
extern const char *pcApplicationFTPUserHook( const char *pcUserName );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 ) /*
/* * Function is called when a user name has been submitted.
* Function is called when a password was received. * The function may return a string such as: "331 Please enter your password"
* Return positive value to allow the user * or return NULL to use the default reply.
*/ */
extern BaseType_t xApplicationFTPPasswordHook( const char *pcUserName, const char *pcPassword ); extern const char * pcApplicationFTPUserHook( const char * pcUserName );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */ #endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 ) #if ( ipconfigFTP_HAS_USER_PASSWORD_HOOK != 0 )
/*
* The FTP server is asking for user-specific properties
*/
typedef struct
{
uint16_t usPortNumber; /* For reference only. Host-endian. */
const char *pcRootDir;
BaseType_t xReadOnly;
}
FTPUserProperties_t;
extern void vApplicationFTPUserPropertiesHook( const char *pcUserName, FTPUserProperties_t *pxProperties );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
#if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 ) /*
/* * Function is called when a password was received.
* A GET request is received containing a special character, * Return positive value to allow the user
* usually a question mark. */
* const char *pcURLData; // A request, e.g. "/request?limit=75" extern BaseType_t xApplicationFTPPasswordHook( const char * pcUserName,
* char *pcBuffer; // Here the answer can be written const char * pcPassword );
* size_t uxBufferLength; // Size of the buffer #endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
*
*/
extern size_t uxApplicationHTTPHandleRequestHook( const char *pcURLData, char *pcBuffer, size_t uxBufferLength );
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
struct xSERVER_CONFIG #if ( ipconfigFTP_HAS_USER_PROPERTIES_HOOK != 0 )
{
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
BaseType_t xPortNumber; /* e.g. 80, 8080, 21 */
BaseType_t xBackLog; /* e.g. 10, maximum number of connected TCP clients */
const char * const pcRootDir; /* Treat this directory as the root directory */
};
struct xTCP_SERVER; /*
typedef struct xTCP_SERVER TCPServer_t; * The FTP server is asking for user-specific properties
*/
typedef struct
{
uint16_t usPortNumber; /* For reference only. Host-endian. */
const char * pcRootDir;
BaseType_t xReadOnly;
}
FTPUserProperties_t;
extern void vApplicationFTPUserPropertiesHook( const char * pcUserName,
FTPUserProperties_t * pxProperties );
#endif /* ipconfigFTP_HAS_USER_PASSWORD_HOOK */
TCPServer_t *FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG *pxConfigs, BaseType_t xCount ); #if ( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 )
void FreeRTOS_TCPServerWork( TCPServer_t *pxServer, TickType_t xBlockingTime );
#if( ipconfigSUPPORT_SIGNALS != 0 ) /*
/* FreeRTOS_TCPServerWork() calls select(). * A GET request is received containing a special character,
The two functions below provide a possibility to interrupt * usually a question mark.
the call to select(). After the interruption, resume * const char *pcURLData; // A request, e.g. "/request?limit=75"
by calling FreeRTOS_TCPServerWork() again. */ * char *pcBuffer; // Here the answer can be written
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t *pxServer ); * size_t uxBufferLength; // Size of the buffer
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t *pxServer, BaseType_t *pxHigherPriorityTaskWoken ); *
#endif */
extern size_t uxApplicationHTTPHandleRequestHook( const char * pcURLData,
char * pcBuffer,
size_t uxBufferLength );
#endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */
#ifdef __cplusplus struct xSERVER_CONFIG
{
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
BaseType_t xPortNumber; /* e.g. 80, 8080, 21 */
BaseType_t xBackLog; /* e.g. 10, maximum number of connected TCP clients */
const char * const pcRootDir; /* Treat this directory as the root directory */
};
struct xTCP_SERVER;
typedef struct xTCP_SERVER TCPServer_t;
TCPServer_t * FreeRTOS_CreateTCPServer( const struct xSERVER_CONFIG * pxConfigs,
BaseType_t xCount );
void FreeRTOS_TCPServerWork( TCPServer_t * pxServer,
TickType_t xBlockingTime );
#if ( ipconfigSUPPORT_SIGNALS != 0 )
/* FreeRTOS_TCPServerWork() calls select().
* The two functions below provide a possibility to interrupt
* the call to select(). After the interruption, resume
* by calling FreeRTOS_TCPServerWork() again. */
BaseType_t FreeRTOS_TCPServerSignal( TCPServer_t * pxServer );
BaseType_t FreeRTOS_TCPServerSignalFromISR( TCPServer_t * pxServer,
BaseType_t * pxHigherPriorityTaskWoken );
#endif
#ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* FREERTOS_TCP_SERVER_H */ #endif /* FREERTOS_TCP_SERVER_H */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS+TCP V2.0.3 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -19,24 +19,25 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://aws.amazon.com/freertos
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
/* /*
Some code which is common to TCP servers like HTTP and FTP * Some code which is common to TCP servers like HTTP and FTP
*/ */
#ifndef FREERTOS_SERVER_PRIVATE_H #ifndef FREERTOS_SERVER_PRIVATE_H
#define FREERTOS_SERVER_PRIVATE_H #define FREERTOS_SERVER_PRIVATE_H
#define FREERTOS_NO_SOCKET NULL #define FREERTOS_NO_SOCKET NULL
/* FreeRTOS+FAT */ /* FreeRTOS+FAT */
#include "ff_stdio.h" #include "ff_stdio.h"
/* Each HTTP server has 1, at most 2 sockets */ /* Each HTTP server has 1, at most 2 sockets */
#define HTTP_SOCKET_COUNT 2 #define HTTP_SOCKET_COUNT 2
/* /*
* ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of: * ipconfigTCP_COMMAND_BUFFER_SIZE sets the size of:
@ -49,11 +50,11 @@
*/ */
#ifndef ipconfigTCP_COMMAND_BUFFER_SIZE #ifndef ipconfigTCP_COMMAND_BUFFER_SIZE
#define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 ) #define ipconfigTCP_COMMAND_BUFFER_SIZE ( 2048 )
#endif #endif
#ifndef ipconfigTCP_FILE_BUFFER_SIZE #ifndef ipconfigTCP_FILE_BUFFER_SIZE
#define ipconfigTCP_FILE_BUFFER_SIZE ( 2048 ) #define ipconfigTCP_FILE_BUFFER_SIZE ( 2048 )
#endif #endif
struct xTCP_CLIENT; struct xTCP_CLIENT;
@ -61,125 +62,140 @@ struct xTCP_CLIENT;
typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ ); typedef BaseType_t ( * FTCPWorkFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ ); typedef void ( * FTCPDeleteFunction ) ( struct xTCP_CLIENT * /* pxClient */ );
#define TCP_CLIENT_FIELDS \ #define TCP_CLIENT_FIELDS \
enum eSERVER_TYPE eType; \ enum eSERVER_TYPE eType; \
struct xTCP_SERVER *pxParent; \ struct xTCP_SERVER * pxParent; \
Socket_t xSocket; \ Socket_t xSocket; \
const char *pcRootDir; \ const char * pcRootDir; \
FTCPWorkFunction fWorkFunction; \ FTCPWorkFunction fWorkFunction; \
FTCPDeleteFunction fDeleteFunction; \ FTCPDeleteFunction fDeleteFunction; \
struct xTCP_CLIENT *pxNextClient struct xTCP_CLIENT * pxNextClient
typedef struct xTCP_CLIENT typedef struct xTCP_CLIENT
{ {
/* This define contains fields which must come first within each of the client structs */ /* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS; TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */ /* --- Keep at the top --- */
} TCPClient_t; } TCPClient_t;
struct xHTTP_CLIENT struct xHTTP_CLIENT
{ {
/* This define contains fields which must come first within each of the client structs */ /* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS; TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */ /* --- Keep at the top --- */
const char *pcUrlData; const char * pcUrlData;
const char *pcRestData; const char * pcRestData;
char pcCurrentFilename[ ffconfigMAX_FILENAME ]; char pcCurrentFilename[ ffconfigMAX_FILENAME ];
size_t uxBytesLeft; size_t uxBytesLeft;
FF_FILE *pxFileHandle; FF_FILE * pxFileHandle;
union { union
struct { {
uint32_t struct
bReplySent : 1; {
}; uint32_t
uint32_t ulFlags; bReplySent : 1;
} bits; };
uint32_t ulFlags;
}
bits;
}; };
typedef struct xHTTP_CLIENT HTTPClient_t; typedef struct xHTTP_CLIENT HTTPClient_t;
struct xFTP_CLIENT struct xFTP_CLIENT
{ {
/* This define contains fields which must come first within each of the client structs */ /* This define contains fields which must come first within each of the client structs */
TCP_CLIENT_FIELDS; TCP_CLIENT_FIELDS;
/* --- Keep at the top --- */ /* --- Keep at the top --- */
uint32_t ulRestartOffset; uint32_t ulRestartOffset;
uint32_t ulRecvBytes; uint32_t ulRecvBytes;
size_t uxBytesLeft; /* Bytes left to send */ size_t uxBytesLeft; /* Bytes left to send */
uint32_t ulClientIP; uint32_t ulClientIP;
TickType_t xStartTime; TickType_t xStartTime;
uint16_t usClientPort; uint16_t usClientPort;
Socket_t xTransferSocket; Socket_t xTransferSocket;
BaseType_t xTransType; BaseType_t xTransType;
BaseType_t xDirCount; BaseType_t xDirCount;
FF_FindData_t xFindData; FF_FindData_t xFindData;
FF_FILE *pxReadHandle; FF_FILE * pxReadHandle;
FF_FILE *pxWriteHandle; FF_FILE * pxWriteHandle;
char pcCurrentDir[ ffconfigMAX_FILENAME ]; char pcCurrentDir[ ffconfigMAX_FILENAME ];
char pcFileName[ ffconfigMAX_FILENAME ]; char pcFileName[ ffconfigMAX_FILENAME ];
char pcConnectionAck[ 128 ]; char pcConnectionAck[ 128 ];
char pcClientAck[ 128 ]; char pcClientAck[ 128 ];
union { union
struct { {
uint32_t struct
bHelloSent : 1, {
bLoggedIn : 1, uint32_t
bStatusUser : 1, bHelloSent : 1,
bInRename : 1, bLoggedIn : 1,
bReadOnly : 1; bStatusUser : 1,
}; bInRename : 1,
uint32_t ulFTPFlags; bReadOnly : 1;
} bits; };
union { uint32_t ulFTPFlags;
struct { }
uint32_t bits;
bIsListen : 1, /* pdTRUE for passive data connections (using list()). */ union
bDirHasEntry : 1, /* pdTRUE if ff_findfirst() was successful. */ {
bClientConnected : 1, /* pdTRUE after connect() or accept() has succeeded. */ struct
bEmptyFile : 1, /* pdTRUE if a connection-without-data was received. */ {
bHadError : 1; /* pdTRUE if a transfer got aborted because of an error. */ uint32_t
}; bIsListen : 1, /* pdTRUE for passive data connections (using list()). */
uint32_t ulConnFlags; bDirHasEntry : 1, /* pdTRUE if ff_findfirst() was successful. */
} bits1; bClientConnected : 1, /* pdTRUE after connect() or accept() has succeeded. */
bEmptyFile : 1, /* pdTRUE if a connection-without-data was received. */
bHadError : 1; /* pdTRUE if a transfer got aborted because of an error. */
};
uint32_t ulConnFlags;
}
bits1;
}; };
typedef struct xFTP_CLIENT FTPClient_t; typedef struct xFTP_CLIENT FTPClient_t;
BaseType_t xHTTPClientWork( TCPClient_t *pxClient ); BaseType_t xHTTPClientWork( TCPClient_t * pxClient );
BaseType_t xFTPClientWork( TCPClient_t *pxClient ); BaseType_t xFTPClientWork( TCPClient_t * pxClient );
void vHTTPClientDelete( TCPClient_t *pxClient ); void vHTTPClientDelete( TCPClient_t * pxClient );
void vFTPClientDelete( TCPClient_t *pxClient ); void vFTPClientDelete( TCPClient_t * pxClient );
BaseType_t xMakeAbsolute( struct xFTP_CLIENT *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName ); BaseType_t xMakeAbsolute( struct xFTP_CLIENT * pxClient,
BaseType_t xMakeRelative( FTPClient_t *pxClient, char *pcBuffer, BaseType_t xBufferLength, const char *pcFileName ); char * pcBuffer,
BaseType_t xBufferLength,
const char * pcFileName );
BaseType_t xMakeRelative( FTPClient_t * pxClient,
char * pcBuffer,
BaseType_t xBufferLength,
const char * pcFileName );
struct xTCP_SERVER struct xTCP_SERVER
{ {
SocketSet_t xSocketSet; SocketSet_t xSocketSet;
/* A buffer to receive and send TCP commands, either HTTP of FTP. */ /* A buffer to receive and send TCP commands, either HTTP of FTP. */
char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ]; char pcCommandBuffer[ ipconfigTCP_COMMAND_BUFFER_SIZE ];
/* A buffer to access the file system: read or write data. */ /* A buffer to access the file system: read or write data. */
char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ]; char pcFileBuffer[ ipconfigTCP_FILE_BUFFER_SIZE ];
#if( ipconfigUSE_FTP != 0 ) #if ( ipconfigUSE_FTP != 0 )
char pcNewDir[ ffconfigMAX_FILENAME ]; char pcNewDir[ ffconfigMAX_FILENAME ];
#endif #endif
#if( ipconfigUSE_HTTP != 0 ) #if ( ipconfigUSE_HTTP != 0 )
char pcContentsType[40]; /* Space for the msg: "text/javascript" */ char pcContentsType[ 40 ]; /* Space for the msg: "text/javascript" */
char pcExtraContents[40]; /* Space for the msg: "Content-Length: 346500" */ char pcExtraContents[ 40 ]; /* Space for the msg: "Content-Length: 346500" */
#endif #endif
BaseType_t xServerCount; BaseType_t xServerCount;
TCPClient_t *pxClients; TCPClient_t * pxClients;
struct xSERVER struct xSERVER
{ {
enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */ enum eSERVER_TYPE eType; /* eSERVER_HTTP | eSERVER_FTP */
const char *pcRootDir; const char * pcRootDir;
Socket_t xSocket; Socket_t xSocket;
} xServers[ 1 ]; }
xServers[ 1 ];
}; };
#endif /* FREERTOS_SERVER_PRIVATE_H */ #endif /* FREERTOS_SERVER_PRIVATE_H */

View file

@ -1,71 +1,98 @@
// /*
// ntpClient.h * FreeRTOS V202212.00
// * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef __NTPCLIENT_H__ /* ntpClient.h */
#ifndef __NTPCLIENT_H__
#define __NTPCLIENT_H__ #define __NTPCLIENT_H__
#define NTP_PORT 123 #define NTP_PORT 123
typedef uint32_t quint32; typedef uint32_t quint32;
typedef int32_t qint32; typedef int32_t qint32;
typedef uint8_t quint8; typedef uint8_t quint8;
typedef int8_t qint8; typedef int8_t qint8;
typedef union _SNtpFlags SNtpFlags; typedef union _SNtpFlags SNtpFlags;
/** /**
* 64-bit NTP timestamp. * 64-bit NTP timestamp.
*/ */
struct __attribute__ ((__packed__)) _SNtpTimestamp { struct __attribute__( ( __packed__ ) ) _SNtpTimestamp
/** Number of seconds passed since Jan 1 1900, in big-endian format. */ {
quint32 seconds; /** Number of seconds passed since Jan 1 1900, in big-endian format. */
quint32 seconds;
/** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */ /** Fractional time part, in <tt>1/0xFFFFFFFF</tt>s of a second. */
quint32 fraction; quint32 fraction;
}; };
typedef struct _SNtpTimestamp SNtpTimestamp; typedef struct _SNtpTimestamp SNtpTimestamp;
/** /**
* Mandatory part of an NTP packet * Mandatory part of an NTP packet
*/ */
struct SNtpPacket { struct SNtpPacket
/** Flags. */ {
unsigned char flags; // value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 /** Flags. */
unsigned char flags; /* value 0xDB : mode 3 (client), version 3, leap indicator unknown 3 */
/** Stratum of the clock. */ /** Stratum of the clock. */
quint8 stratum; // value 0 : unspecified quint8 stratum; /* value 0 : unspecified */
/** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */ /** Maximum interval between successive messages, in log2 seconds. Note that the value is signed. */
qint8 poll; // 10 means 1 << 10 = 1024 seconds qint8 poll; /* 10 means 1 << 10 = 1024 seconds */
/** Precision of the clock, in log2 seconds. Note that the value is signed. */ /** Precision of the clock, in log2 seconds. Note that the value is signed. */
qint8 precision; // 0xFA = 250 = 0.015625 seconds qint8 precision; /* 0xFA = 250 = 0.015625 seconds */
/** Round trip time to the primary reference source, in NTP short format. */ /** Round trip time to the primary reference source, in NTP short format. */
qint32 rootDelay; // 0x5D2E = 23854 or (23854/65535)= 0.3640 sec qint32 rootDelay; /* 0x5D2E = 23854 or (23854/65535)= 0.3640 sec */
/** Nominal error relative to the primary reference source. */ /** Nominal error relative to the primary reference source. */
qint32 rootDispersion; // 0x0008 CAC8 = 8.7912 seconds qint32 rootDispersion; /* 0x0008 CAC8 = 8.7912 seconds */
/** Reference identifier (either a 4 character string or an IP address). */ /** Reference identifier (either a 4 character string or an IP address). */
qint8 referenceID[4]; // or just 0000 qint8 referenceID[ 4 ]; /* or just 0000 */
/** The time at which the clock was last set or corrected. */ /** The time at which the clock was last set or corrected. */
SNtpTimestamp referenceTimestamp; // Current time SNtpTimestamp referenceTimestamp; /* Current time */
/** The time at which the request departed the client for the server. */ /** The time at which the request departed the client for the server. */
SNtpTimestamp originateTimestamp; // Keep 0 SNtpTimestamp originateTimestamp; /* Keep 0 */
/** The time at which the request arrived at the server. */ /** The time at which the request arrived at the server. */
SNtpTimestamp receiveTimestamp; // Keep 0 SNtpTimestamp receiveTimestamp; /* Keep 0 */
/** The time at which the reply departed the server for client. */ /** The time at which the reply departed the server for client. */
SNtpTimestamp transmitTimestamp; SNtpTimestamp transmitTimestamp;
}; };
/* Add this number to get secs since 1-1-1900 */ /* Add this number to get secs since 1-1-1900 */
#define TIME1970 2208988800UL #define TIME1970 2208988800UL
#endif // __NTPCLIENT_H__ #endif // __NTPCLIENT_H__

View file

@ -1,11 +1,34 @@
/* /*
* A simple demo for NTP using FreeRTOS+TCP * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/ */
#ifndef NTPDEMO_H #ifndef NTPDEMO_H
#define NTPDEMO_H #define NTPDEMO_H
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority ); void vStartNTPTask( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority );
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,7 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
@ -43,10 +43,10 @@
#include "api_mdriver_ram.h" #include "api_mdriver_ram.h"
#ifdef _WINDOWS_ #ifdef _WINDOWS_
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
#define cliNEW_LINE "\r\n" #define cliNEW_LINE "\r\n"
/******************************************************************************* /*******************************************************************************
* See the URL in the comments within main.c for the location of the online * See the URL in the comments within main.c for the location of the online
@ -56,88 +56,99 @@
/* /*
* Print out information on a single file. * Print out information on a single file.
*/ */
static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct ); static void prvCreateFileInfoString( char * pcBuffer,
F_FIND * pxFindStruct );
/* /*
* Copies an existing file into a newly created file. * Copies an existing file into a newly created file.
*/ */
static BaseType_t prvPerformCopy( const char *pcSourceFile, static BaseType_t prvPerformCopy( const char * pcSourceFile,
int32_t lSourceFileLength, int32_t lSourceFileLength,
const char *pcDestinationFile, const char * pcDestinationFile,
char *pxWriteBuffer, char * pxWriteBuffer,
size_t xWriteBufferLen ); size_t xWriteBufferLen );
/* /*
* Implements the DIR command. * Implements the DIR command.
*/ */
static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvDIRCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the CD command. * Implements the CD command.
*/ */
static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvCDCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the DEL command. * Implements the DEL command.
*/ */
static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvDELCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the TYPE command. * Implements the TYPE command.
*/ */
static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvTYPECommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the COPY command. * Implements the COPY command.
*/ */
static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvCOPYCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* Structure that defines the DIR command line command, which lists all the /* Structure that defines the DIR command line command, which lists all the
files in the current directory. */ * files in the current directory. */
static const CLI_Command_Definition_t xDIR = static const CLI_Command_Definition_t xDIR =
{ {
"dir", /* The command string to type. */ "dir", /* The command string to type. */
"\r\ndir:\r\n Lists the files in the current directory\r\n", "\r\ndir:\r\n Lists the files in the current directory\r\n",
prvDIRCommand, /* The function to run. */ prvDIRCommand, /* The function to run. */
0 /* No parameters are expected. */ 0 /* No parameters are expected. */
}; };
/* Structure that defines the CD command line command, which changes the /* Structure that defines the CD command line command, which changes the
working directory. */ * working directory. */
static const CLI_Command_Definition_t xCD = static const CLI_Command_Definition_t xCD =
{ {
"cd", /* The command string to type. */ "cd", /* The command string to type. */
"\r\ncd <dir name>:\r\n Changes the working directory\r\n", "\r\ncd <dir name>:\r\n Changes the working directory\r\n",
prvCDCommand, /* The function to run. */ prvCDCommand, /* The function to run. */
1 /* One parameter is expected. */ 1 /* One parameter is expected. */
}; };
/* Structure that defines the TYPE command line command, which prints the /* Structure that defines the TYPE command line command, which prints the
contents of a file to the console. */ * contents of a file to the console. */
static const CLI_Command_Definition_t xTYPE = static const CLI_Command_Definition_t xTYPE =
{ {
"type", /* The command string to type. */ "type", /* The command string to type. */
"\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n", "\r\ntype <filename>:\r\n Prints file contents to the terminal\r\n",
prvTYPECommand, /* The function to run. */ prvTYPECommand, /* The function to run. */
1 /* One parameter is expected. */ 1 /* One parameter is expected. */
}; };
/* Structure that defines the DEL command line command, which deletes a file. */ /* Structure that defines the DEL command line command, which deletes a file. */
static const CLI_Command_Definition_t xDEL = static const CLI_Command_Definition_t xDEL =
{ {
"del", /* The command string to type. */ "del", /* The command string to type. */
"\r\ndel <filename>:\r\n deletes a file or directory\r\n", "\r\ndel <filename>:\r\n deletes a file or directory\r\n",
prvDELCommand, /* The function to run. */ prvDELCommand, /* The function to run. */
1 /* One parameter is expected. */ 1 /* One parameter is expected. */
}; };
/* Structure that defines the COPY command line command, which deletes a file. */ /* Structure that defines the COPY command line command, which deletes a file. */
static const CLI_Command_Definition_t xCOPY = static const CLI_Command_Definition_t xCOPY =
{ {
"copy", /* The command string to type. */ "copy", /* The command string to type. */
"\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n", "\r\ncopy <source file> <dest file>:\r\n Copies <source file> to <dest file>\r\n",
prvCOPYCommand, /* The function to run. */ prvCOPYCommand, /* The function to run. */
2 /* Two parameters are expected. */ 2 /* Two parameters are expected. */
}; };
@ -145,385 +156,398 @@ static const CLI_Command_Definition_t xCOPY =
void vRegisterFileSystemCLICommands( void ) void vRegisterFileSystemCLICommands( void )
{ {
/* Register all the command line commands defined immediately above. */ /* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xDIR ); FreeRTOS_CLIRegisterCommand( &xDIR );
FreeRTOS_CLIRegisterCommand( &xCD ); FreeRTOS_CLIRegisterCommand( &xCD );
FreeRTOS_CLIRegisterCommand( &xTYPE ); FreeRTOS_CLIRegisterCommand( &xTYPE );
FreeRTOS_CLIRegisterCommand( &xDEL ); FreeRTOS_CLIRegisterCommand( &xDEL );
FreeRTOS_CLIRegisterCommand( &xCOPY ); FreeRTOS_CLIRegisterCommand( &xCOPY );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvTYPECommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvTYPECommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *pcParameter; const char * pcParameter;
BaseType_t xParameterStringLength, xReturn = pdTRUE; BaseType_t xParameterStringLength, xReturn = pdTRUE;
static F_FILE *pxFile = NULL; static F_FILE * pxFile = NULL;
int iChar; int iChar;
size_t xByte; size_t xByte;
size_t xColumns = 50U; size_t xColumns = 50U;
/* Ensure there is always a null terminator after each character written. */ /* Ensure there is always a null terminator after each character written. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen ); memset( pcWriteBuffer, 0x00, xWriteBufferLen );
/* Ensure the buffer leaves space for the \r\n. */ /* Ensure the buffer leaves space for the \r\n. */
configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) ); configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
xWriteBufferLen -= strlen( cliNEW_LINE ); xWriteBufferLen -= strlen( cliNEW_LINE );
if( xWriteBufferLen < xColumns ) if( xWriteBufferLen < xColumns )
{ {
/* Ensure the loop that uses xColumns as an end condition does not /* Ensure the loop that uses xColumns as an end condition does not
write off the end of the buffer. */ * write off the end of the buffer. */
xColumns = xWriteBufferLen; xColumns = xWriteBufferLen;
} }
if( pxFile == NULL ) if( pxFile == NULL )
{ {
/* The file has not been opened yet. Find the file name. */ /* The file has not been opened yet. Find the file name. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* Attempt to open the requested file. */ /* Attempt to open the requested file. */
pxFile = f_open( pcParameter, "r" ); pxFile = f_open( pcParameter, "r" );
} }
if( pxFile != NULL ) if( pxFile != NULL )
{ {
/* Read the next chunk of data from the file. */ /* Read the next chunk of data from the file. */
for( xByte = 0; xByte < xColumns; xByte++ ) for( xByte = 0; xByte < xColumns; xByte++ )
{ {
iChar = f_getc( pxFile ); iChar = f_getc( pxFile );
if( iChar == -1 ) if( iChar == -1 )
{ {
/* No more characters to return. */ /* No more characters to return. */
f_close( pxFile ); f_close( pxFile );
pxFile = NULL; pxFile = NULL;
break; break;
} }
else else
{ {
pcWriteBuffer[ xByte ] = ( char ) iChar; pcWriteBuffer[ xByte ] = ( char ) iChar;
} }
} }
} }
if( pxFile == NULL ) if( pxFile == NULL )
{ {
/* Either the file was not opened, or all the data from the file has /* Either the file was not opened, or all the data from the file has
been returned and the file is now closed. */ * been returned and the file is now closed. */
xReturn = pdFALSE; xReturn = pdFALSE;
} }
strcat( pcWriteBuffer, cliNEW_LINE ); strcat( pcWriteBuffer, cliNEW_LINE );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvCDCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvCDCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *pcParameter; const char * pcParameter;
BaseType_t xParameterStringLength; BaseType_t xParameterStringLength;
unsigned char ucReturned; unsigned char ucReturned;
size_t xStringLength; size_t xStringLength;
/* Obtain the parameter string. */ /* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* Attempt to move to the requested directory. */ /* Attempt to move to the requested directory. */
ucReturned = f_chdir( pcParameter ); ucReturned = f_chdir( pcParameter );
if( ucReturned == F_NO_ERROR ) if( ucReturned == F_NO_ERROR )
{ {
sprintf( pcWriteBuffer, "In: " ); sprintf( pcWriteBuffer, "In: " );
xStringLength = strlen( pcWriteBuffer ); xStringLength = strlen( pcWriteBuffer );
f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) ); f_getcwd( &( pcWriteBuffer[ xStringLength ] ), ( unsigned char ) ( xWriteBufferLen - xStringLength ) );
} }
else else
{ {
sprintf( pcWriteBuffer, "Error" ); sprintf( pcWriteBuffer, "Error" );
} }
strcat( pcWriteBuffer, cliNEW_LINE ); strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvDIRCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvDIRCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
static F_FIND *pxFindStruct = NULL; static F_FIND * pxFindStruct = NULL;
unsigned char ucReturned; unsigned char ucReturned;
BaseType_t xReturn = pdFALSE; BaseType_t xReturn = pdFALSE;
/* This assumes pcWriteBuffer is long enough. */ /* This assumes pcWriteBuffer is long enough. */
( void ) pcCommandString; ( void ) pcCommandString;
/* Ensure the buffer leaves space for the \r\n. */ /* Ensure the buffer leaves space for the \r\n. */
configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) ); configASSERT( xWriteBufferLen > ( strlen( cliNEW_LINE ) * 2 ) );
xWriteBufferLen -= strlen( cliNEW_LINE ); xWriteBufferLen -= strlen( cliNEW_LINE );
if( pxFindStruct == NULL ) if( pxFindStruct == NULL )
{ {
/* This is the first time this function has been executed since the Dir /* This is the first time this function has been executed since the Dir
command was run. Create the find structure. */ * command was run. Create the find structure. */
pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) ); pxFindStruct = ( F_FIND * ) pvPortMalloc( sizeof( F_FIND ) );
if( pxFindStruct != NULL ) if( pxFindStruct != NULL )
{ {
ucReturned = f_findfirst( "*.*", pxFindStruct ); ucReturned = f_findfirst( "*.*", pxFindStruct );
if( ucReturned == F_NO_ERROR ) if( ucReturned == F_NO_ERROR )
{ {
prvCreateFileInfoString( pcWriteBuffer, pxFindStruct ); prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." ); snprintf( pcWriteBuffer, xWriteBufferLen, "Error: f_findfirst() failed." );
} }
} }
else else
{ {
snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." ); snprintf( pcWriteBuffer, xWriteBufferLen, "Failed to allocate RAM (using heap_4.c will prevent fragmentation)." );
} }
} }
else else
{ {
/* The find struct has already been created. Find the next file in /* The find struct has already been created. Find the next file in
the directory. */ * the directory. */
ucReturned = f_findnext( pxFindStruct ); ucReturned = f_findnext( pxFindStruct );
if( ucReturned == F_NO_ERROR ) if( ucReturned == F_NO_ERROR )
{ {
prvCreateFileInfoString( pcWriteBuffer, pxFindStruct ); prvCreateFileInfoString( pcWriteBuffer, pxFindStruct );
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
/* There are no more files. Free the find structure. */ /* There are no more files. Free the find structure. */
vPortFree( pxFindStruct ); vPortFree( pxFindStruct );
pxFindStruct = NULL; pxFindStruct = NULL;
/* No string to return. */ /* No string to return. */
pcWriteBuffer[ 0 ] = 0x00; pcWriteBuffer[ 0 ] = 0x00;
} }
} }
strcat( pcWriteBuffer, cliNEW_LINE ); strcat( pcWriteBuffer, cliNEW_LINE );
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvDELCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvDELCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *pcParameter; const char * pcParameter;
BaseType_t xParameterStringLength; BaseType_t xParameterStringLength;
unsigned char ucReturned; unsigned char ucReturned;
/* This function assumes xWriteBufferLen is large enough! */ /* This function assumes xWriteBufferLen is large enough! */
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
/* Obtain the parameter string. */ /* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* Attempt to delete the file. */ /* Attempt to delete the file. */
ucReturned = f_delete( pcParameter ); ucReturned = f_delete( pcParameter );
if( ucReturned == F_NO_ERROR ) if( ucReturned == F_NO_ERROR )
{ {
sprintf( pcWriteBuffer, "%s was deleted", pcParameter ); sprintf( pcWriteBuffer, "%s was deleted", pcParameter );
} }
else else
{ {
sprintf( pcWriteBuffer, "Error" ); sprintf( pcWriteBuffer, "Error" );
} }
strcat( pcWriteBuffer, cliNEW_LINE ); strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvCOPYCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvCOPYCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
char *pcSourceFile, *pcDestinationFile; char * pcSourceFile, * pcDestinationFile;
BaseType_t xParameterStringLength; BaseType_t xParameterStringLength;
long lSourceLength, lDestinationLength = 0; long lSourceLength, lDestinationLength = 0;
/* Obtain the name of the destination file. */ /* Obtain the name of the destination file. */
pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter pcDestinationFile = ( char * ) FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
2, /* Return the second parameter. */ 2, /* Return the second parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcDestinationFile ); configASSERT( pcDestinationFile );
/* Obtain the name of the source file. */ /* Obtain the name of the source file. */
pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter pcSourceFile = ( char * ) FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcSourceFile ); configASSERT( pcSourceFile );
/* Terminate the string. */ /* Terminate the string. */
pcSourceFile[ xParameterStringLength ] = 0x00; pcSourceFile[ xParameterStringLength ] = 0x00;
/* See if the source file exists, obtain its length if it does. */ /* See if the source file exists, obtain its length if it does. */
lSourceLength = f_filelength( pcSourceFile ); lSourceLength = f_filelength( pcSourceFile );
if( lSourceLength == 0 ) if( lSourceLength == 0 )
{ {
sprintf( pcWriteBuffer, "Source file does not exist" ); sprintf( pcWriteBuffer, "Source file does not exist" );
} }
else else
{ {
/* See if the destination file exists. */ /* See if the destination file exists. */
lDestinationLength = f_filelength( pcDestinationFile ); lDestinationLength = f_filelength( pcDestinationFile );
if( lDestinationLength != 0 ) if( lDestinationLength != 0 )
{ {
sprintf( pcWriteBuffer, "Error: Destination file already exists" ); sprintf( pcWriteBuffer, "Error: Destination file already exists" );
} }
} }
/* Continue only if the source file exists and the destination file does /* Continue only if the source file exists and the destination file does
not exist. */ * not exist. */
if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) ) if( ( lSourceLength != 0 ) && ( lDestinationLength == 0 ) )
{ {
if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS ) if( prvPerformCopy( pcSourceFile, lSourceLength, pcDestinationFile, pcWriteBuffer, xWriteBufferLen ) == pdPASS )
{ {
sprintf( pcWriteBuffer, "Copy made" ); sprintf( pcWriteBuffer, "Copy made" );
} }
else else
{ {
sprintf( pcWriteBuffer, "Error during copy" ); sprintf( pcWriteBuffer, "Error during copy" );
} }
} }
strcat( pcWriteBuffer, cliNEW_LINE ); strcat( pcWriteBuffer, cliNEW_LINE );
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvPerformCopy( const char *pcSourceFile, static BaseType_t prvPerformCopy( const char * pcSourceFile,
int32_t lSourceFileLength, int32_t lSourceFileLength,
const char *pcDestinationFile, const char * pcDestinationFile,
char *pxWriteBuffer, char * pxWriteBuffer,
size_t xWriteBufferLen ) size_t xWriteBufferLen )
{ {
int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining; int32_t lBytesRead = 0, lBytesToRead, lBytesRemaining;
F_FILE *pxFile; F_FILE * pxFile;
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
/* NOTE: Error handling has been omitted for clarity. */ /* NOTE: Error handling has been omitted for clarity. */
while( lBytesRead < lSourceFileLength ) while( lBytesRead < lSourceFileLength )
{ {
/* How many bytes are left? */ /* How many bytes are left? */
lBytesRemaining = lSourceFileLength - lBytesRead; lBytesRemaining = lSourceFileLength - lBytesRead;
/* How many bytes should be read this time around the loop. Can't /* How many bytes should be read this time around the loop. Can't
read more bytes than will fit into the buffer. */ * read more bytes than will fit into the buffer. */
if( lBytesRemaining > ( long ) xWriteBufferLen ) if( lBytesRemaining > ( long ) xWriteBufferLen )
{ {
lBytesToRead = ( long ) xWriteBufferLen; lBytesToRead = ( long ) xWriteBufferLen;
} }
else else
{ {
lBytesToRead = lBytesRemaining; lBytesToRead = lBytesRemaining;
} }
/* Open the source file, seek past the data that has already been /* Open the source file, seek past the data that has already been
read from the file, read the next block of data, then close the * read from the file, read the next block of data, then close the
file again so the destination file can be opened. */ * file again so the destination file can be opened. */
pxFile = f_open( pcSourceFile, "r" ); pxFile = f_open( pcSourceFile, "r" );
if( pxFile != NULL )
{
f_seek( pxFile, lBytesRead, F_SEEK_SET );
f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
f_close( pxFile );
}
else
{
xReturn = pdFAIL;
break;
}
/* Open the destination file and write the block of data to the end of if( pxFile != NULL )
the file. */ {
pxFile = f_open( pcDestinationFile, "a" ); f_seek( pxFile, lBytesRead, F_SEEK_SET );
if( pxFile != NULL ) f_read( pxWriteBuffer, lBytesToRead, 1, pxFile );
{ f_close( pxFile );
f_write( pxWriteBuffer, lBytesToRead, 1, pxFile ); }
f_close( pxFile ); else
} {
else xReturn = pdFAIL;
{ break;
xReturn = pdFAIL; }
break;
}
lBytesRead += lBytesToRead; /* Open the destination file and write the block of data to the end of
} * the file. */
pxFile = f_open( pcDestinationFile, "a" );
return xReturn; if( pxFile != NULL )
{
f_write( pxWriteBuffer, lBytesToRead, 1, pxFile );
f_close( pxFile );
}
else
{
xReturn = pdFAIL;
break;
}
lBytesRead += lBytesToRead;
}
return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCreateFileInfoString( char *pcBuffer, F_FIND *pxFindStruct ) static void prvCreateFileInfoString( char * pcBuffer,
F_FIND * pxFindStruct )
{ {
const char *pcWritableFile = "writable file", *pcReadOnlyFile = "read only file", *pcDirectory = "directory"; const char * pcWritableFile = "writable file", * pcReadOnlyFile = "read only file", * pcDirectory = "directory";
const char * pcAttrib; const char * pcAttrib;
/* Point pcAttrib to a string that describes the file. */ /* Point pcAttrib to a string that describes the file. */
if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 ) if( ( pxFindStruct->attr & F_ATTR_DIR ) != 0 )
{ {
pcAttrib = pcDirectory; pcAttrib = pcDirectory;
} }
else if( pxFindStruct->attr & F_ATTR_READONLY ) else if( pxFindStruct->attr & F_ATTR_READONLY )
{ {
pcAttrib = pcReadOnlyFile; pcAttrib = pcReadOnlyFile;
} }
else else
{ {
pcAttrib = pcWritableFile; pcAttrib = pcWritableFile;
} }
/* Create a string that includes the file name, the file size and the /* Create a string that includes the file name, the file size and the
attributes string. */ * attributes string. */
sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize ); sprintf( pcBuffer, "%s [%s] [size=%d]", pxFindStruct->filename, pcAttrib, ( int ) pxFindStruct->filesize );
} }

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,16 +20,16 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
/****************************************************************************** /******************************************************************************
* *
* https://www.FreeRTOS.org/cli * https://www.FreeRTOS.org/cli
* *
******************************************************************************/ ******************************************************************************/
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@ -46,11 +46,11 @@
#include "FreeRTOS_CLI.h" #include "FreeRTOS_CLI.h"
#ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS #ifndef configINCLUDE_TRACE_RELATED_CLI_COMMANDS
#define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0 #define configINCLUDE_TRACE_RELATED_CLI_COMMANDS 0
#endif #endif
#ifndef configINCLUDE_QUERY_HEAP_COMMAND #ifndef configINCLUDE_QUERY_HEAP_COMMAND
#define configINCLUDE_QUERY_HEAP_COMMAND 0 #define configINCLUDE_QUERY_HEAP_COMMAND 0
#endif #endif
/* /*
@ -61,419 +61,447 @@ void vRegisterSampleCLICommands( void );
/* /*
* Implements the task-stats command. * Implements the task-stats command.
*/ */
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvTaskStatsCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the run-time-stats command. * Implements the run-time-stats command.
*/ */
#if( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvRunTimeStatsCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* configGENERATE_RUN_TIME_STATS */
/* /*
* Implements the echo-three-parameters command. * Implements the echo-three-parameters command.
*/ */
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvThreeParameterEchoCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the echo-parameters command. * Implements the echo-parameters command.
*/ */
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvParameterEchoCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Implements the "query heap" command. * Implements the "query heap" command.
*/ */
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 ) #if ( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
static BaseType_t prvQueryHeapCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvQueryHeapCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
#endif #endif
/* /*
* Implements the "trace start" and "trace stop" commands; * Implements the "trace start" and "trace stop" commands;
*/ */
#if( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 ) #if ( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 )
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvStartStopTraceCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
#endif #endif
/* Structure that defines the "task-stats" command line command. This generates /* Structure that defines the "task-stats" command line command. This generates
a table that gives information on each task in the system. */ * a table that gives information on each task in the system. */
static const CLI_Command_Definition_t xTaskStats = static const CLI_Command_Definition_t xTaskStats =
{ {
"task-stats", /* The command string to type. */ "task-stats", /* The command string to type. */
"\r\ntask-stats:\r\n Displays a table showing the state of each FreeRTOS task\r\n", "\r\ntask-stats:\r\n Displays a table showing the state of each FreeRTOS task\r\n",
prvTaskStatsCommand, /* The function to run. */ prvTaskStatsCommand, /* The function to run. */
0 /* No parameters are expected. */ 0 /* No parameters are expected. */
}; };
/* Structure that defines the "echo_3_parameters" command line command. This /* Structure that defines the "echo_3_parameters" command line command. This
takes exactly three parameters that the command simply echos back one at a * takes exactly three parameters that the command simply echos back one at a
time. */ * time. */
static const CLI_Command_Definition_t xThreeParameterEcho = static const CLI_Command_Definition_t xThreeParameterEcho =
{ {
"echo-3-parameters", "echo-3-parameters",
"\r\necho-3-parameters <param1> <param2> <param3>:\r\n Expects three parameters, echos each in turn\r\n", "\r\necho-3-parameters <param1> <param2> <param3>:\r\n Expects three parameters, echos each in turn\r\n",
prvThreeParameterEchoCommand, /* The function to run. */ prvThreeParameterEchoCommand, /* The function to run. */
3 /* Three parameters are expected, which can take any value. */ 3 /* Three parameters are expected, which can take any value. */
}; };
/* Structure that defines the "echo_parameters" command line command. This /* Structure that defines the "echo_parameters" command line command. This
takes a variable number of parameters that the command simply echos back one at * takes a variable number of parameters that the command simply echos back one at
a time. */ * a time. */
static const CLI_Command_Definition_t xParameterEcho = static const CLI_Command_Definition_t xParameterEcho =
{ {
"echo-parameters", "echo-parameters",
"\r\necho-parameters <...>:\r\n Take variable number of parameters, echos each in turn\r\n", "\r\necho-parameters <...>:\r\n Take variable number of parameters, echos each in turn\r\n",
prvParameterEchoCommand, /* The function to run. */ prvParameterEchoCommand, /* The function to run. */
-1 /* The user can enter any number of commands. */ -1 /* The user can enter any number of commands. */
}; };
#if( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
/* Structure that defines the "run-time-stats" command line command. This
generates a table that shows how much run time each task has */ /* Structure that defines the "run-time-stats" command line command. This
static const CLI_Command_Definition_t xRunTimeStats = * generates a table that shows how much run time each task has */
{ static const CLI_Command_Definition_t xRunTimeStats =
"run-time-stats", /* The command string to type. */ {
"\r\nrun-time-stats:\r\n Displays a table showing how much processing time each FreeRTOS task has used\r\n", "run-time-stats", /* The command string to type. */
prvRunTimeStatsCommand, /* The function to run. */ "\r\nrun-time-stats:\r\n Displays a table showing how much processing time each FreeRTOS task has used\r\n",
0 /* No parameters are expected. */ prvRunTimeStatsCommand, /* The function to run. */
}; 0 /* No parameters are expected. */
};
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* configGENERATE_RUN_TIME_STATS */
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 ) #if ( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
/* Structure that defines the "query_heap" command line command. */ /* Structure that defines the "query_heap" command line command. */
static const CLI_Command_Definition_t xQueryHeap = static const CLI_Command_Definition_t xQueryHeap =
{ {
"query-heap", "query-heap",
"\r\nquery-heap:\r\n Displays the free heap space, and minimum ever free heap space.\r\n", "\r\nquery-heap:\r\n Displays the free heap space, and minimum ever free heap space.\r\n",
prvQueryHeapCommand, /* The function to run. */ prvQueryHeapCommand, /* The function to run. */
0 /* The user can enter any number of commands. */ 0 /* The user can enter any number of commands. */
}; };
#endif /* configQUERY_HEAP_COMMAND */ #endif /* configQUERY_HEAP_COMMAND */
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 #if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
/* Structure that defines the "trace" command line command. This takes a single
parameter, which can be either "start" or "stop". */ /* Structure that defines the "trace" command line command. This takes a single
static const CLI_Command_Definition_t xStartStopTrace = * parameter, which can be either "start" or "stop". */
{ static const CLI_Command_Definition_t xStartStopTrace =
"trace", {
"\r\ntrace [start | stop]:\r\n Starts or stops a trace recording for viewing in FreeRTOS+Trace\r\n", "trace",
prvStartStopTraceCommand, /* The function to run. */ "\r\ntrace [start | stop]:\r\n Starts or stops a trace recording for viewing in FreeRTOS+Trace\r\n",
1 /* One parameter is expected. Valid values are "start" and "stop". */ prvStartStopTraceCommand, /* The function to run. */
}; 1 /* One parameter is expected. Valid values are "start" and "stop". */
};
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */ #endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vRegisterSampleCLICommands( void ) void vRegisterSampleCLICommands( void )
{ {
/* Register all the command line commands defined immediately above. */ /* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xTaskStats ); FreeRTOS_CLIRegisterCommand( &xTaskStats );
FreeRTOS_CLIRegisterCommand( &xThreeParameterEcho ); FreeRTOS_CLIRegisterCommand( &xThreeParameterEcho );
FreeRTOS_CLIRegisterCommand( &xParameterEcho ); FreeRTOS_CLIRegisterCommand( &xParameterEcho );
#if( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
{ {
FreeRTOS_CLIRegisterCommand( &xRunTimeStats ); FreeRTOS_CLIRegisterCommand( &xRunTimeStats );
} }
#endif #endif
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 ) #if ( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
{ {
FreeRTOS_CLIRegisterCommand( &xQueryHeap ); FreeRTOS_CLIRegisterCommand( &xQueryHeap );
} }
#endif #endif
#if( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 ) #if ( configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 )
{ {
FreeRTOS_CLIRegisterCommand( &xStartStopTrace ); FreeRTOS_CLIRegisterCommand( &xStartStopTrace );
} }
#endif #endif
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvTaskStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvTaskStatsCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *const pcHeader = " State Priority Stack #\r\n************************************************\r\n"; const char * const pcHeader = " State Priority Stack #\r\n************************************************\r\n";
BaseType_t xSpacePadding; BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */ /* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" ); strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer ); pcWriteBuffer += strlen( pcWriteBuffer );
/* Minus three for the null terminator and half the number of characters in /* Minus three for the null terminator and half the number of characters in
"Task" so the column lines up with the centre of the heading. */ * "Task" so the column lines up with the centre of the heading. */
configASSERT( configMAX_TASK_NAME_LEN > 3 ); configASSERT( configMAX_TASK_NAME_LEN > 3 );
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{
/* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' ';
pcWriteBuffer++;
/* Ensure always terminated. */ for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
*pcWriteBuffer = 0x00; {
} /* Add a space to align columns after the task's name. */
strcpy( pcWriteBuffer, pcHeader ); *pcWriteBuffer = ' ';
vTaskList( pcWriteBuffer + strlen( pcHeader ) ); pcWriteBuffer++;
/* There is no more data to return after this single string, so return /* Ensure always terminated. */
pdFALSE. */ *pcWriteBuffer = 0x00;
return pdFALSE; }
strcpy( pcWriteBuffer, pcHeader );
vTaskList( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return
* pdFALSE. */
return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configINCLUDE_QUERY_HEAP_COMMAND == 1 ) #if ( configINCLUDE_QUERY_HEAP_COMMAND == 1 )
static BaseType_t prvQueryHeapCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvQueryHeapCommand( char * pcWriteBuffer,
{ size_t xWriteBufferLen,
/* Remove compile time warnings about unused parameters, and check the const char * pcCommandString )
write buffer is not NULL. NOTE - for simplicity, this example assumes the {
write buffer length is adequate, so does not check for buffer overflows. */ /* Remove compile time warnings about unused parameters, and check the
( void ) pcCommandString; * write buffer is not NULL. NOTE - for simplicity, this example assumes the
( void ) xWriteBufferLen; * write buffer length is adequate, so does not check for buffer overflows. */
configASSERT( pcWriteBuffer ); ( void ) pcCommandString;
( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer );
sprintf( pcWriteBuffer, "Current free heap %d bytes, minimum ever free heap %d bytes\r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() ); sprintf( pcWriteBuffer, "Current free heap %d bytes, minimum ever free heap %d bytes\r\n", ( int ) xPortGetFreeHeapSize(), ( int ) xPortGetMinimumEverFreeHeapSize() );
/* There is no more data to return after this single string, so return /* There is no more data to return after this single string, so return
pdFALSE. */ * pdFALSE. */
return pdFALSE; return pdFALSE;
} }
#endif /* configINCLUDE_QUERY_HEAP */ #endif /* configINCLUDE_QUERY_HEAP */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
static BaseType_t prvRunTimeStatsCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvRunTimeStatsCommand( char * pcWriteBuffer,
{ size_t xWriteBufferLen,
const char * const pcHeader = " Abs Time % Time\r\n****************************************\r\n"; const char * pcCommandString )
BaseType_t xSpacePadding; {
const char * const pcHeader = " Abs Time % Time\r\n****************************************\r\n";
BaseType_t xSpacePadding;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
/* Generate a table of task stats. */ /* Generate a table of task stats. */
strcpy( pcWriteBuffer, "Task" ); strcpy( pcWriteBuffer, "Task" );
pcWriteBuffer += strlen( pcWriteBuffer ); pcWriteBuffer += strlen( pcWriteBuffer );
/* Pad the string "task" with however many bytes necessary to make it the /* Pad the string "task" with however many bytes necessary to make it the
length of a task name. Minus three for the null terminator and half the * length of a task name. Minus three for the null terminator and half the
number of characters in "Task" so the column lines up with the centre of * number of characters in "Task" so the column lines up with the centre of
the heading. */ * the heading. */
for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ ) for( xSpacePadding = strlen( "Task" ); xSpacePadding < ( configMAX_TASK_NAME_LEN - 3 ); xSpacePadding++ )
{ {
/* Add a space to align columns after the task's name. */ /* Add a space to align columns after the task's name. */
*pcWriteBuffer = ' '; *pcWriteBuffer = ' ';
pcWriteBuffer++; pcWriteBuffer++;
/* Ensure always terminated. */ /* Ensure always terminated. */
*pcWriteBuffer = 0x00; *pcWriteBuffer = 0x00;
} }
strcpy( pcWriteBuffer, pcHeader ); strcpy( pcWriteBuffer, pcHeader );
vTaskGetRunTimeStats( pcWriteBuffer + strlen( pcHeader ) ); vTaskGetRunTimeStats( pcWriteBuffer + strlen( pcHeader ) );
/* There is no more data to return after this single string, so return /* There is no more data to return after this single string, so return
pdFALSE. */ * pdFALSE. */
return pdFALSE; return pdFALSE;
} }
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* configGENERATE_RUN_TIME_STATS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvThreeParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvThreeParameterEchoCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *pcParameter; const char * pcParameter;
BaseType_t xParameterStringLength, xReturn; BaseType_t xParameterStringLength, xReturn;
static UBaseType_t uxParameterNumber = 0; static UBaseType_t uxParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
if( uxParameterNumber == 0 ) if( uxParameterNumber == 0 )
{ {
/* The first time the function is called after the command has been /* The first time the function is called after the command has been
entered just a header string is returned. */ * entered just a header string is returned. */
sprintf( pcWriteBuffer, "The three parameters were:\r\n" ); sprintf( pcWriteBuffer, "The three parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed /* Next time the function is called the first parameter will be echoed
back. */ * back. */
uxParameterNumber = 1U; uxParameterNumber = 1U;
/* There is more data to be returned as no parameters have been echoed /* There is more data to be returned as no parameters have been echoed
back yet. */ * back yet. */
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
/* Obtain the parameter string. */ /* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
uxParameterNumber, /* Return the next parameter. */ uxParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* Return the parameter string. */ /* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen ); memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber ); sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber );
strncat( pcWriteBuffer, pcParameter, ( size_t ) xParameterStringLength ); strncat( pcWriteBuffer, pcParameter, ( size_t ) xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* If this is the last of the three parameters then there are no more /* If this is the last of the three parameters then there are no more
strings to return after this one. */ * strings to return after this one. */
if( uxParameterNumber == 3U ) if( uxParameterNumber == 3U )
{ {
/* If this is the last of the three parameters then there are no more /* If this is the last of the three parameters then there are no more
strings to return after this one. */ * strings to return after this one. */
xReturn = pdFALSE; xReturn = pdFALSE;
uxParameterNumber = 0; uxParameterNumber = 0;
} }
else else
{ {
/* There are more parameters to return after this one. */ /* There are more parameters to return after this one. */
xReturn = pdTRUE; xReturn = pdTRUE;
uxParameterNumber++; uxParameterNumber++;
} }
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static BaseType_t prvParameterEchoCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvParameterEchoCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
const char *pcParameter; const char * pcParameter;
BaseType_t xParameterStringLength, xReturn; BaseType_t xParameterStringLength, xReturn;
static UBaseType_t uxParameterNumber = 0; static UBaseType_t uxParameterNumber = 0;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
if( uxParameterNumber == 0 ) if( uxParameterNumber == 0 )
{ {
/* The first time the function is called after the command has been /* The first time the function is called after the command has been
entered just a header string is returned. */ * entered just a header string is returned. */
sprintf( pcWriteBuffer, "The parameters were:\r\n" ); sprintf( pcWriteBuffer, "The parameters were:\r\n" );
/* Next time the function is called the first parameter will be echoed /* Next time the function is called the first parameter will be echoed
back. */ * back. */
uxParameterNumber = 1U; uxParameterNumber = 1U;
/* There is more data to be returned as no parameters have been echoed /* There is more data to be returned as no parameters have been echoed
back yet. */ * back yet. */
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
/* Obtain the parameter string. */ /* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
uxParameterNumber, /* Return the next parameter. */ uxParameterNumber, /* Return the next parameter. */
&xParameterStringLength /* Store the parameter string length. */ &xParameterStringLength /* Store the parameter string length. */
); );
if( pcParameter != NULL ) if( pcParameter != NULL )
{ {
/* Return the parameter string. */ /* Return the parameter string. */
memset( pcWriteBuffer, 0x00, xWriteBufferLen ); memset( pcWriteBuffer, 0x00, xWriteBufferLen );
sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber ); sprintf( pcWriteBuffer, "%d: ", ( int ) uxParameterNumber );
strncat( pcWriteBuffer, ( char * ) pcParameter, ( size_t ) xParameterStringLength ); strncat( pcWriteBuffer, ( char * ) pcParameter, ( size_t ) xParameterStringLength );
strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) ); strncat( pcWriteBuffer, "\r\n", strlen( "\r\n" ) );
/* There might be more parameters to return after this one. */ /* There might be more parameters to return after this one. */
xReturn = pdTRUE; xReturn = pdTRUE;
uxParameterNumber++; uxParameterNumber++;
} }
else else
{ {
/* No more parameters were found. Make sure the write buffer does /* No more parameters were found. Make sure the write buffer does
not contain a valid string. */ * not contain a valid string. */
pcWriteBuffer[ 0 ] = 0x00; pcWriteBuffer[ 0 ] = 0x00;
/* No more data to return. */ /* No more data to return. */
xReturn = pdFALSE; xReturn = pdFALSE;
/* Start over the next time this command is executed. */ /* Start over the next time this command is executed. */
uxParameterNumber = 0; uxParameterNumber = 0;
} }
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1 #if configINCLUDE_TRACE_RELATED_CLI_COMMANDS == 1
static BaseType_t prvStartStopTraceCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvStartStopTraceCommand( char * pcWriteBuffer,
{ size_t xWriteBufferLen,
const char *pcParameter; const char * pcCommandString )
BaseType_t lParameterStringLength; {
const char * pcParameter;
BaseType_t lParameterStringLength;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
/* Obtain the parameter string. */ /* Obtain the parameter string. */
pcParameter = FreeRTOS_CLIGetParameter pcParameter = FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */ &lParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* There are only two valid parameter values. */ /* There are only two valid parameter values. */
if( strncmp( pcParameter, "start", strlen( "start" ) ) == 0 ) if( strncmp( pcParameter, "start", strlen( "start" ) ) == 0 )
{ {
/* Start or restart the trace. */ /* Start or restart the trace. */
vTraceStop(); vTraceStop();
vTraceClear(); vTraceClear();
vTraceStart(); vTraceStart();
sprintf( pcWriteBuffer, "Trace recording (re)started.\r\n" ); sprintf( pcWriteBuffer, "Trace recording (re)started.\r\n" );
} }
else if( strncmp( pcParameter, "stop", strlen( "stop" ) ) == 0 ) else if( strncmp( pcParameter, "stop", strlen( "stop" ) ) == 0 )
{ {
/* End the trace, if one is running. */ /* End the trace, if one is running. */
vTraceStop(); vTraceStop();
sprintf( pcWriteBuffer, "Stopping trace recording.\r\n" ); sprintf( pcWriteBuffer, "Stopping trace recording.\r\n" );
} }
else else
{ {
sprintf( pcWriteBuffer, "Valid parameters are 'start' and 'stop'.\r\n" ); sprintf( pcWriteBuffer, "Valid parameters are 'start' and 'stop'.\r\n" );
} }
/* There is no more data to return after this single string, so return /* There is no more data to return after this single string, so return
pdFALSE. */ * pdFALSE. */
return pdFALSE; return pdFALSE;
} }
#endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */ #endif /* configINCLUDE_TRACE_RELATED_CLI_COMMANDS */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,7 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
@ -44,21 +44,21 @@
#include "serial.h" #include "serial.h"
/* Dimensions the buffer into which input characters are placed. */ /* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE 50 #define cmdMAX_INPUT_SIZE 50
/* Dimentions a buffer to be used by the UART driver, if the UART driver uses a /* Dimensions a buffer to be used by the UART driver, if the UART driver uses a
buffer at all. */ * buffer at all. */
#define cmdQUEUE_LENGTH 25 #define cmdQUEUE_LENGTH 25
/* DEL acts as a backspace. */ /* DEL acts as a backspace. */
#define cmdASCII_DEL ( 0x7F ) #define cmdASCII_DEL ( 0x7F )
/* The maximum time to wait for the mutex that guards the UART to become /* The maximum time to wait for the mutex that guards the UART to become
available. */ * available. */
#define cmdMAX_MUTEX_WAIT pdMS_TO_TICKS( 300 ) #define cmdMAX_MUTEX_WAIT pdMS_TO_TICKS( 300 )
#ifndef configCLI_BAUD_RATE #ifndef configCLI_BAUD_RATE
#define configCLI_BAUD_RATE 115200 #define configCLI_BAUD_RATE 115200
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -66,8 +66,9 @@ available. */
/* /*
* The task that implements the command console processing. * The task that implements the command console processing.
*/ */
static void prvUARTCommandConsoleTask( void *pvParameters ); static void prvUARTCommandConsoleTask( void * pvParameters );
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority ); void vUARTCommandConsoleStart( uint16_t usStackSize,
UBaseType_t uxPriority );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -77,7 +78,7 @@ static const char * const pcEndOfOutputMessage = "\r\n[Press ENTER to execute th
static const char * const pcNewLine = "\r\n"; static const char * const pcNewLine = "\r\n";
/* Used to guard access to the UART in case messages are sent to the UART from /* Used to guard access to the UART in case messages are sent to the UART from
more than one task. */ * more than one task. */
static SemaphoreHandle_t xTxMutex = NULL; static SemaphoreHandle_t xTxMutex = NULL;
/* The handle to the UART port, which is not used by all ports. */ /* The handle to the UART port, which is not used by all ports. */
@ -85,141 +86,142 @@ static xComPortHandle xPort = 0;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vUARTCommandConsoleStart( uint16_t usStackSize, UBaseType_t uxPriority ) void vUARTCommandConsoleStart( uint16_t usStackSize,
UBaseType_t uxPriority )
{ {
/* Create the semaphore used to access the UART Tx. */ /* Create the semaphore used to access the UART Tx. */
xTxMutex = xSemaphoreCreateMutex(); xTxMutex = xSemaphoreCreateMutex();
configASSERT( xTxMutex ); configASSERT( xTxMutex );
/* Create that task that handles the console itself. */ /* Create that task that handles the console itself. */
xTaskCreate( prvUARTCommandConsoleTask, /* The task that implements the command console. */ xTaskCreate( prvUARTCommandConsoleTask, /* The task that implements the command console. */
"CLI", /* Text name assigned to the task. This is just to assist debugging. The kernel does not use this name itself. */ "CLI", /* Text name assigned to the task. This is just to assist debugging. The kernel does not use this name itself. */
usStackSize, /* The size of the stack allocated to the task. */ usStackSize, /* The size of the stack allocated to the task. */
NULL, /* The parameter is not used, so NULL is passed. */ NULL, /* The parameter is not used, so NULL is passed. */
uxPriority, /* The priority allocated to the task. */ uxPriority, /* The priority allocated to the task. */
NULL ); /* A handle is not required, so just pass NULL. */ NULL ); /* A handle is not required, so just pass NULL. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvUARTCommandConsoleTask( void *pvParameters ) static void prvUARTCommandConsoleTask( void * pvParameters )
{ {
signed char cRxedChar; signed char cRxedChar;
uint8_t ucInputIndex = 0; uint8_t ucInputIndex = 0;
char *pcOutputString; char * pcOutputString;
static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ]; static char cInputString[ cmdMAX_INPUT_SIZE ], cLastInputString[ cmdMAX_INPUT_SIZE ];
BaseType_t xReturned; BaseType_t xReturned;
xComPortHandle xPort; xComPortHandle xPort;
( void ) pvParameters; ( void ) pvParameters;
/* Obtain the address of the output buffer. Note there is no mutual /* Obtain the address of the output buffer. Note there is no mutual
exclusion on this buffer as it is assumed only one command console interface * exclusion on this buffer as it is assumed only one command console interface
will be used at any one time. */ * will be used at any one time. */
pcOutputString = FreeRTOS_CLIGetOutputBuffer(); pcOutputString = FreeRTOS_CLIGetOutputBuffer();
/* Initialise the UART. */ /* Initialise the UART. */
xPort = xSerialPortInitMinimal( configCLI_BAUD_RATE, cmdQUEUE_LENGTH ); xPort = xSerialPortInitMinimal( configCLI_BAUD_RATE, cmdQUEUE_LENGTH );
/* Send the welcome message. */ /* Send the welcome message. */
vSerialPutString( xPort, ( signed char * ) pcWelcomeMessage, ( unsigned short ) strlen( pcWelcomeMessage ) ); vSerialPutString( xPort, ( signed char * ) pcWelcomeMessage, ( unsigned short ) strlen( pcWelcomeMessage ) );
for( ;; ) for( ; ; )
{ {
/* Wait for the next character. The while loop is used in case /* Wait for the next character. The while loop is used in case
INCLUDE_vTaskSuspend is not set to 1 - in which case portMAX_DELAY will * INCLUDE_vTaskSuspend is not set to 1 - in which case portMAX_DELAY will
be a genuine block time rather than an infinite block time. */ * be a genuine block time rather than an infinite block time. */
while( xSerialGetChar( xPort, &cRxedChar, portMAX_DELAY ) != pdPASS ); while( xSerialGetChar( xPort, &cRxedChar, portMAX_DELAY ) != pdPASS )
{
}
/* Ensure exclusive access to the UART Tx. */ /* Ensure exclusive access to the UART Tx. */
if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS ) if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
{ {
/* Echo the character back. */ /* Echo the character back. */
xSerialPutChar( xPort, cRxedChar, portMAX_DELAY ); xSerialPutChar( xPort, cRxedChar, portMAX_DELAY );
/* Was it the end of the line? */ /* Was it the end of the line? */
if( cRxedChar == '\n' || cRxedChar == '\r' ) if( ( cRxedChar == '\n' ) || ( cRxedChar == '\r' ) )
{ {
/* Just to space the output from the input. */ /* Just to space the output from the input. */
vSerialPutString( xPort, ( signed char * ) pcNewLine, ( unsigned short ) strlen( pcNewLine ) ); vSerialPutString( xPort, ( signed char * ) pcNewLine, ( unsigned short ) strlen( pcNewLine ) );
/* See if the command is empty, indicating that the last command /* See if the command is empty, indicating that the last command
is to be executed again. */ * is to be executed again. */
if( ucInputIndex == 0 ) if( ucInputIndex == 0 )
{ {
/* Copy the last command back into the input string. */ /* Copy the last command back into the input string. */
strcpy( cInputString, cLastInputString ); strcpy( cInputString, cLastInputString );
} }
/* Pass the received command to the command interpreter. The /* Pass the received command to the command interpreter. The
command interpreter is called repeatedly until it returns * command interpreter is called repeatedly until it returns
pdFALSE (indicating there is no more output) as it might * pdFALSE (indicating there is no more output) as it might
generate more than one string. */ * generate more than one string. */
do do
{ {
/* Get the next output string from the command interpreter. */ /* Get the next output string from the command interpreter. */
xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE ); xReturned = FreeRTOS_CLIProcessCommand( cInputString, pcOutputString, configCOMMAND_INT_MAX_OUTPUT_SIZE );
/* Write the generated string to the UART. */ /* Write the generated string to the UART. */
vSerialPutString( xPort, ( signed char * ) pcOutputString, ( unsigned short ) strlen( pcOutputString ) ); vSerialPutString( xPort, ( signed char * ) pcOutputString, ( unsigned short ) strlen( pcOutputString ) );
} while( xReturned != pdFALSE );
} while( xReturned != pdFALSE ); /* All the strings generated by the input command have been
* sent. Clear the input string ready to receive the next command.
* Remember the command that was just processed first in case it is
* to be processed again. */
strcpy( cLastInputString, cInputString );
ucInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
/* All the strings generated by the input command have been vSerialPutString( xPort, ( signed char * ) pcEndOfOutputMessage, ( unsigned short ) strlen( pcEndOfOutputMessage ) );
sent. Clear the input string ready to receive the next command. }
Remember the command that was just processed first in case it is else
to be processed again. */ {
strcpy( cLastInputString, cInputString ); if( cRxedChar == '\r' )
ucInputIndex = 0; {
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE ); /* Ignore the character. */
}
else if( ( cRxedChar == '\b' ) || ( cRxedChar == cmdASCII_DEL ) )
{
/* Backspace was pressed. Erase the last character in the
* string - if any. */
if( ucInputIndex > 0 )
{
ucInputIndex--;
cInputString[ ucInputIndex ] = '\0';
}
}
else
{
/* A character was entered. Add it to the string entered so
* far. When a \n is entered the complete string will be
* passed to the command interpreter. */
if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )
{
if( ucInputIndex < cmdMAX_INPUT_SIZE )
{
cInputString[ ucInputIndex ] = cRxedChar;
ucInputIndex++;
}
}
}
}
vSerialPutString( xPort, ( signed char * ) pcEndOfOutputMessage, ( unsigned short ) strlen( pcEndOfOutputMessage ) ); /* Must ensure to give the mutex back. */
} xSemaphoreGive( xTxMutex );
else }
{ }
if( cRxedChar == '\r' )
{
/* Ignore the character. */
}
else if( ( cRxedChar == '\b' ) || ( cRxedChar == cmdASCII_DEL ) )
{
/* Backspace was pressed. Erase the last character in the
string - if any. */
if( ucInputIndex > 0 )
{
ucInputIndex--;
cInputString[ ucInputIndex ] = '\0';
}
}
else
{
/* A character was entered. Add it to the string entered so
far. When a \n is entered the complete string will be
passed to the command interpreter. */
if( ( cRxedChar >= ' ' ) && ( cRxedChar <= '~' ) )
{
if( ucInputIndex < cmdMAX_INPUT_SIZE )
{
cInputString[ ucInputIndex ] = cRxedChar;
ucInputIndex++;
}
}
}
}
/* Must ensure to give the mutex back. */
xSemaphoreGive( xTxMutex );
}
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vOutputString( const char * const pcMessage ) void vOutputString( const char * const pcMessage )
{ {
if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS ) if( xSemaphoreTake( xTxMutex, cmdMAX_MUTEX_WAIT ) == pdPASS )
{ {
vSerialPutString( xPort, ( signed char * ) pcMessage, ( unsigned short ) strlen( pcMessage ) ); vSerialPutString( xPort, ( signed char * ) pcMessage, ( unsigned short ) strlen( pcMessage ) );
xSemaphoreGive( xTxMutex ); xSemaphoreGive( xTxMutex );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -24,12 +24,12 @@
* *
*/ */
/****************************************************************************** /******************************************************************************
* *
* See the following URL for information on the commands defined in this file: * See the following URL for information on the commands defined in this file:
* https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Ethernet_Related_CLI_Commands.shtml * https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Ethernet_Related_CLI_Commands.shtml
* *
******************************************************************************/ ******************************************************************************/
/* FreeRTOS includes. */ /* FreeRTOS includes. */
@ -45,57 +45,63 @@
#include "FreeRTOS_CLI.h" #include "FreeRTOS_CLI.h"
/* FreeRTOS+UDP includes, just to make the stats available to the CLI /* FreeRTOS+UDP includes, just to make the stats available to the CLI
commands. */ * commands. */
#include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
/* /*
* Defines a command that prints out IP address information. * Defines a command that prints out IP address information.
*/ */
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvDisplayIPConfig( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Defines a command that prints out the gathered demo debug stats. * Defines a command that prints out the gathered demo debug stats.
*/ */
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvDisplayIPDebugStats( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* /*
* Defines a command that sends an ICMP ping request to an IP address. * Defines a command that sends an ICMP ping request to an IP address.
*/ */
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ); static BaseType_t prvPingCommand( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString );
/* Structure that defines the "ip-config" command line command. */ /* Structure that defines the "ip-config" command line command. */
static const CLI_Command_Definition_t xIPConfig = static const CLI_Command_Definition_t xIPConfig =
{ {
"ip-config", "ip-config",
"ip-config:\r\n Displays IP address configuration\r\n\r\n", "ip-config:\r\n Displays IP address configuration\r\n\r\n",
prvDisplayIPConfig, prvDisplayIPConfig,
0 0
}; };
#if configINCLUDE_DEMO_DEBUG_STATS != 0 #if configINCLUDE_DEMO_DEBUG_STATS != 0
/* Structure that defines the "ip-debug-stats" command line command. */ /* Structure that defines the "ip-debug-stats" command line command. */
static const CLI_Command_Definition_t xIPDebugStats = static const CLI_Command_Definition_t xIPDebugStats =
{ {
"ip-debug-stats", /* The command string to type. */ "ip-debug-stats", /* The command string to type. */
"ip-debug-stats:\r\n Shows some IP stack stats useful for debug - an example only.\r\n\r\n", "ip-debug-stats:\r\n Shows some IP stack stats useful for debug - an example only.\r\n\r\n",
prvDisplayIPDebugStats, /* The function to run. */ prvDisplayIPDebugStats, /* The function to run. */
0 /* No parameters are expected. */ 0 /* No parameters are expected. */
}; };
#endif /* configINCLUDE_DEMO_DEBUG_STATS */ #endif /* configINCLUDE_DEMO_DEBUG_STATS */
#if ipconfigSUPPORT_OUTGOING_PINGS == 1 #if ipconfigSUPPORT_OUTGOING_PINGS == 1
/* Structure that defines the "ping" command line command. This takes an IP /* Structure that defines the "ping" command line command. This takes an IP
address or host name and (optionally) the number of bytes to ping as * address or host name and (optionally) the number of bytes to ping as
parameters. */ * parameters. */
static const CLI_Command_Definition_t xPing = static const CLI_Command_Definition_t xPing =
{ {
"ping", "ping",
"ping <ipaddress> <optional:bytes to send>:\r\n for example, ping 192.168.0.3 8, or ping www.example.com\r\n\r\n", "ping <ipaddress> <optional:bytes to send>:\r\n for example, ping 192.168.0.3 8, or ping www.example.com\r\n\r\n",
prvPingCommand, /* The function to run. */ prvPingCommand, /* The function to run. */
-1 /* Ping can take either one or two parameter, so the number of parameters has to be determined by the ping command implementation. */ -1 /* Ping can take either one or two parameter, so the number of parameters has to be determined by the ping command implementation. */
}; };
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
@ -104,225 +110,230 @@ static const CLI_Command_Definition_t xIPConfig =
void vRegisterUDPCLICommands( void ) void vRegisterUDPCLICommands( void )
{ {
/* Register all the command line commands defined immediately above. */ /* Register all the command line commands defined immediately above. */
FreeRTOS_CLIRegisterCommand( &xIPConfig ); FreeRTOS_CLIRegisterCommand( &xIPConfig );
#if configINCLUDE_DEMO_DEBUG_STATS == 1 #if configINCLUDE_DEMO_DEBUG_STATS == 1
{ {
FreeRTOS_CLIRegisterCommand( &xIPDebugStats ); FreeRTOS_CLIRegisterCommand( &xIPDebugStats );
} }
#endif /* configINCLUDE_DEMO_DEBUG_STATS */ #endif /* configINCLUDE_DEMO_DEBUG_STATS */
#if ipconfigSUPPORT_OUTGOING_PINGS == 1 #if ipconfigSUPPORT_OUTGOING_PINGS == 1
{ {
FreeRTOS_CLIRegisterCommand( &xPing ); FreeRTOS_CLIRegisterCommand( &xPing );
} }
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ipconfigSUPPORT_OUTGOING_PINGS == 1 #if ipconfigSUPPORT_OUTGOING_PINGS == 1
static BaseType_t prvPingCommand( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvPingCommand( char * pcWriteBuffer,
{ size_t xWriteBufferLen,
char * pcParameter; const char * pcCommandString )
BaseType_t lParameterStringLength, xReturn; {
uint32_t ulIPAddress, ulBytesToPing; char * pcParameter;
const uint32_t ulDefaultBytesToPing = 8UL; BaseType_t lParameterStringLength, xReturn;
char cBuffer[ 16 ]; uint32_t ulIPAddress, ulBytesToPing;
const uint32_t ulDefaultBytesToPing = 8UL;
char cBuffer[ 16 ];
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
/* Start with an empty string. */ /* Start with an empty string. */
pcWriteBuffer[ 0 ] = 0x00; pcWriteBuffer[ 0 ] = 0x00;
/* Obtain the number of bytes to ping. */ /* Obtain the number of bytes to ping. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter pcParameter = ( char * ) FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
2, /* Return the second parameter. */ 2, /* Return the second parameter. */
&lParameterStringLength /* Store the parameter string length. */ &lParameterStringLength /* Store the parameter string length. */
); );
if( pcParameter == NULL ) if( pcParameter == NULL )
{ {
/* The number of bytes was not specified, so default it. */ /* The number of bytes was not specified, so default it. */
ulBytesToPing = ulDefaultBytesToPing; ulBytesToPing = ulDefaultBytesToPing;
} }
else else
{ {
ulBytesToPing = atol( pcParameter ); ulBytesToPing = atol( pcParameter );
} }
/* Obtain the IP address string. */ /* Obtain the IP address string. */
pcParameter = ( char * ) FreeRTOS_CLIGetParameter pcParameter = ( char * ) FreeRTOS_CLIGetParameter
( (
pcCommandString, /* The command string itself. */ pcCommandString, /* The command string itself. */
1, /* Return the first parameter. */ 1, /* Return the first parameter. */
&lParameterStringLength /* Store the parameter string length. */ &lParameterStringLength /* Store the parameter string length. */
); );
/* Sanity check something was returned. */ /* Sanity check something was returned. */
configASSERT( pcParameter ); configASSERT( pcParameter );
/* Attempt to obtain the IP address. If the first character is not a /* Attempt to obtain the IP address. If the first character is not a
digit, assume the host name has been passed in. */ * digit, assume the host name has been passed in. */
if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) ) if( ( *pcParameter >= '0' ) && ( *pcParameter <= '9' ) )
{ {
ulIPAddress = FreeRTOS_inet_addr( pcParameter ); ulIPAddress = FreeRTOS_inet_addr( pcParameter );
} }
else else
{ {
/* Terminate the host name. */ /* Terminate the host name. */
pcParameter[ lParameterStringLength ] = 0x00; pcParameter[ lParameterStringLength ] = 0x00;
/* Attempt to resolve host. */ /* Attempt to resolve host. */
ulIPAddress = FreeRTOS_gethostbyname( pcParameter ); ulIPAddress = FreeRTOS_gethostbyname( pcParameter );
} }
/* Convert IP address, which may have come from a DNS lookup, to string. */ /* Convert IP address, which may have come from a DNS lookup, to string. */
FreeRTOS_inet_ntoa( ulIPAddress, cBuffer ); FreeRTOS_inet_ntoa( ulIPAddress, cBuffer );
if( ulIPAddress != 0 ) if( ulIPAddress != 0 )
{ {
xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY ); xReturn = FreeRTOS_SendPingRequest( ulIPAddress, ( uint16_t ) ulBytesToPing, portMAX_DELAY );
} }
else else
{ {
xReturn = pdFALSE; xReturn = pdFALSE;
} }
if( xReturn == pdFALSE ) if( xReturn == pdFALSE )
{ {
sprintf( pcWriteBuffer, "%s", "Could not send ping request\r\n" ); sprintf( pcWriteBuffer, "%s", "Could not send ping request\r\n" );
} }
else else
{ {
sprintf( pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, ( int ) xReturn ); sprintf( pcWriteBuffer, "Ping sent to %s with identifier %d\r\n", cBuffer, ( int ) xReturn );
} }
return pdFALSE; return pdFALSE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* ipconfigSUPPORT_OUTGOING_PINGS */ #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
#if configINCLUDE_DEMO_DEBUG_STATS != 0 #if configINCLUDE_DEMO_DEBUG_STATS != 0
static BaseType_t prvDisplayIPDebugStats( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvDisplayIPDebugStats( char * pcWriteBuffer,
{ size_t xWriteBufferLen,
static BaseType_t xIndex = -1; const char * pcCommandString )
extern xExampleDebugStatEntry_t xIPTraceValues[]; {
BaseType_t xReturn; static BaseType_t xIndex = -1;
extern xExampleDebugStatEntry_t xIPTraceValues[];
BaseType_t xReturn;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
xIndex++; xIndex++;
if( xIndex < xExampleDebugStatEntries() ) if( xIndex < xExampleDebugStatEntries() )
{ {
sprintf( pcWriteBuffer, "%s %d\r\n", ( char * ) xIPTraceValues[ xIndex ].pucDescription, ( int ) xIPTraceValues[ xIndex ].ulData ); sprintf( pcWriteBuffer, "%s %d\r\n", ( char * ) xIPTraceValues[ xIndex ].pucDescription, ( int ) xIPTraceValues[ xIndex ].ulData );
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
{ {
/* Reset the index for the next time it is called. */ /* Reset the index for the next time it is called. */
xIndex = -1; xIndex = -1;
/* Ensure nothing remains in the write buffer. */ /* Ensure nothing remains in the write buffer. */
pcWriteBuffer[ 0 ] = 0x00; pcWriteBuffer[ 0 ] = 0x00;
xReturn = pdFALSE; xReturn = pdFALSE;
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* configINCLUDE_DEMO_DEBUG_STATS */ #endif /* configINCLUDE_DEMO_DEBUG_STATS */
static BaseType_t prvDisplayIPConfig( char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString ) static BaseType_t prvDisplayIPConfig( char * pcWriteBuffer,
size_t xWriteBufferLen,
const char * pcCommandString )
{ {
static BaseType_t xIndex = 0; static BaseType_t xIndex = 0;
BaseType_t xReturn; BaseType_t xReturn;
uint32_t ulAddress; uint32_t ulAddress;
/* Remove compile time warnings about unused parameters, and check the /* Remove compile time warnings about unused parameters, and check the
write buffer is not NULL. NOTE - for simplicity, this example assumes the * write buffer is not NULL. NOTE - for simplicity, this example assumes the
write buffer length is adequate, so does not check for buffer overflows. */ * write buffer length is adequate, so does not check for buffer overflows. */
( void ) pcCommandString; ( void ) pcCommandString;
( void ) xWriteBufferLen; ( void ) xWriteBufferLen;
configASSERT( pcWriteBuffer ); configASSERT( pcWriteBuffer );
switch( xIndex ) switch( xIndex )
{ {
case 0 : case 0:
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
FreeRTOS_GetEndPointConfiguration( &ulAddress, NULL, NULL, NULL, pxNetworkEndPoints ); FreeRTOS_GetEndPointConfiguration( &ulAddress, NULL, NULL, NULL, pxNetworkEndPoints );
#else #else
FreeRTOS_GetAddressConfiguration( &ulAddress, NULL, NULL, NULL ); FreeRTOS_GetAddressConfiguration( &ulAddress, NULL, NULL, NULL );
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
sprintf( pcWriteBuffer, "\r\nIP address " ); sprintf( pcWriteBuffer, "\r\nIP address " );
xReturn = pdTRUE; xReturn = pdTRUE;
xIndex++; xIndex++;
break; break;
case 1 : case 1:
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
FreeRTOS_GetEndPointConfiguration( NULL, &ulAddress, NULL, NULL, pxNetworkEndPoints ); FreeRTOS_GetEndPointConfiguration( NULL, &ulAddress, NULL, NULL, pxNetworkEndPoints );
#else #else
FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL ); FreeRTOS_GetAddressConfiguration( NULL, &ulAddress, NULL, NULL );
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
sprintf( pcWriteBuffer, "\r\nNet mask " ); sprintf( pcWriteBuffer, "\r\nNet mask " );
xReturn = pdTRUE; xReturn = pdTRUE;
xIndex++; xIndex++;
break; break;
case 2 : case 2:
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
FreeRTOS_GetEndPointConfiguration( NULL, NULL, &ulAddress, NULL, pxNetworkEndPoints ); FreeRTOS_GetEndPointConfiguration( NULL, NULL, &ulAddress, NULL, pxNetworkEndPoints );
#else #else
FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL ); FreeRTOS_GetAddressConfiguration( NULL, NULL, &ulAddress, NULL );
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
sprintf( pcWriteBuffer, "\r\nGateway address " ); sprintf( pcWriteBuffer, "\r\nGateway address " );
xReturn = pdTRUE; xReturn = pdTRUE;
xIndex++; xIndex++;
break; break;
case 3 : case 3:
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
FreeRTOS_GetEndPointConfiguration( NULL, NULL, NULL, &ulAddress, pxNetworkEndPoints ); FreeRTOS_GetEndPointConfiguration( NULL, NULL, NULL, &ulAddress, pxNetworkEndPoints );
#else #else
FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress ); FreeRTOS_GetAddressConfiguration( NULL, NULL, NULL, &ulAddress );
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
sprintf( pcWriteBuffer, "\r\nDNS server address " ); sprintf( pcWriteBuffer, "\r\nDNS server address " );
xReturn = pdTRUE; xReturn = pdTRUE;
xIndex++; xIndex++;
break; break;
default : default:
ulAddress = 0; ulAddress = 0;
sprintf( pcWriteBuffer, "\r\n\r\n" ); sprintf( pcWriteBuffer, "\r\n\r\n" );
xReturn = pdFALSE; xReturn = pdFALSE;
xIndex = 0; xIndex = 0;
break; break;
} }
if( ulAddress != 0 ) if( ulAddress != 0 )
{ {
FreeRTOS_inet_ntoa( ulAddress, ( &( pcWriteBuffer[ strlen( pcWriteBuffer ) ] ) ) ); FreeRTOS_inet_ntoa( ulAddress, ( &( pcWriteBuffer[ strlen( pcWriteBuffer ) ] ) ) );
} }
return xReturn; return xReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,7 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
@ -41,13 +41,13 @@
#include "api_mdriver_ram.h" #include "api_mdriver_ram.h"
/* 8.3 format, plus null terminator. */ /* 8.3 format, plus null terminator. */
#define fsMAX_FILE_NAME_LEN 13 #define fsMAX_FILE_NAME_LEN 13
/* The number of bytes read/written to the example files at a time. */ /* The number of bytes read/written to the example files at a time. */
#define fsRAM_BUFFER_SIZE 200 #define fsRAM_BUFFER_SIZE 200
/* The number of bytes written to the file that uses f_putc() and f_getc(). */ /* The number of bytes written to the file that uses f_putc() and f_getc(). */
#define fsPUTC_FILE_SIZE 100 #define fsPUTC_FILE_SIZE 100
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -83,238 +83,234 @@ static void prvVerifyDemoFileUsing_f_getc( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A buffer used to both create content to write to disk, and read content back /* A buffer used to both create content to write to disk, and read content back
from a disk. Note there is no mutual exclusion on this buffer. */ * from a disk. Note there is no mutual exclusion on this buffer. */
static char cRAMBuffer[ fsRAM_BUFFER_SIZE ]; static char cRAMBuffer[ fsRAM_BUFFER_SIZE ];
/* Names of directories that are created. */ /* Names of directories that are created. */
static const char *pcRoot = "/", *pcDirectory1 = "SUB1", *pcDirectory2 = "SUB2", *pcFullPath = "/SUB1/SUB2"; static const char * pcRoot = "/", * pcDirectory1 = "SUB1", * pcDirectory2 = "SUB2", * pcFullPath = "/SUB1/SUB2";
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vCreateAndVerifySampleFiles( void ) void vCreateAndVerifySampleFiles( void )
{ {
unsigned char ucStatus; unsigned char ucStatus;
/* First create the volume. */ /* First create the volume. */
ucStatus = f_initvolume( ram_initfunc ); ucStatus = f_initvolume( ram_initfunc );
/* It is expected that the volume is not formatted. */ /* It is expected that the volume is not formatted. */
if( ucStatus == F_ERR_NOTFORMATTED ) if( ucStatus == F_ERR_NOTFORMATTED )
{ {
/* Format the created volume. */ /* Format the created volume. */
ucStatus = f_format( F_FAT12_MEDIA ); ucStatus = f_format( F_FAT12_MEDIA );
} }
if( ucStatus == F_NO_ERROR ) if( ucStatus == F_NO_ERROR )
{ {
/* Create a set of files using f_write(). */ /* Create a set of files using f_write(). */
prvCreateDemoFilesUsing_f_write(); prvCreateDemoFilesUsing_f_write();
/* Read back and verify the files that were created using f_write(). */ /* Read back and verify the files that were created using f_write(). */
prvVerifyDemoFileUsing_f_read(); prvVerifyDemoFileUsing_f_read();
/* Create sub directories two deep then create a file using putc. */ /* Create sub directories two deep then create a file using putc. */
prvCreateDemoFileUsing_f_putc(); prvCreateDemoFileUsing_f_putc();
/* Read back and verify the file created by /* Read back and verify the file created by
prvCreateDemoFileUsing_f_putc(). */ * prvCreateDemoFileUsing_f_putc(). */
prvVerifyDemoFileUsing_f_getc(); prvVerifyDemoFileUsing_f_getc();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCreateDemoFilesUsing_f_write( void ) static void prvCreateDemoFilesUsing_f_write( void )
{ {
BaseType_t xFileNumber, xWriteNumber; BaseType_t xFileNumber, xWriteNumber;
char cFileName[ fsMAX_FILE_NAME_LEN ]; char cFileName[ fsMAX_FILE_NAME_LEN ];
const BaseType_t xMaxFiles = 5; const BaseType_t xMaxFiles = 5;
long lItemsWritten; long lItemsWritten;
F_FILE *pxFile; F_FILE * pxFile;
/* Create xMaxFiles files. Each created file will be /* Create xMaxFiles files. Each created file will be
( xFileNumber * fsRAM_BUFFER_SIZE ) bytes in length, and filled * ( xFileNumber * fsRAM_BUFFER_SIZE ) bytes in length, and filled
with a different repeating character. */ * with a different repeating character. */
for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ ) for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ )
{ {
/* Generate a file name. */ /* Generate a file name. */
sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber ); sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber );
/* Obtain the current working directory and print out the file name and /* Obtain the current working directory and print out the file name and
the directory into which the file is being written. */ * the directory into which the file is being written. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Open the file, creating the file if it does not already exist. */ /* Open the file, creating the file if it does not already exist. */
pxFile = f_open( cFileName, "w" ); pxFile = f_open( cFileName, "w" );
configASSERT( pxFile ); configASSERT( pxFile );
/* Fill the RAM buffer with data that will be written to the file. This /* Fill the RAM buffer with data that will be written to the file. This
is just a repeating ascii character that indicates the file number. */ * is just a repeating ascii character that indicates the file number. */
memset( cRAMBuffer, ( int ) ( '0' + xFileNumber ), fsRAM_BUFFER_SIZE ); memset( cRAMBuffer, ( int ) ( '0' + xFileNumber ), fsRAM_BUFFER_SIZE );
/* Write the RAM buffer to the opened file a number of times. The /* Write the RAM buffer to the opened file a number of times. The
number of times the RAM buffer is written to the file depends on the * number of times the RAM buffer is written to the file depends on the
file number, so the length of each created file will be different. */ * file number, so the length of each created file will be different. */
for( xWriteNumber = 0; xWriteNumber < xFileNumber; xWriteNumber++ ) for( xWriteNumber = 0; xWriteNumber < xFileNumber; xWriteNumber++ )
{ {
lItemsWritten = f_write( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile ); lItemsWritten = f_write( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile );
configASSERT( lItemsWritten == 1 ); configASSERT( lItemsWritten == 1 );
} }
/* Close the file so another file can be created. */ /* Close the file so another file can be created. */
f_close( pxFile ); f_close( pxFile );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvVerifyDemoFileUsing_f_read( void ) static void prvVerifyDemoFileUsing_f_read( void )
{ {
BaseType_t xFileNumber, xReadNumber; BaseType_t xFileNumber, xReadNumber;
char cFileName[ fsMAX_FILE_NAME_LEN ]; char cFileName[ fsMAX_FILE_NAME_LEN ];
const BaseType_t xMaxFiles = 5; const BaseType_t xMaxFiles = 5;
long lItemsRead, lChar; long lItemsRead, lChar;
F_FILE *pxFile; F_FILE * pxFile;
/* Read back the files that were created by /* Read back the files that were created by
prvCreateDemoFilesUsing_f_write(). */ * prvCreateDemoFilesUsing_f_write(). */
for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ ) for( xFileNumber = 1; xFileNumber <= xMaxFiles; xFileNumber++ )
{ {
/* Generate the file name. */ /* Generate the file name. */
sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber ); sprintf( cFileName, "root%03d.txt", ( int ) xFileNumber );
/* Obtain the current working directory and print out the file name and /* Obtain the current working directory and print out the file name and
the directory from which the file is being read. */ * the directory from which the file is being read. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Open the file for reading. */ /* Open the file for reading. */
pxFile = f_open( cFileName, "r" ); pxFile = f_open( cFileName, "r" );
configASSERT( pxFile ); configASSERT( pxFile );
/* Read the file into the RAM buffer, checking the file contents are as /* Read the file into the RAM buffer, checking the file contents are as
expected. The size of the file depends on the file number. */ * expected. The size of the file depends on the file number. */
for( xReadNumber = 0; xReadNumber < xFileNumber; xReadNumber++ ) for( xReadNumber = 0; xReadNumber < xFileNumber; xReadNumber++ )
{ {
/* Start with the RAM buffer clear. */ /* Start with the RAM buffer clear. */
memset( cRAMBuffer, 0x00, fsRAM_BUFFER_SIZE ); memset( cRAMBuffer, 0x00, fsRAM_BUFFER_SIZE );
lItemsRead = f_read( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile ); lItemsRead = f_read( cRAMBuffer, fsRAM_BUFFER_SIZE, 1, pxFile );
configASSERT( lItemsRead == 1 ); configASSERT( lItemsRead == 1 );
/* Check the RAM buffer is filled with the expected data. Each /* Check the RAM buffer is filled with the expected data. Each
file contains a different repeating ascii character that indicates * file contains a different repeating ascii character that indicates
the number of the file. */ * the number of the file. */
for( lChar = 0; lChar < fsRAM_BUFFER_SIZE; lChar++ ) for( lChar = 0; lChar < fsRAM_BUFFER_SIZE; lChar++ )
{ {
configASSERT( cRAMBuffer[ lChar ] == ( '0' + ( char ) xFileNumber ) ); configASSERT( cRAMBuffer[ lChar ] == ( '0' + ( char ) xFileNumber ) );
} }
} }
/* Close the file. */ /* Close the file. */
f_close( pxFile ); f_close( pxFile );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvCreateDemoFileUsing_f_putc( void ) static void prvCreateDemoFileUsing_f_putc( void )
{ {
unsigned char ucReturn; unsigned char ucReturn;
int iByte, iReturned; int iByte, iReturned;
F_FILE *pxFile; F_FILE * pxFile;
char cFileName[ fsMAX_FILE_NAME_LEN ]; char cFileName[ fsMAX_FILE_NAME_LEN ];
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Create a sub directory. */ /* Create a sub directory. */
ucReturn = f_mkdir( pcDirectory1 ); ucReturn = f_mkdir( pcDirectory1 );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Move into the created sub-directory. */ /* Move into the created sub-directory. */
ucReturn = f_chdir( pcDirectory1 ); ucReturn = f_chdir( pcDirectory1 );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
/* Create a subdirectory in the new directory. */ /* Create a subdirectory in the new directory. */
ucReturn = f_mkdir( pcDirectory2 ); ucReturn = f_mkdir( pcDirectory2 );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Move into the directory just created - now two directories down from /* Move into the directory just created - now two directories down from
the root. */ * the root. */
ucReturn = f_chdir( pcDirectory2 ); ucReturn = f_chdir( pcDirectory2 );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 ); configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 );
/* Generate the file name. */ /* Generate the file name. */
sprintf( cFileName, "%s.txt", pcDirectory2 ); sprintf( cFileName, "%s.txt", pcDirectory2 );
/* Print out the file name and the directory into which the file is being /* Print out the file name and the directory into which the file is being
written. */ * written. */
pxFile = f_open( cFileName, "w" ); pxFile = f_open( cFileName, "w" );
/* Create a file 1 byte at a time. The file is filled with incrementing /* Create a file 1 byte at a time. The file is filled with incrementing
ascii characters starting from '0'. */ * ascii characters starting from '0'. */
for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ ) for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ )
{ {
iReturned = f_putc( ( ( int ) '0' + iByte ), pxFile ); iReturned = f_putc( ( ( int ) '0' + iByte ), pxFile );
configASSERT( iReturned == ( ( int ) '0' + iByte ) ); configASSERT( iReturned == ( ( int ) '0' + iByte ) );
} }
/* Finished so close the file. */ /* Finished so close the file. */
f_close( pxFile ); f_close( pxFile );
/* Move back to the root directory. */ /* Move back to the root directory. */
ucReturn = f_chdir( "../.." ); ucReturn = f_chdir( "../.." );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcRoot ) == 0 ); configASSERT( strcmp( cRAMBuffer, pcRoot ) == 0 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvVerifyDemoFileUsing_f_getc( void ) static void prvVerifyDemoFileUsing_f_getc( void )
{ {
unsigned char ucReturn; unsigned char ucReturn;
int iByte, iReturned; int iByte, iReturned;
F_FILE *pxFile; F_FILE * pxFile;
char cFileName[ fsMAX_FILE_NAME_LEN ]; char cFileName[ fsMAX_FILE_NAME_LEN ];
/* Move into the directory in which the file was created. */ /* Move into the directory in which the file was created. */
ucReturn = f_chdir( pcFullPath ); ucReturn = f_chdir( pcFullPath );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 ); configASSERT( strcmp( cRAMBuffer, pcFullPath ) == 0 );
/* Generate the file name. */ /* Generate the file name. */
sprintf( cFileName, "%s.txt", pcDirectory2 ); sprintf( cFileName, "%s.txt", pcDirectory2 );
/* This time the file is opened for reading. */ /* This time the file is opened for reading. */
pxFile = f_open( cFileName, "r" ); pxFile = f_open( cFileName, "r" );
/* Read the file 1 byte at a time. */ /* Read the file 1 byte at a time. */
for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ ) for( iByte = 0; iByte < fsPUTC_FILE_SIZE; iByte++ )
{ {
iReturned = f_getc( pxFile ); iReturned = f_getc( pxFile );
configASSERT( iReturned == ( ( int ) '0' + iByte ) ); configASSERT( iReturned == ( ( int ) '0' + iByte ) );
} }
/* Finished so close the file. */ /* Finished so close the file. */
f_close( pxFile ); f_close( pxFile );
/* Move back to the root directory. */ /* Move back to the root directory. */
ucReturn = f_chdir( "../.." ); ucReturn = f_chdir( "../.." );
configASSERT( ucReturn == F_NO_ERROR ); configASSERT( ucReturn == F_NO_ERROR );
/* Obtain and print out the working directory. */ /* Obtain and print out the working directory. */
f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE ); f_getcwd( cRAMBuffer, fsRAM_BUFFER_SIZE );
} }

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,13 +20,15 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
#ifndef UDP_COMMAND_INTERPRETER_H #ifndef UDP_COMMAND_INTERPRETER_H
#define UDP_COMMAND_INTERPRETER_H #define UDP_COMMAND_INTERPRETER_H
void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority ); void vStartUDPCommandInterpreterTask( uint16_t usStackSize,
uint32_t ulPort,
UBaseType_t uxPriority );
#endif /* UDP_COMMAND_INTERPRETER_H */ #endif /* UDP_COMMAND_INTERPRETER_H */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -43,18 +43,18 @@
#include "UDPCommandInterpreter.h" #include "UDPCommandInterpreter.h"
/* Dimensions the buffer into which input characters are placed. */ /* Dimensions the buffer into which input characters are placed. */
#define cmdMAX_INPUT_SIZE 60 #define cmdMAX_INPUT_SIZE 60
/* Dimensions the buffer into which string outputs can be placed. */ /* Dimensions the buffer into which string outputs can be placed. */
#define cmdMAX_OUTPUT_SIZE 1250 #define cmdMAX_OUTPUT_SIZE 1250
/* Dimensions the buffer passed to the recvfrom() call. */ /* Dimensions the buffer passed to the recvfrom() call. */
#define cmdSOCKET_INPUT_BUFFER_SIZE 60 #define cmdSOCKET_INPUT_BUFFER_SIZE 60
/* /*
* The task that runs FreeRTOS+CLI. * The task that runs FreeRTOS+CLI.
*/ */
void vUDPCommandInterpreterTask( void *pvParameters ); void vUDPCommandInterpreterTask( void * pvParameters );
/* /*
* Open and configure the UDP socket. * Open and configure the UDP socket.
@ -63,9 +63,11 @@ static xSocket_t prvOpenUDPServerSocket( uint16_t usPort );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, UBaseType_t uxPriority ) void vStartUDPCommandInterpreterTask( uint16_t usStackSize,
uint32_t ulPort,
UBaseType_t uxPriority )
{ {
xTaskCreate( vUDPCommandInterpreterTask, "CLI", usStackSize, ( void * ) ulPort, uxPriority, NULL ); xTaskCreate( vUDPCommandInterpreterTask, "CLI", usStackSize, ( void * ) ulPort, uxPriority, NULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -74,133 +76,132 @@ void vStartUDPCommandInterpreterTask( uint16_t usStackSize, uint32_t ulPort, UBa
* interpreter. In this case a UDP port is used. See the URL in the comments * interpreter. In this case a UDP port is used. See the URL in the comments
* within main.c for the location of the online documentation. * within main.c for the location of the online documentation.
*/ */
void vUDPCommandInterpreterTask( void *pvParameters ) void vUDPCommandInterpreterTask( void * pvParameters )
{ {
long lBytes, lByte; long lBytes, lByte;
signed char cInChar, cInputIndex = 0; signed char cInChar, cInputIndex = 0;
static char cInputString[ cmdMAX_INPUT_SIZE ], cOutputString[ cmdMAX_OUTPUT_SIZE ], cLocalBuffer[ cmdSOCKET_INPUT_BUFFER_SIZE ]; static char cInputString[ cmdMAX_INPUT_SIZE ], cOutputString[ cmdMAX_OUTPUT_SIZE ], cLocalBuffer[ cmdSOCKET_INPUT_BUFFER_SIZE ];
BaseType_t xMoreDataToFollow; BaseType_t xMoreDataToFollow;
struct freertos_sockaddr xClient; struct freertos_sockaddr xClient;
socklen_t xClientAddressLength = 0; /* This is required as a parameter to maintain the sendto() Berkeley sockets API - but it is not actually used so can take any value. */ socklen_t xClientAddressLength = 0; /* This is required as a parameter to maintain the sendto() Berkeley sockets API - but it is not actually used so can take any value. */
xSocket_t xSocket; xSocket_t xSocket;
/* Just to prevent compiler warnings. */ /* Just to prevent compiler warnings. */
( void ) pvParameters; ( void ) pvParameters;
/* Attempt to open the socket. The port number is passed in the task /* Attempt to open the socket. The port number is passed in the task
parameter. The strange casting is to remove compiler warnings on 32-bit * parameter. The strange casting is to remove compiler warnings on 32-bit
machines. */ * machines. */
xSocket = prvOpenUDPServerSocket( ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL ); xSocket = prvOpenUDPServerSocket( ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL );
if( xSocket != FREERTOS_INVALID_SOCKET ) if( xSocket != FREERTOS_INVALID_SOCKET )
{ {
for( ;; ) for( ; ; )
{ {
/* Wait for incoming data on the opened socket. */ /* Wait for incoming data on the opened socket. */
lBytes = FreeRTOS_recvfrom( xSocket, ( void * ) cLocalBuffer, sizeof( cLocalBuffer ), 0, &xClient, &xClientAddressLength ); lBytes = FreeRTOS_recvfrom( xSocket, ( void * ) cLocalBuffer, sizeof( cLocalBuffer ), 0, &xClient, &xClientAddressLength );
if( lBytes != FREERTOS_SOCKET_ERROR ) if( lBytes != FREERTOS_SOCKET_ERROR )
{ {
/* Process each received byte in turn. */ /* Process each received byte in turn. */
lByte = 0; lByte = 0;
while( lByte < lBytes )
{
/* The next character in the input buffer. */
cInChar = cLocalBuffer[ lByte ];
lByte++;
/* Newline characters are taken as the end of the command while( lByte < lBytes )
string. */ {
if( cInChar == '\n' ) /* The next character in the input buffer. */
{ cInChar = cLocalBuffer[ lByte ];
/* Process the input string received prior to the lByte++;
newline. */
do
{
/* Pass the string to FreeRTOS+CLI. */
xMoreDataToFollow = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, cmdMAX_OUTPUT_SIZE );
/* Send the output generated by the command's /* Newline characters are taken as the end of the command
implementation. */ * string. */
FreeRTOS_sendto( xSocket, cOutputString, strlen( cOutputString ), 0, &xClient, xClientAddressLength ); if( cInChar == '\n' )
{
/* Process the input string received prior to the
* newline. */
do
{
/* Pass the string to FreeRTOS+CLI. */
xMoreDataToFollow = FreeRTOS_CLIProcessCommand( cInputString, cOutputString, cmdMAX_OUTPUT_SIZE );
} while( xMoreDataToFollow != pdFALSE ); /* Until the command does not generate any more output. */ /* Send the output generated by the command's
* implementation. */
FreeRTOS_sendto( xSocket, cOutputString, strlen( cOutputString ), 0, &xClient, xClientAddressLength );
} while( xMoreDataToFollow != pdFALSE ); /* Until the command does not generate any more output. */
/* All the strings generated by the command processing /* All the strings generated by the command processing
have been sent. Clear the input string ready to receive * have been sent. Clear the input string ready to receive
the next command. */ * the next command. */
cInputIndex = 0; cInputIndex = 0;
memset( cInputString, 0x00, cmdMAX_INPUT_SIZE ); memset( cInputString, 0x00, cmdMAX_INPUT_SIZE );
/* Transmit a spacer, just to make the command console /* Transmit a spacer, just to make the command console
easier to read. */ * easier to read. */
FreeRTOS_sendto( xSocket, "\r\n", strlen( "\r\n" ), 0, &xClient, xClientAddressLength ); FreeRTOS_sendto( xSocket, "\r\n", strlen( "\r\n" ), 0, &xClient, xClientAddressLength );
} }
else else
{ {
if( cInChar == '\r' ) if( cInChar == '\r' )
{ {
/* Ignore the character. Newlines are used to /* Ignore the character. Newlines are used to
detect the end of the input string. */ * detect the end of the input string. */
} }
else if( cInChar == '\b' ) else if( cInChar == '\b' )
{ {
/* Backspace was pressed. Erase the last character /* Backspace was pressed. Erase the last character
in the string - if any. */ * in the string - if any. */
if( cInputIndex > 0 ) if( cInputIndex > 0 )
{ {
cInputIndex--; cInputIndex--;
cInputString[ cInputIndex ] = '\0'; cInputString[ cInputIndex ] = '\0';
} }
} }
else else
{ {
/* A character was entered. Add it to the string /* A character was entered. Add it to the string
entered so far. When a \n is entered the complete * entered so far. When a \n is entered the complete
string will be passed to the command interpreter. */ * string will be passed to the command interpreter. */
if( cInputIndex < cmdMAX_INPUT_SIZE ) if( cInputIndex < cmdMAX_INPUT_SIZE )
{ {
cInputString[ cInputIndex ] = cInChar; cInputString[ cInputIndex ] = cInChar;
cInputIndex++; cInputIndex++;
} }
} }
} }
} }
} }
} }
} }
else else
{ {
/* The socket could not be opened. */ /* The socket could not be opened. */
vTaskDelete( NULL ); vTaskDelete( NULL );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static xSocket_t prvOpenUDPServerSocket( uint16_t usPort ) static xSocket_t prvOpenUDPServerSocket( uint16_t usPort )
{ {
struct freertos_sockaddr xServer; struct freertos_sockaddr xServer;
xSocket_t xSocket = FREERTOS_INVALID_SOCKET; xSocket_t xSocket = FREERTOS_INVALID_SOCKET;
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
if( xSocket != FREERTOS_INVALID_SOCKET)
{
/* Zero out the server structure. */
memset( ( void * ) &xServer, 0x00, sizeof( xServer ) );
/* Set family and port. */ if( xSocket != FREERTOS_INVALID_SOCKET )
xServer.sin_port = FreeRTOS_htons( usPort ); {
xServer.sin_family = FREERTOS_AF_INET; /* Zero out the server structure. */
memset( ( void * ) &xServer, 0x00, sizeof( xServer ) );
/* Bind the address to the socket. */ /* Set family and port. */
if( FreeRTOS_bind( xSocket, &xServer, sizeof( xServer ) ) == -1 ) xServer.sin_port = FreeRTOS_htons( usPort );
{ xServer.sin_family = FREERTOS_AF_INET;
FreeRTOS_closesocket( xSocket );
xSocket = FREERTOS_INVALID_SOCKET;
}
}
return xSocket; /* Bind the address to the socket. */
if( FreeRTOS_bind( xSocket, &xServer, sizeof( xServer ) ) == -1 )
{
FreeRTOS_closesocket( xSocket );
xSocket = FREERTOS_INVALID_SOCKET;
}
}
return xSocket;
} }

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -26,12 +26,12 @@
/****************************************************************************** /******************************************************************************
* *
* See the following web page for essential TwoEchoClient.c usage and * See the following web page for essential TwoEchoClient.c usage and
* configuration details: * configuration details:
* https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Common_Echo_Clients.shtml * https://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Examples/Common_Echo_Clients.shtml
* *
******************************************************************************/ ******************************************************************************/
/* Standard includes. */ /* Standard includes. */
@ -48,339 +48,341 @@
#include "FreeRTOS_Sockets.h" #include "FreeRTOS_Sockets.h"
/* Small delay used between attempts to obtain a zero copy buffer. */ /* Small delay used between attempts to obtain a zero copy buffer. */
#define echoTINY_DELAY ( ( TickType_t ) 2 ) #define echoTINY_DELAY ( ( TickType_t ) 2 )
/* The echo tasks create a socket, send out a number of echo requests /* The echo tasks create a socket, send out a number of echo requests
(listening for each echo reply), then close the socket again before * (listening for each echo reply), then close the socket again before
starting over. This delay is used between each iteration to ensure the * starting over. This delay is used between each iteration to ensure the
network does not get too congested. */ * network does not get too congested. */
#define echoLOOP_DELAY ( ( TickType_t ) 250 / portTICK_RATE_MS ) #define echoLOOP_DELAY ( ( TickType_t ) 250 / portTICK_RATE_MS )
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 #if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
/* When the trace recorder code is included user events are generated to
mark the sending and receiving of the echoed data (only in the zero copy /* When the trace recorder code is included user events are generated to
task. */ * mark the sending and receiving of the echoed data (only in the zero copy
#define echoMARK_SEND_IN_TRACE_BUFFER( x ) vTraceUserEvent( x ) * task. */
traceLabel xZeroCopySendEvent, xZeroCopyReceiveEvent; #define echoMARK_SEND_IN_TRACE_BUFFER( x ) vTraceUserEvent( x )
traceLabel xZeroCopySendEvent, xZeroCopyReceiveEvent;
#else #else
/* When the trace recorder code is not included just #define away the call
to post the user event. */ /* When the trace recorder code is not included just #define away the call
#define echoMARK_SEND_IN_TRACE_BUFFER( x ) * to post the user event. */
#define xZeroCopySendEvent 0 #define echoMARK_SEND_IN_TRACE_BUFFER( x )
#define xZeroCopyReceiveEvent 0 #define xZeroCopySendEvent 0
#define xZeroCopyReceiveEvent 0
#endif #endif
/* The echo server is assumed to be on port 7, which is the standard echo /* The echo server is assumed to be on port 7, which is the standard echo
protocol port. */ * protocol port. */
#define echoECHO_PORT ( 7 ) #define echoECHO_PORT ( 7 )
/* /*
* Uses a socket to send data to, then receive data from, the standard echo * Uses a socket to send data to, then receive data from, the standard echo
* port number 7. prvEchoClientTask() uses the standard interface. * port number 7. prvEchoClientTask() uses the standard interface.
* prvZeroCopyEchoClientTask() uses the zero copy interface. * prvZeroCopyEchoClientTask() uses the zero copy interface.
*/ */
static void prvEchoClientTask( void *pvParameters ); static void prvEchoClientTask( void * pvParameters );
static void prvZeroCopyEchoClientTask( void *pvParameters ); static void prvZeroCopyEchoClientTask( void * pvParameters );
/* The receive timeout is set shorter when the windows simulator is used /* The receive timeout is set shorter when the windows simulator is used
because simulated time is slower than real time. */ * because simulated time is slower than real time. */
#ifdef _WINDOWS_ #ifdef _WINDOWS_
const TickType_t xReceiveTimeOut = 50 / portTICK_RATE_MS; const TickType_t xReceiveTimeOut = 50 / portTICK_RATE_MS;
#else #else
const TickType_t xReceiveTimeOut = 500 / portTICK_RATE_MS; const TickType_t xReceiveTimeOut = 500 / portTICK_RATE_MS;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vStartEchoClientTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority ) void vStartEchoClientTasks( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority )
{ {
/* Create the echo client task that does not use the zero copy interface. */ /* Create the echo client task that does not use the zero copy interface. */
xTaskCreate( prvEchoClientTask, /* The function that implements the task. */ xTaskCreate( prvEchoClientTask, /* The function that implements the task. */
"Echo0", /* Just a text name for the task to aid debugging. */ "Echo0", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
NULL, /* The task parameter, not used in this case. */ NULL, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL ); /* The task handle is not used. */ NULL ); /* The task handle is not used. */
/* Create the echo client task that does use the zero copy interface. */ /* Create the echo client task that does use the zero copy interface. */
xTaskCreate( prvZeroCopyEchoClientTask, /* The function that implements the task. */ xTaskCreate( prvZeroCopyEchoClientTask, /* The function that implements the task. */
"Echo1", /* Just a text name for the task to aid debugging. */ "Echo1", /* Just a text name for the task to aid debugging. */
usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */
NULL, /* The task parameter, not used in this case. */ NULL, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL ); /* The task handle is not used. */ NULL ); /* The task handle is not used. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvEchoClientTask( void *pvParameters ) static void prvEchoClientTask( void * pvParameters )
{ {
xSocket_t xSocket; xSocket_t xSocket;
struct freertos_sockaddr xEchoServerAddress; struct freertos_sockaddr xEchoServerAddress;
char cTxString[ 25 ], cRxString[ 25 ]; /* Make sure the stack is large enough to hold these. Turn on stack overflow checking during debug to be sure. */ char cTxString[ 25 ], cRxString[ 25 ]; /* Make sure the stack is large enough to hold these. Turn on stack overflow checking during debug to be sure. */
int32_t lLoopCount = 0UL; int32_t lLoopCount = 0UL;
const int32_t lMaxLoopCount = 50; const int32_t lMaxLoopCount = 50;
volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL; volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
uint32_t xAddressLength = sizeof( xEchoServerAddress ); uint32_t xAddressLength = sizeof( xEchoServerAddress );
/* Remove compiler warning about unused parameters. */ /* Remove compiler warning about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
/* Echo requests are sent to the echo server. The address of the echo /* Echo requests are sent to the echo server. The address of the echo
server is configured by the constants configECHO_SERVER_ADDR0 to * server is configured by the constants configECHO_SERVER_ADDR0 to
configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ * configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{ {
xEchoServerAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, xEchoServerAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 ); configECHO_SERVER_ADDR3 );
} }
#else #else
{ {
xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 ); configECHO_SERVER_ADDR3 );
} }
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xEchoServerAddress.sin_family = FREERTOS_AF_INET; xEchoServerAddress.sin_family = FREERTOS_AF_INET;
for( ;; ) for( ; ; )
{ {
/* Create a socket. */ /* Create a socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
/* Set a time out so a missing reply does not cause the task to block /* Set a time out so a missing reply does not cause the task to block
indefinitely. */ * indefinitely. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
/* Send a number of echo requests. */ /* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{ {
/* Create the string that is sent to the echo server. */ /* Create the string that is sent to the echo server. */
sprintf( cTxString, "Message number %u\r\n", ( unsigned int ) ulTxCount ); sprintf( cTxString, "Message number %u\r\n", ( unsigned int ) ulTxCount );
/* Send the string to the socket. ulFlags is set to 0, so the zero /* Send the string to the socket. ulFlags is set to 0, so the zero
copy interface is not used. That means the data from cTxString is * copy interface is not used. That means the data from cTxString is
copied into a network buffer inside FreeRTOS_sendto(), and cTxString * copied into a network buffer inside FreeRTOS_sendto(), and cTxString
can be reused as soon as FreeRTOS_sendto() has returned. 1 is added * can be reused as soon as FreeRTOS_sendto() has returned. 1 is added
to ensure the NULL string terminator is sent as part of the message. */ * to ensure the NULL string terminator is sent as part of the message. */
FreeRTOS_sendto( xSocket, /* The socket being sent to. */ FreeRTOS_sendto( xSocket, /* The socket being sent to. */
( void * ) cTxString, /* The data being sent. */ ( void * ) cTxString, /* The data being sent. */
strlen( cTxString ) + 1,/* The length of the data being sent. */ strlen( cTxString ) + 1, /* The length of the data being sent. */
0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */ 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
&xEchoServerAddress, /* The destination address. */ &xEchoServerAddress, /* The destination address. */
sizeof( xEchoServerAddress ) ); sizeof( xEchoServerAddress ) );
/* Keep a count of how many echo requests have been transmitted so /* Keep a count of how many echo requests have been transmitted so
it can be compared to the number of echo replies received. It would * it can be compared to the number of echo replies received. It would
be expected to loose at least one to an ARP message the first time * be expected to loose at least one to an ARP message the first time
the connection is created. */ * the connection is created. */
ulTxCount++; ulTxCount++;
/* Receive data echoed back to the socket. ulFlags is zero, so the /* Receive data echoed back to the socket. ulFlags is zero, so the
zero copy option is not being used and the received data will be * zero copy option is not being used and the received data will be
copied into the buffer pointed to by cRxString. xAddressLength is * copied into the buffer pointed to by cRxString. xAddressLength is
not actually used (at the time of writing this comment, anyway) by * not actually used (at the time of writing this comment, anyway) by
FreeRTOS_recvfrom(), but is set appropriately in case future * FreeRTOS_recvfrom(), but is set appropriately in case future
versions do use it. */ * versions do use it. */
memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) ); memset( ( void * ) cRxString, 0x00, sizeof( cRxString ) );
FreeRTOS_recvfrom( xSocket, /* The socket being received from. */ FreeRTOS_recvfrom( xSocket, /* The socket being received from. */
cRxString, /* The buffer into which the received data will be written. */ cRxString, /* The buffer into which the received data will be written. */
sizeof( cRxString ), /* The size of the buffer provided to receive the data. */ sizeof( cRxString ), /* The size of the buffer provided to receive the data. */
0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */ 0, /* ulFlags with the FREERTOS_ZERO_COPY bit clear. */
&xEchoServerAddress, /* The address from where the data was sent (the source address). */ &xEchoServerAddress, /* The address from where the data was sent (the source address). */
&xAddressLength ); &xAddressLength );
/* Compare the transmitted string to the received string. */ /* Compare the transmitted string to the received string. */
if( strcmp( cRxString, cTxString ) == 0 ) if( strcmp( cRxString, cTxString ) == 0 )
{ {
/* The echo reply was received without error. */ /* The echo reply was received without error. */
ulRxCount++; ulRxCount++;
} }
}; }
/* Pause for a short while to ensure the network is not too /* Pause for a short while to ensure the network is not too
congested. */ * congested. */
vTaskDelay( echoLOOP_DELAY ); vTaskDelay( echoLOOP_DELAY );
/* Close this socket before looping back to create another. */ /* Close this socket before looping back to create another. */
FreeRTOS_closesocket( xSocket ); FreeRTOS_closesocket( xSocket );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvZeroCopyEchoClientTask( void *pvParameters ) static void prvZeroCopyEchoClientTask( void * pvParameters )
{ {
xSocket_t xSocket; xSocket_t xSocket;
struct freertos_sockaddr xEchoServerAddress; struct freertos_sockaddr xEchoServerAddress;
static char cTxString[ 40 ]; static char cTxString[ 40 ];
int32_t lLoopCount = 0UL; int32_t lLoopCount = 0UL;
volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL; volatile uint32_t ulRxCount = 0UL, ulTxCount = 0UL;
uint32_t xAddressLength = sizeof( xEchoServerAddress ); uint32_t xAddressLength = sizeof( xEchoServerAddress );
int32_t lReturned; int32_t lReturned;
uint8_t *pucUDPPayloadBuffer; uint8_t * pucUDPPayloadBuffer;
const int32_t lMaxLoopCount = 50; const int32_t lMaxLoopCount = 50;
const char * const pcStringToSend = "Zero copy message number"; const char * const pcStringToSend = "Zero copy message number";
/* The buffer is large enough to hold the string, a number, and the string terminator. */ /* The buffer is large enough to hold the string, a number, and the string terminator. */
const size_t xBufferLength = strlen( pcStringToSend ) + 15; const size_t xBufferLength = strlen( pcStringToSend ) + 15;
#if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 #if ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1
{ {
/* When the trace recorder code is included user events are generated to /* When the trace recorder code is included user events are generated to
mark the sending and receiving of the echoed data (only in the zero copy * mark the sending and receiving of the echoed data (only in the zero copy
task). */ * task). */
xZeroCopySendEvent = xTraceOpenLabel( "ZeroCopyTx" ); xZeroCopySendEvent = xTraceOpenLabel( "ZeroCopyTx" );
xZeroCopyReceiveEvent = xTraceOpenLabel( "ZeroCopyRx" ); xZeroCopyReceiveEvent = xTraceOpenLabel( "ZeroCopyRx" );
} }
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS */ #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS */
/* Remove compiler warning about unused parameters. */ /* Remove compiler warning about unused parameters. */
( void ) pvParameters; ( void ) pvParameters;
/* Delay for a little while to ensure the task is out of synch with the /* Delay for a little while to ensure the task is out of synch with the
other echo task implemented above. */ * other echo task implemented above. */
vTaskDelay( echoLOOP_DELAY >> 1 ); vTaskDelay( echoLOOP_DELAY >> 1 );
/* Echo requests are sent to the echo server. The address of the echo /* Echo requests are sent to the echo server. The address of the echo
server is configured by the constants configECHO_SERVER_ADDR0 to * server is configured by the constants configECHO_SERVER_ADDR0 to
configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */ * configECHO_SERVER_ADDR3 in FreeRTOSConfig.h. */
xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT ); xEchoServerAddress.sin_port = FreeRTOS_htons( echoECHO_PORT );
#if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) #if defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 )
{ {
xEchoServerAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, xEchoServerAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 ); configECHO_SERVER_ADDR3 );
} }
#else #else
{ {
xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0, xEchoServerAddress.sin_addr = FreeRTOS_inet_addr_quick( configECHO_SERVER_ADDR0,
configECHO_SERVER_ADDR1, configECHO_SERVER_ADDR1,
configECHO_SERVER_ADDR2, configECHO_SERVER_ADDR2,
configECHO_SERVER_ADDR3 ); configECHO_SERVER_ADDR3 );
} }
#endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */ #endif /* defined( ipconfigIPv4_BACKWARD_COMPATIBLE ) && ( ipconfigIPv4_BACKWARD_COMPATIBLE == 0 ) */
xEchoServerAddress.sin_family = FREERTOS_AF_INET; xEchoServerAddress.sin_family = FREERTOS_AF_INET;
for( ;; ) for( ; ; )
{ {
/* Create a socket. */ /* Create a socket. */
xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP );
configASSERT( xSocket != FREERTOS_INVALID_SOCKET ); configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
/* Set a time out so a missing reply does not cause the task to block /* Set a time out so a missing reply does not cause the task to block
indefinitely. */ * indefinitely. */
FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
/* Send a number of echo requests. */ /* Send a number of echo requests. */
for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ ) for( lLoopCount = 0; lLoopCount < lMaxLoopCount; lLoopCount++ )
{ {
/* This task is going to send using the zero copy interface. The /* This task is going to send using the zero copy interface. The
data being sent is therefore written directly into a buffer that is * data being sent is therefore written directly into a buffer that is
passed by reference into the FreeRTOS_sendto() function. First * passed by reference into the FreeRTOS_sendto() function. First
obtain a buffer of adequate size from the IP stack. Although a max * obtain a buffer of adequate size from the IP stack. Although a max
delay is used, the actual delay will be capped to * delay is used, the actual delay will be capped to
ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the test to ensure a buffer * ipconfigMAX_SEND_BLOCK_TIME_TICKS, hence the test to ensure a buffer
was actually obtained. */ * was actually obtained. */
pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xBufferLength, portMAX_DELAY ); pucUDPPayloadBuffer = ( uint8_t * ) FreeRTOS_GetUDPPayloadBuffer( xBufferLength, portMAX_DELAY );
if( pucUDPPayloadBuffer != NULL ) if( pucUDPPayloadBuffer != NULL )
{ {
/* A buffer was successfully obtained. Create the string that is /* A buffer was successfully obtained. Create the string that is
sent to the echo server. Note the string is written directly * sent to the echo server. Note the string is written directly
into the buffer obtained from the IP stack. */ * into the buffer obtained from the IP stack. */
sprintf( ( char * ) pucUDPPayloadBuffer, "%s %u\r\n", "Zero copy message number", ( unsigned int ) ulTxCount ); sprintf( ( char * ) pucUDPPayloadBuffer, "%s %u\r\n", "Zero copy message number", ( unsigned int ) ulTxCount );
/* Also copy the string into a local buffer so it can be compared /* Also copy the string into a local buffer so it can be compared
with the string that is later received back from the echo server. */ * with the string that is later received back from the echo server. */
strcpy( cTxString, ( char * ) pucUDPPayloadBuffer ); strcpy( cTxString, ( char * ) pucUDPPayloadBuffer );
/* Pass the buffer into the send function. ulFlags has the /* Pass the buffer into the send function. ulFlags has the
FREERTOS_ZERO_COPY bit set so the IP stack will take control of * FREERTOS_ZERO_COPY bit set so the IP stack will take control of
the buffer, rather than copy data out of the buffer. */ * the buffer, rather than copy data out of the buffer. */
echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopySendEvent ); echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopySendEvent );
lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */ lReturned = FreeRTOS_sendto( xSocket, /* The socket being sent to. */
( void * ) pucUDPPayloadBuffer, /* The buffer being passed into the IP stack. */ ( void * ) pucUDPPayloadBuffer, /* The buffer being passed into the IP stack. */
strlen( cTxString ) + 1, /* The length of the data being sent. Plus 1 to ensure the null terminator is part of the data. */ strlen( cTxString ) + 1, /* The length of the data being sent. Plus 1 to ensure the null terminator is part of the data. */
FREERTOS_ZERO_COPY, /* ulFlags with the zero copy bit is set. */ FREERTOS_ZERO_COPY, /* ulFlags with the zero copy bit is set. */
&xEchoServerAddress, /* Where the data is being sent. */ &xEchoServerAddress, /* Where the data is being sent. */
sizeof( xEchoServerAddress ) ); sizeof( xEchoServerAddress ) );
if( lReturned == 0 ) if( lReturned == 0 )
{ {
/* The send operation failed, so this task is still /* The send operation failed, so this task is still
responsible for the buffer obtained from the IP stack. To * responsible for the buffer obtained from the IP stack. To
ensure the buffer is not lost it must either be used again, * ensure the buffer is not lost it must either be used again,
or, as in this case, returned to the IP stack using * or, as in this case, returned to the IP stack using
FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can * FreeRTOS_ReleaseUDPPayloadBuffer(). pucUDPPayloadBuffer can
be safely re-used to receive from the socket below once the * be safely re-used to receive from the socket below once the
buffer has been returned to the stack. */ * buffer has been returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer ); FreeRTOS_ReleaseUDPPayloadBuffer( ( void * ) pucUDPPayloadBuffer );
} }
else else
{ {
/* The send was successful so the IP stack is now managing /* The send was successful so the IP stack is now managing
the buffer pointed to by pucUDPPayloadBuffer, and the IP * the buffer pointed to by pucUDPPayloadBuffer, and the IP
stack will return the buffer once it has been sent. * stack will return the buffer once it has been sent.
pucUDPPayloadBuffer can be safely re-used to receive from * pucUDPPayloadBuffer can be safely re-used to receive from
the socket below. */ * the socket below. */
} }
/* Keep a count of how many echo requests have been transmitted /* Keep a count of how many echo requests have been transmitted
so it can be compared to the number of echo replies received. * so it can be compared to the number of echo replies received.
It would be expected to loose at least one to an ARP message the * It would be expected to loose at least one to an ARP message the
first time the connection is created. */ * first time the connection is created. */
ulTxCount++; ulTxCount++;
/* Receive data on the socket. ulFlags has the zero copy bit set /* Receive data on the socket. ulFlags has the zero copy bit set
(FREERTOS_ZERO_COPY) indicating to the stack that a reference to * (FREERTOS_ZERO_COPY) indicating to the stack that a reference to
the received data should be passed out to this task using the * the received data should be passed out to this task using the
second parameter to the FreeRTOS_recvfrom() call. When this is * second parameter to the FreeRTOS_recvfrom() call. When this is
done the IP stack is no longer responsible for releasing the * done the IP stack is no longer responsible for releasing the
buffer, and the task *must* return the buffer to the stack when * buffer, and the task *must* return the buffer to the stack when
it is no longer needed. By default the receive block time is * it is no longer needed. By default the receive block time is
portMAX_DELAY. */ * portMAX_DELAY. */
echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopyReceiveEvent ); echoMARK_SEND_IN_TRACE_BUFFER( xZeroCopyReceiveEvent );
lReturned = FreeRTOS_recvfrom( xSocket, /* The socket to receive from. */ lReturned = FreeRTOS_recvfrom( xSocket, /* The socket to receive from. */
( void * ) &pucUDPPayloadBuffer, /* pucUDPPayloadBuffer will be set to point to the buffer that already contains the received data. */ ( void * ) &pucUDPPayloadBuffer, /* pucUDPPayloadBuffer will be set to point to the buffer that already contains the received data. */
0, /* Ignored because the zero copy interface is being used. */ 0, /* Ignored because the zero copy interface is being used. */
FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */ FREERTOS_ZERO_COPY, /* ulFlags with the FREERTOS_ZERO_COPY bit set. */
&xEchoServerAddress, /* The address from which the data was sent. */ &xEchoServerAddress, /* The address from which the data was sent. */
&xAddressLength ); &xAddressLength );
if( lReturned > 0 ) if( lReturned > 0 )
{ {
/* Compare the string sent to the echo server with the string /* Compare the string sent to the echo server with the string
received back from the echo server. */ * received back from the echo server. */
if( strcmp( ( char * ) pucUDPPayloadBuffer, cTxString ) == 0 ) if( strcmp( ( char * ) pucUDPPayloadBuffer, cTxString ) == 0 )
{ {
/* The strings matched. */ /* The strings matched. */
ulRxCount++; ulRxCount++;
} }
/* The buffer that contains the data passed out of the stack /* The buffer that contains the data passed out of the stack
*must* be returned to the stack. */ * must* be returned to the stack. */
FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer ); FreeRTOS_ReleaseUDPPayloadBuffer( pucUDPPayloadBuffer );
} }
} }
} }
/* Pause for a short while to ensure the network is not too /* Pause for a short while to ensure the network is not too
congested. */ * congested. */
vTaskDelay( echoLOOP_DELAY ); vTaskDelay( echoLOOP_DELAY );
/* Close this socket before looping back to create another. */ /* Close this socket before looping back to create another. */
FreeRTOS_closesocket( xSocket ); FreeRTOS_closesocket( xSocket );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,7 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
@ -32,6 +32,7 @@
* to send to and receive from an echo server. The other task uses the zero * to send to and receive from an echo server. The other task uses the zero
* copy interface to send to and receive from an echo server. * copy interface to send to and receive from an echo server.
*/ */
void vStartEchoClientTasks( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority ); void vStartEchoClientTasks( uint16_t usTaskStackSize,
UBaseType_t uxTaskPriority );
#endif /* TWO_ECHO_CLIENTS_H */ #endif /* TWO_ECHO_CLIENTS_H */

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS V202212.00 * FreeRTOS V202212.00
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -20,7 +20,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* *
* https://www.FreeRTOS.org * https://www.FreeRTOS.org
* https://aws.amazon.com/freertos * https://github.com/FreeRTOS
* *
*/ */
@ -43,7 +43,7 @@
#include "DemoIPTrace.h" #include "DemoIPTrace.h"
/* It is possible to remove the trace macros using the /* It is possible to remove the trace macros using the
configINCLUDE_DEMO_DEBUG_STATS setting in FreeRTOSIPConfig.h. */ * configINCLUDE_DEMO_DEBUG_STATS setting in FreeRTOSIPConfig.h. */
#if configINCLUDE_DEMO_DEBUG_STATS == 1 #if configINCLUDE_DEMO_DEBUG_STATS == 1
/* /*
@ -53,97 +53,98 @@ configINCLUDE_DEMO_DEBUG_STATS setting in FreeRTOSIPConfig.h. */
* number of network buffers that were available during the execution of the * number of network buffers that were available during the execution of the
* stack). * stack).
*/ */
static void prvStoreLowest( uint32_t *pulCurrentValue, uint32_t ulCount ); static void prvStoreLowest( uint32_t * pulCurrentValue,
uint32_t ulCount );
/* /*
* Each row in the xIPTraceValues[] table contains a pointer to a function that * Each row in the xIPTraceValues[] table contains a pointer to a function that
* updates the value for that row. Rows that simply increment an event count * updates the value for that row. Rows that simply increment an event count
* point to this function. * point to this function.
*/ */
static void prvIncrementEventCount( uint32_t *pulCurrentValue, uint32_t ulCount ); static void prvIncrementEventCount( uint32_t * pulCurrentValue,
uint32_t ulCount );
xExampleDebugStatEntry_t xIPTraceValues[] = xExampleDebugStatEntry_t xIPTraceValues[] =
{ {
/* Comment out array entries to remove individual trace items. */ /* Comment out array entries to remove individual trace items. */
{ iptraceID_NETWORK_INTERFACE_RECEIVE, ( const uint8_t * const ) "Packets received by the network interface", prvIncrementEventCount, 0 }, { iptraceID_NETWORK_INTERFACE_RECEIVE, ( const uint8_t * const ) "Packets received by the network interface", prvIncrementEventCount, 0 },
{ iptraceID_NETWORK_INTERFACE_TRANSMIT, ( const uint8_t * const ) "Count of transmitted packets", prvIncrementEventCount, 0 }, { iptraceID_NETWORK_INTERFACE_TRANSMIT, ( const uint8_t * const ) "Count of transmitted packets", prvIncrementEventCount, 0 },
{ iptraceID_PACKET_DROPPED_TO_GENERATE_ARP, ( const uint8_t * const ) "Count of packets dropped to generate ARP", prvIncrementEventCount, 0 }, { iptraceID_PACKET_DROPPED_TO_GENERATE_ARP, ( const uint8_t * const ) "Count of packets dropped to generate ARP", prvIncrementEventCount, 0 },
{ iptraceID_NETWORK_BUFFER_OBTAINED, ( const uint8_t * const ) "Lowest ever available network buffers", prvStoreLowest, 0xffffUL }, { iptraceID_NETWORK_BUFFER_OBTAINED, ( const uint8_t * const ) "Lowest ever available network buffers", prvStoreLowest, 0xffffUL },
{ iptraceID_NETWORK_EVENT_RECEIVED, ( const uint8_t * const ) "Lowest ever free space in network event queue", prvStoreLowest, 0xffffUL }, { iptraceID_NETWORK_EVENT_RECEIVED, ( const uint8_t * const ) "Lowest ever free space in network event queue", prvStoreLowest, 0xffffUL },
{ iptraceID_FAILED_TO_OBTAIN_NETWORK_BUFFER, ( const uint8_t * const ) "Count of failed attempts to obtain a network buffer",prvIncrementEventCount, 0 }, { iptraceID_FAILED_TO_OBTAIN_NETWORK_BUFFER, ( const uint8_t * const ) "Count of failed attempts to obtain a network buffer", prvIncrementEventCount, 0 },
{ iptraceID_ARP_TABLE_ENTRY_EXPIRED, ( const uint8_t * const ) "Count of expired ARP entries", prvIncrementEventCount, 0 }, { iptraceID_ARP_TABLE_ENTRY_EXPIRED, ( const uint8_t * const ) "Count of expired ARP entries", prvIncrementEventCount, 0 },
{ iptraceID_FAILED_TO_CREATE_SOCKET, ( const uint8_t * const ) "Count of failures to create a socket", prvIncrementEventCount, 0 }, { iptraceID_FAILED_TO_CREATE_SOCKET, ( const uint8_t * const ) "Count of failures to create a socket", prvIncrementEventCount, 0 },
{ iptraceID_RECVFROM_DISCARDING_BYTES, ( const uint8_t * const ) "Count of times recvfrom() has discarding bytes", prvIncrementEventCount, 0 }, { iptraceID_RECVFROM_DISCARDING_BYTES, ( const uint8_t * const ) "Count of times recvfrom() has discarding bytes", prvIncrementEventCount, 0 },
{ iptraceID_ETHERNET_RX_EVENT_LOST, ( const uint8_t * const ) "Count of lost Ethenret Rx events (event queue full?)",prvIncrementEventCount, 0 }, { iptraceID_ETHERNET_RX_EVENT_LOST, ( const uint8_t * const ) "Count of lost Ethernet Rx events (event queue full?)", prvIncrementEventCount, 0 },
{ iptraceID_STACK_TX_EVENT_LOST, ( const uint8_t * const ) "Count of lost IP stack events (event queue full?)", prvIncrementEventCount, 0 }, { iptraceID_STACK_TX_EVENT_LOST, ( const uint8_t * const ) "Count of lost IP stack events (event queue full?)", prvIncrementEventCount, 0 },
{ ipconfigID_BIND_FAILED, ( const uint8_t * const ) "Count of failed calls to bind()", prvIncrementEventCount, 0 }, { ipconfigID_BIND_FAILED, ( const uint8_t * const ) "Count of failed calls to bind()", prvIncrementEventCount, 0 },
{ iptraceID_RECVFROM_TIMEOUT, ( const uint8_t * const ) "Count of receive timeouts", prvIncrementEventCount, 0 }, { iptraceID_RECVFROM_TIMEOUT, ( const uint8_t * const ) "Count of receive timeouts", prvIncrementEventCount, 0 },
{ iptraceID_SENDTO_DATA_TOO_LONG, ( const uint8_t * const ) "Count of failed sends due to oversized payload", prvIncrementEventCount, 0 }, { iptraceID_SENDTO_DATA_TOO_LONG, ( const uint8_t * const ) "Count of failed sends due to oversized payload", prvIncrementEventCount, 0 },
{ iptraceID_SENDTO_SOCKET_NOT_BOUND, ( const uint8_t * const ) "Count of failed sends due to unbound socket", prvIncrementEventCount, 0 }, { iptraceID_SENDTO_SOCKET_NOT_BOUND, ( const uint8_t * const ) "Count of failed sends due to unbound socket", prvIncrementEventCount, 0 },
{ iptraceID_NO_BUFFER_FOR_SENDTO, ( const uint8_t * const ) "Count of failed transmits due to timeout", prvIncrementEventCount, 0 }, { iptraceID_NO_BUFFER_FOR_SENDTO, ( const uint8_t * const ) "Count of failed transmits due to timeout", prvIncrementEventCount, 0 },
{ iptraceID_WAIT_FOR_TX_DMA_DESCRIPTOR, ( const uint8_t * const ) "Number of times task had to wait to obtain a DMA Tx descriptor", prvIncrementEventCount, 0 }, { iptraceID_WAIT_FOR_TX_DMA_DESCRIPTOR, ( const uint8_t * const ) "Number of times task had to wait to obtain a DMA Tx descriptor", prvIncrementEventCount, 0 },
{ iptraceID_FAILED_TO_NOTIFY_SELECT_GROUP, ( const uint8_t * const ) "Failed to notify select group", prvIncrementEventCount, 0 } { iptraceID_FAILED_TO_NOTIFY_SELECT_GROUP, ( const uint8_t * const ) "Failed to notify select group", prvIncrementEventCount, 0 }
}; };
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xExampleDebugStatEntries( void ) BaseType_t xExampleDebugStatEntries( void )
{ {
/* Return the number of entries in the xIPTraceValues[] table. */ /* Return the number of entries in the xIPTraceValues[] table. */
return ( BaseType_t ) ( sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t ) ); return ( BaseType_t ) ( sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t ) );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vExampleDebugStatUpdate( uint8_t ucIdentifier, uint32_t ulValue ) void vExampleDebugStatUpdate( uint8_t ucIdentifier,
{ uint32_t ulValue )
BaseType_t xIndex; {
const BaseType_t xEntries = sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t ); BaseType_t xIndex;
const BaseType_t xEntries = sizeof( xIPTraceValues ) / sizeof( xExampleDebugStatEntry_t );
/* Update an entry in the xIPTraceValues[] table. Each row in the table /* Update an entry in the xIPTraceValues[] table. Each row in the table
includes a pointer to a function that performs the actual update. This * includes a pointer to a function that performs the actual update. This
function just executes the update function from that table row. */ * function just executes the update function from that table row. */
for( xIndex = 0; xIndex < xEntries; xIndex++ ) for( xIndex = 0; xIndex < xEntries; xIndex++ )
{ {
if( xIPTraceValues[ xIndex ].ucIdentifier == ucIdentifier ) if( xIPTraceValues[ xIndex ].ucIdentifier == ucIdentifier )
{ {
xIPTraceValues[ xIndex ].vPerformAction( &( xIPTraceValues[ xIndex ].ulData ), ulValue ); xIPTraceValues[ xIndex ].vPerformAction( &( xIPTraceValues[ xIndex ].ulData ), ulValue );
break; break;
} }
} }
configASSERT( xIndex != xEntries ); configASSERT( xIndex != xEntries );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvIncrementEventCount( uint32_t *pulCurrentValue, uint32_t ulCount ) static void prvIncrementEventCount( uint32_t * pulCurrentValue,
{ uint32_t ulCount )
/* Each row in the xIPTraceValues[] table contains a pointer to a function {
that updates the value for that row. Rows that simply increment an event /* Each row in the xIPTraceValues[] table contains a pointer to a function
count point to this function. */ * that updates the value for that row. Rows that simply increment an event
( void ) ulCount; * count point to this function. */
( *pulCurrentValue )++; ( void ) ulCount;
} ( *pulCurrentValue )++;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvStoreLowest( uint32_t *pulCurrentValue, uint32_t ulCount ) static void prvStoreLowest( uint32_t * pulCurrentValue,
{ uint32_t ulCount )
/* Each row in the xIPTraceValues[] table contains a pointer to a function {
that updates the value for that row. Rows that latch the lowest value /* Each row in the xIPTraceValues[] table contains a pointer to a function
point to this function (for example, this function can be used to latch * that updates the value for that row. Rows that latch the lowest value
the lowest number of network buffers that were available during the * point to this function (for example, this function can be used to latch
execution of the stack). */ * the lowest number of network buffers that were available during the
if( ulCount < *pulCurrentValue ) * execution of the stack). */
{ if( ulCount < *pulCurrentValue )
*pulCurrentValue = ulCount; {
} *pulCurrentValue = ulCount;
} }
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* configINCLUDE_DEMO_DEBUG_STATS == 1 */ #endif /* configINCLUDE_DEMO_DEBUG_STATS == 1 */

Some files were not shown because too many files have changed in this diff Show more