diff --git a/.github/actions/main-setup/action.yaml b/.github/actions/main-setup/action.yaml new file mode 100644 index 000000000..0e20fc3f3 --- /dev/null +++ b/.github/actions/main-setup/action.yaml @@ -0,0 +1,34 @@ +name: ot3-firmware Repo Setup +description: Setup for ot3-firmware Github Actions + +inputs: + cache-version: + description: CACHE_VERSION from secrets + required: true + +runs: + using: composite + steps: + - name: Update and install gcc-10 & g++-10 + shell: bash + run: | + sudo apt update + sudo apt install -y gcc-10 g++-10 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + + - name: Cache STM32 Tools + uses: actions/cache@v3 + id: cache-tools + with: + path: ${{ env.DEFAULT_DIRECTORY }}/stm32-tools + key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ inputs.cache-version }} + + - name: Setup opentrons monorepo + uses: actions/checkout@v4 + with: + repository: opentrons/opentrons + path: opentrons diff --git a/.github/workflows/bootloader.yaml b/.github/workflows/bootloader.yaml deleted file mode 100644 index c47dfddf2..000000000 --- a/.github/workflows/bootloader.yaml +++ /dev/null @@ -1,77 +0,0 @@ -name: "Bootloader build/test" -on: - pull_request: - paths: - - "bootloader/**" - - "common/**" - - "include/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "bootloader/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "bootloader/**" - - "common/**" - - "include/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "bootloader/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/bootloader.yaml" - branches: - - "*" - tags: - - "bootloader@*" - workflow_dispatch: - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure g4" - run: cmake --preset=cross . - - name: "Format" - run: cmake --build ./build-cross --target bootloader-format-ci - - name: "Build g4" - run: cmake --build --preset=bootloader - - name: "Lint" - run: cmake --build ./build-cross --target bootloader-lint - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target bootloader-build-and-test diff --git a/.github/workflows/build-simulators.yaml b/.github/workflows/build-simulators.yaml new file mode 100644 index 000000000..966a45def --- /dev/null +++ b/.github/workflows/build-simulators.yaml @@ -0,0 +1,66 @@ +name: "build simulators" +on: + push: + branches: + - "*" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + +defaults: + run: + shell: bash + working-directory: ot3-firmware + +jobs: + build-simulators: + strategy: + matrix: + target: [ + bootloader, + gantry-x, + gantry-y, + gripper, + head, + pipettes-single, + pipettes-multi, + pipettes-96, + ] + name: ${{ matrix.target }} simulator + runs-on: "ubuntu-20.04" + timeout-minutes: 10 + steps: + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 + with: + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Configure + run: cmake --preset=host-gcc10 . + + - name: setup state manager + run: cmake --build ./build-host --target state-manager-setup + + - name: Build Simulator + run: cmake --build ./build-host --target ${{ matrix.target }}-simulator + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }}-simulator-${{ github.ref_name }} + path: ./ot3-firmware/build-host/*/simulator/*-simulator diff --git a/.github/workflows/build-tests.yaml b/.github/workflows/build-tests.yaml new file mode 100644 index 000000000..b6fbfd09d --- /dev/null +++ b/.github/workflows/build-tests.yaml @@ -0,0 +1,45 @@ +name: "build-and-test" +on: + push: + branches: + - "*" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + +defaults: + run: + shell: bash + working-directory: ot3-firmware + +jobs: + build-and-test: + name: Run all tests + runs-on: "ubuntu-20.04" + timeout-minutes: 10 + steps: + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 + with: + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Configure + run: cmake --preset=host-gcc10 . + + - name: Test + run: cmake --build ./build-host --target build-and-test diff --git a/.github/workflows/can.yaml b/.github/workflows/can.yaml deleted file mode 100644 index 509416590..000000000 --- a/.github/workflows/can.yaml +++ /dev/null @@ -1,75 +0,0 @@ -name: "Can build/test" -on: - pull_request: - paths: - - "can/**" - - "include/can/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "can/**" - - "include/can/**" - - "include/common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/can.yaml" - branches: - - "*" - tags: - - "can@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=debug - - name: "Format" - run: cmake --build ./build-cross --target can-format-ci - - name: "Build" - run: cmake --build ./build-cross --target can - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target can-build-and-test diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 8d38a9f7b..e7d171bbb 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -12,43 +12,57 @@ env: defaults: run: shell: bash + working-directory: ot3-firmware +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true jobs: generate-coverage: name: 'Generate-Coverage' runs-on: 'ubuntu-20.04' timeout-minutes: 10 - env: - CC: gcc-10 - CXX: g++-10 steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 lcov - - uses: actions/setup-python@v4 + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 with: - python-version: '3.10' - - name: 'Install lcov_cobertura module' - run: pip install lcov_cobertura - - uses: 'actions/checkout@v2' + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 with: - fetch-depth: 0 - - uses: "actions/cache@v3" + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: 'Configure' + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Install LCOV + run: sudo apt install -y lcov + + - name: Install lcov_cobertura module + run: pip install lcov_cobertura + + - name: Configure run: cmake --preset=host-gcc10 -DENABLE_COVERAGE=On -DCMAKE_BUILD_TYPE=Debug - - name: 'Run all tests' + + - name: Run all tests run: cmake --build --preset tests - - name: 'Generate coverage' + + - name: Generate coverage run: cmake --build --preset tests --target lcov-geninfo - - name: 'Convert coverage to xml' + + - name: Convert coverage to xml run: lcov_cobertura build-host/lcov/data/capture/all_targets.info + - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: - files: ./coverage.xml + files: ot3-firmware/coverage.xml name: codecov-ot3-firmware fail_ci_if_error: true diff --git a/.github/workflows/common.yaml b/.github/workflows/common.yaml deleted file mode 100644 index c6bda9e19..000000000 --- a/.github/workflows/common.yaml +++ /dev/null @@ -1,75 +0,0 @@ -name: "Common build/test" -on: - pull_request: - paths: - - "common/**" - - "include/common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "common/**" - - "include/common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/common.yaml" - branches: - - "*" - tags: - - "common@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=debug - - name: "Format" - run: cmake --build ./build-cross --target common-format-ci - # TODO (AL 2021-07-09) - uncomment when adding common-lint is added - - name: "Build" - run: cmake --build ./build-cross --target common - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target common-build-and-test diff --git a/.github/workflows/cross-compile-all.yaml b/.github/workflows/cross-compile-all.yaml new file mode 100644 index 000000000..c298273f2 --- /dev/null +++ b/.github/workflows/cross-compile-all.yaml @@ -0,0 +1,128 @@ +name: "cross-compile/format/lint all targets" +on: + push: + branches: + - "*" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref_name }} + cancel-in-progress: true + +defaults: + run: + shell: bash + working-directory: ot3-firmware + +jobs: + build-cross: + runs-on: "ubuntu-20.04" + timeout-minutes: 20 + strategy: + matrix: + target: [ + gantry-x, + gantry-y, + gripper, + head, + hepa-uv, + pipettes-single, + pipettes-multi, + pipettes-96, + rear-panel + ] + fail-fast: false + name: Build ${{ matrix.target }} + steps: + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 + with: + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Configure + run: cmake --preset=cross . + + - name: Build all STM32G4 applications + run: cmake --build --preset=${{ matrix.target }} --target ${{ matrix.target }}-images ${{ matrix.target }}-applications + + format: + runs-on: "ubuntu-20.04" + timeout-minutes: 20 + name: Formatting + steps: + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 + with: + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Configure + run: cmake --preset=cross . + + - name: Format + run: cmake --build ./build-cross --target format-ci + + lint: + runs-on: "ubuntu-20.04" + timeout-minutes: 20 + name: ${{ matrix.target }} lint + strategy: + matrix: + target: [ + bootloader, + gantry, + gripper, + head, + hepa-uv, + pipettes, + rear-panel + ] + steps: + - name: Checkout ot3-firmware repo + uses: actions/checkout@v4 + with: + path: ot3-firmware + + - name: Checkout github actions directory + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/actions + sparse-checkout-cone-mode: false + path: actions + + - name: Setup main + uses: ./actions/.github/actions/main-setup + with: + cache-version: ${{ secrets.CACHE_VERSION }} + + - name: Configure + run: cmake --preset=cross . + + - name: Format + run: cmake --build ./build-cross --target ${{ matrix.target }}-lint diff --git a/.github/workflows/eeprom.yaml b/.github/workflows/eeprom.yaml deleted file mode 100644 index 86381231f..000000000 --- a/.github/workflows/eeprom.yaml +++ /dev/null @@ -1,84 +0,0 @@ -name: "Eeprom build/test" -on: - pull_request: - paths: - - "eeprom/**" - - "i2c/**" - - "include/i2c/**" - - "include/eeprom/**" - - "common/**" - - "include/common/**" - - "common/**" - - "include/can/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "eeprom/**" - - "i2c/**" - - "include/i2c/**" - - "include/eeprom/**" - - "common/**" - - "include/common/**" - - "common/**" - - "include/can/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/eeprom.yaml" - branches: - - "*" - tags: - - "eeprom@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Format" - run: cmake --build ./build-cross --target eeprom-format-ci - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target eeprom-build-and-test diff --git a/.github/workflows/gantry.yaml b/.github/workflows/gantry.yaml deleted file mode 100644 index 51ff7ccd3..000000000 --- a/.github/workflows/gantry.yaml +++ /dev/null @@ -1,123 +0,0 @@ -name: "Gantry build/test" -on: - pull_request: - paths: - - "gantry/**" - - "common/**" - - "include/**" - - "spi/**" - - "!include/pipettes/**" - - "!include/head/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "gantry/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "gantry/**" - - "common/**" - - "include/**" - - "spi/**" - - "!include/pipettes/**" - - "!include/head/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "gantry/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/gantry.yaml" - branches: - - "*" - tags: - - "gantry@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 20 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Format" - run: cmake --build ./build-cross --target gantry-format-ci - - name: "Build" - run: cmake --build --preset=gantry --target gantry-images gantry-applications - - name: "Lint" - run: cmake --build ./build-cross --target gantry-lint - - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: "Configure" - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: 'Build and test' - run: cmake --build ./build-host --target gantry-build-and-test - working-directory: ot3-firmware - - - name: 'Setup state_manager' - run: cmake --build ./build-host/ --target state-manager-setup - working-directory: ot3-firmware - - - name: 'Build X simulator' - run: cmake --build ./build-host --target gantry-x-simulator - working-directory: ot3-firmware - - - name: 'Build Y simulator' - run: cmake --build ./build-host --target gantry-y-simulator - working-directory: ot3-firmware - - - name: "Upload simulator artifacts" - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: "gantry-simulators-${{github.ref_name}}" - path: | - build-host/gantry/simulator/gantry-*-simulator diff --git a/.github/workflows/gripper.yaml b/.github/workflows/gripper.yaml deleted file mode 100644 index d0d10cdf3..000000000 --- a/.github/workflows/gripper.yaml +++ /dev/null @@ -1,125 +0,0 @@ -name: "Gripper build/test" -on: - pull_request: - paths: - - "gripper/**" - - "common/**" - - "can/**" - - "spi/**" - - "motor-control/**" - - "include/**" - - "!include/pipettes/**" - - "!include/gantry/**" - - "!include/head/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "gripper/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "gripper/**" - - "common/**" - - "can/**" - - "spi/**" - - "motor-control/**" - - "include/**" - - "!include/pipettes/**" - - "!include/gantry/**" - - "!include/head/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "gripper/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/gripper.yaml" - branches: - - "*" - tags: - - "gripper@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 20 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Format" - run: cmake --build ./build-cross --target gripper-format-ci - - name: "Build" - run: cmake --build ./build-cross --target gripper-images gripper-applications - - name: "Lint" - run: cmake --build ./build-cross --target gripper-lint - - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: "Configure" - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: 'Build and test' - run: cmake --build ./build-host --target gripper-build-and-test - working-directory: ot3-firmware - - - name: 'Setup state_manager' - run: cmake --build ./build-host/ --target state-manager-setup - working-directory: ot3-firmware - - - name: 'Build simulator' - run: cmake --build ./build-host --target gripper-simulator - working-directory: ot3-firmware - - - name: "Upload artifacts" - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: "gripper-simulator-${{github.ref_name}}" - path: | - build-host/gripper/simulator/gripper-simulator diff --git a/.github/workflows/head.yaml b/.github/workflows/head.yaml deleted file mode 100644 index 1986d5287..000000000 --- a/.github/workflows/head.yaml +++ /dev/null @@ -1,122 +0,0 @@ -name: "Head build/test" -on: - pull_request: - paths: - - "head/**" - - "common/**" - - "can/**" - - "spi/**" - - "motor-control/**" - - "include/**" - - "!include/pipettes/**" - - "!include/gantry/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "head/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "head/**" - - "common/**" - - "can/**" - - "spi/**" - - "motor-control/**" - - "include/**" - - "!include/pipettes/**" - - "!include/gantry/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "head/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/head.yaml" - branches: - - "*" - tags: - - "head@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 20 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Format" - run: cmake --build ./build-cross --target head-format-ci - - name: "Build" - run: cmake --build ./build-cross --target head-exes head-images head-applications - - name: "Lint" - run: cmake --build ./build-cross --target head-lint - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: "Configure" - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: 'Build and test' - run: cmake --build ./build-host --target head-build-and-test - working-directory: ot3-firmware - - - name: 'Setup state_manager' - run: cmake --build ./build-host/ --target state-manager-setup - working-directory: ot3-firmware - - - name: 'Build simulator' - run: cmake --build ./build-host --target head-simulator - working-directory: ot3-firmware - - - name: 'Upload artifacts' - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: "head-simulator-${{github.ref_name}}" - path: | - build-host/head/simulator/head-simulator diff --git a/.github/workflows/i2c.yaml b/.github/workflows/i2c.yaml deleted file mode 100644 index 0a3e51c1f..000000000 --- a/.github/workflows/i2c.yaml +++ /dev/null @@ -1,76 +0,0 @@ -name: "i2c build/test" -on: - pull_request: - paths: - - "i2c/**" - - "include/i2c/**" - - "cmake/*" - - "!cmake/Arduino*" - - "include/common/**" - - "common/**" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "i2c/**" - - "include/i2c/**" - - "include/common/**" - - "common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/i2c.yaml" - branches: - - "*" - tags: - - "i2c@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=debug - - name: "Format" - run: cmake --build ./build-cross --target i2c-format-ci - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target i2c-build-and-test diff --git a/.github/workflows/motorcontrol.yaml b/.github/workflows/motorcontrol.yaml deleted file mode 100644 index 97199e352..000000000 --- a/.github/workflows/motorcontrol.yaml +++ /dev/null @@ -1,58 +0,0 @@ -name: "motor-control build/test" -on: - pull_request: - paths: - - "motor-control/**" - - "include/motor-control/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "motor-control/**" - - "include/motor-control/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/common.yaml" - branches: - - "*" - tags: - - "motor-control@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: "Format check" - run: cmake --build ./build-host --target motor-control-format-ci - - name: "Build and test" - run: cmake --build ./build-host --target motor-control-build-and-test diff --git a/.github/workflows/ot3_state_manager.yaml b/.github/workflows/ot3_state_manager.yaml deleted file mode 100644 index bc6ad38be..000000000 --- a/.github/workflows/ot3_state_manager.yaml +++ /dev/null @@ -1,77 +0,0 @@ -# This workflow runs test and lint on branch pushes that touch the -# state_manager project. - -name: 'state_manager Lint & Test' - -on: - push: - branches: - - 'main' - - 'release-*' - pull_request: - paths: - - 'state_manager/state_manager/**' - - 'state_manager/tests/**' - - 'state_manager/generate_state_manager_headers.py' - - 'state_manager/CMakeLists.txt' - - 'state_manager/pyproject.toml' - - '.github/workflows/state_manager.yaml' - workflow_dispatch: - -defaults: - run: - shell: bash - -jobs: - lint-test: - name: 'state_manager linting and tests' - runs-on: 'ubuntu-20.04' - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: actions/checkout@v3 - with: - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: "3.8" - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: Build Host - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: Setup repo - run: cmake --build --preset simulators - working-directory: ot3-firmware - - - name: Lint - run: cmake --build ./build-host/ --target state-manager-lint - working-directory: ot3-firmware - - - name: Test - run: cmake --build ./build-host/ --target state-manager-test - working-directory: ot3-firmware - - - name: Upload Coverage Report - uses: 'codecov/codecov-action@v2' - with: - files: ./ot3-firmware/state-manager/coverage.xml - flags: state-manager diff --git a/.github/workflows/pipettes.yaml b/.github/workflows/pipettes.yaml deleted file mode 100644 index c5d41914b..000000000 --- a/.github/workflows/pipettes.yaml +++ /dev/null @@ -1,133 +0,0 @@ -name: "Pipettes build/test" -on: - pull_request: - paths: - - "pipettes/**" - - "common/**" - - "can/**" - - "motor-control/**" - - "spi/**" - - "include/**" - - "!include/gantry/**" - - "!include/head/**" - - "i2c/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "pipettes/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "pipettes/**" - - "common/**" - - "can/**" - - "i2c/**" - - "spi/**" - - "motor-control/**" - - "include/**" - - "!include/gantry/**" - - "!include/head/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "pipettes/CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/pipettes.yaml" - branches: - - "*" - tags: - - "pipettes@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 20 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure current revs" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Build current revs" - run: cmake --build --preset=pipettes --target pipettes-images pipettes-applications - - name: "Lint" - run: cmake --build --preset=pipettes --target pipettes-lint - - name: "Format" - run: cmake --build --preset=pipettes --target pipettes-format-ci - - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 20 - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: "Configure" - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: 'Build and test' - run: cmake --build ./build-host --target pipettes-build-and-test - working-directory: ot3-firmware - - - name: 'Setup state_manager' - run: cmake --build ./build-host/ --target state-manager-setup - working-directory: ot3-firmware - - - name: 'Build single simulator' - run: cmake --build ./build-host --target pipettes-single-simulator - working-directory: ot3-firmware - - - name: 'Build multi simulator' - run: cmake --build ./build-host --target pipettes-multi-simulator - working-directory: ot3-firmware - - - name: 'Build 96 simulator' - run: cmake --build ./build-host --target pipettes-96-simulator - working-directory: ot3-firmware - - - name: "Upload artifacts" - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v3 - with: - name: "pipettes-simulators-${{github.ref_name}}" - path: | - build-host/pipettes/simulator/pipettes-*-simulator diff --git a/.github/workflows/rear_panel.yaml b/.github/workflows/rear_panel.yaml deleted file mode 100644 index 21268a872..000000000 --- a/.github/workflows/rear_panel.yaml +++ /dev/null @@ -1,80 +0,0 @@ -name: "rear-panel build/test" -on: - pull_request: - paths: - - "rear-panel/**" - - "include/rear-panel/**" - - "cmake/*" - - "!cmake/Arduino*" - - "include/common/**" - - "common/**" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "rear-panel/**" - - "include/rear-panel/**" - - "include/common/**" - - "common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/rear-panel.yaml" - branches: - - "*" - tags: - - "rear-panel@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=RelWithDebInfo - - name: "Format" - run: cmake --build ./build-cross --target rear-panel-format-ci - - name: "Lint" - run: cmake --build ./build-cross --target rear-panel-lint - - name: "Build" - run: cmake --build ./build-cross --target rear-panel-applications - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target rear-panel-build-and-test diff --git a/.github/workflows/sensors.yaml b/.github/workflows/sensors.yaml deleted file mode 100644 index eeb4eb2e5..000000000 --- a/.github/workflows/sensors.yaml +++ /dev/null @@ -1,102 +0,0 @@ -name: "Sensors build/test" -on: - pull_request: - paths: - - "i2c/**" - - "include/motor-control/core/**" - - "motor-control/core/**" - - "include/i2c/**" - - "common/**" - - "include/common/**" - - "include/sensors/**" - - "common/**" - - "include/can/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "include/motor-control/core/**" - - "motor-control/core/**" - - "i2c/**" - - "include/i2c/**" - - "common/**" - - "include/common/**" - - "include/sensors/**" - - "common/**" - - "include/can/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/sensors.yaml" - branches: - - "*" - tags: - - "sensors@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=debug - - name: "Format" - run: cmake --build ./build-cross --target sensors-format-ci - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - name: Update and install gcc-10 & g++-10 - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - - name: Checkout ot3-firmware repository - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - path: ot3-firmware - - - name: Checkout opentrons repository - uses: actions/checkout@v3 - with: - repository: "Opentrons/opentrons" - path: opentrons - - - name: Cache stm32-tools - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - - name: "Configure" - run: cmake --preset=host-gcc10 . - working-directory: ot3-firmware - - - name: 'Build and test' - run: cmake --build ./build-host --target sensors-build-and-test - working-directory: ot3-firmware diff --git a/.github/workflows/spi.yaml b/.github/workflows/spi.yaml deleted file mode 100644 index ed1d51247..000000000 --- a/.github/workflows/spi.yaml +++ /dev/null @@ -1,75 +0,0 @@ -name: "spi build/test" -on: - pull_request: - paths: - - "spi/**" - - "common/**" - - "include/spi/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - push: - paths: - - "spi/**" - - "common/**" - - "include/spi/**" - - "include/common/**" - - "cmake/*" - - "!cmake/Arduino*" - - "CMakeLists.txt" - - "CMakePresets.json" - - ".clang-format" - - ".clang-tidy" - - ".github/workflows/spi.yaml" - branches: - - "*" - tags: - - "spi@*" - workflow_dispatch: - -env: - ci: 1 - -defaults: - run: - shell: bash - -jobs: - cross-compile-check: - name: "Cross-Compile/Check" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=cross . -DCMAKE_BUILD_TYPE=debug - - name: "Format" - run: cmake --build ./build-cross --target spi-format-ci - host-compile-test: - name: "Host-Compile/Test" - runs-on: "ubuntu-20.04" - timeout-minutes: 10 - steps: - - run: | - sudo apt update - sudo apt install gcc-10 g++-10 - - uses: "actions/checkout@v2" - with: - fetch-depth: 0 - - uses: "actions/cache@v3" - with: - path: "./stm32-tools" - key: ${{ runner.os }}-${{ hashFiles('**/cmake/*') }}-${{ secrets.CACHE_VERSION }} - - name: "Configure" - run: cmake --preset=host-gcc10 . - - name: 'Build and test' - run: cmake --build ./build-host --target spi-build-and-test diff --git a/CMakeLists.txt b/CMakeLists.txt index bef77ac12..65aa199ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ add_subdir_for_archs(SUBDIR gantry ARCHS cortex-m4) add_subdir_for_archs(SUBDIR head ARCHS cortex-m4) add_subdir_for_archs(SUBDIR gripper ARCHS cortex-m4) add_subdir_for_archs(SUBDIR pipettes ARCHS cortex-m4 cortex-m33) +add_subdir_for_archs(SUBDIR hepa-uv ARCHS cortex-m4) list(REMOVE_DUPLICATES LINT_TARGETS) message(VERBOSE "Checking if cross-compiling.") @@ -141,6 +142,7 @@ file(GLOB_RECURSE SOURCES_FOR_FORMAT ./spi/*.hpp ./spi/*.cpp ./eeprom/*.hpp ./eeprom/*.cpp ./rear-panel/*.hpp ./rear-panel/*.cpp + ./hepa-uv/*.cpp ) # Targets for formatting. These are here rather than in individual target CMakeLists (e.g. diff --git a/CMakePresets.json b/CMakePresets.json index 18cf67ffb..de644b8f5 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -139,6 +139,17 @@ "gripper" ] }, + { + "name": "hepa-uv", + "displayName": "hepa-uv binary", + "description": "Build the hepa-uv cross binary", + "configurePreset": "cross", + "jobs": 4, + "targets": [ + "hepa-uv" + ] + }, + { "name": "gantry", "displayName": "gantry binaries", @@ -212,7 +223,8 @@ "bootloader-gripper-applications", "bootloader-pipettes-single-applications", "bootloader-pipettes-multi-applications", - "bootloader-pipettes-96-applications" + "bootloader-pipettes-96-applications", + "bootloader-hepa-uv-applications" ] }, { @@ -222,7 +234,6 @@ "configurePreset": "host", "jobs": 4, "targets": [ - "state-manager-setup", "bootloader-simulator", "head-simulator", "gantry-x-simulator", diff --git a/bootloader/firmware/stm32G4/CMakeLists.txt b/bootloader/firmware/stm32G4/CMakeLists.txt index 27520bfc5..8664cd97a 100644 --- a/bootloader/firmware/stm32G4/CMakeLists.txt +++ b/bootloader/firmware/stm32G4/CMakeLists.txt @@ -156,6 +156,25 @@ foreach_revision( NO_CREATE_INSTALL_RULES ) +set(hepauv_sources ${_g4_sources}) + +macro(hepauv_bootloader_loop) + target_link_libraries(${REVISION_TARGET} + PUBLIC STM32G491RETx_bootloader + STM32G4xx_Drivers_Bootloader + bootloader-core) + + target_compile_definitions(${REVISION_TARGET} PUBLIC node_id_hepa_uv) +endmacro() + +foreach_revision( + PROJECT_NAME bootloader-hepa-uv + CALL_FOREACH_REV hepauv_bootloader_loop + REVISIONS b1 + SOURCES hepauv_sources + NO_CREATE_IMAGE_HEX + NO_CREATE_INSTALL_RULES + ) target_include_directories(STM32G4xx_Drivers_Bootloader PUBLIC .) diff --git a/bootloader/firmware/stm32G4/node_id_stm32g4xx.c b/bootloader/firmware/stm32G4/node_id_stm32g4xx.c index 8e1ec9826..f2cf9629d 100644 --- a/bootloader/firmware/stm32G4/node_id_stm32g4xx.c +++ b/bootloader/firmware/stm32G4/node_id_stm32g4xx.c @@ -73,9 +73,11 @@ CANNodeId get_node_id(void) { #elif defined(node_id_pipette_left) return can_nodeid_pipette_left_bootloader; #elif defined(node_id_pipette_right) - return can_nodeid_pipette_right_bootloader + return can_nodeid_pipette_right_bootloader; #elif defined(node_id_pipette_dynamic) return get_dynamic_nodeid(); +#elif defined(node_id_hepa_uv) + return can_nodeid_hepa_uv_bootloader; #else #error "No node id" #endif diff --git a/common/firmware/gpio.c b/common/firmware/gpio.c index e58412d18..6a79511be 100644 --- a/common/firmware/gpio.c +++ b/common/firmware/gpio.c @@ -42,4 +42,4 @@ __attribute__((section( ".ccmram" ))) #endif bool gpio_is_set(void* port, uint16_t pin, uint8_t active_setting) { return HAL_GPIO_ReadPin(port, pin) == active_setting; -} +} \ No newline at end of file diff --git a/common/firmware/gpio.cpp b/common/firmware/gpio.cpp index fb4c58c2e..a6fafced2 100644 --- a/common/firmware/gpio.cpp +++ b/common/firmware/gpio.cpp @@ -24,4 +24,4 @@ __attribute__((section( ".ccmram" ))) auto gpio::is_set(const gpio::PinConfig& pc) -> bool { return gpio_is_set(pc.port, pc.pin, pc.active_setting); -} +} \ No newline at end of file diff --git a/gripper/firmware/motor_hardware_shared.c b/gripper/firmware/motor_hardware_shared.c index 6bb83221e..2017fd2e3 100644 --- a/gripper/firmware/motor_hardware_shared.c +++ b/gripper/firmware/motor_hardware_shared.c @@ -1,7 +1,6 @@ #include "motor_hardware.h" #include "system_stm32g4xx.h" - static motor_interrupt_callback timer_callback = NULL; static z_encoder_overflow_callback z_enc_overflow_callback = NULL; static diag0_interrupt_callback* diag0_callback = NULL; @@ -232,3 +231,12 @@ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { } } +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + if (GPIO_Pin == ESTOP_IN_PIN) { + #if PCBA_PRIMARY_REVISION != 'b' && PCBA_PRIMARY_REVISION != 'a' + HAL_GPIO_WritePin(EBRAKE_PORT, EBRAKE_PIN, GPIO_PIN_RESET); + #endif + // this keeps the motor disengaged when estop is released + HAL_GPIO_WritePin(Z_MOT_ENABLE_PORT, Z_MOT_ENABLE_PIN, GPIO_PIN_RESET); + } +} \ No newline at end of file diff --git a/gripper/firmware/stm32g4xx_it.c b/gripper/firmware/stm32g4xx_it.c index df86ca705..6a90023e6 100644 --- a/gripper/firmware/stm32g4xx_it.c +++ b/gripper/firmware/stm32g4xx_it.c @@ -198,10 +198,21 @@ void TIM7_IRQHandler(void) { call_motor_handler(); } +__attribute__((section(".ccmram"))) void EXTI2_IRQHandler(void) { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); } +/** + * @brief This function handles EXTI line[15:10] interrupts. + */ +__attribute__((section(".ccmram"))) +void EXTI15_10_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_10)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); + } +} + extern void xPortSysTickHandler(void); void SysTick_Handler(void) { HAL_IncTick(); diff --git a/gripper/firmware/stm32g4xx_it.h b/gripper/firmware/stm32g4xx_it.h index 3354a2cda..b5eb3bed8 100644 --- a/gripper/firmware/stm32g4xx_it.h +++ b/gripper/firmware/stm32g4xx_it.h @@ -48,6 +48,7 @@ void TIM3_IRQHandler(void); void TIM7_IRQHandler(void); void TIM8_CC_IRQHandler(void); void TIM8_UP_IRQHandler(void); +void EXTI15_10_IRQHandler(void); #ifdef __cplusplus } diff --git a/gripper/firmware/utility_gpio.c b/gripper/firmware/utility_gpio.c index 3eab7b052..b62451d06 100644 --- a/gripper/firmware/utility_gpio.c +++ b/gripper/firmware/utility_gpio.c @@ -68,9 +68,12 @@ static void estop_input_gpio_init() { /*Configure GPIO pin EStopin : PA10 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = ESTOP_IN_PIN; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(ESTOP_IN_PORT, &GPIO_InitStruct); + + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); } static void tool_detect_gpio_init(void) { diff --git a/head/firmware/motor_hardware.h b/head/firmware/motor_hardware.h index b3a760ee0..2cce7382f 100644 --- a/head/firmware/motor_hardware.h +++ b/head/firmware/motor_hardware.h @@ -15,6 +15,7 @@ extern TIM_HandleTypeDef htim3; typedef void (*motor_interrupt_callback)(); typedef void (*encoder_overflow_callback)(int32_t); typedef void (*diag0_interrupt_callback)(); + HAL_StatusTypeDef initialize_spi(SPI_HandleTypeDef* hspi); void initialize_timer(motor_interrupt_callback callback, encoder_overflow_callback left_enc_overflow_callback, diff --git a/head/firmware/motor_hardware_common.c b/head/firmware/motor_hardware_common.c index 8c9a22ff2..e895252fe 100644 --- a/head/firmware/motor_hardware_common.c +++ b/head/firmware/motor_hardware_common.c @@ -356,7 +356,17 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef *htim) { } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { - if (GPIO_Pin == GPIO_PIN_13) { + // disengage motor whenever estop is engaged + if (GPIO_Pin == GPIO_PIN_4) { + #if PCBA_PRIMARY_REVISION != 'b' && PCBA_PRIMARY_REVISION != 'a' + // right & left brake + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_5, GPIO_PIN_RESET); + #endif + + // disable both left and right enable pins + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); + } else if (GPIO_Pin == GPIO_PIN_13) { if (diag0_z_callback != NULL) { if (*diag0_z_callback != NULL) { (*diag0_z_callback)(); diff --git a/head/firmware/stm32g4xx_it.c b/head/firmware/stm32g4xx_it.c index 6cc5709bc..60100c6f2 100644 --- a/head/firmware/stm32g4xx_it.c +++ b/head/firmware/stm32g4xx_it.c @@ -144,6 +144,15 @@ void FDCAN1_IT0_IRQHandler(void) { HAL_FDCAN_IRQHandler(can_get_device_handle()); } +/** + * @brief This function handles EXTI line4 interrupt. + */ +void EXTI4_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); + } +} + /** * @brief This function handles TIM7 global interrupt. */ diff --git a/head/firmware/stm32g4xx_it.h b/head/firmware/stm32g4xx_it.h index 563c2a6ba..9bb73af46 100644 --- a/head/firmware/stm32g4xx_it.h +++ b/head/firmware/stm32g4xx_it.h @@ -42,6 +42,7 @@ void PendSV_Handler(void); void SysTick_Handler(void); void DMA1_Channel2_IRQHandler(void); void DMA1_Channel3_IRQHandler(void); +void EXTI4_IRQHandler(void); #ifdef __cplusplus } diff --git a/head/firmware/utility_hardware.c b/head/firmware/utility_hardware.c index 50a7a8aa4..7d7c91f96 100644 --- a/head/firmware/utility_hardware.c +++ b/head/firmware/utility_hardware.c @@ -62,30 +62,15 @@ void estop_input_gpio_init() { /*Configure GPIO pin EStopin : PB4 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_4; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); -} -void ebrake_gpio_init() { - __HAL_RCC_GPIOB_CLK_ENABLE(); - // left brake PB0 - // right brake PB5 - GPIO_InitTypeDef GPIO_InitStruct = {0}; - GPIO_InitStruct.Pin = GPIO_PIN_0; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); - - - GPIO_InitStruct.Pin = GPIO_PIN_5; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET); + HAL_NVIC_SetPriority(EXTI4_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(EXTI4_IRQn); } + void carrier_detect_gpio_init() { // Z/left: PC5 // A/right: PB2 @@ -109,7 +94,6 @@ void carrier_detect_gpio_init() { } void utility_gpio_init() { - ebrake_gpio_init(); carrier_detect_gpio_init(); limit_switch_gpio_init(); estop_input_gpio_init(); diff --git a/hepa-uv/CMakeLists.txt b/hepa-uv/CMakeLists.txt new file mode 100644 index 000000000..bc76be1a0 --- /dev/null +++ b/hepa-uv/CMakeLists.txt @@ -0,0 +1,33 @@ +# hepa-uv source tree + +add_subdirectory(core) + +if (${CMAKE_CROSSCOMPILING}) + if (${ARM_ARCH_TYPE} STREQUAL "cortex-m4") + add_subdirectory(firmware) + endif () +else () + add_subdirectory(simulator) + add_subdirectory(tests) +endif () + +file(GLOB_RECURSE HEPA_SOURCES_FOR_FORMAT ./*.cpp ./*.hpp ../include/hepa-uv/*.hpp) + +# Targets for formatting. These are here rather than in individual target CMakeLists (e.g. +# the ones in tests/ or firmware/) because they don't have semantic reasoning involved and +# can therefore operate on file globs, unlike lint/static analysis + +# Target for use during dev - edits files +add_custom_target( + hepa-uv-format + ALL + COMMAND ${Clang_CLANGFORMAT_EXECUTABLE} -style=file -i ${HEPA_SOURCES_FOR_FORMAT} +) + +# Target for use in ci - warnings are errors, doesn't edit files +add_custom_target( + hepa-uv-format-ci + COMMAND ${Clang_CLANGFORMAT_EXECUTABLE} -style=file -Werror --ferror-limit=0 -n ${HEPA_SOURCES_FOR_FORMAT} +) + +set(LINT_TARGETS ${LINT_TARGETS} PARENT_SCOPE) diff --git a/hepa-uv/core/CMakeLists.txt b/hepa-uv/core/CMakeLists.txt new file mode 100644 index 000000000..b1474e65a --- /dev/null +++ b/hepa-uv/core/CMakeLists.txt @@ -0,0 +1,8 @@ +function(target_hepa_uv_core TARGET) + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/can_tasks.cpp + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tasks.cpp) + target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR}) + target_link_libraries(${TARGET} PUBLIC common-core) + target_include_directories(${TARGET} INTERFACE ${CMAKE_SOURCE_DIR}/cpp-utils/include) +endfunction() diff --git a/hepa-uv/core/can_tasks.cpp b/hepa-uv/core/can_tasks.cpp new file mode 100644 index 000000000..73d1e1b73 --- /dev/null +++ b/hepa-uv/core/can_tasks.cpp @@ -0,0 +1,126 @@ +#include + +#include "hepa-uv/core/can_task.hpp" + +using namespace can::dispatch; + +static auto& main_queues = hepauv_tasks::get_main_queues(); + +auto can_sender_queue = freertos_message_queue::FreeRTOSMessageQueue< + can::message_writer_task::TaskMessage>{}; + +/** Handler of system messages. */ +static auto system_message_handler = + can::message_handlers::system::SystemMessageHandler{ + main_queues, + version_get()->version, + version_get()->flags, + std::span(std::cbegin(version_get()->sha), + std::cend(version_get()->sha)), + revision_get()->primary, + revision_get()->secondary}; +static auto system_dispatch_target = + can_task::SystemDispatchTarget{system_message_handler}; + +struct CheckForNodeId { + can::ids::NodeId node_id; + auto operator()(uint32_t arbitration_id) const { + auto arb = can::arbitration_id::ArbitrationId(arbitration_id); + auto _node_id = arb.node_id(); + return ((_node_id == node_id) || + (_node_id == can::ids::NodeId::broadcast) || + (_node_id == can::ids::NodeId::hepa_uv)); + } +}; + +/** Dispatcher to the various handlers */ +static auto main_dispatcher = can::dispatch::Dispatcher( + [](uint32_t arbitration_id) -> bool { + auto arb = can::arbitration_id::ArbitrationId(arbitration_id); + auto node_id = arb.node_id(); + return ((node_id == can::ids::NodeId::broadcast) || + (node_id == can::ids::NodeId::hepa_uv)); + }, + system_dispatch_target); + +auto static reader_message_buffer = + freertos_message_buffer::FreeRTOSMessageBuffer<1024>{}; +static auto reader_message_buffer_writer = + can::message_buffer::CanMessageBufferWriter(reader_message_buffer); + +/** + * New CAN message callback. + * + * @param identifier Arbitration id + * @param data Message data + * @param length Message data length + */ +void callback(void*, uint32_t identifier, uint8_t* data, uint8_t length) { + reader_message_buffer_writer.send_from_isr(identifier, data, + data + length); // NOLINT +} + +/** + * Entry point for the reader task. + * TODO (2021-12-15, AL): Most of what happens in this task should be moved out + * when we move to separate motor tasks. + */ +[[noreturn]] void can_task::CanMessageReaderTask::operator()( + can::bus::CanBus* can_bus) { + can_bus->set_incoming_message_callback(nullptr, callback); + + auto filter = can::arbitration_id::ArbitrationId(); + + // Accept broadcast + filter.node_id(can::ids::NodeId::broadcast); + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::to_fifo0, filter, + can::arbitration_id::ArbitrationId::node_id_bit_mask); + + // TODO: add HEPA/UV filter + filter.node_id(can::ids::NodeId::hepa_uv); + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::to_fifo1, filter, + can::arbitration_id::ArbitrationId::node_id_bit_mask); + + // Reject everything else. + can_bus->add_filter(CanFilterType::mask, CanFilterConfig::reject, 0, 0); + + auto poller = can::freertos_dispatch::FreeRTOSCanBufferPoller( + reader_message_buffer, main_dispatcher); + poller(); +} + +auto static reader_task = can_task::CanMessageReaderTask{}; +auto static writer_task = can_task::CanMessageWriterTask{can_sender_queue}; + +auto static reader_task_control = + freertos_task::FreeRTOSTask<512, can_task::CanMessageReaderTask>{ + reader_task}; +auto static writer_task_control = + freertos_task::FreeRTOSTask<512, can_task::CanMessageWriterTask>{ + writer_task}; + +/** + * Start the can reader task + * @param canbus The can bus reference + * @return The task entry point. + */ +auto can_task::start_reader(can::bus::CanBus& canbus) + -> can_task::CanMessageReaderTask& { + LOG("Starting the CAN reader task"); + + reader_task_control.start(5, "can reader task", &canbus); + return reader_task; +} + +/** + * Start the can writer task + * @param canbus The can bus reference + * @return The task entry point + */ +auto can_task::start_writer(can::bus::CanBus& canbus) + -> can_task::CanMessageWriterTask& { + LOG("Starting the CAN writer task"); + + writer_task_control.start(5, "can writer task", &canbus); + return writer_task; +} diff --git a/hepa-uv/core/tasks.cpp b/hepa-uv/core/tasks.cpp new file mode 100644 index 000000000..fe7b3b8f0 --- /dev/null +++ b/hepa-uv/core/tasks.cpp @@ -0,0 +1,82 @@ +#include "hepa-uv/core/tasks.hpp" + +#include "common/core/freertos_task.hpp" +#include "common/core/freertos_timer.hpp" +#include "hepa-uv/core/can_task.hpp" +#include "hepa-uv/firmware/gpio_drive_hardware.hpp" +#include "hepa-uv/firmware/utility_gpio.h" + +#pragma GCC diagnostic push +// NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) +#pragma GCC diagnostic ignored "-Wvolatile" +#pragma GCC diagnostic pop + +static auto tasks = hepauv_tasks::AllTask{}; +static auto queues = hepauv_tasks::QueueClient{can::ids::NodeId::hepa_uv}; + +static auto hepa_task_builder = + freertos_task::TaskStarter<512, hepa_task::HepaTask>{}; + +static auto uv_task_builder = + freertos_task::TaskStarter<512, uv_task::UVTask>{}; + +static auto led_control_task_builder = + freertos_task::TaskStarter<512, led_control_task::LEDControlTask>{}; + +/** + * Start hepa_uv tasks. + */ +void hepauv_tasks::start_tasks( + can::bus::CanBus& can_bus, + gpio_drive_hardware::GpioDrivePins& gpio_drive_pins, + led_control_hardware::LEDControlHardware& led_hardware) { + auto& can_writer = can_task::start_writer(can_bus); + can_task::start_reader(can_bus); + + // TODO: including led_hardware for testing, this should be a AssesorClient + auto& hepa_task = + hepa_task_builder.start(5, "hepa_fan", gpio_drive_pins, queues); + auto& uv_task = + uv_task_builder.start(5, "uv_ballast", gpio_drive_pins, queues); + auto& led_control_task = + led_control_task_builder.start(5, "push_button_leds", led_hardware); + + tasks.hepa_task_handler = &hepa_task; + tasks.uv_task_handler = &uv_task; + tasks.led_control_task_handler = &led_control_task; + tasks.can_writer = &can_writer; + + queues.set_queue(&can_writer.get_queue()); + queues.hepa_queue = &hepa_task.get_queue(); + queues.uv_queue = &uv_task.get_queue(); + queues.led_control_queue = &led_control_task.get_queue(); +} + +hepauv_tasks::QueueClient::QueueClient(can::ids::NodeId this_fw) + : can::message_writer::MessageWriter{this_fw} {} + +void hepauv_tasks::QueueClient::send_hepa_message( + const hepa_task::TaskMessage& m) { + hepa_queue->try_write(m); +} + +void hepauv_tasks::QueueClient::send_uv_message(const uv_task::TaskMessage& m) { + uv_queue->try_write(m); +} + +void hepauv_tasks::QueueClient::send_led_control_message( + const led_control_task::TaskMessage& m) { + led_control_queue->try_write(m); +} + +/** + * Access to the tasks singleton + * @return + */ +auto hepauv_tasks::get_all_tasks() -> AllTask& { return tasks; } + +/** + * Access to the queues singleton + * @return + */ +auto hepauv_tasks::get_main_queues() -> QueueClient& { return queues; } diff --git a/hepa-uv/firmware/CMakeLists.txt b/hepa-uv/firmware/CMakeLists.txt new file mode 100644 index 000000000..1e2f1f16f --- /dev/null +++ b/hepa-uv/firmware/CMakeLists.txt @@ -0,0 +1,89 @@ +# This CMakeLists.txt handles everything that is compiled only when +# cross-compiling, like the board support packages and special options. +find_package(STM32G4xx) +include(RevisionHandling) +include(ClangTidy) + +set(COMMON_EXECUTABLE_DIR "${CMAKE_SOURCE_DIR}/common/firmware") +set(CAN_FW_DIR "${CMAKE_SOURCE_DIR}/can/firmware") + +set(REVISIONS hepa-rev1) + +# Add source files that should be checked by clang-tidy here +set(HEPA_UV_FW_LINTABLE_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/freertos_idle_timer_task.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/led_control_task/led_control_hardware.cpp + ${COMMON_EXECUTABLE_DIR}/system/iwdg.cpp + ${CAN_FW_DIR}/hal_can_bus.cpp + ${CAN_FW_DIR}/utils.c + ${CAN_FW_DIR}/hal_can.c + ) + +set(HEPAUV_FW_NON_LINTABLE_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/system_stm32g4xx.c + ${CMAKE_CURRENT_SOURCE_DIR}/stm32g4xx_it.c + ${CMAKE_CURRENT_SOURCE_DIR}/clocking.c + ${CMAKE_CURRENT_SOURCE_DIR}/utility_gpio.c + ${CMAKE_CURRENT_SOURCE_DIR}/led_hardware.c + ${CMAKE_CURRENT_SOURCE_DIR}/can.c + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_setup.c + ${COMMON_EXECUTABLE_DIR}/errors/errors.c + ${COMMON_EXECUTABLE_DIR}/system/app_update.c + ${COMMON_EXECUTABLE_DIR}/system/iwdg.c + ) + +set(HEPAUV_SRCS_B1 + ${HEPA_UV_FW_LINTABLE_SRCS} + ${HEPAUV_FW_NON_LINTABLE_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/main_rev1.cpp +) +set(HEPAUV_SRCS_C1 ${HEPAUV_SRCS_B1}) +set(HEPAUV_SRCS_C2 ${HEPAUV_SRCS_C1}) + +macro(hepa_uv_loop) + set(_driver_suffix ${PROJECT_NAME}_${REVISION}) + add_STM32G4_driver(${_driver_suffix}) + add_STM32G4_freertos(${_driver_suffix}) + + target_include_directories(STM32G4xx_Drivers_${_driver_suffix} + PUBLIC .) + target_include_directories(STM32G4xx_FreeRTOS_${_driver_suffix} + PUBLIC .) + + target_compile_definitions(STM32G4xx_Drivers_${_driver_suffix} + PUBLIC STM32G491xx) + target_compile_definitions(STM32G4xx_FreeRTOS_${_driver_suffix} + PUBLIC STM32G491xx) + + set_target_properties( + STM32G4xx_FreeRTOS_${_driver_suffix} + PROPERTIES FREERTOS_HEAP_IMPLEMENTATION "heap_5") + + target_hepa_uv_core(${REVISION_TARGET}) + target_ot_motor_control(${REVISION_TARGET}) + + target_i2c_firmware(${REVISION_TARGET}) + + target_link_libraries(${REVISION_TARGET} + PUBLIC STM32G491RETx + STM32G4xx_Drivers_${_driver_suffix} STM32G4xx_FreeRTOS_${_driver_suffix} + can-core) + install_if_latest_revision( + FILENAME ${REVISION_HEX_IMAGE_FILE} + COMPONENT hepauv-images + THISREVISION ${REVISION} + REVISIONS ${REVISIONS} + ) +endmacro() + +foreach_revision( + PROJECT_NAME hepa-uv + REVISIONS b1 + SOURCES HEPAUV_SRCS_B1 + CALL_FOREACH_REV hepa_uv_loop) + +alias_for_revision(PROJECT_NAME hepa-uv REVISION b1 REVISION_ALIAS rev1) + +add_clang_tidy_target( + TARGET_NAME hepa-uv-lint + LINT_SOURCES ${HEPA_UV_FW_LINTABLE_SRCS}) diff --git a/hepa-uv/firmware/FreeRTOSConfig.h b/hepa-uv/firmware/FreeRTOSConfig.h new file mode 100644 index 000000000..be6b09bf3 --- /dev/null +++ b/hepa-uv/firmware/FreeRTOSConfig.h @@ -0,0 +1,175 @@ +/* + * FreeRTOS Kernel V10.0.1 + * 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 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * this is a template configuration files + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * These parameters and more are described within the 'configuration' section of + *the FreeRTOS API documentation available on the FreeRTOS.org web site. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +/* CMSIS-RTOSv2 defines 56 levels of priorities. To be able to use them + * all and avoid application misbehavior, + * configUSE_PORT_OPTIMISED_TASK_SELECTION must be set to 0 and + * configMAX_PRIORITIES to 56 + * + */ +/* #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0*/ +/* #define configMAX_PRIORITIES ( 56 ) */ +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES (7) +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMINIMAL_STACK_SIZE ((uint16_t)128) +#define configTOTAL_HEAP_SIZE ((size_t)(15 * 1024)) +#define configMAX_TASK_NAME_LEN (16) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 0 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 8 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (6) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 + +/*------------- CMSIS-RTOS V2 specific defines -----------*/ +/* When using CMSIS-RTOSv2 set configSUPPORT_STATIC_ALLOCATION to 1 + * is mandatory to avoid compile errors. + * CMSIS-RTOS V2 implmentation requires the following defines + * +#define configSUPPORT_STATIC_ALLOCATION 1 <-- cmsis_os threads are +created using xTaskCreateStatic() API #define configMAX_PRIORITIES (56) <-- +Priority range in CMSIS-RTOS V2 is [0 .. 56] #define +configUSE_PORT_OPTIMISED_TASK_SELECTION 0 <-- when set to 1, +configMAX_PRIORITIES can't be more than 32 which is not suitable for the new +CMSIS-RTOS v2 priority range +*/ + +/* the CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation +used + * by the application thus the correct define need to be enabled from the list + * below + * +//define USE_FreeRTOS_HEAP_1 +//define USE_FreeRTOS_HEAP_2 +//define USE_FreeRTOS_HEAP_3 +//define USE_FreeRTOS_HEAP_4 +//define USE_FreeRTOS_HEAP_5 +*/ + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY \ + (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY \ + (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +/* IMPORTANT: FreeRTOS is using the SysTick as internal time base, thus make + sure the system and peripherials are using a different time base (TIM based + for example). + */ +#define xPortSysTickHandler FreeRTOS_SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/hepa-uv/firmware/can.c b/hepa-uv/firmware/can.c new file mode 100644 index 000000000..cd7d8a9c9 --- /dev/null +++ b/hepa-uv/firmware/can.c @@ -0,0 +1,85 @@ +#include "common/firmware/can.h" + +/** + * Initialize a connection to FDCAN1 + * + * @param handle Pointer to an FDCAN handle + * @return HAL_OK on success + */ +HAL_StatusTypeDef MX_FDCAN1_Init( + FDCAN_HandleTypeDef* handle, + uint8_t clock_divider, + uint8_t segment_1_tqs, + uint8_t segment_2_tqs, + uint8_t max_sync_jump_width) { + handle->Instance = FDCAN1; + handle->Init.ClockDivider = FDCAN_CLOCK_DIV1; + handle->Init.FrameFormat = FDCAN_FRAME_FD_NO_BRS; + handle->Init.Mode = FDCAN_MODE_NORMAL; + handle->Init.AutoRetransmission = ENABLE; + handle->Init.TransmitPause = DISABLE; + handle->Init.ProtocolException = DISABLE; + handle->Init.NominalPrescaler = clock_divider; + handle->Init.NominalSyncJumpWidth = max_sync_jump_width; + handle->Init.NominalTimeSeg1 = segment_1_tqs; + handle->Init.NominalTimeSeg2 = segment_2_tqs; + handle->Init.DataPrescaler = clock_divider; + handle->Init.DataSyncJumpWidth = max_sync_jump_width; + handle->Init.DataTimeSeg1 = segment_1_tqs; + handle->Init.DataTimeSeg2 = segment_2_tqs; + handle->Init.StdFiltersNbr = 20; + handle->Init.ExtFiltersNbr = 20; + handle->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; + return HAL_FDCAN_Init(handle); +} + + +/** + * @brief FDCAN MSP Initialization + * This function configures the hardware resources used in this example + * @param hfdcan: FDCAN handle pointer + * @retval None + */ +void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (hfdcan->Instance == FDCAN1) { + /* Peripheral clock enable */ + __HAL_RCC_FDCAN_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**FDCAN1 GPIO Configuration + PA11 ------> FDCAN1_RX + PA12 ------> FDCAN1_TX + */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + // Priority is 0-15 (highest to lowest). Use lowest priority until we + // believe it is too low. + HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 15, 15); + HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn); + } +} + +/** + * @brief FDCAN MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hfdcan: FDCAN handle pointer + * @retval None + */ +void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan) { + if (hfdcan->Instance == FDCAN1) { + /* Peripheral clock disable */ + __HAL_RCC_FDCAN_CLK_DISABLE(); + + /**FDCAN1 GPIO Configuration + PA11 ------> FDCAN1_RX + PA12 ------> FDCAN1_TX + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12); + } +} diff --git a/hepa-uv/firmware/clocking.c b/hepa-uv/firmware/clocking.c new file mode 100644 index 000000000..efe930690 --- /dev/null +++ b/hepa-uv/firmware/clocking.c @@ -0,0 +1,19 @@ +#include "common/firmware/clocking.h" + +#include "common/firmware/errors.h" +#include "stm32g4xx_hal_conf.h" + +void RCC_Peripheral_Clock_Select() { + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + PeriphClkInit.PeriphClockSelection = + RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_FDCAN | RCC_PERIPHCLK_I2C2 | + RCC_PERIPHCLK_I2C3; + PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2; + PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL; + PeriphClkInit.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1; + PeriphClkInit.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { + Error_Handler(); + } +} diff --git a/hepa-uv/firmware/freertos_idle_timer_task.cpp b/hepa-uv/firmware/freertos_idle_timer_task.cpp new file mode 100644 index 000000000..39cf620f8 --- /dev/null +++ b/hepa-uv/firmware/freertos_idle_timer_task.cpp @@ -0,0 +1,42 @@ +/* + * Configuration for the FreeRTOS idle task, which is necessary when we told it + * we're using static allocation. Provides the same configuration as the other + * stacks, but in callback form (vApplicationGetIdleTaskMemory is called by the + * RTOS internals) + */ + +#include + +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" + +StaticTask_t + idle_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +StaticTask_t + idle_timer_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_timer_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// This is a callback defined in a C file so it has to be linked as such +extern "C" void vApplicationGetIdleTaskMemory( + StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { + // Same configuration as in the other tasks, but a smaller stack + *ppxIdleTaskTCBBuffer = &idle_task_tcb; + *ppxIdleTaskStackBuffer = idle_task_stack.data(); + *pulIdleTaskStackSize = idle_task_stack.size(); +} + +extern "C" void vApplicationGetTimerTaskMemory( + StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize) { + *ppxTimerTaskTCBBuffer = &idle_timer_tcb; + *ppxTimerTaskStackBuffer = idle_timer_stack.data(); + *pulTimerTaskStackSize = idle_timer_stack.size(); +} diff --git a/hepa-uv/firmware/i2c_setup.c b/hepa-uv/firmware/i2c_setup.c new file mode 100644 index 000000000..2c31b5e51 --- /dev/null +++ b/hepa-uv/firmware/i2c_setup.c @@ -0,0 +1,173 @@ +#include "hepa-uv/firmware/i2c_setup.h" + +#include "common/firmware/errors.h" +#include "platform_specific_hal_conf.h" + +#define EEPROM_GPIO_BANK GPIOC +#define EEPROM_GPIO_PIN GPIO_PIN_12 + +static I2C_HandleTypeDef hi2c2; +static I2C_HandleTypeDef hi2c3; + +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + __HAL_RCC_GPIOC_CLK_ENABLE(); + + if (hi2c->Instance == I2C2) { + // PIN PC4 is SCL + // PIN PA8 is SDA + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init( + GPIOA, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + + GPIO_InitStruct.Pin = GPIO_PIN_4; + HAL_GPIO_Init( + GPIOC, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + __HAL_RCC_I2C2_CLK_ENABLE(); + + HAL_NVIC_SetPriority(I2C2_EV_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C2_EV_IRQn); + HAL_NVIC_SetPriority(I2C2_ER_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C2_ER_IRQn); + } + + if (hi2c->Instance == I2C3) { + // PIN PC8 is SCL + // PIN PC9 is SDA + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF8_I2C3; + HAL_GPIO_Init( + GPIOC, // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + &GPIO_InitStruct); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast) + __HAL_RCC_I2C3_CLK_ENABLE(); + + HAL_NVIC_SetPriority(I2C3_EV_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C3_EV_IRQn); + HAL_NVIC_SetPriority(I2C3_ER_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(I2C3_ER_IRQn); + } +} + +HAL_I2C_HANDLE MX_I2C2_Init() { + hi2c2.Instance = I2C2; + hi2c2.Init.Timing = 0x10C0ECFF; + hi2c2.Init.OwnAddress1 = 0; + hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c2.Init.OwnAddress2 = 0; + hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c2) != HAL_OK) { + Error_Handler(); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != + HAL_OK) { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK) { + Error_Handler(); + } + return &hi2c2; +} + +HAL_I2C_HANDLE MX_I2C3_Init() { + hi2c3.Instance = I2C3; + hi2c3.Init.Timing = 0x10C0ECFF; + hi2c3.Init.OwnAddress1 = 0; + hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c3.Init.OwnAddress2 = 0; + hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c3) != HAL_OK) { + Error_Handler(); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != + HAL_OK) { + Error_Handler(); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK) { + Error_Handler(); + } + return &hi2c3; +} + +/** + * @brief enable the eeprom write protect pin. + */ +void eeprom_write_protect_init(void) { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + + /*Configure GPIO pin : C12 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = EEPROM_GPIO_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(EEPROM_GPIO_BANK, &GPIO_InitStruct); +} + +/** + * @brief enable writing to the eeprom. + */ +void enable_eeprom_write() { + HAL_GPIO_WritePin(GPIOC, EEPROM_GPIO_PIN, GPIO_PIN_RESET); +} + +/** + * @brief disable writing to the eeprom. + */ +void disable_eeprom_write() { + HAL_GPIO_WritePin(GPIOC, EEPROM_GPIO_PIN, GPIO_PIN_SET); +} + +void i2c_setup(I2CHandlerStruct* i2c_handles) { + HAL_I2C_HANDLE i2c2 = MX_I2C2_Init(); + i2c_handles->i2c2 = i2c2; + HAL_I2C_HANDLE i2c3 = MX_I2C3_Init(); + i2c_handles->i2c3 = i2c3; + eeprom_write_protect_init(); + + // write protect the eeprom. + disable_eeprom_write(); +} + +void I2C2_EV_IRQHandler(void) +{ + HAL_I2C_EV_IRQHandler(&hi2c2); +} + +void I2C2_ER_IRQHandler(void) +{ + HAL_I2C_ER_IRQHandler(&hi2c2); +} + +void I2C3_EV_IRQHandler(void) +{ + HAL_I2C_EV_IRQHandler(&hi2c3); +} + +void I2C3_ER_IRQHandler(void) +{ + HAL_I2C_ER_IRQHandler(&hi2c3); +} diff --git a/hepa-uv/firmware/led_control_task/led_control_hardware.cpp b/hepa-uv/firmware/led_control_task/led_control_hardware.cpp new file mode 100644 index 000000000..e14822e75 --- /dev/null +++ b/hepa-uv/firmware/led_control_task/led_control_hardware.cpp @@ -0,0 +1,17 @@ +#include "hepa-uv/firmware/led_control_hardware.hpp" + +#include "hepa-uv/core/led_control_task.hpp" +#include "hepa-uv/firmware/led_hardware.h" + +using namespace led_control_hardware; + +// NOLINTNEXTLINE(readability-convert-member-functions-to-static) +auto LEDControlHardware::initialize() -> void { + button_led_hw_initialize_leds(); +} + +void LEDControlHardware::set_button_led_power(uint8_t button, uint32_t r, + uint32_t g, uint32_t b, + uint32_t w) { + set_button_led_pwm(static_cast(button), r, g, b, w); +} \ No newline at end of file diff --git a/hepa-uv/firmware/led_hardware.c b/hepa-uv/firmware/led_hardware.c new file mode 100644 index 000000000..976bf5eb0 --- /dev/null +++ b/hepa-uv/firmware/led_hardware.c @@ -0,0 +1,297 @@ +#include "hepa-uv/firmware/led_hardware.h" +#include "hepa-uv/firmware/utility_gpio.h" +#include "common/firmware/errors.h" + +#include "platform_specific_hal_conf.h" +#include "system_stm32g4xx.h" + +TIM_HandleTypeDef htim1; +TIM_HandleTypeDef htim8; +TIM_HandleTypeDef htim16; +TIM_HandleTypeDef htim20; + +TIM_OC_InitTypeDef htim1_sConfigOC = {0}; +TIM_OC_InitTypeDef htim8_sConfigOC = {0}; +TIM_OC_InitTypeDef htim16_sConfigOC = {0}; +TIM_OC_InitTypeDef htim20_sConfigOC = {0}; + + +uint32_t round_closest(uint32_t dividend, uint32_t divisor) { + return (dividend + (divisor / 2)) / divisor; +} + +uint32_t calc_prescaler(uint32_t timer_clk_freq, uint32_t counter_clk_freq) { + return timer_clk_freq >= counter_clk_freq + ? round_closest(timer_clk_freq, counter_clk_freq) - 1U + : 0U; +} + +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_pwm) { + if(htim_pwm->Instance == TIM1) { + __HAL_RCC_TIM1_CLK_ENABLE(); + } else if(htim_pwm->Instance == TIM8) { + __HAL_RCC_TIM8_CLK_ENABLE(); + } else if(htim_pwm->Instance == TIM16) { + __HAL_RCC_TIM16_CLK_ENABLE(); + } else if(htim_pwm->Instance == TIM20) { + __HAL_RCC_TIM20_CLK_ENABLE(); + } +} + +void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (htim->Instance == TIM1) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**TIM1 GPIO Configuration + PA9 ------> TIM1_CH2 + PA10 ------> TIM1_CH3 + */ + GPIO_InitStruct.Pin = HEPA_R_CTRL_PIN | HEPA_W_CTRL_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF6_TIM1; + HAL_GPIO_Init(HEPA_R_CTRL_PORT, &GPIO_InitStruct); + + // PC5 ------> TIM1_CH4N + GPIO_InitStruct.Pin = UV_B_CTRL_PIN; + HAL_GPIO_Init(UV_B_CTRL_PORT, &GPIO_InitStruct); + } else if (htim->Instance == TIM8) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + /**TIM8 GPIO Configuration + PB0 ------> TIM8_CH2N + PB1 ------> TIM8_CH3N + */ + GPIO_InitStruct.Pin = UV_G_CTRL_PIN | UV_R_CTRL_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF4_TIM8; + HAL_GPIO_Init(UV_G_CTRL_PORT, &GPIO_InitStruct); + + /* + PC6 ------> TIM8_CH1 + */ + GPIO_InitStruct.Pin = HEPA_G_CTRL_PIN; + HAL_GPIO_Init(HEPA_G_CTRL_PORT, &GPIO_InitStruct); + } else if (htim->Instance == TIM16) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**TIM16 GPIO Configuration + PB4 ------> TIM16_CH1 + */ + GPIO_InitStruct.Pin = HEPA_B_CTRL_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF1_TIM16; + HAL_GPIO_Init(HEPA_B_CTRL_PORT, &GPIO_InitStruct); + } else if (htim->Instance == TIM20) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**TIM20 GPIO Configuration + PB2 ------> TIM20_CH1 + */ + GPIO_InitStruct.Pin = UV_W_CTRL_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF3_TIM20; + HAL_GPIO_Init(UV_W_CTRL_PORT, &GPIO_InitStruct); + } +} + +/** + * @brief TIM Initialization Function for the LED timers. + * @param tim Pointer to the timer we are configuring + * @retval None + */ +static void MX_TIM_Init(TIM_TypeDef* tim) { + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; + + TIM_HandleTypeDef* htim; + TIM_OC_InitTypeDef* htim_sConfigOC; + unsigned int channels[3]; + int channels_size = 0; + if (tim == TIM1){ + htim = &htim1; + htim_sConfigOC = &htim1_sConfigOC; + /* Channels + HEPA_R_CTRL -> ch2 + HEPA_W_CTRL -> ch3 + UV_B_CTRL -> ch4 + */ + channels_size = 3; + channels[0] = TIM_CHANNEL_2; + channels[1] = TIM_CHANNEL_3; + channels[2] = TIM_CHANNEL_4; + } else if (tim == TIM8) { + htim = &htim8; + htim_sConfigOC = &htim8_sConfigOC; + /* Channels + HEPA_G_CTRL -> ch1 + UV_G_CTRL -> ch2 + UV_R_CTRL -> ch3 + */ + channels_size = 3; + channels[0] = TIM_CHANNEL_1; + channels[1] = TIM_CHANNEL_2; + channels[2] = TIM_CHANNEL_3; + } else if (tim == TIM16) { + htim = &htim16; + htim_sConfigOC = &htim16_sConfigOC; + /* Channels + HEPA_B_CTRL -> ch1 + */ + channels_size = 1; + channels[0] = TIM_CHANNEL_1; + } else if (tim == TIM20) { + htim = &htim20; + htim_sConfigOC = &htim20_sConfigOC; + /* Channels + UV_W_CTRL -> ch1 + */ + channels_size = 1; + channels[0] = TIM_CHANNEL_1; + } else { + Error_Handler(); + return; + } + + htim->State = HAL_TIM_STATE_RESET; + htim->Instance = tim; + /* + * Setting counter clock frequency to 2 kHz + */ + htim->Init.Prescaler = + calc_prescaler(SystemCoreClock, LED_TIMER_FREQ); + htim->Init.CounterMode = TIM_COUNTERMODE_UP; + htim->Init.Period = LED_PWM_WIDTH - 1; + htim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim->Init.RepetitionCounter = 0; + htim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(htim) != HAL_OK) { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(htim, &sClockSourceConfig) != HAL_OK) { + Error_Handler(); + } + if (HAL_TIM_PWM_Init(htim) != HAL_OK) { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(htim, &sMasterConfig) != + HAL_OK) { + Error_Handler(); + } + htim_sConfigOC->OCMode = TIM_OCMODE_PWM1; + /* Set duty cycle at 0% */ + htim_sConfigOC->Pulse = 0; + htim_sConfigOC->OCPolarity = TIM_OCPOLARITY_HIGH; + htim_sConfigOC->OCNPolarity = TIM_OCNPOLARITY_HIGH; + htim_sConfigOC->OCFastMode = TIM_OCFAST_DISABLE; + htim_sConfigOC->OCIdleState = TIM_OCIDLESTATE_RESET; + htim_sConfigOC->OCNIdleState = TIM_OCNIDLESTATE_RESET; + + // Enable the corresponding channels for this timer + for (int i = 0; i < channels_size; i++) { + if (HAL_TIM_PWM_ConfigChannel(htim, htim_sConfigOC, channels[i]) != + HAL_OK) { + Error_Handler(); + } + } + + sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; + sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; + sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; + sBreakDeadTimeConfig.DeadTime = 0; + sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; + sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; + sBreakDeadTimeConfig.BreakFilter = 0; + sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; + sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; + sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; + sBreakDeadTimeConfig.Break2Filter = 0; + sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; + sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; + if (HAL_TIMEx_ConfigBreakDeadTime(htim, &sBreakDeadTimeConfig) != + HAL_OK) { + Error_Handler(); + } + HAL_TIM_MspPostInit(htim); +} + +void button_led_hw_update_pwm(uint32_t duty_cycle, LED_TYPE led, PUSH_BUTTON_TYPE button) { + + // TODO: fix this + if (button == HEPA_BUTTON) { + switch(led) { + case RED_LED: + htim1.Instance->CCR2 = duty_cycle; + break; + case GREEN_LED: + htim8.Instance->CCR1 = duty_cycle; + break; + case BLUE_LED: + htim16.Instance->CCR1 = duty_cycle; + break; + case WHITE_LED: + htim1.Instance->CCR3 = duty_cycle; + break; + default: + break; + } + } else if (button == UV_BUTTON) { + switch(led) { + case RED_LED: + htim8.Instance->CCR3 = duty_cycle; + break; + case GREEN_LED: + htim8.Instance->CCR2 = duty_cycle; + break; + case BLUE_LED: + htim1.Instance->CCR4 = duty_cycle; + break; + case WHITE_LED: + htim20.Instance->CCR1=duty_cycle; + break; + default: + break; + } + } +} + +void set_button_led_pwm(PUSH_BUTTON_TYPE button, uint32_t red, uint32_t green, uint32_t blue, uint32_t white) { + button_led_hw_update_pwm(red, RED_LED, button); + button_led_hw_update_pwm(green, GREEN_LED, button); + button_led_hw_update_pwm(blue, BLUE_LED, button); + button_led_hw_update_pwm(white, WHITE_LED, button); +} + +void button_led_hw_initialize_leds() { + // Initialize the timers and channels + MX_TIM_Init(TIM1); + MX_TIM_Init(TIM8); + MX_TIM_Init(TIM16); + MX_TIM_Init(TIM20); + + // Set the the button LEDS to idle (white) + set_button_led_pwm(HEPA_BUTTON, 0, 0, 0, 50); + set_button_led_pwm(UV_BUTTON, 0, 0, 0, 50); + + // Activate the channels + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); + HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3); + HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1); + HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1); + HAL_TIM_PWM_Start(&htim20, TIM_CHANNEL_1); + // Activate the complementary output + HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_4); + HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_2); + HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_3); +} diff --git a/hepa-uv/firmware/main_rev1.cpp b/hepa-uv/firmware/main_rev1.cpp new file mode 100644 index 000000000..f800b4996 --- /dev/null +++ b/hepa-uv/firmware/main_rev1.cpp @@ -0,0 +1,137 @@ +#include + +// clang-format off +#include "FreeRTOS.h" +#include "task.h" +#include "system_stm32g4xx.h" +#include "hepa-uv/firmware/i2c_setup.h" +// clang-format on +#pragma GCC diagnostic push +// NOLINTNEXTLINE(clang-diagnostic-unknown-warning-option) +#pragma GCC diagnostic ignored "-Wvolatile" +#include "stm32g4xx_hal.h" +#pragma GCC diagnostic pop + +#include "can/core/bit_timings.hpp" +#include "can/firmware/hal_can.h" +#include "can/firmware/hal_can_bus.hpp" +#include "common/core/app_update.h" +#include "common/firmware/clocking.h" +#include "common/firmware/gpio.hpp" +#include "common/firmware/iwdg.hpp" +#include "common/firmware/utility_gpio.h" +#include "hepa-uv/core/messages.hpp" +#include "hepa-uv/core/tasks.hpp" +#include "hepa-uv/firmware/led_control_hardware.hpp" +#include "hepa-uv/firmware/led_hardware.h" +#include "hepa-uv/firmware/utility_gpio.h" + +static auto iWatchdog = iwdg::IndependentWatchDog{}; + +/** + * The can bus. + */ +static auto canbus = can::hal::bus::HalCanBus( + can_get_device_handle(), + gpio::PinConfig{// NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = LED_DRIVE_PORT, + .pin = LED_DRIVE_PIN, + .active_setting = GPIO_PIN_RESET}); +// Unfortunately, these numbers need to be literals or defines +// to get the compile-time checks to work so we can't actually +// correctly rely on the hal to get these numbers - they need +// to be checked against current configuration. However, they are +// - clock input is 85MHz assuming the CAN is clocked from PCLK1 +// which has a clock divider of 2, and the system clock is 170MHZ +// - 50ns requested time quantum yields a 235ns actual +// - 250KHz bitrate requested yields 250312KHz actual +// - 88.3% sample point +// Should drive +// segment 1 = 73 quanta +// segment 2 = 11 quanta +// +// For the exact timing values these generate see +// can/tests/test_bit_timings.cpp +static constexpr auto can_bit_timings = + can::bit_timings::BitTimings<170 * can::bit_timings::MHZ, 100, + 500 * can::bit_timings::KHZ, 800>{}; + +static auto gpio_drive_pins = gpio_drive_hardware::GpioDrivePins{ + .door_open = + gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = DOOR_OPEN_MCU_PORT, + .pin = DOOR_OPEN_MCU_PIN, + .active_setting = DOOR_OPEN_MCU_AS}, + .reed_switch = + gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = REED_SW_MCU_PORT, + .pin = REED_SW_MCU_PIN, + .active_setting = REED_SW_MCU_AS}, + .hepa_push_button = + gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = HEPA_NO_MCU_PORT, + .pin = HEPA_NO_MCU_PIN, + }, + .uv_push_button = + gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = UV_NO_MCU_PORT, + .pin = UV_NO_MCU_PIN, + }, + .hepa_on_off = + gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = HEPA_ON_OFF_PORT, + .pin = HEPA_ON_OFF_PIN, + .active_setting = HEPA_ON_OFF_AS}, + .uv_on_off = gpio::PinConfig{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) + .port = UV_ON_OFF_MCU_PORT, + .pin = UV_ON_OFF_MCU_PIN, + .active_setting = UV_ON_OFF_AS}}; + +static auto& hepauv_queues = hepauv_tasks::get_main_queues(); + +extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + switch (GPIO_Pin) { + case DOOR_OPEN_MCU_PIN: + case REED_SW_MCU_PIN: + case HEPA_NO_MCU_PIN: + case UV_NO_MCU_PIN: + if (hepauv_queues.hepa_queue != nullptr) { + static_cast(hepauv_queues.hepa_queue->try_write_isr( + interrupt_task_messages::GPIOInterruptChanged{ + .pin = GPIO_Pin})); + } + if (hepauv_queues.uv_queue != nullptr) { + static_cast(hepauv_queues.uv_queue->try_write_isr( + interrupt_task_messages::GPIOInterruptChanged{ + .pin = GPIO_Pin})); + } + break; + default: + break; + } +} + +static auto led_hardware = led_control_hardware::LEDControlHardware(); + +auto main() -> int { + HardwareInit(); + RCC_Peripheral_Clock_Select(); + utility_gpio_init(); + button_led_hw_initialize_leds(); + + app_update_clear_flags(); + + canbus.start(can_bit_timings); + + hepauv_tasks::start_tasks(canbus, gpio_drive_pins, led_hardware); + + iWatchdog.start(6); + + vTaskStartScheduler(); +} diff --git a/hepa-uv/firmware/stm32g4xx_hal_conf.h b/hepa-uv/firmware/stm32g4xx_hal_conf.h new file mode 100644 index 000000000..791bd60e6 --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_hal_conf.h @@ -0,0 +1,396 @@ +/** + ****************************************************************************** + * @file stm32g4xx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32g4xx_hal_conf.h. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32G4xx_HAL_CONF_H +#define STM32G4xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_COMP_MODULE_ENABLED +#define HAL_CORDIC_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_CRC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FDCAN_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_FMAC_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_HRTIM_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_OPAMP_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_QSPI_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED + +/* ########################## Register Callbacks selection + * ############################## */ +/** + * @brief This is the list of modules where register callback can be used + */ + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U +#define USE_HAL_EXTI_REGISTER_CALLBACKS 0U +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U +#define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U +#define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U + +/* ########################## Oscillator Values adaptation + * ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your + * application. This value is used by the RCC HAL module to compute the system + * frequency (when HSE is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSE_VALUE) +#define HSE_VALUE (16000000UL) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined(HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT (100UL) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system + * frequency (when HSI is used as system clock source, directly or through the + * PLL). + */ +#if !defined(HSI_VALUE) +#define HSI_VALUE (16000000UL) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB FS and RNG. + * This internal oscillator is mainly dedicated to provide a high + * precision clock to the USB peripheral by means of a special Clock Recovery + * System (CRS) circuitry. When the CRS is not used, the HSI48 RC oscillator + * runs on it default frequency which is subject to manufacturing process + * variations. + */ +#if !defined(HSI48_VALUE) +#define HSI48_VALUE \ + (48000000UL) /*!< Value of the Internal High Speed oscillator for USB \ + FS/RNG in Hz. The real value my vary depending on \ + manufacturing process variations.*/ +#endif /* HSI48_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined(LSI_VALUE) +/*!< Value of the Internal Low Speed oscillator in Hz +The real value may vary depending on the variations in voltage and +temperature.*/ +#define LSI_VALUE (32000UL) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system + * frequency + */ +#if !defined(LSE_VALUE) +#define LSE_VALUE (32768UL) /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined(LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT (5000UL) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S and SAI peripherals + * This value is used by the I2S and SAI HAL modules to compute the I2S + * and SAI clock source frequency, this source is inserted directly through + * I2S_CKIN pad. + */ +#if !defined(EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE \ + (48000UL) /*!< Value of the External clock source in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ + +#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY \ + (0UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ + +#define USE_SPI_CRC 1U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32g4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32g4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32g4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32g4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32g4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32g4xx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED +#include "stm32g4xx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32g4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32g4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED +#include "stm32g4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32g4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32g4xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32g4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_FMAC_MODULE_ENABLED +#include "stm32g4xx_hal_fmac.h" +#endif /* HAL_FMAC_MODULE_ENABLED */ + +#ifdef HAL_HRTIM_MODULE_ENABLED +#include "stm32g4xx_hal_hrtim.h" +#endif /* HAL_HRTIM_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32g4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32g4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32g4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED +#include "stm32g4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32g4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32g4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32g4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_OPAMP_MODULE_ENABLED +#include "stm32g4xx_hal_opamp.h" +#endif /* HAL_OPAMP_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32g4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32g4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED +#include "stm32g4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32g4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32g4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32g4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32g4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32g4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32g4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32g4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32g4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32g4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32g4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32g4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) \ + ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions + ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32G4xx_HAL_CONF_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/stm32g4xx_it.c b/hepa-uv/firmware/stm32g4xx_it.c new file mode 100644 index 000000000..207ea169b --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_it.c @@ -0,0 +1,164 @@ +/** + ****************************************************************************** + * @file Templates/Src/stm32g4xx_it.c + * @author MCD Application Team + * @brief Main Interrupt Service Routines. + * This file provides template for all exceptions handler and + * peripherals interrupt service routine. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32g4xx_it.h" + +#include "FreeRTOSConfig.h" +#include "can/firmware/hal_can.h" +#include "stm32g4xx_hal.h" + +/** @addtogroup STM32G4xx_HAL_Examples + * @{ + */ + +/** @addtogroup Templates + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* External variables --------------------------------------------------------*/ +DMA_HandleTypeDef hdma_spi1_tx; +DMA_HandleTypeDef hdma_spi1_rx; + +/******************************************************************************/ +/* Cortex-M4 Processor Exceptions Handlers */ +/******************************************************************************/ + +/** + * @brief This function handles NMI exception. + * @param None + * @retval None + */ +void NMI_Handler(void) {} + +/** + * @brief This function handles Hard Fault exception. + * @param None + * @retval None + */ +void HardFault_Handler(void) { + /* Go to infinite loop when Hard Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Memory Manage exception. + * @param None + * @retval None + */ +void MemManage_Handler(void) { + /* Go to infinite loop when Memory Manage exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Bus Fault exception. + * @param None + * @retval None + */ +void BusFault_Handler(void) { + /* Go to infinite loop when Bus Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Usage Fault exception. + * @param None + * @retval None + */ +void UsageFault_Handler(void) { + /* Go to infinite loop when Usage Fault exception occurs */ + while (1) { + } +} + +/** + * @brief This function handles Debug Monitor exception. + * @param None + * @retval None + */ +void DebugMon_Handler(void) {} + +/******************************************************************************/ +/* STM32G4xx Peripherals Interrupt Handlers */ +/* Add here the Interrupt Handler for the used peripheral(s) (PPP), for the */ +/* available peripheral interrupt handler's name please refer to the startup */ +/* file (startup_stm32g4xxxx.s). */ +/******************************************************************************/ + +void EXTI2_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_2)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2); + } +} + +void EXTI9_5_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_7)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); + } +} + +void EXTI15_10_IRQHandler(void) { + if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_10)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10); + } else if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_11)) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11); + } +} + +/** + * @brief This function handles DMA1 channel2 global interrupt. + */ + __attribute__((section(".ccmram"))) +void DMA1_Channel2_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_spi1_rx); } + +/** + * @brief This function handles DMA1 channel3 global interrupt. + */ + __attribute__((section(".ccmram"))) +void DMA1_Channel3_IRQHandler(void) { HAL_DMA_IRQHandler(&hdma_spi1_tx); } + +/** + * @brief This function handles FDCAN1 interrupt 0. + */ + __attribute__((section(".ccmram"))) +void FDCAN1_IT0_IRQHandler(void) { + HAL_FDCAN_IRQHandler(can_get_device_handle()); +} + +extern void xPortSysTickHandler(void); +void SysTick_Handler(void) { + HAL_IncTick(); + xPortSysTickHandler(); +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/stm32g4xx_it.h b/hepa-uv/firmware/stm32g4xx_it.h new file mode 100644 index 000000000..152c80265 --- /dev/null +++ b/hepa-uv/firmware/stm32g4xx_it.h @@ -0,0 +1,56 @@ +/** + ****************************************************************************** + * @file Templates/Inc/stm32g4xx_it.h + * @author MCD Application Team + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32G4xx_IT_H +#define STM32G4xx_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macros -----------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void DMA1_Channel2_IRQHandler(void); +void DMA1_Channel3_IRQHandler(void); +void FDCAN1_IT0_IRQHandler(void); +void EXTI2_IRQHandler(void); +void EXTI9_5_IRQHandler(void); +void EXTI15_10_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif /* STM32G4xx_IT_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/system_stm32g4xx.c b/hepa-uv/firmware/system_stm32g4xx.c new file mode 100644 index 000000000..8c35abc77 --- /dev/null +++ b/hepa-uv/firmware/system_stm32g4xx.c @@ -0,0 +1,342 @@ +/** + ****************************************************************************** + * @file system_stm32g4xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32g4xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be + *used by the user application to setup the SysTick timer or configure other + *parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * After each device reset the HSI (16 MHz) is used as system clock source. + * Then SystemInit() function is called, in "startup_stm32g4xx.s" file, to + * configure the system clock before to branch to main program. + * + * This file configures the system clock as follows: + *============================================================================= + *----------------------------------------------------------------------------- + * System Clock source | HSI + *----------------------------------------------------------------------------- + * SYSCLK(Hz) | 16000000 + *----------------------------------------------------------------------------- + * HCLK(Hz) | 16000000 + *----------------------------------------------------------------------------- + * AHB Prescaler | 1 + *----------------------------------------------------------------------------- + * APB1 Prescaler | 1 + *----------------------------------------------------------------------------- + * APB2 Prescaler | 1 + *----------------------------------------------------------------------------- + * PLL_M | 1 + *----------------------------------------------------------------------------- + * PLL_N | 16 + *----------------------------------------------------------------------------- + * PLL_P | 7 + *----------------------------------------------------------------------------- + * PLL_Q | 2 + *----------------------------------------------------------------------------- + * PLL_R | 2 + *----------------------------------------------------------------------------- + * Require 48MHz for RNG | Disabled + *----------------------------------------------------------------------------- + *============================================================================= + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32g4xx_system + * @{ + */ + +/** @addtogroup STM32G4xx_System_Private_Includes + * @{ + */ + +#include "system_stm32g4xx.h" + +#include "stm32g4xx.h" +#include "stm32g4xx_hal.h" + +#include "common/firmware/errors.h" +#include "bootloader/firmware/constants.h" + +#if !defined(HSE_VALUE) +#define HSE_VALUE 16000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined(HSI_VALUE) +#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Defines + * @{ + */ + +/** + * The vector table is offset by the space reserved for our bootloader. This must + * align with the value in the linker script. + */ +#define VECT_TAB_OFFSET APP_OFFSET + +/******************************************************************************/ +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Variables + * @{ + */ +/* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock + frequency Note: If you use this function to configure the system clock; then + there is no need to call the 2 first functions listed above, since + SystemCoreClock variable is updated automatically. +*/ +uint32_t SystemCoreClock = HSE_VALUE; + +const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, + 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U}; +const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U}; + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system. + * @param None + * @retval None + */ + +void SystemInit(void) { +/* FPU settings ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << (10 * 2)) | + (3UL << (11 * 2))); /* set CP10 and CP11 Full Access */ +#endif + + /* Configure the Vector Table location add offset address + * ------------------*/ +#ifdef VECT_TAB_SRAM + SCB->VTOR = SRAM_BASE | + VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#else + SCB->VTOR = FLASH_BASE | + VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ +#endif +} + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 72000000 + * HCLK(Hz) = 72000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 2 + * APB2 Prescaler = 1 + * HSE Frequency(Hz) = 8000000 + * PREDIV = RCC_PREDIV_DIV1 (1) + * PLLMUL = RCC_PLL_MUL9 (9) + * Flash Latency(WS) = 2 + * @param None + * @retval None + */ +void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSIState = RCC_HSI_OFF; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; + RCC_OscInitStruct.PLL.PLLN = 85; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4); + PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or + * configure other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any + * configuration based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the + * HSI_VALUE(**) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the + * HSE_VALUE(***) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the + * HSE_VALUE(***) or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (**) HSI_VALUE is a constant defined in stm32g4xx_hal.h file (default + * value 16 MHz) but the real value may vary depending on the variations in + * voltage and temperature. + * + * (***) HSE_VALUE is a constant defined in stm32g4xx_hal.h file + * (default value 24 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using + * fractional value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) { + uint32_t tmp, pllvco, pllr, pllsource, pllm; + + /* Get SYSCLK source + * -------------------------------------------------------*/ + switch (RCC->CFGR & RCC_CFGR_SWS) { + case 0x04: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + + case 0x08: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + + case 0x0C: /* PLL used as system clock source */ + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SYSCLK = PLL_VCO / PLLR + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC); + pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4) + 1U; + if (pllsource == 0x02UL) /* HSI used as PLL clock source */ + { + pllvco = (HSI_VALUE / pllm); + } else /* HSE used as PLL clock source */ + { + pllvco = (HSE_VALUE / pllm); + } + pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8); + pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25) + 1U) * 2U; + SystemCoreClock = pllvco / pllr; + break; + + default: + break; + } + /* Compute HCLK clock frequency + * --------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK clock frequency */ + SystemCoreClock >>= tmp; +} + +void HardwareInit(void) { + HAL_Init(); + SystemClock_Config(); + SystemCoreClockUpdate(); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/system_stm32g4xx.h b/hepa-uv/firmware/system_stm32g4xx.h new file mode 100644 index 000000000..106ecdec0 --- /dev/null +++ b/hepa-uv/firmware/system_stm32g4xx.h @@ -0,0 +1,108 @@ +/** + ****************************************************************************** + * @file system_stm32g4xx.h + * @author MCD Application Team + * @brief CMSIS Cortex-M4 Device System Source File for STM32G4xx devices. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2019 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32g4xx_system + * @{ + */ + +/** + * @brief Define to prevent recursive inclusion + */ +#include + +#ifndef __SYSTEM_STM32G4XX_H +#define __SYSTEM_STM32G4XX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup STM32G4xx_System_Includes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Variables + * @{ + */ +/* The SystemCoreClock variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetSysClockFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock + frequency Note: If you use this function to configure the system clock; then + there is no need to call the 2 first functions listed above, since + SystemCoreClock variable is updated automatically. +*/ +extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ + +extern const uint8_t AHBPrescTable[16]; /*!< AHB prescalers table values */ +extern const uint8_t APBPrescTable[8]; /*!< APB prescalers table values */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32G4xx_System_Exported_Functions + * @{ + */ + +extern void SystemInit(void); +extern void SystemCoreClockUpdate(void); +void HardwareInit(void); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__SYSTEM_STM32G4XX_H */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/hepa-uv/firmware/utility_gpio.c b/hepa-uv/firmware/utility_gpio.c new file mode 100644 index 000000000..9bba75704 --- /dev/null +++ b/hepa-uv/firmware/utility_gpio.c @@ -0,0 +1,171 @@ +#include "hepa-uv/firmware/utility_gpio.h" + +#include "platform_specific_hal_conf.h" +#include "stm32g4xx_hal_gpio.h" + +/** + * @brief LED Drive Initialization Function + * @param None + * @retval None +*/ +void LED_drive_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA1 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = LED_DRIVE_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(LED_DRIVE_PORT, &GPIO_InitStruct); +} + +/** + * @brief Door Open GPIO Initialization Function + * @param None + * @retval None +*/ +void door_open_input_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*Configure GPIO pin DOOR_OPEN_MCU : PC7 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = DOOR_OPEN_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(DOOR_OPEN_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief Reed Switch GPIO Initialization Function + * @param None + * @retval None +*/ +void reed_switch_input_gpio_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*Configure GPIO pin REED_SW_MCU : PC11 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = REED_SW_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(REED_SW_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief AUX ID Initialization Function + * @param None + * @retval None +*/ +void aux_input_gpio_init(void) { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*Configure GPIO pin AUX_ID_MCU : PC12 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = AUX_ID_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + HAL_GPIO_Init(AUX_ID_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief Hepa Push Button GPIO Initialization Function + * @param None + * @retval None +*/ +void hepa_push_button_input_gpio_init(void) { + /*Configure Ports Clock Enable*/ + __HAL_RCC_GPIOB_CLK_ENABLE(); + /*Configure GPIO pin HEPA_NO_MCU : PB10 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = HEPA_NO_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(HEPA_NO_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief UV Push Button GPIO Initialization Function + * @param None + * @retval None +*/ +void uv_push_button_input_gpio_init(void) { + /*Configure Ports Clock Enable*/ + __HAL_RCC_GPIOC_CLK_ENABLE(); + /*Configure GPIO pin UV_NO_MCU : PC2 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = UV_NO_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(UV_NO_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief HEPA ON/OFF GPIO Initialization Function + * @param None + * @retval None +*/ +void hepa_on_off_output_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA7 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = HEPA_ON_OFF_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(HEPA_ON_OFF_PORT, &GPIO_InitStruct); +} + +/** + * @brief UV ON/OFF GPIO Initialization Function + * @param None + * @retval None +*/ +void uv_on_off_output_init() { + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + /*Configure GPIO pin LED_DRIVE : PA4 */ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = UV_ON_OFF_MCU_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_PULLDOWN; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(UV_ON_OFF_MCU_PORT, &GPIO_InitStruct); +} + +/** + * @brief NVIC EXTI interrupt priority Initialization + * @param None + * @retval None + */ +static void nvic_priority_enable_init() { + /* EXTI interrupt init DOOR_OPEN_MCU : PC7*/ + // PC7 -> GPIO_EXTI6 (EXTI9_5_IRQn) + HAL_NVIC_SetPriority(EXTI9_5_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); + + /* EXTI interrupt init REED_SW_MCU : PC11*/ + /* EXTI interrupt init HEPA_NO_MCU : PB10*/ + // PC11 -> GPIO_EXTI11 (EXTI15_10_IRQn) + // PB11 -> GPIO_EXTI11 (EXTI15_10_IRQn) + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); + + /* EXTI interrupt init UV_NO_MCU : PC2*/ + // PC2 -> GPIO_EXTI2 (EXTI2_IRQn) + HAL_NVIC_SetPriority(EXTI2_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(EXTI2_IRQn); +} + +void utility_gpio_init(void) { + LED_drive_gpio_init(); + nvic_priority_enable_init(); + door_open_input_gpio_init(); + reed_switch_input_gpio_init(); + aux_input_gpio_init(); + hepa_push_button_input_gpio_init(); + uv_push_button_input_gpio_init(); + hepa_on_off_output_init(); + uv_on_off_output_init(); +} diff --git a/hepa-uv/simulator/CMakeLists.txt b/hepa-uv/simulator/CMakeLists.txt new file mode 100644 index 000000000..a8ce6d81b --- /dev/null +++ b/hepa-uv/simulator/CMakeLists.txt @@ -0,0 +1,58 @@ +# Load free for the posix port +find_package(FreeRTOS) + +# Set up the include directories +include_directories( + . + ${CMAKE_CURRENT_SOURCE_DIR}/../../include + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/include + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils + +) + +# Create the FreeRTOS source file list +FILE( + GLOB FREERTOS_SOURCES + ${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/*.c +) + +# Add the posix port files +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/MemMang/heap_3.c") +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/utils/wait_for_event.c") +list(APPEND FREERTOS_SOURCES "${FreeRTOS_SOURCE_DIR}/FreeRTOS/Source/portable/ThirdParty/GCC/Posix/port.c") + + +# Create the freertos lib +add_library(freertos-hepa-uv STATIC ${FREERTOS_SOURCES}) + +set(HEPA_UV_SIMULATOR_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/freertos_idle_timer_task.cpp + ) + +add_executable( + hepa-uv-simulator + ${HEPA_UV_SIMULATOR_SRC} +) + +add_revision(TARGET hepa-uv-simulator REVISION a1) + + +if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux" AND DEFINED ENV{USE_SOCKETCAN}) + target_compile_definitions(hepa-uv-simulator PUBLIC USE_SOCKETCAN) +endif () + +target_compile_definitions(hepa-uv-simulator PUBLIC ENABLE_LOGGING) + +target_can_simlib(hepa-uv-simulator) + +target_hepa_uv_core(hepa-uv-simulator) + +target_link_libraries(hepa-uv-simulator PRIVATE can-core common-simulation freertos-hepa-uv pthread Boost::boost Boost::program_options state_manager) + +set_target_properties(hepa-uv-simulator + PROPERTIES CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE + C_STANDARD 11 + C_STANDARD_REQUIRED TRUE) diff --git a/hepa-uv/simulator/FreeRTOSConfig.h b/hepa-uv/simulator/FreeRTOSConfig.h new file mode 100644 index 000000000..ea2403deb --- /dev/null +++ b/hepa-uv/simulator/FreeRTOSConfig.h @@ -0,0 +1,182 @@ +/* + * FreeRTOS Kernel V10.0.1 + * 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 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. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/** + * This file is only present to support the FreeRTOS POSIX Port. + * + * TODO (AmitL, 2021-08-17): This file is entirely lifted from our FW projects. + * It should be specialized for the POSIX port. + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * this is a template configuration files + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * These parameters and more are described within the 'configuration' section of + *the FreeRTOS API documentation available on the FreeRTOS.org web site. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +/* Ensure stdint is only used by the compiler, and not the assembler. */ +#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__) +#include +extern uint32_t SystemCoreClock; +#endif + +/* CMSIS-RTOSv2 defines 56 levels of priorities. To be able to use them + * all and avoid application misbehavior, + * configUSE_PORT_OPTIMISED_TASK_SELECTION must be set to 0 and + * configMAX_PRIORITIES to 56 + * + */ +/* #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0*/ +/* #define configMAX_PRIORITIES ( 56 ) */ +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES (7) +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configCPU_CLOCK_HZ (SystemCoreClock) +#define configTICK_RATE_HZ ((TickType_t)1000) +#define configMINIMAL_STACK_SIZE ((uint16_t)128) +#define configTOTAL_HEAP_SIZE ((size_t)(64 * 1024)) +#define configMAX_TASK_NAME_LEN (16) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_MALLOC_FAILED_HOOK 0 +#define configUSE_APPLICATION_TASK_TAG 0 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configGENERATE_RUN_TIME_STATS 1 +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 8 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES (2) + +/* Software timer definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (6) +#define configTIMER_QUEUE_LENGTH 10 +#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 0 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 1 + +/*------------- CMSIS-RTOS V2 specific defines -----------*/ +/* When using CMSIS-RTOSv2 set configSUPPORT_STATIC_ALLOCATION to 1 + * is mandatory to avoid compile errors. + * CMSIS-RTOS V2 implmentation requires the following defines + * +#define configSUPPORT_STATIC_ALLOCATION 1 <-- cmsis_os threads are +created using xTaskCreateStatic() API #define configMAX_PRIORITIES (56) <-- +Priority range in CMSIS-RTOS V2 is [0 .. 56] #define +configUSE_PORT_OPTIMISED_TASK_SELECTION 0 <-- when set to 1, +configMAX_PRIORITIES can't be more than 32 which is not suitable for the new +CMSIS-RTOS v2 priority range +*/ + +/* the CMSIS-RTOS V2 FreeRTOS wrapper is dependent on the heap implementation +used + * by the application thus the correct define need to be enabled from the list + * below + * +//define USE_FreeRTOS_HEAP_1 +//define USE_FreeRTOS_HEAP_2 +//define USE_FreeRTOS_HEAP_3 +//define USE_FreeRTOS_HEAP_4 +//define USE_FreeRTOS_HEAP_5 +*/ + +/* Cortex-M specific definitions. */ +#ifdef __NVIC_PRIO_BITS +/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */ +#define configPRIO_BITS __NVIC_PRIO_BITS +#else +#define configPRIO_BITS 4 /* 15 priority levels */ +#endif + +/* The lowest interrupt priority that can be used in a call to a "set priority" +function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0xf + +/* The highest interrupt priority that can be used by any interrupt service +routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL +INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER +PRIORITY THAN THIS! (higher priorities are lower numeric values. */ +#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 + +/* Interrupt priorities used by the kernel port layer itself. These are generic +to all Cortex-M ports, and do not rely on any particular library functions. */ +#define configKERNEL_INTERRUPT_PRIORITY \ + (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY \ + (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS)) + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT(x) \ + if ((x) == 0) { \ + taskDISABLE_INTERRUPTS(); \ + for (;;) \ + ; \ + } + +/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS + standard names. */ +#define vPortSVCHandler SVC_Handler +#define xPortPendSVHandler PendSV_Handler + +/* IMPORTANT: FreeRTOS is using the SysTick as internal time base, thus make + sure the system and peripherials are using a different time base (TIM based + for example). + */ +#define xPortSysTickHandler SysTick_Handler + +#endif /* FREERTOS_CONFIG_H */ diff --git a/hepa-uv/simulator/freertos_idle_timer_task.cpp b/hepa-uv/simulator/freertos_idle_timer_task.cpp new file mode 100644 index 000000000..87b80a629 --- /dev/null +++ b/hepa-uv/simulator/freertos_idle_timer_task.cpp @@ -0,0 +1,43 @@ +/* + * Configuration for the FreeRTOS idle task, which is necessary when we told it + * we're using static allocation. Provides the same configuration as the other + * stacks, but in callback form (vApplicationGetIdleTaskMemory is called by the + * RTOS internals) + * + * This file is only present to support the FreeRTOS POSIX Port. + */ + +#include + +#include "FreeRTOS.h" +#include "task.h" + +StaticTask_t + idle_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + idle_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +StaticTask_t + timer_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +std::array + timer_task_stack; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// This is a callback defined in a C file so it has to be linked as such +extern "C" void vApplicationGetIdleTaskMemory( + StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize) { + // Same configuration as in the other tasks, but a smaller stack + *ppxIdleTaskTCBBuffer = &idle_task_tcb; + *ppxIdleTaskStackBuffer = idle_task_stack.data(); + *pulIdleTaskStackSize = idle_task_stack.size(); +} + +extern "C" void vApplicationGetTimerTaskMemory( + StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize) { + *ppxTimerTaskTCBBuffer = &timer_task_tcb; + *ppxTimerTaskStackBuffer = timer_task_stack.data(); + *pulTimerTaskStackSize = timer_task_stack.size(); +} diff --git a/hepa-uv/simulator/main.cpp b/hepa-uv/simulator/main.cpp new file mode 100644 index 000000000..b0918fb89 --- /dev/null +++ b/hepa-uv/simulator/main.cpp @@ -0,0 +1,90 @@ +#include + +#include +#include +#include + +#include "FreeRTOS.h" +#include "boost/program_options.hpp" +#include "can/simlib/sim_canbus.hpp" +#include "common/core/freertos_synchronization.hpp" +#include "common/core/freertos_task.hpp" +#include "common/simulation/state_manager.hpp" +#include "hepa-uv/core/tasks.hpp" +#include "hepa-uv/firmware/gpio_drive_hardware.hpp" +#include "task.h" + +namespace po = boost::program_options; + +void signal_handler(int signum) { + LOG("Interrupt signal (%d) received.", signum); + exit(signum); +} + +/** + * The CAN bus. + */ + +static std::shared_ptr> + state_manager_connection; + +static auto state_manager_task = state_manager::StateManagerTask< + freertos_synchronization::FreeRTOSCriticalSection>{}; + +static auto state_manager_task_control = + freertos_task::FreeRTOSTask<512, decltype(state_manager_task)>{ + state_manager_task}; + +auto handle_options(int argc, char** argv) -> po::variables_map { + auto cmdlinedesc = + po::options_description("simulator for the Flex HEPA/UV module."); + auto envdesc = po::options_description(""); + cmdlinedesc.add_options()("help,h", "Show this help message."); + auto can_arg_xform = can::sim::transport::add_options(cmdlinedesc, envdesc); + auto state_mgr_arg_xform = state_manager::add_options(cmdlinedesc, envdesc); + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, cmdlinedesc), vm); + if (vm.count("help")) { + std::cout << cmdlinedesc << std::endl; + std::exit(0); + } + po::store(po::parse_environment( + envdesc, + [can_arg_xform, state_mgr_arg_xform]( + const std::string& input_val) -> std::string { + auto can_xformed = can_arg_xform(input_val); + if (can_xformed != "") { + return can_xformed; + } + auto state_mgr_xformed = state_mgr_arg_xform(input_val); + return state_mgr_xformed; + }), + vm); + po::notify(vm); + return vm; +} + +static auto gpio_drive_pins = gpio_drive_hardware::GpioDrivePins{}; + +int main(int argc, char** argv) { + // TODO: (ba, 2024-01-18): Fix the simulator later on + signal(SIGINT, signal_handler); + + LOG_INIT("HEPA/UV", []() -> const char* { + return pcTaskGetName(xTaskGetCurrentTaskHandle()); + }); + auto options = handle_options(argc, argv); + + state_manager_connection = state_manager::create< + freertos_synchronization::FreeRTOSCriticalSection>(options); + state_manager_task_control.start(5, "state mgr task", + &state_manager_connection); + + static auto canbus = + can::sim::bus::SimCANBus(can::sim::transport::create(options)); + hepauv_tasks::start_tasks(canbus, gpio_drive_pins); + + vTaskStartScheduler(); +} diff --git a/hepa-uv/tests/CMakeLists.txt b/hepa-uv/tests/CMakeLists.txt new file mode 100644 index 000000000..97a2bcba0 --- /dev/null +++ b/hepa-uv/tests/CMakeLists.txt @@ -0,0 +1,40 @@ +# this CMakeLists.txt file is only used when host-compiling to build tests + +find_package(Catch2 REQUIRED) +include(CTest) +include(Catch) +include(AddBuildAndTestTarget) + +add_executable( + hepa-uv + test_main.cpp + test_leds.cpp +) + +target_include_directories(hepa-uv PUBLIC ${CMAKE_SOURCE_DIR}/include) +set_target_properties(hepa-uv + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED TRUE) + +target_compile_options(hepa-uv + PUBLIC + -Wall + -Werror + -Wextra + -Wno-missing-field-initializers + $<$:-Weffc++> + $<$:-Wreorder> + $<$:-Wsign-promo> + $<$:-Wextra-semi> + $<$:-Wctor-dtor-privacy> + $<$:-fno-rtti> +) +add_revision(TARGET hepa-uv REVISION b1) + +target_link_libraries(hepa-uv Catch2::Catch2) + +catch_discover_tests(hepa-uv) +add_build_and_test_target(hepa-uv) + +add_coverage(hepa-uv) diff --git a/hepa-uv/tests/test_leds.cpp b/hepa-uv/tests/test_leds.cpp new file mode 100644 index 000000000..cf8dc1ed1 --- /dev/null +++ b/hepa-uv/tests/test_leds.cpp @@ -0,0 +1,4 @@ +#include "catch2/catch.hpp" + +// Just a dummy test case for CI. +TEST_CASE("Holder Test Case") { REQUIRE(true); } \ No newline at end of file diff --git a/hepa-uv/tests/test_main.cpp b/hepa-uv/tests/test_main.cpp new file mode 100644 index 000000000..62bf7476a --- /dev/null +++ b/hepa-uv/tests/test_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch2/catch.hpp" diff --git a/include/bootloader/core/ids.h b/include/bootloader/core/ids.h index 9afd0191c..e50866985 100644 --- a/include/bootloader/core/ids.h +++ b/include/bootloader/core/ids.h @@ -127,12 +127,14 @@ typedef enum { can_nodeid_gripper = 0x20, can_nodeid_gripper_z = 0x21, can_nodeid_gripper_g = 0x22, + can_nodeid_hepa_uv = 0x32, can_nodeid_pipette_left_bootloader = 0x6f, can_nodeid_pipette_right_bootloader = 0x7f, can_nodeid_gantry_x_bootloader = 0x3f, can_nodeid_gantry_y_bootloader = 0x4f, can_nodeid_head_bootloader = 0x5f, can_nodeid_gripper_bootloader = 0x2f, + can_nodeid_hepa_uv_bootloader = 0x3e, } CANNodeId; /** Common error codes. */ diff --git a/include/can/core/ids.hpp b/include/can/core/ids.hpp index c39685f9a..b915e2853 100644 --- a/include/can/core/ids.hpp +++ b/include/can/core/ids.hpp @@ -132,12 +132,14 @@ enum class NodeId { gripper = 0x20, gripper_z = 0x21, gripper_g = 0x22, + hepa_uv = 0x32, pipette_left_bootloader = 0x6f, pipette_right_bootloader = 0x7f, gantry_x_bootloader = 0x3f, gantry_y_bootloader = 0x4f, head_bootloader = 0x5f, gripper_bootloader = 0x2f, + hepa_uv_bootloader = 0x3e, }; /** Common error codes. */ diff --git a/include/can/core/messages.hpp b/include/can/core/messages.hpp index 273fbeb22..8ac097aeb 100644 --- a/include/can/core/messages.hpp +++ b/include/can/core/messages.hpp @@ -1272,6 +1272,7 @@ struct BindSensorOutputResponse using TipStatusQueryRequest = Empty; +// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct PushTipPresenceNotification : BaseMessage { uint32_t message_index; @@ -1511,6 +1512,7 @@ struct SetGripperErrorToleranceRequest using GetMotorUsageRequest = Empty; +// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct GetMotorUsageResponse : BaseMessage { uint32_t message_index; diff --git a/include/hepa-uv/core/can_task.hpp b/include/hepa-uv/core/can_task.hpp new file mode 100644 index 000000000..9c6e01a09 --- /dev/null +++ b/include/hepa-uv/core/can_task.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "can/core/freertos_can_dispatch.hpp" +#include "can/core/message_handlers/system.hpp" +#include "common/core/freertos_message_queue.hpp" +#include "hepa-uv/core/tasks.hpp" + +namespace can_task { + +using namespace hepauv_tasks; + +using SystemDispatchTarget = can::dispatch::DispatchParseTarget< + can::message_handlers::system::SystemMessageHandler< + hepauv_tasks::QueueClient>, + can::messages::DeviceInfoRequest, can::messages::InitiateFirmwareUpdate, + can::messages::FirmwareUpdateStatusRequest, can::messages::TaskInfoRequest>; + +auto constexpr reader_message_buffer_size = 1024; + +struct CanMessageReaderTask { + [[noreturn]] void operator()(can::bus::CanBus* can_bus); +}; + +/** + * Create the can message reader task. + * + * @param canbus reference to the can bus + * @return The task. + */ +auto start_reader(can::bus::CanBus& canbus) -> CanMessageReaderTask&; + +using CanMessageWriterTask = can::message_writer_task::MessageWriterTask< + freertos_message_queue::FreeRTOSMessageQueue>; + +/** + * Create the can message writer task. + * + * @param canbus reference to the can bus + * @return The task. + */ +auto start_writer(can::bus::CanBus& canbus) -> CanMessageWriterTask&; + +} // namespace can_task diff --git a/include/hepa-uv/core/constants.h b/include/hepa-uv/core/constants.h new file mode 100644 index 000000000..8fc509aa9 --- /dev/null +++ b/include/hepa-uv/core/constants.h @@ -0,0 +1,30 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// the number of selectable points in the PWM +#define LED_PWM_WIDTH (256UL) + +typedef enum LED_TYPE { + RED_LED, + GREEN_LED, + BLUE_LED, + WHITE_LED +} LED_TYPE; + +typedef enum PUSH_BUTTON_TYPE { + HEPA_BUTTON, + UV_BUTTON +} PUSH_BUTTON_TYPE; + +typedef struct LEDState { + LED_TYPE led; + uint32_t duty_cycle; +} LEDState; + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/include/hepa-uv/core/hepa_task.hpp b/include/hepa-uv/core/hepa_task.hpp new file mode 100644 index 000000000..d71958d7b --- /dev/null +++ b/include/hepa-uv/core/hepa_task.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include "can/core/ids.hpp" +#include "common/core/bit_utils.hpp" +#include "common/core/logging.h" +#include "common/core/message_queue.hpp" +#include "common/firmware/gpio.hpp" +#include "hepa-uv/core/constants.h" +#include "hepa-uv/core/messages.hpp" +#include "hepa-uv/firmware/gpio_drive_hardware.hpp" +#include "hepa-uv/firmware/led_control_hardware.hpp" + +namespace hepa_task { + +using TaskMessage = interrupt_task_messages::TaskMessage; + +template +class HepaMessageHandler { + public: + explicit HepaMessageHandler(gpio_drive_hardware::GpioDrivePins &drive_pins, + LEDControlClient &led_control_client) + : drive_pins{drive_pins}, led_control_client{led_control_client} { + // get current state + hepa_push_button = gpio::is_set(drive_pins.hepa_push_button); + // turn off the HEPA fan + gpio::reset(drive_pins.hepa_on_off); + } + HepaMessageHandler(const HepaMessageHandler &) = delete; + HepaMessageHandler(const HepaMessageHandler &&) = delete; + auto operator=(const HepaMessageHandler &) -> HepaMessageHandler & = delete; + auto operator=(const HepaMessageHandler &&) + -> HepaMessageHandler && = delete; + ~HepaMessageHandler() {} + + void handle_message(const TaskMessage &m) { + std::visit([this](auto o) { this->visit(o); }, m); + } + + private: + void visit(const std::monostate &) {} + + // Handle GPIO EXTI Interrupts here + void visit(const interrupt_task_messages::GPIOInterruptChanged &m) { + if (m.pin == drive_pins.hepa_push_button.pin) { + hepa_push_button = !hepa_push_button; + // handle state changes here + if (hepa_push_button) { + gpio::set(drive_pins.hepa_on_off); + led_control_client.send_led_control_message( + led_control_task_messages::PushButtonLED{HEPA_BUTTON, 0, 50, + 0, 0}); + } else { + gpio::reset(drive_pins.hepa_on_off); + led_control_client.send_led_control_message( + led_control_task_messages::PushButtonLED{HEPA_BUTTON, 0, 0, + 0, 50}); + } + } + + // TODO: send CAN message to host + } + + // state tracking variables + bool hepa_push_button = false; + bool hepa_fan_on = false; + + gpio_drive_hardware::GpioDrivePins &drive_pins; + LEDControlClient &led_control_client; +}; + +/** + * The task type. + */ +template