diff options
-rw-r--r-- | .github/workflows/build.yml | 379 | ||||
-rw-r--r-- | .github/workflows/docs.yml | 93 | ||||
-rw-r--r-- | .github/workflows/properties/build.properties.json | 6 | ||||
-rw-r--r-- | .github/workflows/properties/docs.properties.json | 6 | ||||
-rw-r--r-- | .github/workflows/properties/publish.properties.json | 6 | ||||
-rw-r--r-- | .github/workflows/publish.yml | 94 | ||||
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | Cargo.toml | 10 | ||||
-rw-r--r-- | book/en/src/by-example/app.md | 14 | ||||
-rw-r--r-- | book/en/src/by-example/resources.md | 10 | ||||
-rw-r--r-- | book/ru/src/by-example/app.md | 2 | ||||
-rw-r--r-- | build.rs | 5 | ||||
-rw-r--r-- | ci/install.sh | 9 | ||||
-rw-r--r-- | ci/script.sh | 23 | ||||
-rw-r--r-- | examples/schedule.rs | 7 | ||||
-rw-r--r-- | examples/t-cfg-resources.rs | 36 | ||||
-rw-r--r-- | macros/src/codegen.rs | 3 | ||||
-rw-r--r-- | macros/src/codegen/init.rs | 6 | ||||
-rw-r--r-- | macros/src/codegen/post_init.rs | 9 | ||||
-rw-r--r-- | macros/src/codegen/resources.rs | 10 | ||||
-rw-r--r-- | src/cyccnt.rs | 4 |
21 files changed, 710 insertions, 23 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..00086ff5 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,379 @@ +name: Build +on: + push: + branches: + - master + - ghatest + pull_request: + branches: + - master + - ghatest + +env: + CARGO_TERM_COLOR: always + +jobs: + # Run cargo fmt --check, includes macros/ + style: + name: Check Style with cargo fmt + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt + + - name: cargo fmt --check + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + # Compilation check + check: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - thumbv7m-none-eabi + - thumbv6m-none-eabi + - x86_64-unknown-linux-gnu + toolchain: + - stable + - 1.36.0 + - nightly + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }}) + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: ${{ matrix.target }} + override: true + + - name: Disable optimisation profiles + if: matrix.toolchain == '1.36.0' + run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml + + - name: cargo check + uses: actions-rs/cargo@v1 + with: + use-cross: false + command: check + args: --target=${{ matrix.target }} + + # Verify all examples + checkexamples: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - thumbv7m-none-eabi + - thumbv6m-none-eabi + toolchain: + - stable + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }}) + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: ${{ matrix.target }} + override: true + - uses: actions-rs/cargo@v1 + with: + use-cross: false + command: check + args: --examples --target=${{ matrix.target }} --features __min_r1_43 + + - name: cargo check -p homogeneous + uses: actions-rs/cargo@v1 + with: + use-cross: false + command: check + args: -p homogeneous --examples --target=${{ matrix.target }} + + - name: Install QEMU + run: | + mkdir qemu + curl -L https://github.com/japaric/qemu-bin/raw/master/14.04/qemu-system-arm-2.12.0 > qemu/qemu-system-arm + chmod +x qemu/qemu-system-arm + + - name: Setup arm-none-eabi-gcc + uses: fiam/arm-none-eabi-gcc@v1 + with: + release: '9-2019-q4' # The arm-none-eabi-gcc release to use. + + - name: Run-pass tests + run: | + # Add QEMU to the path + echo $PATH + PATH=$(pwd)/qemu:$PATH + arm_example() { + local COMMAND=$1 + local EXAMPLE=$2 + local BUILD_MODE=$3 + local FEATURES=$4 + local BUILD_NUM=$5 + + if [ $BUILD_MODE = "release" ]; then + local RELEASE_FLAG="--release" + else + local RELEASE_FLAG="" + fi + + if [ -n "$FEATURES" ]; then + local FEATURES_FLAG="--features $FEATURES" + local FEATURES_STR=${FEATURES/,/_}_ + else + local FEATURES_FLAG="" + local FEATURES_STR="" + fi + local CARGO_FLAGS="--example $EXAMPLE --target ${{ matrix.target }} $RELEASE_FLAG $FEATURES_FLAG" + + if [ $COMMAND = "run" ]; then + cargo $COMMAND $CARGO_FLAGS | diff -u ci/expected/$EXAMPLE.run - + else + cargo $COMMAND $CARGO_FLAGS + fi + arm-none-eabi-objcopy -O ihex target/${{ matrix.target }}/$BUILD_MODE/examples/$EXAMPLE ci/builds/${EXAMPLE}_${FEATURES_STR}${BUILD_MODE}_${BUILD_NUM}.hex + } + + mkdir -p ci/builds + exs=( + idle + init + hardware + preempt + binds + + resource + lock + late + only-shared-access + + task + message + capacity + + types + not-send + not-sync + shared-with-init + + generics + cfg + pool + ramfunc + ) + + for ex in ${exs[@]}; do + if [ $ex = pool ]; then + if [ ${{ matrix.target }} = thumbv6m-none-eabi ]; then + continue + fi + + td=$(mktemp -d) + + cargo run --example $ex --target ${{ matrix.target }} --features __v7 >\ + $td/pool.run + grep 'foo(0x2' $td/pool.run + grep 'bar(0x2' $td/pool.run + arm-none-eabi-objcopy -O ihex target/${{ matrix.target }}/debug/examples/$ex \ + ci/builds/${ex}___v7_debug_1.hex + + cargo run --example $ex --target ${{ matrix.target }} --features __v7 --release >\ + $td/pool.run + grep 'foo(0x2' $td/pool.run + grep 'bar(0x2' $td/pool.run + arm-none-eabi-objcopy -O ihex target/${{ matrix.target }}/release/examples/$ex \ + ci/builds/${ex}___v7_release_1.hex + + rm -rf $td + + continue + fi + + if [ $ex = types ]; then + if [ ${{ matrix.target }} = thumbv6m-none-eabi ]; then + continue + fi + + arm_example "run" $ex "debug" "__v7" "1" + arm_example "run" $ex "release" "__v7" "1" + + continue + fi + + arm_example "run" $ex "debug" "" "1" + if [ $ex = types ]; then + arm_example "run" $ex "release" "" "1" + else + arm_example "build" $ex "release" "" "1" + fi + done + + built=() + cargo clean + for ex in ${exs[@]}; do + if [ $ex = types ] || [ $ex = pool ]; then + if [ ${{ matrix.target }} = thumbv6m-none-eabi ]; then + continue + fi + + arm_example "build" $ex "debug" "__v7" "2" + cmp ci/builds/${ex}___v7_debug_1.hex \ + ci/builds/${ex}___v7_debug_2.hex + arm_example "build" $ex "release" "__v7" "2" + cmp ci/builds/${ex}___v7_release_1.hex \ + ci/builds/${ex}___v7_release_2.hex + else + arm_example "build" $ex "debug" "" "2" + cmp ci/builds/${ex}_debug_1.hex \ + ci/builds/${ex}_debug_2.hex + arm_example "build" $ex "release" "" "2" + cmp ci/builds/${ex}_release_1.hex \ + ci/builds/${ex}_release_2.hex + fi + + built+=( $ex ) + done + + ( cd target/${{ matrix.target }}/release/examples/ && size ${built[@]} ) + + + # Check the correctness of macros/ crate + checkmacros: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - x86_64-unknown-linux-gnu + toolchain: + - stable + - 1.36.0 + - nightly + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Rust ${{ matrix.toolchain }} with target (${{ matrix.target }}) + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: ${{ matrix.target }} + override: true + + - name: Disable optimisation profiles + if: matrix.toolchain == '1.36.0' + run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml + + - name: cargo check + uses: actions-rs/cargo@v1 + with: + use-cross: false + command: check + args: --manifest-path macros/Cargo.toml --target=${{ matrix.target }} + + # Run test suite for thumbv7m + testv7: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.36.0 + target: thumbv7m-none-eabi + override: true + + - name: Disable optimisation profiles + run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml + + - uses: actions-rs/cargo@v1 + with: + use-cross: false + command: test + args: --test single --features __v7 + + # Run test suite for thumbv6m + testv6: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.36.0 + target: thumbv6m-none-eabi + override: true + + - name: Disable optimisation profiles + run: sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml + + - uses: actions-rs/cargo@v1 + with: + use-cross: false + command: test + args: --test single + + # Verify all multicore examples + checkmulticore: + runs-on: ubuntu-latest + strategy: + matrix: + target: + - x86_64-unknown-linux-gnu + toolchain: + - nightly + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install Rust ${{ matrix.toolchain }} with x86_64-unknown-linux-gnu + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: x86_64-unknown-linux-gnu + override: true + - name: Install Rust ${{ matrix.toolchain }} with thumbv7m-none-eabi + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: thumbv7m-none-eabi + override: true + - name: Install Rust ${{ matrix.toolchain }} with thumbv6m-none-eabi + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + target: thumbv6m-none-eabi + override: true + - uses: actions-rs/cargo@v1 + with: + command: install + args: microamp-tools --version 0.1.0-alpha.3 + + - name: Check multi-core examples + run: | + cd heterogeneous + exs=( + smallest + x-init-2 + x-init + x-schedule + x-spawn + ) + for ex in ${exs[@]}; do + cargo-microamp --example=$ex --target thumbv7m-none-eabi,thumbv6m-none-eabi --check + done diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..297bff06 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,93 @@ +name: Docs + +on: + push: + branches: + - master + - ghatest + pull_request: + branches: + - master + - ghatest + +env: + CARGO_TERM_COLOR: always + +jobs: + docs: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Python 3.x + uses: actions/setup-python@v2 + with: + # Semantic version range syntax or exact version of a Python version + python-version: '3.x' + # Optional - x64 or x86 architecture, defaults to x64 + architecture: 'x64' + + # You can test your matrix by printing the current Python version + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Install dependencies + run: pip install git+https://github.com/linkchecker/linkchecker.git + + - name: Remove cargo-config + run: rm -f .cargo/config + + - name: Build docs + run: cargo doc + + - name: Check links + run: | + td=$(mktemp -d) + cp -r target/doc $td/api + linkchecker $td/api/rtfm/ + linkchecker $td/api/cortex_m_rtfm_macros/ + + mdbook: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up Python 3.x + uses: actions/setup-python@v2 + with: + # Semantic version range syntax or exact version of a Python version + python-version: '3.x' + # Optional - x64 or x86 architecture, defaults to x64 + architecture: 'x64' + + # You can test your matrix by printing the current Python version + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Install dependencies + run: pip install git+https://github.com/linkchecker/linkchecker.git + + - name: mdBook Action + uses: peaceiris/actions-mdbook@v1.1.11 + with: + mdbook-version: '0.3.1' + + - name: Build book in English + run: cd book/en && mdbook build + + - name: Build book in Russian + run: cd book/ru && mdbook build + + - name: Check links + run: | + td=$(mktemp -d) + mkdir $td/book + cp -r book/en/book $td/book/en + cp -r book/ru/book $td/book/ru + cp LICENSE-* $td/book/en + cp LICENSE-* $td/book/ru + + linkchecker $td/book/en/ + linkchecker $td/book/ru/ diff --git a/.github/workflows/properties/build.properties.json b/.github/workflows/properties/build.properties.json new file mode 100644 index 00000000..e447a1ed --- /dev/null +++ b/.github/workflows/properties/build.properties.json @@ -0,0 +1,6 @@ +{ + "name": "Build", + "description": "Build and test a Rust project with Cargo.", + "iconName": "rust", + "categories": ["Rust"] +} diff --git a/.github/workflows/properties/docs.properties.json b/.github/workflows/properties/docs.properties.json new file mode 100644 index 00000000..a9a052c4 --- /dev/null +++ b/.github/workflows/properties/docs.properties.json @@ -0,0 +1,6 @@ +{ + "name": "Docs", + "description": "Build the books.", + "iconName": "rust", + "categories": ["Rust"] +} diff --git a/.github/workflows/properties/publish.properties.json b/.github/workflows/properties/publish.properties.json new file mode 100644 index 00000000..fa9b8cda --- /dev/null +++ b/.github/workflows/properties/publish.properties.json @@ -0,0 +1,6 @@ +{ + "name": "Publish", + "description": "Publish the books and docs.", + "iconName": "rust", + "categories": ["Rust"] +} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..7436bf88 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,94 @@ +name: Publish + +on: + push: + branches: + - master + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Python 3.x + uses: actions/setup-python@v2 + with: + # Semantic version range syntax or exact version of a Python version + python-version: '3.x' + # Optional - x64 or x86 architecture, defaults to x64 + architecture: 'x64' + + # You can test your matrix by printing the current Python version + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: mdBook Action + uses: peaceiris/actions-mdbook@v1.1.11 + with: + mdbook-version: '0.3.1' + # mdbook-version: 'latest' + + - name: Remove cargo-config + run: rm -f .cargo/config + + - name: Build docs + run: cargo doc + + - name: Build books + run: | + langs=( en ru ) + latest=0.5 + vers=( 0.4.x ) + + # Create directories + td=$(mktemp -d) + mkdir -p $td/$latest/book/ + cp -r target/doc $td/$latest/api + + # sed fixes + sed 's|URL|rtfm/index.html|g' redirect.html > $td/$latest/api/index.html + sed 's|URL|0.5|g' redirect.html > $td/index.html + sed 's|URL|book/en|g' redirect.html > $td/$latest/index.html + + # Build books + for lang in ${langs[@]}; do + ( cd book/$lang && mdbook build ) + cp -r book/$lang/book $td/$latest/book/$lang + cp LICENSE-* $td/$latest/book/$lang/ + done + + # Build older versions + root=$(pwd) + for ver in ${vers[@]}; do + prefix=${ver%.*} + + mkdir -p $td/$prefix/book + src=$(mktemp -d) + curl -L https://github.com/rtfm-rs/cortex-m-rtfm/archive/v${ver}.tar.gz | tar xz --strip-components 1 -C $src + + pushd $src + rm -f .cargo/config + cargo doc || cargo doc --features timer-queue + cp -r target/doc $td/$prefix/api + sed 's|URL|rtfm/index.html|g' $root/redirect.html > $td/$prefix/api/index.html + for lang in ${langs[@]}; do + ( cd book/$lang && mdbook build ) + cp -r book/$lang/book $td/$prefix/book/$lang + cp LICENSE-* $td/$prefix/book/$lang/ + done + sed 's|URL|book/en|g' $root/redirect.html > $td/$prefix/index.html + popd + + rm -rf $src + done + + # Forward CNAME file + cp CNAME $td/ + mv $td/ bookstodeploy + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./bookstodeploy diff --git a/.travis.yml b/.travis.yml index 1bb25051..c2651307 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,7 @@ before_install: install: - bash ci/install.sh - export PATH="$PATH:$PWD/qemu" + - export PATH="$PATH:$PWD/mdbook-bin" script: - bash ci/script.sh @@ -39,6 +39,10 @@ name = "t-cfg" required-features = ["__v7"] [[example]] +name = "t-cfg-resources" +required-features = ["__min_r1_43"] + +[[example]] name = "t-schedule" required-features = ["__v7"] @@ -47,12 +51,15 @@ name = "types" required-features = ["__v7"] [dependencies] -cortex-m = "0.6.0" +cortex-m = "0.6.2" cortex-m-rtfm-macros = { path = "macros", version = "0.5.0" } rtfm-core = "0.3.0" cortex-m-rt = "0.6.9" heapless = "0.5.0" +[build-dependencies] +version_check = "0.9" + [dependencies.microamp] optional = true version = "0.1.0-alpha.2" @@ -74,6 +81,7 @@ heterogeneous = ["cortex-m-rtfm-macros/heterogeneous", "microamp"] homogeneous = ["cortex-m-rtfm-macros/homogeneous"] # used for testing this crate; do not use in applications __v7 =[] +__min_r1_43 =[] [profile.release] codegen-units = 1 diff --git a/book/en/src/by-example/app.md b/book/en/src/by-example/app.md index f6871942..2450c59a 100644 --- a/book/en/src/by-example/app.md +++ b/book/en/src/by-example/app.md @@ -70,7 +70,7 @@ so it must run forever. When no `idle` function is declared, the runtime sets the [SLEEPONEXIT] bit and then sends the microcontroller to sleep after running `init`. -[SLEEPONEXIT]: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit +[SLEEPONEXIT]: https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit Like in `init`, `static mut` variables will be transformed into `&'static mut` references that are safe to access. @@ -103,10 +103,10 @@ mut` variables are safe to use within a hardware task. ``` ``` console -$ cargo run --example interrupt +$ cargo run --example hardware {{#include ../../../../ci/expected/hardware.run}}``` -So far all the RTFM applications we have seen look no different that the +So far all the RTFM applications we have seen look no different than the applications one can write using only the `cortex-m-rt` crate. From this point we start introducing features unique to RTFM. @@ -115,7 +115,7 @@ we start introducing features unique to RTFM. The static priority of each handler can be declared in the `task` attribute using the `priority` argument. Tasks can have priorities in the range `1..=(1 << NVIC_PRIO_BITS)` where `NVIC_PRIO_BITS` is a constant defined in the `device` -crate. When the `priority` argument is omitted the priority is assumed to be +crate. When the `priority` argument is omitted, the priority is assumed to be `1`. The `idle` task has a non-configurable static priority of `0`, the lowest priority. @@ -135,17 +135,17 @@ The following example showcases the priority based scheduling of tasks. ``` ``` console -$ cargo run --example interrupt +$ cargo run --example preempt {{#include ../../../../ci/expected/preempt.run}}``` Note that the task `gpiob` does *not* preempt task `gpioc` because its priority is the *same* as `gpioc`'s. However, once `gpioc` terminates the execution of -task `gpiob` is prioritized over `gpioa`'s due to its higher priority. `gpioa` +task, `gpiob` is prioritized over `gpioa` due to its higher priority. `gpioa` is resumed only after `gpiob` terminates. One more note about priorities: choosing a priority higher than what the device supports (that is `1 << NVIC_PRIO_BITS`) will result in a compile error. Due to -limitations in the language the error message is currently far from helpful: it +limitations in the language, the error message is currently far from helpful: it will say something along the lines of "evaluation of constant value failed" and the span of the error will *not* point out to the problematic interrupt value -- we are sorry about this! diff --git a/book/en/src/by-example/resources.md b/book/en/src/by-example/resources.md index b33ca9bb..db7630ea 100644 --- a/book/en/src/by-example/resources.md +++ b/book/en/src/by-example/resources.md @@ -11,7 +11,7 @@ All resources are declared as a single `struct` within the `#[app]` pseudo-module. Each field in the structure corresponds to a different resource. Resources can optionally be given an initial value using the `#[init]` attribute. Resources that are not given an initial value are referred to as -*late* resources and are covered in more detail in a follow up section in this +*late* resources and are covered in more detail in a follow-up section in this page. Each context (task handler, `init` or `idle`) must declare the resources it @@ -31,7 +31,7 @@ access to a resource named `shared`. $ cargo run --example resource {{#include ../../../../ci/expected/resource.run}}``` -Note that the `shared` resource cannot accessed from `idle`. Attempting to do +Note that the `shared` resource cannot be accessed from `idle`. Attempting to do so results in a compile error. ## `lock` @@ -75,14 +75,14 @@ $ cargo run --example lock ## Late resources -Late resources are resources that are not given an initial value at compile -using the `#[init]` attribute but instead are initialized are runtime using the +Late resources are resources that are not given an initial value at compile time +using the `#[init]` attribute but instead are initialized at runtime using the `init::LateResources` values returned by the `init` function. Late resources are useful for *moving* (as in transferring the ownership of) peripherals initialized in `init` into interrupt handlers. -The example below uses late resources to stablish a lockless, one-way channel +The example below uses late resources to establish a lockless, one-way channel between the `UART0` interrupt handler and the `idle` task. A single producer single consumer [`Queue`] is used as the channel. The queue is split into consumer and producer end points in `init` and then each end point is stored diff --git a/book/ru/src/by-example/app.md b/book/ru/src/by-example/app.md index 7dc08127..884257dd 100644 --- a/book/ru/src/by-example/app.md +++ b/book/ru/src/by-example/app.md @@ -66,7 +66,7 @@ $ cargo run --example init Когда функция `idle` не определена, рантайм устанавливает бит [SLEEPONEXIT], после чего отправляет микроконтроллер в состояние сна после выполнения `init`. -[SLEEPONEXIT]: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit +[SLEEPONEXIT]: https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit Как и в `init`, переменные `static mut`будут преобразованы в ссылки `&'static mut` с безопасным доступом. @@ -1,8 +1,13 @@ use std::env; +use version_check; fn main() { let target = env::var("TARGET").unwrap(); + if version_check::Channel::read().unwrap().is_nightly() { + println!("cargo:rustc-cfg=rustc_is_nightly") + } + if target.starts_with("thumbv6m") { println!("cargo:rustc-cfg=armv6m") } diff --git a/ci/install.sh b/ci/install.sh index 54701224..624efd87 100644 --- a/ci/install.sh +++ b/ci/install.sh @@ -15,7 +15,6 @@ main() { fi rustup target add $TARGET - mkdir qemu curl -L https://github.com/japaric/qemu-bin/raw/master/14.04/qemu-system-arm-2.12.0 > qemu/qemu-system-arm chmod +x qemu/qemu-system-arm @@ -23,7 +22,13 @@ main() { pip install linkchecker --user fi - install_crate mdbook 0.3.1 + # Download binary mdbook and add to path + curl -L https://github.com/rust-lang/mdBook/releases/download/v0.3.1/mdbook-v0.3.1-x86_64-unknown-linux-gnu.tar.gz > mdbook.tar.gz + tar -xf mdbook.tar.gz + mkdir -p mdbook-bin + mv mdbook mdbook-bin/ + + #install_crate mdbook 0.3.1 } main diff --git a/ci/script.sh b/ci/script.sh index 78341e1b..7743b8ba 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -36,6 +36,12 @@ main() { mkdir -p ci/builds + # Current MSRV cannot handle profiles, remove compilation optimisations + if [[ $TRAVIS_RUST_VERSION == 1.*.* ]]; then + echo "Removing optimisation profiles" + sed -i '/^\[profile.*build-override]$/,/^$/{/^#/!{/^$/!d}}' Cargo.toml + fi + if [ $T = x86_64-unknown-linux-gnu ]; then if [[ $TRAVIS_RUST_VERSION == 1.*.* ]]; then # test on a fixed version (MSRV) to avoid problems with changes in rustc diagnostics @@ -44,6 +50,13 @@ main() { fi if [ $TRAVIS_RUST_VERSION = nightly ]; then + # Tests where required MSRV > 1.36 + #local exs=( + #) + #for ex in ${exs[@]}; do + # cargo check --example $ex --target $T + #done + # multi-core compile-pass tests pushd heterogeneous local exs=( @@ -89,8 +102,18 @@ main() { if [ $TARGET = thumbv6m-none-eabi ]; then cargo check --target $T --examples + + # Check examples with specific features not compatible with MSRV + if [[ $TRAVIS_RUST_VERSION != 1.*.* ]]; then + cargo check --target $T --examples --features __min_r1_43 + fi else cargo check --target $T --examples --features __v7 + + # Check examples with specific features not compatible with MSRV + if [[ $TRAVIS_RUST_VERSION != 1.*.* ]]; then + cargo check --target $T --examples --features __v7,__min_r1_43 + fi fi cargo check -p homogeneous --target $T --examples diff --git a/examples/schedule.rs b/examples/schedule.rs index 97818e36..d5de9dbf 100644 --- a/examples/schedule.rs +++ b/examples/schedule.rs @@ -1,9 +1,11 @@ //! examples/schedule.rs +#![deny(unsafe_code)] #![deny(warnings)] #![no_main] #![no_std] +use cortex_m::peripheral::DWT; use cortex_m_semihosting::hprintln; use panic_halt as _; use rtfm::cyccnt::{Instant, U32Ext as _}; @@ -15,11 +17,12 @@ const APP: () = { fn init(mut cx: init::Context) { // Initialize (enable) the monotonic timer (CYCCNT) cx.core.DCB.enable_trace(); - // required on devices that software lock the DWT (e.g. STM32F7) - unsafe { cx.core.DWT.lar.write(0xC5ACCE55) } + // required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7) + DWT::unlock(); cx.core.DWT.enable_cycle_counter(); // semantically, the monotonic timer is frozen at time "zero" during `init` + // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value let now = cx.start; // the start time of the system hprintln!("init @ {:?}", now).unwrap(); diff --git a/examples/t-cfg-resources.rs b/examples/t-cfg-resources.rs new file mode 100644 index 00000000..a8efe79e --- /dev/null +++ b/examples/t-cfg-resources.rs @@ -0,0 +1,36 @@ +//! [compile-pass] check that `#[cfg]` attributes applied on resources work +//! +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtfm::app(device = lm3s6965)] +const APP: () = { + struct Resources { + // A resource + #[init(0)] + shared: u32, + + // A conditionally compiled resource behind feature_x + #[cfg(feature = "feature_x")] + x: u32, + + dummy: (), + } + + #[init] + fn init(_: init::Context) -> init::LateResources { + init::LateResources { + // The feature needs to be applied everywhere x is defined or used + #[cfg(feature = "feature_x")] + x: 0, + dummy: (), // dummy such that we have at least one late resource + } + } + + #[idle] + fn idle(_cx: idle::Context) -> ! { + loop {} + } +}; diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 02138481..60074849 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -39,7 +39,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let (const_app_init, root_init, user_init, call_init) = init::codegen(core, app, analysis, extra); - let (const_app_post_init, post_init_stmts) = post_init::codegen(core, analysis, extra); + let (const_app_post_init, post_init_stmts) = + post_init::codegen(core, &app, analysis, extra); let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(core, app, analysis, extra); diff --git a/macros/src/codegen/init.rs b/macros/src/codegen/init.rs index fc2faa34..534b79b0 100644 --- a/macros/src/codegen/init.rs +++ b/macros/src/codegen/init.rs @@ -44,8 +44,12 @@ pub fn codegen( .iter() .map(|name| { let ty = &app.late_resources[name].ty; + let cfgs = &app.late_resources[name].cfgs; - quote!(pub #name: #ty) + quote!( + #(#cfgs)* + pub #name: #ty + ) }) .collect::<Vec<_>>() }) diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs index 19773e45..b816e072 100644 --- a/macros/src/codegen/post_init.rs +++ b/macros/src/codegen/post_init.rs @@ -1,11 +1,13 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use rtfm_syntax::ast::App; use crate::{analyze::Analysis, check::Extra, codegen::util}; /// Generates code that runs after `#[init]` returns pub fn codegen( core: u8, + app: &App, analysis: &Analysis, extra: &Extra, ) -> (Vec<TokenStream2>, Vec<TokenStream2>) { @@ -16,8 +18,13 @@ pub fn codegen( if let Some(late_resources) = analysis.late_resources.get(&core) { for name in late_resources { // if it's live + let cfgs = app.late_resources[name].cfgs.clone(); if analysis.locations.get(name).is_some() { - stmts.push(quote!(#name.as_mut_ptr().write(late.#name);)); + // Need to also include the cfgs + stmts.push(quote!( + #(#cfgs)* + #name.as_mut_ptr().write(late.#name); + )); } } } diff --git a/macros/src/codegen/resources.rs b/macros/src/codegen/resources.rs index 8cb788d1..83bfabd7 100644 --- a/macros/src/codegen/resources.rs +++ b/macros/src/codegen/resources.rs @@ -101,9 +101,15 @@ pub fn codegen( )); let ptr = if expr.is_none() { - quote!(#name.as_mut_ptr()) + quote!( + #(#cfgs)* + #name.as_mut_ptr() + ) } else { - quote!(&mut #name) + quote!( + #(#cfgs)* + &mut #name + ) }; const_app.push(util::impl_mutex( diff --git a/src/cyccnt.rs b/src/cyccnt.rs index 338bbbea..6bc2ef0a 100644 --- a/src/cyccnt.rs +++ b/src/cyccnt.rs @@ -30,6 +30,10 @@ pub struct Instant { impl Instant { /// Returns an instant corresponding to "now" + /// + /// *HEADS UP* this function can, and will, return nonsensical values if called within `init`. + /// Only use it in `idle` and tasks. In `init`, use the `init::Context.start` field, or the + /// `CYCCNT::zero` function, instead of this function pub fn now() -> Self { Instant { inner: DWT::get_cycle_count() as i32, |